Commit b8ef7e7f authored by Jan Wieck's avatar Jan Wieck

Completed FOREIGN KEY syntax.

Added functionality for automatic trigger creation during CREATE TABLE.

Added ON DELETE RESTRICT and some others.

Jan
parent 1d8ce772
...@@ -394,6 +394,8 @@ RelationRemoveTriggers(Relation rel) ...@@ -394,6 +394,8 @@ RelationRemoveTriggers(Relation rel)
stmt.relname = pstrdup(RelationGetRelationName(refrel)); stmt.relname = pstrdup(RelationGetRelationName(refrel));
stmt.trigname = nameout(&pg_trigger->tgname); stmt.trigname = nameout(&pg_trigger->tgname);
elog(NOTICE, "DROP TABLE implicitly drops referential integrity trigger from table \"%s\"", stmt.relname);
DropTrigger(&stmt); DropTrigger(&stmt);
pfree(stmt.relname); pfree(stmt.relname);
......
This diff is collapsed.
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.116 1999/11/30 03:57:24 momjian Exp $ * $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.117 1999/12/06 18:02:43 wieck Exp $
* *
* HISTORY * HISTORY
* AUTHOR DATE MAJOR EVENT * AUTHOR DATE MAJOR EVENT
...@@ -143,7 +143,6 @@ static Node *doNegate(Node *n); ...@@ -143,7 +143,6 @@ static Node *doNegate(Node *n);
%type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted %type <boolean> TriggerActionTime, TriggerForSpec, PLangTrusted
%type <ival> OptConstrTrigDeferrable, OptConstrTrigInitdeferred
%type <str> OptConstrFromTable %type <str> OptConstrFromTable
%type <str> TriggerEvents, TriggerFuncArg %type <str> TriggerEvents, TriggerFuncArg
...@@ -249,8 +248,10 @@ static Node *doNegate(Node *n); ...@@ -249,8 +248,10 @@ static Node *doNegate(Node *n);
%type <node> TableConstraint %type <node> TableConstraint
%type <list> ColPrimaryKey, ColQualList, ColQualifier %type <list> ColPrimaryKey, ColQualList, ColQualifier
%type <node> ColConstraint, ColConstraintElem %type <node> ColConstraint, ColConstraintElem
%type <list> key_actions, key_action %type <ival> key_actions, key_action, key_reference
%type <str> key_match, key_reference %type <str> key_match
%type <ival> ConstraintAttributeSpec, ConstraintDeferrabilitySpec,
ConstraintTimeSpec
%type <list> constraints_set_list %type <list> constraints_set_list
%type <list> constraints_set_namelist %type <list> constraints_set_namelist
...@@ -975,9 +976,24 @@ ColPrimaryKey: PRIMARY KEY ...@@ -975,9 +976,24 @@ ColPrimaryKey: PRIMARY KEY
ColConstraint: ColConstraint:
CONSTRAINT name ColConstraintElem CONSTRAINT name ColConstraintElem
{
switch (nodeTag($3))
{
case T_Constraint:
{ {
Constraint *n = (Constraint *)$3; Constraint *n = (Constraint *)$3;
if (n != NULL) n->name = $2; if (n != NULL) n->name = $2;
}
break;
case T_FkConstraint:
{
FkConstraint *n = (FkConstraint *)$3;
if (n != NULL) n->constr_name = $2;
}
break;
default:
break;
}
$$ = $3; $$ = $3;
} }
| ColConstraintElem | ColConstraintElem
...@@ -1062,8 +1078,23 @@ ColConstraintElem: CHECK '(' a_expr ')' ...@@ -1062,8 +1078,23 @@ ColConstraintElem: CHECK '(' a_expr ')'
} }
| REFERENCES ColId opt_column_list key_match key_actions | REFERENCES ColId opt_column_list key_match key_actions
{ {
elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented"); /* XXX
$$ = NULL; * Need ConstraintAttributeSpec as $6 -- Jan
*/
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 = true;
n->initdeferred = false;
/*
n->deferrable = ($6 & 1) != 0;
n->initdeferred = ($6 & 2) != 0;
*/
$$ = (Node *)n;
} }
; ;
...@@ -1072,9 +1103,24 @@ ColConstraintElem: CHECK '(' a_expr ')' ...@@ -1072,9 +1103,24 @@ ColConstraintElem: CHECK '(' a_expr ')'
* - thomas 1997-12-03 * - thomas 1997-12-03
*/ */
TableConstraint: CONSTRAINT name ConstraintElem TableConstraint: CONSTRAINT name ConstraintElem
{
switch (nodeTag($3))
{
case T_Constraint:
{ {
Constraint *n = (Constraint *)$3; Constraint *n = (Constraint *)$3;
if (n != NULL) n->name = $2; if (n != NULL) n->name = $2;
}
break;
case T_FkConstraint:
{
FkConstraint *n = (FkConstraint *)$3;
if (n != NULL) n->constr_name = $2;
}
break;
default:
break;
}
$$ = $3; $$ = $3;
} }
| ConstraintElem | ConstraintElem
...@@ -1110,31 +1156,51 @@ ConstraintElem: CHECK '(' a_expr ')' ...@@ -1110,31 +1156,51 @@ ConstraintElem: CHECK '(' a_expr ')'
n->keys = $4; n->keys = $4;
$$ = (Node *)n; $$ = (Node *)n;
} }
| FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions | FOREIGN KEY '(' columnList ')' REFERENCES ColId opt_column_list key_match key_actions ConstraintAttributeSpec
{ {
elog(NOTICE,"CREATE TABLE/FOREIGN KEY clause ignored; not yet implemented"); FkConstraint *n = makeNode(FkConstraint);
$$ = NULL; 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 = ($11 & 1) != 0;
n->initdeferred = ($11 & 2) != 0;
$$ = (Node *)n;
} }
; ;
key_match: MATCH FULL { $$ = NULL; } key_match: MATCH FULL
| MATCH PARTIAL { $$ = NULL; } {
| /*EMPTY*/ { $$ = NULL; } $$ = "FULL";
}
| MATCH PARTIAL
{
elog(ERROR, "FOREIGN KEY match type PARTIAL not implemented yet");
$$ = "PARTIAL";
}
| /*EMPTY*/
{
elog(ERROR, "FOREIGN KEY match type UNSPECIFIED not implemented yet");
$$ = "UNSPECIFIED";
}
; ;
key_actions: key_action key_action { $$ = NIL; } key_actions: key_action key_action { $$ = $1 | $2; }
| key_action { $$ = NIL; } | key_action { $$ = $1; }
| /*EMPTY*/ { $$ = NIL; } | /*EMPTY*/ { $$ = 0; }
; ;
key_action: ON DELETE key_reference { $$ = NIL; } key_action: ON DELETE key_reference { $$ = $3 << FKCONSTR_ON_DELETE_SHIFT; }
| ON UPDATE key_reference { $$ = NIL; } | ON UPDATE key_reference { $$ = $3 << FKCONSTR_ON_UPDATE_SHIFT; }
; ;
key_reference: NO ACTION { $$ = NULL; } key_reference: NO ACTION { $$ = FKCONSTR_ON_KEY_NOACTION; }
| CASCADE { $$ = NULL; } | RESTRICT { $$ = FKCONSTR_ON_KEY_RESTRICT; }
| SET DEFAULT { $$ = NULL; } | CASCADE { $$ = FKCONSTR_ON_KEY_CASCADE; }
| SET NULL_P { $$ = NULL; } | SET NULL_P { $$ = FKCONSTR_ON_KEY_SETNULL; }
| SET DEFAULT { $$ = FKCONSTR_ON_KEY_SETDEFAULT; }
; ;
OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; } OptInherit: INHERITS '(' relation_name_list ')' { $$ = $3; }
...@@ -1329,14 +1395,14 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON ...@@ -1329,14 +1395,14 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
} }
| CREATE CONSTRAINT TRIGGER name AFTER TriggerOneEvent ON | CREATE CONSTRAINT TRIGGER name AFTER TriggerOneEvent ON
relation_name OptConstrFromTable relation_name OptConstrFromTable
OptConstrTrigDeferrable OptConstrTrigInitdeferred ConstraintAttributeSpec
FOR EACH ROW EXECUTE PROCEDURE name '(' TriggerFuncArgs ')' FOR EACH ROW EXECUTE PROCEDURE name '(' TriggerFuncArgs ')'
{ {
CreateTrigStmt *n = makeNode(CreateTrigStmt); CreateTrigStmt *n = makeNode(CreateTrigStmt);
n->trigname = $4; n->trigname = $4;
n->relname = $8; n->relname = $8;
n->funcname = $17; n->funcname = $16;
n->args = $19; n->args = $18;
n->before = false; n->before = false;
n->row = true; n->row = true;
n->actions[0] = $6; n->actions[0] = $6;
...@@ -1346,22 +1412,9 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON ...@@ -1346,22 +1412,9 @@ CreateTrigStmt: CREATE TRIGGER name TriggerActionTime TriggerEvents ON
n->attr = NULL; /* unused */ n->attr = NULL; /* unused */
n->when = NULL; /* unused */ n->when = NULL; /* unused */
/*
* Check that the DEFERRABLE and INITIALLY combination
* makes sense
*/
n->isconstraint = true; n->isconstraint = true;
if ($11 == 1) n->deferrable = ($10 & 1) != 0;
{ n->initdeferred = ($10 & 2) != 0;
if ($10 == 0)
elog(ERROR, "INITIALLY DEFERRED constraint "
"cannot be NOT DEFERRABLE");
n->deferrable = true;
n->initdeferred = true;
} else {
n->deferrable = ($10 == 1);
n->initdeferred = false;
}
n->constrrelname = $9; n->constrrelname = $9;
$$ = (Node *)n; $$ = (Node *)n;
...@@ -1443,34 +1496,44 @@ OptConstrFromTable: /* Empty */ ...@@ -1443,34 +1496,44 @@ OptConstrFromTable: /* Empty */
} }
; ;
OptConstrTrigDeferrable: /* Empty */ ConstraintAttributeSpec: /* Empty */
{ $$ = 0; }
| ConstraintDeferrabilitySpec
{ $$ = $1; }
| ConstraintDeferrabilitySpec ConstraintTimeSpec
{ {
$$ = -1; if ($1 == 0 && $2 != 0)
elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
$$ = $1 | $2;
} }
| DEFERRABLE | ConstraintTimeSpec
{ {
$$ = 1; if ($1 != 0)
$$ = 3;
else
$$ = 0;
} }
| NOT DEFERRABLE | ConstraintTimeSpec ConstraintDeferrabilitySpec
{ {
$$ = 0; if ($2 == 0 && $1 != 0)
elog(ERROR, "INITIALLY DEFERRED constraint must be DEFERRABLE");
$$ = $1 | $2;
} }
; ;
OptConstrTrigInitdeferred: /* Empty */ ConstraintDeferrabilitySpec: NOT DEFERRABLE
{ { $$ = 0; }
$$ = -1; | DEFERRABLE
} { $$ = 1; }
;
ConstraintTimeSpec: INITIALLY IMMEDIATE
{ $$ = 0; }
| INITIALLY DEFERRED | INITIALLY DEFERRED
{ { $$ = 2; }
$$ = 1;
}
| INITIALLY IMMEDIATE
{
$$ = 0;
}
; ;
DropTrigStmt: DROP TRIGGER name ON relation_name DropTrigStmt: DROP TRIGGER name ON relation_name
{ {
DropTrigStmt *n = makeNode(DropTrigStmt); DropTrigStmt *n = makeNode(DropTrigStmt);
......
This diff is collapsed.
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: nodes.h,v 1.56 1999/11/23 20:07:02 momjian Exp $ * $Id: nodes.h,v 1.57 1999/12/06 18:02:46 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -215,7 +215,8 @@ typedef enum NodeTag ...@@ -215,7 +215,8 @@ typedef enum NodeTag
T_JoinExpr, T_JoinExpr,
T_CaseExpr, T_CaseExpr,
T_CaseWhen, T_CaseWhen,
T_RowMark T_RowMark,
T_FkConstraint
} NodeTag; } NodeTag;
/* /*
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* *
* Copyright (c) 1994, Regents of the University of California * Copyright (c) 1994, Regents of the University of California
* *
* $Id: parsenodes.h,v 1.87 1999/11/30 03:57:29 momjian Exp $ * $Id: parsenodes.h,v 1.88 1999/12/06 18:02:47 wieck Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -172,6 +172,37 @@ typedef struct Constraint ...@@ -172,6 +172,37 @@ typedef struct Constraint
List *keys; /* list of primary keys */ List *keys; /* list of primary keys */
} Constraint; } Constraint;
/* ----------
* Definitions for FOREIGN KEY constraints in CreateStmt
* ----------
*/
#define FKCONSTR_ON_KEY_NOACTION 0x0000
#define FKCONSTR_ON_KEY_RESTRICT 0x0001
#define FKCONSTR_ON_KEY_CASCADE 0x0002
#define FKCONSTR_ON_KEY_SETNULL 0x0004
#define FKCONSTR_ON_KEY_SETDEFAULT 0x0008
#define FKCONSTR_ON_DELETE_MASK 0x000F
#define FKCONSTR_ON_DELETE_SHIFT 0
#define FKCONSTR_ON_UPDATE_MASK 0x00F0
#define FKCONSTR_ON_UPDATE_SHIFT 4
typedef struct FkConstraint
{
NodeTag type;
char *constr_name; /* Constraint name */
char *pktable_name; /* Primary key table name */
List *fk_attrs; /* Attributes of foreign key */
List *pk_attrs; /* Corresponding attrs in PK table */
char *match_type; /* FULL or PARTIAL */
int32 actions; /* ON DELETE/UPDATE actions */
bool deferrable; /* DEFERRABLE */
bool initdeferred; /* INITIALLY DEFERRED */
} FkConstraint;
/* ---------------------- /* ----------------------
* Create/Drop TRIGGER Statements * Create/Drop TRIGGER Statements
* ---------------------- * ----------------------
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment