2626 *
2727 *
2828 * IDENTIFICATION
29- * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.18 1997/08/2203:12:16 vadim Exp $
29+ * $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.19 1997/08/2214:28:20 vadim Exp $
3030 *
3131 *-------------------------------------------------------------------------
3232 */
@@ -73,8 +73,6 @@ static void ExecDelete(TupleTableSlot *slot, ItemPointer tupleid,
7373static void ExecReplace (TupleTableSlot * slot ,ItemPointer tupleid ,
7474EState * estate ,Query * parseTree );
7575
76- static HeapTuple ExecAttrDefault (Relation rel ,HeapTuple tuple );
77-
7876/* end of local decls */
7977
8078#ifdef QUERY_LIMIT
@@ -930,29 +928,15 @@ ExecAppend(TupleTableSlot *slot,
930928
931929if (resultRelationDesc -> rd_att -> constr )
932930 {
933- if (resultRelationDesc -> rd_att -> constr -> num_defval > 0 )
934- {
935- HeapTuple newtuple ;
936-
937- newtuple = ExecAttrDefault (resultRelationDesc ,tuple );
938-
939- if (newtuple != tuple )
940- {
941- Assert (slot -> ttc_shouldFree );
942- slot -> val = tuple = newtuple ;
943- }
944- }
945-
946- if (resultRelationDesc -> rd_att -> constr -> has_not_null )
931+ HeapTuple newtuple ;
932+
933+ newtuple = ExecConstraints ("ExecAppend" ,resultRelationDesc ,tuple );
934+
935+ if (newtuple != tuple )/* modified by DEFAULT */
947936 {
948- int attrChk ;
949-
950- for (attrChk = 1 ;attrChk <=resultRelationDesc -> rd_att -> natts ;attrChk ++ )
951- {
952- if (resultRelationDesc -> rd_att -> attrs [attrChk - 1 ]-> attnotnull && heap_attisnull (tuple ,attrChk ))
953- elog (WARN ,"ExecAppend: Fail to add null value in not null attribute %s" ,
954- resultRelationDesc -> rd_att -> attrs [attrChk - 1 ]-> attname .data );
955- }
937+ Assert (slot -> ttc_shouldFree );
938+ pfree (tuple );
939+ slot -> val = tuple = newtuple ;
956940 }
957941 }
958942
@@ -1081,15 +1065,19 @@ ExecReplace(TupleTableSlot *slot,
10811065 * ----------------
10821066 */
10831067
1084- if (resultRelationDesc -> rd_att -> constr && resultRelationDesc -> rd_att -> constr -> has_not_null )
1085- {
1086- int attrChk ;
1087- for (attrChk = 1 ;attrChk <=resultRelationDesc -> rd_att -> natts ;attrChk ++ ) {
1088- if (resultRelationDesc -> rd_att -> attrs [attrChk - 1 ]-> attnotnull && heap_attisnull (tuple ,attrChk ))
1089- elog (WARN ,"ExecReplace: Fail to update null value in not null attribute %s" ,
1090- resultRelationDesc -> rd_att -> attrs [attrChk - 1 ]-> attname .data );
1091- }
1092- }
1068+ if (resultRelationDesc -> rd_att -> constr )
1069+ {
1070+ HeapTuple newtuple ;
1071+
1072+ newtuple = ExecConstraints ("ExecReplace" ,resultRelationDesc ,tuple );
1073+
1074+ if (newtuple != tuple )/* modified by DEFAULT */
1075+ {
1076+ Assert (slot -> ttc_shouldFree );
1077+ pfree (tuple );
1078+ slot -> val = tuple = newtuple ;
1079+ }
1080+ }
10931081
10941082/* ----------------
10951083 *replace the heap tuple
@@ -1140,7 +1128,8 @@ ExecAttrDefault (Relation rel, HeapTuple tuple)
11401128{
11411129int ndef = rel -> rd_att -> constr -> num_defval ;
11421130AttrDefault * attrdef = rel -> rd_att -> constr -> defval ;
1143- ExprContext * econtext = makeNode (ExprContext );
1131+ ExprContext * econtext = makeNode (ExprContext );
1132+ HeapTuple newtuple ;
11441133Node * expr ;
11451134bool isnull ;
11461135bool isdone ;
@@ -1150,21 +1139,23 @@ ExecAttrDefault (Relation rel, HeapTuple tuple)
11501139char * repl = NULL ;
11511140int i ;
11521141
1142+ econtext -> ecxt_scantuple = NULL ;/* scan tuple slot */
1143+ econtext -> ecxt_innertuple = NULL ;/* inner tuple slot */
1144+ econtext -> ecxt_outertuple = NULL ;/* outer tuple slot */
1145+ econtext -> ecxt_relation = NULL ;/* relation */
1146+ econtext -> ecxt_relid = 0 ;/* relid */
1147+ econtext -> ecxt_param_list_info = NULL ;/* param list info */
1148+ econtext -> ecxt_range_table = NULL ;/* range table */
11531149for (i = 0 ;i < ndef ;i ++ )
11541150 {
11551151if ( !heap_attisnull (tuple ,attrdef [i ].adnum ) )
11561152continue ;
11571153expr = (Node * )stringToNode (attrdef [i ].adbin );
1158- econtext -> ecxt_scantuple = NULL ;/* scan tuple slot */
1159- econtext -> ecxt_innertuple = NULL ;/* inner tuple slot */
1160- econtext -> ecxt_outertuple = NULL ;/* outer tuple slot */
1161- econtext -> ecxt_relation = NULL ;/* relation */
1162- econtext -> ecxt_relid = 0 ;/* relid */
1163- econtext -> ecxt_param_list_info = NULL ;/* param list info */
1164- econtext -> ecxt_range_table = NULL ;/* range table */
11651154
11661155val = ExecEvalExpr (expr ,econtext ,& isnull ,& isdone );
11671156
1157+ pfree (expr );
1158+
11681159if (isnull )
11691160continue ;
11701161
@@ -1182,9 +1173,108 @@ ExecAttrDefault (Relation rel, HeapTuple tuple)
11821173
11831174 }
11841175
1176+ pfree (econtext );
1177+
11851178if (repl == NULL )
11861179return (tuple );
11871180
1188- return (heap_modifytuple (tuple ,InvalidBuffer ,rel ,replValue ,replNull ,repl ));
1181+ newtuple = heap_modifytuple (tuple ,InvalidBuffer ,rel ,replValue ,replNull ,repl );
1182+
1183+ pfree (repl );
1184+ pfree (replNull );
1185+ pfree (replValue );
1186+
1187+ return (newtuple );
1188+
1189+ }
1190+
1191+ static char *
1192+ ExecRelCheck (Relation rel ,HeapTuple tuple )
1193+ {
1194+ int ncheck = rel -> rd_att -> constr -> num_check ;
1195+ ConstrCheck * check = rel -> rd_att -> constr -> check ;
1196+ ExprContext * econtext = makeNode (ExprContext );
1197+ TupleTableSlot * slot = makeNode (TupleTableSlot );
1198+ RangeTblEntry * rte = makeNode (RangeTblEntry );
1199+ List * rtlist ;
1200+ List * qual ;
1201+ bool res ;
1202+ int i ;
1203+
1204+ slot -> val = tuple ;
1205+ slot -> ttc_shouldFree = false;
1206+ slot -> ttc_descIsNew = true;
1207+ slot -> ttc_tupleDescriptor = rel -> rd_att ;
1208+ slot -> ttc_buffer = InvalidBuffer ;
1209+ slot -> ttc_whichplan = -1 ;
1210+ rte -> relname = nameout (& (rel -> rd_rel -> relname ));
1211+ rte -> timeRange = NULL ;
1212+ rte -> refname = rte -> relname ;
1213+ rte -> relid = rel -> rd_id ;
1214+ rte -> inh = false;
1215+ rte -> archive = false;
1216+ rte -> inFromCl = true;
1217+ rte -> timeQual = NULL ;
1218+ rtlist = lcons (rte ,NIL );
1219+ econtext -> ecxt_scantuple = slot ;/* scan tuple slot */
1220+ econtext -> ecxt_innertuple = NULL ;/* inner tuple slot */
1221+ econtext -> ecxt_outertuple = NULL ;/* outer tuple slot */
1222+ econtext -> ecxt_relation = rel ;/* relation */
1223+ econtext -> ecxt_relid = 0 ;/* relid */
1224+ econtext -> ecxt_param_list_info = NULL ;/* param list info */
1225+ econtext -> ecxt_range_table = rtlist ;/* range table */
1226+
1227+ for (i = 0 ;i < ncheck ;i ++ )
1228+ {
1229+ qual = (List * )stringToNode (check [i ].ccbin );
1230+
1231+ res = ExecQual (qual ,econtext );
1232+
1233+ pfree (qual );
1234+
1235+ if ( !res )
1236+ return (check [i ].ccname );
1237+ }
1238+
1239+ pfree (slot );
1240+ pfree (rte -> relname );
1241+ pfree (rte );
1242+ pfree (rtlist );
1243+ pfree (econtext );
1244+
1245+ return ((char * )NULL );
1246+
1247+ }
1248+
1249+ HeapTuple
1250+ ExecConstraints (char * caller ,Relation rel ,HeapTuple tuple )
1251+ {
1252+ HeapTuple newtuple = tuple ;
1253+
1254+ Assert (rel -> rd_att -> constr );
11891255
1256+ if (rel -> rd_att -> constr -> num_defval > 0 )
1257+ newtuple = tuple = ExecAttrDefault (rel ,tuple );
1258+
1259+ if (rel -> rd_att -> constr -> has_not_null )
1260+ {
1261+ int attrChk ;
1262+
1263+ for (attrChk = 1 ;attrChk <=rel -> rd_att -> natts ;attrChk ++ )
1264+ {
1265+ if (rel -> rd_att -> attrs [attrChk - 1 ]-> attnotnull && heap_attisnull (tuple ,attrChk ))
1266+ elog (WARN ,"%s: Fail to add null value in not null attribute %s" ,
1267+ caller ,rel -> rd_att -> attrs [attrChk - 1 ]-> attname .data );
1268+ }
1269+ }
1270+
1271+ if (rel -> rd_att -> constr -> num_check > 0 )
1272+ {
1273+ char * failed ;
1274+
1275+ if ( (failed = ExecRelCheck (rel ,tuple ) )!= NULL )
1276+ elog (WARN ,"%s: rejected due to CHECK constraint %s" ,caller ,failed );
1277+ }
1278+
1279+ return (newtuple );
11901280}