Subclasses inherit constraints of super classes properly
This commit is contained in:
parent
dd8ad64118
commit
a1464e971c
|
@ -8,11 +8,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
<<<<<<< creatinh.c
|
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.63 2000/08/04 06:12:11 inoue Exp $
|
||||||
* $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
|
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -29,13 +25,14 @@
|
||||||
#include "commands/creatinh.h"
|
#include "commands/creatinh.h"
|
||||||
#include "miscadmin.h"
|
#include "miscadmin.h"
|
||||||
#include "utils/syscache.h"
|
#include "utils/syscache.h"
|
||||||
|
#include "optimizer/clauses.h"
|
||||||
|
|
||||||
/* ----------------
|
/* ----------------
|
||||||
* local stuff
|
* local stuff
|
||||||
* ----------------
|
* ----------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static bool checkAttrExists(const char *attributeName,
|
static int checkAttrExists(const char *attributeName,
|
||||||
const char *attributeType, List *schema);
|
const char *attributeType, List *schema);
|
||||||
static List *MergeAttributes(List *schema, List *supers, List **supconstr);
|
static List *MergeAttributes(List *schema, List *supers, List **supconstr);
|
||||||
static void StoreCatalogInheritance(Oid relationId, List *supers);
|
static void StoreCatalogInheritance(Oid relationId, List *supers);
|
||||||
|
@ -246,6 +243,45 @@ TruncateRelation(char *name)
|
||||||
heap_truncate(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
|
* MergeAttributes
|
||||||
* Returns new schema given initial schema and supers.
|
* Returns new schema given initial schema and supers.
|
||||||
|
@ -283,6 +319,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||||
List *entry;
|
List *entry;
|
||||||
List *inhSchema = NIL;
|
List *inhSchema = NIL;
|
||||||
List *constraints = NIL;
|
List *constraints = NIL;
|
||||||
|
int attnums;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Validates that there are no duplications. Validity checking of
|
* 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
|
* merge the inherited attributes into the schema
|
||||||
*/
|
*/
|
||||||
|
attnums = 0;
|
||||||
foreach(entry, supers)
|
foreach(entry, supers)
|
||||||
{
|
{
|
||||||
char *name = strVal(lfirst(entry));
|
char *name = strVal(lfirst(entry));
|
||||||
|
@ -333,15 +371,30 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||||
AttrNumber attrno;
|
AttrNumber attrno;
|
||||||
TupleDesc tupleDesc;
|
TupleDesc tupleDesc;
|
||||||
TupleConstr *constr;
|
TupleConstr *constr;
|
||||||
|
AttrNumber *newattno, *partialAttidx;
|
||||||
|
Node *expr;
|
||||||
|
int i, attidx, attno_exist;
|
||||||
|
|
||||||
relation = heap_openr(name, AccessShareLock);
|
relation = heap_openr(name, AccessShareLock);
|
||||||
setRelhassubclassInRelation(relation->rd_id, true);
|
setRelhassubclassInRelation(relation->rd_id, true);
|
||||||
tupleDesc = RelationGetDescr(relation);
|
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;
|
constr = tupleDesc->constr;
|
||||||
|
|
||||||
if (relation->rd_rel->relkind != RELKIND_RELATION)
|
if (relation->rd_rel->relkind != RELKIND_RELATION)
|
||||||
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
|
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
|
||||||
|
|
||||||
|
attidx = 0;
|
||||||
for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
|
for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
|
||||||
{
|
{
|
||||||
Form_pg_attribute attribute = tupleDesc->attrs[attrno];
|
Form_pg_attribute attribute = tupleDesc->attrs[attrno];
|
||||||
|
@ -365,16 +418,21 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||||
* check validity
|
* check validity
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
if (checkAttrExists(attributeName, attributeType, schema))
|
if (checkAttrExists(attributeName, attributeType, schema) != 0)
|
||||||
elog(ERROR, "CREATE TABLE: attribute \"%s\" already exists in inherited schema",
|
elog(ERROR, "CREATE TABLE: attribute \"%s\" already exists in inherited schema",
|
||||||
attributeName);
|
attributeName);
|
||||||
|
|
||||||
if (checkAttrExists(attributeName, attributeType, inhSchema))
|
if (0 < (attno_exist = checkAttrExists(attributeName, attributeType, inhSchema)))
|
||||||
|
{
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* this entry already exists
|
* this entry already exists
|
||||||
*/
|
*/
|
||||||
|
newattno[attribute->attnum - 1] = attno_exist;
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
attidx++;
|
||||||
|
partialAttidx[attribute->attnum - 1] = attidx;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* add an entry to the schema
|
* add an entry to the schema
|
||||||
|
@ -408,6 +466,13 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||||
}
|
}
|
||||||
partialResult = lcons(def, partialResult);
|
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)
|
if (constr && constr->num_check > 0)
|
||||||
{
|
{
|
||||||
|
@ -424,10 +489,14 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
|
||||||
else
|
else
|
||||||
cdef->name = pstrdup(check[i].ccname);
|
cdef->name = pstrdup(check[i].ccname);
|
||||||
cdef->raw_expr = NULL;
|
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);
|
constraints = lappend(constraints, cdef);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pfree(newattno);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Close the parent rel, but keep our AccessShareLock on it until
|
* 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)
|
checkAttrExists(const char *attributeName, const char *attributeType, List *schema)
|
||||||
{
|
{
|
||||||
List *s;
|
List *s;
|
||||||
|
int i = 0;
|
||||||
|
|
||||||
foreach(s, schema)
|
foreach(s, schema)
|
||||||
{
|
{
|
||||||
ColumnDef *def = lfirst(s);
|
ColumnDef *def = lfirst(s);
|
||||||
|
|
||||||
|
++i;
|
||||||
if (strcmp(attributeName, def->colname) == 0)
|
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)
|
if (strcmp(attributeType, def->typename->name) != 0)
|
||||||
elog(ERROR, "CREATE TABLE: attribute \"%s\" type conflict (%s and %s)",
|
elog(ERROR, "CREATE TABLE: attribute \"%s\" type conflict (%s and %s)",
|
||||||
attributeName, attributeType, def->typename->name);
|
attributeName, attributeType, def->typename->name);
|
||||||
return true;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue