Skip to content

Commit a1464e9

Browse files
author
Hiroshi Inoue
committed
Subclasses inherit constraints of super classes properly
1 parent dd8ad64 commit a1464e9

File tree

1 file changed

+84
-13
lines changed

1 file changed

+84
-13
lines changed

src/backend/commands/creatinh.c

Lines changed: 84 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
<<<<<<< creatinh.c
12-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.62 2000/07/04 06:11:27 tgl Exp $
13-
=======
14-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.62 2000/07/04 06:11:27 tgl Exp $
15-
>>>>>>> 1.58
11+
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.63 2000/08/04 06:12:11 inoue Exp $
1612
*
1713
*-------------------------------------------------------------------------
1814
*/
@@ -29,13 +25,14 @@
2925
#include "commands/creatinh.h"
3026
#include "miscadmin.h"
3127
#include "utils/syscache.h"
28+
#include "optimizer/clauses.h"
3229

3330
/* ----------------
3431
* local stuff
3532
* ----------------
3633
*/
3734

38-
static bool checkAttrExists(const char *attributeName,
35+
static int checkAttrExists(const char *attributeName,
3936
const char *attributeType, List *schema);
4037
static List *MergeAttributes(List *schema, List *supers, List **supconstr);
4138
static void StoreCatalogInheritance(Oid relationId, List *supers);
@@ -246,6 +243,45 @@ TruncateRelation(char *name)
246243
heap_truncate(name);
247244
}
248245

