/ Check-in [34a6b741]
Login

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Remove unused code and tighten existing code to make the library a little smaller. (CVS 1168)
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | trunk
Files: files | file ages | folders
SHA1: 34a6b7416c6c9bcdf301f5e7b072a0362a746105
User & Date: drh 2004-01-08 02:17:32
Context
2004-01-12
00:21
Make sure the in-memory database can handle malloc failures. (CVS 1169) check-in: ba92af18 user: drh tags: trunk
2004-01-08
02:17
Remove unused code and tighten existing code to make the library a little smaller. (CVS 1168) check-in: 34a6b741 user: drh tags: trunk
2004-01-07
20:37
Rework the fix to ticket #461 so that we do not have to do redundant tests of WHERE clause terms looking for NULLs. See also check-in (1103). (CVS 1167) check-in: 5fd58178 user: drh tags: trunk
Changes
Hide Diffs Side-by-Side Diffs Ignore Whitespace Patch

Changes to src/date.c.

    12     12   ** This file contains the C functions that implement date and time
    13     13   ** functions for SQLite.  
    14     14   **
    15     15   ** There is only one exported symbol in this file - the function
    16     16   ** sqliteRegisterDateTimeFunctions() found at the bottom of the file.
    17     17   ** All other code has file scope.
    18     18   **
    19         -** $Id: date.c,v 1.7 2004/01/07 03:29:16 drh Exp $
           19  +** $Id: date.c,v 1.8 2004/01/08 02:17:32 drh Exp $
    20     20   **
    21     21   ** NOTES:
    22     22   **
    23     23   ** SQLite processes all times and dates as Julian Day numbers.  The
    24     24   ** dates and times are stored as the number of days since noon
    25     25   ** in Greenwich on November 24, 4714 B.C. according to the Gregorian
    26     26   ** calendar system.
................................................................................
   217    217   
   218    218     if( p->validJD ) return;
   219    219     if( p->validYMD ){
   220    220       Y = p->Y;
   221    221       M = p->M;
   222    222       D = p->D;
   223    223     }else{
   224         -    Y = 2000;
          224  +    Y = 2000;  /* If no YMD specified, assume 2000-Jan-01 */
   225    225       M = 1;
   226    226       D = 1;
   227    227     }
   228    228     if( M<=2 ){
   229    229       Y--;
   230    230       M += 12;
   231    231     }
