Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Modified statement machine in sqlite3_complete() to return 0 on empty string. Added/updated tests for same. Ticket [356c885b0b]. |
---|---|
Downloads: | Tarball | ZIP archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
76eca7295cf7df4bef013af6c8c37251 |
User & Date: | shaneh 2009-12-17 22:17:39.000 |
Original Comment: | Modified statement machine in sqlite3_complete() to return 0 on empty string. Added/updated tests for same. Ticket 356c885b0b. |
References
2009-12-17
| ||
22:18 | • Ticket [356c885b0b] sqlite3_complete() should return 0 on empty string status still Fixed with 1 other change (artifact: 9743fa039c user: shane) | |
Context
2009-12-20
| ||
15:00 | Fix a problem in FTS3 phrase queries. Add tests to check that it really is fixed. (check-in: 956de051f4 user: dan tags: trunk) | |
2009-12-17
| ||
22:17 | Modified statement machine in sqlite3_complete() to return 0 on empty string. Added/updated tests for same. Ticket [356c885b0b]. (check-in: 76eca7295c user: shaneh tags: trunk) | |
22:12 | Fixed some TCL test cases to work if SQLITE_OMIT_TRIGGER is defined. (check-in: 85e3c73497 user: shaneh tags: trunk) | |
Changes
Changes to src/complete.c.
︙ | ︙ | |||
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 | /* ** Token types used by the sqlite3_complete() routine. See the header ** comments on that procedure for additional information. */ #define tkSEMI 0 #define tkWS 1 #define tkOTHER 2 #define tkEXPLAIN 3 #define tkCREATE 4 #define tkTEMP 5 #define tkTRIGGER 6 #define tkEND 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;". ** | > > | > > | | | | | | | | > | | > | | | | | | | | | > | | | 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 | /* ** Token types used by the sqlite3_complete() routine. See the header ** comments on that procedure for additional information. */ #define tkSEMI 0 #define tkWS 1 #define tkOTHER 2 #ifndef SQLITE_OMIT_TRIGGER #define tkEXPLAIN 3 #define tkCREATE 4 #define tkTEMP 5 #define tkTRIGGER 6 #define tkEND 7 #endif /* ** 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 8 states: ** ** (0) INVALID We have not yet seen a non-whitespace character. ** ** (1) 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. ** ** (2) NORMAL We are in the middle of statement which ends with a single ** semicolon. ** ** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of ** a statement. ** ** (4) CREATE The keyword CREATE has been seen at the beginning of a ** statement, possibly preceeded by EXPLAIN and/or followed by ** TEMP or TEMPORARY ** ** (5) TRIGGER We are in the middle of a trigger definition that must be ** ended by a semicolon, the keyword END, and another semicolon. ** ** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at ** the end of a trigger definition. ** ** (7) 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) tkSEMI A semicolon. ** (1) tkWS Whitespace. ** (2) tkOTHER Any other SQL token. ** (3) tkEXPLAIN The "explain" keyword. ** (4) tkCREATE The "create" keyword. ** (5) tkTEMP The "temp" or "temporary" keyword. ** (6) tkTRIGGER The "trigger" keyword. ** (7) tkEND The "end" keyword. ** ** Whitespace never causes a state transition and is always ignored. ** This means that a SQL string of all whitespace is invalid. ** ** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed ** to recognize the end of a trigger can be omitted. All we have to do ** is look for a semicolon that is not part of an string or comment. */ int sqlite3_complete(const char *zSql){ u8 state = 0; /* Current state, using numbers defined in header comment */ u8 token; /* Value of the next token */ #ifndef SQLITE_OMIT_TRIGGER /* A complex statement machine used to detect the end of a CREATE TRIGGER ** statement. This is the normal case. */ static const u8 trans[8][8] = { /* Token: */ /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ /* 0 INVALID: */ { 1, 0, 2, 3, 4, 2, 2, 2, }, /* 1 START: */ { 1, 1, 2, 3, 4, 2, 2, 2, }, /* 2 NORMAL: */ { 1, 2, 2, 2, 2, 2, 2, 2, }, /* 3 EXPLAIN: */ { 1, 3, 3, 2, 4, 2, 2, 2, }, /* 4 CREATE: */ { 1, 4, 2, 2, 2, 4, 5, 2, }, /* 5 TRIGGER: */ { 6, 5, 5, 5, 5, 5, 5, 5, }, /* 6 SEMI: */ { 6, 6, 5, 5, 5, 5, 5, 7, }, /* 7 END: */ { 1, 7, 5, 5, 5, 5, 5, 5, }, }; #else /* If triggers are not supported by this compile then the statement machine ** used to detect the end of a statement is much simplier */ static const u8 trans[3][3] = { /* Token: */ /* State: ** SEMI WS OTHER */ /* 0 INVALID: */ { 1, 0, 2, }, /* 1 START: */ { 1, 1, 2, }, /* 2 NORMAL: */ { 1, 2, 2, }, }; #endif /* SQLITE_OMIT_TRIGGER */ while( *zSql ){ switch( *zSql ){ case ';': { /* A semicolon */ token = tkSEMI; |
︙ | ︙ | |||
155 156 157 158 159 160 161 | } case '-': { /* SQL-style comments from "--" to end of line */ if( zSql[1]!='-' ){ token = tkOTHER; break; } while( *zSql && *zSql!='\n' ){ zSql++; } | | | 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | } 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==1; token = tkWS; break; } case '[': { /* Microsoft-style identifiers in [...] */ zSql++; while( *zSql && *zSql!=']' ){ zSql++; } if( *zSql==0 ) return 0; |
︙ | ︙ | |||
239 240 241 242 243 244 245 | } break; } } state = trans[state][token]; zSql++; } | | | 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 | } break; } } state = trans[state][token]; zSql++; } return state==1; } #ifndef SQLITE_OMIT_UTF16 /* ** This routine is the same as the sqlite3_complete() routine described ** above, except that the parameter is required to be UTF-16 encoded, not ** UTF-8. |
︙ | ︙ |
Changes to test/main.test.
︙ | ︙ | |||
21 22 23 24 25 26 27 | ifcapable {complete} { # Tests of the sqlite_complete() function. # do_test main-1.1 { db complete {This is a test} } {0} | | | | > > > | | > > > > > > > > > > > > > > > > | 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | ifcapable {complete} { # Tests of the sqlite_complete() function. # do_test main-1.1 { db complete {This is a test} } {0} do_test main-1.2.0 { db complete { } } {0} do_test main-1.2.1 { db complete {} } {0} do_test main-1.3.0 { db complete { -- a comment ; } } {0} do_test main-1.3.1 { db complete { /* a comment ; */ } } {0} do_test main-1.4.0 { db complete { -- a comment ; ; } } {1} do_test main-1.4.1 { db complete { /* a comment ; */ ; } } {1} do_test main-1.4.2 { db complete { /* a comment ; */ ; } } {1} do_test main-1.5 { db complete {DROP TABLE 'xyz;} } {0} do_test main-1.6 { db complete {DROP TABLE 'xyz';} } {1} |
︙ | ︙ |