Skip to content

Commit 316d4e2

Browse files
committed
Code review for check-domain-constraints-in-COPY patch. Do correct thing
when default expression for a domain is being used. Avoid repetitive catalog lookups.
1 parent 4e5c2a8 commit 316d4e2

File tree

1 file changed

+84
-64
lines changed

1 file changed

+84
-64
lines changed

src/backend/commands/copy.c

Lines changed: 84 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
*
88
*
99
* IDENTIFICATION
10-
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.174 2002/09/20 15:43:03 momjian Exp $
10+
* $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.175 2002/09/20 16:56:02 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -43,6 +43,7 @@
4343
#include "utils/lsyscache.h"
4444
#include "utils/syscache.h"
4545

46+
4647
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
4748
#define OCTVALUE(c) ((c) - '0')
4849

@@ -746,8 +747,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
746747
num_defaults;
747748
FmgrInfo *in_functions;
748749
Oid *elements;
749-
bool *isDomain;
750-
bool hasDomain = false;
750+
Node **constraintexprs;
751+
Const **constraintconsts;
752+
bool hasConstraints = false;
751753
int i;
752754
List *cur;
753755
Oid in_func_oid;
@@ -792,36 +794,31 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
792794
ExecSetSlotDescriptor(slot, tupDesc, false);
793795

794796
/*
795-
* pick up the input function and default expression (if any) for each
796-
* attribute in the relation. (We don't actually use the input
797-
* function if it's a binary copy.)
797+
* Pick up the required catalog information for each attribute in the
798+
* relation, including the input function, the element type (to pass
799+
* to the input function), and info about defaults and constraints.
800+
* (We don't actually use the input function if it's a binary copy.)
798801
*/
799-
defmap = (int *) palloc(sizeof(int) * num_phys_attrs);
800-
defexprs = (Node **) palloc(sizeof(Node *) * num_phys_attrs);
801802
in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
802803
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
803-
isDomain = (bool *) palloc(num_phys_attrs * sizeof(bool));
804+
defmap = (int *) palloc(num_phys_attrs * sizeof(int));
805+
defexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
806+
constraintexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
807+
constraintconsts = (Const **) palloc(num_phys_attrs * sizeof(Const *));
808+
MemSet(constraintexprs, 0, num_phys_attrs * sizeof(Node *));
804809

805810
for (i = 0; i < num_phys_attrs; i++)
806811
{
807812
/* We don't need info for dropped attributes */
808813
if (attr[i]->attisdropped)
809814
continue;
810815

811-
/* Test for the base type */
812-
if (getBaseType(attr[i]->atttypid) != attr[i]->atttypid)
813-
{
814-
hasDomain = true;
815-
isDomain[i] = true;
816-
}
817-
else
818-
isDomain[i] = false;
819-
820816
/* Fetch the input function */
821817
in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
822818
fmgr_info(in_func_oid, &in_functions[i]);
823819
elements[i] = GetTypeElement(attr[i]->atttypid);
824820

821+
/* Get default info if needed */
825822
if (intMember(i + 1, attnumlist))
826823
{
827824
/* attribute is to be copied */
@@ -839,6 +836,45 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
839836
num_defaults++;
840837
}
841838
}
839+
840+
/* If it's a domain type, get info on domain constraints */
841+
if (get_typtype(attr[i]->atttypid) == 'd')
842+
{
843+
Const *con;
844+
Node *node;
845+
846+
/*
847+
* Easiest way to do this is to use parse_coerce.c to set up
848+
* an expression that checks the constraints. (At present,
849+
* the expression might contain a length-coercion-function call
850+
* and/or ConstraintTest nodes.) The bottom of the expression
851+
* is a Const node that we fill in with the actual datum during
852+
* the data input loop.
853+
*
854+
* XXX to prevent premature constant folding in parse_coerce,
855+
* pass in a NULL constant to start with. See the comments in
856+
* coerce_type; this should be changed someday to use some sort
857+
* of Param node instead of a Const.
858+
*/
859+
con = makeConst(attr[i]->atttypid,
860+
attr[i]->attlen,
861+
(Datum) 0,
862+
true, /* is null */
863+
attr[i]->attbyval,
864+
false, /* not a set */
865+
false); /* not coerced */
866+
867+
node = coerce_type_constraints((Node *) con, attr[i]->atttypid,
868+
COERCE_IMPLICIT_CAST);
869+
870+
/* check whether any constraints actually found */
871+
if (node != (Node *) con)
872+
{
873+
constraintexprs[i] = node;
874+
constraintconsts[i] = con;
875+
hasConstraints = true;
876+
}
877+
}
842878
}
843879

844880
if (!binary)
@@ -1090,52 +1126,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
10901126
}
10911127
}
10921128

1093-
/* Deal with domains */
1094-
if (hasDomain)
1095-
{
1096-
ParseState *pstate;
1097-
pstate = make_parsestate(NULL);
1098-
1099-
foreach(cur, attnumlist)
1100-
{
1101-
int attnum = lfirsti(cur);
1102-
int m = attnum - 1;
1103-
1104-
Const *con;
1105-
Node *node;
1106-
bool isNull = (nulls[m] == 'n');
1107-
1108-
/* This is not a domain, so lets skip it */
1109-
if (!isDomain[m])
1110-
continue;
1111-
1112-
/*
1113-
* This is a domain. As such, we must process it's input
1114-
* function and coerce_type_constraints. The simplest way
1115-
* of doing that is to allow coerce_type to accomplish its
1116-
* job from an unknown constant
1117-
*/
1118-
1119-
/* Create a constant */
1120-
con = makeConst(attr[m]->atttypid,
1121-
attr[m]->attlen,
1122-
values[m],
1123-
isNull,
1124-
attr[m]->attbyval,
1125-
false, /* not a set */
1126-
false); /* not coerced */
1127-
1128-
/* Process constraints */
1129-
node = coerce_type_constraints((Node *) con, attr[m]->atttypid,
1130-
COERCE_IMPLICIT_CAST);
1131-
1132-
values[m] = ExecEvalExpr(node, econtext,
1133-
&isNull, NULL);
1134-
1135-
nulls[m] = isNull ? 'n' : ' ';
1136-
}
1137-
}
1138-
11391129
/*
11401130
* Now compute and insert any defaults available for the columns
11411131
* not provided by the input data. Anything not processed here or
@@ -1151,6 +1141,36 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
11511141
nulls[defmap[i]] = ' ';
11521142
}
11531143

1144+
/*
1145+
* Next apply any domain constraints
1146+
*/
1147+
if (hasConstraints)
1148+
{
1149+
for (i = 0; i < num_phys_attrs; i++)
1150+
{
1151+
Node *node = constraintexprs[i];
1152+
Const *con;
1153+
bool isnull;
1154+
1155+
if (node == NULL)
1156+
continue; /* no constraint for this attr */
1157+
1158+
/* Insert current row's value into the Const node */
1159+
con = constraintconsts[i];
1160+
con->constvalue = values[i];
1161+
con->constisnull = (nulls[i] == 'n');
1162+
1163+
/*
1164+
* Execute the constraint expression. Allow the expression
1165+
* to replace the value (consider e.g. a timestamp precision
1166+
* restriction).
1167+
*/
1168+
values[i] = ExecEvalExpr(node, econtext,
1169+
&isnull, NULL);
1170+
nulls[i] = isnull ? 'n' : ' ';
1171+
}
1172+
}
1173+
11541174
/*
11551175
* And now we can form the input tuple.
11561176
*/

0 commit comments

Comments
 (0)