7
7
*
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
43
43
#include "utils/lsyscache.h"
44
44
#include "utils/syscache.h"
45
45
46
+
46
47
#define ISOCTAL (c ) (((c) >= '0') && ((c) <= '7'))
47
48
#define OCTVALUE (c ) ((c) - '0')
48
49
@@ -746,8 +747,9 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
746
747
num_defaults ;
747
748
FmgrInfo * in_functions ;
748
749
Oid * elements ;
749
- bool * isDomain ;
750
- bool hasDomain = false;
750
+ Node * * constraintexprs ;
751
+ Const * * constraintconsts ;
752
+ bool hasConstraints = false;
751
753
int i ;
752
754
List * cur ;
753
755
Oid in_func_oid ;
@@ -792,36 +794,31 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
792
794
ExecSetSlotDescriptor (slot , tupDesc , false);
793
795
794
796
/*
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.)
798
801
*/
799
- defmap = (int * ) palloc (sizeof (int ) * num_phys_attrs );
800
- defexprs = (Node * * ) palloc (sizeof (Node * ) * num_phys_attrs );
801
802
in_functions = (FmgrInfo * ) palloc (num_phys_attrs * sizeof (FmgrInfo ));
802
803
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 * ));
804
809
805
810
for (i = 0 ; i < num_phys_attrs ; i ++ )
806
811
{
807
812
/* We don't need info for dropped attributes */
808
813
if (attr [i ]-> attisdropped )
809
814
continue ;
810
815
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
-
820
816
/* Fetch the input function */
821
817
in_func_oid = (Oid ) GetInputFunction (attr [i ]-> atttypid );
822
818
fmgr_info (in_func_oid , & in_functions [i ]);
823
819
elements [i ] = GetTypeElement (attr [i ]-> atttypid );
824
820
821
+ /* Get default info if needed */
825
822
if (intMember (i + 1 , attnumlist ))
826
823
{
827
824
/* attribute is to be copied */
@@ -839,6 +836,45 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
839
836
num_defaults ++ ;
840
837
}
841
838
}
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
+ }
842
878
}
843
879
844
880
if (!binary )
@@ -1090,52 +1126,6 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
1090
1126
}
1091
1127
}
1092
1128
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
-
1139
1129
/*
1140
1130
* Now compute and insert any defaults available for the columns
1141
1131
* not provided by the input data. Anything not processed here or
@@ -1151,6 +1141,36 @@ CopyFrom(Relation rel, List *attnumlist, bool binary, bool oids,
1151
1141
nulls [defmap [i ]] = ' ' ;
1152
1142
}
1153
1143
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
+
1154
1174
/*
1155
1175
* And now we can form the input tuple.
1156
1176
*/
0 commit comments