1 2 #pragma ident "%Z%%M% %I% %E% SMI" 3 4 /* 5 ** 2001 September 15 6 ** 7 ** The author disclaims copyright to this source code. In place of 8 ** a legal notice, here is a blessing: 9 ** 10 ** May you do good and not evil. 11 ** May you find forgiveness for yourself and forgive others. 12 ** May you share freely, never taking more than you give. 13 ** 14 ************************************************************************* 15 ** An tokenizer for SQL 16 ** 17 ** This file contains C code that splits an SQL input string up into 18 ** individual tokens and sends those tokens one-by-one over to the 19 ** parser for analysis. 20 ** 21 ** $Id: tokenize.c,v 1.68 2004/02/14 23:59:58 drh Exp $ 22 */ 23 #include "sqliteInt.h" 24 #include "os.h" 25 #include <ctype.h> 26 #include <stdlib.h> 27 28 /* 29 ** All the keywords of the SQL language are stored as in a hash 30 ** table composed of instances of the following structure. 31 */ 32 typedef struct Keyword Keyword; 33 struct Keyword { 34 char *zName; /* The keyword name */ 35 u8 tokenType; /* Token value for this keyword */ 36 u8 len; /* Length of this keyword */ 37 u8 iNext; /* Index in aKeywordTable[] of next with same hash */ 38 }; 39 40 /* 41 ** These are the keywords 42 */ 43 static Keyword aKeywordTable[] = { 44 { "ABORT", TK_ABORT, }, 45 { "AFTER", TK_AFTER, }, 46 { "ALL", TK_ALL, }, 47 { "AND", TK_AND, }, 48 { "AS", TK_AS, }, 49 { "ASC", TK_ASC, }, 50 { "ATTACH", TK_ATTACH, }, 51 { "BEFORE", TK_BEFORE, }, 52 { "BEGIN", TK_BEGIN, }, 53 { "BETWEEN", TK_BETWEEN, }, 54 { "BY", TK_BY, }, 55 { "CASCADE", TK_CASCADE, }, 56 { "CASE", TK_CASE, }, 57 { "CHECK", TK_CHECK, }, 58 { "CLUSTER", TK_CLUSTER, }, 59 { "COLLATE", TK_COLLATE, }, 60 { "COMMIT", TK_COMMIT, }, 61 { "CONFLICT", TK_CONFLICT, }, 62 { "CONSTRAINT", TK_CONSTRAINT, }, 63 { "COPY", TK_COPY, }, 64 { "CREATE", TK_CREATE, }, 65 { "CROSS", TK_JOIN_KW, }, 66 { "DATABASE", TK_DATABASE, }, 67 { "DEFAULT", TK_DEFAULT, }, 68 { "DEFERRED", TK_DEFERRED, }, 69 { "DEFERRABLE", TK_DEFERRABLE, }, 70 { "DELETE", TK_DELETE, }, 71 { "DELIMITERS", TK_DELIMITERS, }, 72 { "DESC", TK_DESC, }, 73 { "DETACH", TK_DETACH, }, 74 { "DISTINCT", TK_DISTINCT, }, 75 { "DROP", TK_DROP, }, 76 { "END", TK_END, }, 77 { "EACH", TK_EACH, }, 78 { "ELSE", TK_ELSE, }, 79 { "EXCEPT", TK_EXCEPT, }, 80 { "EXPLAIN", TK_EXPLAIN, }, 81 { "FAIL", TK_FAIL, }, 82 { "FOR", TK_FOR, }, 83 { "FOREIGN", TK_FOREIGN, }, 84 { "FROM", TK_FROM, }, 85 { "FULL", TK_JOIN_KW, }, 86 { "GLOB", TK_GLOB, }, 87 { "GROUP", TK_GROUP, }, 88 { "HAVING", TK_HAVING, }, 89 { "IGNORE", TK_IGNORE, }, 90 { "IMMEDIATE", TK_IMMEDIATE, }, 91 { "IN", TK_IN, }, 92 { "INDEX", TK_INDEX, }, 93 { "INITIALLY", TK_INITIALLY, }, 94 { "INNER", TK_JOIN_KW, }, 95 { "INSERT", TK_INSERT, }, 96 { "INSTEAD", TK_INSTEAD, }, 97 { "INTERSECT", TK_INTERSECT, }, 98 { "INTO", TK_INTO, }, 99 { "IS", TK_IS, }, 100 { "ISNULL", TK_ISNULL, }, 101 { "JOIN", TK_JOIN, }, 102 { "KEY", TK_KEY, }, 103 { "LEFT", TK_JOIN_KW, }, 104 { "LIKE", TK_LIKE, }, 105 { "LIMIT", TK_LIMIT, }, 106 { "MATCH", TK_MATCH, }, 107 { "NATURAL", TK_JOIN_KW, }, 108 { "NOT", TK_NOT, }, 109 { "NOTNULL", TK_NOTNULL, }, 110 { "NULL", TK_NULL, }, 111 { "OF", TK_OF, }, 112 { "OFFSET", TK_OFFSET, }, 113 { "ON", TK_ON, }, 114 { "OR", TK_OR, }, 115 { "ORDER", TK_ORDER, }, 116 { "OUTER", TK_JOIN_KW, }, 117 { "PRAGMA", TK_PRAGMA, }, 118 { "PRIMARY", TK_PRIMARY, }, 119 { "RAISE", TK_RAISE, }, 120 { "REFERENCES", TK_REFERENCES, }, 121 { "REPLACE", TK_REPLACE, }, 122 { "RESTRICT", TK_RESTRICT, }, 123 { "RIGHT", TK_JOIN_KW, }, 124 { "ROLLBACK", TK_ROLLBACK, }, 125 { "ROW", TK_ROW, }, 126 { "SELECT", TK_SELECT, }, 127 { "SET", TK_SET, }, 128 { "STATEMENT", TK_STATEMENT, }, 129 { "TABLE", TK_TABLE, }, 130 { "TEMP", TK_TEMP, }, 131 { "TEMPORARY", TK_TEMP, }, 132 { "THEN", TK_THEN, }, 133 { "TRANSACTION", TK_TRANSACTION, }, 134 { "TRIGGER", TK_TRIGGER, }, 135 { "UNION", TK_UNION, }, 136 { "UNIQUE", TK_UNIQUE, }, 137 { "UPDATE", TK_UPDATE, }, 138 { "USING", TK_USING, }, 139 { "VACUUM", TK_VACUUM, }, 140 { "VALUES", TK_VALUES, }, 141 { "VIEW", TK_VIEW, }, 142 { "WHEN", TK_WHEN, }, 143 { "WHERE", TK_WHERE, }, 144 }; 145 146 /* 147 ** This is the hash table 148 */ 149 #define KEY_HASH_SIZE 101 150 static u8 aiHashTable[KEY_HASH_SIZE]; 151 152 153 /* 154 ** This function looks up an identifier to determine if it is a 155 ** keyword. If it is a keyword, the token code of that keyword is 156 ** returned. If the input is not a keyword, TK_ID is returned. 157 */ 158 int sqliteKeywordCode(const char *z, int n){ 159 int h, i; 160 Keyword *p; 161 static char needInit = 1; 162 if( needInit ){ 163 /* Initialize the keyword hash table */ 164 sqliteOsEnterMutex(); 165 if( needInit ){ 166 int nk; 167 nk = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]); 168 for(i=0; i<nk; i++){ 169 aKeywordTable[i].len = strlen(aKeywordTable[i].zName); 170 h = sqliteHashNoCase(aKeywordTable[i].zName, aKeywordTable[i].len); 171 h %= KEY_HASH_SIZE; 172 aKeywordTable[i].iNext = aiHashTable[h]; 173 aiHashTable[h] = i+1; 174 } 175 needInit = 0; 176 } 177 sqliteOsLeaveMutex(); 178 } 179 h = sqliteHashNoCase(z, n) % KEY_HASH_SIZE; 180 for(i=aiHashTable[h]; i; i=p->iNext){ 181 p = &aKeywordTable[i-1]; 182 if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){ 183 return p->tokenType; 184 } 185 } 186 return TK_ID; 187 } 188 189 190 /* 191 ** If X is a character that can be used in an identifier and 192 ** X&0x80==0 then isIdChar[X] will be 1. If X&0x80==0x80 then 193 ** X is always an identifier character. (Hence all UTF-8 194 ** characters can be part of an identifier). isIdChar[X] will 195 ** be 0 for every character in the lower 128 ASCII characters 196 ** that cannot be used as part of an identifier. 197 ** 198 ** In this implementation, an identifier can be a string of 199 ** alphabetic characters, digits, and "_" plus any character 200 ** with the high-order bit set. The latter rule means that 201 ** any sequence of UTF-8 characters or characters taken from 202 ** an extended ISO8859 character set can form an identifier. 203 */ 204 static const char isIdChar[] = { 205 /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ 206 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ 207 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ 208 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ 209 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ 210 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ 211 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ 212 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ 213 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ 214 }; 215 216 217 /* 218 ** Return the length of the token that begins at z[0]. 219 ** Store the token type in *tokenType before returning. 220 */ 221 static int sqliteGetToken(const unsigned char *z, int *tokenType){ 222 int i; 223 switch( *z ){ 224 case ' ': case '\t': case '\n': case '\f': case '\r': { 225 for(i=1; isspace(z[i]); i++){} 226 *tokenType = TK_SPACE; 227 return i; 228 } 229 case '-': { 230 if( z[1]=='-' ){ 231 for(i=2; z[i] && z[i]!='\n'; i++){} 232 *tokenType = TK_COMMENT; 233 return i; 234 } 235 *tokenType = TK_MINUS; 236 return 1; 237 } 238 case '(': { 239 *tokenType = TK_LP; 240 return 1; 241 } 242 case ')': { 243 *tokenType = TK_RP; 244 return 1; 245 } 246 case ';': { 247 *tokenType = TK_SEMI; 248 return 1; 249 } 250 case '+': { 251 *tokenType = TK_PLUS; 252 return 1; 253 } 254 case '*': { 255 *tokenType = TK_STAR; 256 return 1; 257 } 258 case '/': { 259 if( z[1]!='*' || z[2]==0 ){ 260 *tokenType = TK_SLASH; 261 return 1; 262 } 263 for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){} 264 if( z[i] ) i++; 265 *tokenType = TK_COMMENT; 266 return i; 267 } 268 case '%': { 269 *tokenType = TK_REM; 270 return 1; 271 } 272 case '=': { 273 *tokenType = TK_EQ; 274 return 1 + (z[1]=='='); 275 } 276 case '<': { 277 if( z[1]=='=' ){ 278 *tokenType = TK_LE; 279 return 2; 280 }else if( z[1]=='>' ){ 281 *tokenType = TK_NE; 282 return 2; 283 }else if( z[1]=='<' ){ 284 *tokenType = TK_LSHIFT; 285 return 2; 286 }else{ 287 *tokenType = TK_LT; 288 return 1; 289 } 290 } 291 case '>': { 292 if( z[1]=='=' ){ 293 *tokenType = TK_GE; 294 return 2; 295 }else if( z[1]=='>' ){ 296 *tokenType = TK_RSHIFT; 297 return 2; 298 }else{ 299 *tokenType = TK_GT; 300 return 1; 301 } 302 } 303 case '!': { 304 if( z[1]!='=' ){ 305 *tokenType = TK_ILLEGAL; 306 return 2; 307 }else{ 308 *tokenType = TK_NE; 309 return 2; 310 } 311 } 312 case '|': { 313 if( z[1]!='|' ){ 314 *tokenType = TK_BITOR; 315 return 1; 316 }else{ 317 *tokenType = TK_CONCAT; 318 return 2; 319 } 320 } 321 case ',': { 322 *tokenType = TK_COMMA; 323 return 1; 324 } 325 case '&': { 326 *tokenType = TK_BITAND; 327 return 1; 328 } 329 case '~': { 330 *tokenType = TK_BITNOT; 331 return 1; 332 } 333 case '\'': case '"': { 334 int delim = z[0]; 335 for(i=1; z[i]; i++){ 336 if( z[i]==delim ){ 337 if( z[i+1]==delim ){ 338 i++; 339 }else{ 340 break; 341 } 342 } 343 } 344 if( z[i] ) i++; 345 *tokenType = TK_STRING; 346 return i; 347 } 348 case '.': { 349 *tokenType = TK_DOT; 350 return 1; 351 } 352 case '0': case '1': case '2': case '3': case '4': 353 case '5': case '6': case '7': case '8': case '9': { 354 *tokenType = TK_INTEGER; 355 for(i=1; isdigit(z[i]); i++){} 356 if( z[i]=='.' && isdigit(z[i+1]) ){ 357 i += 2; 358 while( isdigit(z[i]) ){ i++; } 359 *tokenType = TK_FLOAT; 360 } 361 if( (z[i]=='e' || z[i]=='E') && 362 ( isdigit(z[i+1]) 363 || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2])) 364 ) 365 ){ 366 i += 2; 367 while( isdigit(z[i]) ){ i++; } 368 *tokenType = TK_FLOAT; 369 } 370 return i; 371 } 372 case '[': { 373 for(i=1; z[i] && z[i-1]!=']'; i++){} 374 *tokenType = TK_ID; 375 return i; 376 } 377 case '?': { 378 *tokenType = TK_VARIABLE; 379 return 1; 380 } 381 default: { 382 if( (*z&0x80)==0 && !isIdChar[*z] ){ 383 break; 384 } 385 for(i=1; (z[i]&0x80)!=0 || isIdChar[z[i]]; i++){} 386 *tokenType = sqliteKeywordCode((char*)z, i); 387 return i; 388 } 389 } 390 *tokenType = TK_ILLEGAL; 391 return 1; 392 } 393 394 /* 395 ** Run the parser on the given SQL string. The parser structure is 396 ** passed in. An SQLITE_ status code is returned. If an error occurs 397 ** and pzErrMsg!=NULL then an error message might be written into 398 ** memory obtained from malloc() and *pzErrMsg made to point to that 399 ** error message. Or maybe not. 400 */ 401 int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ 402 int nErr = 0; 403 int i; 404 void *pEngine; 405 int tokenType; 406 int lastTokenParsed = -1; 407 sqlite *db = pParse->db; 408 extern void *sqliteParserAlloc(void*(*)(int)); 409 extern void sqliteParserFree(void*, void(*)(void*)); 410 extern int sqliteParser(void*, int, Token, Parse*); 411 412 db->flags &= ~SQLITE_Interrupt; 413 pParse->rc = SQLITE_OK; 414 i = 0; 415 pEngine = sqliteParserAlloc((void*(*)(int))malloc); 416 if( pEngine==0 ){ 417 sqliteSetString(pzErrMsg, "out of memory", (char*)0); 418 return 1; 419 } 420 pParse->sLastToken.dyn = 0; 421 pParse->zTail = zSql; 422 while( sqlite_malloc_failed==0 && zSql[i]!=0 ){ 423 assert( i>=0 ); 424 pParse->sLastToken.z = &zSql[i]; 425 assert( pParse->sLastToken.dyn==0 ); 426 pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType); 427 i += pParse->sLastToken.n; 428 switch( tokenType ){ 429 case TK_SPACE: 430 case TK_COMMENT: { 431 if( (db->flags & SQLITE_Interrupt)!=0 ){ 432 pParse->rc = SQLITE_INTERRUPT; 433 sqliteSetString(pzErrMsg, "interrupt", (char*)0); 434 goto abort_parse; 435 } 436 break; 437 } 438 case TK_ILLEGAL: { 439 sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, 440 pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0); 441 nErr++; 442 goto abort_parse; 443 } 444 case TK_SEMI: { 445 pParse->zTail = &zSql[i]; 446 /* Fall thru into the default case */ 447 } 448 default: { 449 sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse); 450 lastTokenParsed = tokenType; 451 if( pParse->rc!=SQLITE_OK ){ 452 goto abort_parse; 453 } 454 break; 455 } 456 } 457 } 458 abort_parse: 459 if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ 460 if( lastTokenParsed!=TK_SEMI ){ 461 sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse); 462 pParse->zTail = &zSql[i]; 463 } 464 sqliteParser(pEngine, 0, pParse->sLastToken, pParse); 465 } 466 sqliteParserFree(pEngine, free); 467 if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ 468 sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc), 469 (char*)0); 470 } 471 if( pParse->zErrMsg ){ 472 if( pzErrMsg && *pzErrMsg==0 ){ 473 *pzErrMsg = pParse->zErrMsg; 474 }else{ 475 sqliteFree(pParse->zErrMsg); 476 } 477 pParse->zErrMsg = 0; 478 if( !nErr ) nErr++; 479 } 480 if( pParse->pVdbe && pParse->nErr>0 ){ 481 sqliteVdbeDelete(pParse->pVdbe); 482 pParse->pVdbe = 0; 483 } 484 if( pParse->pNewTable ){ 485 sqliteDeleteTable(pParse->db, pParse->pNewTable); 486 pParse->pNewTable = 0; 487 } 488 if( pParse->pNewTrigger ){ 489 sqliteDeleteTrigger(pParse->pNewTrigger); 490 pParse->pNewTrigger = 0; 491 } 492 if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ 493 pParse->rc = SQLITE_ERROR; 494 } 495 return nErr; 496 } 497 498 /* 499 ** Token types used by the sqlite_complete() routine. See the header 500 ** comments on that procedure for additional information. 501 */ 502 #define tkEXPLAIN 0 503 #define tkCREATE 1 504 #define tkTEMP 2 505 #define tkTRIGGER 3 506 #define tkEND 4 507 #define tkSEMI 5 508 #define tkWS 6 509 #define tkOTHER 7 510 511 /* 512 ** Return TRUE if the given SQL string ends in a semicolon. 513 ** 514 ** Special handling is require for CREATE TRIGGER statements. 515 ** Whenever the CREATE TRIGGER keywords are seen, the statement 516 ** must end with ";END;". 517 ** 518 ** This implementation uses a state machine with 7 states: 519 ** 520 ** (0) START At the beginning or end of an SQL statement. This routine 521 ** returns 1 if it ends in the START state and 0 if it ends 522 ** in any other state. 523 ** 524 ** (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of 525 ** a statement. 526 ** 527 ** (2) CREATE The keyword CREATE has been seen at the beginning of a 528 ** statement, possibly preceeded by EXPLAIN and/or followed by 529 ** TEMP or TEMPORARY 530 ** 531 ** (3) NORMAL We are in the middle of statement which ends with a single 532 ** semicolon. 533 ** 534 ** (4) TRIGGER We are in the middle of a trigger definition that must be 535 ** ended by a semicolon, the keyword END, and another semicolon. 536 ** 537 ** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at 538 ** the end of a trigger definition. 539 ** 540 ** (6) END We've seen the ";END" of the ";END;" that occurs at the end 541 ** of a trigger difinition. 542 ** 543 ** Transitions between states above are determined by tokens extracted 544 ** from the input. The following tokens are significant: 545 ** 546 ** (0) tkEXPLAIN The "explain" keyword. 547 ** (1) tkCREATE The "create" keyword. 548 ** (2) tkTEMP The "temp" or "temporary" keyword. 549 ** (3) tkTRIGGER The "trigger" keyword. 550 ** (4) tkEND The "end" keyword. 551 ** (5) tkSEMI A semicolon. 552 ** (6) tkWS Whitespace 553 ** (7) tkOTHER Any other SQL token. 554 ** 555 ** Whitespace never causes a state transition and is always ignored. 556 */ 557 int sqlite_complete(const char *zSql){ 558 u8 state = 0; /* Current state, using numbers defined in header comment */ 559 u8 token; /* Value of the next token */ 560 561 /* The following matrix defines the transition from one state to another 562 ** according to what token is seen. trans[state][token] returns the 563 ** next state. 564 */ 565 static const u8 trans[7][8] = { 566 /* Token: */ 567 /* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */ 568 /* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, }, 569 /* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, }, 570 /* 2 CREATE: */ { 3, 3, 2, 4, 3, 0, 2, 3, }, 571 /* 3 NORMAL: */ { 3, 3, 3, 3, 3, 0, 3, 3, }, 572 /* 4 TRIGGER: */ { 4, 4, 4, 4, 4, 5, 4, 4, }, 573 /* 5 SEMI: */ { 4, 4, 4, 4, 6, 5, 5, 4, }, 574 /* 6 END: */ { 4, 4, 4, 4, 4, 0, 6, 4, }, 575 }; 576 577 while( *zSql ){ 578 switch( *zSql ){ 579 case ';': { /* A semicolon */ 580 token = tkSEMI; 581 break; 582 } 583 case ' ': 584 case '\r': 585 case '\t': 586 case '\n': 587 case '\f': { /* White space is ignored */ 588 token = tkWS; 589 break; 590 } 591 case '/': { /* C-style comments */ 592 if( zSql[1]!='*' ){ 593 token = tkOTHER; 594 break; 595 } 596 zSql += 2; 597 while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } 598 if( zSql[0]==0 ) return 0; 599 zSql++; 600 token = tkWS; 601 break; 602 } 603 case '-': { /* SQL-style comments from "--" to end of line */ 604 if( zSql[1]!='-' ){ 605 token = tkOTHER; 606 break; 607 } 608 while( *zSql && *zSql!='\n' ){ zSql++; } 609 if( *zSql==0 ) return state==0; 610 token = tkWS; 611 break; 612 } 613 case '[': { /* Microsoft-style identifiers in [...] */ 614 zSql++; 615 while( *zSql && *zSql!=']' ){ zSql++; } 616 if( *zSql==0 ) return 0; 617 token = tkOTHER; 618 break; 619 } 620 case '"': /* single- and double-quoted strings */ 621 case '\'': { 622 int c = *zSql; 623 zSql++; 624 while( *zSql && *zSql!=c ){ zSql++; } 625 if( *zSql==0 ) return 0; 626 token = tkOTHER; 627 break; 628 } 629 default: { 630 if( isIdChar[(u8)*zSql] ){ 631 /* Keywords and unquoted identifiers */ 632 int nId; 633 for(nId=1; isIdChar[(u8)zSql[nId]]; nId++){} 634 switch( *zSql ){ 635 case 'c': case 'C': { 636 if( nId==6 && sqliteStrNICmp(zSql, "create", 6)==0 ){ 637 token = tkCREATE; 638 }else{ 639 token = tkOTHER; 640 } 641 break; 642 } 643 case 't': case 'T': { 644 if( nId==7 && sqliteStrNICmp(zSql, "trigger", 7)==0 ){ 645 token = tkTRIGGER; 646 }else if( nId==4 && sqliteStrNICmp(zSql, "temp", 4)==0 ){ 647 token = tkTEMP; 648 }else if( nId==9 && sqliteStrNICmp(zSql, "temporary", 9)==0 ){ 649 token = tkTEMP; 650 }else{ 651 token = tkOTHER; 652 } 653 break; 654 } 655 case 'e': case 'E': { 656 if( nId==3 && sqliteStrNICmp(zSql, "end", 3)==0 ){ 657 token = tkEND; 658 }else if( nId==7 && sqliteStrNICmp(zSql, "explain", 7)==0 ){ 659 token = tkEXPLAIN; 660 }else{ 661 token = tkOTHER; 662 } 663 break; 664 } 665 default: { 666 token = tkOTHER; 667 break; 668 } 669 } 670 zSql += nId-1; 671 }else{ 672 /* Operators and special symbols */ 673 token = tkOTHER; 674 } 675 break; 676 } 677 } 678 state = trans[state][token]; 679 zSql++; 680 } 681 return state==0; 682 } 683