]> granicus.if.org Git - postgresql/commitdiff
First workaround solution for Jan's column constraint attributes.
authorThomas G. Lockhart <lockhart@fourpalms.org>
Sat, 19 Feb 2000 08:25:49 +0000 (08:25 +0000)
committerThomas G. Lockhart <lockhart@fourpalms.org>
Sat, 19 Feb 2000 08:25:49 +0000 (08:25 +0000)
src/backend/parser/gram.y

index b6962f8fad6f4be3f6ee42519f55a9304f167aae..6e69020018687cffdf8442c6c675f40806a67587 100644 (file)
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.144 2000/02/18 09:29:40 inoue Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.145 2000/02/19 08:25:49 thomas Exp $
  *
  * HISTORY
  *       AUTHOR                        DATE                    MAJOR EVENT
@@ -263,14 +263,15 @@ static Node *doNegate(Node *n);
 %type <str>            TypeId
 
 %type <node>   TableConstraint
-%type <list>   ColPrimaryKey, ColQualList, ColQualifier
+%type <list>   ColQualList, ColQualifier
 %type <list>   ColQualListWithNull
-%type <node>   ColConstraint, ColConstraintElem
+%type <node>   ColConstraint, ColConstraintElem, PrimaryKey, NotNull
+%type <node>   DefaultClause, DefaultExpr
 %type <node>   ColConstraintWithNull, ColConstraintElemWithNull
-%type <ival>   key_actions, key_action, key_reference
+%type <ival>   key_actions, key_delete, key_update, key_reference
 %type <str>            key_match
-%type <ival>   ConstraintAttributeSpec, ConstraintDeferrabilitySpec,
-                               ConstraintTimeSpec
+%type <ival>   ConstraintAttribute, DeferrabilityClause,
+                               TimeClause
 
 %type <list>   constraints_set_list
 %type <list>   constraints_set_namelist
@@ -1028,40 +1029,132 @@ OptTableElement:  columnDef                                            { $$ = $1; }
                        | TableConstraint                                       { $$ = $1; }
                ;
 
-columnDef:  ColId Typename ColQualifier
+columnDef:  ColId Typename ColQualifier opt_collate
                                {
                                        ColumnDef *n = makeNode(ColumnDef);
                                        n->colname = $1;
                                        n->typename = $2;
+#if 0
                                        n->raw_default = NULL;
                                        n->cooked_default = NULL;
                                        n->is_not_null = FALSE;
+#endif
                                        n->constraints = $3;
+
+                                       if ($4 != NULL)
+                                               elog(NOTICE,"CREATE TABLE/COLLATE %s not yet implemented"
+                                                        "; clause ignored", $4);
+
                                        $$ = (Node *)n;
                                }
-                       | ColId SERIAL ColPrimaryKey
+                       | ColId SERIAL PrimaryKey
                                {
                                        ColumnDef *n = makeNode(ColumnDef);
                                        n->colname = $1;
                                        n->typename = makeNode(TypeName);
                                        n->typename->name = xlateSqlType("integer");
                                        n->typename->typmod = -1;
+#if 0
                                        n->raw_default = NULL;
                                        n->cooked_default = NULL;
+#endif
                                        n->is_not_null = TRUE;
                                        n->is_sequence = TRUE;
-                                       n->constraints = $3;
+                                       n->constraints = lcons($3, NIL);
 
                                        $$ = (Node *)n;
                                }
                ;
 