................................................................................
   363    363     p->s -= s;
   364    364     p->h = s/3600;
   365    365     s -= p->h*3600;
   366    366     p->m = s/60;
   367    367     p->s += s - p->m*60;
   368    368     p->validHMS = 1;
   369    369   }
          370  +
          371  +/*
          372  +** Compute both YMD and HMS
          373  +*/
          374  +static void computeYMD_HMS(DateTime *p){
          375  +  computeYMD(p);
          376  +  computeHMS(p);
          377  +}
          378  +
          379  +/*
          380  +** Clear the YMD and HMS and the TZ
          381  +*/
          382  +static void clearYMD_HMS_TZ(DateTime *p){
          383  +  p->validYMD = 0;
          384  +  p->validHMS = 0;
          385  +  p->validTZ = 0;
          386  +}
   370    387   
   371    388   /*
   372    389   ** Compute the difference (in days) between localtime and UTC (a.k.a. GMT)
   373    390   ** for the time value p where p is in UTC.
   374    391   */
   375    392   static double localtimeOffset(DateTime *p){
   376    393     DateTime x, y;
   377    394     time_t t;
   378    395     struct tm *pTm;
   379         -  computeYMD(p);
   380         -  computeHMS(p);
   381    396     x = *p;
          397  +  computeYMD_HMS(&x);
   382    398     if( x.Y<1971 || x.Y>=2038 ){
   383    399       x.Y = 2000;
   384    400       x.M = 1;
   385    401       x.D = 1;
   386    402       x.h = 0;
   387    403       x.m = 0;
   388    404       x.s = 0.0;
................................................................................
   404    420     y.s = pTm->tm_sec;
   405    421     sqliteOsLeaveMutex();
   406    422     y.validYMD = 1;
   407    423     y.validHMS = 1;
   408    424     y.validJD = 0;
   409    425     y.validTZ = 0;
   410    426     computeJD(&y);
   411         -  /* printf("x=%d-%02d-%02d %02d:%02d:%02d\n",x.Y,x.M,x.D,x.h,x.m,(int)x.s); */
   412         -  /* printf("y=%d-%02d-%02d %02d:%02d:%02d\n",y.Y,y.M,y.D,y.h,y.m,(int)y.s); */
   413         -  /* printf("diff=%.17g\n", y.rJD - x.rJD); */
   414    427     return y.rJD - x.rJD;
   415    428   }
   416    429   
   417    430   /*
   418    431   ** Process a modifier to a date-time stamp.  The modifiers are
   419    432   ** as follows:
   420    433   **
................................................................................
   450    463         **
   451    464         ** Assuming the current time value is UTC (a.k.a. GMT), shift it to
   452    465         ** show local time.
   453    466         */
   454    467         if( strcmp(z, "localtime")==0 ){
   455    468           computeJD(p);
   456    469           p->rJD += localtimeOffset(p);
   457         -        p->validYMD = 0;
   458         -        p->validHMS = 0;
   459         -        p->validTZ = 0;
          470  +        clearYMD_HMS_TZ(p);
   460    471           rc = 0;
   461    472         }
   462    473         break;
   463    474       }
   464    475       case 'u': {
   465    476         /*
   466    477         **    unixepoch
   467    478         **
   468    479         ** Treat the current value of p->rJD as the number of
   469    480         ** seconds since 1970.  Convert to a real julian day number.
   470    481         */
   471    482         if( strcmp(z, "unixepoch")==0 && p->validJD ){
   472    483           p->rJD = p->rJD/86400.0 + 2440587.5;
   473         -        p->validYMD = 0;
   474         -        p->validHMS = 0;
   475         -        p->validTZ = 0;
          484  +        clearYMD_HMS_TZ(p);
   476    485           rc = 0;
   477    486         }else if( strcmp(z, "utc")==0 ){
   478    487           double c1;
   479    488           computeJD(p);
   480    489           c1 = localtimeOffset(p);
   481    490           p->rJD -= c1;
   482         -        p->validYMD = 0;
   483         -        p->validHMS = 0;
   484         -        p->validTZ = 0;
          491  +        clearYMD_HMS_TZ(p);
   485    492           p->rJD += c1 - localtimeOffset(p);
   486         -        p->validYMD = 0;
   487         -        p->validHMS = 0;
   488         -        p->validTZ = 0;
   489    493           rc = 0;
   490    494         }
   491    495         break;
   492    496       }
   493    497       case 'w': {
   494    498         /*
   495    499         **    weekday N
................................................................................
   497    501         ** Move the date to the same time on the next occurrance of
   498    502         ** weekday N where 0==Sunday, 1==Monday, and so forth.  If the
   499    503         ** date is already on the appropriate weekday, this is a no-op.
   500    504         */
   501    505         if( strncmp(z, "weekday ", 8)==0 && getValue(&z[8],&r)>0
   502    506                    && (n=r)==r && n>=0 && r<7 ){
   503    507           int Z;
   504         -        computeYMD(p);
   505         -        computeHMS(p);
          508  +        computeYMD_HMS(p);
   506    509           p->validTZ = 0;
   507    510           p->validJD = 0;
   508    511           computeJD(p);
   509    512           Z = p->rJD + 1.5;
   510    513           Z %= 7;
   511    514           if( Z>n ) Z -= 7;
   512    515           p->rJD += n - Z;
   513         -        p->validYMD = 0;
   514         -        p->validHMS = 0;
          516  +        clearYMD_HMS_TZ(p);
   515    517           rc = 0;
   516    518         }
   517    519         break;
   518    520       }
   519    521       case 's': {
   520    522         /*
   521    523         **    start of TTTTT
................................................................................
   565    567         strcpy(z, zMod);
   566    568         if( z[n-1]=='s' ){ z[n-1] = 0; n--; }
   567    569         computeJD(p);
   568    570         rc = 0;
   569    571         if( n==3 && strcmp(z,"day")==0 ){
   570    572           p->rJD += r;
   571    573         }else if( n==4 && strcmp(z,"hour")==0 ){
   572         -        computeJD(p);
   573    574           p->rJD += r/24.0;
   574    575         }else if( n==6 && strcmp(z,"minute")==0 ){
   575         -        computeJD(p);
   576    576           p->rJD += r/(24.0*60.0);
   577    577         }else if( n==6 && strcmp(z,"second")==0 ){
   578         -        computeJD(p);
   579    578           p->rJD += r/(24.0*60.0*60.0);
   580    579         }else if( n==5 && strcmp(z,"month")==0 ){
   581    580           int x, y;
   582         -        computeYMD(p);
   583         -        computeHMS(p);
          581  +        computeYMD_HMS(p);
   584    582           p->M += r;
   585    583           x = p->M>0 ? (p->M-1)/12 : (p->M-12)/12;
   586    584           p->Y += x;
   587    585           p->M -= x*12;
   588    586           p->validJD = 0;
   589    587           computeJD(p);
   590    588           y = r;
   591    589           if( y!=r ){
   592    590             p->rJD += (r - y)*30.0;
   593    591           }
   594    592         }else if( n==4 && strcmp(z,"year")==0 ){
   595         -        computeYMD(p);
   596         -        computeHMS(p);
          593  +        computeYMD_HMS(p);
   597    594           p->Y += r;
   598    595           p->validJD = 0;
   599    596           computeJD(p);
   600    597         }else{
   601    598           rc = 1;
   602    599         }
   603         -      p->validYMD = 0;
   604         -      p->validHMS = 0;
   605         -      p->validTZ = 0;
          600  +      clearYMD_HMS_TZ(p);
   606    601         break;
   607    602       }
   608    603       default: {
   609    604         break;
   610    605       }
   611    606     }
   612    607     return rc;
................................................................................
   652    647   **
   653    648   ** Return YYYY-MM-DD HH:MM:SS
   654    649   */
   655    650   static void datetimeFunc(sqlite_func *context, int argc, const char **argv){
   656    651     DateTime x;
   657    652     if( isDate(argc, argv, &x)==0 ){
   658    653       char zBuf[100];
   659         -    computeYMD(&x);
   660         -    computeHMS(&x);
          654  +    computeYMD_HMS(&x);
   661    655       sprintf(zBuf, "%04d-%02d-%02d %02d:%02d:%02d",x.Y, x.M, x.D, x.h, x.m,
   662    656              (int)(x.s));
   663    657       sqlite_set_result_string(context, zBuf, -1);
   664    658     }
   665    659   }
   666    660   
   667    661   /*
................................................................................
   756    750     if( n<sizeof(zBuf) ){
   757    751       z = zBuf;
   758    752     }else{
   759    753       z = sqliteMalloc( n );
   760    754       if( z==0 ) return;
   761    755     }
   762    756     computeJD(&x);
   763         -  computeYMD(&x);
   764         -  computeHMS(&x);
          757  +  computeYMD_HMS(&x);
   765    758     for(i=j=0; zFmt[i]; i++){
   766    759       if( zFmt[i]!='%' ){
   767    760         z[j++] = zFmt[i];
   768    761       }else{
   769    762         i++;
   770    763         switch( zFmt[i] ){
   771    764           case 'd':  sprintf(&z[j],"%02d",x.D); j+=2; break;

Changes to src/hash.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 is the implementation of generic hash-tables
    13     13   ** used in SQLite.
    14     14   **
    15         -** $Id: hash.c,v 1.10 2003/05/12 23:06:53 drh Exp $
           15  +** $Id: hash.c,v 1.11 2004/01/08 02:17:33 drh Exp $
    16     16   */
    17     17   #include "sqliteInt.h"
    18     18   #include <assert.h>
    19     19   
    20     20   /* Turn bulk memory into a hash table object by initializing the
    21     21   ** fields of the Hash structure.
    22     22   **
................................................................................
    71     71   static int intHash(const void *pKey, int nKey){
    72     72     return nKey ^ (nKey<<8) ^ (nKey>>8);
    73     73   }
    74     74   static int intCompare(const void *pKey1, int n1, const void *pKey2, int n2){
    75     75     return n2 - n1;
    76     76   }
    77     77   
           78  +#if 0 /* NOT USED */
    78     79   /*
    79     80   ** Hash and comparison functions when the mode is SQLITE_HASH_POINTER
    80     81   */
    81     82   static int ptrHash(const void *pKey, int nKey){
    82     83     uptr x = Addr(pKey);
    83     84     return x ^ (x<<8) ^ (x>>8);
    84     85   }
    85     86   static int ptrCompare(const void *pKey1, int n1, const void *pKey2, int n2){
    86     87     if( pKey1==pKey2 ) return 0;
    87     88     if( pKey1<pKey2 ) return -1;
    88     89     return 1;
    89     90   }
           91  +#endif
    90     92   
    91     93   /*
    92     94   ** Hash and comparison functions when the mode is SQLITE_HASH_STRING
    93     95   */
    94     96   static int strHash(const void *pKey, int nKey){
    95     97     return sqliteHashNoCase((const char*)pKey, nKey); 
    96     98   }
................................................................................
   126    128   ** is a pointer to another function.  Specifically, the return value
   127    129   ** of hashFunction() is a pointer to a function that takes two parameters
   128    130   ** with types "const void*" and "int" and returns an "int".
   129    131   */
   130    132   static int (*hashFunction(int keyClass))(const void*,int){
   131    133     switch( keyClass ){
   132    134       case SQLITE_HASH_INT:     return &intHash;
   133         -    case SQLITE_HASH_POINTER: return &ptrHash;
          135  +    /* case SQLITE_HASH_POINTER: return &ptrHash; // NOT USED */
   134    136       case SQLITE_HASH_STRING:  return &strHash;
   135    137       case SQLITE_HASH_BINARY:  return &binHash;;
   136    138       default: break;
   137    139     }
   138    140     return 0;
   139    141   }
   140    142   
................................................................................
   143    145   **
   144    146   ** For help in interpreted the obscure C code in the function definition,
   145    147   ** see the header comment on the previous function.
   146    148   */
   147    149   static int (*compareFunction(int keyClass))(const void*,int,const void*,int){
   148    150     switch( keyClass ){
   149    151       case SQLITE_HASH_INT:     return &intCompare;
   150         -    case SQLITE_HASH_POINTER: return &ptrCompare;
          152  +    /* case SQLITE_HASH_POINTER: return &ptrCompare; // NOT USED */
   151    153       case SQLITE_HASH_STRING:  return &strCompare;
   152    154       case SQLITE_HASH_BINARY:  return &binCompare;
   153    155       default: break;
   154    156     }
   155    157     return 0;
   156    158   }
   157    159   

Changes to src/hash.h.

     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 is the header file for the generic hash-table implemenation
    13     13   ** used in SQLite.
    14     14   **
    15         -** $Id: hash.h,v 1.5 2002/06/08 23:25:09 drh Exp $
           15  +** $Id: hash.h,v 1.6 2004/01/08 02:17:33 drh Exp $
    16     16   */
    17     17   #ifndef _SQLITE_HASH_H_
    18     18   #define _SQLITE_HASH_H_
    19     19   
    20     20   /* Forward declarations of structures. */
    21     21   typedef struct Hash Hash;
    22     22   typedef struct HashElem HashElem;
................................................................................
    67     67   **   SQLITE_HASH_BINARY      pKey points to binary data nKey bytes long. 
    68     68   **                           memcmp() is used to compare keys.
    69     69   **
    70     70   ** A copy of the key is made for SQLITE_HASH_STRING and SQLITE_HASH_BINARY
    71     71   ** if the copyKey parameter to HashInit is 1.  
    72     72   */
    73     73   #define SQLITE_HASH_INT       1
    74         -#define SQLITE_HASH_POINTER   2
           74  +/* #define SQLITE_HASH_POINTER   2 // NOT USED */
    75     75   #define SQLITE_HASH_STRING    3
    76     76   #define SQLITE_HASH_BINARY    4
    77     77   
    78     78   /*
    79     79   ** Access routines.  To delete, insert a NULL pointer.
    80     80   */
    81     81   void sqliteHashInit(Hash*, int keytype, int copyKey);

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.66 2003/12/23 02:17:35 drh Exp $
           18  +** $Id: tokenize.c,v 1.67 2004/01/08 02:17:33 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   /*
    26     26   ** All the keywords of the SQL language are stored as in a hash
    27     27   ** table composed of instances of the following structure.
    28     28   */
    29     29   typedef struct Keyword Keyword;
    30     30   struct Keyword {
    31     31     char *zName;             /* The keyword name */
    32         -  u16 len;                 /* Number of characters in the keyword */
    33         -  u16 tokenType;           /* The token value for this keyword */
    34         -  Keyword *pNext;          /* Next keyword with the same hash */
           32  +  u8 tokenType;            /* Token value for this keyword */
           33  +  u8 len;                  /* Length of this keyword */
           34  +  u8 iNext;                /* Index in aKeywordTable[] of next with same hash */
    35     35   };
    36     36   
    37     37   /*
    38     38   ** These are the keywords
    39     39   */
    40     40   static Keyword aKeywordTable[] = {
    41         -  { "ABORT",             0, TK_ABORT,            0 },
    42         -  { "AFTER",             0, TK_AFTER,            0 },
    43         -  { "ALL",               0, TK_ALL,              0 },
    44         -  { "AND",               0, TK_AND,              0 },
    45         -  { "AS",                0, TK_AS,               0 },
    46         -  { "ASC",               0, TK_ASC,              0 },
    47         -  { "ATTACH",            0, TK_ATTACH,           0 },
    48         -  { "BEFORE",            0, TK_BEFORE,           0 },
    49         -  { "BEGIN",             0, TK_BEGIN,            0 },
    50         -  { "BETWEEN",           0, TK_BETWEEN,          0 },
    51         -  { "BY",                0, TK_BY,               0 },
    52         -  { "CASCADE",           0, TK_CASCADE,          0 },
    53         -  { "CASE",              0, TK_CASE,             0 },
    54         -  { "CHECK",             0, TK_CHECK,            0 },
    55         -  { "CLUSTER",           0, TK_CLUSTER,          0 },
    56         -  { "COLLATE",           0, TK_COLLATE,          0 },
    57         -  { "COMMIT",            0, TK_COMMIT,           0 },
    58         -  { "CONFLICT",          0, TK_CONFLICT,         0 },
    59         -  { "CONSTRAINT",        0, TK_CONSTRAINT,       0 },
    60         -  { "COPY",              0, TK_COPY,             0 },
    61         -  { "CREATE",            0, TK_CREATE,           0 },
    62         -  { "CROSS",             0, TK_JOIN_KW,          0 },
    63         -  { "DATABASE",          0, TK_DATABASE,         0 },
    64         -  { "DEFAULT",           0, TK_DEFAULT,          0 },
    65         -  { "DEFERRED",          0, TK_DEFERRED,         0 },
    66         -  { "DEFERRABLE",        0, TK_DEFERRABLE,       0 },
    67         -  { "DELETE",            0, TK_DELETE,           0 },
    68         -  { "DELIMITERS",        0, TK_DELIMITERS,       0 },
    69         -  { "DESC",              0, TK_DESC,             0 },
    70         -  { "DETACH",            0, TK_DETACH,           0 },
    71         -  { "DISTINCT",          0, TK_DISTINCT,         0 },
    72         -  { "DROP",              0, TK_DROP,             0 },
    73         -  { "END",               0, TK_END,              0 },
    74         -  { "EACH",              0, TK_EACH,             0 },
    75         -  { "ELSE",              0, TK_ELSE,             0 },
    76         -  { "EXCEPT",            0, TK_EXCEPT,           0 },
    77         -  { "EXPLAIN",           0, TK_EXPLAIN,          0 },
    78         -  { "FAIL",              0, TK_FAIL,             0 },
    79         -  { "FOR",               0, TK_FOR,              0 },
    80         -  { "FOREIGN",           0, TK_FOREIGN,          0 },
    81         -  { "FROM",              0, TK_FROM,             0 },
    82         -  { "FULL",              0, TK_JOIN_KW,          0 },
    83         -  { "GLOB",              0, TK_GLOB,             0 },
    84         -  { "GROUP",             0, TK_GROUP,            0 },
    85         -  { "HAVING",            0, TK_HAVING,           0 },
    86         -  { "IGNORE",            0, TK_IGNORE,           0 },
    87         -  { "IMMEDIATE",         0, TK_IMMEDIATE,        0 },
    88         -  { "IN",                0, TK_IN,               0 },
    89         -  { "INDEX",             0, TK_INDEX,            0 },
    90         -  { "INITIALLY",         0, TK_INITIALLY,        0 },
    91         -  { "INNER",             0, TK_JOIN_KW,          0 },
    92         -  { "INSERT",            0, TK_INSERT,           0 },
    93         -  { "INSTEAD",           0, TK_INSTEAD,          0 },
    94         -  { "INTERSECT",         0, TK_INTERSECT,        0 },
    95         -  { "INTO",              0, TK_INTO,             0 },
    96         -  { "IS",                0, TK_IS,               0 },
    97         -  { "ISNULL",            0, TK_ISNULL,           0 },
    98         -  { "JOIN",              0, TK_JOIN,             0 },
    99         -  { "KEY",               0, TK_KEY,              0 },
   100         -  { "LEFT",              0, TK_JOIN_KW,          0 },
   101         -  { "LIKE",              0, TK_LIKE,             0 },
   102         -  { "LIMIT",             0, TK_LIMIT,            0 },
   103         -  { "MATCH",             0, TK_MATCH,            0 },
   104         -  { "NATURAL",           0, TK_JOIN_KW,          0 },
   105         -  { "NOT",               0, TK_NOT,              0 },
   106         -  { "NOTNULL",           0, TK_NOTNULL,          0 },
   107         -  { "NULL",              0, TK_NULL,             0 },
   108         -  { "OF",                0, TK_OF,               0 },
   109         -  { "OFFSET",            0, TK_OFFSET,           0 },
   110         -  { "ON",                0, TK_ON,               0 },
   111         -  { "OR",                0, TK_OR,               0 },
   112         -  { "ORDER",             0, TK_ORDER,            0 },
   113         -  { "OUTER",             0, TK_JOIN_KW,          0 },
   114         -  { "PRAGMA",            0, TK_PRAGMA,           0 },
   115         -  { "PRIMARY",           0, TK_PRIMARY,          0 },
   116         -  { "RAISE",             0, TK_RAISE,            0 },
   117         -  { "REFERENCES",        0, TK_REFERENCES,       0 },
   118         -  { "REPLACE",           0, TK_REPLACE,          0 },
   119         -  { "RESTRICT",          0, TK_RESTRICT,         0 },
   120         -  { "RIGHT",             0, TK_JOIN_KW,          0 },
   121         -  { "ROLLBACK",          0, TK_ROLLBACK,         0 },
   122         -  { "ROW",               0, TK_ROW,              0 },
   123         -  { "SELECT",            0, TK_SELECT,           0 },
   124         -  { "SET",               0, TK_SET,              0 },
   125         -  { "STATEMENT",         0, TK_STATEMENT,        0 },
   126         -  { "TABLE",             0, TK_TABLE,            0 },
   127         -  { "TEMP",              0, TK_TEMP,             0 },
   128         -  { "TEMPORARY",         0, TK_TEMP,             0 },
   129         -  { "THEN",              0, TK_THEN,             0 },
   130         -  { "TRANSACTION",       0, TK_TRANSACTION,      0 },
   131         -  { "TRIGGER",           0, TK_TRIGGER,          0 },
   132         -  { "UNION",             0, TK_UNION,            0 },
   133         -  { "UNIQUE",            0, TK_UNIQUE,           0 },
   134         -  { "UPDATE",            0, TK_UPDATE,           0 },
   135         -  { "USING",             0, TK_USING,            0 },
   136         -  { "VACUUM",            0, TK_VACUUM,           0 },
   137         -  { "VALUES",            0, TK_VALUES,           0 },
   138         -  { "VIEW",              0, TK_VIEW,             0 },
   139         -  { "WHEN",              0, TK_WHEN,             0 },
   140         -  { "WHERE",             0, TK_WHERE,            0 },
           41  +  { "ABORT",             TK_ABORT,        },
           42  +  { "AFTER",             TK_AFTER,        },
           43  +  { "ALL",               TK_ALL,          },
           44  +  { "AND",               TK_AND,          },
           45  +  { "AS",                TK_AS,           },
           46  +  { "ASC",               TK_ASC,          },
           47  +  { "ATTACH",            TK_ATTACH,       },
           48  +  { "BEFORE",            TK_BEFORE,       },
           49  +  { "BEGIN",             TK_BEGIN,        },
           50  +  { "BETWEEN",           TK_BETWEEN,      },
           51  +  { "BY",                TK_BY,           },
           52  +  { "CASCADE",           TK_CASCADE,      },
           53  +  { "CASE",              TK_CASE,         },
           54  +  { "CHECK",             TK_CHECK,        },
           55  +  { "CLUSTER",           TK_CLUSTER,      },
           56  +  { "COLLATE",           TK_COLLATE,      },
           57  +  { "COMMIT",            TK_COMMIT,       },
           58  +  { "CONFLICT",          TK_CONFLICT,     },
           59  +  { "CONSTRAINT",        TK_CONSTRAINT,   },
           60  +  { "COPY",              TK_COPY,         },
           61  +  { "CREATE",            TK_CREATE,       },
           62  +  { "CROSS",             TK_JOIN_KW,      },
           63  +  { "DATABASE",          TK_DATABASE,     },
           64  +  { "DEFAULT",           TK_DEFAULT,      },
           65  +  { "DEFERRED",          TK_DEFERRED,     },
           66  +  { "DEFERRABLE",        TK_DEFERRABLE,   },
           67  +  { "DELETE",            TK_DELETE,       },
           68  +  { "DELIMITERS",        TK_DELIMITERS,   },
           69  +  { "DESC",              TK_DESC,         },
           70  +  { "DETACH",            TK_DETACH,       },
           71  +  { "DISTINCT",          TK_DISTINCT,     },
           72  +  { "DROP",              TK_DROP,         },
           73  +  { "END",               TK_END,          },
           74  +  { "EACH",              TK_EACH,         },
           75  +  { "ELSE",              TK_ELSE,         },
           76  +  { "EXCEPT",            TK_EXCEPT,       },
           77  +  { "EXPLAIN",           TK_EXPLAIN,      },
           78  +  { "FAIL",              TK_FAIL,         },
           79  +  { "FOR",               TK_FOR,          },
           80  +  { "FOREIGN",           TK_FOREIGN,      },
           81  +  { "FROM",              TK_FROM,         },
           82  +  { "FULL",              TK_JOIN_KW,      },
           83  +  { "GLOB",              TK_GLOB,         },
           84  +  { "GROUP",             TK_GROUP,        },
           85  +  { "HAVING",            TK_HAVING,       },
           86  +  { "IGNORE",            TK_IGNORE,       },
           87  +  { "IMMEDIATE",         TK_IMMEDIATE,    },
           88  +  { "IN",                TK_IN,           },
           89  +  { "INDEX",             TK_INDEX,        },
           90  +  { "INITIALLY",         TK_INITIALLY,    },
           91  +  { "INNER",             TK_JOIN_KW,      },
           92  +  { "INSERT",            TK_INSERT,       },
           93  +  { "INSTEAD",           TK_INSTEAD,      },
           94  +  { "INTERSECT",         TK_INTERSECT,    },
           95  +  { "INTO",              TK_INTO,         },
           96  +  { "IS",                TK_IS,           },
           97  +  { "ISNULL",            TK_ISNULL,       },
           98  +  { "JOIN",              TK_JOIN,         },
           99  +  { "KEY",               TK_KEY,          },
          100  +  { "LEFT",              TK_JOIN_KW,      },
          101  +  { "LIKE",              TK_LIKE,         },
          102  +  { "LIMIT",             TK_LIMIT,        },
          103  +  { "MATCH",             TK_MATCH,        },
          104  +  { "NATURAL",           TK_JOIN_KW,      },
          105  +  { "NOT",               TK_NOT,          },
          106  +  { "NOTNULL",           TK_NOTNULL,      },
          107  +  { "NULL",              TK_NULL,         },
          108  +  { "OF",                TK_OF,           },
          109  +  { "OFFSET",            TK_OFFSET,       },
          110  +  { "ON",                TK_ON,           },
          111  +  { "OR",                TK_OR,           },
          112  +  { "ORDER",             TK_ORDER,        },
          113  +  { "OUTER",             TK_JOIN_KW,      },
          114  +  { "PRAGMA",            TK_PRAGMA,       },
          115  +  { "PRIMARY",           TK_PRIMARY,      },
          116  +  { "RAISE",             TK_RAISE,        },
          117  +  { "REFERENCES",        TK_REFERENCES,   },
          118  +  { "REPLACE",           TK_REPLACE,      },
          119  +  { "RESTRICT",          TK_RESTRICT,     },
          120  +  { "RIGHT",             TK_JOIN_KW,      },
          121  +  { "ROLLBACK",          TK_ROLLBACK,     },
          122  +  { "ROW",               TK_ROW,          },
          123  +  { "SELECT",            TK_SELECT,       },
          124  +  { "SET",               TK_SET,          },
          125  +  { "STATEMENT",         TK_STATEMENT,    },
          126  +  { "TABLE",             TK_TABLE,        },
          127  +  { "TEMP",              TK_TEMP,         },
          128  +  { "TEMPORARY",         TK_TEMP,         },
          129  +  { "THEN",              TK_THEN,         },
          130  +  { "TRANSACTION",       TK_TRANSACTION,  },
          131  +  { "TRIGGER",           TK_TRIGGER,      },
          132  +  { "UNION",             TK_UNION,        },
          133  +  { "UNIQUE",            TK_UNIQUE,       },
          134  +  { "UPDATE",            TK_UPDATE,       },
          135  +  { "USING",             TK_USING,        },
          136  +  { "VACUUM",            TK_VACUUM,       },
          137  +  { "VALUES",            TK_VALUES,       },
          138  +  { "VIEW",              TK_VIEW,         },
          139  +  { "WHEN",              TK_WHEN,         },
          140  +  { "WHERE",             TK_WHERE,        },
   141    141   };
   142    142   
   143    143   /*
   144    144   ** This is the hash table
   145    145   */
   146         -#define KEY_HASH_SIZE 71
   147         -static Keyword *apHashTable[KEY_HASH_SIZE];
          146  +#define KEY_HASH_SIZE 101
          147  +static u8 aiHashTable[KEY_HASH_SIZE];
   148    148   
   149    149   
   150    150   /*
   151    151   ** This function looks up an identifier to determine if it is a
   152    152   ** keyword.  If it is a keyword, the token code of that keyword is 
   153    153   ** returned.  If the input is not a keyword, TK_ID is returned.
   154    154   */
   155    155   int sqliteKeywordCode(const char *z, int n){
   156         -  int h;
          156  +  int h, i;
   157    157     Keyword *p;
   158    158     static char needInit = 1;
   159    159     if( needInit ){
   160    160       /* Initialize the keyword hash table */
   161    161       sqliteOsEnterMutex();
   162    162       if( needInit ){
   163         -      int i;
   164         -      int n;
   165         -      n = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]);
   166         -      for(i=0; i<n; i++){
          163  +      int nk;
          164  +      nk = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]);
          165  +      for(i=0; i<nk; i++){
   167    166           aKeywordTable[i].len = strlen(aKeywordTable[i].zName);
   168    167           h = sqliteHashNoCase(aKeywordTable[i].zName, aKeywordTable[i].len);
   169    168           h %= KEY_HASH_SIZE;
   170         -        aKeywordTable[i].pNext = apHashTable[h];
   171         -        apHashTable[h] = &aKeywordTable[i];
          169  +        aKeywordTable[i].iNext = aiHashTable[h];
          170  +        aiHashTable[h] = i+1;
   172    171         }
   173    172         needInit = 0;
   174    173       }
   175    174       sqliteOsLeaveMutex();
   176    175     }
   177    176     h = sqliteHashNoCase(z, n) % KEY_HASH_SIZE;
   178         -  for(p=apHashTable[h]; p; p=p->pNext){
          177  +  for(i=aiHashTable[h]; i; i=p->iNext){
          178  +    p = &aKeywordTable[i-1];
   179    179       if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){
   180    180         return p->tokenType;
   181    181       }
   182    182     }
   183    183     return TK_ID;
   184    184   }
   185    185   
   186    186   
   187    187   /*
   188         -** If X is a character that can be used in an identifier then
   189         -** isIdChar[X] will be 1.  Otherwise isIdChar[X] will be 0.
          188  +** If X is a character that can be used in an identifier and
          189  +** X&0x80==0 then isIdChar[X] will be 1.  If X&0x80==0x80 then
          190  +** X is always an identifier character.  (Hence all UTF-8
          191  +** characters can be part of an identifier).  isIdChar[X] will
          192  +** be 0 for every character in the lower 128 ASCII characters
          193  +** that cannot be used as part of an identifier.
   190    194   **
   191    195   ** In this implementation, an identifier can be a string of
   192    196   ** alphabetic characters, digits, and "_" plus any character
   193    197   ** with the high-order bit set.  The latter rule means that
   194    198   ** any sequence of UTF-8 characters or characters taken from
   195    199   ** an extended ISO8859 character set can form an identifier.
   196    200   */
