|
dvander@1203
|
1 |
/* |
|
dvander@1203
|
2 |
** 2001 September 15 |
|
dvander@1203
|
3 |
** |
|
dvander@1203
|
4 |
** The author disclaims copyright to this source code. In place of |
|
dvander@1203
|
5 |
** a legal notice, here is a blessing: |
|
dvander@1203
|
6 |
** |
|
dvander@1203
|
7 |
** May you do good and not evil. |
|
dvander@1203
|
8 |
** May you find forgiveness for yourself and forgive others. |
|
dvander@1203
|
9 |
** May you share freely, never taking more than you give. |
|
dvander@1203
|
10 |
** |
|
dvander@1203
|
11 |
************************************************************************* |
|
dvander@1203
|
12 |
** An tokenizer for SQL |
|
dvander@1203
|
13 |
** |
|
dvander@1203
|
14 |
** This file contains C code that splits an SQL input string up into |
|
dvander@1203
|
15 |
** individual tokens and sends those tokens one-by-one over to the |
|
dvander@1203
|
16 |
** parser for analysis. |
|
dvander@1203
|
17 |
** |
|
dvander@1203
|
18 |
** $Id$ |
|
dvander@1203
|
19 |
*/ |
|
dvander@1203
|
20 |
#include "sqliteInt.h" |
|
dvander@1203
|
21 |
#include "os.h" |
|
dvander@1203
|
22 |
#include <ctype.h> |
|
dvander@1203
|
23 |
#include <stdlib.h> |
|
dvander@1203
|
24 |
|
|
dvander@1203
|
25 |
/* |
|
dvander@1203
|
26 |
** The charMap() macro maps alphabetic characters into their |
|
dvander@1203
|
27 |
** lower-case ASCII equivalent. On ASCII machines, this is just |
|
dvander@1203
|
28 |
** an upper-to-lower case map. On EBCDIC machines we also need |
|
dvander@1203
|
29 |
** to adjust the encoding. Only alphabetic characters and underscores |
|
dvander@1203
|
30 |
** need to be translated. |
|
dvander@1203
|
31 |
*/ |
|
dvander@1203
|
32 |
#ifdef SQLITE_ASCII |
|
dvander@1203
|
33 |
# define charMap(X) sqlite3UpperToLower[(unsigned char)X] |
|
dvander@1203
|
34 |
#endif |
|
dvander@1203
|
35 |
#ifdef SQLITE_EBCDIC |
|
dvander@1203
|
36 |
# define charMap(X) ebcdicToAscii[(unsigned char)X] |
|
dvander@1203
|
37 |
const unsigned char ebcdicToAscii[] = { |
|
dvander@1203
|
38 |
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ |
|
dvander@1203
|
39 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 0x */ |
|
dvander@1203
|
40 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 1x */ |
|
dvander@1203
|
41 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ |
|
dvander@1203
|
42 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 3x */ |
|
dvander@1203
|
43 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 4x */ |
|
dvander@1203
|
44 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 5x */ |
|
dvander@1203
|
45 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 95, 0, 0, /* 6x */ |
|
dvander@1203
|
46 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 7x */ |
|
dvander@1203
|
47 |
0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* 8x */ |
|
dvander@1203
|
48 |
0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* 9x */ |
|
dvander@1203
|
49 |
0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ax */ |
|
dvander@1203
|
50 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ |
|
dvander@1203
|
51 |
0, 97, 98, 99,100,101,102,103,104,105, 0, 0, 0, 0, 0, 0, /* Cx */ |
|
dvander@1203
|
52 |
0,106,107,108,109,110,111,112,113,114, 0, 0, 0, 0, 0, 0, /* Dx */ |
|
dvander@1203
|
53 |
0, 0,115,116,117,118,119,120,121,122, 0, 0, 0, 0, 0, 0, /* Ex */ |
|
dvander@1203
|
54 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Fx */ |
|
dvander@1203
|
55 |
}; |
|
dvander@1203
|
56 |
#endif |
|
dvander@1203
|
57 |
|
|
dvander@1203
|
58 |
/* |
|
dvander@1203
|
59 |
** The sqlite3KeywordCode function looks up an identifier to determine if |
|
dvander@1203
|
60 |
** it is a keyword. If it is a keyword, the token code of that keyword is |
|
dvander@1203
|
61 |
** returned. If the input is not a keyword, TK_ID is returned. |
|
dvander@1203
|
62 |
** |
|
dvander@1203
|
63 |
** The implementation of this routine was generated by a program, |
|
dvander@1203
|
64 |
** mkkeywordhash.h, located in the tool subdirectory of the distribution. |
|
dvander@1203
|
65 |
** The output of the mkkeywordhash.c program is written into a file |
|
dvander@1203
|
66 |
** named keywordhash.h and then included into this source file by |
|
dvander@1203
|
67 |
** the #include below. |
|
dvander@1203
|
68 |
*/ |
|
dvander@1203
|
69 |
#include "keywordhash.h" |
|
dvander@1203
|
70 |
|
|
dvander@1203
|
71 |
|
|
dvander@1203
|
72 |
/* |
|
dvander@1203
|
73 |
** If X is a character that can be used in an identifier then |
|
dvander@1203
|
74 |
** IdChar(X) will be true. Otherwise it is false. |
|
dvander@1203
|
75 |
** |
|
dvander@1203
|
76 |
** For ASCII, any character with the high-order bit set is |
|
dvander@1203
|
77 |
** allowed in an identifier. For 7-bit characters, |
|
dvander@1203
|
78 |
** sqlite3IsIdChar[X] must be 1. |
|
dvander@1203
|
79 |
** |
|
dvander@1203
|
80 |
** For EBCDIC, the rules are more complex but have the same |
|
dvander@1203
|
81 |
** end result. |
|
dvander@1203
|
82 |
** |
|
dvander@1203
|
83 |
** Ticket #1066. the SQL standard does not allow '$' in the |
|
dvander@1203
|
84 |
** middle of identfiers. But many SQL implementations do. |
|
dvander@1203
|
85 |
** SQLite will allow '$' in identifiers for compatibility. |
|
dvander@1203
|
86 |
** But the feature is undocumented. |
|
dvander@1203
|
87 |
*/ |
|
dvander@1203
|
88 |
#ifdef SQLITE_ASCII |
|
dvander@1203
|
89 |
const char sqlite3IsIdChar[] = { |
|
dvander@1203
|
90 |
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ |
|
dvander@1203
|
91 |
0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* 2x */ |
|
dvander@1203
|
92 |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x */ |
|
dvander@1203
|
93 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x */ |
|
dvander@1203
|
94 |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x */ |
|
dvander@1203
|
95 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x */ |
|
dvander@1203
|
96 |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, /* 7x */ |
|
dvander@1203
|
97 |
}; |
|
dvander@1203
|
98 |
#define IdChar(C) (((c=C)&0x80)!=0 || (c>0x1f && sqlite3IsIdChar[c-0x20])) |
|
dvander@1203
|
99 |
#endif |
|
dvander@1203
|
100 |
#ifdef SQLITE_EBCDIC |
|
dvander@1203
|
101 |
const char sqlite3IsIdChar[] = { |
|
dvander@1203
|
102 |
/* x0 x1 x2 x3 x4 x5 x6 x7 x8 x9 xA xB xC xD xE xF */ |
|
dvander@1203
|
103 |
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 4x */ |
|
dvander@1203
|
104 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, /* 5x */ |
|
dvander@1203
|
105 |
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, /* 6x */ |
|
dvander@1203
|
106 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, /* 7x */ |
|
dvander@1203
|
107 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 0, /* 8x */ |
|
dvander@1203
|
108 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 0, /* 9x */ |
|
dvander@1203
|
109 |
1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, /* Ax */ |
|
dvander@1203
|
110 |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, /* Bx */ |
|
dvander@1203
|
111 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Cx */ |
|
dvander@1203
|
112 |
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Dx */ |
|
dvander@1203
|
113 |
0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, /* Ex */ |
|
dvander@1203
|
114 |
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, /* Fx */ |
|
dvander@1203
|
115 |
}; |
|
dvander@1203
|
116 |
#define IdChar(C) (((c=C)>=0x42 && sqlite3IsIdChar[c-0x40])) |
|
dvander@1203
|
117 |
#endif |
|
dvander@1203
|
118 |
|
|
dvander@1203
|
119 |
|
|
dvander@1203
|
120 |
/* |
|
dvander@1203
|
121 |
** Return the length of the token that begins at z[0]. |
|
dvander@1203
|
122 |
** Store the token type in *tokenType before returning. |
|
dvander@1203
|
123 |
*/ |
|
dvander@1203
|
124 |
static int getToken(const unsigned char *z, int *tokenType){ |
|
dvander@1203
|
125 |
int i, c; |
|
dvander@1203
|
126 |
switch( *z ){ |
|
dvander@1203
|
127 |
case ' ': case '\t': case '\n': case '\f': case '\r': { |
|
dvander@1203
|
128 |
for(i=1; isspace(z[i]); i++){} |
|
dvander@1203
|
129 |
*tokenType = TK_SPACE; |
|
dvander@1203
|
130 |
return i; |
|
dvander@1203
|
131 |
} |
|
dvander@1203
|
132 |
case '-': { |
|
dvander@1203
|
133 |
if( z[1]=='-' ){ |
|
dvander@1203
|
134 |
for(i=2; (c=z[i])!=0 && c!='\n'; i++){} |
|
dvander@1203
|
135 |
*tokenType = TK_COMMENT; |
|
dvander@1203
|
136 |
return i; |
|
dvander@1203
|
137 |
} |
|
dvander@1203
|
138 |
*tokenType = TK_MINUS; |
|
dvander@1203
|
139 |
return 1; |
|
dvander@1203
|
140 |
} |
|
dvander@1203
|
141 |
case '(': { |
|
dvander@1203
|
142 |
*tokenType = TK_LP; |
|
dvander@1203
|
143 |
return 1; |
|
dvander@1203
|
144 |
} |
|
dvander@1203
|
145 |
case ')': { |
|
dvander@1203
|
146 |
*tokenType = TK_RP; |
|
dvander@1203
|
147 |
return 1; |
|
dvander@1203
|
148 |
} |
|
dvander@1203
|
149 |
case ';': { |
|
dvander@1203
|
150 |
*tokenType = TK_SEMI; |
|
dvander@1203
|
151 |
return 1; |
|
dvander@1203
|
152 |
} |
|
dvander@1203
|
153 |
case '+': { |
|
dvander@1203
|
154 |
*tokenType = TK_PLUS; |
|
dvander@1203
|
155 |
return 1; |
|
dvander@1203
|
156 |
} |
|
dvander@1203
|
157 |
case '*': { |
|
dvander@1203
|
158 |
*tokenType = TK_STAR; |
|
dvander@1203
|
159 |
return 1; |
|
dvander@1203
|
160 |
} |
|
dvander@1203
|
161 |
case '/': { |
|
dvander@1203
|
162 |
if( z[1]!='*' || z[2]==0 ){ |
|
dvander@1203
|
163 |
*tokenType = TK_SLASH; |
|
dvander@1203
|
164 |
return 1; |
|
dvander@1203
|
165 |
} |
|
dvander@1203
|
166 |
for(i=3, c=z[2]; (c!='*' || z[i]!='/') && (c=z[i])!=0; i++){} |
|
dvander@1203
|
167 |
if( c ) i++; |
|
dvander@1203
|
168 |
*tokenType = TK_COMMENT; |
|
dvander@1203
|
169 |
return i; |
|
dvander@1203
|
170 |
} |
|
dvander@1203
|
171 |
case '%': { |
|
dvander@1203
|
172 |
*tokenType = TK_REM; |
|
dvander@1203
|
173 |
return 1; |
|
dvander@1203
|
174 |
} |
|
dvander@1203
|
175 |
case '=': { |
|
dvander@1203
|
176 |
*tokenType = TK_EQ; |
|
dvander@1203
|
177 |
return 1 + (z[1]=='='); |
|
dvander@1203
|
178 |
} |
|
dvander@1203
|
179 |
case '<': { |
|
dvander@1203
|
180 |
if( (c=z[1])=='=' ){ |
|
dvander@1203
|
181 |
*tokenType = TK_LE; |
|
dvander@1203
|
182 |
return 2; |
|
dvander@1203
|
183 |
}else if( c=='>' ){ |
|
dvander@1203
|
184 |
*tokenType = TK_NE; |
|
dvander@1203
|
185 |
return 2; |
|
dvander@1203
|
186 |
}else if( c=='<' ){ |
|
dvander@1203
|
187 |
*tokenType = TK_LSHIFT; |
|
dvander@1203
|
188 |
return 2; |
|
dvander@1203
|
189 |
}else{ |
|
dvander@1203
|
190 |
*tokenType = TK_LT; |
|
dvander@1203
|
191 |
return 1; |
|
dvander@1203
|
192 |
} |
|
dvander@1203
|
193 |
} |
|
dvander@1203
|
194 |
case '>': { |
|
dvander@1203
|
195 |
if( (c=z[1])=='=' ){ |
|
dvander@1203
|
196 |
*tokenType = TK_GE; |
|
dvander@1203
|
197 |
return 2; |
|
dvander@1203
|
198 |
}else if( c=='>' ){ |
|
dvander@1203
|
199 |
*tokenType = TK_RSHIFT; |
|
dvander@1203
|
200 |
return 2; |
|
dvander@1203
|
201 |
}else{ |
|
dvander@1203
|
202 |
*tokenType = TK_GT; |
|
dvander@1203
|
203 |
return 1; |
|
dvander@1203
|
204 |
} |
|
dvander@1203
|
205 |
} |
|
dvander@1203
|
206 |
case '!': { |
|
dvander@1203
|
207 |
if( z[1]!='=' ){ |
|
dvander@1203
|
208 |
*tokenType = TK_ILLEGAL; |
|
dvander@1203
|
209 |
return 2; |
|
dvander@1203
|
210 |
}else{ |
|
dvander@1203
|
211 |
*tokenType = TK_NE; |
|
dvander@1203
|
212 |
return 2; |
|
dvander@1203
|
213 |
} |
|
dvander@1203
|
214 |
} |
|
dvander@1203
|
215 |
case '|': { |
|
dvander@1203
|
216 |
if( z[1]!='|' ){ |
|
dvander@1203
|
217 |
*tokenType = TK_BITOR; |
|
dvander@1203
|
218 |
return 1; |
|
dvander@1203
|
219 |
}else{ |
|
dvander@1203
|
220 |
*tokenType = TK_CONCAT; |
|
dvander@1203
|
221 |
return 2; |
|
dvander@1203
|
222 |
} |
|
dvander@1203
|
223 |
} |
|
dvander@1203
|
224 |
case ',': { |
|
dvander@1203
|
225 |
*tokenType = TK_COMMA; |
|
dvander@1203
|
226 |
return 1; |
|
dvander@1203
|
227 |
} |
|
dvander@1203
|
228 |
case '&': { |
|
dvander@1203
|
229 |
*tokenType = TK_BITAND; |
|
dvander@1203
|
230 |
return 1; |
|
dvander@1203
|
231 |
} |
|
dvander@1203
|
232 |
case '~': { |
|
dvander@1203
|
233 |
*tokenType = TK_BITNOT; |
|
dvander@1203
|
234 |
return 1; |
|
dvander@1203
|
235 |
} |
|
dvander@1203
|
236 |
case '`': |
|
dvander@1203
|
237 |
case '\'': |
|
dvander@1203
|
238 |
case '"': { |
|
dvander@1203
|
239 |
int delim = z[0]; |
|
dvander@1203
|
240 |
for(i=1; (c=z[i])!=0; i++){ |
|
dvander@1203
|
241 |
if( c==delim ){ |
|
dvander@1203
|
242 |
if( z[i+1]==delim ){ |
|
dvander@1203
|
243 |
i++; |
|
dvander@1203
|
244 |
}else{ |
|
dvander@1203
|
245 |
break; |
|
dvander@1203
|
246 |
} |
|
dvander@1203
|
247 |
} |
|
dvander@1203
|
248 |
} |
|
dvander@1203
|
249 |
if( c ){ |
|
dvander@1203
|
250 |
*tokenType = TK_STRING; |
|
dvander@1203
|
251 |
return i+1; |
|
dvander@1203
|
252 |
}else{ |
|
dvander@1203
|
253 |
*tokenType = TK_ILLEGAL; |
|
dvander@1203
|
254 |
return i; |
|
dvander@1203
|
255 |
} |
|
dvander@1203
|
256 |
} |
|
dvander@1203
|
257 |
case '.': { |
|
dvander@1203
|
258 |
#ifndef SQLITE_OMIT_FLOATING_POINT |
|
dvander@1203
|
259 |
if( !isdigit(z[1]) ) |
|
dvander@1203
|
260 |
#endif |
|
dvander@1203
|
261 |
{ |
|
dvander@1203
|
262 |
*tokenType = TK_DOT; |
|
dvander@1203
|
263 |
return 1; |
|
dvander@1203
|
264 |
} |
|
dvander@1203
|
265 |
/* If the next character is a digit, this is a floating point |
|
dvander@1203
|
266 |
** number that begins with ".". Fall thru into the next case */ |
|
dvander@1203
|
267 |
} |
|
dvander@1203
|
268 |
case '0': case '1': case '2': case '3': case '4': |
|
dvander@1203
|
269 |
case '5': case '6': case '7': case '8': case '9': { |
|
dvander@1203
|
270 |
*tokenType = TK_INTEGER; |
|
dvander@1203
|
271 |
for(i=0; isdigit(z[i]); i++){} |
|
dvander@1203
|
272 |
#ifndef SQLITE_OMIT_FLOATING_POINT |
|
dvander@1203
|
273 |
if( z[i]=='.' ){ |
|
dvander@1203
|
274 |
i++; |
|
dvander@1203
|
275 |
while( isdigit(z[i]) ){ i++; } |
|
dvander@1203
|
276 |
*tokenType = TK_FLOAT; |
|
dvander@1203
|
277 |
} |
|
dvander@1203
|
278 |
if( (z[i]=='e' || z[i]=='E') && |
|
dvander@1203
|
279 |
( isdigit(z[i+1]) |
|
dvander@1203
|
280 |
|| ((z[i+1]=='+' || z[i+1]=='-') && isdigit(z[i+2])) |
|
dvander@1203
|
281 |
) |
|
dvander@1203
|
282 |
){ |
|
dvander@1203
|
283 |
i += 2; |
|
dvander@1203
|
284 |
while( isdigit(z[i]) ){ i++; } |
|
dvander@1203
|
285 |
*tokenType = TK_FLOAT; |
|
dvander@1203
|
286 |
} |
|
dvander@1203
|
287 |
#endif |
|
dvander@1203
|
288 |
while( IdChar(z[i]) ){ |
|
dvander@1203
|
289 |
*tokenType = TK_ILLEGAL; |
|
dvander@1203
|
290 |
i++; |
|
dvander@1203
|
291 |
} |
|
dvander@1203
|
292 |
return i; |
|
dvander@1203
|
293 |
} |
|
dvander@1203
|
294 |
case '[': { |
|
dvander@1203
|
295 |
for(i=1, c=z[0]; c!=']' && (c=z[i])!=0; i++){} |
|
dvander@1203
|
296 |
*tokenType = TK_ID; |
|
dvander@1203
|
297 |
return i; |
|
dvander@1203
|
298 |
} |
|
dvander@1203
|
299 |
case '?': { |
|
dvander@1203
|
300 |
*tokenType = TK_VARIABLE; |
|
dvander@1203
|
301 |
for(i=1; isdigit(z[i]); i++){} |
|
dvander@1203
|
302 |
return i; |
|
dvander@1203
|
303 |
} |
|
dvander@1203
|
304 |
case '#': { |
|
dvander@1203
|
305 |
for(i=1; isdigit(z[i]); i++){} |
|
dvander@1203
|
306 |
if( i>1 ){ |
|
dvander@1203
|
307 |
/* Parameters of the form #NNN (where NNN is a number) are used |
|
dvander@1203
|
308 |
** internally by sqlite3NestedParse. */ |
|
dvander@1203
|
309 |
*tokenType = TK_REGISTER; |
|
dvander@1203
|
310 |
return i; |
|
dvander@1203
|
311 |
} |
|
dvander@1203
|
312 |
/* Fall through into the next case if the '#' is not followed by |
|
dvander@1203
|
313 |
** a digit. Try to match #AAAA where AAAA is a parameter name. */ |
|
dvander@1203
|
314 |
} |
|
dvander@1203
|
315 |
#ifndef SQLITE_OMIT_TCL_VARIABLE |
|
dvander@1203
|
316 |
case '$': |
|
dvander@1203
|
317 |
#endif |
|
dvander@1203
|
318 |
case '@': /* For compatibility with MS SQL Server */ |
|
dvander@1203
|
319 |
case ':': { |
|
dvander@1203
|
320 |
int n = 0; |
|
dvander@1203
|
321 |
*tokenType = TK_VARIABLE; |
|
dvander@1203
|
322 |
for(i=1; (c=z[i])!=0; i++){ |
|
dvander@1203
|
323 |
if( IdChar(c) ){ |
|
dvander@1203
|
324 |
n++; |
|
dvander@1203
|
325 |
#ifndef SQLITE_OMIT_TCL_VARIABLE |
|
dvander@1203
|
326 |
}else if( c=='(' && n>0 ){ |
|
dvander@1203
|
327 |
do{ |
|
dvander@1203
|
328 |
i++; |
|
dvander@1203
|
329 |
}while( (c=z[i])!=0 && !isspace(c) && c!=')' ); |
|
dvander@1203
|
330 |
if( c==')' ){ |
|
dvander@1203
|
331 |
i++; |
|
dvander@1203
|
332 |
}else{ |
|
dvander@1203
|
333 |
*tokenType = TK_ILLEGAL; |
|
dvander@1203
|
334 |
} |
|
dvander@1203
|
335 |
break; |
|
dvander@1203
|
336 |
}else if( c==':' && z[i+1]==':' ){ |
|
dvander@1203
|
337 |
i++; |
|
dvander@1203
|
338 |
#endif |
|
dvander@1203
|
339 |
}else{ |
|
dvander@1203
|
340 |
break; |
|
dvander@1203
|
341 |
} |
|
dvander@1203
|
342 |
} |
|
dvander@1203
|
343 |
if( n==0 ) *tokenType = TK_ILLEGAL; |
|
dvander@1203
|
344 |
return i; |
|
dvander@1203
|
345 |
} |
|
dvander@1203
|
346 |
#ifndef SQLITE_OMIT_BLOB_LITERAL |
|
dvander@1203
|
347 |
case 'x': case 'X': { |
|
dvander@1203
|
348 |
if( (c=z[1])=='\'' || c=='"' ){ |
|
dvander@1203
|
349 |
int delim = c; |
|
dvander@1203
|
350 |
*tokenType = TK_BLOB; |
|
dvander@1203
|
351 |
for(i=2; (c=z[i])!=0; i++){ |
|
dvander@1203
|
352 |
if( c==delim ){ |
|
dvander@1203
|
353 |
if( i%2 ) *tokenType = TK_ILLEGAL; |
|
dvander@1203
|
354 |
break; |
|
dvander@1203
|
355 |
} |
|
dvander@1203
|
356 |
if( !isxdigit(c) ){ |
|
dvander@1203
|
357 |
*tokenType = TK_ILLEGAL; |
|
dvander@1203
|
358 |
return i; |
|
dvander@1203
|
359 |
} |
|
dvander@1203
|
360 |
} |
|
dvander@1203
|
361 |
if( c ) i++; |
|
dvander@1203
|
362 |
return i; |
|
dvander@1203
|
363 |
} |
|
dvander@1203
|
364 |
/* Otherwise fall through to the next case */ |
|
dvander@1203
|
365 |
} |
|
dvander@1203
|
366 |
#endif |
|
dvander@1203
|
367 |
default: { |
|
dvander@1203
|
368 |
if( !IdChar(*z) ){ |
|
dvander@1203
|
369 |
break; |
|
dvander@1203
|
370 |
} |
|
dvander@1203
|
371 |
for(i=1; IdChar(z[i]); i++){} |
|
dvander@1203
|
372 |
*tokenType = keywordCode((char*)z, i); |
|
dvander@1203
|
373 |
return i; |
|
dvander@1203
|
374 |
} |
|
dvander@1203
|
375 |
} |
|
dvander@1203
|
376 |
*tokenType = TK_ILLEGAL; |
|
dvander@1203
|
377 |
return 1; |
|
dvander@1203
|
378 |
} |
|
dvander@1203
|
379 |
int sqlite3GetToken(const unsigned char *z, int *tokenType){ |
|
dvander@1203
|
380 |
return getToken(z, tokenType); |
|
dvander@1203
|
381 |
} |
|
dvander@1203
|
382 |
|
|
dvander@1203
|
383 |
/* |
|
dvander@1203
|
384 |
** The interface to the LEMON-generated parser |
|
dvander@1203
|
385 |
*/ |
|
dvander@1203
|
386 |
void *sqlite3ParserAlloc(void*(*)(size_t)); |
|
dvander@1203
|
387 |
void sqlite3ParserFree(void*, void(*)(void*)); |
|
dvander@1203
|
388 |
void sqlite3Parser(void*, int, Token, Parse*); |
|
dvander@1203
|
389 |
|
|
dvander@1203
|
390 |
/* |
|
dvander@1203
|
391 |
** Run the parser on the given SQL string. The parser structure is |
|
dvander@1203
|
392 |
** passed in. An SQLITE_ status code is returned. If an error occurs |
|
dvander@1203
|
393 |
** and pzErrMsg!=NULL then an error message might be written into |
|
dvander@1203
|
394 |
** memory obtained from malloc() and *pzErrMsg made to point to that |
|
dvander@1203
|
395 |
** error message. Or maybe not. |
|
dvander@1203
|
396 |
*/ |
|
dvander@1203
|
397 |
int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzErrMsg){ |
|
dvander@1203
|
398 |
int nErr = 0; |
|
dvander@1203
|
399 |
int i; |
|
dvander@1203
|
400 |
void *pEngine; |
|
dvander@1203
|
401 |
int tokenType; |
|
dvander@1203
|
402 |
int lastTokenParsed = -1; |
|
dvander@1203
|
403 |
sqlite3 *db = pParse->db; |
|
dvander@1203
|
404 |
|
|
dvander@1203
|
405 |
if( db->activeVdbeCnt==0 ){ |
|
dvander@1203
|
406 |
db->u1.isInterrupted = 0; |
|
dvander@1203
|
407 |
} |
|
dvander@1203
|
408 |
pParse->rc = SQLITE_OK; |
|
dvander@1203
|
409 |
i = 0; |
|
dvander@1203
|
410 |
pEngine = sqlite3ParserAlloc((void*(*)(size_t))sqlite3MallocX); |
|
dvander@1203
|
411 |
if( pEngine==0 ){ |
|
dvander@1203
|
412 |
return SQLITE_NOMEM; |
|
dvander@1203
|
413 |
} |
|
dvander@1203
|
414 |
assert( pParse->sLastToken.dyn==0 ); |
|
dvander@1203
|
415 |
assert( pParse->pNewTable==0 ); |
|
dvander@1203
|
416 |
assert( pParse->pNewTrigger==0 ); |
|
dvander@1203
|
417 |
assert( pParse->nVar==0 ); |
|
dvander@1203
|
418 |
assert( pParse->nVarExpr==0 ); |
|
dvander@1203
|
419 |
assert( pParse->nVarExprAlloc==0 ); |
|
dvander@1203
|
420 |
assert( pParse->apVarExpr==0 ); |
|
dvander@1203
|
421 |
pParse->zTail = pParse->zSql = zSql; |
|
dvander@1203
|
422 |
while( !sqlite3MallocFailed() && zSql[i]!=0 ){ |
|
dvander@1203
|
423 |
assert( i>=0 ); |
|
dvander@1203
|
424 |
pParse->sLastToken.z = (u8*)&zSql[i]; |
|
dvander@1203
|
425 |
assert( pParse->sLastToken.dyn==0 ); |
|
dvander@1203
|
426 |
pParse->sLastToken.n = getToken((unsigned char*)&zSql[i],&tokenType); |
|
dvander@1203
|
427 |
i += pParse->sLastToken.n; |
|
dvander@1203
|
428 |
if( i>SQLITE_MAX_SQL_LENGTH ){ |
|
dvander@1203
|
429 |
pParse->rc = SQLITE_TOOBIG; |
|
dvander@1203
|
430 |
break; |
|
dvander@1203
|
431 |
} |
|
dvander@1203
|
432 |
switch( tokenType ){ |
|
dvander@1203
|
433 |
case TK_SPACE: |
|
dvander@1203
|
434 |
case TK_COMMENT: { |
|
dvander@1203
|
435 |
if( db->u1.isInterrupted ){ |
|
dvander@1203
|
436 |
pParse->rc = SQLITE_INTERRUPT; |
|
dvander@1203
|
437 |
sqlite3SetString(pzErrMsg, "interrupt", (char*)0); |
|
dvander@1203
|
438 |
goto abort_parse; |
|
dvander@1203
|
439 |
} |
|
dvander@1203
|
440 |
break; |
|
dvander@1203
|
441 |
} |
|
dvander@1203
|
442 |
case TK_ILLEGAL: { |
|
dvander@1203
|
443 |
if( pzErrMsg ){ |
|
dvander@1203
|
444 |
sqliteFree(*pzErrMsg); |
|
dvander@1203
|
445 |
*pzErrMsg = sqlite3MPrintf("unrecognized token: \"%T\"", |
|
dvander@1203
|
446 |
&pParse->sLastToken); |
|
dvander@1203
|
447 |
} |
|
dvander@1203
|
448 |
nErr++; |
|
dvander@1203
|
449 |
goto abort_parse; |
|
dvander@1203
|
450 |
} |
|
dvander@1203
|
451 |
case TK_SEMI: { |
|
dvander@1203
|
452 |
pParse->zTail = &zSql[i]; |
|
dvander@1203
|
453 |
/* Fall thru into the default case */ |
|
dvander@1203
|
454 |
} |
|
dvander@1203
|
455 |
default: { |
|
dvander@1203
|
456 |
sqlite3Parser(pEngine, tokenType, pParse->sLastToken, pParse); |
|
dvander@1203
|
457 |
lastTokenParsed = tokenType; |
|
dvander@1203
|
458 |
if( pParse->rc!=SQLITE_OK ){ |
|
dvander@1203
|
459 |
goto abort_parse; |
|
dvander@1203
|
460 |
} |
|
dvander@1203
|
461 |
break; |
|
dvander@1203
|
462 |
} |
|
dvander@1203
|
463 |
} |
|
dvander@1203
|
464 |
} |
|
dvander@1203
|
465 |
abort_parse: |
|
dvander@1203
|
466 |
if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){ |
|
dvander@1203
|
467 |
if( lastTokenParsed!=TK_SEMI ){ |
|
dvander@1203
|
468 |
sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse); |
|
dvander@1203
|
469 |
pParse->zTail = &zSql[i]; |
|
dvander@1203
|
470 |
} |
|
dvander@1203
|
471 |
sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse); |
|
dvander@1203
|
472 |
} |
|
dvander@1203
|
473 |
sqlite3ParserFree(pEngine, sqlite3FreeX); |
|
dvander@1203
|
474 |
if( sqlite3MallocFailed() ){ |
|
dvander@1203
|
475 |
pParse->rc = SQLITE_NOMEM; |
|
dvander@1203
|
476 |
} |
|
dvander@1203
|
477 |
if( pParse->rc!=SQLITE_OK && pParse->rc!=SQLITE_DONE && pParse->zErrMsg==0 ){ |
|
dvander@1203
|
478 |
sqlite3SetString(&pParse->zErrMsg, sqlite3ErrStr(pParse->rc), (char*)0); |
|
dvander@1203
|
479 |
} |
|
dvander@1203
|
480 |
if( pParse->zErrMsg ){ |
|
dvander@1203
|
481 |
if( pzErrMsg && *pzErrMsg==0 ){ |
|
dvander@1203
|
482 |
*pzErrMsg = pParse->zErrMsg; |
|
dvander@1203
|
483 |
}else{ |
|
dvander@1203
|
484 |
sqliteFree(pParse->zErrMsg); |
|
dvander@1203
|
485 |
} |
|
dvander@1203
|
486 |
pParse->zErrMsg = 0; |
|
dvander@1203
|
487 |
if( !nErr ) nErr++; |
|
dvander@1203
|
488 |
} |
|
dvander@1203
|
489 |
if( pParse->pVdbe && pParse->nErr>0 && pParse->nested==0 ){ |
|
dvander@1203
|
490 |
sqlite3VdbeDelete(pParse->pVdbe); |
|
dvander@1203
|
491 |
pParse->pVdbe = 0; |
|
dvander@1203
|
492 |
} |
|
dvander@1203
|
493 |
#ifndef SQLITE_OMIT_SHARED_CACHE |
|
dvander@1203
|
494 |
if( pParse->nested==0 ){ |
|
dvander@1203
|
495 |
sqliteFree(pParse->aTableLock); |
|
dvander@1203
|
496 |
pParse->aTableLock = 0; |
|
dvander@1203
|
497 |
pParse->nTableLock = 0; |
|
dvander@1203
|
498 |
} |
|
dvander@1203
|
499 |
#endif |
|
dvander@1203
|
500 |
|
|
dvander@1203
|
501 |
if( !IN_DECLARE_VTAB ){ |
|
dvander@1203
|
502 |
/* If the pParse->declareVtab flag is set, do not delete any table |
|
dvander@1203
|
503 |
** structure built up in pParse->pNewTable. The calling code (see vtab.c) |
|
dvander@1203
|
504 |
** will take responsibility for freeing the Table structure. |
|
dvander@1203
|
505 |
*/ |
|
dvander@1203
|
506 |
sqlite3DeleteTable(pParse->pNewTable); |
|
dvander@1203
|
507 |
} |
|
dvander@1203
|
508 |
|
|
dvander@1203
|
509 |
sqlite3DeleteTrigger(pParse->pNewTrigger); |
|
dvander@1203
|
510 |
sqliteFree(pParse->apVarExpr); |
|
dvander@1203
|
511 |
if( nErr>0 && (pParse->rc==SQLITE_OK || pParse->rc==SQLITE_DONE) ){ |
|
dvander@1203
|
512 |
pParse->rc = SQLITE_ERROR; |
|
dvander@1203
|
513 |
} |
|
dvander@1203
|
514 |
return nErr; |
|
dvander@1203
|
515 |
} |