wasCSharpSQLite – Blame information for rev
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | using System; |
2 | using System.Diagnostics; |
||
3 | using System.Text; |
||
4 | |||
5 | namespace Community.CsharpSqlite |
||
6 | { |
||
7 | public partial class Sqlite3 |
||
8 | { |
||
9 | /* |
||
10 | ** 2001 September 15 |
||
11 | ** |
||
12 | ** The author disclaims copyright to this source code. In place of |
||
13 | ** a legal notice, here is a blessing: |
||
14 | ** |
||
15 | ** May you do good and not evil. |
||
16 | ** May you find forgiveness for yourself and forgive others. |
||
17 | ** May you share freely, never taking more than you give. |
||
18 | ** |
||
19 | ************************************************************************* |
||
20 | ** An tokenizer for SQL |
||
21 | ** |
||
22 | ** This file contains C code that splits an SQL input string up into |
||
23 | ** individual tokens and sends those tokens one-by-one over to the |
||
24 | ** parser for analysis. |
||
25 | ************************************************************************* |
||
26 | ** Included in SQLite3 port to C#-SQLite; 2008 Noah B Hart |
||
27 | ** C#-SQLite is an independent reimplementation of the SQLite software library |
||
28 | ** |
||
29 | ** SQLITE_SOURCE_ID: 2011-06-23 19:49:22 4374b7e83ea0a3fbc3691f9c0c936272862f32f2 |
||
30 | ** |
||
31 | ************************************************************************* |
||
32 | */ |
||
33 | //#include "sqliteInt.h" |
||
34 | //#include <stdlib.h> |
||
35 | |||
36 | /* |
||
37 | ** The charMap() macro maps alphabetic characters into their |
||
38 | ** lower-case ASCII equivalent. On ASCII machines, this is just |
||
39 | ** an upper-to-lower case map. On EBCDIC machines we also need |
||
40 | ** to adjust the encoding. Only alphabetic characters and underscores |
||
41 | ** need to be translated. |
||
42 | */ |
||
43 | #if SQLITE_ASCII |
||
44 | //# define charMap(X) sqlite3UpperToLower[(unsigned char)X] |
||
45 | #endif |
||
46 | //#if SQLITE_EBCDIC |
||
47 | //# define charMap(X) ebcdicToAscii[(unsigned char)X] |
||
48 | //const unsigned char ebcdicToAscii[] = { |
||
49 | ///* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ |
||
50 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ |
||
51 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ |
||
52 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ |
||
53 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ |
||
54 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ |
||
55 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ |
||
56 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */ |
||
57 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ |
||
58 | // 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */ |
||
59 | // 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */ |
||
60 | // 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */ |
||
61 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ |
||
62 | // 0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */ |
||
63 | // 0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */ |
||
64 | // 0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */ |
||
65 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */ |
||
66 | //}; |
||
67 | //#endif |
||
68 | |||
69 | /* |
||
70 | ** The sqlite3KeywordCode function looks up an identifier to determine if |
||
71 | ** it is a keyword. If it is a keyword, the token code of that keyword is |
||
72 | ** returned. If the input is not a keyword, TK_ID is returned. |
||
73 | ** |
||
74 | ** The implementation of this routine was generated by a program, |
||
75 | ** mkkeywordhash.h, located in the tool subdirectory of the distribution. |
||
76 | ** The output of the mkkeywordhash.c program is written into a file |
||
77 | ** named keywordhash.h and then included into this source file by |
||
78 | ** the #include below. |
||
79 | */ |
||
80 | //#include "keywordhash.h" |
||
81 | |||
82 | |||
83 | /* |
||
84 | ** If X is a character that can be used in an identifier then |
||
85 | ** IdChar(X) will be true. Otherwise it is false. |
||
86 | ** |
||
87 | ** For ASCII, any character with the high-order bit set is |
||
88 | ** allowed in an identifier. For 7-bit characters, |
||
89 | ** sqlite3IsIdChar[X] must be 1. |
||
90 | ** |
||
91 | ** For EBCDIC, the rules are more complex but have the same |
||
92 | ** end result. |
||
93 | ** |
||
94 | ** Ticket #1066. the SQL standard does not allow '$' in the |
||
95 | ** middle of identfiers. But many SQL implementations do. |
||
96 | ** SQLite will allow '$' in identifiers for compatibility. |
||
97 | ** But the feature is undocumented. |
||
98 | */ |
||
99 | #if SQLITE_ASCII |
||
100 | //#define IdChar(C) ((sqlite3CtypeMap[(unsigned char)C]&0x46)!=0) |
||
101 | #endif |
||
102 | //#if SQLITE_EBCDIC |
||
103 | //const char sqlite3IsEbcdicIdChar[] = { |
||
104 | ///* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ |
||
105 | // 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */ |
||
106 | // 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */ |
||
107 | // 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */ |
||
108 | // 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */ |
||
109 | // 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */ |
||
110 | // 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */ |
||
111 | // 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */ |
||
112 | // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ |
||
113 | // 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */ |
||
114 | // 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */ |
||
115 | // 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */ |
||
116 | // 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */ |
||
117 | //}; |
||
118 | //#define IdChar(C) (((c=C)>=0x42 && sqlite3IsEbcdicIdChar[c-0x40])) |
||
119 | //#endif |
||
120 | |||
121 | |||
122 | /* |
||
123 | ** Return the length of the token that begins at z[iOffset + 0]. |
||
124 | ** Store the token type in *tokenType before returning. |
||
125 | */ |
||
126 | static int sqlite3GetToken( string z, int iOffset, ref int tokenType ) |
||
127 | { |
||
128 | int i; |
||
129 | char c = '\0'; |
||
130 | switch ( z[iOffset + 0] ) |
||
131 | { |
||
132 | case ' ': |
||
133 | case '\t': |
||
134 | case '\n': |
||
135 | case '\f': |
||
136 | case '\r': |
||
137 | { |
||
138 | testcase( z[iOffset + 0] == ' ' ); |
||
139 | testcase( z[iOffset + 0] == '\t' ); |
||
140 | testcase( z[iOffset + 0] == '\n' ); |
||
141 | testcase( z[iOffset + 0] == '\f' ); |
||
142 | testcase( z[iOffset + 0] == '\r' ); |
||
143 | for ( i = 1; z.Length > iOffset + i && sqlite3Isspace( z[iOffset + i] ); i++ ) |
||
144 | { |
||
145 | } |
||
146 | tokenType = TK_SPACE; |
||
147 | return i; |
||
148 | } |
||
149 | case '-': |
||
150 | { |
||
151 | if ( z.Length > iOffset + 1 && z[iOffset + 1] == '-' ) |
||
152 | { |
||
153 | /* IMP: R-15891-05542 -- syntax diagram for comments */ |
||
154 | for ( i = 2; z.Length > iOffset + i && ( c = z[iOffset + i] ) != 0 && c != '\n'; i++ ) |
||
155 | { |
||
156 | } |
||
157 | tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
||
158 | return i; |
||
159 | } |
||
160 | tokenType = TK_MINUS; |
||
161 | return 1; |
||
162 | } |
||
163 | case '(': |
||
164 | { |
||
165 | tokenType = TK_LP; |
||
166 | return 1; |
||
167 | } |
||
168 | case ')': |
||
169 | { |
||
170 | tokenType = TK_RP; |
||
171 | return 1; |
||
172 | } |
||
173 | case ';': |
||
174 | { |
||
175 | tokenType = TK_SEMI; |
||
176 | return 1; |
||
177 | } |
||
178 | case '+': |
||
179 | { |
||
180 | tokenType = TK_PLUS; |
||
181 | return 1; |
||
182 | } |
||
183 | case '*': |
||
184 | { |
||
185 | tokenType = TK_STAR; |
||
186 | return 1; |
||
187 | } |
||
188 | case '/': |
||
189 | { |
||
190 | if ( iOffset + 2 >= z.Length || z[iOffset + 1] != '*' ) |
||
191 | { |
||
192 | tokenType = TK_SLASH; |
||
193 | return 1; |
||
194 | } |
||
195 | /* IMP: R-15891-05542 -- syntax diagram for comments */ |
||
196 | for ( i = 3, c = z[iOffset + 2]; iOffset + i < z.Length && ( c != '*' || ( z[iOffset + i] != '/' ) && ( c != 0 ) ); i++ ) |
||
197 | { |
||
198 | c = z[iOffset + i]; |
||
199 | } |
||
200 | if ( iOffset + i == z.Length ) |
||
201 | c = '\0'; |
||
202 | if ( c != 0 ) |
||
203 | i++; |
||
204 | tokenType = TK_SPACE; /* IMP: R-22934-25134 */ |
||
205 | return i; |
||
206 | } |
||
207 | case '%': |
||
208 | { |
||
209 | tokenType = TK_REM; |
||
210 | return 1; |
||
211 | } |
||
212 | case '=': |
||
213 | { |
||
214 | tokenType = TK_EQ; |
||
215 | return 1 + ( z[iOffset + 1] == '=' ? 1 : 0 ); |
||
216 | } |
||
217 | case '<': |
||
218 | { |
||
219 | if ( ( c = z[iOffset + 1] ) == '=' ) |
||
220 | { |
||
221 | tokenType = TK_LE; |
||
222 | return 2; |
||
223 | } |
||
224 | else if ( c == '>' ) |
||
225 | { |
||
226 | tokenType = TK_NE; |
||
227 | return 2; |
||
228 | } |
||
229 | else if ( c == '<' ) |
||
230 | { |
||
231 | tokenType = TK_LSHIFT; |
||
232 | return 2; |
||
233 | } |
||
234 | else |
||
235 | { |
||
236 | tokenType = TK_LT; |
||
237 | return 1; |
||
238 | } |
||
239 | } |
||
240 | case '>': |
||
241 | { |
||
242 | if ( z.Length > iOffset + 1 && ( c = z[iOffset + 1] ) == '=' ) |
||
243 | { |
||
244 | tokenType = TK_GE; |
||
245 | return 2; |
||
246 | } |
||
247 | else if ( c == '>' ) |
||
248 | { |
||
249 | tokenType = TK_RSHIFT; |
||
250 | return 2; |
||
251 | } |
||
252 | else |
||
253 | { |
||
254 | tokenType = TK_GT; |
||
255 | return 1; |
||
256 | } |
||
257 | } |
||
258 | case '!': |
||
259 | { |
||
260 | if ( z[iOffset + 1] != '=' ) |
||
261 | { |
||
262 | tokenType = TK_ILLEGAL; |
||
263 | return 2; |
||
264 | } |
||
265 | else |
||
266 | { |
||
267 | tokenType = TK_NE; |
||
268 | return 2; |
||
269 | } |
||
270 | } |
||
271 | case '|': |
||
272 | { |
||
273 | if ( z[iOffset + 1] != '|' ) |
||
274 | { |
||
275 | tokenType = TK_BITOR; |
||
276 | return 1; |
||
277 | } |
||
278 | else |
||
279 | { |
||
280 | tokenType = TK_CONCAT; |
||
281 | return 2; |
||
282 | } |
||
283 | } |
||
284 | case ',': |
||
285 | { |
||
286 | tokenType = TK_COMMA; |
||
287 | return 1; |
||
288 | } |
||
289 | case '&': |
||
290 | { |
||
291 | tokenType = TK_BITAND; |
||
292 | return 1; |
||
293 | } |
||
294 | case '~': |
||
295 | { |
||
296 | tokenType = TK_BITNOT; |
||
297 | return 1; |
||
298 | } |
||
299 | case '`': |
||
300 | case '\'': |
||
301 | case '"': |
||
302 | { |
||
303 | int delim = z[iOffset + 0]; |
||
304 | testcase( delim == '`' ); |
||
305 | testcase( delim == '\'' ); |
||
306 | testcase( delim == '"' ); |
||
307 | for ( i = 1; ( iOffset + i ) < z.Length && ( c = z[iOffset + i] ) != 0; i++ ) |
||
308 | { |
||
309 | if ( c == delim ) |
||
310 | { |
||
311 | if ( z.Length > iOffset + i + 1 && z[iOffset + i + 1] == delim ) |
||
312 | { |
||
313 | i++; |
||
314 | } |
||
315 | else |
||
316 | { |
||
317 | break; |
||
318 | } |
||
319 | } |
||
320 | } |
||
321 | if ( ( iOffset + i == z.Length && c != delim ) || z[iOffset + i] != delim ) |
||
322 | { |
||
323 | tokenType = TK_ILLEGAL; |
||
324 | return i + 1; |
||
325 | } |
||
326 | if ( c == '\'' ) |
||
327 | { |
||
328 | tokenType = TK_STRING; |
||
329 | return i + 1; |
||
330 | } |
||
331 | else if ( c != 0 ) |
||
332 | { |
||
333 | tokenType = TK_ID; |
||
334 | return i + 1; |
||
335 | } |
||
336 | else |
||
337 | { |
||
338 | tokenType = TK_ILLEGAL; |
||
339 | return i; |
||
340 | } |
||
341 | } |
||
342 | case '.': |
||
343 | { |
||
344 | #if !SQLITE_OMIT_FLOATING_POINT |
||
345 | if ( !sqlite3Isdigit( z[iOffset + 1] ) ) |
||
346 | #endif |
||
347 | { |
||
348 | tokenType = TK_DOT; |
||
349 | return 1; |
||
350 | } |
||
351 | /* If the next character is a digit, this is a floating point |
||
352 | ** number that begins with ".". Fall thru into the next case */ |
||
353 | goto case '0'; |
||
354 | } |
||
355 | case '0': |
||
356 | case '1': |
||
357 | case '2': |
||
358 | case '3': |
||
359 | case '4': |
||
360 | case '5': |
||
361 | case '6': |
||
362 | case '7': |
||
363 | case '8': |
||
364 | case '9': |
||
365 | { |
||
366 | testcase( z[iOffset] == '0' ); |
||
367 | testcase( z[iOffset] == '1' ); |
||
368 | testcase( z[iOffset] == '2' ); |
||
369 | testcase( z[iOffset] == '3' ); |
||
370 | testcase( z[iOffset] == '4' ); |
||
371 | testcase( z[iOffset] == '5' ); |
||
372 | testcase( z[iOffset] == '6' ); |
||
373 | testcase( z[iOffset] == '7' ); |
||
374 | testcase( z[iOffset] == '8' ); |
||
375 | testcase( z[iOffset] == '9' ); |
||
376 | tokenType = TK_INTEGER; |
||
377 | for ( i = 0; z.Length > iOffset + i && sqlite3Isdigit( z[iOffset + i] ); i++ ) |
||
378 | { |
||
379 | } |
||
380 | #if !SQLITE_OMIT_FLOATING_POINT |
||
381 | if ( z.Length > iOffset + i && z[iOffset + i] == '.' ) |
||
382 | { |
||
383 | i++; |
||
384 | while ( z.Length > iOffset + i && sqlite3Isdigit( z[iOffset + i] ) ) |
||
385 | { |
||
386 | i++; |
||
387 | } |
||
388 | tokenType = TK_FLOAT; |
||
389 | } |
||
390 | if ( z.Length > iOffset + i + 1 && ( z[iOffset + i] == 'e' || z[iOffset + i] == 'E' ) && |
||
391 | ( sqlite3Isdigit( z[iOffset + i + 1] ) |
||
392 | || z.Length > iOffset + i + 2 && ( ( z[iOffset + i + 1] == '+' || z[iOffset + i + 1] == '-' ) && sqlite3Isdigit( z[iOffset + i + 2] ) ) |
||
393 | ) |
||
394 | ) |
||
395 | { |
||
396 | i += 2; |
||
397 | while ( z.Length > iOffset + i && sqlite3Isdigit( z[iOffset + i] ) ) |
||
398 | { |
||
399 | i++; |
||
400 | } |
||
401 | tokenType = TK_FLOAT; |
||
402 | } |
||
403 | #endif |
||
404 | while ( iOffset + i < z.Length && IdChar( (byte)z[iOffset + i] ) ) |
||
405 | { |
||
406 | tokenType = TK_ILLEGAL; |
||
407 | i++; |
||
408 | } |
||
409 | return i; |
||
410 | } |
||
411 | |||
412 | case '[': |
||
413 | { |
||
414 | for ( i = 1, c = z[iOffset + 0]; c != ']' && ( iOffset + i ) < z.Length && ( c = z[iOffset + i] ) != 0; i++ ) |
||
415 | { |
||
416 | } |
||
417 | tokenType = c == ']' ? TK_ID : TK_ILLEGAL; |
||
418 | return i; |
||
419 | } |
||
420 | case '?': |
||
421 | { |
||
422 | tokenType = TK_VARIABLE; |
||
423 | for ( i = 1; z.Length > iOffset + i && sqlite3Isdigit( z[iOffset + i] ); i++ ) |
||
424 | { |
||
425 | } |
||
426 | return i; |
||
427 | } |
||
428 | case '#': |
||
429 | { |
||
430 | for ( i = 1; z.Length > iOffset + i && sqlite3Isdigit( z[iOffset + i] ); i++ ) |
||
431 | { |
||
432 | } |
||
433 | if ( i > 1 ) |
||
434 | { |
||
435 | /* Parameters of the form #NNN (where NNN is a number) are used |
||
436 | ** internally by sqlite3NestedParse. */ |
||
437 | tokenType = TK_REGISTER; |
||
438 | return i; |
||
439 | } |
||
440 | /* Fall through into the next case if the '#' is not followed by |
||
441 | ** a digit. Try to match #AAAA where AAAA is a parameter name. */ |
||
442 | goto case ':'; |
||
443 | } |
||
444 | #if !SQLITE_OMIT_TCL_VARIABLE |
||
445 | case '$': |
||
446 | #endif |
||
447 | case '@': /* For compatibility with MS SQL Server */ |
||
448 | case ':': |
||
449 | { |
||
450 | int n = 0; |
||
451 | testcase( z[iOffset + 0] == '$' ); |
||
452 | testcase( z[iOffset + 0] == '@' ); |
||
453 | testcase( z[iOffset + 0] == ':' ); |
||
454 | tokenType = TK_VARIABLE; |
||
455 | for ( i = 1; z.Length > iOffset + i && ( c = z[iOffset + i] ) != 0; i++ ) |
||
456 | { |
||
457 | if (IdChar((byte)c)) |
||
458 | { |
||
459 | n++; |
||
460 | #if !SQLITE_OMIT_TCL_VARIABLE |
||
461 | } |
||
462 | else if ( c == '(' && n > 0 ) |
||
463 | { |
||
464 | do |
||
465 | { |
||
466 | i++; |
||
467 | } while ( ( iOffset + i ) < z.Length && ( c = z[iOffset + i] ) != 0 && !sqlite3Isspace( c ) && c != ')' ); |
||
468 | if ( c == ')' ) |
||
469 | { |
||
470 | i++; |
||
471 | } |
||
472 | else |
||
473 | { |
||
474 | tokenType = TK_ILLEGAL; |
||
475 | } |
||
476 | break; |
||
477 | } |
||
478 | else if ( c == ':' && z[iOffset + i + 1] == ':' ) |
||
479 | { |
||
480 | i++; |
||
481 | #endif |
||
482 | } |
||
483 | else |
||
484 | { |
||
485 | break; |
||
486 | } |
||
487 | } |
||
488 | if ( n == 0 ) |
||
489 | tokenType = TK_ILLEGAL; |
||
490 | return i; |
||
491 | } |
||
492 | #if !SQLITE_OMIT_BLOB_LITERAL |
||
493 | case 'x': |
||
494 | case 'X': |
||
495 | { |
||
496 | testcase( z[iOffset + 0] == 'x' ); |
||
497 | testcase( z[iOffset + 0] == 'X' ); |
||
498 | if ( z.Length > iOffset + 1 && z[iOffset + 1] == '\'' ) |
||
499 | { |
||
500 | tokenType = TK_BLOB; |
||
501 | for ( i = 2; z.Length > iOffset + i && sqlite3Isxdigit( z[iOffset + i] ); i++ ) |
||
502 | { |
||
503 | } |
||
504 | if ( iOffset + i == z.Length || z[iOffset + i] != '\'' || i % 2 != 0 ) |
||
505 | { |
||
506 | tokenType = TK_ILLEGAL; |
||
507 | while ( z.Length > iOffset + i && z[iOffset + i] != '\'' ) |
||
508 | { |
||
509 | i++; |
||
510 | } |
||
511 | } |
||
512 | if ( z.Length > iOffset + i ) |
||
513 | i++; |
||
514 | return i; |
||
515 | } |
||
516 | goto default; |
||
517 | /* Otherwise fall through to the next case */ |
||
518 | } |
||
519 | #endif |
||
520 | default: |
||
521 | { |
||
522 | if ( !IdChar( (byte)z[iOffset] ) ) |
||
523 | { |
||
524 | break; |
||
525 | } |
||
526 | for ( i = 1; i < z.Length - iOffset && IdChar( (byte)z[iOffset + i] ); i++ ) |
||
527 | { |
||
528 | } |
||
529 | tokenType = keywordCode( z, iOffset, i ); |
||
530 | return i; |
||
531 | } |
||
532 | } |
||
533 | tokenType = TK_ILLEGAL; |
||
534 | return 1; |
||
535 | } |
||
536 | |||
537 | /* |
||
538 | ** Run the parser on the given SQL string. The parser structure is |
||
539 | ** passed in. An SQLITE_ status code is returned. If an error occurs |
||
540 | ** then an and attempt is made to write an error message into |
||
541 | ** memory obtained from sqlite3_malloc() and to make pzErrMsg point to that |
||
542 | ** error message. |
||
543 | */ |
||
544 | static int sqlite3RunParser( Parse pParse, string zSql, ref string pzErrMsg ) |
||
545 | { |
||
546 | int nErr = 0; /* Number of errors encountered */ |
||
547 | int i; /* Loop counter */ |
||
548 | yyParser pEngine; /* The LEMON-generated LALR(1) parser */ |
||
549 | int tokenType = 0; /* type of the next token */ |
||
550 | int lastTokenParsed = -1; /* type of the previous token */ |
||
551 | byte enableLookaside; /* Saved value of db->lookaside.bEnabled */ |
||
552 | sqlite3 db = pParse.db; /* The database connection */ |
||
553 | int mxSqlLen; /* Max length of an SQL string */ |
||
554 | |||
555 | mxSqlLen = db.aLimit[SQLITE_LIMIT_SQL_LENGTH]; |
||
556 | if ( db.activeVdbeCnt == 0 ) |
||
557 | { |
||
558 | db.u1.isInterrupted = false; |
||
559 | } |
||
560 | pParse.rc = SQLITE_OK; |
||
561 | pParse.zTail = new StringBuilder( zSql ); |
||
562 | i = 0; |
||
563 | Debug.Assert( pzErrMsg != null ); |
||
564 | pEngine = sqlite3ParserAlloc();//sqlite3ParserAlloc((void*(*)(size_t))sqlite3Malloc); |
||
565 | //if ( pEngine == null ) |
||
566 | //{ |
||
567 | // db.mallocFailed = 1; |
||
568 | // return SQLITE_NOMEM; |
||
569 | //} |
||
570 | Debug.Assert( pParse.pNewTable == null ); |
||
571 | Debug.Assert( pParse.pNewTrigger == null ); |
||
572 | Debug.Assert( pParse.nVar == 0 ); |
||
573 | Debug.Assert( pParse.nzVar == 0 ); |
||
574 | Debug.Assert( pParse.azVar == null ); |
||
575 | enableLookaside = db.lookaside.bEnabled; |
||
576 | if ( db.lookaside.pStart != 0 ) |
||
577 | db.lookaside.bEnabled = 1; |
||
578 | while ( /* 0 == db.mallocFailed && */ i < zSql.Length ) |
||
579 | { |
||
580 | Debug.Assert( i >= 0 ); |
||
581 | //pParse->sLastToken.z = &zSql[i]; |
||
582 | pParse.sLastToken.n = sqlite3GetToken( zSql, i, ref tokenType ); |
||
583 | pParse.sLastToken.z = zSql.Substring( i ); |
||
584 | i += pParse.sLastToken.n; |
||
585 | if ( i > mxSqlLen ) |
||
586 | { |
||
587 | pParse.rc = SQLITE_TOOBIG; |
||
588 | break; |
||
589 | } |
||
590 | switch ( tokenType ) |
||
591 | { |
||
592 | case TK_SPACE: |
||
593 | { |
||
594 | if ( db.u1.isInterrupted ) |
||
595 | { |
||
596 | sqlite3ErrorMsg( pParse, "interrupt" ); |
||
597 | pParse.rc = SQLITE_INTERRUPT; |
||
598 | goto abort_parse; |
||
599 | } |
||
600 | break; |
||
601 | } |
||
602 | case TK_ILLEGAL: |
||
603 | { |
||
604 | sqlite3DbFree( db, ref pzErrMsg ); |
||
605 | pzErrMsg = sqlite3MPrintf( db, "unrecognized token: \"%T\"", |
||
606 | (object)pParse.sLastToken ); |
||
607 | nErr++; |
||
608 | goto abort_parse; |
||
609 | } |
||
610 | case TK_SEMI: |
||
611 | { |
||
612 | //pParse.zTail = new StringBuilder(zSql.Substring( i,zSql.Length-i )); |
||
613 | /* Fall thru into the default case */ |
||
614 | goto default; |
||
615 | } |
||
616 | default: |
||
617 | { |
||
618 | sqlite3Parser( pEngine, tokenType, pParse.sLastToken, pParse ); |
||
619 | lastTokenParsed = tokenType; |
||
620 | if ( pParse.rc != SQLITE_OK ) |
||
621 | { |
||
622 | goto abort_parse; |
||
623 | } |
||
624 | break; |
||
625 | } |
||
626 | } |
||
627 | } |
||
628 | abort_parse: |
||
629 | pParse.zTail = new StringBuilder(); |
||
630 | if (zSql.Length > i ) { |
||
631 | pParse.zTail.Append(zSql.Substring( i, zSql.Length - i )); |
||
632 | } |
||
633 | if ( zSql.Length >= i && nErr == 0 && pParse.rc == SQLITE_OK ) |
||
634 | { |
||
635 | if ( lastTokenParsed != TK_SEMI ) |
||
636 | { |
||
637 | sqlite3Parser( pEngine, TK_SEMI, pParse.sLastToken, pParse ); |
||
638 | } |
||
639 | sqlite3Parser( pEngine, 0, pParse.sLastToken, pParse ); |
||
640 | } |
||
641 | #if YYTRACKMAXSTACKDEPTH |
||
642 | sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK, |
||
643 | sqlite3ParserStackPeak(pEngine) |
||
644 | ); |
||
645 | #endif //* YYDEBUG */ |
||
646 | sqlite3ParserFree( pEngine, null );//sqlite3_free ); |
||
647 | db.lookaside.bEnabled = enableLookaside; |
||
648 | //if ( db.mallocFailed != 0 ) |
||
649 | //{ |
||
650 | // pParse.rc = SQLITE_NOMEM; |
||
651 | //} |
||
652 | if ( pParse.rc != SQLITE_OK && pParse.rc != SQLITE_DONE && pParse.zErrMsg.Length == 0 ) |
||
653 | { |
||
654 | sqlite3SetString( ref pParse.zErrMsg, db, sqlite3ErrStr( pParse.rc ) ); |
||
655 | } |
||
656 | //assert( pzErrMsg!=0 ); |
||
657 | if ( pParse.zErrMsg != null ) |
||
658 | { |
||
659 | pzErrMsg = pParse.zErrMsg; |
||
660 | sqlite3_log( pParse.rc, "%s", pzErrMsg ); |
||
661 | pParse.zErrMsg = string.Empty; |
||
662 | nErr++; |
||
663 | } |
||
664 | if ( pParse.pVdbe != null && pParse.nErr > 0 && pParse.nested == 0 ) |
||
665 | { |
||
666 | sqlite3VdbeDelete( ref pParse.pVdbe ); |
||
667 | pParse.pVdbe = null; |
||
668 | } |
||
669 | #if !SQLITE_OMIT_SHARED_CACHE |
||
670 | if ( pParse.nested == 0 ) |
||
671 | { |
||
672 | sqlite3DbFree( db, ref pParse.aTableLock ); |
||
673 | pParse.aTableLock = null; |
||
674 | pParse.nTableLock = 0; |
||
675 | } |
||
676 | #endif |
||
677 | #if !SQLITE_OMIT_VIRTUALTABLE |
||
678 | pParse.apVtabLock = null;//sqlite3_free( pParse.apVtabLock ); |
||
679 | #endif |
||
680 | if ( !IN_DECLARE_VTAB(pParse) ) |
||
681 | { |
||
682 | /* If the pParse.declareVtab flag is set, do not delete any table |
||
683 | ** structure built up in pParse.pNewTable. The calling code (see vtab.c) |
||
684 | ** will take responsibility for freeing the Table structure. |
||
685 | */ |
||
686 | sqlite3DeleteTable( db, ref pParse.pNewTable ); |
||
687 | } |
||
688 | |||
689 | #if !SQLITE_OMIT_TRIGGER |
||
690 | sqlite3DeleteTrigger( db, ref pParse.pNewTrigger ); |
||
691 | #endif |
||
692 | //for ( i = pParse.nzVar - 1; i >= 0; i-- ) |
||
693 | // sqlite3DbFree( db, pParse.azVar[i] ); |
||
694 | sqlite3DbFree( db, ref pParse.azVar ); |
||
695 | sqlite3DbFree( db, ref pParse.aAlias ); |
||
696 | while ( pParse.pAinc != null ) |
||
697 | { |
||
698 | AutoincInfo p = pParse.pAinc; |
||
699 | pParse.pAinc = p.pNext; |
||
700 | sqlite3DbFree( db, ref p ); |
||
701 | } |
||
702 | while ( pParse.pZombieTab != null ) |
||
703 | { |
||
704 | Table p = pParse.pZombieTab; |
||
705 | pParse.pZombieTab = p.pNextZombie; |
||
706 | sqlite3DeleteTable( db, ref p ); |
||
707 | } |
||
708 | if ( nErr > 0 && pParse.rc == SQLITE_OK ) |
||
709 | { |
||
710 | pParse.rc = SQLITE_ERROR; |
||
711 | } |
||
712 | return nErr; |
||
713 | } |
||
714 | } |
||
715 | } |