mirror of
https://git.postgresql.org/git/postgresql.git
synced 2025-01-24 18:55:04 +08:00
Subclasses inherit constraints of super classes properly
This commit is contained in:
parent
dd8ad64118
commit
a1464e971c
@ -8,11 +8,7 @@
|
||||
*
|
||||
*
|
||||
* 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 $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -29,13 +25,14 @@
|
||||
#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);
|
||||
@ -246,6 +243,45 @@ TruncateRelation(char *name)
|
||||
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.
|
||||
@ -283,6 +319,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||
List *entry;
|
||||
List *inhSchema = NIL;
|
||||
List *constraints = NIL;
|
||||
int attnums;
|
||||
|
||||
/*
|
||||
* Validates that there are no duplications. Validity checking of
|
||||
@ -325,6 +362,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||
/*
|
||||
* merge the inherited attributes into the schema
|
||||
*/
|
||||
attnums = 0;
|
||||
foreach(entry, supers)
|
||||
{
|
||||
char *name = strVal(lfirst(entry));
|
||||
@ -333,15 +371,30 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||
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];
|
||||
@ -365,16 +418,21 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||
* 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
|
||||
@ -408,6 +466,13 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||
}
|
||||
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)
|
||||
{
|
||||
@ -424,10 +489,14 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||
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
|
||||
@ -645,17 +714,19 @@ again:
|
||||
|
||||
|
||||
/*
|
||||
* 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)
|
||||
{
|
||||
|
||||
@ -665,10 +736,10 @@ checkAttrExists(const char *attributeName, const char *attributeType, List *sche
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user