Skip to content

Commit 8f2f180

Browse files
committed
Code review for LIKE INCLUDING CONSTRAINTS patch --- improve comments,
don't cheat on the raw-vs-cooked status of a constraint.
1 parent 3f16647 commit 8f2f180

File tree

3 files changed

+142
-106
lines changed

3 files changed

+142
-106
lines changed

src/backend/commands/tablecmds.c

Lines changed: 114 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.204 2006/10/06 17:13:59 petere Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.205 2006/10/11 16:42:58 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -163,6 +163,8 @@ static List *MergeAttributes(List *schema, List *supers, bool istemp,
163163
List **supOids, List **supconstr, int *supOidCount);
164164
static void MergeConstraintsIntoExisting(Relation child_rel, Relation parent_rel);
165165
static void MergeAttributesIntoExisting(Relation child_rel, Relation parent_rel);
166+
static void add_nonduplicate_constraint(Constraint *cdef,
167+
ConstrCheck *check, int *ncheck);
166168
static bool change_varattnos_walker(Node *node, const AttrNumber *newattno);
167169
static void StoreCatalogInheritance(Oid relationId, List *supers);
168170
static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
@@ -285,7 +287,6 @@ DefineRelation(CreateStmt *stmt, char relkind)
285287
List *rawDefaults;
286288
Datum reloptions;
287289
ListCell *listptr;
288-
int i;
289290
AttrNumber attnum;
290291

