diff options
author | Wez Furlong <wez@php.net> | 2003-06-04 22:40:00 +0000 |
---|---|---|
committer | Wez Furlong <wez@php.net> | 2003-06-04 22:40:00 +0000 |
commit | 80e7f7001d39add9010ba78be636245410b79c24 (patch) | |
tree | 23ae7f9f01ea9bb1add35b1ff85efa2421d05142 /ext/sqlite/libsqlite/src/tokenize.c | |
parent | 82a1818fdec3afe8e3a5cc8aa7171f4472ea1e4a (diff) | |
download | php-git-80e7f7001d39add9010ba78be636245410b79c24.tar.gz |
Update bundled library to version 2.8.2.
Make OnUpdateInt compatible with ZE2.
Fix the makefile fragment for non-gnu makes
Diffstat (limited to 'ext/sqlite/libsqlite/src/tokenize.c')
-rw-r--r-- | ext/sqlite/libsqlite/src/tokenize.c | 206 |
1 files changed, 197 insertions, 9 deletions
diff --git a/ext/sqlite/libsqlite/src/tokenize.c b/ext/sqlite/libsqlite/src/tokenize.c index f24da9e181..f053a75934 100644 --- a/ext/sqlite/libsqlite/src/tokenize.c +++ b/ext/sqlite/libsqlite/src/tokenize.c @@ -44,6 +44,7 @@ static Keyword aKeywordTable[] = { { "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 }, @@ -59,12 +60,14 @@ static Keyword aKeywordTable[] = { { "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 }, @@ -349,18 +352,15 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){ return i; } case '.': { - if( !isdigit(z[1]) ){ - *tokenType = TK_DOT; - return 1; - } - /* Fall thru into the next 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]=='.' ){ - i++; + if( z[i]=='.' && isdigit(z[i+1]) ){ + i += 2; while( isdigit(z[i]) ){ i++; } *tokenType = TK_FLOAT; } @@ -372,8 +372,6 @@ static int sqliteGetToken(const unsigned char *z, int *tokenType){ i += 2; while( isdigit(z[i]) ){ i++; } *tokenType = TK_FLOAT; - }else if( z[0]=='.' ){ - *tokenType = TK_FLOAT; } return i; } @@ -489,8 +487,198 @@ abort_parse: 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; +} |