diff options
Diffstat (limited to 'src/backend/commands/tablecmds.c')
-rw-r--r-- | src/backend/commands/tablecmds.c | 131 |
1 files changed, 22 insertions, 109 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 70753e33e43..d69809a2f86 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -68,6 +68,7 @@ #include "parser/parser.h" #include "rewrite/rewriteDefine.h" #include "rewrite/rewriteHandler.h" +#include "rewrite/rewriteManip.h" #include "storage/bufmgr.h" #include "storage/lmgr.h" #include "storage/lock.h" @@ -253,7 +254,6 @@ static void truncate_check_rel(Relation rel); static List *MergeAttributes(List *schema, List *supers, char relpersistence, List **supOids, List **supconstr, int *supOidCount); static bool MergeCheckConstraint(List *constraints, char *name, Node *expr); -static bool change_varattnos_walker(Node *node, const AttrNumber *newattno); static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel); static void MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel); static void StoreCatalogInheritance(Oid relationId, List *supers); @@ -1496,7 +1496,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, * parents after the first one, nor if we have dropped columns.) */ newattno = (AttrNumber *) - palloc(tupleDesc->natts * sizeof(AttrNumber)); + palloc0(tupleDesc->natts * sizeof(AttrNumber)); for (parent_attno = 1; parent_attno <= tupleDesc->natts; parent_attno++) @@ -1510,15 +1510,7 @@ MergeAttributes(List *schema, List *supers, char relpersistence, * Ignore dropped columns in the parent. */ if (attribute->attisdropped) - { - /* - * change_varattnos_of_a_node asserts that this is greater - * than zero, so if anything tries to use it, we should find - * out. - */ - newattno[parent_attno - 1] = 0; - continue; - } + continue; /* leave newattno entry as zero */ /* * Does it conflict with some previously inherited column? @@ -1656,14 +1648,30 @@ MergeAttributes(List *schema, List *supers, char relpersistence, { char *name = check[i].ccname; Node *expr; + bool found_whole_row; /* ignore if the constraint is non-inheritable */ if (check[i].ccnoinherit) continue; - /* adjust varattnos of ccbin here */ - expr = stringToNode(check[i].ccbin); - change_varattnos_of_a_node(expr, newattno); + /* Adjust Vars to match new table's column numbering */ + expr = map_variable_attnos(stringToNode(check[i].ccbin), + 1, 0, + newattno, tupleDesc->natts, + &found_whole_row); + + /* + * For the moment we have to reject whole-row variables. + * We could convert them, if we knew the new table's rowtype + * OID, but that hasn't been assigned yet. + */ + if (found_whole_row) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot convert whole-row table reference"), + errdetail("Constraint \"%s\" contains a whole-row reference to table \"%s\".", + name, + RelationGetRelationName(relation)))); /* check for duplicate */ if (!MergeCheckConstraint(constraints, name, expr)) @@ -1867,101 +1875,6 @@ MergeCheckConstraint(List *constraints, char *name, Node *expr) /* - * Replace varattno values in an expression tree according to the given - * map array, that is, varattno N is replaced by newattno[N-1]. It is - * caller's responsibility to ensure that the array is long enough to - * define values for all user varattnos present in the tree. System column - * attnos remain unchanged. - * - * Note that the passed node tree is modified in-place! - */ -void -change_varattnos_of_a_node(Node *node, const AttrNumber *newattno) -{ - /* no setup needed, so away we go */ - (void) change_varattnos_walker(node, newattno); -} - -static bool -change_varattnos_walker(Node *node, const AttrNumber *newattno) -{ - if (node == NULL) - return false; - if (IsA(node, Var)) - { - Var *var = (Var *) node; - - if (var->varlevelsup == 0 && var->varno == 1 && - var->varattno > 0) - { - /* - * ??? the following may be a problem when the node is multiply - * referenced though stringToNode() doesn't create such a node - * currently. - */ - Assert(newattno[var->varattno - 1] > 0); - var->varattno = var->varoattno = newattno[var->varattno - 1]; - } - return false; - } - return expression_tree_walker(node, change_varattnos_walker, - (void *) newattno); -} - -/* - * Generate a map for change_varattnos_of_a_node from old and new TupleDesc's, - * matching according to column name. - */ -AttrNumber * -varattnos_map(TupleDesc olddesc, TupleDesc newdesc) -{ - AttrNumber *attmap; - int i, - j; - - attmap = (AttrNumber *) palloc0(sizeof(AttrNumber) * olddesc->natts); - for (i = 1; i <= olddesc->natts; i++) - { - if (olddesc->attrs[i - 1]->attisdropped) - continue; /* leave the entry as zero */ - - for (j = 1; j <= newdesc->natts; j++) - { - if (strcmp(NameStr(olddesc->attrs[i - 1]->attname), - NameStr(newdesc->attrs[j - 1]->attname)) == 0) - { - attmap[i - 1] = j; - break; - } - } - } - return attmap; -} - -/* - * Generate a map for change_varattnos_of_a_node from a TupleDesc and a list - * of ColumnDefs - */ -AttrNumber * -varattnos_map_schema(TupleDesc old, List *schema) -{ - AttrNumber *attmap; - int i; - - attmap = (AttrNumber *) palloc0(sizeof(AttrNumber) * old->natts); - for (i = 1; i <= old->natts; i++) - { - if (old->attrs[i - 1]->attisdropped) - continue; /* leave the entry as zero */ - - attmap[i - 1] = findAttrByName(NameStr(old->attrs[i - 1]->attname), - schema); - } - return attmap; -} - - -/* * StoreCatalogInheritance * Updates the system catalogs with proper inheritance information. * |