wasCSharpSQLite – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System.Diagnostics; |
2 | |||
3 | namespace Community.CsharpSqlite |
||
4 | { |
||
5 | |||
6 | using u8 = System.Byte; |
||
7 | |||
8 | public partial class Sqlite3 |
||
9 | { |
||
10 | /* |
||
11 | ** 2001 September 15 |
||
12 | ** |
||
13 | ** The author disclaims copyright to this source code. In place of |
||
14 | ** a legal notice, here is a blessing: |
||
15 | ** |
||
16 | ** May you do good and not evil. |
||
17 | ** May you find forgiveness for yourself and forgive others. |
||
18 | ** May you share freely, never taking more than you give. |
||
19 | ** |
||
20 | ************************************************************************* |
||
21 | ** An tokenizer for SQL |
||
22 | ** |
||
23 | ** This file contains C code that implements the sqlite3_complete() API. |
||
24 | ** This code used to be part of the tokenizer.c source file. But by |
||
25 | ** separating it out, the code will be automatically omitted from |
||
26 | ** static links that do not use it. |
||
27 | ************************************************************************* |
||
28 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
29 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
30 | ** |
||
31 | ** SQLITE_SOURCE_ID: 2010-08-23 18:52:01 42537b60566f288167f1b5864a5435986838e3a3 |
||
32 | ** |
||
33 | ************************************************************************* |
||
34 | */ |
||
35 | //#include "sqliteInt.h" |
||
36 | #if !SQLITE_OMIT_COMPLETE |
||
37 | |||
38 | /* |
||
39 | ** This is defined in tokenize.c. We just have to import the definition. |
||
40 | */ |
||
41 | #if !SQLITE_AMALGAMATION |
||
42 | #if SQLITE_ASCII |
||
43 | //#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) |
||
44 | static bool IdChar( u8 C ) |
||
45 | { |
||
46 | return ( sqlite3CtypeMap[(char)C] & 0x46 ) != 0; |
||
47 | } |
||
48 | #endif |
||
49 | //#if SQLITE_EBCDIC |
||
50 | //extern const char sqlite3IsEbcdicIdChar[]; |
||
51 | //#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) |
||
52 | //#endif |
||
53 | #endif // * SQLITE_AMALGAMATION */ |
||
54 | |||
55 | |||
56 | /* |
||
57 | ** Token types used by the sqlite3_complete() routine. See the header |
||
58 | ** comments on that procedure for additional information. |
||
59 | */ |
||
60 | const int tkSEMI = 0; |
||
61 | const int tkWS = 1; |
||
62 | const int tkOTHER = 2; |
||
63 | #if !SQLITE_OMIT_TRIGGER |
||
64 | const int tkEXPLAIN = 3; |
||
65 | const int tkCREATE = 4; |
||
66 | const int tkTEMP = 5; |
||
67 | const int tkTRIGGER = 6; |
||
68 | const int tkEND = 7; |
||
69 | #endif |
||
70 | |||
71 | /* |
||
72 | ** Return TRUE if the given SQL string ends in a semicolon. |
||
73 | ** |
||
74 | ** Special handling is require for CREATE TRIGGER statements. |
||
75 | ** Whenever the CREATE TRIGGER keywords are seen, the statement |
||
76 | ** must end with ";END;". |
||
77 | ** |
||
78 | ** This implementation uses a state machine with 8 states: |
||
79 | ** |
||
80 | ** (0) INVALID We have not yet seen a non-whitespace character. |
||
81 | ** |
||
82 | ** (1) START At the beginning or end of an SQL statement. This routine |
||
83 | ** returns 1 if it ends in the START state and 0 if it ends |
||
84 | ** in any other state. |
||
85 | ** |
||
86 | ** (2) NORMAL We are in the middle of statement which ends with a single |
||
87 | ** semicolon. |
||
88 | ** |
||
89 | ** (3) EXPLAIN The keyword EXPLAIN has been seen at the beginning of |
||
90 | ** a statement. |
||
91 | ** |
||
92 | ** (4) CREATE The keyword CREATE has been seen at the beginning of a |
||
93 | ** statement, possibly preceeded by EXPLAIN and/or followed by |
||
94 | ** TEMP or TEMPORARY |
||
95 | ** |
||
96 | ** (5) TRIGGER We are in the middle of a trigger definition that must be |
||
97 | ** ended by a semicolon, the keyword END, and another semicolon. |
||
98 | ** |
||
99 | ** (6) SEMI We've seen the first semicolon in the ";END;" that occurs at |
||
100 | ** the end of a trigger definition. |
||
101 | ** |
||
102 | ** (7) END We've seen the ";END" of the ";END;" that occurs at the end |
||
103 | ** of a trigger difinition. |
||
104 | ** |
||
105 | ** Transitions between states above are determined by tokens extracted |
||
106 | ** from the input. The following tokens are significant: |
||
107 | ** |
||
108 | ** (0) tkSEMI A semicolon. |
||
109 | ** (1) tkWS Whitespace. |
||
110 | ** (2) tkOTHER Any other SQL token. |
||
111 | ** (3) tkEXPLAIN The "explain" keyword. |
||
112 | ** (4) tkCREATE The "create" keyword. |
||
113 | ** (5) tkTEMP The "temp" or "temporary" keyword. |
||
114 | ** (6) tkTRIGGER The "trigger" keyword. |
||
115 | ** (7) tkEND The "end" keyword. |
||
116 | ** |
||
117 | ** Whitespace never causes a state transition and is always ignored. |
||
118 | ** This means that a SQL string of all whitespace is invalid. |
||
119 | ** |
||
120 | ** If we compile with SQLITE_OMIT_TRIGGER, all of the computation needed |
||
121 | ** to recognize the end of a trigger can be omitted. All we have to do |
||
122 | ** is look for a semicolon that is not part of an string or comment. |
||
123 | */ |
||
124 | |||
125 | static public int sqlite3_complete( string zSql ) |
||
126 | { |
||
127 | int state = 0; /* Current state, using numbers defined in header comment */ |
||
128 | int token; /* Value of the next token */ |
||
129 | |||
130 | #if !SQLITE_OMIT_TRIGGER |
||
131 | /* A complex statement machine used to detect the end of a CREATE TRIGGER |
||
132 | ** statement. This is the normal case. |
||
133 | */ |
||
134 | u8[][] trans = new u8[][] { |
||
135 | /* Token: */ |
||
136 | /* State: ** SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END */ |
||
137 | /* 0 INVALID: */ new u8[]{ 1, 0, 2, 3, 4, 2, 2, 2, }, |
||
138 | /* 1 START: */ new u8[]{ 1, 1, 2, 3, 4, 2, 2, 2, }, |
||
139 | /* 2 NORMAL: */ new u8[]{ 1, 2, 2, 2, 2, 2, 2, 2, }, |
||
140 | /* 3 EXPLAIN: */ new u8[]{ 1, 3, 3, 2, 4, 2, 2, 2, }, |
||
141 | /* 4 CREATE: */ new u8[]{ 1, 4, 2, 2, 2, 4, 5, 2, }, |
||
142 | /* 5 TRIGGER: */ new u8[]{ 6, 5, 5, 5, 5, 5, 5, 5, }, |
||
143 | /* 6 SEMI: */ new u8[]{ 6, 6, 5, 5, 5, 5, 5, 7, }, |
||
144 | /* 7 END: */ new u8[]{ 1, 7, 5, 5, 5, 5, 5, 5, }, |
||
145 | }; |
||
146 | #else |
||
147 | /* If triggers are not supported by this compile then the statement machine |
||
148 | ** used to detect the end of a statement is much simplier |
||
149 | */ |
||
150 | u8[][] trans = new u8[][] { |
||
151 | /* Token: */ |
||
152 | /* State: ** SEMI WS OTHER */ |
||
153 | /* 0 INVALID: */new u8[] { 1, 0, 2, }, |
||
154 | /* 1 START: */new u8[] { 1, 1, 2, }, |
||
155 | /* 2 NORMAL: */new u8[] { 1, 2, 2, }, |
||
156 | }; |
||
157 | #endif // * SQLITE_OMIT_TRIGGER */ |
||
158 | |||
159 | int zIdx = 0; |
||
160 | while ( zIdx < zSql.Length ) |
||
161 | { |
||
162 | switch ( zSql[zIdx] ) |
||
163 | { |
||
164 | case ';': |
||
165 | { /* A semicolon */ |
||
166 | token = tkSEMI; |
||
167 | break; |
||
168 | } |
||
169 | case ' ': |
||
170 | case '\r': |
||
171 | case '\t': |
||
172 | case '\n': |
||
173 | case '\f': |
||
174 | { /* White space is ignored */ |
||
175 | token = tkWS; |
||
176 | break; |
||
177 | } |
||
178 | case '/': |
||
179 | { /* C-style comments */ |
||
180 | if ( zSql[zIdx + 1] != '*' ) |
||
181 | { |
||
182 | token = tkOTHER; |
||
183 | break; |
||
184 | } |
||
185 | zIdx += 2; |
||
186 | while ( zIdx < zSql.Length && zSql[zIdx] != '*' || zIdx < zSql.Length - 1 && zSql[zIdx + 1] != '/' ) |
||
187 | { |
||
188 | zIdx++; |
||
189 | } |
||
190 | if ( zIdx == zSql.Length ) |
||
191 | return 0; |
||
192 | zIdx++; |
||
193 | token = tkWS; |
||
194 | break; |
||
195 | } |
||
196 | case '-': |
||
197 | { /* SQL-style comments from "--" to end of line */ |
||
198 | if ( zSql[zIdx + 1] != '-' ) |
||
199 | { |
||
200 | token = tkOTHER; |
||
201 | break; |
||
202 | } |
||
203 | while ( zIdx < zSql.Length && zSql[zIdx] != '\n' ) |
||
204 | { |
||
205 | zIdx++; |
||
206 | } |
||
207 | if ( zIdx == zSql.Length ) |
||
208 | return state == 1 ? 1 : 0;//if( *zSql==0 ) return state==1; |
||
209 | token = tkWS; |
||
210 | break; |
||
211 | } |
||
212 | case '[': |
||
213 | { /* Microsoft-style identifiers in [...] */ |
||
214 | zIdx++; |
||
215 | while ( zIdx < zSql.Length && zSql[zIdx] != ']' ) |
||
216 | { |
||
217 | zIdx++; |
||
218 | } |
||
219 | if ( zIdx == zSql.Length ) |
||
220 | return 0; |
||
221 | token = tkOTHER; |
||
222 | break; |
||
223 | } |
||
224 | case '`': /* Grave-accent quoted symbols used by MySQL */ |
||
225 | case '"': /* single- and double-quoted strings */ |
||
226 | case '\'': |
||
227 | { |
||
228 | int c = zSql[zIdx]; |
||
229 | zIdx++; |
||
230 | while ( zIdx < zSql.Length && zSql[zIdx] != c ) |
||
231 | { |
||
232 | zIdx++; |
||
233 | } |
||
234 | if ( zIdx == zSql.Length ) |
||
235 | return 0; |
||
236 | token = tkOTHER; |
||
237 | break; |
||
238 | } |
||
239 | default: |
||
240 | { |
||
241 | //#if SQLITE_EBCDIC |
||
242 | // unsigned char c; |
||
243 | //#endif |
||
244 | if ( IdChar( (u8)zSql[zIdx] ) ) |
||
245 | { |
||
246 | /* Keywords and unquoted identifiers */ |
||
247 | int nId; |
||
248 | for ( nId = 1; ( zIdx + nId ) < zSql.Length && IdChar( (u8)zSql[zIdx + nId] ); nId++ ) |
||
249 | { |
||
250 | } |
||
251 | #if SQLITE_OMIT_TRIGGER |
||
252 | token = tkOTHER; |
||
253 | #else |
||
254 | switch ( zSql[zIdx] ) |
||
255 | { |
||
256 | case 'c': |
||
257 | case 'C': |
||
258 | { |
||
259 | if ( nId == 6 && sqlite3StrNICmp( zSql, zIdx, "create", 6 ) == 0 ) |
||
260 | { |
||
261 | token = tkCREATE; |
||
262 | } |
||
263 | else |
||
264 | { |
||
265 | token = tkOTHER; |
||
266 | } |
||
267 | break; |
||
268 | } |
||
269 | case 't': |
||
270 | case 'T': |
||
271 | { |
||
272 | if ( nId == 7 && sqlite3StrNICmp( zSql, zIdx, "trigger", 7 ) == 0 ) |
||
273 | { |
||
274 | token = tkTRIGGER; |
||
275 | } |
||
276 | else if ( nId == 4 && sqlite3StrNICmp( zSql, zIdx, "temp", 4 ) == 0 ) |
||
277 | { |
||
278 | token = tkTEMP; |
||
279 | } |
||
280 | else if ( nId == 9 && sqlite3StrNICmp( zSql, zIdx, "temporary", 9 ) == 0 ) |
||
281 | { |
||
282 | token = tkTEMP; |
||
283 | } |
||
284 | else |
||
285 | { |
||
286 | token = tkOTHER; |
||
287 | } |
||
288 | break; |
||
289 | } |
||
290 | case 'e': |
||
291 | case 'E': |
||
292 | { |
||
293 | if ( nId == 3 && sqlite3StrNICmp( zSql, zIdx, "end", 3 ) == 0 ) |
||
294 | { |
||
295 | token = tkEND; |
||
296 | } |
||
297 | else |
||
298 | #if !SQLITE_OMIT_EXPLAIN |
||
299 | if ( nId == 7 && sqlite3StrNICmp( zSql, zIdx, "explain", 7 ) == 0 ) |
||
300 | { |
||
301 | token = tkEXPLAIN; |
||
302 | } |
||
303 | else |
||
304 | #endif |
||
305 | { |
||
306 | token = tkOTHER; |
||
307 | } |
||
308 | break; |
||
309 | } |
||
310 | default: |
||
311 | { |
||
312 | token = tkOTHER; |
||
313 | break; |
||
314 | } |
||
315 | } |
||
316 | #endif // * SQLITE_OMIT_TRIGGER */ |
||
317 | zIdx += nId - 1; |
||
318 | } |
||
319 | else |
||
320 | { |
||
321 | /* Operators and special symbols */ |
||
322 | token = tkOTHER; |
||
323 | } |
||
324 | break; |
||
325 | } |
||
326 | } |
||
327 | state = trans[state][token]; |
||
328 | zIdx++; |
||
329 | } |
||
330 | return ( state == 1 ) ? 1 : 0;//return state==1; |
||
331 | } |
||
332 | |||
333 | #if !SQLITE_OMIT_UTF16 |
||
334 | /* |
||
335 | ** This routine is the same as the sqlite3_complete() routine described |
||
336 | ** above, except that the parameter is required to be UTF-16 encoded, not |
||
337 | ** UTF-8. |
||
338 | */ |
||
339 | int sqlite3_complete16(const void *zSql){ |
||
340 | sqlite3_value pVal; |
||
341 | char const *zSql8; |
||
342 | int rc = SQLITE_NOMEM; |
||
343 | |||
344 | #if !SQLITE_OMIT_AUTOINIT |
||
345 | rc = sqlite3_initialize(); |
||
346 | if( rc !=0) return rc; |
||
347 | #endif |
||
348 | pVal = sqlite3ValueNew(0); |
||
349 | sqlite3ValueSetStr(pVal, -1, zSql, SQLITE_UTF16NATIVE, SQLITE_STATIC); |
||
350 | zSql8 = sqlite3ValueText(pVal, SQLITE_UTF8); |
||
351 | if( zSql8 ){ |
||
352 | rc = sqlite3_complete(zSql8); |
||
353 | }else{ |
||
354 | rc = SQLITE_NOMEM; |
||
355 | } |
||
356 | sqlite3ValueFree(pVal); |
||
357 | return sqlite3ApiExit(0, rc); |
||
358 | } |
||
359 | #endif // * SQLITE_OMIT_UTF16 */ |
||
360 | #endif // * SQLITE_OMIT_COMPLETE */ |
||
361 | } |
||
362 | } |