]> granicus.if.org Git - postgresql/commitdiff
Change CREATE TABLE so that column default expressions coming from different
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 6 Oct 2009 00:55:35 +0000 (00:55 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 6 Oct 2009 00:55:35 +0000 (00:55 +0000)
inheritance parent tables are compared using equal(), instead of doing
strcmp() on the nodeToString representation.  The old implementation was
always a tad cheesy, and it finally fails completely as of 8.4, now that the
node tree might contain syntax location information.  equal() knows it's
supposed to ignore those fields, but strcmp() hardly can.  Per recent
report from Scott Ribe.

src/backend/commands/tablecmds.c
src/backend/nodes/copyfuncs.c
src/backend/nodes/equalfuncs.c
src/backend/nodes/outfuncs.c
src/backend/parser/parse_utilcmd.c
src/include/nodes/parsenodes.h
src/test/regress/expected/inherit.out
src/test/regress/sql/inherit.sql

index 6ea4457d8177918ec50e0e51675f3069805b8818..a2bd54c183a67507dac5dc70f20a678821dc6f75 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.288.2.1 2009/08/07 15:28:07 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.288.2.2 2009/10/06 00:55:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -486,7 +486,7 @@ DefineRelation(CreateStmt *stmt, char relkind)
                        cooked->contype = CONSTR_DEFAULT;
                        cooked->name = NULL;
                        cooked->attnum = attnum;
-                       cooked->expr = stringToNode(colDef->cooked_default);
+                       cooked->expr = colDef->cooked_default;
                        cooked->is_local = true;        /* not used for defaults */
                        cooked->inhcount = 0;           /* ditto */
                        cookedDefaults = lappend(cookedDefaults, cooked);
@@ -1136,8 +1136,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
        List       *constraints = NIL;
        int                     parentsWithOids = 0;
        bool            have_bogus_defaults = false;
-       char       *bogus_marker = "Bogus!";            /* marks conflicting defaults */
        int                     child_attno;
+       static Node     bogus_marker = { 0 };           /* marks conflicting defaults */
 
        /*
         * Check for and reject tables with too many columns. We perform this
@@ -1321,7 +1321,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                         */
                        if (attribute->atthasdef)
                        {
-                               char       *this_default = NULL;
+                               Node       *this_default = NULL;
                                AttrDefault *attrdef;
                                int                     i;
 
@@ -1332,7 +1332,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                                {
                                        if (attrdef[i].adnum == parent_attno)
                                        {
-                                               this_default = attrdef[i].adbin;
+                                               this_default = stringToNode(attrdef[i].adbin);
                                                break;
                                        }
                                }
@@ -1350,10 +1350,10 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                                 */
                                Assert(def->raw_default == NULL);
                                if (def->cooked_default == NULL)
-                                       def->cooked_default = pstrdup(this_default);
-                               else if (strcmp(def->cooked_default, this_default) != 0)
+                                       def->cooked_default = this_default;
+                               else if (!equal(def->cooked_default, this_default))
                                {
-                                       def->cooked_default = bogus_marker;
+                                       def->cooked_default = &bogus_marker;
                                        have_bogus_defaults = true;
                                }
                        }
@@ -1492,7 +1492,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                {
                        ColumnDef  *def = lfirst(entry);
 
-                       if (def->cooked_default == bogus_marker)
+                       if (def->cooked_default == &bogus_marker)
                                ereport(ERROR,
                                                (errcode(ERRCODE_INVALID_COLUMN_DEFINITION),
                                  errmsg("column \"%s\" inherits conflicting default values",
index 72c9877ffd5c8c8b906d9f526746d83e8fc2656b..fbf254ad8a1f9e720276d36c70dd59579fb79724 100644 (file)
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.432 2009/06/18 01:27:02 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.432.2.1 2009/10/06 00:55:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2073,7 +2073,7 @@ _copyColumnDef(ColumnDef *from)
        COPY_SCALAR_FIELD(is_local);
        COPY_SCALAR_FIELD(is_not_null);
        COPY_NODE_FIELD(raw_default);
-       COPY_STRING_FIELD(cooked_default);
+       COPY_NODE_FIELD(cooked_default);
        COPY_NODE_FIELD(constraints);
 
        return newnode;
index 041b96971c63657cdb78caaaa0431212944ebad4..39a2de5030721672ded434446beb511c047551f1 100644 (file)
@@ -22,7 +22,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.355 2009/06/18 01:27:02 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.355.2.1 2009/10/06 00:55:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2052,7 +2052,7 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b)
        COMPARE_SCALAR_FIELD(is_local);
        COMPARE_SCALAR_FIELD(is_not_null);
        COMPARE_NODE_FIELD(raw_default);
-       COMPARE_STRING_FIELD(cooked_default);
+       COMPARE_NODE_FIELD(cooked_default);
        COMPARE_NODE_FIELD(constraints);
 
        return true;
index d79bd750d04cf4a472278b124384acddde9576d6..93aec9928ce89f3b6715df4a4a1f1dea1f7d2d95 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.360 2009/06/11 14:48:58 momjian Exp $
+ *       $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.360.2.1 2009/10/06 00:55:34 tgl Exp $
  *
  * NOTES
  *       Every node type that can appear in stored rules' parsetrees *must*
@@ -1837,7 +1837,7 @@ _outColumnDef(StringInfo str, ColumnDef *node)
        WRITE_BOOL_FIELD(is_local);
        WRITE_BOOL_FIELD(is_not_null);
        WRITE_NODE_FIELD(raw_default);
-       WRITE_STRING_FIELD(cooked_default);
+       WRITE_NODE_FIELD(cooked_default);
        WRITE_NODE_FIELD(constraints);
 }
 
index e5a3621cce6ca518138789501efe1d7d9eec36de..4a9406ffbddcb197f844b5f5c29d283e2531a654 100644 (file)
@@ -19,7 +19,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *     $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.21 2009/06/11 14:49:00 momjian Exp $
+ *     $PostgreSQL: pgsql/src/backend/parser/parse_utilcmd.c,v 2.21.2.1 2009/10/06 00:55:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -642,7 +642,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
                 */
                if (attribute->atthasdef && including_defaults)
                {
-                       char       *this_default = NULL;
+                       Node       *this_default = NULL;
                        AttrDefault *attrdef;
                        int                     i;
 
@@ -653,7 +653,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
                        {
                                if (attrdef[i].adnum == parent_attno)
                                {
-                                       this_default = attrdef[i].adbin;
+                                       this_default = stringToNode(attrdef[i].adbin);
                                        break;
                                }
                        }
@@ -664,7 +664,7 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
                         * but it can't; so default is ready to apply to child.
                         */
 
-                       def->cooked_default = pstrdup(this_default);
+                       def->cooked_default = this_default;
                }
        }
 
index 7793f66f20fd5597e5628b4b9c9d9b7b7bb14923..f27d9a26bda9ea5e6e3c9a228dc82325151a463f 100644 (file)
@@ -13,7 +13,7 @@
  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.395 2009/06/18 01:27:02 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.395.2.1 2009/10/06 00:55:35 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -443,10 +443,9 @@ typedef struct RangeFunction
  *
  * If the column has a default value, we may have the value expression
  * in either "raw" form (an untransformed parse tree) or "cooked" form
- * (the nodeToString representation of an executable expression tree),
- * depending on how this ColumnDef node was created (by parsing, or by
- * inheritance from an existing relation).     We should never have both
- * in the same node!
+ * (a post-parse-analysis, executable expression tree), depending on
+ * how this ColumnDef node was created (by parsing, or by inheritance
+ * from an existing relation).  We should never have both in the same node!
  *
  * The constraints list may contain a CONSTR_DEFAULT item in a raw
  * parsetree produced by gram.y, but transformCreateStmt will remove
@@ -462,7 +461,7 @@ typedef struct ColumnDef
        bool            is_local;               /* column has local (non-inherited) def'n */
        bool            is_not_null;    /* NOT NULL constraint specified? */
        Node       *raw_default;        /* default value (untransformed parse tree) */
-       char       *cooked_default; /* nodeToString representation */
+       Node       *cooked_default; /* default value (transformed expr tree) */
        List       *constraints;        /* other constraints on column */
 } ColumnDef;
 
index 100edb35396dc63c7e62e20565b910eb68c24f30..04eb41afb63bd53a3088b429575cdd7eb9087f61 100644 (file)
@@ -571,6 +571,21 @@ order by 1,2;
  bar2    |  4 |   4
 (8 rows)
 
+/* Test multiple inheritance of column defaults */
+CREATE TABLE firstparent (tomorrow date default now()::date + 1);
+CREATE TABLE secondparent (tomorrow date default  now() :: date  +  1);
+CREATE TABLE jointchild () INHERITS (firstparent, secondparent);  -- ok
+NOTICE:  merging multiple inherited definitions of column "tomorrow"
+CREATE TABLE thirdparent (tomorrow date default now()::date - 1);
+CREATE TABLE otherchild () INHERITS (firstparent, thirdparent);  -- not ok
+NOTICE:  merging multiple inherited definitions of column "tomorrow"
+ERROR:  column "tomorrow" inherits conflicting default values
+HINT:  To resolve the conflict, specify a default explicitly.
+CREATE TABLE otherchild (tomorrow date default now())
+  INHERITS (firstparent, thirdparent);  -- ok, child resolves ambiguous default
+NOTICE:  merging multiple inherited definitions of column "tomorrow"
+NOTICE:  merging column "tomorrow" with inherited definition
+DROP TABLE firstparent, secondparent, jointchild, thirdparent, otherchild;
 /* Test inheritance of structure (LIKE) */
 CREATE TABLE inhx (xx text DEFAULT 'text');
 /*
index 1730a485756a83c63cd5355b395695964b736182..e68c658ec7730856192b647b56463fd94e9b9874 100644 (file)
@@ -121,6 +121,17 @@ update bar set f2 = f2 + 100 where f1 in (select f1 from foo);
 SELECT relname, bar.* FROM bar, pg_class where bar.tableoid = pg_class.oid
 order by 1,2;
 
+/* Test multiple inheritance of column defaults */
+
+CREATE TABLE firstparent (tomorrow date default now()::date + 1);
+CREATE TABLE secondparent (tomorrow date default  now() :: date  +  1);
+CREATE TABLE jointchild () INHERITS (firstparent, secondparent);  -- ok
+CREATE TABLE thirdparent (tomorrow date default now()::date - 1);
+CREATE TABLE otherchild () INHERITS (firstparent, thirdparent);  -- not ok
+CREATE TABLE otherchild (tomorrow date default now())
+  INHERITS (firstparent, thirdparent);  -- ok, child resolves ambiguous default
+
+DROP TABLE firstparent, secondparent, jointchild, thirdparent, otherchild;
 
 /* Test inheritance of structure (LIKE) */
 CREATE TABLE inhx (xx text DEFAULT 'text');