/ Check-in [6fdcee3c]
Login

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 | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1:6fdcee3c99e994ef3ab83a0cc57344cdb16210df
User & Date: drh 2002-06-02 18:19:00
Context
2002-06-02
18:22
Fix a compiler warning. (CVS 604) check-in: 637ee587 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: 6fdcee3c 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: 7acbf84b user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/expr.c.

     8      8   **    May you find forgiveness for yourself and forgive others.
     9      9   **    May you share freely, never taking more than you give.
    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains routines used for analyzing expressions and
    13     13   ** for generating VDBE code that evaluates expressions in SQLite.
    14     14   **
    15         -** $Id: expr.c,v 1.67 2002/06/02 16:09:02 drh Exp $
           15  +** $Id: expr.c,v 1.68 2002/06/02 18:19:00 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18         -
           18  +#include <ctype.h>
    19     19   
    20     20   /*
    21     21   ** Construct a new expression node and return a pointer to it.  Memory
    22     22   ** for this node is obtained from sqliteMalloc().  The calling function
    23     23   ** is responsible for making sure the node eventually gets freed.
    24     24   */
    25     25   Expr *sqliteExpr(int op, Expr *pLeft, Expr *pRight, Token *pToken){

Changes to src/parse.y.

    10     10   **
    11     11   *************************************************************************
    12     12   ** This file contains SQLite's grammar for SQL.  Process this file
    13     13   ** using the lemon parser generator to generate C code that runs
    14     14   ** the parser.  Lemon will also generate a header file containing
    15     15   ** numeric codes for all of the tokens.
    16     16   **
    17         -** @(#) $Id: parse.y,v 1.69 2002/05/24 16:14:15 drh Exp $
           17  +** @(#) $Id: parse.y,v 1.70 2002/06/02 18:19:00 drh Exp $
    18     18   */
    19     19   %token_prefix TK_
    20     20   %token_type {Token}
    21     21   %default_type {Token}
    22     22   %extra_argument {Parse *pParse}
    23     23   %syntax_error {
    24     24     sqliteSetString(&pParse->zErrMsg,"syntax error",0);
................................................................................
   111    111   //
   112    112   %type id {Token}
   113    113   id(A) ::= ABORT(X).      {A = X;}
   114    114   id(A) ::= AFTER(X).      {A = X;}
   115    115   id(A) ::= ASC(X).        {A = X;}
   116    116   id(A) ::= BEFORE(X).     {A = X;}
   117    117   id(A) ::= BEGIN(X).      {A = X;}
          118  +id(A) ::= CASCADE(X).    {A = X;}
   118    119   id(A) ::= CLUSTER(X).    {A = X;}
   119    120   id(A) ::= CONFLICT(X).   {A = X;}
   120    121   id(A) ::= COPY(X).       {A = X;}
          122  +id(A) ::= DEFERRED(X).   {A = X;}
   121    123   id(A) ::= DELIMITERS(X). {A = X;}
   122    124   id(A) ::= DESC(X).       {A = X;}
   123    125   id(A) ::= EACH(X).       {A = X;}
   124    126   id(A) ::= END(X).        {A = X;}
   125    127   id(A) ::= EXPLAIN(X).    {A = X;}
   126    128   id(A) ::= FAIL(X).       {A = X;}
   127    129   id(A) ::= FOR(X).        {A = X;}
          130  +id(A) ::= FULL(X).       {A = X;}
   128    131   id(A) ::= ID(X).         {A = X;}
   129    132   id(A) ::= IGNORE(X).     {A = X;}
          133  +id(A) ::= IMMEDATE(X).   {A = X;}
          134  +id(A) ::= INITIALLY(X).  {A = X;}
   130    135   id(A) ::= INSTEAD(X).    {A = X;}
          136  +id(A) ::= MATCH(X).      {A = X;}
   131    137   id(A) ::= JOIN(X).       {A = X;}
   132    138   id(A) ::= KEY(X).        {A = X;}
   133    139   id(A) ::= OF(X).         {A = X;}
   134    140   id(A) ::= OFFSET(X).     {A = X;}
          141  +id(A) ::= PARTIAL(X).    {A = X;}
   135    142   id(A) ::= PRAGMA(X).     {A = X;}
   136    143   id(A) ::= REPLACE(X).    {A = X;}
          144  +id(A) ::= RESTRICT(X).   {A = X;}
   137    145   id(A) ::= ROW(X).        {A = X;}
   138    146   id(A) ::= STATEMENT(X).  {A = X;}
   139    147   id(A) ::= TEMP(X).       {A = X;}
   140    148   id(A) ::= TRIGGER(X).    {A = X;}
   141    149   id(A) ::= VACUUM(X).     {A = X;}
   142    150   id(A) ::= VIEW(X).       {A = X;}
   143    151   
................................................................................
   175    183   // In addition to the type name, we also care about the primary key and
   176    184   // UNIQUE constraints.
   177    185   //
   178    186   ccons ::= NOT NULL onconf(R).               {sqliteAddNotNull(pParse, R);}
   179    187   ccons ::= PRIMARY KEY sortorder onconf(R).  {sqliteAddPrimaryKey(pParse,0,R);}
   180    188   ccons ::= UNIQUE onconf(R).            {sqliteCreateIndex(pParse,0,0,0,R,0,0);}
   181    189   ccons ::= CHECK LP expr RP onconf.
          190  +ccons ::= references.
          191  +ccons ::= defer_subclause.
          192  +
          193  +// A REFERENCES clause is parsed but the current implementation does not
          194  +// do anything with it.
          195  +//
          196  +references ::= REFERENCES ids LP idxlist RP refargs.
          197  +references ::= REFERENCES ids refargs.
          198  +refargs ::= .
          199  +refargs ::= refargs refarg.
          200  +refarg ::= MATCH FULL.
          201  +refarg ::= MATCH PARTIAL.
          202  +refarg ::= ON DELETE refact.
          203  +refarg ::= ON UPDATE refact.
          204  +refact ::= SET NULL.
          205  +refact ::= SET DEFAULT.
          206  +refact ::= CASCADE.
          207  +refact ::= RESTRICT.
          208  +defer_subclause ::= NOT DEFERRABLE init_deferred_pred_opt.
          209  +defer_subclause ::= DEFERRABLE init_deferred_pred_opt.
          210  +init_deferred_pred_opt ::= .
          211  +init_deferred_pred_opt ::= INITIALLY DEFERRED.
          212  +init_deferred_pred_opt ::= INITIALLY IMMEDIATE.
   182    213   
   183    214   // For the time being, the only constraint we care about is the primary
   184    215   // key and UNIQUE.  Both create indices.
   185    216   //
   186    217   conslist_opt ::= .
   187    218   conslist_opt ::= COMMA conslist.
   188    219   conslist ::= conslist COMMA tcons.
................................................................................
   190    221   conslist ::= tcons.
   191    222   tcons ::= CONSTRAINT ids.
   192    223   tcons ::= PRIMARY KEY LP idxlist(X) RP onconf(R).
   193    224                                                {sqliteAddPrimaryKey(pParse,X,R);}
   194    225   tcons ::= UNIQUE LP idxlist(X) RP onconf(R).
   195    226                                          {sqliteCreateIndex(pParse,0,0,X,R,0,0);}
   196    227   tcons ::= CHECK expr onconf.
          228  +tcons ::= FOREIGN KEY LP idxlist RP references defer_subclause_opt.
          229  +defer_subclause_opt ::= .
          230  +defer_subclause_opt ::= defer_subclause.
   197    231   
   198    232   // The following is a non-standard extension that allows us to declare the
   199    233   // default behavior when there is a constraint conflict.
   200    234   //
   201    235   %type onconf {int}
   202    236   %type orconf {int}
   203    237   %type resolvetype {int}

Changes to src/tokenize.c.

    11     11   *************************************************************************
    12     12   ** An tokenizer for SQL
    13     13   **
    14     14   ** This file contains C code that splits an SQL input string up into
    15     15   ** individual tokens and sends those tokens one-by-one over to the
    16     16   ** parser for analysis.
    17     17   **
    18         -** $Id: tokenize.c,v 1.43 2002/05/24 16:14:15 drh Exp $
           18  +** $Id: tokenize.c,v 1.44 2002/06/02 18:19:00 drh Exp $
    19     19   */
    20     20   #include "sqliteInt.h"
    21     21   #include "os.h"
    22     22   #include <ctype.h>
    23     23   #include <stdlib.h>
    24     24   
    25     25   /*
................................................................................
    44     44     { "AND",               0, TK_AND,              0 },
    45     45     { "AS",                0, TK_AS,               0 },
    46     46     { "ASC",               0, TK_ASC,              0 },
    47     47     { "BEFORE",            0, TK_BEFORE,           0 },
    48     48     { "BEGIN",             0, TK_BEGIN,            0 },
    49     49     { "BETWEEN",           0, TK_BETWEEN,          0 },
    50     50     { "BY",                0, TK_BY,               0 },
           51  +  { "CASCADE",           0, TK_CASCADE,          0 },
    51     52     { "CASE",              0, TK_CASE,             0 },
    52     53     { "CHECK",             0, TK_CHECK,            0 },
    53     54     { "CLUSTER",           0, TK_CLUSTER,          0 },
    54     55     { "COMMIT",            0, TK_COMMIT,           0 },
    55     56     { "CONFLICT",          0, TK_CONFLICT,         0 },
    56     57     { "CONSTRAINT",        0, TK_CONSTRAINT,       0 },
    57     58     { "COPY",              0, TK_COPY,             0 },
    58     59     { "CREATE",            0, TK_CREATE,           0 },
    59     60     { "DEFAULT",           0, TK_DEFAULT,          0 },
           61  +  { "DEFERRED",          0, TK_DEFERRED,         0 },
           62  +  { "DEFERRABLE",        0, TK_DEFERRABLE,       0 },
    60     63     { "DELETE",            0, TK_DELETE,           0 },
    61     64     { "DELIMITERS",        0, TK_DELIMITERS,       0 },
    62     65     { "DESC",              0, TK_DESC,             0 },
    63     66     { "DISTINCT",          0, TK_DISTINCT,         0 },
    64     67     { "DROP",              0, TK_DROP,             0 },
    65     68     { "END",               0, TK_END,              0 },
    66     69     { "EACH",              0, TK_EACH,             0 },
    67     70     { "ELSE",              0, TK_ELSE,             0 },
    68     71     { "EXCEPT",            0, TK_EXCEPT,           0 },
    69     72     { "EXPLAIN",           0, TK_EXPLAIN,          0 },
    70     73     { "FAIL",              0, TK_FAIL,             0 },
    71     74     { "FOR",               0, TK_FOR,              0 },
           75  +  { "FOREIGN",           0, TK_FOREIGN,          0 },
    72     76     { "FROM",              0, TK_FROM,             0 },
           77  +  { "FULL",              0, TK_FULL,             0 },
    73     78     { "GLOB",              0, TK_GLOB,             0 },
    74     79     { "GROUP",             0, TK_GROUP,            0 },
    75     80     { "HAVING",            0, TK_HAVING,           0 },
    76     81     { "IGNORE",            0, TK_IGNORE,           0 },
           82  +  { "IMMEDIATE",         0, TK_IMMEDIATE,        0 },
    77     83     { "IN",                0, TK_IN,               0 },
    78     84     { "INDEX",             0, TK_INDEX,            0 },
           85  +  { "INITIALLY",         0, TK_INITIALLY,        0 },
    79     86     { "INSERT",            0, TK_INSERT,           0 },
    80     87     { "INSTEAD",           0, TK_INSTEAD,          0 },
    81     88     { "INTERSECT",         0, TK_INTERSECT,        0 },
    82     89     { "INTO",              0, TK_INTO,             0 },
    83     90     { "IS",                0, TK_IS,               0 },
    84     91     { "ISNULL",            0, TK_ISNULL,           0 },
    85     92     { "JOIN",              0, TK_JOIN,             0 },
    86     93     { "KEY",               0, TK_KEY,              0 },
    87     94     { "LIKE",              0, TK_LIKE,             0 },
    88     95     { "LIMIT",             0, TK_LIMIT,            0 },
           96  +  { "MATCH",             0, TK_MATCH,            0 },
    89     97     { "NOT",               0, TK_NOT,              0 },
    90     98     { "NOTNULL",           0, TK_NOTNULL,          0 },
    91     99     { "NULL",              0, TK_NULL,             0 },
    92    100     { "OF",                0, TK_OF,               0 },
    93    101     { "OFFSET",            0, TK_OFFSET,           0 },
    94    102     { "ON",                0, TK_ON,               0 },
    95    103     { "OR",                0, TK_OR,               0 },
    96    104     { "ORDER",             0, TK_ORDER,            0 },
          105  +  { "PARTIAL",           0, TK_PARTIAL,          0 },
    97    106     { "PRAGMA",            0, TK_PRAGMA,           0 },
    98    107     { "PRIMARY",           0, TK_PRIMARY,          0 },
          108  +  { "REFERENCES",        0, TK_REFERENCES,       0 },
    99    109     { "REPLACE",           0, TK_REPLACE,          0 },
          110  +  { "RESTRICT",          0, TK_RESTRICT,         0 },
   100    111     { "ROLLBACK",          0, TK_ROLLBACK,         0 },
   101    112     { "ROW",               0, TK_ROW,              0 },
   102    113     { "SELECT",            0, TK_SELECT,           0 },
   103    114     { "SET",               0, TK_SET,              0 },
   104    115     { "STATEMENT",         0, TK_STATEMENT,        0 },
   105    116     { "TABLE",             0, TK_TABLE,            0 },
   106    117     { "TEMP",              0, TK_TEMP,             0 },

Changes to test/table.test.

     7      7   #    May you find forgiveness for yourself and forgive others.
     8      8   #    May you share freely, never taking more than you give.
     9      9   #
    10     10   #***********************************************************************
    11     11   # This file implements regression tests for SQLite library.  The
    12     12   # focus of this file is testing the CREATE TABLE statement.
    13     13   #
    14         -# $Id: table.test,v 1.16 2002/05/22 21:27:04 drh Exp $
           14  +# $Id: table.test,v 1.17 2002/06/02 18:19:00 drh Exp $
    15     15   
    16     16   set testdir [file dirname $argv0]
    17     17   source $testdir/tester.tcl
    18     18   
    19     19   # Create a basic table and verify it is added to sqlite_master
    20     20   #
    21     21   do_test table-1.1 {
................................................................................
   373    373   # Make sure we cannot have duplicate column names within a table.
   374    374   #
   375    375   do_test table-9.1 {
   376    376     catchsql {
   377    377       CREATE TABLE t6(a,b,a);
   378    378     }
   379    379   } {1 {duplicate column name: a}}
          380  +
          381  +# Check the foreign key syntax.
          382  +#
          383  +do_test table-10.1 {
          384  +  catchsql {
          385  +    CREATE TABLE t6(a REFERENCES t4(a) NOT NULL);
          386  +    INSERT INTO t6 VALUES(NULL);
          387  +  }
          388  +} {1 {constraint failed}}
          389  +do_test table-10.2 {
          390  +  catchsql {
          391  +    DROP TABLE t6;
          392  +    CREATE TABLE t6(a REFERENCES t4(a) MATCH PARTIAL);
          393  +  }
          394  +} {0 {}}
          395  +do_test table-10.3 {
          396  +  catchsql {
          397  +    DROP TABLE t6;
          398  +    CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON DELETE SET NULL NOT NULL);
          399  +  }
          400  +} {0 {}}
          401  +do_test table-10.4 {
          402  +  catchsql {
          403  +    DROP TABLE t6;
          404  +    CREATE TABLE t6(a REFERENCES t4 MATCH FULL ON UPDATE SET DEFAULT DEFAULT 1);
          405  +  }
          406  +} {0 {}}
          407  +do_test table-10.5 {
          408  +  catchsql {
          409  +    DROP TABLE t6;
          410  +    CREATE TABLE t6(a NOT NULL NOT DEFERRABLE INITIALLY IMMEDIATE);
          411  +  }
          412  +} {0 {}}
          413  +do_test table-10.6 {
          414  +  catchsql {
          415  +    DROP TABLE t6;
          416  +    CREATE TABLE t6(a NOT NULL DEFERRABLE INITIALLY DEFERRED);
          417  +  }
          418  +} {0 {}}
          419  +do_test table-10.7 {
          420  +  catchsql {
          421  +    DROP TABLE t6;
          422  +    CREATE TABLE t6(a,
          423  +      FOREIGN KEY (a) REFERENCES t4(b) DEFERRABLE INITIALLY DEFERRED
          424  +    );
          425  +  }
          426  +} {0 {}}
          427  +do_test table-10.8 {
          428  +  catchsql {
          429  +    DROP TABLE t6;
          430  +    CREATE TABLE t6(a,b,c,
          431  +      FOREIGN KEY (b,c) REFERENCES t4(x,y) MATCH PARTIAL
          432  +        ON UPDATE SET NULL ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED
          433  +    );
          434  +  }
          435  +} {0 {}}
          436  +
   380    437   
   381    438   
   382    439   finish_test