291292
/*
@@ -378,49 +379,35 @@ DefineRelation(CreateStmt *stmt, char relkind)
378379
localHasOids = interpretOidsOption(stmt->options);
379380
descriptor->tdhasoid = (localHasOids || parentOidCount > 0);
380381

381-
if (old_constraints != NIL)
382+
if (old_constraints || stmt->constraints)
382383
{
383-
ConstrCheck *check = (ConstrCheck *)
384-
palloc0(list_length(old_constraints) * sizeof(ConstrCheck));
384+
ConstrCheck *check;
385385
int ncheck = 0;
386386

387+
/* make array that's certainly big enough */
388+
check = (ConstrCheck *)
389+
palloc((list_length(old_constraints) +
390+
list_length(stmt->constraints)) * sizeof(ConstrCheck));
391+
/* deal with constraints from MergeAttributes */
387392
foreach(listptr, old_constraints)
388393
{
389394
Constraint *cdef = (Constraint *) lfirst(listptr);
390-
bool dup = false;
391395

392-
if (cdef->contype != CONSTR_CHECK)
393-
continue;
394-
Assert(cdef->name != NULL);
395-
Assert(cdef->raw_expr == NULL && cdef->cooked_expr != NULL);
396+
if (cdef->contype == CONSTR_CHECK)
397+
add_nonduplicate_constraint(cdef, check, &ncheck);
398+
}
399+
/*
400+
* analyze.c might have passed some precooked constraints too,
401+
* due to LIKE tab INCLUDING CONSTRAINTS
402+
*/
403+
foreach(listptr, stmt->constraints)
404+
{
405+
Constraint *cdef = (Constraint *) lfirst(listptr);
396406

397-
/*
398-
* In multiple-inheritance situations, it's possible to inherit
399-
* the same grandparent constraint through multiple parents.
400-
* Hence, discard inherited constraints that match as to both name
401-
* and expression. Otherwise, gripe if the names conflict.
402-
*/
403-
for (i = 0; i < ncheck; i++)
404-
{
405-
if (strcmp(check[i].ccname, cdef->name) != 0)
406-
continue;
407-
if (strcmp(check[i].ccbin, cdef->cooked_expr) == 0)
408-
{
409-
dup = true;
410-
break;
411-
}
412-
ereport(ERROR,
413-
(errcode(ERRCODE_DUPLICATE_OBJECT),
414-
errmsg("duplicate check constraint name \"%s\"",
415-
cdef->name)));
416-
}
417-
if (!dup)
418-
{
419-
check[ncheck].ccname = cdef->name;
420-
check[ncheck].ccbin = pstrdup(cdef->cooked_expr);
421-
ncheck++;
422-
}
407+
if (cdef->contype == CONSTR_CHECK && cdef->cooked_expr != NULL)
408+
add_nonduplicate_constraint(cdef, check, &ncheck);
423409
}
410+
/* if we found any, insert 'em into the descriptor */
424411
if (ncheck > 0)
425412
{
426413
if (descriptor->constr == NULL)
@@ -1118,66 +1105,57 @@ MergeAttributes(List *schema, List *supers, bool istemp,
11181105
return schema;
11191106
}
11201107

1108+
11211109
/*
1122-
* Varattnos of pg_constraint.conbin must be rewritten when subclasses inherit
1123-
* constraints from parent classes, since the inherited attributes could
1124-
* be given different column numbers in multiple-inheritance cases.
1125-
*
1126-
* Note that the passed node tree is modified in place!
1127-
*
1128-
* This function is used elsewhere such as in analyze.c
1129-
*
1110+
* In multiple-inheritance situations, it's possible to inherit
1111+
* the same grandparent constraint through multiple parents.
1112+
* Hence, we want to discard inherited constraints that match as to
1113+
* both name and expression. Otherwise, gripe if there are conflicting
1114+
* names. Nonconflicting constraints are added to the array check[]
1115+
* of length *ncheck ... caller must ensure there is room!
11301116
*/
1131-
1132-
void
1133-
change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
1117+
static void
1118+
add_nonduplicate_constraint(Constraint *cdef, ConstrCheck *check, int *ncheck)
11341119
{
1135-
change_varattnos_walker(node, newattno);
1136-
}
1137-
1138-
/* Generate a map for change_varattnos_of_a_node from two tupledesc's. */
1120+
int i;
11391121

1140-
AttrNumber *
1141-
varattnos_map(TupleDesc old, TupleDesc new)
1142-
{
1143-
int i,
1144-
j;
1145-
AttrNumber *attmap = palloc0(sizeof(AttrNumber) * old->natts);
1122+
/* Should only see precooked constraints here */
1123+
Assert(cdef->contype == CONSTR_CHECK);
1124+
Assert(cdef->name != NULL);
1125+
Assert(cdef->raw_expr == NULL && cdef->cooked_expr != NULL);
11461126

1147-
for (i = 1; i <= old->natts; i++)
1127+
for (i = 0; i < *ncheck; i++)
11481128
{
1149-
if (old->attrs[i - 1]->attisdropped)
1150-
{
1151-
attmap[i - 1] = 0;
1129+
if (strcmp(check[i].ccname, cdef->name) != 0)
11521130
continue;
1153-
}
1154-
for (j = 1; j <= new->natts; j++)
1155-
if (!strcmp(NameStr(old->attrs[i - 1]->attname), NameStr(new->attrs[j - 1]->attname)))
1156-
attmap[i - 1] = j;
1131+
if (strcmp(check[i].ccbin, cdef->cooked_expr) == 0)
1132+
return; /* duplicate constraint, so ignore it */
1133+
ereport(ERROR,
1134+
(errcode(ERRCODE_DUPLICATE_OBJECT),
1135+
errmsg("duplicate check constraint name \"%s\"",
1136+
cdef->name)));
11571137
}
1158-
return attmap;
1138+
/* No match on name, so add it to array */
1139+
check[*ncheck].ccname = cdef->name;
1140+
check[*ncheck].ccbin = pstrdup(cdef->cooked_expr);
1141+
(*ncheck)++;
11591142
}
11601143

1144+
11611145
/*
1162-
* Generate a map for change_varattnos_of_a_node from a tupledesc and a list of
1163-
* ColumnDefs
1146+
* Replace varattno values in an expression tree according to the given
1147+
* map array, that is, varattno N is replaced by newattno[N-1]. It is
1148+
* caller's responsibility to ensure that the array is long enough to
1149+
* define values for all user varattnos present in the tree. System column
1150+
* attnos remain unchanged.
1151+
*
1152+
* Note that the passed node tree is modified in-place!
11641153
*/
1165-
AttrNumber *
1166-
varattnos_map_schema(TupleDesc old, List *schema)
1154+
void
1155+
change_varattnos_of_a_node(Node *node, const AttrNumber *newattno)
11671156
{
1168-
int i;
1169-
AttrNumber *attmap = palloc0(sizeof(AttrNumber) * old->natts);
1170-
1171-
for (i = 1; i <= old->natts; i++)
1172-
{
1173-
if (old->attrs[i - 1]->attisdropped)
1174-
{
1175-
attmap[i - 1] = 0;
1176-
continue;
1177-
}
1178-
attmap[i - 1] = findAttrByName(NameStr(old->attrs[i - 1]->attname), schema);
1179-
}
1180-
return attmap;
1157+
/* no setup needed, so away we go */
1158+
(void) change_varattnos_walker(node, newattno);
11811159
}
11821160

11831161
static bool
@@ -1206,6 +1184,59 @@ change_varattnos_walker(Node *node, const AttrNumber *newattno)
12061184
(void *) newattno);
12071185
}
12081186

