From 42d5e34e779c540787712e6475c25a1cb4e03e61 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Mon, 18 Dec 2000 01:37:56 +0000 Subject: [PATCH] Repair mishandling of PRIMARY KEY declaration that references an inherited column, per bug report from Elphick 12/15/00. --- src/backend/parser/analyze.c | 79 ++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 25 deletions(-) diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c index 4be93ff582..1c7c5dab56 100644 --- a/src/backend/parser/analyze.c +++ b/src/backend/parser/analyze.c @@ -6,7 +6,7 @@ * Portions Copyright (c) 1996-2000, PostgreSQL, Inc * Portions Copyright (c) 1994, Regents of the University of California * - * $Id: analyze.c,v 1.172 2000/12/07 01:12:08 tgl Exp $ + * $Id: analyze.c,v 1.173 2000/12/18 01:37:56 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -945,9 +945,10 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) index->withClause = NIL; index->whereClause = NULL; - foreach(keys, constraint->keys) + foreach (keys, constraint->keys) { - int found=0; + bool found = false; + key = (Ident *) lfirst(keys); Assert(IsA(key, Ident)); column = NULL; @@ -956,26 +957,58 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) column = lfirst(columns); Assert(IsA(column, ColumnDef)); if (strcmp(column->colname, key->name) == 0) + { + found = true; break; + } + } + if (found) + { + /* found column in the new table; force it to be NOT NULL */ + if (constraint->contype == CONSTR_PRIMARY) + column->is_not_null = TRUE; } - if (columns == NIL) { /* try inherited tables */ + else + { + /* try inherited tables */ + List *inhRelnames = stmt->inhRelnames; List *inher; - List *inhRelnames=stmt->inhRelnames; - Relation rel; - foreach (inher, inhRelnames) { - int count=0; - Value *inh=lfirst(inher); - if (inh->type!=T_String) { - elog(ERROR, "inherited table name list returns a non-string"); - } - rel=heap_openr(inh->val.str, AccessShareLock); + + foreach (inher, inhRelnames) + { + Value *inh = lfirst(inher); + Relation rel; + int count; + + Assert(IsA(inh, String)); + rel = heap_openr(inh->val.str, AccessShareLock); if (rel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "inherited table \"%s\" is not a relation", - inh->val.str); - for (; countrd_att->natts; count++) { - char *name=NameStr(rel->rd_att->attrs[count]->attname); - if (strcmp(key->name, name) == 0) { - found=1; + inh->val.str); + for (count = 0; count < rel->rd_att->natts; count++) + { + Form_pg_attribute inhattr = rel->rd_att->attrs[count]; + char *inhname = NameStr(inhattr->attname); + + if (strcmp(key->name, inhname) == 0) + { + found = true; + /* + * If the column is inherited, we currently have + * no easy way to force it to be NOT NULL. + * Only way I can see to fix this would be to + * convert the inherited-column info to ColumnDef + * nodes before we reach this point, and then + * create the table from those nodes rather than + * referencing the parent tables later. That + * would likely be cleaner, but too much work + * to contemplate right now. Instead, raise an + * error if the inherited column won't be NOT NULL. + * (Would a NOTICE be more reasonable?) + */ + if (! inhattr->attnotnull) + elog(ERROR, "inherited attribute \"%s\" cannot be a PRIMARY KEY because it is not marked NOT NULL", + inhname); break; } } @@ -984,16 +1017,11 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) break; } } - else { - found=1; - } if (!found) - elog(ERROR, "CREATE TABLE: column '%s' named in key does not exist", + elog(ERROR, "CREATE TABLE: column \"%s\" named in key does not exist", key->name); - if (constraint->contype == CONSTR_PRIMARY) - column->is_not_null = TRUE; iparam = makeNode(IndexElem); iparam->name = pstrdup(key->name); iparam->args = NIL; @@ -1001,7 +1029,8 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt) index->indexParams = lappend(index->indexParams, iparam); if (index->idxname == NULL) - index->idxname = CreateIndexName(stmt->relname, iparam->name, "key", ilist); + index->idxname = CreateIndexName(stmt->relname, iparam->name, + "key", ilist); } if (index->idxname == NULL) /* should not happen */ -- 2.11.0