Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | 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) |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
6fdcee3c99e994ef3ab83a0cc57344cd |
User & Date: | drh 2002-06-02 18:19:00.000 |
Context
2002-06-02
| ||
18:22 | Fix a compiler warning. (CVS 604) (check-in: 637ee587b5 user: drh tags: trunk) | |
18:19 | 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) (check-in: 6fdcee3c99 user: drh tags: trunk) | |
16:09 | Enhance the ORDER BY clause so that an integer term means to sort by the corresponding column. (CVS 602) (check-in: 7acbf84b49 user: drh tags: trunk) | |
Changes
Changes to src/expr.c.
︙ | ︙ | |||
8 9 10 11 12 13 14 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** | | | | 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ** May you find forgiveness for yourself and forgive others. ** May you share freely, never taking more than you give. ** ************************************************************************* ** This file contains routines used for analyzing expressions and ** for generating VDBE code that evaluates expressions in SQLite. ** ** $Id: expr.c,v 1.68 2002/06/02 18:19:00 drh Exp $ */ #include "sqliteInt.h" #include <ctype.h> /* ** Construct a new expression node and return a pointer to it. Memory ** for this node is obtained from sqliteMalloc(). The calling function ** is responsible for making sure the node eventually gets freed. */ Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){ |
︙ | ︙ |
Changes to src/parse.y.
︙ | ︙ | |||
10 11 12 13 14 15 16 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** | | | 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ** ************************************************************************* ** This file contains SQLite's grammar for SQL. Process this file ** using the lemon parser generator to generate C code that runs ** the parser. Lemon will also generate a header file containing ** numeric codes for all of the tokens. ** ** @(#) $Id: parse.y,v 1.70 2002/06/02 18:19:00 drh Exp $ */ %token_prefix TK_ %token_type {Token} %default_type {Token} %extra_argument {Parse *pParse} %syntax_error { sqliteSetString(&pParse->zErrMsg,"syntax error",0); |
︙ | ︙ | |||
111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 | // %type id {Token} id(A) ::= ABORT(X). {A = X;} 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) ::= CLUSTER(X). {A = X;} id(A) ::= CONFLICT(X). {A = X;} id(A) ::= COPY(X). {A = X;} id(A) ::= DELIMITERS(X). {A = X;} id(A) ::= DESC(X). {A = X;} id(A) ::= EACH(X). {A = X;} 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) ::= ID(X). {A = X;} id(A) ::= IGNORE(X). {A = X;} id(A) ::= INSTEAD(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) ::= PRAGMA(X). {A = X;} id(A) ::= REPLACE(X). {A = X;} id(A) ::= ROW(X). {A = X;} id(A) ::= STATEMENT(X). {A = X;} id(A) ::= TEMP(X). {A = X;} id(A) ::= TRIGGER(X). {A = X;} id(A) ::= VACUUM(X). {A = X;} id(A) ::= VIEW(X). {A = X;} | > > > > > > > > | 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 | // %type id {Token} id(A) ::= ABORT(X). {A = X;} 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;} 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;} id(A) ::= TRIGGER(X). {A = X;} id(A) ::= VACUUM(X). {A = X;} id(A) ::= VIEW(X). {A = X;} |
︙ | ︙ | |||
175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 | // In addition to the type name, we also care about the primary key and // UNIQUE constraints. // 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. // For the time being, the only constraint we care about is the primary // key and UNIQUE. Both create indices. // conslist_opt ::= . conslist_opt ::= COMMA conslist. conslist ::= conslist COMMA tcons. conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT ids. tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R). {sqliteAddPrimaryKey(pParse,X,R);} tcons ::= UNIQUE LP idxlist(X) RP onconf(R). {sqliteCreateIndex(pParse,0,0,X,R,0,0);} tcons ::= CHECK expr onconf. // The following is a non-standard extension that allows us to declare the // default behavior when there is a constraint conflict. // %type onconf {int} %type orconf {int} %type resolvetype {int} | > > > > > > > > > > > > > > > > > > > > > > > > > > | 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 | // In addition to the type name, we also care about the primary key and // UNIQUE constraints. // 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. // conslist_opt ::= . conslist_opt ::= COMMA conslist. conslist ::= conslist COMMA tcons. conslist ::= conslist tcons. conslist ::= tcons. tcons ::= CONSTRAINT ids. tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R). {sqliteAddPrimaryKey(pParse,X,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. // %type onconf {int} %type orconf {int} %type resolvetype {int} |
︙ | ︙ |
Changes to src/tokenize.c.
︙ | ︙ | |||
11 12 13 14 15 16 17 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** | | | 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | ************************************************************************* ** An tokenizer for SQL ** ** This file contains C code that splits an SQL input string up into ** individual tokens and sends those tokens one-by-one over to the ** parser for analysis. ** ** $Id: tokenize.c,v 1.44 2002/06/02 18:19:00 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include <ctype.h> #include <stdlib.h> /* |
︙ | ︙ | |||
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | { "AND", 0, TK_AND, 0 }, { "AS", 0, TK_AS, 0 }, { "ASC", 0, TK_ASC, 0 }, { "BEFORE", 0, TK_BEFORE, 0 }, { "BEGIN", 0, TK_BEGIN, 0 }, { "BETWEEN", 0, TK_BETWEEN, 0 }, { "BY", 0, TK_BY, 0 }, { "CASE", 0, TK_CASE, 0 }, { "CHECK", 0, TK_CHECK, 0 }, { "CLUSTER", 0, TK_CLUSTER, 0 }, { "COMMIT", 0, TK_COMMIT, 0 }, { "CONFLICT", 0, TK_CONFLICT, 0 }, { "CONSTRAINT", 0, TK_CONSTRAINT, 0 }, { "COPY", 0, TK_COPY, 0 }, { "CREATE", 0, TK_CREATE, 0 }, { "DEFAULT", 0, TK_DEFAULT, 0 }, { "DELETE", 0, TK_DELETE, 0 }, { "DELIMITERS", 0, TK_DELIMITERS, 0 }, { "DESC", 0, TK_DESC, 0 }, { "DISTINCT", 0, TK_DISTINCT, 0 }, { "DROP", 0, TK_DROP, 0 }, { "END", 0, TK_END, 0 }, { "EACH", 0, TK_EACH, 0 }, { "ELSE", 0, TK_ELSE, 0 }, { "EXCEPT", 0, TK_EXCEPT, 0 }, { "EXPLAIN", 0, TK_EXPLAIN, 0 }, { "FAIL", 0, TK_FAIL, 0 }, { "FOR", 0, TK_FOR, 0 }, { "FROM", 0, TK_FROM, 0 }, { "GLOB", 0, TK_GLOB, 0 }, { "GROUP", 0, TK_GROUP, 0 }, { "HAVING", 0, TK_HAVING, 0 }, { "IGNORE", 0, TK_IGNORE, 0 }, { "IN", 0, TK_IN, 0 }, { "INDEX", 0, TK_INDEX, 0 }, { "INSERT", 0, TK_INSERT, 0 }, { "INSTEAD", 0, TK_INSTEAD, 0 }, { "INTERSECT", 0, TK_INTERSECT, 0 }, { "INTO", 0, TK_INTO, 0 }, { "IS", 0, TK_IS, 0 }, { "ISNULL", 0, TK_ISNULL, 0 }, { "JOIN", 0, TK_JOIN, 0 }, { "KEY", 0, TK_KEY, 0 }, { "LIKE", 0, TK_LIKE, 0 }, { "LIMIT", 0, TK_LIMIT, 0 }, { "NOT", 0, TK_NOT, 0 }, { "NOTNULL", 0, TK_NOTNULL, 0 }, { "NULL", 0, TK_NULL, 0 }, { "OF", 0, TK_OF, 0 }, { "OFFSET", 0, TK_OFFSET, 0 }, { "ON", 0, TK_ON, 0 }, { "OR", 0, TK_OR, 0 }, { "ORDER", 0, TK_ORDER, 0 }, { "PRAGMA", 0, TK_PRAGMA, 0 }, { "PRIMARY", 0, TK_PRIMARY, 0 }, { "REPLACE", 0, TK_REPLACE, 0 }, { "ROLLBACK", 0, TK_ROLLBACK, 0 }, { "ROW", 0, TK_ROW, 0 }, { "SELECT", 0, TK_SELECT, 0 }, { "SET", 0, TK_SET, 0 }, { "STATEMENT", 0, TK_STATEMENT, 0 }, { "TABLE", 0, TK_TABLE, 0 }, { "TEMP", 0, TK_TEMP, 0 }, | > > > > > > > > > > > | 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 | { "AND", 0, TK_AND, 0 }, { "AS", 0, TK_AS, 0 }, { "ASC", 0, TK_ASC, 0 }, { "BEFORE", 0, TK_BEFORE, 0 }, { "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 }, { "COMMIT", 0, TK_COMMIT, 0 }, { "CONFLICT", 0, TK_CONFLICT, 0 }, { "CONSTRAINT", 0, TK_CONSTRAINT, 0 }, { "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 }, { "DISTINCT", 0, TK_DISTINCT, 0 }, { "DROP", 0, TK_DROP, 0 }, { "END", 0, TK_END, 0 }, { "EACH", 0, TK_EACH, 0 }, { "ELSE", 0, TK_ELSE, 0 }, { "EXCEPT", 0, TK_EXCEPT, 0 }, { "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 }, { "INTO", 0, TK_INTO, 0 }, { "IS", 0, TK_IS, 0 }, { "ISNULL", 0, TK_ISNULL, 0 }, { "JOIN", 0, TK_JOIN, 0 }, { "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 }, { "OF", 0, TK_OF, 0 }, { "OFFSET", 0, TK_OFFSET, 0 }, { "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 }, { "SET", 0, TK_SET, 0 }, { "STATEMENT", 0, TK_STATEMENT, 0 }, { "TABLE", 0, TK_TABLE, 0 }, { "TEMP", 0, TK_TEMP, 0 }, |
︙ | ︙ |
Changes to test/table.test.
1 2 3 4 5 6 7 8 9 10 11 12 13 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | # 2001 September 15 # # The author disclaims copyright to this source code. In place of # a legal notice, here is a blessing: # # May you do good and not evil. # May you find forgiveness for yourself and forgive others. # May you share freely, never taking more than you give. # #*********************************************************************** # This file implements regression tests for SQLite library. The # focus of this file is testing the CREATE TABLE statement. # # $Id: table.test,v 1.17 2002/06/02 18:19:00 drh Exp $ set testdir [file dirname $argv0] source $testdir/tester.tcl # Create a basic table and verify it is added to sqlite_master # do_test table-1.1 { |
︙ | ︙ | |||
373 374 375 376 377 378 379 380 | # Make sure we cannot have duplicate column names within a table. # do_test table-9.1 { catchsql { CREATE TABLE t6(a,b,a); } } {1 {duplicate column name: a}} | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 | # Make sure we cannot have duplicate column names within a table. # do_test table-9.1 { catchsql { CREATE TABLE t6(a,b,a); } } {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 |