OSDN Git Service

Complain if the same column name is inherited from multiple parents
authorTom Lane <tgl@sss.pgh.pa.us>
Mon, 2 Apr 2001 18:30:49 +0000 (18:30 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Mon, 2 Apr 2001 18:30:49 +0000 (18:30 +0000)
with different default values, unless the child table redeclares the
column with an explicit default.  This was judged to be the approach
least likely to cause unpleasant surprises.

src/backend/commands/creatinh.c

index 7aaaa3c..bb9af25 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.75 2001/03/30 20:50:36 tgl Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/commands/Attic/creatinh.c,v 1.76 2001/04/02 18:30:49 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -276,6 +276,20 @@ TruncateRelation(char *name)
  *
  *        If the same attribute name appears multiple times, then it appears
  *        in the result table in the proper location for its first appearance.
+ *
+ *        Constraints (including NOT NULL constraints) for the child table
+ *        are the union of all relevant constraints, from both the child schema
+ *        and parent tables.
+ *
+ *        The default value for a child column is defined as:
+ *             (1) If the child schema specifies a default, that value is used.
+ *             (2) If neither the child nor any parent specifies a default, then
+ *                     the column will not have a default.
+ *             (3) If conflicting defaults are inherited from different parents
+ *                     (and not overridden by the child), an error is raised.
+ *             (4) Otherwise the inherited default is used.
+ *             Rule (3) is new in Postgres 7.1; in earlier releases you got a
+ *             rather arbitrary choice of which parent default to use.
  *----------
  */
 static List *
@@ -286,6 +300,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
        List       *inhSchema = NIL;
        List       *parentOids = NIL;
        List       *constraints = NIL;
+       bool            have_bogus_defaults = false;
+       char       *bogus_marker = "Bogus!"; /* marks conflicting defaults */
        int                     child_attno;
 
        /*
@@ -305,10 +321,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                        ColumnDef  *restdef = lfirst(rest);
 
                        if (strcmp(coldef->colname, restdef->colname) == 0)
-                       {
                                elog(ERROR, "CREATE TABLE: attribute \"%s\" duplicated",
                                         coldef->colname);
-                       }
                }
        }
        /*
@@ -321,10 +335,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                foreach(rest, lnext(entry))
                {
                        if (strcmp(strVal(lfirst(entry)), strVal(lfirst(rest))) == 0)
-                       {
                                elog(ERROR, "CREATE TABLE: inherited relation \"%s\" duplicated",
                                         strVal(lfirst(entry)));
-                       }
                }
        }
 
@@ -436,31 +448,44 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                                newattno[parent_attno - 1] = ++child_attno;
                        }
                        /*
-                        * Copy default if any, overriding any default from earlier parent
+                        * Copy default if any
                         */
                        if (attribute->atthasdef)
                        {
+                               char       *this_default = NULL;
                                AttrDefault *attrdef;
                                int                     i;
 
-                               def->raw_default = NULL;
-                               def->cooked_default = NULL;
-
+                               /* Find default in constraint structure */
                                Assert(constr != NULL);
                                attrdef = constr->defval;
                                for (i = 0; i < constr->num_defval; i++)
                                {
                                        if (attrdef[i].adnum == parent_attno)
                                        {
-                                               /*
-                                                * if default expr could contain any vars, we'd
-                                                * need to fix 'em, but it can't ...
-                                                */
-                                               def->cooked_default = pstrdup(attrdef[i].adbin);
+                                               this_default = attrdef[i].adbin;
                                                break;
                                        }
                                }
-                               Assert(def->cooked_default != NULL);
+                               Assert(this_default != NULL);
+                               /*
+                                * If default expr could contain any vars, we'd need to fix
+                                * 'em, but it can't; so default is ready to apply to child.
+                                *
+                                * If we already had a default from some prior parent,
+                                * check to see if they are the same.  If so, no problem;
+                                * if not, mark the column as having a bogus default.
+                                * Below, we will complain if the bogus default isn't
+                                * overridden by the child schema.
+                                */
+                               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 = bogus_marker;
+                                       have_bogus_defaults = true;
+                               }
                        }
                }
                /*
@@ -555,6 +580,23 @@ MergeAttributes(List *schema, List *supers, bool istemp,
                schema = inhSchema;
        }
 
+       /*
+        * If we found any conflicting parent default values, check to make
+        * sure they were overridden by the child.
+        */
+       if (have_bogus_defaults)
+       {
+               foreach(entry, schema)
+               {
+                       ColumnDef  *def = lfirst(entry);
+
+                       if (def->cooked_default == bogus_marker)
+                               elog(ERROR, "CREATE TABLE: attribute \"%s\" inherits conflicting default values"
+                                        "\n\tTo resolve the conflict, specify a default explicitly",
+                                        def->colname);
+               }
+       }
+
        *supOids = parentOids;
        *supconstr = constraints;
        return schema;