From: Thomas G. Lockhart Date: Sat, 19 Feb 2000 08:25:49 +0000 (+0000) Subject: First workaround solution for Jan's column constraint attributes. X-Git-Tag: REL7_0~605 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=dfdff4e0f125d309ba35e3600cb0c78df4eea546;p=postgresql First workaround solution for Jan's column constraint attributes. --- diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y index b6962f8fad..6e69020018 100644 --- a/src/backend/parser/gram.y +++ b/src/backend/parser/gram.y @@ -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 TypeId %type TableConstraint -%type ColPrimaryKey, ColQualList, ColQualifier +%type ColQualList, ColQualifier %type ColQualListWithNull -%type ColConstraint, ColConstraintElem +%type ColConstraint, ColConstraintElem, PrimaryKey, NotNull +%type DefaultClause, DefaultExpr %type ColConstraintWithNull, ColConstraintElemWithNull -%type key_actions, key_action, key_reference +%type key_actions, key_delete, key_update, key_reference %type key_match -%type ConstraintAttributeSpec, ConstraintDeferrabilitySpec, - ConstraintTimeSpec +%type ConstraintAttribute, DeferrabilityClause, + TimeClause %type constraints_set_list %type 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"); }