-ColQualifier:  ColQualList                                     { $$ = $1; }
-                       | NULL_P ColQualListWithNull    { $$ = $2; }
-                       | NULL_P                                                { $$ = NULL; }
+/*
+ * ColQualifier encapsulates an entire column qualification,
+ * including DEFAULT, constraints, and constraint attributes.
+ * Note that the DefaultClause handles the empty case.
+ */
+ColQualifier:  DefaultClause ColQualList
+                               {
+                                       if ($1 != NULL)
+                                               $$ = lcons($1, $2);
+                                       else
+                                               $$ = $2;
+                               }
+                       | NotNull DefaultClause ColQualListWithNull
+                               {
+                                       $$ = lcons($1, $3);
+                                       if ($2 != NULL)
+                                               $$ = lcons($2, $$);
+                               }
+                       | DefaultExpr NotNull ColQualListWithNull
+                               {
+                                       $$ = lcons($2, $3);
+                                       if ($1 != NULL)
+                                               $$ = lcons($1, $$);
+                               }
+                       | DefaultExpr NotNull
+                               {
+                                       $$ = lcons($2, NIL);
+                                       if ($1 != NULL)
+                                               $$ = lcons($1, $$);
+                               }
+                       | NotNull DefaultClause
+                               {
+                                       $$ = lcons($1, NIL);
+                                       if ($2 != NULL)
+                                               $$ = lcons($2, $$);
+                               }
+                       | NULL_P DefaultClause ColQualListWithNull
+                               {
+                                       $$ = $3;
+                                       if ($2 != NULL)
+                                               $$ = lcons($2, $$);
+                               }
+                       | NULL_P DefaultClause
+                               {
+                                       if ($2 != NULL)
+                                               $$ = lcons($2, NIL);
+                                       else
+                                               $$ = NIL;
+                               }
+                       | DefaultClause
+                               {
+                                       if ($1 != NULL)
+                                               $$ = lcons($1, NIL);
+                                       else
+                                               $$ = NIL;
+                               }
+               ;
+
+/*
+ * DEFAULT expression must be b_expr not a_expr to prevent shift/reduce
+ * conflict on NOT (since NOT might start a subsequent NOT NULL constraint,
+ * or be part of a_expr NOT LIKE or similar constructs).
+ */
+DefaultClause:  DefaultExpr                                    { $$ = $1; }
                        | /*EMPTY*/                                             { $$ = NULL; }
                ;
 
+DefaultExpr:  DEFAULT NULL_P
+                               {
+                                       Constraint *n = makeNode(Constraint);
+                                       n->contype = CONSTR_DEFAULT;
+                                       n->name = NULL;
+                                       n->raw_expr = NULL;
+                                       n->cooked_expr = NULL;
+                                       n->keys = NULL;
+                                       $$ = (Node *)n;
+                               }
+                       | DEFAULT b_expr
+                               {
+                                       Constraint *n = makeNode(Constraint);
+                                       n->contype = CONSTR_DEFAULT;
+                                       n->name = NULL;
+                                       n->raw_expr = $2;
+                                       n->cooked_expr = NULL;
+                                       n->keys = NULL;
+                                       $$ = (Node *)n;
+                               }
+               ;
+
 ColQualList:  ColQualList ColConstraint
                                {
                                        if ($2 != NULL)
@@ -1078,12 +1171,12 @@ ColQualList:  ColQualList ColConstraint
                                }
                ;
 
-ColQualListWithNull:  ColQualListWithNull ColConstraintWithNull
+ColQualListWithNull:  ColConstraintWithNull ColQualListWithNull
                                {
-                                       if ($2 != NULL)
-                                               $$ = lappend($1, $2);
+                                       if ($1 != NULL)
+                                               $$ = lcons($1, $2);
                                        else
-                                               $$ = $1;
+                                               $$ = $2;
                                }
                        | ColConstraintWithNull
                                {
@@ -1094,21 +1187,7 @@ ColQualListWithNull:  ColQualListWithNull ColConstraintWithNull
                                }
                ;
 
