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