/* ** 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. ** ************************************************************************* ** 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.66 2003/12/23 02:17:35 drh Exp $ */ #include "sqliteInt.h" #include "os.h" #include #include /* ** All the keywords of the SQL language are stored as in a hash ** table composed of instances of the following structure. */ typedef struct Keyword Keyword; struct Keyword { char *zName; /* The keyword name */ u16 len; /* Number of characters in the keyword */ u16 tokenType; /* The token value for this keyword */ Keyword *pNext; /* Next keyword with the same hash */ }; /* ** These are the keywords */ static Keyword aKeywordTable[] = { { "ABORT", 0, TK_ABORT, 0 }, { "AFTER", 0, TK_AFTER, 0 }, { "ALL", 0, TK_ALL, 0 }, { "AND", 0, TK_AND, 0 }, { "AS", 0, TK_AS, 0 }, { "ASC", 0, TK_ASC, 0 }, { "ATTACH", 0, TK_ATTACH, 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 }, { "COLLATE", 0, TK_COLLATE, 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 }, { "CROSS", 0, TK_JOIN_KW, 0 }, { "DATABASE", 0, TK_DATABASE, 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 }, { "DETACH", 0, TK_DETACH, 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_JOIN_KW, 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 }, { "INNER", 0, TK_JOIN_KW, 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 }, { "LEFT", 0, TK_JOIN_KW, 0 }, { "LIKE", 0, TK_LIKE, 0 }, { "LIMIT", 0, TK_LIMIT, 0 }, { "MATCH", 0, TK_MATCH, 0 }, { "NATURAL", 0, TK_JOIN_KW, 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 }, { "OUTER", 0, TK_JOIN_KW, 0 }, { "PRAGMA", 0, TK_PRAGMA, 0 }, { "PRIMARY", 0, TK_PRIMARY, 0 }, { "RAISE", 0, TK_RAISE, 0 }, { "REFERENCES", 0, TK_REFERENCES, 0 }, { "REPLACE", 0, TK_REPLACE, 0 }, { "RESTRICT", 0, TK_RESTRICT, 0 }, { "RIGHT", 0, TK_JOIN_KW, 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 }, { "TEMPORARY", 0, TK_TEMP, 0 }, { "THEN", 0, TK_THEN, 0 }, { "TRANSACTION", 0, TK_TRANSACTION, 0 }, { "TRIGGER", 0, TK_TRIGGER, 0 }, { "UNION", 0, TK_UNION, 0 }, { "UNIQUE", 0, TK_UNIQUE, 0 }, { "UPDATE", 0, TK_UPDATE, 0 }, { "USING", 0, TK_USING, 0 }, { "VACUUM", 0, TK_VACUUM, 0 }, { "VALUES", 0, TK_VALUES, 0 }, { "VIEW", 0, TK_VIEW, 0 }, { "WHEN", 0, TK_WHEN, 0 }, { "WHERE", 0, TK_WHERE, 0 }, }; /* ** This is the hash table */ #define KEY_HASH_SIZE 71 static Keyword *apHashTable[KEY_HASH_SIZE]; /* ** This function looks up an identifier to determine if it is a ** keyword. If it is a keyword, the token code of that keyword is ** returned. If the input is not a keyword, TK_ID is returned. */ int sqliteKeywordCode(const char *z, int n){ int h; Keyword *p; static char needInit = 1; if( needInit ){ /* Initialize the keyword hash table */ sqliteOsEnterMutex(); if( needInit ){ int i; int n; n = sizeof(aKeywordTable)/sizeof(aKeywordTable[0]); for(i=0; ipNext){ if( p->len==n && sqliteStrNICmp(p->zName, z, n)==0 ){ return p->tokenType; } } return TK_ID; } /* ** If X is a character that can be used in an identifier then ** isIdChar[X] will be 1. Otherwise isIdChar[X] will be 0. ** ** In this implementation, an identifier can be a string of ** alphabetic characters, digits, and "_" plus any character ** with the high-order bit set. The latter rule means that ** any sequence of UTF-8 characters or characters taken from ** an extended ISO8859 character set can form an identifier. */ static const char isIdChar[] = { /* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 8x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 9x */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Ax */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Bx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Cx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Dx */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Ex */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* Fx */ }; /* ** Return the length of the token that begins at z[0]. ** Store the token type in *tokenType before returning. */ static int sqliteGetToken(const unsigned char *z, int *tokenType){ int i; switch( *z ){ case ' ': case '\t': case '\n': case '\f': case '\r': { for(i=1; isspace(z[i]); i++){} *tokenType = TK_SPACE; return i; } case '-': { if( z[1]=='-' ){ for(i=2; z[i] && z[i]!='\n'; i++){} *tokenType = TK_COMMENT; return i; } *tokenType = TK_MINUS; return 1; } case '(': { *tokenType = TK_LP; return 1; } case ')': { *tokenType = TK_RP; return 1; } case ';': { *tokenType = TK_SEMI; return 1; } case '+': { *tokenType = TK_PLUS; return 1; } case '*': { *tokenType = TK_STAR; return 1; } case '/': { if( z[1]!='*' || z[2]==0 ){ *tokenType = TK_SLASH; return 1; } for(i=3; z[i] && (z[i]!='/' || z[i-1]!='*'); i++){} if( z[i] ) i++; *tokenType = TK_COMMENT; return i; } case '%': { *tokenType = TK_REM; return 1; } case '=': { *tokenType = TK_EQ; return 1 + (z[1]=='='); } case '<': { if( z[1]=='=' ){ *tokenType = TK_LE; return 2; }else if( z[1]=='>' ){ *tokenType = TK_NE; return 2; }else if( z[1]=='<' ){ *tokenType = TK_LSHIFT; return 2; }else{ *tokenType = TK_LT; return 1; } } case '>': { if( z[1]=='=' ){ *tokenType = TK_GE; return 2; }else if( z[1]=='>' ){ *tokenType = TK_RSHIFT; return 2; }else{ *tokenType = TK_GT; return 1; } } case '!': { if( z[1]!='=' ){ *tokenType = TK_ILLEGAL; return 2; }else{ *tokenType = TK_NE; return 2; } } case '|': { if( z[1]!='|' ){ *tokenType = TK_BITOR; return 1; }else{ *tokenType = TK_CONCAT; return 2; } } case ',': { *tokenType = TK_COMMA; return 1; } case '&': { *tokenType = TK_BITAND; return 1; } case '~': { *tokenType = TK_BITNOT; return 1; } case '\'': case '"': { int delim = z[0]; for(i=1; z[i]; i++){ if( z[i]==delim ){ if( z[i+1]==delim ){ i++; }else{ break; } } } if( z[i] ) i++; *tokenType = TK_STRING; return i; } case '.': { *tokenType = TK_DOT; return 1; } case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { *tokenType = TK_INTEGER; for(i=1; isdigit(z[i]); i++){} if( z[i]=='.' && isdigit(z[i+1]) ){ i += 2; while( isdigit(z[i]) ){ i++; } *tokenType = TK_FLOAT; } if( (z[i]=='e' || z[i]=='E') && ( isdigit(z[i+1]) || ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2])) ) ){ i += 2; while( isdigit(z[i]) ){ i++; } *tokenType = TK_FLOAT; } return i; } case '[': { for(i=1; z[i] && z[i-1]!=']'; i++){} *tokenType = TK_ID; return i; } case '?': { *tokenType = TK_VARIABLE; return 1; } default: { if( !isIdChar[*z] ){ break; } for(i=1; isIdChar[z[i]]; i++){} *tokenType = sqliteKeywordCode((char*)z, i); return i; } } *tokenType = TK_ILLEGAL; return 1; } /* ** Run the parser on the given SQL string. The parser structure is ** passed in. An SQLITE_ status code is returned. If an error occurs ** and pzErrMsg!=NULL then an error message might be written into ** memory obtained from malloc() and *pzErrMsg made to point to that ** error message. Or maybe not. */ int sqliteRunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ int nErr = 0; int i; void *pEngine; int tokenType; int lastTokenParsed = -1; sqlite *db = pParse->db; extern void *sqliteParserAlloc(void*(*)(int)); extern void sqliteParserFree(void*, void(*)(void*)); extern int sqliteParser(void*, int, Token, Parse*); db->flags &= ~SQLITE_Interrupt; pParse->rc = SQLITE_OK; i = 0; pEngine = sqliteParserAlloc((void*(*)(int))malloc); if( pEngine==0 ){ sqliteSetString(pzErrMsg, "out of memory", (char*)0); return 1; } pParse->sLastToken.dyn = 0; pParse->zTail = zSql; while( sqlite_malloc_failed==0 && zSql[i]!=0 ){ assert( i>=0 ); pParse->sLastToken.z = &zSql[i]; assert( pParse->sLastToken.dyn==0 ); pParse->sLastToken.n = sqliteGetToken((unsigned char*)&zSql[i], &tokenType); i += pParse->sLastToken.n; switch( tokenType ){ case TK_SPACE: case TK_COMMENT: { if( (db->flags & SQLITE_Interrupt)!=0 ){ pParse->rc = SQLITE_INTERRUPT; sqliteSetString(pzErrMsg, "interrupt", (char*)0); goto abort_parse; } break; } case TK_ILLEGAL: { sqliteSetNString(pzErrMsg, "unrecognized token: \"", -1, pParse->sLastToken.z, pParse->sLastToken.n, "\"", 1, 0); nErr++; goto abort_parse; } case TK_SEMI: { pParse->zTail = &zSql[i]; /* Fall thru into the default case */ } default: { sqliteParser(pEngine, tokenType, pParse->sLastToken, pParse); lastTokenParsed = tokenType; if( pParse->rc!=SQLITE_OK ){ goto abort_parse; } break; } } } abort_parse: if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ if( lastTokenParsed!=TK_SEMI ){ sqliteParser(pEngine, TK_SEMI, pParse->sLastToken, pParse); pParse->zTail = &zSql[i]; } sqliteParser(pEngine, 0, pParse->sLastToken, pParse); } sqliteParserFree(pEngine, free); if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ sqliteSetString(&pParse->zErrMsg, sqlite_error_string(pParse->rc), (char*)0); } if( pParse->zErrMsg ){ if( pzErrMsg && *pzErrMsg==0 ){ *pzErrMsg = pParse->zErrMsg; }else{ sqliteFree(pParse->zErrMsg); } pParse->zErrMsg = 0; if( !nErr ) nErr++; } if( pParse->pVdbe && (pParse->useCallback || pParse->nErr>0) ){ sqliteVdbeDelete(pParse->pVdbe); pParse->pVdbe = 0; } if( pParse->pNewTable ){ sqliteDeleteTable(pParse->db, pParse->pNewTable); pParse->pNewTable = 0; } if( pParse->pNewTrigger ){ sqliteDeleteTrigger(pParse->pNewTrigger); pParse->pNewTrigger = 0; } if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ pParse->rc = SQLITE_ERROR; } return nErr; } /* ** Token types used by the sqlite_complete() routine. See the header ** comments on that procedure for additional information. */ #define tkEXPLAIN 0 #define tkCREATE 1 #define tkTEMP 2 #define tkTRIGGER 3 #define tkEND 4 #define tkSEMI 5 #define tkWS 6 #define tkOTHER 7 /* ** Return TRUE if the given SQL string ends in a semicolon. ** ** Special handling is require for CREATE TRIGGER statements. ** Whenever the CREATE TRIGGER keywords are seen, the statement ** must end with ";END;". ** ** This implementation uses a state machine with 7 states: ** ** (0) START At the beginning or end of an SQL statement. This routine ** returns 1 if it ends in the START state and 0 if it ends ** in any other state. ** ** (1) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (2) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (3) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** ** (4) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** ** (5) SEMI We've seen the first semicolon in the ";END;" that occurs at ** the end of a trigger definition. ** ** (6) END We've seen the ";END" of the ";END;" that occurs at the end ** of a trigger difinition. ** ** Transitions between states above are determined by tokens extracted ** from the input. The following tokens are significant: ** ** (0) tkEXPLAIN The "explain" keyword. ** (1) tkCREATE The "create" keyword. ** (2) tkTEMP The "temp" or "temporary" keyword. ** (3) tkTRIGGER The "trigger" keyword. ** (4) tkEND The "end" keyword. ** (5) tkSEMI A semicolon. ** (6) tkWS Whitespace ** (7) tkOTHER Any other SQL token. ** ** Whitespace never causes a state transition and is always ignored. */ int sqlite_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ /* The following matrix defines the transition from one state to another ** according to what token is seen. trans[state][token] returns the ** next state. */ static const u8 trans[7][8] = { /* Token: */ /* State: ** EXPLAIN CREATE TEMP TRIGGER END SEMI WS OTHER */ /* 0 START: */ { 1, 2, 3, 3, 3, 0, 0, 3, }, /* 1 EXPLAIN: */ { 3, 2, 3, 3, 3, 0, 1, 3, }, /* 2 CREATE: */ { 3, 3, 2, 4, 3, 0, 2, 3, }, /* 3 NORMAL: */ { 3, 3, 3, 3, 3, 0, 3, 3, }, /* 4 TRIGGER: */ { 4, 4, 4, 4, 4, 5, 4, 4, }, /* 5 SEMI: */ { 4, 4, 4, 4, 6, 5, 5, 4, }, /* 6 END: */ { 4, 4, 4, 4, 4, 0, 6, 4, }, }; while( *zSql ){ switch( *zSql ){ case ';': { /* A semicolon */ token = tkSEMI; break; } case ' ': case '\r': case '\t': case '\n': case '\f': { /* White space is ignored */ token = tkWS; break; } case '/': { /* C-style comments */ if( zSql[1]!='*' ){ token = tkOTHER; break; } zSql += 2; while( zSql[0] && (zSql[0]!='*' || zSql[1]!='/') ){ zSql++; } if( zSql[0]==0 ) return 0; zSql++; token = tkWS; break; } case '-': { /* SQL-style comments from "--" to end of line */ if( zSql[1]!='-' ){ token = tkOTHER; break; } while( *zSql && *zSql!='\n' ){ zSql++; } if( *zSql==0 ) return state==0; token = tkWS; break; } case '[': { /* Microsoft-style identifiers in [...] */ zSql++; while( *zSql && *zSql!=']' ){ zSql++; } if( *zSql==0 ) return 0; token = tkOTHER; break; } case '"': /* single- and double-quoted strings */ case '\'': { int c = *zSql; zSql++; while( *zSql && *zSql!=c ){ zSql++; } if( *zSql==0 ) return 0; token = tkOTHER; break; } default: { if( isIdChar[(u8)*zSql] ){ /* Keywords and unquoted identifiers */ int nId; for(nId=1; isIdChar[(u8)zSql[nId]]; nId++){} switch( *zSql ){ case 'c': case 'C': { if( nId==6 && sqliteStrNICmp(zSql, "create", 6)==0 ){ token = tkCREATE; }else{ token = tkOTHER; } break; } case 't': case 'T': { if( nId==7 && sqliteStrNICmp(zSql, "trigger", 7)==0 ){ token = tkTRIGGER; }else if( nId==4 && sqliteStrNICmp(zSql, "temp", 4)==0 ){ token = tkTEMP; }else if( nId==9 && sqliteStrNICmp(zSql, "temporary", 9)==0 ){ token = tkTEMP; }else{ token = tkOTHER; } break; } case 'e': case 'E': { if( nId==3 && sqliteStrNICmp(zSql, "end", 3)==0 ){ token = tkEND; }else if( nId==7 && sqliteStrNICmp(zSql, "explain", 7)==0 ){ token = tkEXPLAIN; }else{ token = tkOTHER; } break; } default: { token = tkOTHER; break; } } zSql += nId-1; }else{ /* Operators and special symbols */ token = tkOTHER; } break; } } state = trans[state][token]; zSql++; } return state==0; }