*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.174 2002/09/20 15:43:03 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/commands/copy.c,v 1.175 2002/09/20 16:56:02 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#include "utils/lsyscache.h"
#include "utils/syscache.h"
+
#define ISOCTAL(c) (((c) >= '0') && ((c) <= '7'))
#define OCTVALUE(c) ((c) - '0')
num_defaults;
FmgrInfo *in_functions;
Oid *elements;
- bool *isDomain;
- bool hasDomain = false;
+ Node **constraintexprs;
+ Const **constraintconsts;
+ bool hasConstraints = false;
int i;
List *cur;
Oid in_func_oid;
ExecSetSlotDescriptor(slot, tupDesc, false);
/*
- * pick up the input function and default expression (if any) for each
- * attribute in the relation. (We don't actually use the input
- * function if it's a binary copy.)
+ * Pick up the required catalog information for each attribute in the
+ * relation, including the input function, the element type (to pass
+ * to the input function), and info about defaults and constraints.
+ * (We don't actually use the input function if it's a binary copy.)
*/
- defmap = (int *) palloc(sizeof(int) * num_phys_attrs);
- defexprs = (Node **) palloc(sizeof(Node *) * num_phys_attrs);
in_functions = (FmgrInfo *) palloc(num_phys_attrs * sizeof(FmgrInfo));
elements = (Oid *) palloc(num_phys_attrs * sizeof(Oid));
- isDomain = (bool *) palloc(num_phys_attrs * sizeof(bool));
+ defmap = (int *) palloc(num_phys_attrs * sizeof(int));
+ defexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
+ constraintexprs = (Node **) palloc(num_phys_attrs * sizeof(Node *));
+ constraintconsts = (Const **) palloc(num_phys_attrs * sizeof(Const *));
+ MemSet(constraintexprs, 0, num_phys_attrs * sizeof(Node *));
for (i = 0; i < num_phys_attrs; i++)
{
if (attr[i]->attisdropped)
continue;
- /* Test for the base type */
- if (getBaseType(attr[i]->atttypid) != attr[i]->atttypid)
- {
- hasDomain = true;
- isDomain[i] = true;
- }
- else
- isDomain[i] = false;
-
/* Fetch the input function */
in_func_oid = (Oid) GetInputFunction(attr[i]->atttypid);
fmgr_info(in_func_oid, &in_functions[i]);
elements[i] = GetTypeElement(attr[i]->atttypid);
+ /* Get default info if needed */
if (intMember(i + 1, attnumlist))
{
/* attribute is to be copied */
num_defaults++;
}
}
+
+ /* If it's a domain type, get info on domain constraints */
+ if (get_typtype(attr[i]->atttypid) == 'd')
+ {
+ Const *con;
+ Node *node;
+
+ /*
+ * Easiest way to do this is to use parse_coerce.c to set up
+ * an expression that checks the constraints. (At present,
+ * the expression might contain a length-coercion-function call
+ * and/or ConstraintTest nodes.) The bottom of the expression
+ * is a Const node that we fill in with the actual datum during
+ * the data input loop.
+ *
+ * XXX to prevent premature constant folding in parse_coerce,
+ * pass in a NULL constant to start with. See the comments in
+ * coerce_type; this should be changed someday to use some sort
+ * of Param node instead of a Const.
+ */
+ con = makeConst(attr[i]->atttypid,
+ attr[i]->attlen,
+ (Datum) 0,
+ true, /* is null */
+ attr[i]->attbyval,
+ false, /* not a set */
+ false); /* not coerced */
+
+ node = coerce_type_constraints((Node *) con, attr[i]->atttypid,
+ COERCE_IMPLICIT_CAST);
+
+ /* check whether any constraints actually found */
+ if (node != (Node *) con)
+ {
+ constraintexprs[i] = node;
+ constraintconsts[i] = con;
+ hasConstraints = true;
+ }
+ }
}
if (!binary)
}
}
- /* Deal with domains */
- if (hasDomain)
- {
- ParseState *pstate;
- pstate = make_parsestate(NULL);
-
- foreach(cur, attnumlist)
- {
- int attnum = lfirsti(cur);
- int m = attnum - 1;
-
- Const *con;
- Node *node;
- bool isNull = (nulls[m] == 'n');
-
- /* This is not a domain, so lets skip it */
- if (!isDomain[m])
- continue;
-
- /*
- * This is a domain. As such, we must process it's input
- * function and coerce_type_constraints. The simplest way
- * of doing that is to allow coerce_type to accomplish its
- * job from an unknown constant
- */
-
- /* Create a constant */
- con = makeConst(attr[m]->atttypid,
- attr[m]->attlen,
- values[m],
- isNull,
- attr[m]->attbyval,
- false, /* not a set */
- false); /* not coerced */
-
- /* Process constraints */
- node = coerce_type_constraints((Node *) con, attr[m]->atttypid,
- COERCE_IMPLICIT_CAST);
-
- values[m] = ExecEvalExpr(node, econtext,
- &isNull, NULL);
-
- nulls[m] = isNull ? 'n' : ' ';
- }
- }
-
/*
* Now compute and insert any defaults available for the columns
* not provided by the input data. Anything not processed here or
nulls[defmap[i]] = ' ';
}
+ /*
+ * Next apply any domain constraints
+ */
+ if (hasConstraints)
+ {
+ for (i = 0; i < num_phys_attrs; i++)
+ {
+ Node *node = constraintexprs[i];
+ Const *con;
+ bool isnull;
+
+ if (node == NULL)
+ continue; /* no constraint for this attr */
+
+ /* Insert current row's value into the Const node */
+ con = constraintconsts[i];
+ con->constvalue = values[i];
+ con->constisnull = (nulls[i] == 'n');
+
+ /*
+ * Execute the constraint expression. Allow the expression
+ * to replace the value (consider e.g. a timestamp precision
+ * restriction).
+ */
+ values[i] = ExecEvalExpr(node, econtext,
+ &isnull, NULL);
+ nulls[i] = isnull ? 'n' : ' ';
+ }
+ }
+
/*
* And now we can form the input tuple.
*/