1187+
/*
1188+
* Generate a map for change_varattnos_of_a_node from old and new TupleDesc's,
1189+
* matching according to column name.
1190+
*/
1191+
AttrNumber *
1192+
varattnos_map(TupleDesc old, TupleDesc new)
1193+
{
1194+
AttrNumber *attmap;
1195+
int i,
1196+
j;
1197+
1198+
attmap = (AttrNumber *) palloc0(sizeof(AttrNumber) * old->natts);
1199+
for (i = 1; i <= old->natts; i++)
1200+
{
1201+
if (old->attrs[i - 1]->attisdropped)
1202+
continue; /* leave the entry as zero */
1203+
1204+
for (j = 1; j <= new->natts; j++)
1205+
{
1206+
if (strcmp(NameStr(old->attrs[i - 1]->attname),
1207+
NameStr(new->attrs[j - 1]->attname)) == 0)
1208+
{
1209+
attmap[i - 1] = j;
1210+
break;
1211+
}
1212+
}
1213+
}
1214+
return attmap;
1215+
}
1216+
1217+
/*
1218+
* Generate a map for change_varattnos_of_a_node from a TupleDesc and a list
1219+
* of ColumnDefs
1220+
*/
1221+
AttrNumber *
1222+
varattnos_map_schema(TupleDesc old, List *schema)
1223+
{
1224+
AttrNumber *attmap;
1225+
int i;
1226+
1227+
attmap = (AttrNumber *) palloc0(sizeof(AttrNumber) * old->natts);
1228+
for (i = 1; i <= old->natts; i++)
1229+
{
1230+
if (old->attrs[i - 1]->attisdropped)
1231+
continue; /* leave the entry as zero */
1232+
1233+
attmap[i - 1] = findAttrByName(NameStr(old->attrs[i - 1]->attname),
1234+
schema);
1235+
}
1236+
return attmap;
1237+
}
1238+
1239+
12091240
/*
12101241
* StoreCatalogInheritance
12111242
* Updates the system catalogs with proper inheritance information.

src/backend/parser/analyze.c

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
77
* Portions Copyright (c) 1994, Regents of the University of California
88
*
9-
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.352 2006/10/04 00:29:55 momjian Exp $
9+
* $PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.353 2006/10/11 16:42:59 tgl Exp $
1010
*
1111
*-------------------------------------------------------------------------
1212
*/
@@ -1286,12 +1286,10 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
12861286
InhRelation *inhRelation)
12871287
{
12881288
AttrNumber parent_attno;
1289-
12901289
Relation relation;
12911290
TupleDesc tupleDesc;
12921291
TupleConstr *constr;
12931292
AclResult aclresult;
1294-
12951293
bool including_defaults = false;
12961294
bool including_constraints = false;
12971295
bool including_indexes = false;
@@ -1342,15 +1340,18 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
13421340
including_indexes = false;
13431341
break;
13441342
default:
1345-
elog(ERROR, "unrecognized CREATE TABLE LIKE option: %d", option);
1343+
elog(ERROR, "unrecognized CREATE TABLE LIKE option: %d",
1344+
option);
13461345
}
13471346
}
13481347

13491348
if (including_indexes)
1350-
elog(ERROR, "TODO");
1349+
ereport(ERROR,
1350+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1351+
errmsg("LIKE INCLUDING INDEXES is not implemented")));
13511352

