On 03.06.2016 02:02, Rod Taylor wrote:


On Thu, Jun 2, 2016 at 10:42 AM, Konstantin Knizhnik <k.knizh...@postgrespro.ru <mailto:k.knizh...@postgrespro.ru>> wrote:

    On 02.06.2016 17:22, Tom Lane wrote:

        konstantin knizhnik <k.knizh...@postgrespro.ru
        <mailto:k.knizh...@postgrespro.ru>> writes:

            Attached please find patch for DefineDomain function.

        You didn't attach the patch,


    Sorry, but I did attached the patch - I see the attachment in my
    mail received from the group.
    Multidimensional arrays work fine:

    knizhnik=# SELECT '{{14},{20}}'::teenager[][];
    ERROR:  value for domain teenager violates check constraint
    "teenager_check"
    LINE 1: SELECT '{{14},{20}}'::teenager[][];
                   ^
    knizhnik=# SELECT '{{14},{19}}'::teenager[][];
      teenager
    -------------
     {{14},{19}}
    (1 row)

    knizhnik=# SELECT ('{{14},{19}}'::teenager[][])[1][1];
     teenager
    ----------
           14
    (1 row)


    Domain of array of domain also works:


I applied the domain.patch from above on HEAD, and all I get is cache lookup failures. The type_sanity regression test fails too.

postgres=# CREATE DOMAIN teenager AS int CHECK (VALUE BETWEEN 13 AND 20);
CREATE DOMAIN
postgres=# CREATE DOMAIN teenager_groups AS teenager[];
CREATE DOMAIN
postgres=# CREATE TABLE x (col teenager_groups);
ERROR:  cache lookup failed for type 0


Anyway, if that worked for me I would have done this which I expect will succeed when it shouldn't.

INSERT INTO x VALUES (ARRAY[13,14,20]);
ALTER DOMAIN teenager DROP CONSTRAINT teenager_check;
ALTER DOMAIN teenager ADD CHECK (VALUE BETWEEN 13 AND 19);


Sorry, the problem is more difficult than I originally expected:(
Attached patch passes all regression tests and correctly handle conversion of arrays. But constraints are not checked for table columns. I failed to locate place where this check should be inserted...

Originally I was mostly interested in domains as kind of typedefs: convenient way to assign type to some particular kind of columns,
for example object reference used in ORM.
There are two main goals of using domain here:
1. Be able to easily change representation of object identifier, for example from integer to bigint. 2. Detect all columns containing references (distinguish them from columns containing just normal integers). I do not see any other mechanism in PostgreSQL which can address this problem (for example user defined type can not help here).

I wonder if it is possible to support arrays of domain which do not have constraints?
Or such partial support is worser than prohibiting arrays of domains at all?

--
Konstantin Knizhnik
Postgres Professional: http://www.postgrespro.com
The Russian Postgres Company

diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 71d4df9..e227fa8 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -752,11 +752,13 @@ DefineDomain(CreateDomainStmt *stmt)
 	ListCell   *listptr;
 	Oid			basetypeoid;
 	Oid			old_type_oid;
+	Oid         array_oid;
 	Oid			domaincoll;
 	Form_pg_type baseType;
 	int32		basetypeMod;
 	Oid			baseColl;
 	ObjectAddress address;
+	char       *array_type;
 
 	/* Convert list of names to a name and namespace */
 	domainNamespace = QualifiedNameGetCreationNamespace(stmt->domainname,
@@ -1023,6 +1025,14 @@ DefineDomain(CreateDomainStmt *stmt)
 		}
 	}
 
+
+	/*
+	 * OK, we're done checking, time to make the type.  We must assign the
+	 * array type OID ahead of calling TypeCreate, since the base type and
+	 * array type each refer to the other.
+	 */
+	array_oid = AssignTypeArrayOid();
+
 	/*
 	 * Have TypeCreate do all the real work.
 	 */
@@ -1047,7 +1057,7 @@ DefineDomain(CreateDomainStmt *stmt)
 				   analyzeProcedure,	/* analyze procedure */
 				   InvalidOid,	/* no array element type */
 				   false,		/* this isn't an array */
-				   InvalidOid,	/* no arrays for domains (yet) */
+				   array_oid,	/* array type we are about to create */
 				   basetypeoid, /* base type ID */
 				   defaultValue,	/* default type value (text) */
 				   defaultValueBin,		/* default type value (binary) */
@@ -1060,6 +1070,48 @@ DefineDomain(CreateDomainStmt *stmt)
 				   domaincoll); /* type's collation */
 
 	/*
+	 * Create the array type that goes with it.
+	 */
+	array_type = makeArrayTypeName(domainName, domainNamespace);
+
+/* alignment must be 'i' or 'd' for arrays */
+	alignment = (alignment == 'd') ? 'd' : 'i';
+
+	TypeCreate(array_oid,/* force assignment of this type OID */
+			   array_type,/* 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 */
+			   InvalidOid,/* typmodout procedure */
+			   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(array_type);
+
+    /*
 	 * Process constraints which refer to the domain ID returned by TypeCreate
 	 */
 	foreach(listptr, schema)
@@ -2846,8 +2898,6 @@ get_rels_with_domain(Oid domainOid, LOCKMODE lockmode)
 		/* Check for directly dependent types --- must be domains */
 		if (pg_depend->classid == TypeRelationId)
 		{
-			Assert(get_typtype(pg_depend->objid) == TYPTYPE_DOMAIN);
-
 			/*
 			 * Recursively add dependent columns to the output list.  This is
 			 * a bit inefficient since we may fail to combine RelToCheck
diff --git a/src/backend/executor/execQual.c b/src/backend/executor/execQual.c
index c0ca58b..df4674f 100644
--- a/src/backend/executor/execQual.c
+++ b/src/backend/executor/execQual.c
@@ -4807,9 +4807,6 @@ ExecInitExpr(Expr *node, PlanState *parent)
 					ereport(ERROR,
 							(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
 							 errmsg("target type is not an array")));
-				/* Arrays over domains aren't supported yet */
-				Assert(getBaseType(astate->resultelemtype) ==
-					   astate->resultelemtype);
 				astate->elemfunc.fn_oid = InvalidOid;	/* not initialized */
 				astate->amstate = (ArrayMapState *) palloc0(sizeof(ArrayMapState));
 				state = (ExprState *) astate;
-- 
Sent via pgsql-hackers mailing list (pgsql-hackers@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-hackers

Reply via email to