|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.204 2006/10/06 17:13:59 petere Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.205 2006/10/11 16:42:58 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -163,6 +163,8 @@ static List *MergeAttributes(List *schema, List *supers, bool istemp,
|
163 | 163 | List**supOids,List**supconstr,int*supOidCount);
|
164 | 164 | staticvoidMergeConstraintsIntoExisting(Relationchild_rel,Relationparent_rel);
|
165 | 165 | staticvoidMergeAttributesIntoExisting(Relationchild_rel,Relationparent_rel);
|
| 166 | +staticvoidadd_nonduplicate_constraint(Constraint*cdef, |
| 167 | +ConstrCheck*check,int*ncheck); |
166 | 168 | staticboolchange_varattnos_walker(Node*node,constAttrNumber*newattno);
|
167 | 169 | staticvoidStoreCatalogInheritance(OidrelationId,List*supers);
|
168 | 170 | staticvoidStoreCatalogInheritance1(OidrelationId,OidparentOid,
|
@@ -285,7 +287,6 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
285 | 287 | List*rawDefaults;
|
286 | 288 | Datumreloptions;
|
287 | 289 | ListCell*listptr;
|
288 |
| -inti; |
289 | 290 | AttrNumberattnum;
|
290 | 291 |
|
291 | 292 | /*
|
@@ -378,49 +379,35 @@ DefineRelation(CreateStmt *stmt, char relkind)
|
378 | 379 | localHasOids=interpretOidsOption(stmt->options);
|
379 | 380 | descriptor->tdhasoid= (localHasOids||parentOidCount>0);
|
380 | 381 |
|
381 |
| -if (old_constraints!=NIL) |
| 382 | +if (old_constraints||stmt->constraints) |
382 | 383 | {
|
383 |
| -ConstrCheck*check= (ConstrCheck*) |
384 |
| -palloc0(list_length(old_constraints)*sizeof(ConstrCheck)); |
| 384 | +ConstrCheck*check; |
385 | 385 | intncheck=0;
|
386 | 386 |
|
| 387 | +/* make array that's certainly big enough */ |
| 388 | +check= (ConstrCheck*) |
| 389 | +palloc((list_length(old_constraints)+ |
| 390 | +list_length(stmt->constraints))*sizeof(ConstrCheck)); |
| 391 | +/* deal with constraints from MergeAttributes */ |
387 | 392 | foreach(listptr,old_constraints)
|
388 | 393 | {
|
389 | 394 | Constraint*cdef= (Constraint*)lfirst(listptr);
|
390 |
| -booldup= false; |
391 | 395 |
|
392 |
| -if (cdef->contype!=CONSTR_CHECK) |
393 |
| -continue; |
394 |
| -Assert(cdef->name!=NULL); |
395 |
| -Assert(cdef->raw_expr==NULL&&cdef->cooked_expr!=NULL); |
| 396 | +if (cdef->contype==CONSTR_CHECK) |
| 397 | +add_nonduplicate_constraint(cdef,check,&ncheck); |
| 398 | +} |
| 399 | +/* |
| 400 | + * analyze.c might have passed some precooked constraints too, |
| 401 | + * due to LIKE tab INCLUDING CONSTRAINTS |
| 402 | + */ |
| 403 | +foreach(listptr,stmt->constraints) |
| 404 | +{ |
| 405 | +Constraint*cdef= (Constraint*)lfirst(listptr); |
396 | 406 |
|
397 |
| -/* |
398 |
| - * In multiple-inheritance situations, it's possible to inherit |
399 |
| - * the same grandparent constraint through multiple parents. |
400 |
| - * Hence, discard inherited constraints that match as to both name |
401 |
| - * and expression.Otherwise, gripe if the names conflict. |
402 |
| - */ |
403 |
| -for (i=0;i<ncheck;i++) |
404 |
| -{ |
405 |
| -if (strcmp(check[i].ccname,cdef->name)!=0) |
406 |
| -continue; |
407 |
| -if (strcmp(check[i].ccbin,cdef->cooked_expr)==0) |
408 |
| -{ |
409 |
| -dup= true; |
410 |
| -break; |
411 |
| -} |
412 |
| -ereport(ERROR, |
413 |
| -(errcode(ERRCODE_DUPLICATE_OBJECT), |
414 |
| -errmsg("duplicate check constraint name \"%s\"", |
415 |
| -cdef->name))); |
416 |
| -} |
417 |
| -if (!dup) |
418 |
| -{ |
419 |
| -check[ncheck].ccname=cdef->name; |
420 |
| -check[ncheck].ccbin=pstrdup(cdef->cooked_expr); |
421 |
| -ncheck++; |
422 |
| -} |
| 407 | +if (cdef->contype==CONSTR_CHECK&&cdef->cooked_expr!=NULL) |
| 408 | +add_nonduplicate_constraint(cdef,check,&ncheck); |
423 | 409 | }
|
| 410 | +/* if we found any, insert 'em into the descriptor */ |
424 | 411 | if (ncheck>0)
|
425 | 412 | {
|
426 | 413 | if (descriptor->constr==NULL)
|
@@ -1118,66 +1105,57 @@ MergeAttributes(List *schema, List *supers, bool istemp,
|
1118 | 1105 | returnschema;
|
1119 | 1106 | }
|
1120 | 1107 |
|
| 1108 | + |
1121 | 1109 | /*
|
1122 |
| - * Varattnos of pg_constraint.conbin must be rewritten when subclasses inherit |
1123 |
| - * constraints from parent classes, since the inherited attributes could |
1124 |
| - * be given different column numbers in multiple-inheritance cases. |
1125 |
| - * |
1126 |
| - * Note that the passed node tree is modified in place! |
1127 |
| - * |
1128 |
| - * This function is used elsewhere such as in analyze.c |
1129 |
| - * |
| 1110 | + * In multiple-inheritance situations, it's possible to inherit |
| 1111 | + * the same grandparent constraint through multiple parents. |
| 1112 | + * Hence, we want to discard inherited constraints that match as to |
| 1113 | + * both name and expression. Otherwise, gripe if there are conflicting |
| 1114 | + * names. Nonconflicting constraints are added to the array check[] |
| 1115 | + * of length *ncheck ... caller must ensure there is room! |
1130 | 1116 | */
|
1131 |
| - |
1132 |
| -void |
1133 |
| -change_varattnos_of_a_node(Node*node,constAttrNumber*newattno) |
| 1117 | +staticvoid |
| 1118 | +add_nonduplicate_constraint(Constraint*cdef,ConstrCheck*check,int*ncheck) |
1134 | 1119 | {
|
1135 |
| -change_varattnos_walker(node,newattno); |
1136 |
| -} |
1137 |
| - |
1138 |
| -/* Generate a map for change_varattnos_of_a_node from two tupledesc's. */ |
| 1120 | +inti; |
1139 | 1121 |
|
1140 |
| -AttrNumber* |
1141 |
| -varattnos_map(TupleDescold,TupleDescnew) |
1142 |
| -{ |
1143 |
| -inti, |
1144 |
| -j; |
1145 |
| -AttrNumber*attmap=palloc0(sizeof(AttrNumber)*old->natts); |
| 1122 | +/* Should only see precooked constraints here */ |
| 1123 | +Assert(cdef->contype==CONSTR_CHECK); |
| 1124 | +Assert(cdef->name!=NULL); |
| 1125 | +Assert(cdef->raw_expr==NULL&&cdef->cooked_expr!=NULL); |
1146 | 1126 |
|
1147 |
| -for (i=1;i <=old->natts;i++) |
| 1127 | +for (i=0;i<*ncheck;i++) |
1148 | 1128 | {
|
1149 |
| -if (old->attrs[i-1]->attisdropped) |
1150 |
| -{ |
1151 |
| -attmap[i-1]=0; |
| 1129 | +if (strcmp(check[i].ccname,cdef->name)!=0) |
1152 | 1130 | continue;
|
1153 |
| -} |
1154 |
| -for (j=1;j <=new->natts;j++) |
1155 |
| -if (!strcmp(NameStr(old->attrs[i-1]->attname),NameStr(new->attrs[j-1]->attname))) |
1156 |
| -attmap[i-1]=j; |
| 1131 | +if (strcmp(check[i].ccbin,cdef->cooked_expr)==0) |
| 1132 | +return;/* duplicate constraint, so ignore it */ |
| 1133 | +ereport(ERROR, |
| 1134 | +(errcode(ERRCODE_DUPLICATE_OBJECT), |
| 1135 | +errmsg("duplicate check constraint name \"%s\"", |
| 1136 | +cdef->name))); |
1157 | 1137 | }
|
1158 |
| -returnattmap; |
| 1138 | +/* No match on name, so add it to array */ |
| 1139 | +check[*ncheck].ccname=cdef->name; |
| 1140 | +check[*ncheck].ccbin=pstrdup(cdef->cooked_expr); |
| 1141 | +(*ncheck)++; |
1159 | 1142 | }
|
1160 | 1143 |
|
| 1144 | + |
1161 | 1145 | /*
|
1162 |
| - * Generate a map for change_varattnos_of_a_node from a tupledesc and a list of |
1163 |
| - * ColumnDefs |
| 1146 | + * Replace varattno values in an expression tree according to the given |
| 1147 | + * map array, that is, varattno N is replaced by newattno[N-1]. It is |
| 1148 | + * caller's responsibility to ensure that the array is long enough to |
| 1149 | + * define values for all user varattnos present in the tree. System column |
| 1150 | + * attnos remain unchanged. |
| 1151 | + * |
| 1152 | + * Note that the passed node tree is modified in-place! |
1164 | 1153 | */
|
1165 |
| -AttrNumber* |
1166 |
| -varattnos_map_schema(TupleDescold,List*schema) |
| 1154 | +void |
| 1155 | +change_varattnos_of_a_node(Node*node,constAttrNumber*newattno) |
1167 | 1156 | {
|
1168 |
| -inti; |
1169 |
| -AttrNumber*attmap=palloc0(sizeof(AttrNumber)*old->natts); |
1170 |
| - |
1171 |
| -for (i=1;i <=old->natts;i++) |
1172 |
| -{ |
1173 |
| -if (old->attrs[i-1]->attisdropped) |
1174 |
| -{ |
1175 |
| -attmap[i-1]=0; |
1176 |
| -continue; |
1177 |
| -} |
1178 |
| -attmap[i-1]=findAttrByName(NameStr(old->attrs[i-1]->attname),schema); |
1179 |
| -} |
1180 |
| -returnattmap; |
| 1157 | +/* no setup needed, so away we go */ |
| 1158 | +(void)change_varattnos_walker(node,newattno); |
1181 | 1159 | }
|
1182 | 1160 |
|
1183 | 1161 | staticbool
|
@@ -1206,6 +1184,59 @@ change_varattnos_walker(Node *node, const AttrNumber *newattno)
|
1206 | 1184 | (void*)newattno);
|
1207 | 1185 | }
|
1208 | 1186 |
|
| 1187 | +/* |
| 1188 | + * Generate a map for change_varattnos_of_a_node from old and new TupleDesc's, |
| 1189 | + * matching according to column name. |
| 1190 | + */ |
| 1191 | +AttrNumber* |
| 1192 | +varattnos_map(TupleDescold,TupleDescnew) |
| 1193 | +{ |
| 1194 | +AttrNumber*attmap; |
| 1195 | +inti, |
| 1196 | +j; |
| 1197 | + |
| 1198 | +attmap= (AttrNumber*)palloc0(sizeof(AttrNumber)*old->natts); |
| 1199 | +for (i=1;i <=old->natts;i++) |
| 1200 | +{ |
| 1201 | +if (old->attrs[i-1]->attisdropped) |
| 1202 | +continue;/* leave the entry as zero */ |
| 1203 | + |
| 1204 | +for (j=1;j <=new->natts;j++) |
| 1205 | +{ |
| 1206 | +if (strcmp(NameStr(old->attrs[i-1]->attname), |
| 1207 | +NameStr(new->attrs[j-1]->attname))==0) |
| 1208 | +{ |
| 1209 | +attmap[i-1]=j; |
| 1210 | +break; |
| 1211 | +} |
| 1212 | +} |
| 1213 | +} |
| 1214 | +returnattmap; |
| 1215 | +} |
| 1216 | + |
| 1217 | +/* |
| 1218 | + * Generate a map for change_varattnos_of_a_node from a TupleDesc and a list |
| 1219 | + * of ColumnDefs |
| 1220 | + */ |
| 1221 | +AttrNumber* |
| 1222 | +varattnos_map_schema(TupleDescold,List*schema) |
| 1223 | +{ |
| 1224 | +AttrNumber*attmap; |
| 1225 | +inti; |
| 1226 | + |
| 1227 | +attmap= (AttrNumber*)palloc0(sizeof(AttrNumber)*old->natts); |
| 1228 | +for (i=1;i <=old->natts;i++) |
| 1229 | +{ |
| 1230 | +if (old->attrs[i-1]->attisdropped) |
| 1231 | +continue;/* leave the entry as zero */ |
| 1232 | + |
| 1233 | +attmap[i-1]=findAttrByName(NameStr(old->attrs[i-1]->attname), |
| 1234 | +schema); |
| 1235 | +} |
| 1236 | +returnattmap; |
| 1237 | +} |
| 1238 | + |
| 1239 | + |
1209 | 1240 | /*
|
1210 | 1241 | * StoreCatalogInheritance
|
1211 | 1242 | *Updates the system catalogs with proper inheritance information.
|
|