13521353
/*
1353-
* Insert the inherited attributes into the cxt for the new table
1354+
* Insert the copied attributes into the cxt for the new table
13541355
* definition.
13551356
*/
13561357
for (parent_attno = 1; parent_attno <= tupleDesc->natts;
@@ -1367,7 +1368,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
13671368
continue;
13681369

13691370
/*
1370-
* Create a new inherited column.
1371+
* Create a new column, which is marked as NOT inherited.
13711372
*
13721373
* For constraints, ONLY the NOT NULL constraint is inherited by the
13731374
* new column definition per SQL99.
@@ -1389,7 +1390,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
13891390
cxt->columns = lappend(cxt->columns, def);
13901391

13911392
/*
1392-
* Copy default if any, and the default has been requested
1393+
* Copy default, if present and the default has been requested
13931394
*/
13941395
if (attribute->atthasdef && including_defaults)
13951396
{
@@ -1419,10 +1420,14 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
14191420
}
14201421
}
14211422

1423+
/*
1424+
* Copy CHECK constraints if requested, being careful to adjust
1425+
* attribute numbers
1426+
*/
14221427
if (including_constraints && tupleDesc->constr)
14231428
{
1424-
int ccnum;
14251429
AttrNumber *attmap = varattnos_map_schema(tupleDesc, cxt->columns);
1430+
int ccnum;
14261431

14271432
for (ccnum = 0; ccnum < tupleDesc->constr->num_check; ccnum++)
14281433
{
@@ -1435,8 +1440,8 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
14351440

14361441
n->contype = CONSTR_CHECK;
14371442
n->name = pstrdup(ccname);
1438-
n->raw_expr = ccbin_node;
1439-
n->cooked_expr = NULL;
1443+
n->raw_expr = NULL;
1444+
n->cooked_expr = nodeToString(ccbin_node);
14401445
n->indexspace = NULL;
14411446
cxt->ckconstraints = lappend(cxt->ckconstraints, (Node *) n);
14421447
}

src/include/nodes/parsenodes.h

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.331 2006/10/04 00:30:09 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.332 2006/10/11 16:42:59 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -414,9 +414,19 @@ typedef struct InhRelation
414414
{
415415
NodeTag type;
416416
RangeVar *relation;
417-
List *options;
417+
List *options; /* integer List of CreateStmtLikeOption */
418418
} InhRelation;
419419

420+
typedef enum CreateStmtLikeOption
421+
{
422+
CREATE_TABLE_LIKE_INCLUDING_DEFAULTS,
423+
CREATE_TABLE_LIKE_EXCLUDING_DEFAULTS,
424+
CREATE_TABLE_LIKE_INCLUDING_CONSTRAINTS,
425+
CREATE_TABLE_LIKE_EXCLUDING_CONSTRAINTS,
426+
CREATE_TABLE_LIKE_INCLUDING_INDEXES,
427+
CREATE_TABLE_LIKE_EXCLUDING_INDEXES
428+
} CreateStmtLikeOption;
429+
420430
/*
421431
* IndexElem - index parameters (used in CREATE INDEX)
422432
*
@@ -1055,16 +1065,6 @@ typedef struct CreateStmt
10551065
char *tablespacename; /* table space to use, or NULL */
10561066
} CreateStmt;
10571067

1058-
typedef enum CreateStmtLikeOption
1059-
{
1060-
CREATE_TABLE_LIKE_INCLUDING_DEFAULTS,
1061-
CREATE_TABLE_LIKE_EXCLUDING_DEFAULTS,
1062-
CREATE_TABLE_LIKE_INCLUDING_CONSTRAINTS,
1063-
CREATE_TABLE_LIKE_EXCLUDING_CONSTRAINTS,
1064-
CREATE_TABLE_LIKE_INCLUDING_INDEXES,
1065-
CREATE_TABLE_LIKE_EXCLUDING_INDEXES
1066-
} CreateStmtLikeOption;
1067-
10681068
/* ----------
10691069
* Definitions for plain (non-FOREIGN KEY) constraints in CreateStmt
10701070
*

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