*
*
* IDENTIFICATION
-<<<<<<< creatinh.c
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.62 2000/07/04 06:11:27 tgl Exp $
-=======
- * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.62 2000/07/04 06:11:27 tgl Exp $
->>>>>>> 1.58
+ * $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.63 2000/08/04 06:12:11 inoue Exp $
*
*-------------------------------------------------------------------------
*/
#include "commands/creatinh.h"
#include "miscadmin.h"
#include "utils/syscache.h"
+#include "optimizer/clauses.h"
/* ----------------
* local stuff
* ----------------
*/
-static bool checkAttrExists(const char *attributeName,
+static int checkAttrExists(const char *attributeName,
const char *attributeType, List *schema);
static List *MergeAttributes(List *schema, List *supers, List **supconstr);
static void StoreCatalogInheritance(Oid relationId, List *supers);
heap_truncate(name);
}
+/*
+ * complementary static functions for MergeAttributes().
+ * Varattnos of pg_relcheck.rcbin should be rewritten when
+ * subclasses inherit the constraints from the super class.
+ * Note that these functions rewrite varattnos while walking
+ * through a node tree.
+ */
+static bool
+change_varattnos_walker(Node *node, const AttrNumber *newattno)
+{
+ if (node == NULL)
+ return false;
+ if (IsA(node, Var))
+ {
+ Var *var = (Var *) node;
+
+ Assert(newattno != NULL);
+ if (var->varlevelsup == 0 && var->varno == 1)
+ {
+ /*
+ * ??? 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 = newattno[var->varattno - 1];
+ return true;
+ }
+ else
+ return false;
+ }
+ return expression_tree_walker(node, change_varattnos_walker, (void *)newattno);
+}
+static bool
+change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
+{
+ return expression_tree_walker(node, change_varattnos_walker, (void *)newattno);
+}
/*
* MergeAttributes
* Returns new schema given initial schema and supers.
List *entry;
List *inhSchema = NIL;
List *constraints = NIL;
+ int attnums;
/*
* Validates that there are no duplications. Validity checking of
/*
* merge the inherited attributes into the schema
*/
+ attnums = 0;
foreach(entry, supers)
{
char *name = strVal(lfirst(entry));
AttrNumber attrno;
TupleDesc tupleDesc;
TupleConstr *constr;
+ AttrNumber *newattno, *partialAttidx;
+ Node *expr;
+ int i, attidx, attno_exist;
relation = heap_openr(name, AccessShareLock);
setRelhassubclassInRelation(relation->rd_id, true);
tupleDesc = RelationGetDescr(relation);
+ /* allocate a new attribute number table and initialize */
+ newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
+ for (i = 0; i < tupleDesc->natts; i++)
+ newattno [i] = 0;
+ /*
+ * searching and storing order are different.
+ * another table is needed.
+ */
+ partialAttidx = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
+ for (i = 0; i < tupleDesc->natts; i++)
+ partialAttidx [i] = 0;
constr = tupleDesc->constr;
if (relation->rd_rel->relkind != RELKIND_RELATION)
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
+ attidx = 0;
for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
{
Form_pg_attribute attribute = tupleDesc->attrs[attrno];
* check validity
*
*/
- if (checkAttrExists(attributeName, attributeType, schema))
+ if (checkAttrExists(attributeName, attributeType, schema) != 0)
elog(ERROR, "CREATE TABLE: attribute \"%s\" already exists in inherited schema",
attributeName);
- if (checkAttrExists(attributeName, attributeType, inhSchema))
+ if (0 < (attno_exist = checkAttrExists(attributeName, attributeType, inhSchema)))
+ {
/*
* this entry already exists
*/
+ newattno[attribute->attnum - 1] = attno_exist;
continue;
+ }
+ attidx++;
+ partialAttidx[attribute->attnum - 1] = attidx;
/*
* add an entry to the schema
}
partialResult = lcons(def, partialResult);
}
+ for (i = 0; i < tupleDesc->natts; i++)
+ {
+ if (partialAttidx[i] > 0)
+ newattno[i] = attnums + attidx + 1 - partialAttidx[i];
+ }
+ attnums += attidx;
+ pfree(partialAttidx);
if (constr && constr->num_check > 0)
{
else
cdef->name = pstrdup(check[i].ccname);
cdef->raw_expr = NULL;
- cdef->cooked_expr = pstrdup(check[i].ccbin);
+ /* adjust varattnos of ccbin here */
+ expr = stringToNode(check[i].ccbin);
+ change_varattnos_of_a_node(expr, newattno);
+ cdef->cooked_expr = nodeToString(expr);
constraints = lappend(constraints, cdef);
}
}
+ pfree(newattno);
/*
* Close the parent rel, but keep our AccessShareLock on it until
/*
- * returns true if attribute already exists in schema, false otherwise.
+ * returns the index(star with 1) if attribute already exists in schema, 0 otherwise.
*/
-static bool
+static int
checkAttrExists(const char *attributeName, const char *attributeType, List *schema)
{
List *s;
+ int i = 0;
foreach(s, schema)
{
ColumnDef *def = lfirst(s);
+ ++i;
if (strcmp(attributeName, def->colname) == 0)
{
if (strcmp(attributeType, def->typename->name) != 0)
elog(ERROR, "CREATE TABLE: attribute \"%s\" type conflict (%s and %s)",
attributeName, attributeType, def->typename->name);
- return true;
+ return i;
}
}
- return false;
+ return 0;
}