OSDN Git Service

Repair mishandling of PRIMARY KEY declaration that references an
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Dec 2000 01:37:56 +0000 (01:37 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 18 Dec 2000 01:37:56 +0000 (01:37 +0000)
inherited column, per bug report from Elphick 12/15/00.

src/backend/parser/analyze.c

index 4be93ff..1c7c5da 100644 (file)
@@ -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 (; count<rel->rd_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 */