-ColPrimaryKey:  PRIMARY KEY
-                               {
-                                       Constraint *n = makeNode(Constraint);
-                                       n->contype = CONSTR_PRIMARY;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
-                                       n->keys = NULL;
-                                       $$ = lcons((Node *)n, NIL);
-                               }
-                       | /*EMPTY*/                                                     { $$ = NULL; }
-               ;
-
-ColConstraint:
-               CONSTRAINT name ColConstraintElem
+ColConstraint: CONSTRAINT name ColConstraintElem
                                {
                                        switch (nodeTag($3))
                                        {
@@ -1133,8 +1212,7 @@ ColConstraint:
                                { $$ = $1; }
                ;
 
-ColConstraintWithNull:
-               CONSTRAINT name ColConstraintElemWithNull
+ColConstraintWithNull:  CONSTRAINT name ColConstraintElemWithNull
                                {
                                        switch (nodeTag($3))
                                        {
@@ -1169,25 +1247,11 @@ ColConstraintWithNull:
  * that a column may have that value. WITH NULL leads to
  * shift/reduce conflicts with WITH TIME ZONE anyway.
  * - thomas 1999-01-08
- *
- * DEFAULT expression must be b_expr not a_expr to prevent shift/reduce
- * conflict on NOT (since NOT might start a subsequent NOT NULL constraint,
- * or be part of a_expr NOT LIKE or similar constructs).
  */
 ColConstraintElem:  ColConstraintElemWithNull
                                {
                                        $$ = $1;
                                }
-                       | NOT NULL_P
-                               {
-                                       Constraint *n = makeNode(Constraint);
-                                       n->contype = CONSTR_NOTNULL;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
-                                       n->keys = NULL;
-                                       $$ = (Node *)n;
-                               }
                        | UNIQUE
                                {
                                        Constraint *n = makeNode(Constraint);
@@ -1198,15 +1262,9 @@ ColConstraintElem:  ColConstraintElemWithNull
                                        n->keys = NULL;
                                        $$ = (Node *)n;
                                }
-                       | PRIMARY KEY
+                       | PrimaryKey
                                {
-                                       Constraint *n = makeNode(Constraint);
-                                       n->contype = CONSTR_PRIMARY;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
-                                       n->keys = NULL;
-                                       $$ = (Node *)n;
+                                       $$ = $1;
                                }
                ;
 
@@ -1220,31 +1278,23 @@ ColConstraintElemWithNull:  CHECK '(' a_expr ')'
                                        n->keys = NULL;
                                        $$ = (Node *)n;
                                }
-                       | DEFAULT NULL_P
+                       | REFERENCES ColId opt_column_list
+                               key_match key_actions ConstraintAttribute
                                {
-                                       Constraint *n = makeNode(Constraint);
-                                       n->contype = CONSTR_DEFAULT;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
-                                       n->keys = NULL;
-                                       $$ = (Node *)n;
-                               }
-                       | DEFAULT b_expr
-                               {
-                                       Constraint *n = makeNode(Constraint);
-                                       n->contype = CONSTR_DEFAULT;
-                                       n->name = NULL;
-                                       n->raw_expr = $2;
-                                       n->cooked_expr = NULL;
-                                       n->keys = NULL;
+                                       FkConstraint *n = makeNode(FkConstraint);
+                                       n->constr_name          = NULL;
+                                       n->pktable_name         = $2;
+                                       n->fk_attrs                     = NIL;
+                                       n->pk_attrs                     = $3;
+                                       n->match_type           = $4;
+                                       n->actions                      = $5;
+                                       n->deferrable           = (($6 & 1) != 0);
+                                       n->initdeferred         = (($6 & 2) != 0);
                                        $$ = (Node *)n;
                                }
-                       | REFERENCES ColId opt_column_list key_match key_actions 
+                       | REFERENCES ColId opt_column_list
+                               key_match key_actions
                                {
-                                       /* XXX
-                                        *      Need ConstraintAttributeSpec as $6 -- Jan
-                                        */
                                        FkConstraint *n = makeNode(FkConstraint);
                                        n->constr_name          = NULL;
                                        n->pktable_name         = $2;
@@ -1254,14 +1304,33 @@ ColConstraintElemWithNull:  CHECK '(' a_expr ')'
                                        n->actions                      = $5;
                                        n->deferrable           = true;
                                        n->initdeferred         = false;
-                                       /*
-                                       n->deferrable           = ($6 & 1) != 0;
-                                       n->initdeferred         = ($6 & 2) != 0;
-                                       */
                                        $$ = (Node *)n;
                                }
                ;
 
+PrimaryKey:  PRIMARY KEY
+                               {
+                                       Constraint *n = makeNode(Constraint);
+                                       n->contype = CONSTR_PRIMARY;
+                                       n->name = NULL;
+                                       n->raw_expr = NULL;
+                                       n->cooked_expr = NULL;
+                                       n->keys = NULL;
+                                       $$ = (Node *)n;
+                               }
+               ;
+
+NotNull:  NOT NULL_P
+                               {
+                                       Constraint *n = makeNode(Constraint);
+                                       n->contype = CONSTR_NOTNULL;
+                                       n->name = NULL;
+                                       n->raw_expr = NULL;
+                                       n->cooked_expr = NULL;
+                                       n->keys = NULL;
+                                       $$ = (Node *)n;
+                               }
+
 /* ConstraintElem specifies constraint syntax which is not embedded into
  *  a column definition. ColConstraintElem specifies the embedded form.
  * - thomas 1997-12-03
@@ -1310,17 +1379,14 @@ ConstraintElem:  CHECK '(' a_expr ')'
                                        n->keys = $3;
                                        $$ = (Node *)n;
                                }
-               | PRIMARY KEY '(' columnList ')'
+               | PrimaryKey '(' columnList ')'
                                {
-                                       Constraint *n = makeNode(Constraint);
-                                       n->contype = CONSTR_PRIMARY;
-                                       n->name = NULL;
-                                       n->raw_expr = NULL;
-                                       n->cooked_expr = NULL;
-                                       n->keys = $4;
+                                       Constraint *n = (Constraint *)$1;
+                                       n->keys = $3;
                                        $$ = (Node *)n;
                                }
-               | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions ConstraintAttributeSpec
+               | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list
+                               key_match key_actions ConstraintAttribute
                                {
                                        FkConstraint *n = makeNode(FkConstraint);
                                        n->constr_name          = NULL;
@@ -1333,6 +1399,20 @@ ConstraintElem:  CHECK '(' a_expr ')'
                                        n->initdeferred         = ($11 & 2) != 0;
                                        $$ = (Node *)n;
                                }
+               | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list
+                               key_match key_actions
+                               {
+                                       FkConstraint *n = makeNode(FkConstraint);
+                                       n->constr_name          = NULL;
+                                       n->pktable_name         = $7;
+                                       n->fk_attrs                     = $4;
+                                       n->pk_attrs                     = $8;
+                                       n->match_type           = $9;
+                                       n->actions                      = $10;
+                                       n->deferrable           = false;
+                                       n->initdeferred         = false;
+                                       $$ = (Node *)n;
+                               }
                ;
 
 key_match:  MATCH FULL
@@ -1341,7 +1421,7 @@ key_match:  MATCH FULL
                        }
                | MATCH PARTIAL
                        {
-                               elog(ERROR, "FOREIGN KEY match type PARTIAL not implemented yet");
+                               elog(ERROR, "FOREIGN KEY/MATCH PARTIAL not yet implemented");
                                $$ = "PARTIAL";
                        }
                | /*EMPTY*/
@@ -1350,13 +1430,17 @@ key_match:  MATCH FULL
                        }
                ;
 
-key_actions:  key_action key_action            { $$ = $1 | $2; }
-               | key_action                                    { $$ = $1; }
+key_actions:  key_delete                               { $$ = $1; }
+               | key_update                                    { $$ = $1; }
+               | key_delete key_update                 { $$ = $1 | $2; }
+               | key_update key_delete                 { $$ = $1 | $2; }
                | /*EMPTY*/                                             { $$ = 0; }
                ;
 
-key_action:  ON DELETE key_reference   { $$ = $3 << FKCONSTR_ON_DELETE_SHIFT; }
-               | ON UPDATE key_reference               { $$ = $3 << FKCONSTR_ON_UPDATE_SHIFT; }
+key_delete:  ON DELETE key_reference   { $$ = $3 << FKCONSTR_ON_DELETE_SHIFT; }
+               ;
+
+key_update:  ON UPDATE key_reference   { $$ = $3 << FKCONSTR_ON_UPDATE_SHIFT; }
                ;
 
 key_reference:  NO ACTION                              { $$ = FKCONSTR_ON_KEY_NOACTION; }
@@ -1558,7 +1642,7 @@ CreateTrigStmt:  CREATE TRIGGER name TriggerActionTime TriggerEvents ON
                                }
                | CREATE CONSTRAINT TRIGGER name AFTER TriggerEvents ON
                                relation_name OptConstrFromTable 
-                               ConstraintAttributeSpec
+                               ConstraintAttribute
                                FOR EACH ROW EXECUTE PROCEDURE name '(' TriggerFuncArgs ')'
                                {
                                        CreateTrigStmt *n = makeNode(CreateTrigStmt);
@@ -1658,41 +1742,37 @@ OptConstrFromTable:                     /* Empty */
                                }
                ;
 
-ConstraintAttributeSpec:  ConstraintDeferrabilitySpec
-                       { $$ = $1; }
-               | ConstraintDeferrabilitySpec ConstraintTimeSpec
+ConstraintAttribute:  DeferrabilityClause
                        {
-                               if ($1 == 0 && $2 != 0)
-                                       elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
-                               $$ = $1 | $2;
+                               $$ = $1;
                        }
-               | ConstraintTimeSpec
+               | TimeClause
                        {
                                if ($1 != 0)
                                        $$ = 3;
                                else
                                        $$ = 0;
                        }
-               | ConstraintTimeSpec ConstraintDeferrabilitySpec
+               | DeferrabilityClause TimeClause
+                       {
+                               if ($1 == 0 && $2 != 0)
+                                       elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
+                               $$ = $1 | $2;
+                       }
+               | TimeClause DeferrabilityClause
                        {
                                if ($2 == 0 && $1 != 0)
                                        elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
                                $$ = $1 | $2;
                        }
-               | /* Empty */
-                       { $$ = 0; }
                ;
 
-ConstraintDeferrabilitySpec: NOT DEFERRABLE
-                       { $$ = 0; }
-               | DEFERRABLE
-                       { $$ = 1; }
+DeferrabilityClause:  DEFERRABLE                               { $$ = 1; }
+               | NOT DEFERRABLE                                                { $$ = 0; }
                ;
 
-ConstraintTimeSpec: INITIALLY IMMEDIATE
-                       { $$ = 0; }
-               | INITIALLY DEFERRED
-                       { $$ = 2; }
+TimeClause:  INITIALLY IMMEDIATE                               { $$ = 0; }
+               | INITIALLY DEFERRED                                    { $$ = 2; }
                ;
 
 
@@ -2734,18 +2814,7 @@ CreatedbStmt:  CREATE DATABASE database_name WITH createdb_opt_location createdb
                     n = makeNode(CreatedbStmt);
                                        n->dbname = $3;
                                        n->dbpath = $5;
-#ifdef MULTIBYTE
-                                       if ($6 != NULL) {
-                                               n->encoding = pg_char_to_encoding($6);
-                                               if (n->encoding < 0) {
-                                                       elog(ERROR, "Encoding name '%s' is invalid", $6);
-                                               }
-                                       } else {
-                                               n->encoding = GetTemplateEncoding();
-                                       }
-#else
-                                       n->encoding = 0;
-#endif
+                                       n->encoding = $6;
                                        $$ = (Node *)n;
                                }
                | CREATE DATABASE database_name
