From 04738cb9ffd962fc72b54c26e658905b08b6f167 Mon Sep 17 00:00:00 2001 From: drh Date: Sun, 2 Jun 2002 18:19:00 +0000 Subject: [PATCH] Add the ability to parse FOREIGN KEYs. Foreign keys are still ignored, but at least they now do not cause a syntax error. (CVS 603) FossilOrigin-Name: 6fdcee3c99e994ef3ab83a0cc57344cdb16210df --- manifest | 18 +++++++-------- manifest.uuid | 2 +- src/expr.c | 4 ++-- src/parse.y | 36 +++++++++++++++++++++++++++++- src/tokenize.c | 13 ++++++++++- test/table.test | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- 6 files changed, 117 insertions(+), 15 deletions(-) diff --git a/manifest b/manifest index b8c64658d2..f5476b0c15 100644 --- a/manifest +++ b/manifest @@ -1,5 +1,5 @@ -C Enhance\sthe\sORDER\sBY\sclause\sso\sthat\san\sinteger\sterm\smeans\sto\ssort\sby\sthe\ncorresponding\scolumn.\s(CVS\s602) -D 2002-06-02T16:09:02 +C Add\sthe\sability\sto\sparse\sFOREIGN\sKEYs.\s\sForeign\skeys\sare\sstill\signored,\nbut\sat\sleast\sthey\snow\sdo\snot\scause\sa\ssyntax\serror.\s(CVS\s603) +D 2002-06-02T18:19:00 F Makefile.in 6291a33b87d2a395aafd7646ee1ed562c6f2c28c F Makefile.template 4e11752e0b5c7a043ca50af4296ec562857ba495 F README a4c0ba11354ef6ba0776b400d057c59da47a4cc0 @@ -23,7 +23,7 @@ F src/btree.h 8abeabfe6e0b1a990b64fa457592a6482f6674f3 F src/build.c 36e42718a7a94f554ea39508993378482f5335c7 F src/delete.c a2b098cbbf518e6b641847e26de85827793bc523 F src/encode.c 346b12b46148506c32038524b95c4631ab46d760 -F src/expr.c 4ee07b536119e7ee4f572e1ca83ad86c1aef0058 +F src/expr.c 4c1b3b3dd0263a36661976a2071f947bf6a4048b F src/func.c 061a520a122da7e4f9dcac15697bb996aac7d5df F src/hash.c 6a6236b89c8c060c65dabd300a1c8ce7c10edb72 F src/hash.h dca065dda89d4575f3176e75e9a3dc0f4b4fb8b9 @@ -34,7 +34,7 @@ F src/os.c 9cc40c5384baba4a85e160e67807645ca98ba3cc F src/os.h 4a361fccfbc4e7609b3e1557f604f94c1e96ad10 F src/pager.c 1e41053c949cea1f09d8dafada5fe8f90785e650 F src/pager.h 6fddfddd3b73aa8abc081b973886320e3c614f0e -F src/parse.y c681da701bf142967325b8791f22418e2d81552d +F src/parse.y 68c0ab3d6bc938d1edcd087a18f28246c763076a F src/printf.c d8032ee18b860c812eeff596c9bebfdacb7930fd F src/random.c 19e8e00fe0df32a742f115773f57651be327cabe F src/select.c ad9061b4735ccd79fc073415979882cd5c424c71 @@ -48,7 +48,7 @@ F src/test1.c 09d95048b66ce6dcd2bae90f443589043d7d631e F src/test2.c 669cc22781c6461a273416ec1a7414d25c081730 F src/test3.c 4e52fff8b01f08bd202f7633feda5639b7ba2b5e F src/threadtest.c 81f0598e0f031c1bd506af337fdc1b7e8dff263f -F src/tokenize.c facec7dc0b4a13e17ad67702f548dac2f7c6a732 +F src/tokenize.c 35c63867d03fcaf81fe520f8d8206981d0c7270e F src/trigger.c d02f8e3510c7c2ad948a0e8c3bb0cca8adaf80c5 F src/update.c f68375173bf5338cae3e97012708e10f206aedd9 F src/util.c 7cf46b5612f5d12601c697374b9c6b38b2332ce8 @@ -95,7 +95,7 @@ F test/select5.test c2a6c4a003316ee42cbbd689eebef8fdce0db2ac F test/select6.test efb8d0c07a440441db87db2c4ade6904e1407e85 F test/sort.test 3b996ce7ca385f9cd559944ac0f4027a23aa546b F test/subselect.test f3bc1dcbddddcea08d818fcff75228ad3464fc83 -F test/table.test d9fd161dc9a2dbe0795d836336019ea6d0952ef8 +F test/table.test 42511f98a3e9bbee62913e3ae1774777faa23d35 F test/tableapi.test 3c80421a889e1d106df16e5800fa787f0d2914a6 F test/tclsqlite.test 79deeffd7cd637ca0f06c5dbbf2f44d272079533 F test/temptable.test daa83489eea2e9aaeeece09675c28be84c72cb67 @@ -136,7 +136,7 @@ F www/speed.tcl da8afcc1d3ccc5696cfb388a68982bc3d9f7f00f F www/sqlite.tcl 8b5884354cb615049aed83039f8dfe1552a44279 F www/tclsqlite.tcl 1db15abeb446aad0caf0b95b8b9579720e4ea331 F www/vdbe.tcl 2013852c27a02a091d39a766bc87cff329f21218 -P df9cc852ad02dbec5558d3915a0303f7e7b79b2b -R d820e9b413015f44b726f7ec86a28058 +P 7acbf84b492202d8b5a05276a95b475027eb5f58 +R 877ef09a15f8898a71498bdf36c4a9ea U drh -Z 52b5b2062ca7af0b018c152f36b11673 +Z 5f9a38c2f7b726600f68471f0ff58f27 diff --git a/manifest.uuid b/manifest.uuid index 56899c72e7..c907224632 100644 --- a/manifest.uuid +++ b/manifest.uuid @@ -1 +1 @@ -7acbf84b492202d8b5a05276a95b475027eb5f58 \ No newline at end of file +6fdcee3c99e994ef3ab83a0cc57344cdb16210df \ No newline at end of file diff --git a/src/expr.c b/src/expr.c index b5bb89c99e..924719b7b3 100644 --- a/src/expr.c +++ b/src/expr.c @@ -12,10 +12,10 @@ ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** -** $Id: expr.c,v 1.67 2002/06/02 16:09:02 drh Exp $ +** $Id: expr.c,v 1.68 2002/06/02 18:19:00 drh Exp $ */ #include "sqliteInt.h" - +#include /* ** Construct a new expression node and return a pointer to it. Memory diff --git a/src/parse.y b/src/parse.y index f78a9995ca..aac2ec4bb8 100644 --- a/src/parse.y +++ b/src/parse.y @@ -14,7 +14,7 @@ ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** -** @(#) $Id: parse.y,v 1.69 2002/05/24 16:14:15 drh Exp $ +** @(#) $Id: parse.y,v 1.70 2002/06/02 18:19:00 drh Exp $ */ %token_prefix TK_ %token_type {Token} @@ -115,9 +115,11 @@ id(A) ::= AFTER(X). {A = X;} id(A) ::= ASC(X). {A = X;} id(A) ::= BEFORE(X). {A = X;} id(A) ::= BEGIN(X). {A = X;} +id(A) ::= CASCADE(X). {A = X;} id(A) ::= CLUSTER(X). {A = X;} id(A) ::= CONFLICT(X). {A = X;} id(A) ::= COPY(X). {A = X;} +id(A) ::= DEFERRED(X). {A = X;} id(A) ::= DELIMITERS(X). {A = X;} id(A) ::= DESC(X). {A = X;} id(A) ::= EACH(X). {A = X;} @@ -125,15 +127,21 @@ id(A) ::= END(X). {A = X;} id(A) ::= EXPLAIN(X). {A = X;} id(A) ::= FAIL(X). {A = X;} id(A) ::= FOR(X). {A = X;} +id(A) ::= FULL(X). {A = X;} id(A) ::= ID(X). {A = X;} id(A) ::= IGNORE(X). {A = X;} +id(A) ::= IMMEDATE(X). {A = X;} +id(A) ::= INITIALLY(X). {A = X;} id(A) ::= INSTEAD(X). {A = X;} +id(A) ::= MATCH(X). {A = X;} id(A) ::= JOIN(X). {A = X;} id(A) ::= KEY(X). {A = X;} id(A) ::= OF(X). {A = X;} id(A) ::= OFFSET(X). {A = X;} +id(A) ::= PARTIAL(X). {A = X;} id(A) ::= PRAGMA(X). {A = X;} id(A) ::= REPLACE(X). {A = X;} +id(A) ::= RESTRICT(X). {A = X;} id(A) ::= ROW(X). {A = X;} id(A) ::= STATEMENT(X). {A = X;} id(A) ::= TEMP(X). {A = X;} @@ -179,6 +187,29 @@ ccons ::= NOT NULL onconf(R). {sqliteAddNotNull(pParse, R);} ccons ::= PRIMARY KEY sortorder onconf(R). {sqliteAddPrimaryKey(pParse,0,R);} ccons ::= UNIQUE onconf(R). {sqliteCreateIndex(pParse,0,0,0,R,0,0);} ccons ::= CHECK LP expr RP onconf. +ccons ::= references. +ccons ::= defer_subclause. + +// A REFERENCES clause is parsed but the current implementation does not +// do anything with it. +// +references ::= REFERENCES ids LP idxlist RP refargs. +references ::= REFERENCES ids refargs. +refargs ::= . +refargs ::= refargs refarg. +refarg ::= MATCH FULL. +refarg ::= MATCH PARTIAL. +refarg ::= ON DELETE refact. +refarg ::= ON UPDATE refact. +refact ::= SET NULL. +refact ::= SET DEFAULT. +refact ::= CASCADE. +refact ::= RESTRICT. +defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt. +defer_subclause ::= DEFERRABLE init_deferred_pred_opt. +init_deferred_pred_opt ::= . +init_deferred_pred_opt ::= INITIALLY DEFERRED. +init_deferred_pred_opt ::= INITIALLY IMMEDIATE. // For the time being, the only constraint we care about is the primary // key and UNIQUE. Both create indices. @@ -194,6 +225,9 @@ tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R). tcons ::= UNIQUE LP idxlist(X) RP onconf(R). {sqliteCreateIndex(pParse,0,0,X,R,0,0);} tcons ::= CHECK expr onconf. +tcons ::= FOREIGN KEY LP idxlist RP references defer_subclause_opt. +defer_subclause_opt ::= . +defer_subclause_opt ::= defer_subclause. // The following is a non-standard extension that allows us to declare the // default behavior when there is a constraint conflict. diff --git a/src/tokenize.c b/src/tokenize.c index b566f09e8d..5be1b33545 100644 --- a/src/tokenize.c +++ b/src/tokenize.c @@ -15,7 +15,7 @@ ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** -** $Id: tokenize.c,v 1.43 2002/05/24 16:14:15 drh Exp $ +** $Id: tokenize.c,v 1.44 2002/06/02 18:19:00 drh Exp $ */ #include "sqliteInt.h" #include "os.h" @@ -48,6 +48,7 @@ static Keyword aKeywordTable[] = { { "BEGIN", 0, TK_BEGIN, 0 }, { "BETWEEN", 0, TK_BETWEEN, 0 }, { "BY", 0, TK_BY, 0 }, + { "CASCADE", 0, TK_CASCADE, 0 }, { "CASE", 0, TK_CASE, 0 }, { "CHECK", 0, TK_CHECK, 0 }, { "CLUSTER", 0, TK_CLUSTER, 0 }, @@ -57,6 +58,8 @@ static Keyword aKeywordTable[] = { { "COPY", 0, TK_COPY, 0 }, { "CREATE", 0, TK_CREATE, 0 }, { "DEFAULT", 0, TK_DEFAULT, 0 }, + { "DEFERRED", 0, TK_DEFERRED, 0 }, + { "DEFERRABLE", 0, TK_DEFERRABLE, 0 }, { "DELETE", 0, TK_DELETE, 0 }, { "DELIMITERS", 0, TK_DELIMITERS, 0 }, { "DESC", 0, TK_DESC, 0 }, @@ -69,13 +72,17 @@ static Keyword aKeywordTable[] = { { "EXPLAIN", 0, TK_EXPLAIN, 0 }, { "FAIL", 0, TK_FAIL, 0 }, { "FOR", 0, TK_FOR, 0 }, + { "FOREIGN", 0, TK_FOREIGN, 0 }, { "FROM", 0, TK_FROM, 0 }, + { "FULL", 0, TK_FULL, 0 }, { "GLOB", 0, TK_GLOB, 0 }, { "GROUP", 0, TK_GROUP, 0 }, { "HAVING", 0, TK_HAVING, 0 }, { "IGNORE", 0, TK_IGNORE, 0 }, + { "IMMEDIATE", 0, TK_IMMEDIATE, 0 }, { "IN", 0, TK_IN, 0 }, { "INDEX", 0, TK_INDEX, 0 }, + { "INITIALLY", 0, TK_INITIALLY, 0 }, { "INSERT", 0, TK_INSERT, 0 }, { "INSTEAD", 0, TK_INSTEAD, 0 }, { "INTERSECT", 0, TK_INTERSECT, 0 }, @@ -86,6 +93,7 @@ static Keyword aKeywordTable[] = { { "KEY", 0, TK_KEY, 0 }, { "LIKE", 0, TK_LIKE, 0 }, { "LIMIT", 0, TK_LIMIT, 0 }, + { "MATCH", 0, TK_MATCH, 0 }, { "NOT", 0, TK_NOT, 0 }, { "NOTNULL", 0, TK_NOTNULL, 0 }, { "NULL", 0, TK_NULL, 0 }, @@ -94,9 +102,12 @@ static Keyword aKeywordTable[] = { { "ON", 0, TK_ON, 0 }, { "OR", 0, TK_OR, 0 }, { "ORDER", 0, TK_ORDER, 0 }, + { "PARTIAL", 0, TK_PARTIAL, 0 }, { "PRAGMA", 0, TK_PRAGMA, 0 }, { "PRIMARY", 0, TK_PRIMARY, 0 }, + { "REFERENCES", 0, TK_REFERENCES, 0 }, { "REPLACE", 0, TK_REPLACE, 0 }, + { "RESTRICT", 0, TK_RESTRICT, 0 }, { "ROLLBACK", 0, TK_ROLLBACK, 0 }, { "ROW", 0, TK_ROW, 0 }, { "SELECT", 0, TK_SELECT, 0 }, diff --git a/test/table.test b/test/table.test index 1b403fe264..6c8c00bb78 100644 --- a/test/table.test +++ b/test/table.test @@ -11,7 +11,7 @@ # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # -# $Id: table.test,v 1.16 2002/05/22 21:27:04 drh Exp $ +# $Id: table.test,v 1.17 2002/06/02 18:19:00 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl @@ -378,5 +378,62 @@ do_test table-9.1 { } } {1 {duplicate column name: a}} +# Check the foreign key syntax. +# +do_test table-10.1 { + catchsql { + CREATE TABLE t6(a REFERENCES t4(a) NOT NULL); + INSERT INTO t6 VALUES(NULL); + } +} {1 {constraint failed}} +do_test table-10.2 { + catchsql { + DROP TABLE t6; + CREATE TABLE t6(a REFERENCES t4(a) MATCH PARTIAL); + } +} {0 {}} +do_test table-10.3 { + catchsql { + DROP TABLE t6; + CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON DELETE SET NULL NOT NULL); + } +} {0 {}} +do_test table-10.4 { + catchsql { + DROP TABLE t6; + CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON UPDATE SET DEFAULT DEFAULT 1); + } +} {0 {}} +do_test table-10.5 { + catchsql { + DROP TABLE t6; + CREATE TABLE t6(a NOT NULL NOT DEFERRABLE INITIALLY IMMEDIATE); + } +} {0 {}} +do_test table-10.6 { + catchsql { + DROP TABLE t6; + CREATE TABLE t6(a NOT NULL DEFERRABLE INITIALLY DEFERRED); + } +} {0 {}} +do_test table-10.7 { + catchsql { + DROP TABLE t6; + CREATE TABLE t6(a, + FOREIGN KEY (a) REFERENCES t4(b) DEFERRABLE INITIALLY DEFERRED + ); + } +} {0 {}} +do_test table-10.8 { + catchsql { + DROP TABLE t6; + CREATE TABLE t6(a,b,c, + FOREIGN KEY (b,c) REFERENCES t4(x,y) MATCH PARTIAL + ON UPDATE SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED + ); + } +} {0 {}} + + finish_test -- 2.47.3