................................................................................
   200    204       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 1x */
   201    205       0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,  /* 2x */
   202    206       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0,  /* 3x */
   203    207       0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 4x */
   204    208       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1,  /* 5x */
   205    209       0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 6x */
   206    210       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0,  /* 7x */
   207         -    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 8x */
   208         -    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* 9x */
   209         -    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* Ax */
   210         -    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* Bx */
   211         -    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* Cx */
   212         -    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* Dx */
   213         -    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* Ex */
   214         -    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  /* Fx */
   215    211   };
   216    212   
   217    213   
   218    214   /*
   219    215   ** Return the length of the token that begins at z[0]. 
   220    216   ** Store the token type in *tokenType before returning.
   221    217   */
................................................................................
   376    372         return i;
   377    373       }
   378    374       case '?': {
   379    375         *tokenType = TK_VARIABLE;
   380    376         return 1;
   381    377       }
   382    378       default: {
   383         -      if( !isIdChar[*z] ){
          379  +      if( (*z&0x80)==0 && !isIdChar[*z] ){
   384    380           break;
   385    381         }
   386         -      for(i=1; isIdChar[z[i]]; i++){}
          382  +      for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){}
   387    383         *tokenType = sqliteKeywordCode((char*)z, i);
   388    384         return i;
   389    385       }
   390    386     }
   391    387     *tokenType = TK_ILLEGAL;
   392    388     return 1;
   393    389   }