@@ -2795,7 +2864,7 @@ createdb_opt_encoding:
 #ifdef MULTIBYTE
             $$ = GetTemplateEncoding();
 #else
-            $$ = -1;
+            $$ = 0;
 #endif
         }
         | /*EMPTY*/
@@ -2803,7 +2872,7 @@ createdb_opt_encoding:
 #ifdef MULTIBYTE
             $$ = GetTemplateEncoding();
 #else
-            $$= -1;
+            $$= 0;
 #endif
         }
         ;
@@ -3935,7 +4004,7 @@ Character:  character '(' Iconst ')'
                                }
                ;
 
-character:  CHARACTER opt_varying opt_charset opt_collate
+character:  CHARACTER opt_varying opt_charset
                                {
                                        char *type, *c;
                                        if (($3 == NULL) || (strcasecmp($3, "sql_text") == 0)) {
@@ -3951,8 +4020,6 @@ character:  CHARACTER opt_varying opt_charset opt_collate
                                                        type = xlateSqlType($3);
                                                }
                                        };
-                                       if ($4 != NULL)
-                                               elog(NOTICE,"COLLATE %s not yet implemented; clause ignored",$4);
                                        $$ = type;
                                }
                | CHAR opt_varying                                              { $$ = xlateSqlType($2? "varchar": "char"); }