246+
/*
247+
* complementary static functions for MergeAttributes().
248+
* Varattnos of pg_relcheck.rcbin should be rewritten when
249+
* subclasses inherit the constraints from the super class.
250+
* Note that these functions rewrite varattnos while walking
251+
* through a node tree.
252+
*/
253+
static bool
254+
change_varattnos_walker(Node *node, const AttrNumber *newattno)
255+
{
256+
if (node == NULL)
257+
return false;
258+
if (IsA(node, Var))
259+
{
260+
Var *var = (Var *) node;
261+
262+
Assert(newattno != NULL);
263+
if (var->varlevelsup == 0 && var->varno == 1)
264+
{
265+
/*
266+
* ??? the following may be a problem when the
267+
* node is multiply referenced though
268+
* stringToNode() doesn't create such a node
269+
* currently.
270+
*/
271+
Assert(newattno[var->varattno - 1] > 0);
272+
var->varattno = newattno[var->varattno - 1];
273+
return true;
274+
}
275+
else
276+
return false;
277+
}
278+
return expression_tree_walker(node, change_varattnos_walker, (void *)newattno);
279+
}
280+
static bool
281+
change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
282+
{
283+
return expression_tree_walker(node, change_varattnos_walker, (void *)newattno);
284+
}
249285
/*
250286
* MergeAttributes
251287
* Returns new schema given initial schema and supers.
@@ -283,6 +319,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
283319
List *entry;
284320
List *inhSchema = NIL;
285321
List *constraints = NIL;
322+
int attnums;
286323

287324
/*
288325
* Validates that there are no duplications. Validity checking of
@@ -325,6 +362,7 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
325362
/*
326363
* merge the inherited attributes into the schema
327364
*/
365+
attnums = 0;
328366
foreach(entry, supers)
329367
{
330368
char *name = strVal(lfirst(entry));
@@ -333,15 +371,30 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
333371
AttrNumber attrno;
334372
TupleDesc tupleDesc;
335373
TupleConstr *constr;
374+
AttrNumber *newattno, *partialAttidx;
375+
Node *expr;
376+
int i, attidx, attno_exist;
336377

337378
relation = heap_openr(name, AccessShareLock);
338379
setRelhassubclassInRelation(relation->rd_id, true);
339380
tupleDesc = RelationGetDescr(relation);
381+
/* allocate a new attribute number table and initialize */
382+
newattno = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
383+
for (i = 0; i < tupleDesc->natts; i++)
384+
newattno [i] = 0;
385+
/*
386+
* searching and storing order are different.
387+
* another table is needed.
388+
*/
389+
partialAttidx = (AttrNumber *) palloc(tupleDesc->natts * sizeof(AttrNumber));
390+
for (i = 0; i < tupleDesc->natts; i++)
391+
partialAttidx [i] = 0;
340392
constr = tupleDesc->constr;
341393

342394
if (relation->rd_rel->relkind != RELKIND_RELATION)
343395
elog(ERROR, "CREATE TABLE: inherited relation \"%s\" is not a table", name);
344396

397+
attidx = 0;
345398
for (attrno = relation->rd_rel->relnatts - 1; attrno >= 0; attrno--)
346399
{
347400
Form_pg_attribute attribute = tupleDesc->attrs[attrno];
@@ -365,16 +418,21 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
365418
* check validity
366419
*
367420
*/
368-
if (checkAttrExists(attributeName, attributeType, schema))
421+
if (checkAttrExists(attributeName, attributeType, schema) != 0)
369422
elog(ERROR, "CREATE TABLE: attribute \"%s\" already exists in inherited schema",
370423
attributeName);
371424

372-
if (checkAttrExists(attributeName, attributeType, inhSchema))
425+
if (0 < (attno_exist = checkAttrExists(attributeName, attributeType, inhSchema)))
426+
{
373427

374428
/*
375429
* this entry already exists
376430
*/
431+
newattno[attribute->attnum - 1] = attno_exist;
377432
continue;
433+
}
434+
attidx++;
435+
partialAttidx[attribute->attnum - 1] = attidx;
378436

379437
/*
380438
* add an entry to the schema
@@ -408,6 +466,13 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
408466
}
409467
partialResult = lcons(def, partialResult);
410468
}
469+
for (i = 0; i < tupleDesc->natts; i++)
470+
{
471+
if (partialAttidx[i] > 0)
472+
newattno[i] = attnums + attidx + 1 - partialAttidx[i];
473+
}
474+
attnums += attidx;
475+
pfree(partialAttidx);
411476

412477
if (constr && constr->num_check > 0)
413478
{
@@ -424,10 +489,14 @@ MergeAttributes(List *schema, List *supers, List **supconstr)
424489
else
425490
cdef->name = pstrdup(check[i].ccname);
426491
cdef->raw_expr = NULL;
427-
cdef->cooked_expr = pstrdup(check[i].ccbin);
492+
/* adjust varattnos of ccbin here */
493+
expr = stringToNode(check[i].ccbin);
494+
change_varattnos_of_a_node(expr, newattno);
495+
cdef->cooked_expr = nodeToString(expr);
428496
constraints = lappend(constraints, cdef);
429497
}
430498
}
499+
pfree(newattno);
431500

432501
/*
433502
* Close the parent rel, but keep our AccessShareLock on it until
@@ -645,17 +714,19 @@ StoreCatalogInheritance(Oid relationId, List *supers)
645714

646715

647716
/*
648-
* returns true if attribute already exists in schema, false otherwise.
717+
* returns the index(star with 1) if attribute already exists in schema, 0 otherwise.
649718
*/
650-
static bool
719+
static int
651720
checkAttrExists(const char *attributeName, const char *attributeType, List *schema)
652721
{
653722
List *s;
723+
int i = 0;
654724

655725
foreach(s, schema)
656726
{
657727
ColumnDef *def = lfirst(s);
658728

729+
++i;
659730
if (strcmp(attributeName, def->colname) == 0)
660731
{
661732

@@ -665,10 +736,10 @@ checkAttrExists(const char *attributeName, const char *attributeType, List *sche
665736
if (strcmp(attributeType, def->typename->name) != 0)
666737
elog(ERROR, "CREATE TABLE: attribute \"%s\" type conflict (%s and %s)",
667738
attributeName, attributeType, def->typename->name);
668-
return true;
739+
return i;
669740
}
670741
}
671-
return false;
742+
return 0;
672743
}
673744

674745

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy