diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c index 29ac5d5..c7bbe22 100644 *** a/src/backend/commands/typecmds.c --- b/src/backend/commands/typecmds.c *************** ObjectAddress *** 729,734 **** --- 729,735 ---- DefineDomain(CreateDomainStmt *stmt) { char *domainName; + char *domainArrayName; Oid domainNamespace; AclResult aclresult; int16 internalLength; *************** DefineDomain(CreateDomainStmt *stmt) *** 757,762 **** --- 758,764 ---- Oid basetypeoid; Oid old_type_oid; Oid domaincoll; + Oid domainArrayOid; Form_pg_type baseType; int32 basetypeMod; Oid baseColl; *************** DefineDomain(CreateDomainStmt *stmt) *** 1027,1032 **** --- 1029,1037 ---- } } + /* Allocate OID for array type */ + domainArrayOid = AssignTypeArrayOid(); + /* * Have TypeCreate do all the real work. */ *************** DefineDomain(CreateDomainStmt *stmt) *** 1051,1057 **** analyzeProcedure, /* analyze procedure */ InvalidOid, /* no array element type */ false, /* this isn't an array */ ! InvalidOid, /* no arrays for domains (yet) */ basetypeoid, /* base type ID */ defaultValue, /* default type value (text) */ defaultValueBin, /* default type value (binary) */ --- 1056,1062 ---- analyzeProcedure, /* analyze procedure */ InvalidOid, /* no array element type */ false, /* this isn't an array */ ! domainArrayOid, /* array type we are about to create */ basetypeoid, /* base type ID */ defaultValue, /* default type value (text) */ defaultValueBin, /* default type value (binary) */ *************** DefineDomain(CreateDomainStmt *stmt) *** 1064,1069 **** --- 1069,1116 ---- domaincoll); /* type's collation */ /* + * Create the array type that goes with it. + */ + domainArrayName = makeArrayTypeName(domainName, domainNamespace); + + /* alignment must be 'i' or 'd' for arrays */ + alignment = (alignment == 'd') ? 'd' : 'i'; + + TypeCreate(domainArrayOid, /* force assignment of this type OID */ + domainArrayName, /* type name */ + domainNamespace, /* namespace */ + InvalidOid, /* relation oid (n/a here) */ + 0, /* relation kind (ditto) */ + GetUserId(), /* owner's ID */ + -1, /* internal size (always varlena) */ + TYPTYPE_BASE, /* type-type (base type) */ + TYPCATEGORY_ARRAY, /* type-category (array) */ + false, /* array types are never preferred */ + delimiter, /* array element delimiter */ + F_ARRAY_IN, /* input procedure */ + F_ARRAY_OUT, /* output procedure */ + F_ARRAY_RECV, /* receive procedure */ + F_ARRAY_SEND, /* send procedure */ + InvalidOid, /* typmodin procedure - none */ + InvalidOid, /* typmodout procedure - none */ + F_ARRAY_TYPANALYZE, /* analyze procedure */ + address.objectId, /* element type ID */ + true, /* yes this is an array type */ + InvalidOid, /* no further array type */ + InvalidOid, /* base type ID */ + NULL, /* never a default type value */ + NULL, /* binary default isn't sent either */ + false, /* never passed by value */ + alignment, /* see above */ + 'x', /* ARRAY is always toastable */ + -1, /* typMod (Domains only) */ + 0, /* Array dimensions of typbasetype */ + false, /* Type NOT NULL */ + domaincoll); /* type's collation */ + + pfree(domainArrayName); + + /* * Process constraints which refer to the domain ID returned by TypeCreate */ foreach(listptr, schema) *************** DefineEnum(CreateEnumStmt *stmt) *** 1139,1144 **** --- 1186,1192 ---- errmsg("type \"%s\" already exists", enumName))); } + /* Allocate OID for array type */ enumArrayOid = AssignTypeArrayOid(); /* Create the pg_type entry */ diff --git a/src/test/regress/expected/domain.out b/src/test/regress/expected/domain.out index 3acc696..1e62c57 100644 *** a/src/test/regress/expected/domain.out --- b/src/test/regress/expected/domain.out *************** Rules: *** 310,315 **** --- 310,410 ---- drop table dcomptable; drop type comptype cascade; NOTICE: drop cascades to type dcomptypea + -- Test arrays over domains + create domain posint as int check (value > 0); + create table pitable (f1 posint[]); + insert into pitable values(array[42]); + insert into pitable values(array[-1]); -- fail + ERROR: value for domain posint violates check constraint "posint_check" + insert into pitable values('{0}'); -- fail + ERROR: value for domain posint violates check constraint "posint_check" + LINE 1: insert into pitable values('{0}'); + ^ + update pitable set f1[1] = f1[1] + 1; + update pitable set f1[1] = 0; -- fail + ERROR: value for domain posint violates check constraint "posint_check" + select * from pitable; + f1 + ------ + {43} + (1 row) + + drop table pitable; + create domain vc4 as varchar(4); + create table vc4table (f1 vc4[]); + insert into vc4table values(array['too long']); -- fail + ERROR: value too long for type character varying(4) + insert into vc4table values(array['too long']::vc4[]); -- cast truncates + select * from vc4table; + f1 + ---------- + {"too "} + (1 row) + + drop table vc4table; + drop type vc4; + -- You can sort of fake arrays-of-arrays by putting a domain in between + create domain dposinta as posint[]; + create table dposintatable (f1 dposinta[]); + insert into dposintatable values(array[array[42]]); -- fail + ERROR: column "f1" is of type dposinta[] but expression is of type integer[] + LINE 1: insert into dposintatable values(array[array[42]]); + ^ + HINT: You will need to rewrite or cast the expression. + insert into dposintatable values(array[array[42]::posint[]]); -- still fail + ERROR: column "f1" is of type dposinta[] but expression is of type posint[] + LINE 1: insert into dposintatable values(array[array[42]::posint[]])... + ^ + HINT: You will need to rewrite or cast the expression. + insert into dposintatable values(array[array[42]::dposinta]); -- but this works + select f1, f1[1], (f1[1])[1] from dposintatable; + f1 | f1 | f1 + ----------+------+---- + {"{42}"} | {42} | 42 + (1 row) + + select pg_typeof(f1) from dposintatable; + pg_typeof + ------------ + dposinta[] + (1 row) + + select pg_typeof(f1[1]) from dposintatable; + pg_typeof + ----------- + dposinta + (1 row) + + select pg_typeof(f1[1][1]) from dposintatable; + pg_typeof + ----------- + dposinta + (1 row) + + select pg_typeof((f1[1])[1]) from dposintatable; + pg_typeof + ----------- + posint + (1 row) + + update dposintatable set f1[2] = array[99]; + select f1, f1[1], (f1[2])[1] from dposintatable; + f1 | f1 | f1 + -----------------+------+---- + {"{42}","{99}"} | {42} | 99 + (1 row) + + -- it'd be nice if you could do something like this, but for now you can't: + update dposintatable set f1[2][1] = array[97]; + ERROR: wrong number of array subscripts + -- maybe someday we can make this syntax work: + update dposintatable set (f1[2])[1] = array[98]; + ERROR: syntax error at or near "[" + LINE 1: update dposintatable set (f1[2])[1] = array[98]; + ^ + drop table dposintatable; + drop domain posint cascade; + NOTICE: drop cascades to type dposinta -- Test not-null restrictions create domain dnotnull varchar(15) NOT NULL; create domain dnull varchar(15); diff --git a/src/test/regress/sql/domain.sql b/src/test/regress/sql/domain.sql index 0fd383e..8fb3e20 100644 *** a/src/test/regress/sql/domain.sql --- b/src/test/regress/sql/domain.sql *************** drop table dcomptable; *** 166,171 **** --- 166,214 ---- drop type comptype cascade; + -- Test arrays over domains + + create domain posint as int check (value > 0); + + create table pitable (f1 posint[]); + insert into pitable values(array[42]); + insert into pitable values(array[-1]); -- fail + insert into pitable values('{0}'); -- fail + update pitable set f1[1] = f1[1] + 1; + update pitable set f1[1] = 0; -- fail + select * from pitable; + drop table pitable; + + create domain vc4 as varchar(4); + create table vc4table (f1 vc4[]); + insert into vc4table values(array['too long']); -- fail + insert into vc4table values(array['too long']::vc4[]); -- cast truncates + select * from vc4table; + drop table vc4table; + drop type vc4; + + -- You can sort of fake arrays-of-arrays by putting a domain in between + create domain dposinta as posint[]; + create table dposintatable (f1 dposinta[]); + insert into dposintatable values(array[array[42]]); -- fail + insert into dposintatable values(array[array[42]::posint[]]); -- still fail + insert into dposintatable values(array[array[42]::dposinta]); -- but this works + select f1, f1[1], (f1[1])[1] from dposintatable; + select pg_typeof(f1) from dposintatable; + select pg_typeof(f1[1]) from dposintatable; + select pg_typeof(f1[1][1]) from dposintatable; + select pg_typeof((f1[1])[1]) from dposintatable; + update dposintatable set f1[2] = array[99]; + select f1, f1[1], (f1[2])[1] from dposintatable; + -- it'd be nice if you could do something like this, but for now you can't: + update dposintatable set f1[2][1] = array[97]; + -- maybe someday we can make this syntax work: + update dposintatable set (f1[2])[1] = array[98]; + + drop table dposintatable; + drop domain posint cascade; + + -- Test not-null restrictions create domain dnotnull varchar(15) NOT NULL;