Line data Source code
1 : /*
2 : * SPDX-License-Identifier: MPL-2.0
3 : *
4 : * This Source Code Form is subject to the terms of the Mozilla Public
5 : * License, v. 2.0. If a copy of the MPL was not distributed with this
6 : * file, You can obtain one at http://mozilla.org/MPL/2.0/.
7 : *
8 : * Copyright 2024 MonetDB Foundation;
9 : * Copyright August 2008 - 2023 MonetDB B.V.;
10 : * Copyright 1997 - July 2008 CWI.
11 : */
12 :
13 : #include "monetdb_config.h"
14 : #include <wctype.h>
15 : #include "sql_mem.h"
16 : #include "sql_scan.h"
17 : #include "sql_types.h"
18 : #include "sql_symbol.h"
19 : #include "sql_mvc.h"
20 : #include "sql_parser.tab.h"
21 : #include "sql_semantic.h"
22 : #include "sql_parser.h" /* for sql_error() */
23 :
24 : #include "stream.h"
25 : #include "mapi_prompt.h"
26 : #include <unistd.h>
27 : #include <string.h>
28 : #include <ctype.h>
29 : #include "sql_keyword.h"
30 :
31 : /**
32 : * Removes all comments before the query. In query comments are kept.
33 : */
34 : char *
35 401121 : query_cleaned(allocator *sa, const char *query)
36 : {
37 401121 : char *q, *r, *c = NULL;
38 401121 : int lines = 0;
39 401121 : int quote = 0; /* inside quotes ('..', "..", {..}) */
40 401121 : bool bs = false; /* seen a backslash in a quoted string */
41 401121 : bool incomment1 = false; /* inside traditional C style comment */
42 401121 : bool incomment2 = false; /* inside comment starting with -- */
43 401121 : bool inline_comment = false;
44 :
45 401121 : r = SA_NEW_ARRAY(sa, char, strlen(query) + 1);
46 401120 : if(!r)
47 : return NULL;
48 :
49 67770409 : for (q = r; *query; query++) {
50 67369289 : if (incomment1) {
51 16116 : if (*query == '/' && query[-1] == '*') {
52 233 : incomment1 = false;
53 233 : if (c == r && lines > 0) {
54 225 : q = r; // reset to beginning
55 225 : lines = 0;
56 225 : continue;
57 : }
58 : }
59 15891 : if (*query == '\n') lines++;
60 15891 : *q++ = *query;
61 67353173 : } else if (incomment2) {
62 827673 : if (*query == '\n') {
63 2832 : incomment2 = false;
64 2832 : inline_comment = false;
65 : /* add newline only if comment doesn't
66 : * occupy whole line */
67 2832 : if (q > r && q[-1] != '\n'){
68 939 : *q++ = '\n';
69 939 : lines++;
70 : }
71 824841 : } else if (inline_comment){
72 20650 : *q++ = *query; // preserve in line query comments
73 : }
74 66525500 : } else if (quote) {
75 22261142 : if (bs) {
76 : bs = false;
77 22257845 : } else if (*query == '\\') {
78 : bs = true;
79 22254548 : } else if (*query == quote) {
80 674381 : quote = 0;
81 : }
82 22261142 : *q++ = *query;
83 44264358 : } else if (*query == '"' || *query == '\'') {
84 673918 : quote = *query;
85 673918 : *q++ = *query;
86 43590440 : } else if (*query == '{') {
87 508 : quote = '}';
88 508 : *q++ = *query;
89 43589932 : } else if (*query == '-' && query[1] == '-') {
90 2832 : if (q > r && q[-1] != '\n') {
91 939 : inline_comment = true;
92 939 : *q++ = *query; // preserve in line query comments
93 : }
94 : incomment2 = true;
95 43587100 : } else if (*query == '/' && query[1] == '*') {
96 233 : incomment1 = true;
97 233 : c = q;
98 233 : *q++ = *query;
99 43586867 : } else if (*query == '\n') {
100 : /* collapse newlines */
101 862930 : if (q > r && q[-1] != '\n') {
102 820954 : *q++ = '\n';
103 820954 : lines++;
104 : }
105 42723937 : } else if (*query == ' ' || *query == '\t') {
106 : /* collapse white space */
107 7043737 : if (q > r && q[-1] != ' ')
108 5560618 : *q++ = ' ';
109 : } else {
110 35680200 : *q++ = *query;
111 : }
112 : }
113 401120 : *q = 0;
114 401120 : return r;
115 : }
116 :
117 : int
118 332 : scanner_init_keywords(void)
119 : {
120 332 : int failed = 0;
121 :
122 332 : failed += keywords_insert("false", BOOL_FALSE);
123 332 : failed += keywords_insert("true", BOOL_TRUE);
124 332 : failed += keywords_insert("bool", sqlBOOL);
125 :
126 332 : failed += keywords_insert("ALTER", ALTER);
127 332 : failed += keywords_insert("ADD", ADD);
128 332 : failed += keywords_insert("AND", AND);
129 :
130 332 : failed += keywords_insert("RANK", RANK);
131 332 : failed += keywords_insert("DENSE_RANK", RANK);
132 332 : failed += keywords_insert("PERCENT_RANK", RANK);
133 332 : failed += keywords_insert("CUME_DIST", RANK);
134 332 : failed += keywords_insert("ROW_NUMBER", RANK);
135 332 : failed += keywords_insert("NTILE", RANK);
136 332 : failed += keywords_insert("LAG", RANK);
137 332 : failed += keywords_insert("LEAD", RANK);
138 332 : failed += keywords_insert("FETCH", FETCH);
139 332 : failed += keywords_insert("FIRST_VALUE", RANK);
140 332 : failed += keywords_insert("LAST_VALUE", RANK);
141 332 : failed += keywords_insert("NTH_VALUE", RANK);
142 :
143 332 : failed += keywords_insert("BEST", BEST);
144 332 : failed += keywords_insert("EFFORT", EFFORT);
145 :
146 332 : failed += keywords_insert("AS", AS);
147 332 : failed += keywords_insert("ASC", ASC);
148 332 : failed += keywords_insert("AUTHORIZATION", AUTHORIZATION);
149 332 : failed += keywords_insert("BETWEEN", BETWEEN);
150 332 : failed += keywords_insert("SYMMETRIC", SYMMETRIC);
151 332 : failed += keywords_insert("ASYMMETRIC", ASYMMETRIC);
152 332 : failed += keywords_insert("BY", BY);
153 332 : failed += keywords_insert("CAST", CAST);
154 332 : failed += keywords_insert("CONVERT", CONVERT);
155 332 : failed += keywords_insert("CHARACTER", CHARACTER);
156 332 : failed += keywords_insert("CHAR", CHARACTER);
157 332 : failed += keywords_insert("VARYING", VARYING);
158 332 : failed += keywords_insert("VARCHAR", VARCHAR);
159 332 : failed += keywords_insert("BINARY", BINARY);
160 332 : failed += keywords_insert("LARGE", LARGE);
161 332 : failed += keywords_insert("OBJECT", OBJECT);
162 332 : failed += keywords_insert("CLOB", CLOB);
163 332 : failed += keywords_insert("BLOB", sqlBLOB);
164 332 : failed += keywords_insert("TEXT", sqlTEXT);
165 332 : failed += keywords_insert("TINYTEXT", sqlTEXT);
166 332 : failed += keywords_insert("STRING", CLOB); /* ? */
167 332 : failed += keywords_insert("CHECK", CHECK);
168 332 : failed += keywords_insert("CLIENT", CLIENT);
169 332 : failed += keywords_insert("SERVER", SERVER);
170 332 : failed += keywords_insert("COMMENT", COMMENT);
171 332 : failed += keywords_insert("CONSTRAINT", CONSTRAINT);
172 332 : failed += keywords_insert("CREATE", CREATE);
173 332 : failed += keywords_insert("CROSS", CROSS);
174 332 : failed += keywords_insert("COPY", COPY);
175 332 : failed += keywords_insert("RECORDS", RECORDS);
176 332 : failed += keywords_insert("DELIMITERS", DELIMITERS);
177 332 : failed += keywords_insert("STDIN", STDIN);
178 332 : failed += keywords_insert("STDOUT", STDOUT);
179 :
180 332 : failed += keywords_insert("TINYINT", TINYINT);
181 332 : failed += keywords_insert("SMALLINT", SMALLINT);
182 332 : failed += keywords_insert("INTEGER", sqlINTEGER);
183 332 : failed += keywords_insert("INT", sqlINTEGER);
184 332 : failed += keywords_insert("MEDIUMINT", sqlINTEGER);
185 332 : failed += keywords_insert("BIGINT", BIGINT);
186 : #ifdef HAVE_HGE
187 332 : failed += keywords_insert("HUGEINT", HUGEINT);
188 : #endif
189 332 : failed += keywords_insert("DEC", sqlDECIMAL);
190 332 : failed += keywords_insert("DECIMAL", sqlDECIMAL);
191 332 : failed += keywords_insert("NUMERIC", sqlDECIMAL);
192 332 : failed += keywords_insert("DECLARE", DECLARE);
193 332 : failed += keywords_insert("DEFAULT", DEFAULT);
194 332 : failed += keywords_insert("DESC", DESC);
195 332 : failed += keywords_insert("DISTINCT", DISTINCT);
196 332 : failed += keywords_insert("DOUBLE", sqlDOUBLE);
197 332 : failed += keywords_insert("REAL", sqlREAL);
198 332 : failed += keywords_insert("DROP", DROP);
199 332 : failed += keywords_insert("ESCAPE", ESCAPE);
200 332 : failed += keywords_insert("EXISTS", EXISTS);
201 332 : failed += keywords_insert("UESCAPE", UESCAPE);
202 332 : failed += keywords_insert("EXTRACT", EXTRACT);
203 332 : failed += keywords_insert("FLOAT", sqlFLOAT);
204 332 : failed += keywords_insert("FOR", FOR);
205 332 : failed += keywords_insert("FOREIGN", FOREIGN);
206 332 : failed += keywords_insert("FROM", FROM);
207 332 : failed += keywords_insert("FWF", FWF);
208 :
209 332 : failed += keywords_insert("BIG", BIG);
210 332 : failed += keywords_insert("LITTLE", LITTLE);
211 332 : failed += keywords_insert("NATIVE", NATIVE);
212 332 : failed += keywords_insert("ENDIAN", ENDIAN);
213 :
214 332 : failed += keywords_insert("REFERENCES", REFERENCES);
215 :
216 332 : failed += keywords_insert("MATCH", MATCH);
217 332 : failed += keywords_insert("FULL", FULL);
218 332 : failed += keywords_insert("PARTIAL", PARTIAL);
219 332 : failed += keywords_insert("SIMPLE", SIMPLE);
220 :
221 332 : failed += keywords_insert("INSERT", INSERT);
222 332 : failed += keywords_insert("UPDATE", UPDATE);
223 332 : failed += keywords_insert("DELETE", sqlDELETE);
224 332 : failed += keywords_insert("TRUNCATE", TRUNCATE);
225 332 : failed += keywords_insert("MATCHED", MATCHED);
226 :
227 332 : failed += keywords_insert("ACTION", ACTION);
228 332 : failed += keywords_insert("CASCADE", CASCADE);
229 332 : failed += keywords_insert("RESTRICT", RESTRICT);
230 332 : failed += keywords_insert("FIRST", FIRST);
231 332 : failed += keywords_insert("GLOBAL", GLOBAL);
232 332 : failed += keywords_insert("GROUP", sqlGROUP);
233 332 : failed += keywords_insert("GROUPING", GROUPING);
234 332 : failed += keywords_insert("ROLLUP", ROLLUP);
235 332 : failed += keywords_insert("CUBE", CUBE);
236 332 : failed += keywords_insert("HAVING", HAVING);
237 332 : failed += keywords_insert("ILIKE", ILIKE);
238 332 : failed += keywords_insert("IMPRINTS", IMPRINTS);
239 332 : failed += keywords_insert("IN", sqlIN);
240 332 : failed += keywords_insert("INNER", INNER);
241 332 : failed += keywords_insert("INTO", INTO);
242 332 : failed += keywords_insert("IS", IS);
243 332 : failed += keywords_insert("JOIN", JOIN);
244 332 : failed += keywords_insert("KEY", KEY);
245 332 : failed += keywords_insert("LATERAL", LATERAL);
246 332 : failed += keywords_insert("LEFT", LEFT);
247 332 : failed += keywords_insert("LIKE", LIKE);
248 332 : failed += keywords_insert("LIMIT", LIMIT);
249 332 : failed += keywords_insert("SAMPLE", SAMPLE);
250 332 : failed += keywords_insert("SEED", SEED);
251 332 : failed += keywords_insert("LAST", LAST);
252 332 : failed += keywords_insert("LOCAL", LOCAL);
253 332 : failed += keywords_insert("NATURAL", NATURAL);
254 332 : failed += keywords_insert("NOT", NOT);
255 332 : failed += keywords_insert("NULL", sqlNULL);
256 332 : failed += keywords_insert("NULLS", NULLS);
257 332 : failed += keywords_insert("OFFSET", OFFSET);
258 332 : failed += keywords_insert("ON", ON);
259 332 : failed += keywords_insert("OPTIONS", OPTIONS);
260 332 : failed += keywords_insert("OPTION", OPTION);
261 332 : failed += keywords_insert("OR", OR);
262 332 : failed += keywords_insert("ORDER", ORDER);
263 332 : failed += keywords_insert("ORDERED", ORDERED);
264 332 : failed += keywords_insert("OUTER", OUTER);
265 332 : failed += keywords_insert("OVER", OVER);
266 332 : failed += keywords_insert("PARTITION", PARTITION);
267 332 : failed += keywords_insert("PATH", PATH);
268 332 : failed += keywords_insert("PRECISION", PRECISION);
269 332 : failed += keywords_insert("PRIMARY", PRIMARY);
270 :
271 332 : failed += keywords_insert("USER", USER);
272 332 : failed += keywords_insert("RENAME", RENAME);
273 332 : failed += keywords_insert("UNENCRYPTED", UNENCRYPTED);
274 332 : failed += keywords_insert("ENCRYPTED", ENCRYPTED);
275 332 : failed += keywords_insert("PASSWORD", PASSWORD);
276 332 : failed += keywords_insert("GRANT", GRANT);
277 332 : failed += keywords_insert("REVOKE", REVOKE);
278 332 : failed += keywords_insert("ROLE", ROLE);
279 332 : failed += keywords_insert("ADMIN", ADMIN);
280 332 : failed += keywords_insert("PRIVILEGES", PRIVILEGES);
281 332 : failed += keywords_insert("PUBLIC", PUBLIC);
282 332 : failed += keywords_insert("CURRENT_USER", CURRENT_USER);
283 332 : failed += keywords_insert("CURRENT_ROLE", CURRENT_ROLE);
284 332 : failed += keywords_insert("SESSION_USER", SESSION_USER);
285 332 : failed += keywords_insert("CURRENT_SCHEMA", CURRENT_SCHEMA);
286 332 : failed += keywords_insert("SESSION", sqlSESSION);
287 332 : failed += keywords_insert("MAX_MEMORY", MAX_MEMORY);
288 332 : failed += keywords_insert("MAX_WORKERS", MAX_WORKERS);
289 332 : failed += keywords_insert("OPTIMIZER", OPTIMIZER);
290 :
291 332 : failed += keywords_insert("RIGHT", RIGHT);
292 332 : failed += keywords_insert("SCHEMA", SCHEMA);
293 332 : failed += keywords_insert("SELECT", SELECT);
294 332 : failed += keywords_insert("SET", SET);
295 332 : failed += keywords_insert("SETS", SETS);
296 332 : failed += keywords_insert("AUTO_COMMIT", AUTO_COMMIT);
297 :
298 332 : failed += keywords_insert("ALL", ALL);
299 332 : failed += keywords_insert("ANY", ANY);
300 332 : failed += keywords_insert("SOME", SOME);
301 332 : failed += keywords_insert("EVERY", ANY);
302 : /*
303 : failed += keywords_insert("SQLCODE", SQLCODE );
304 : */
305 332 : failed += keywords_insert("COLUMN", COLUMN);
306 332 : failed += keywords_insert("TABLE", TABLE);
307 332 : failed += keywords_insert("TEMPORARY", TEMPORARY);
308 332 : failed += keywords_insert("TEMP", TEMP);
309 332 : failed += keywords_insert("REMOTE", REMOTE);
310 332 : failed += keywords_insert("MERGE", MERGE);
311 332 : failed += keywords_insert("REPLICA", REPLICA);
312 332 : failed += keywords_insert("UNLOGGED", UNLOGGED);
313 332 : failed += keywords_insert("TO", TO);
314 332 : failed += keywords_insert("UNION", UNION);
315 332 : failed += keywords_insert("EXCEPT", EXCEPT);
316 332 : failed += keywords_insert("INTERSECT", INTERSECT);
317 332 : failed += keywords_insert("CORRESPONDING", CORRESPONDING);
318 332 : failed += keywords_insert("UNIQUE", UNIQUE);
319 332 : failed += keywords_insert("USING", USING);
320 332 : failed += keywords_insert("VALUES", VALUES);
321 332 : failed += keywords_insert("VIEW", VIEW);
322 332 : failed += keywords_insert("WHERE", WHERE);
323 332 : failed += keywords_insert("WITH", WITH);
324 332 : failed += keywords_insert("WITHOUT", WITHOUT);
325 332 : failed += keywords_insert("DATA", DATA);
326 :
327 332 : failed += keywords_insert("DATE", sqlDATE);
328 332 : failed += keywords_insert("TIME", TIME);
329 332 : failed += keywords_insert("TIMESTAMP", TIMESTAMP);
330 332 : failed += keywords_insert("INTERVAL", INTERVAL);
331 332 : failed += keywords_insert("CURRENT_DATE", CURRENT_DATE);
332 332 : failed += keywords_insert("CURRENT_TIME", CURRENT_TIME);
333 332 : failed += keywords_insert("CURRENT_TIMESTAMP", CURRENT_TIMESTAMP);
334 332 : failed += keywords_insert("CURRENT_TIMEZONE", CURRENT_TIMEZONE);
335 332 : failed += keywords_insert("NOW", CURRENT_TIMESTAMP);
336 332 : failed += keywords_insert("LOCALTIME", LOCALTIME);
337 332 : failed += keywords_insert("LOCALTIMESTAMP", LOCALTIMESTAMP);
338 332 : failed += keywords_insert("ZONE", ZONE);
339 :
340 332 : failed += keywords_insert("CENTURY", CENTURY);
341 332 : failed += keywords_insert("DECADE", DECADE);
342 332 : failed += keywords_insert("YEAR", YEAR);
343 332 : failed += keywords_insert("QUARTER", QUARTER);
344 332 : failed += keywords_insert("MONTH", MONTH);
345 332 : failed += keywords_insert("WEEK", WEEK);
346 332 : failed += keywords_insert("DOW", DOW);
347 332 : failed += keywords_insert("DOY", DOY);
348 332 : failed += keywords_insert("DAY", DAY);
349 332 : failed += keywords_insert("HOUR", HOUR);
350 332 : failed += keywords_insert("MINUTE", MINUTE);
351 332 : failed += keywords_insert("SECOND", SECOND);
352 332 : failed += keywords_insert("EPOCH", EPOCH);
353 :
354 332 : failed += keywords_insert("POSITION", POSITION);
355 332 : failed += keywords_insert("SUBSTRING", SUBSTRING);
356 332 : failed += keywords_insert("SPLIT_PART", SPLIT_PART);
357 332 : failed += keywords_insert("TRIM", TRIM);
358 332 : failed += keywords_insert("LEADING", LEADING);
359 332 : failed += keywords_insert("TRAILING", TRAILING);
360 332 : failed += keywords_insert("BOTH", BOTH);
361 :
362 332 : failed += keywords_insert("CASE", CASE);
363 332 : failed += keywords_insert("WHEN", WHEN);
364 332 : failed += keywords_insert("THEN", THEN);
365 332 : failed += keywords_insert("ELSE", ELSE);
366 332 : failed += keywords_insert("END", END);
367 332 : failed += keywords_insert("NULLIF", NULLIF);
368 332 : failed += keywords_insert("COALESCE", COALESCE);
369 332 : failed += keywords_insert("ELSEIF", ELSEIF);
370 332 : failed += keywords_insert("IF", IF);
371 332 : failed += keywords_insert("WHILE", WHILE);
372 332 : failed += keywords_insert("DO", DO);
373 :
374 332 : failed += keywords_insert("COMMIT", COMMIT);
375 332 : failed += keywords_insert("ROLLBACK", ROLLBACK);
376 332 : failed += keywords_insert("SAVEPOINT", SAVEPOINT);
377 332 : failed += keywords_insert("RELEASE", RELEASE);
378 332 : failed += keywords_insert("WORK", WORK);
379 332 : failed += keywords_insert("CHAIN", CHAIN);
380 332 : failed += keywords_insert("PRESERVE", PRESERVE);
381 332 : failed += keywords_insert("ROWS", ROWS);
382 332 : failed += keywords_insert("NO", NO);
383 332 : failed += keywords_insert("START", START);
384 332 : failed += keywords_insert("TRANSACTION", TRANSACTION);
385 332 : failed += keywords_insert("READ", READ);
386 332 : failed += keywords_insert("WRITE", WRITE);
387 332 : failed += keywords_insert("ONLY", ONLY);
388 332 : failed += keywords_insert("ISOLATION", ISOLATION);
389 332 : failed += keywords_insert("LEVEL", LEVEL);
390 332 : failed += keywords_insert("UNCOMMITTED", UNCOMMITTED);
391 332 : failed += keywords_insert("COMMITTED", COMMITTED);
392 332 : failed += keywords_insert("REPEATABLE", sqlREPEATABLE);
393 332 : failed += keywords_insert("SNAPSHOT", SNAPSHOT);
394 332 : failed += keywords_insert("SERIALIZABLE", SERIALIZABLE);
395 332 : failed += keywords_insert("DIAGNOSTICS", DIAGNOSTICS);
396 332 : failed += keywords_insert("SIZE", sqlSIZE);
397 332 : failed += keywords_insert("STORAGE", STORAGE);
398 :
399 332 : failed += keywords_insert("TYPE", TYPE);
400 332 : failed += keywords_insert("PROCEDURE", PROCEDURE);
401 332 : failed += keywords_insert("FUNCTION", FUNCTION);
402 332 : failed += keywords_insert("LOADER", sqlLOADER);
403 332 : failed += keywords_insert("REPLACE", REPLACE);
404 :
405 332 : failed += keywords_insert("FIELD", FIELD);
406 332 : failed += keywords_insert("FILTER", FILTER);
407 332 : failed += keywords_insert("AGGREGATE", AGGREGATE);
408 332 : failed += keywords_insert("RETURNS", RETURNS);
409 332 : failed += keywords_insert("EXTERNAL", EXTERNAL);
410 332 : failed += keywords_insert("NAME", sqlNAME);
411 332 : failed += keywords_insert("RETURN", RETURN);
412 332 : failed += keywords_insert("CALL", CALL);
413 332 : failed += keywords_insert("LANGUAGE", LANGUAGE);
414 :
415 332 : failed += keywords_insert("ANALYZE", ANALYZE);
416 332 : failed += keywords_insert("EXPLAIN", SQL_EXPLAIN);
417 332 : failed += keywords_insert("PLAN", SQL_PLAN);
418 332 : failed += keywords_insert("TRACE", SQL_TRACE);
419 332 : failed += keywords_insert("PREPARE", PREPARE);
420 332 : failed += keywords_insert("PREP", PREP);
421 332 : failed += keywords_insert("EXECUTE", EXECUTE);
422 332 : failed += keywords_insert("EXEC", EXEC);
423 332 : failed += keywords_insert("DEALLOCATE", DEALLOCATE);
424 :
425 332 : failed += keywords_insert("INDEX", INDEX);
426 :
427 332 : failed += keywords_insert("SEQUENCE", SEQUENCE);
428 332 : failed += keywords_insert("RESTART", RESTART);
429 332 : failed += keywords_insert("INCREMENT", INCREMENT);
430 332 : failed += keywords_insert("MAXVALUE", MAXVALUE);
431 332 : failed += keywords_insert("MINVALUE", MINVALUE);
432 332 : failed += keywords_insert("CYCLE", CYCLE);
433 332 : failed += keywords_insert("CACHE", CACHE);
434 332 : failed += keywords_insert("NEXT", NEXT);
435 332 : failed += keywords_insert("VALUE", VALUE);
436 332 : failed += keywords_insert("GENERATED", GENERATED);
437 332 : failed += keywords_insert("ALWAYS", ALWAYS);
438 332 : failed += keywords_insert("IDENTITY", IDENTITY);
439 332 : failed += keywords_insert("SERIAL", SERIAL);
440 332 : failed += keywords_insert("BIGSERIAL", BIGSERIAL);
441 332 : failed += keywords_insert("AUTO_INCREMENT", AUTO_INCREMENT);
442 332 : failed += keywords_insert("CONTINUE", CONTINUE);
443 :
444 332 : failed += keywords_insert("TRIGGER", TRIGGER);
445 332 : failed += keywords_insert("ATOMIC", ATOMIC);
446 332 : failed += keywords_insert("BEGIN", BEGIN);
447 332 : failed += keywords_insert("OF", OF);
448 332 : failed += keywords_insert("BEFORE", BEFORE);
449 332 : failed += keywords_insert("AFTER", AFTER);
450 332 : failed += keywords_insert("ROW", ROW);
451 332 : failed += keywords_insert("STATEMENT", STATEMENT);
452 332 : failed += keywords_insert("NEW", sqlNEW);
453 332 : failed += keywords_insert("OLD", OLD);
454 332 : failed += keywords_insert("EACH", EACH);
455 332 : failed += keywords_insert("REFERENCING", REFERENCING);
456 :
457 332 : failed += keywords_insert("RANGE", RANGE);
458 332 : failed += keywords_insert("UNBOUNDED", UNBOUNDED);
459 332 : failed += keywords_insert("PRECEDING", PRECEDING);
460 332 : failed += keywords_insert("FOLLOWING", FOLLOWING);
461 332 : failed += keywords_insert("CURRENT", CURRENT);
462 332 : failed += keywords_insert("EXCLUDE", EXCLUDE);
463 332 : failed += keywords_insert("OTHERS", OTHERS);
464 332 : failed += keywords_insert("TIES", TIES);
465 332 : failed += keywords_insert("GROUPS", GROUPS);
466 332 : failed += keywords_insert("WINDOW", WINDOW);
467 :
468 : /* special SQL/XML keywords */
469 332 : failed += keywords_insert("XMLCOMMENT", XMLCOMMENT);
470 332 : failed += keywords_insert("XMLCONCAT", XMLCONCAT);
471 332 : failed += keywords_insert("XMLDOCUMENT", XMLDOCUMENT);
472 332 : failed += keywords_insert("XMLELEMENT", XMLELEMENT);
473 332 : failed += keywords_insert("XMLATTRIBUTES", XMLATTRIBUTES);
474 332 : failed += keywords_insert("XMLFOREST", XMLFOREST);
475 332 : failed += keywords_insert("XMLPARSE", XMLPARSE);
476 332 : failed += keywords_insert("STRIP", STRIP);
477 332 : failed += keywords_insert("WHITESPACE", WHITESPACE);
478 332 : failed += keywords_insert("XMLPI", XMLPI);
479 332 : failed += keywords_insert("XMLQUERY", XMLQUERY);
480 332 : failed += keywords_insert("PASSING", PASSING);
481 332 : failed += keywords_insert("XMLTEXT", XMLTEXT);
482 332 : failed += keywords_insert("NIL", NIL);
483 332 : failed += keywords_insert("REF", REF);
484 332 : failed += keywords_insert("ABSENT", ABSENT);
485 332 : failed += keywords_insert("DOCUMENT", DOCUMENT);
486 332 : failed += keywords_insert("ELEMENT", ELEMENT);
487 332 : failed += keywords_insert("CONTENT", CONTENT);
488 332 : failed += keywords_insert("XMLNAMESPACES", XMLNAMESPACES);
489 332 : failed += keywords_insert("NAMESPACE", NAMESPACE);
490 332 : failed += keywords_insert("XMLVALIDATE", XMLVALIDATE);
491 332 : failed += keywords_insert("RETURNING", RETURNING);
492 332 : failed += keywords_insert("LOCATION", LOCATION);
493 332 : failed += keywords_insert("ID", ID);
494 332 : failed += keywords_insert("ACCORDING", ACCORDING);
495 332 : failed += keywords_insert("XMLSCHEMA", XMLSCHEMA);
496 332 : failed += keywords_insert("URI", URI);
497 332 : failed += keywords_insert("XMLAGG", XMLAGG);
498 :
499 : /* keywords for opengis */
500 332 : failed += keywords_insert("GEOMETRY", GEOMETRY);
501 :
502 332 : failed += keywords_insert("POINT", GEOMETRYSUBTYPE);
503 332 : failed += keywords_insert("LINESTRING", GEOMETRYSUBTYPE);
504 332 : failed += keywords_insert("POLYGON", GEOMETRYSUBTYPE);
505 332 : failed += keywords_insert("MULTIPOINT", GEOMETRYSUBTYPE);
506 332 : failed += keywords_insert("MULTILINESTRING", GEOMETRYSUBTYPE);
507 332 : failed += keywords_insert("MULTIPOLYGON", GEOMETRYSUBTYPE);
508 332 : failed += keywords_insert("GEOMETRYCOLLECTION", GEOMETRYSUBTYPE);
509 :
510 332 : failed += keywords_insert("POINTZ", GEOMETRYSUBTYPE);
511 332 : failed += keywords_insert("LINESTRINGZ", GEOMETRYSUBTYPE);
512 332 : failed += keywords_insert("POLYGONZ", GEOMETRYSUBTYPE);
513 332 : failed += keywords_insert("MULTIPOINTZ", GEOMETRYSUBTYPE);
514 332 : failed += keywords_insert("MULTILINESTRINGZ", GEOMETRYSUBTYPE);
515 332 : failed += keywords_insert("MULTIPOLYGONZ", GEOMETRYSUBTYPE);
516 332 : failed += keywords_insert("GEOMETRYCOLLECTIONZ", GEOMETRYSUBTYPE);
517 :
518 332 : failed += keywords_insert("POINTM", GEOMETRYSUBTYPE);
519 332 : failed += keywords_insert("LINESTRINGM", GEOMETRYSUBTYPE);
520 332 : failed += keywords_insert("POLYGONM", GEOMETRYSUBTYPE);
521 332 : failed += keywords_insert("MULTIPOINTM", GEOMETRYSUBTYPE);
522 332 : failed += keywords_insert("MULTILINESTRINGM", GEOMETRYSUBTYPE);
523 332 : failed += keywords_insert("MULTIPOLYGONM", GEOMETRYSUBTYPE);
524 332 : failed += keywords_insert("GEOMETRYCOLLECTIONM", GEOMETRYSUBTYPE);
525 :
526 332 : failed += keywords_insert("POINTZM", GEOMETRYSUBTYPE);
527 332 : failed += keywords_insert("LINESTRINGZM", GEOMETRYSUBTYPE);
528 332 : failed += keywords_insert("POLYGONZM", GEOMETRYSUBTYPE);
529 332 : failed += keywords_insert("MULTIPOINTZM", GEOMETRYSUBTYPE);
530 332 : failed += keywords_insert("MULTILINESTRINGZM", GEOMETRYSUBTYPE);
531 332 : failed += keywords_insert("MULTIPOLYGONZM", GEOMETRYSUBTYPE);
532 332 : failed += keywords_insert("GEOMETRYCOLLECTIONZM", GEOMETRYSUBTYPE);
533 332 : failed += keywords_insert("LOGIN", LOGIN);
534 : // odbc keywords
535 332 : failed += keywords_insert("d", ODBC_DATE_ESCAPE_PREFIX);
536 332 : failed += keywords_insert("t", ODBC_TIME_ESCAPE_PREFIX);
537 332 : failed += keywords_insert("ts", ODBC_TIMESTAMP_ESCAPE_PREFIX);
538 332 : failed += keywords_insert("guid", ODBC_GUID_ESCAPE_PREFIX);
539 332 : failed += keywords_insert("fn", ODBC_FUNC_ESCAPE_PREFIX);
540 332 : failed += keywords_insert("oj", ODBC_OJ_ESCAPE_PREFIX);
541 332 : failed += keywords_insert("DAYNAME", DAYNAME);
542 332 : failed += keywords_insert("IFNULL", IFNULL);
543 332 : failed += keywords_insert("MONTHNAME", MONTHNAME);
544 332 : failed += keywords_insert("TIMESTAMPADD", TIMESTAMPADD);
545 332 : failed += keywords_insert("TIMESTAMPDIFF", TIMESTAMPDIFF);
546 332 : failed += keywords_insert("SQL_BIGINT", SQL_BIGINT);
547 332 : failed += keywords_insert("SQL_BINARY", SQL_BINARY);
548 332 : failed += keywords_insert("SQL_BIT", SQL_BIT);
549 332 : failed += keywords_insert("SQL_CHAR", SQL_CHAR);
550 332 : failed += keywords_insert("SQL_DATE", SQL_DATE);
551 332 : failed += keywords_insert("SQL_DECIMAL", SQL_DECIMAL);
552 332 : failed += keywords_insert("SQL_DOUBLE", SQL_DOUBLE);
553 332 : failed += keywords_insert("SQL_FLOAT", SQL_FLOAT);
554 332 : failed += keywords_insert("SQL_GUID", SQL_GUID);
555 332 : failed += keywords_insert("SQL_HUGEINT", SQL_HUGEINT);
556 332 : failed += keywords_insert("SQL_INTEGER", SQL_INTEGER);
557 332 : failed += keywords_insert("SQL_INTERVAL_DAY", SQL_INTERVAL_DAY);
558 332 : failed += keywords_insert("SQL_INTERVAL_DAY_TO_HOUR", SQL_INTERVAL_DAY_TO_HOUR);
559 332 : failed += keywords_insert("SQL_INTERVAL_DAY_TO_MINUTE", SQL_INTERVAL_DAY_TO_MINUTE);
560 332 : failed += keywords_insert("SQL_INTERVAL_DAY_TO_SECOND", SQL_INTERVAL_DAY_TO_SECOND);
561 332 : failed += keywords_insert("SQL_INTERVAL_HOUR", SQL_INTERVAL_HOUR);
562 332 : failed += keywords_insert("SQL_INTERVAL_HOUR_TO_MINUTE", SQL_INTERVAL_HOUR_TO_MINUTE);
563 332 : failed += keywords_insert("SQL_INTERVAL_HOUR_TO_SECOND", SQL_INTERVAL_HOUR_TO_SECOND);
564 332 : failed += keywords_insert("SQL_INTERVAL_MINUTE", SQL_INTERVAL_MINUTE);
565 332 : failed += keywords_insert("SQL_INTERVAL_MINUTE_TO_SECOND", SQL_INTERVAL_MINUTE_TO_SECOND);
566 332 : failed += keywords_insert("SQL_INTERVAL_MONTH", SQL_INTERVAL_MONTH);
567 332 : failed += keywords_insert("SQL_INTERVAL_SECOND", SQL_INTERVAL_SECOND);
568 332 : failed += keywords_insert("SQL_INTERVAL_YEAR", SQL_INTERVAL_YEAR);
569 332 : failed += keywords_insert("SQL_INTERVAL_YEAR_TO_MONTH", SQL_INTERVAL_YEAR_TO_MONTH);
570 332 : failed += keywords_insert("SQL_LONGVARBINARY", SQL_LONGVARBINARY);
571 332 : failed += keywords_insert("SQL_LONGVARCHAR", SQL_LONGVARCHAR);
572 332 : failed += keywords_insert("SQL_NUMERIC", SQL_NUMERIC);
573 332 : failed += keywords_insert("SQL_REAL", SQL_REAL);
574 332 : failed += keywords_insert("SQL_SMALLINT", SQL_SMALLINT);
575 332 : failed += keywords_insert("SQL_TIME", SQL_TIME);
576 332 : failed += keywords_insert("SQL_TIMESTAMP", SQL_TIMESTAMP);
577 332 : failed += keywords_insert("SQL_TINYINT", SQL_TINYINT);
578 332 : failed += keywords_insert("SQL_VARBINARY", SQL_VARBINARY);
579 332 : failed += keywords_insert("SQL_VARCHAR", SQL_VARCHAR);
580 332 : failed += keywords_insert("SQL_WCHAR", SQL_WCHAR);
581 332 : failed += keywords_insert("SQL_WLONGVARCHAR", SQL_WLONGVARCHAR);
582 332 : failed += keywords_insert("SQL_WVARCHAR", SQL_WVARCHAR);
583 332 : failed += keywords_insert("SQL_TSI_FRAC_SECOND", SQL_TSI_FRAC_SECOND);
584 332 : failed += keywords_insert("SQL_TSI_SECOND", SQL_TSI_SECOND);
585 332 : failed += keywords_insert("SQL_TSI_MINUTE", SQL_TSI_MINUTE);
586 332 : failed += keywords_insert("SQL_TSI_HOUR", SQL_TSI_HOUR);
587 332 : failed += keywords_insert("SQL_TSI_DAY", SQL_TSI_DAY);
588 332 : failed += keywords_insert("SQL_TSI_WEEK", SQL_TSI_WEEK);
589 332 : failed += keywords_insert("SQL_TSI_MONTH", SQL_TSI_MONTH);
590 332 : failed += keywords_insert("SQL_TSI_QUARTER", SQL_TSI_QUARTER);
591 332 : failed += keywords_insert("SQL_TSI_YEAR", SQL_TSI_YEAR);
592 :
593 332 : failed += keywords_insert("LEAST", MARGFUNC);
594 332 : failed += keywords_insert("GREATEST", MARGFUNC);
595 332 : return failed;
596 : }
597 :
598 : #define find_keyword_bs(lc, s) find_keyword(lc->rs->buf+lc->rs->pos+s)
599 :
600 : void
601 245260 : scanner_init(struct scanner *s, bstream *rs, stream *ws)
602 : {
603 490520 : *s = (struct scanner) {
604 : .rs = rs,
605 : .ws = ws,
606 : .mode = LINE_N,
607 245260 : .raw_string_mode = GDKgetenv_istrue("raw_strings"),
608 : .aborted = false,
609 : };
610 245260 : }
611 :
612 : void
613 1293149 : scanner_query_processed(struct scanner *s)
614 : {
615 1293149 : int cur;
616 :
617 1293149 : if (s->yybak) {
618 501935 : s->rs->buf[s->rs->pos + s->yycur] = s->yybak;
619 501935 : s->yybak = 0;
620 : }
621 1293149 : if (s->rs) {
622 1293149 : s->rs->pos += s->yycur;
623 : /* completely eat the query including white space after the ; */
624 2440185 : while (s->rs->pos < s->rs->len &&
625 2105242 : (cur = s->rs->buf[s->rs->pos], iswspace(cur))) {
626 1147036 : s->rs->pos++;
627 : }
628 : }
629 : /*assert(s->rs->pos <= s->rs->len);*/
630 1293149 : s->yycur = 0;
631 1293149 : s->started = 0;
632 1293149 : s->as = 0;
633 1293149 : s->schema = NULL;
634 1293149 : }
635 :
636 : static int
637 33 : scanner_error(mvc *lc, int cur)
638 : {
639 33 : switch (cur) {
640 0 : case EOF:
641 0 : (void) sql_error(lc, 1, SQLSTATE(42000) "Unexpected end of input");
642 0 : return EOF;
643 33 : default:
644 : /* on Windows at least, iswcntrl returns TRUE for
645 : * U+FEFF, but we just want consistent error
646 : * messages */
647 33 : (void) sql_error(lc, 1, SQLSTATE(42000) "Unexpected%s character (U+%04X)", iswcntrl(cur) && cur != 0xFEFF ? " control" : "", (unsigned) cur);
648 : }
649 33 : return LEX_ERROR;
650 : }
651 :
652 :
653 : /*
654 : UTF-8 encoding is as follows:
655 : U-00000000 - U-0000007F: 0xxxxxxx
656 : U-00000080 - U-000007FF: 110xxxxx 10xxxxxx
657 : U-00000800 - U-0000FFFF: 1110xxxx 10xxxxxx 10xxxxxx
658 : U-00010000 - U-001FFFFF: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
659 : U-00200000 - U-03FFFFFF: 111110xx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
660 : U-04000000 - U-7FFFFFFF: 1111110x 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx 10xxxxxx
661 : */
662 : /* To be correctly coded UTF-8, the sequence should be the shortest
663 : possible encoding of the value being encoded. This means that for
664 : an encoding of length n+1 (1 <= n <= 5), at least one of the bits in
665 : utf8chkmsk[n] should be non-zero (else the encoding could be
666 : shorter).
667 : */
668 : static const int utf8chkmsk[] = {
669 : 0x0000007f,
670 : 0x00000780,
671 : 0x0000f800,
672 : 0x001f0000,
673 : 0x03e00000,
674 : 0x7c000000
675 : };
676 :
677 : static void
678 31304716 : utf8_putchar(struct scanner *lc, int ch)
679 : {
680 31304716 : if ((ch) < 0x80) {
681 31304711 : lc->yycur--;
682 5 : } else if ((ch) < 0x800) {
683 0 : lc->yycur -= 2;
684 5 : } else if ((ch) < 0x10000) {
685 5 : lc->yycur -= 3;
686 : } else {
687 0 : lc->yycur -= 4;
688 : }
689 31304716 : }
690 :
691 : static inline int
692 136285348 : scanner_read_more(struct scanner *lc, size_t n)
693 : {
694 136285348 : bstream *b = lc->rs;
695 136285348 : bool more = false;
696 :
697 :
698 136285348 : if (lc->aborted)
699 : return EOF;
700 136289653 : while (b->len < b->pos + lc->yycur + n) {
701 :
702 136368 : if (lc->mode == LINE_1 || !lc->started)
703 : return EOF;
704 :
705 : /* query is not finished ask for more */
706 3669 : if (b->eof || !isa_block_stream(b->s)) {
707 1513 : if (bstream_getoob(b)) {
708 0 : lc->aborted = true;
709 0 : return EOF;
710 : }
711 2156 : if (mnstr_write(lc->ws, PROMPT2, sizeof(PROMPT2) - 1, 1) == 1)
712 2156 : mnstr_flush(lc->ws, MNSTR_FLUSH_DATA);
713 2156 : b->eof = false;
714 2156 : more = true;
715 : }
716 : /* we need more query text */
717 4312 : if (bstream_next(b) < 0) {
718 0 : if (mnstr_errnr(b->s) == MNSTR_INTERRUPT) {
719 : // now what?
720 0 : lc->errstr = "Query aborted";
721 0 : lc->aborted = true;
722 0 : mnstr_clearerr(b->s);
723 : }
724 0 : return EOF;
725 4312 : } else if (/* we asked for more data but didn't get any */
726 2156 : (more && b->eof && b->len < b->pos + lc->yycur + n))
727 : return EOF;
728 4305 : if (more && b->pos + lc->yycur + 2 == b->len && b->buf[b->pos + lc->yycur] == '\200' && b->buf[b->pos + lc->yycur + 1] == '\n') {
729 0 : lc->errstr = "Query aborted";
730 0 : b->len -= 2;
731 0 : b->buf[b->len] = 0;
732 0 : return EOF;
733 : }
734 : }
735 : return 1;
736 : }
737 :
738 : static inline int
739 135034472 : scanner_getc(struct scanner *lc)
740 : {
741 135034472 : bstream *b = lc->rs;
742 135034472 : unsigned char *s = NULL;
743 135034472 : int c, m, n, mask;
744 :
745 135034472 : if (scanner_read_more(lc, 1) == EOF) {
746 : //lc->errstr = SQLSTATE(42000) "end of input stream";
747 : return EOF;
748 : }
749 134895966 : lc->errstr = NULL;
750 :
751 134895966 : s = (unsigned char *) b->buf + b->pos + lc->yycur++;
752 134895966 : if (((c = *s) & 0x80) == 0) {
753 : /* 7-bit char */
754 : return c;
755 : }
756 88250 : for (n = 0, m = 0x40; c & m; n++, m >>= 1)
757 : ;
758 : /* n now is number of 10xxxxxx bytes that should follow */
759 29443 : if (n == 0 || n >= 6 || (b->pos + n) > b->len) {
760 : /* incorrect UTF-8 sequence */
761 : /* n==0: c == 10xxxxxx */
762 : /* n>=6: c == 1111111x */
763 0 : lc->errstr = SQLSTATE(42000) "invalid start of UTF-8 sequence";
764 0 : goto error;
765 : }
766 :
767 29443 : if (scanner_read_more(lc, (size_t) n) == EOF)
768 : return EOF;
769 29443 : s = (unsigned char *) b->buf + b->pos + lc->yycur;
770 :
771 29443 : mask = utf8chkmsk[n];
772 29443 : c &= ~(0xFFC0 >> n); /* remove non-x bits */
773 88249 : while (--n >= 0) {
774 58807 : c <<= 6;
775 58807 : lc->yycur++;
776 58807 : if (((m = *s++) & 0xC0) != 0x80) {
777 : /* incorrect UTF-8 sequence: byte is not 10xxxxxx */
778 : /* this includes end-of-string (m == 0) */
779 1 : lc->errstr = SQLSTATE(42000) "invalid continuation in UTF-8 sequence";
780 1 : goto error;
781 : }
782 58806 : c |= m & 0x3F;
783 : }
784 29442 : if ((c & mask) == 0) {
785 : /* incorrect UTF-8 sequence: not shortest possible */
786 0 : lc->errstr = SQLSTATE(42000) "not shortest possible UTF-8 sequence";
787 0 : goto error;
788 : }
789 :
790 : return c;
791 :
792 1 : error:
793 1 : if (b->pos + lc->yycur < b->len) /* skip bogus char */
794 0 : lc->yycur++;
795 : return EOF;
796 : }
797 :
798 : static int
799 27939556 : scanner_token(struct scanner *lc, int token)
800 : {
801 27939556 : lc->yybak = lc->rs->buf[lc->rs->pos + lc->yycur];
802 27939556 : lc->rs->buf[lc->rs->pos + lc->yycur] = 0;
803 27939556 : lc->yyval = token;
804 27939556 : return lc->yyval;
805 : }
806 :
807 : static int
808 2078968 : scanner_string(mvc *c, int quote, bool escapes)
809 : {
810 2078968 : struct scanner *lc = &c->scanner;
811 2078968 : bstream *rs = lc->rs;
812 2078968 : int cur = quote;
813 2078968 : bool escape = false;
814 2078968 : const size_t limit = quote == '"' ? 1 << 11 : 1 << 30;
815 :
816 2078968 : lc->started = 1;
817 2116613 : while (cur != EOF) {
818 2116598 : size_t pos = 0;
819 2116598 : const size_t yycur = rs->pos + lc->yycur;
820 :
821 35055821 : while (cur != EOF && (quote != '"' || cur != 0xFEFF) && pos < limit &&
822 32939223 : (((cur = rs->buf[yycur + pos++]) & 0x80) == 0) &&
823 65848992 : cur && (cur != quote || escape)) {
824 30822626 : if (escapes && cur == '\\')
825 6612 : escape = !escape;
826 : else
827 : escape = false;
828 : }
829 2116598 : if (pos == limit) {
830 0 : (void) sql_error(c, 2, SQLSTATE(42000) "string too long");
831 0 : return LEX_ERROR;
832 : }
833 : /* BOM character not allowed as an identifier */
834 2116598 : if (cur == EOF || (quote == '"' && cur == 0xFEFF))
835 1 : return scanner_error(c, cur);
836 2116597 : lc->yycur += pos;
837 : /* check for quote escaped quote: Obscure SQL Rule */
838 2116597 : if (cur == quote && rs->buf[yycur + pos] == quote) {
839 8204 : lc->yycur++;
840 8204 : continue;
841 : }
842 2108393 : assert(yycur + pos <= rs->len + 1);
843 2108393 : if (cur == quote && !escape) {
844 2078938 : return scanner_token(lc, STRING);
845 : }
846 29455 : lc->yycur--; /* go back to current (possibly invalid) char */
847 : /* long utf8, if correct isn't the quote */
848 29455 : if (!cur) {
849 30 : if (lc->rs->len >= lc->rs->pos + lc->yycur + 1) {
850 14 : (void) sql_error(c, 2, SQLSTATE(42000) "NULL byte in string");
851 14 : return LEX_ERROR;
852 : }
853 16 : cur = scanner_read_more(lc, 1);
854 : } else {
855 29425 : cur = scanner_getc(lc);
856 : }
857 : }
858 15 : (void) sql_error(c, 2, "%s", lc->errstr ? lc->errstr : SQLSTATE(42000) "Unexpected end of input");
859 15 : return EOF;
860 : }
861 :
862 : /* scan a structure {blah} into a string. We only count the matching {}
863 : * unless escaped. We do not consider embeddings in string literals yet
864 : */
865 :
866 : static int
867 230 : scanner_body(mvc *c)
868 : {
869 230 : struct scanner *lc = &c->scanner;
870 230 : bstream *rs = lc->rs;
871 230 : int cur = (int) 'x';
872 230 : int blk = 1;
873 230 : bool escape = false;
874 :
875 230 : lc->started = 1;
876 230 : assert(rs->buf[rs->pos + lc->yycur-1] == '{');
877 286 : while (cur != EOF) {
878 286 : size_t pos = rs->pos + lc->yycur;
879 :
880 31815 : while ((((cur = rs->buf[pos++]) & 0x80) == 0) && cur && (blk || escape)) {
881 31529 : if (cur != '\\')
882 : escape = false;
883 : else
884 12 : escape = !escape;
885 31529 : blk += cur =='{';
886 31529 : blk -= cur =='}';
887 : }
888 286 : lc->yycur = pos - rs->pos;
889 286 : assert(pos <= rs->len + 1);
890 286 : if (blk == 0 && !escape){
891 230 : lc->yycur--; /* go back to current (possibly invalid) char */
892 230 : return scanner_token(lc, X_BODY);
893 : }
894 56 : lc->yycur--; /* go back to current (possibly invalid) char */
895 56 : if (!cur) {
896 56 : if (lc->rs->len >= lc->rs->pos + lc->yycur + 1) {
897 0 : (void) sql_error(c, 2, SQLSTATE(42000) "NULL byte in string");
898 0 : return LEX_ERROR;
899 : }
900 56 : cur = scanner_read_more(lc, 1);
901 : } else {
902 0 : cur = scanner_getc(lc);
903 : }
904 : }
905 0 : (void) sql_error(c, 2, SQLSTATE(42000) "Unexpected end of input");
906 0 : return EOF;
907 : }
908 :
909 : static int
910 13473634 : keyword_or_ident(mvc * c, int cur)
911 : {
912 13473634 : struct scanner *lc = &c->scanner;
913 13473634 : keyword *k = NULL;
914 13473634 : size_t s;
915 :
916 13473634 : lc->started = 1;
917 13473634 : utf8_putchar(lc, cur);
918 13473609 : s = lc->yycur;
919 13473609 : lc->yyval = IDENT;
920 80583889 : while ((cur = scanner_getc(lc)) != EOF) {
921 80583779 : if (!iswalnum(cur) && cur != '_') {
922 13473499 : utf8_putchar(lc, cur);
923 13473509 : (void)scanner_token(lc, IDENT);
924 13473509 : if ((k = find_keyword_bs(lc,s)))
925 8266965 : lc->yyval = k->token;
926 13473664 : return lc->yyval;
927 : }
928 : }
929 : if (cur < 0)
930 : return cur;
931 : (void)scanner_token(lc, IDENT);
932 : if ((k = find_keyword_bs(lc,s)))
933 : lc->yyval = k->token;
934 : return lc->yyval;
935 : }
936 :
937 : static int
938 14034121 : skip_white_space(struct scanner * lc)
939 : {
940 17657931 : int cur;
941 :
942 17657931 : do {
943 17657931 : lc->yysval = lc->yycur;
944 17657931 : } while ((cur = scanner_getc(lc)) != EOF && iswspace(cur));
945 14034133 : return cur;
946 : }
947 :
948 : static int
949 69254 : skip_c_comment(struct scanner * lc)
950 : {
951 69254 : int cur;
952 69254 : int prev = 0;
953 69254 : int started = lc->started;
954 69254 : int depth = 1;
955 :
956 69254 : lc->started = 1;
957 1396668 : while (depth > 0 && (cur = scanner_getc(lc)) != EOF) {
958 1327414 : if (prev == '*' && cur == '/')
959 69254 : depth--;
960 1258160 : else if (prev == '/' && cur == '*') {
961 : /* block comments can nest */
962 0 : cur = 0; /* prevent slash-star-slash from matching */
963 0 : depth++;
964 : }
965 : prev = cur;
966 : }
967 69254 : lc->yysval = lc->yycur;
968 69254 : lc->started = started;
969 : /* a comment is equivalent to a newline */
970 69254 : return cur == EOF ? cur : '\n';
971 : }
972 :
973 : static int
974 3176 : skip_sql_comment(struct scanner * lc)
975 : {
976 3176 : int cur;
977 3176 : int started = lc->started;
978 :
979 3176 : lc->started = 1;
980 828366 : while ((cur = scanner_getc(lc)) != EOF && (cur != '\n'))
981 : ;
982 3176 : lc->yysval = lc->yycur;
983 3176 : lc->started = started;
984 : /* a comment is equivalent to a newline */
985 3176 : return cur;
986 : }
987 :
988 : static int tokenize(mvc * lc, int cur);
989 :
990 5571717 : static inline bool is_valid_decimal_digit(int cur) { return (iswdigit(cur)); }
991 13 : static inline bool is_valid_binary_digit(int cur) { return (iswdigit(cur) && cur < '2'); }
992 10 : static inline bool is_valid_octal_digit(int cur) { return (iswdigit(cur) && cur < '8'); }
993 3688 : static inline bool is_valid_hexadecimal_digit(int cur) { return iswxdigit(cur); }
994 :
995 1850367 : static inline int check_validity_number(mvc* c, int pcur, bool initial_underscore_allowed, int *token, int type) {
996 1850367 : struct scanner *lc = &c->scanner;
997 1850367 : bool (*is_valid_n_ary_digit)(int);
998 :
999 1850367 : if (pcur == '_' && !initial_underscore_allowed) /* ERROR: initial underscore not allowed */ {
1000 0 : *token = 0;
1001 0 : return '_';
1002 : }
1003 :
1004 1850367 : switch (type) {
1005 : case BINARYNUM:
1006 : is_valid_n_ary_digit = &is_valid_binary_digit;
1007 : break;
1008 3 : case OCTALNUM:
1009 3 : is_valid_n_ary_digit = &is_valid_octal_digit;
1010 3 : break;
1011 280 : case HEXADECIMALNUM:
1012 280 : is_valid_n_ary_digit = &is_valid_hexadecimal_digit;
1013 280 : break;
1014 1850082 : default:
1015 1850082 : is_valid_n_ary_digit = &is_valid_decimal_digit;
1016 1850082 : break;
1017 : }
1018 :
1019 1850367 : if ( !(pcur == '_' || is_valid_n_ary_digit(pcur)) ) /* ERROR: first digit is not valid */ {
1020 18 : *token = 0;
1021 18 : return pcur;
1022 : }
1023 :
1024 1850216 : int cur = scanner_getc(lc);
1025 1850131 : *token = type;
1026 3727116 : while (cur != EOF) {
1027 3727108 : if (cur == '_') {
1028 25 : if (pcur == '_') /* ERROR: multiple consecutive underscores */ {
1029 2 : *token = 0;
1030 2 : return '_';
1031 : }
1032 : }
1033 3727083 : else if (!is_valid_n_ary_digit(cur))
1034 : break;
1035 1877077 : pcur = cur;
1036 1877077 : cur = scanner_getc(lc);
1037 : }
1038 :
1039 1849923 : if (pcur == '_') {
1040 3 : *token = 0;
1041 3 : if (iswalnum(cur)) /* ERROR: not a valid digit */
1042 : return cur;
1043 : else /* ERROR: number ends with underscore */
1044 : return '_';
1045 : }
1046 :
1047 : return cur;
1048 : }
1049 :
1050 : static int
1051 1837071 : number(mvc * c, int cur)
1052 : {
1053 1837071 : struct scanner *lc = &c->scanner;
1054 1837071 : int token = sqlINT;
1055 :
1056 : /* a number has one of these forms (expressed in regular expressions):
1057 : * 0x[0-9A-Fa-f]+ -- (hexadecimal) INTEGER
1058 : * \.[0-9]+ -- DECIMAL
1059 : * [0-9]+\.[0-9]* -- DECIMAL
1060 : * [0-9]+@0 -- OID
1061 : * [0-9]*\.[0-9]+[eE][-+]?[0-9]+ -- REAL
1062 : * [0-9]+(\.[0-9]*)?[eE][-+]?[0-9]+ -- REAL
1063 : * [0-9]+ -- (decimal) INTEGER
1064 : */
1065 1837071 : lc->started = 1;
1066 1837071 : if (cur == '0') {
1067 286071 : switch ((cur = scanner_getc(lc))) {
1068 2 : case 'b':
1069 2 : cur = scanner_getc(lc);
1070 2 : if ((cur = check_validity_number(c, cur, true, &token, BINARYNUM)) == EOF) return cur;
1071 : break;
1072 3 : case 'o':
1073 3 : cur = scanner_getc(lc);
1074 3 : if ((cur = check_validity_number(c, cur, true, &token, OCTALNUM)) == EOF) return cur;
1075 : break;
1076 280 : case 'x':
1077 280 : cur = scanner_getc(lc);
1078 280 : if ((cur = check_validity_number(c, cur, true, &token, HEXADECIMALNUM)) == EOF) return cur;
1079 : break;
1080 285787 : default:
1081 285787 : utf8_putchar(lc, cur);
1082 285787 : cur = '0';
1083 : }
1084 : }
1085 1837071 : if (token == sqlINT) {
1086 1836775 : if ((cur = check_validity_number(c, cur, false, &token, sqlINT)) == EOF) return cur;
1087 1836372 : if (cur == '@') {
1088 0 : if (token == sqlINT) {
1089 0 : cur = scanner_getc(lc);
1090 0 : if (cur == EOF)
1091 : return cur;
1092 0 : if (cur == '0') {
1093 0 : cur = scanner_getc(lc);
1094 0 : if (cur == EOF)
1095 : return cur;
1096 0 : token = OIDNUM;
1097 : } else {
1098 : /* number + '@' not followed by 0: show '@' as erroneous */
1099 0 : utf8_putchar(lc, cur);
1100 0 : cur = '@';
1101 0 : token = 0;
1102 : }
1103 : }
1104 : } else {
1105 1836372 : if (cur == '.') {
1106 11080 : cur = scanner_getc(lc);
1107 11080 : if (iswalnum(cur)) /* early exit for numerical forms with final . e.g. 10. */
1108 11073 : if ((cur = check_validity_number(c, cur, false, &token, INTNUM)) == EOF) return cur;
1109 : }
1110 1836372 : if (token != 0)
1111 1836373 : if (cur == 'e' || cur == 'E') {
1112 2225 : cur = scanner_getc(lc);
1113 2225 : if (cur == '+' || cur == '-')
1114 2111 : cur = scanner_getc(lc);
1115 2225 : if ((cur = check_validity_number(c, cur, false, &token, APPROXNUM)) == EOF) return cur;
1116 : }
1117 : }
1118 : }
1119 :
1120 1834443 : assert(cur != EOF);
1121 :
1122 1836668 : if (iswalnum(cur)) /* ERROR: not a valid digit */
1123 6 : token = 0;
1124 :
1125 1836668 : utf8_putchar(lc, cur);
1126 :
1127 1836628 : if (token) {
1128 1836618 : return scanner_token(lc, token);
1129 : } else {
1130 10 : (void)sql_error( c, 2, SQLSTATE(42000) "Unexpected symbol %lc", (wint_t) cur);
1131 10 : return LEX_ERROR;
1132 : }
1133 : }
1134 :
1135 : static
1136 12694873 : int scanner_symbol(mvc * c, int cur)
1137 : {
1138 12694873 : struct scanner *lc = &c->scanner;
1139 12694873 : int next = 0;
1140 12694873 : int started = lc->started;
1141 :
1142 12694873 : switch (cur) {
1143 71895 : case '/':
1144 71895 : lc->started = 1;
1145 71895 : next = scanner_getc(lc);
1146 71895 : if (next < 0)
1147 : return EOF;
1148 71895 : if (next == '*') {
1149 69254 : lc->started = started;
1150 69254 : cur = skip_c_comment(lc);
1151 69254 : if (cur < 0)
1152 : return EOF;
1153 69254 : return tokenize(c, cur);
1154 : } else {
1155 2641 : utf8_putchar(lc, next);
1156 2641 : return scanner_token(lc, cur);
1157 : }
1158 0 : case '0':
1159 : case '1':
1160 : case '2':
1161 : case '3':
1162 : case '4':
1163 : case '5':
1164 : case '6':
1165 : case '7':
1166 : case '8':
1167 : case '9':
1168 0 : return number(c, cur);
1169 5 : case '#':
1170 5 : if ((cur = skip_sql_comment(lc)) == EOF)
1171 : return cur;
1172 5 : return tokenize(c, cur);
1173 775637 : case '\'':
1174 775637 : if (lc->raw_string_mode || lc->next_string_is_raw)
1175 46 : return scanner_string(c, cur, false);
1176 775591 : return scanner_string(c, cur, true);
1177 1296289 : case '"':
1178 1296289 : return scanner_string(c, cur, false);
1179 496 : case '{':
1180 : // if previous tokens like LANGUAGE IDENT
1181 : // TODO checking on IDENT only may not be enough
1182 496 : if (lc->yylast == IDENT)
1183 230 : return scanner_body(c);
1184 266 : lc->started = 1;
1185 266 : return scanner_token(lc, cur);
1186 266 : case '}':
1187 266 : lc->started = 1;
1188 266 : return scanner_token(lc, cur);
1189 29889 : case '-':
1190 29889 : lc->started = 1;
1191 29889 : next = scanner_getc(lc);
1192 29889 : if (next < 0)
1193 : return EOF;
1194 29888 : if (next == '-') {
1195 3171 : lc->started = started;
1196 3171 : if ((cur = skip_sql_comment(lc)) == EOF)
1197 : return cur;
1198 3171 : return tokenize(c, cur);
1199 : }
1200 26717 : lc->started = 1;
1201 26717 : utf8_putchar(lc, next);
1202 26717 : return scanner_token(lc, cur);
1203 12 : case '~': /* binary not */
1204 12 : lc->started = 1;
1205 12 : next = scanner_getc(lc);
1206 12 : if (next < 0)
1207 : return EOF;
1208 12 : if (next == '=')
1209 5 : return scanner_token(lc, GEOM_MBR_EQUAL);
1210 7 : utf8_putchar(lc, next);
1211 7 : return scanner_token(lc, cur);
1212 7108694 : case '^': /* binary xor */
1213 : case '*':
1214 : case '?':
1215 : case ':':
1216 : case '%':
1217 : case '+':
1218 : case '(':
1219 : case ')':
1220 : case ',':
1221 : case '=':
1222 : case '[':
1223 : case ']':
1224 7108694 : lc->started = 1;
1225 7108694 : return scanner_token(lc, cur);
1226 6251 : case '&':
1227 6251 : lc->started = 1;
1228 6251 : cur = scanner_getc(lc);
1229 6251 : if (cur < 0)
1230 : return EOF;
1231 6251 : if (cur < 0)
1232 : return EOF;
1233 6251 : if(cur == '<') {
1234 3 : next = scanner_getc(lc);
1235 3 : if (next < 0)
1236 : return EOF;
1237 3 : if(next == '|') {
1238 0 : return scanner_token(lc, GEOM_OVERLAP_OR_BELOW);
1239 : } else {
1240 3 : utf8_putchar(lc, next); //put the char back
1241 3 : return scanner_token(lc, GEOM_OVERLAP_OR_LEFT);
1242 : }
1243 6248 : } else if(cur == '>')
1244 3 : return scanner_token(lc, GEOM_OVERLAP_OR_RIGHT);
1245 6245 : else if(cur == '&')
1246 3 : return scanner_token(lc, GEOM_OVERLAP);
1247 : else {/* binary and */
1248 6242 : utf8_putchar(lc, cur); //put the char back
1249 6242 : return scanner_token(lc, '&');
1250 : }
1251 19 : case '@':
1252 19 : lc->started = 1;
1253 19 : return scanner_token(lc, AT);
1254 983126 : case ';':
1255 983126 : lc->started = 0;
1256 983126 : return scanner_token(lc, SCOLON);
1257 27 : case '!':
1258 27 : lc->started = 1;
1259 27 : cur = scanner_getc(lc);
1260 27 : if (cur < 0)
1261 : return EOF;
1262 27 : else if (cur == '=') {
1263 21 : lc->rs->buf[lc->rs->pos + lc->yycur - 2] = '<';
1264 21 : lc->rs->buf[lc->rs->pos + lc->yycur - 1] = '>';
1265 21 : return scanner_token( lc, COMPARISON);
1266 : } else {
1267 6 : utf8_putchar(lc, cur); //put the char back
1268 : }
1269 6 : return scanner_token(lc, '!');
1270 51307 : case '<':
1271 51307 : lc->started = 1;
1272 51307 : cur = scanner_getc(lc);
1273 51307 : if (cur < 0)
1274 : return EOF;
1275 51307 : if (cur == '=') {
1276 3123 : return scanner_token( lc, COMPARISON);
1277 48184 : } else if (cur == '>') {
1278 34735 : return scanner_token( lc, COMPARISON);
1279 13449 : } else if (cur == '<') {
1280 44 : next = scanner_getc(lc);
1281 44 : if (next < 0)
1282 : return EOF;
1283 44 : if (next == '=') {
1284 4 : return scanner_token( lc, LEFT_SHIFT_ASSIGN);
1285 40 : } else if (next == '|') {
1286 1 : return scanner_token(lc, GEOM_BELOW);
1287 : } else {
1288 39 : utf8_putchar(lc, next); //put the char back
1289 39 : return scanner_token( lc, LEFT_SHIFT);
1290 : }
1291 13405 : } else if(cur == '-') {
1292 19 : next = scanner_getc(lc);
1293 19 : if (next < 0)
1294 : return EOF;
1295 19 : if(next == '>') {
1296 7 : return scanner_token(lc, GEOM_DIST);
1297 : } else {
1298 : //put the characters back and fall in the next possible case
1299 12 : utf8_putchar(lc, next);
1300 12 : utf8_putchar(lc, cur);
1301 12 : return scanner_token( lc, COMPARISON);
1302 : }
1303 : } else {
1304 13386 : utf8_putchar(lc, cur);
1305 13386 : return scanner_token( lc, COMPARISON);
1306 : }
1307 47906 : case '>':
1308 47906 : lc->started = 1;
1309 47906 : cur = scanner_getc(lc);
1310 47906 : if (cur < 0)
1311 : return EOF;
1312 47906 : if (cur == '>') {
1313 2657 : cur = scanner_getc(lc);
1314 2657 : if (cur < 0)
1315 : return EOF;
1316 2657 : if (cur == '=')
1317 3 : return scanner_token( lc, RIGHT_SHIFT_ASSIGN);
1318 2654 : utf8_putchar(lc, cur);
1319 2654 : return scanner_token( lc, RIGHT_SHIFT);
1320 45249 : } else if (cur != '=') {
1321 42997 : utf8_putchar(lc, cur);
1322 42997 : return scanner_token( lc, COMPARISON);
1323 : } else {
1324 2252 : return scanner_token( lc, COMPARISON);
1325 : }
1326 2141739 : case '.':
1327 2141739 : lc->started = 1;
1328 2141739 : cur = scanner_getc(lc);
1329 2141739 : if (cur < 0)
1330 : return EOF;
1331 2141738 : if (!iswdigit(cur)) {
1332 2141724 : utf8_putchar(lc, cur);
1333 2141724 : return scanner_token( lc, '.');
1334 : } else {
1335 14 : utf8_putchar(lc, cur);
1336 14 : cur = '.';
1337 14 : return number(c, cur);
1338 : }
1339 181305 : case '|': /* binary or or string concat */
1340 181305 : lc->started = 1;
1341 181305 : cur = scanner_getc(lc);
1342 181305 : if (cur < 0)
1343 : return EOF;
1344 181305 : if (cur == '|') {
1345 181280 : return scanner_token(lc, CONCATSTRING);
1346 25 : } else if (cur == '&') {
1347 0 : next = scanner_getc(lc);
1348 0 : if (next < 0)
1349 : return EOF;
1350 0 : if(next == '>') {
1351 0 : return scanner_token(lc, GEOM_OVERLAP_OR_ABOVE);
1352 : } else {
1353 0 : utf8_putchar(lc, next); //put the char back
1354 0 : utf8_putchar(lc, cur); //put the char back
1355 0 : return scanner_token(lc, '|');
1356 : }
1357 25 : } else if (cur == '>') {
1358 1 : next = scanner_getc(lc);
1359 1 : if (next < 0)
1360 : return EOF;
1361 1 : if(next == '>') {
1362 1 : return scanner_token(lc, GEOM_ABOVE);
1363 : } else {
1364 0 : utf8_putchar(lc, next); //put the char back
1365 0 : utf8_putchar(lc, cur); //put the char back
1366 0 : return scanner_token(lc, '|');
1367 : }
1368 : } else {
1369 24 : utf8_putchar(lc, cur);
1370 24 : return scanner_token(lc, '|');
1371 : }
1372 : }
1373 10 : (void)sql_error( c, 3, SQLSTATE(42000) "Unexpected symbol (%lc)", (wint_t) cur);
1374 10 : return LEX_ERROR;
1375 : }
1376 :
1377 : static int
1378 28030950 : tokenize(mvc * c, int cur)
1379 : {
1380 28030950 : struct scanner *lc = &c->scanner;
1381 56056392 : while (1) {
1382 42043671 : if (cur == 0xFEFF) {
1383 : /* on Linux at least, iswpunct returns TRUE
1384 : * for U+FEFF, but we don't want that, we just
1385 : * want to go to the scanner_error case
1386 : * below */
1387 : ;
1388 42043848 : } else if (iswspace(cur)) {
1389 14031235 : if ((cur = skip_white_space(lc)) == EOF)
1390 : return cur;
1391 14012721 : continue; /* try again */
1392 28012613 : } else if (iswdigit(cur)) {
1393 1837055 : return number(c, cur);
1394 26175558 : } else if (iswalpha(cur) || cur == '_') {
1395 13445354 : switch (cur) {
1396 653160 : case 'e': /* string with escapes */
1397 : case 'E':
1398 653160 : if (scanner_read_more(lc, 1) != EOF &&
1399 653160 : lc->rs->buf[lc->rs->pos + lc->yycur] == '\'') {
1400 3747 : return scanner_string(c, scanner_getc(lc), true);
1401 : }
1402 : break;
1403 416323 : case 'x': /* blob */
1404 : case 'X':
1405 : case 'r': /* raw string */
1406 : case 'R':
1407 416323 : if (scanner_read_more(lc, 1) != EOF &&
1408 416323 : lc->rs->buf[lc->rs->pos + lc->yycur] == '\'') {
1409 3278 : return scanner_string(c, scanner_getc(lc), false);
1410 : }
1411 : break;
1412 153907 : case 'u': /* unicode string */
1413 : case 'U':
1414 153907 : if (scanner_read_more(lc, 1) != EOF &&
1415 153924 : lc->rs->buf[lc->rs->pos + lc->yycur] == '&' &&
1416 17 : scanner_read_more(lc, 2) != EOF &&
1417 17 : (lc->rs->buf[lc->rs->pos + lc->yycur + 1] == '\'' ||
1418 : lc->rs->buf[lc->rs->pos + lc->yycur + 1] == '"')) {
1419 17 : cur = scanner_getc(lc); /* '&' */
1420 17 : return scanner_string(c, scanner_getc(lc), false);
1421 : }
1422 : break;
1423 : default:
1424 : break;
1425 : }
1426 13473637 : return keyword_or_ident(c, cur);
1427 12694879 : } else if (iswpunct(cur)) {
1428 12694670 : return scanner_symbol(c, cur);
1429 : }
1430 32 : if (cur == EOF) {
1431 0 : if (lc->mode == LINE_1 || !lc->started )
1432 : return cur;
1433 0 : return scanner_error(c, cur);
1434 : }
1435 : /* none of the above: error */
1436 32 : return scanner_error(c, cur);
1437 : }
1438 : }
1439 :
1440 : /* SQL 'quoted' idents consist of a set of any character of
1441 : * the source language character set other than a 'quote'
1442 : *
1443 : * MonetDB has 3 restrictions:
1444 : * 1 we disallow '%' as the first character.
1445 : * 2 the length is limited to 1024 characters
1446 : * 3 the identifier 'TID%' is not allowed
1447 : */
1448 : static bool
1449 1296278 : valid_ident(const char *restrict s, char *restrict dst)
1450 : {
1451 1296278 : int p = 0;
1452 :
1453 1296278 : if (*s == '%')
1454 : return false;
1455 :
1456 9589640 : while (*s) {
1457 8293362 : if ((dst[p++] = *s++) == '"' && *s == '"')
1458 68 : s++;
1459 8293362 : if (p >= 1024)
1460 : return false;
1461 : }
1462 1296278 : dst[p] = '\0';
1463 1296278 : if (strcmp(dst, TID + 1) == 0) /* an index named 'TID%' could interfere with '%TID%' */
1464 : return false;
1465 : return true;
1466 : }
1467 :
1468 : static inline int
1469 28132318 : sql_get_next_token(YYSTYPE *yylval, void *parm)
1470 : {
1471 28132318 : mvc *c = (mvc*)parm;
1472 28132318 : struct scanner *lc = &c->scanner;
1473 28132318 : int token = 0, cur = 0;
1474 :
1475 28132318 : if (lc->rs->buf == NULL) /* malloc failure */
1476 : return EOF;
1477 :
1478 28132318 : if (lc->yynext) {
1479 61650 : int next = lc->yynext;
1480 :
1481 61650 : lc->yynext = 0;
1482 61650 : return(next);
1483 : }
1484 :
1485 28070668 : if (lc->yybak) {
1486 27050491 : lc->rs->buf[lc->rs->pos + lc->yycur] = lc->yybak;
1487 27050491 : lc->yybak = 0;
1488 : }
1489 :
1490 28070668 : lc->yysval = lc->yycur;
1491 28070668 : lc->yylast = lc->yyval;
1492 28070668 : cur = scanner_getc(lc);
1493 28069928 : if (cur < 0)
1494 : return EOF;
1495 27958636 : token = tokenize(c, cur);
1496 :
1497 27958694 : yylval->sval = (lc->rs->buf + lc->rs->pos + lc->yysval);
1498 :
1499 27958694 : if (token == KW_TYPE)
1500 49020 : token = aTYPE;
1501 :
1502 27958694 : if (token == IDENT || token == COMPARISON ||
1503 22655469 : token == RANK || token == aTYPE || token == MARGFUNC) {
1504 5362123 : yylval->sval = sa_strndup(c->sa, yylval->sval, lc->yycur-lc->yysval);
1505 5362142 : lc->next_string_is_raw = false;
1506 22596571 : } else if (token == STRING) {
1507 2078938 : char quote = *yylval->sval;
1508 2078938 : char *str = sa_alloc( c->sa, (lc->yycur-lc->yysval-2)*2 + 1 );
1509 2078938 : char *dst;
1510 :
1511 2078938 : assert(quote == '"' || quote == '\'' || quote == 'E' || quote == 'e' || quote == 'U' || quote == 'u' || quote == 'X' || quote == 'x' || quote == 'R' || quote == 'r');
1512 :
1513 2078938 : lc->rs->buf[lc->rs->pos + lc->yycur - 1] = 0;
1514 2078938 : switch (quote) {
1515 1296278 : case '"':
1516 1296278 : if (valid_ident(yylval->sval+1,str)) {
1517 : token = IDENT;
1518 : } else {
1519 0 : sql_error(c, 1, SQLSTATE(42000) "Invalid identifier '%s'", yylval->sval+1);
1520 0 : return LEX_ERROR;
1521 : }
1522 : break;
1523 3746 : case 'e':
1524 : case 'E':
1525 3746 : assert(yylval->sval[1] == '\'');
1526 3746 : if (GDKstrFromStr((unsigned char *) str,
1527 : (unsigned char *) yylval->sval + 2,
1528 3746 : lc->yycur-lc->yysval - 2, '\'') < 0) {
1529 1 : char *err = GDKerrbuf;
1530 1 : if (strncmp(err, GDKERROR, strlen(GDKERROR)) == 0)
1531 1 : err += strlen(GDKERROR);
1532 0 : else if (*err == '!')
1533 0 : err++;
1534 1 : sql_error(c, 1, SQLSTATE(42000) "%s", err);
1535 1 : return LEX_ERROR;
1536 : }
1537 : quote = '\'';
1538 : break;
1539 17 : case 'u':
1540 : case 'U':
1541 17 : assert(yylval->sval[1] == '&');
1542 17 : assert(yylval->sval[2] == '\'' || yylval->sval[2] == '"');
1543 17 : strcpy(str, yylval->sval + 3);
1544 17 : token = yylval->sval[2] == '\'' ? USTRING : UIDENT;
1545 17 : quote = yylval->sval[2];
1546 17 : lc->next_string_is_raw = true;
1547 17 : break;
1548 1 : case 'x':
1549 : case 'X':
1550 1 : assert(yylval->sval[1] == '\'');
1551 1 : dst = str;
1552 5 : for (char *src = yylval->sval + 2; *src; dst++)
1553 4 : if ((*dst = *src++) == '\'' && *src == '\'')
1554 0 : src++;
1555 1 : *dst = 0;
1556 1 : quote = '\'';
1557 1 : token = XSTRING;
1558 1 : lc->next_string_is_raw = true;
1559 1 : break;
1560 3270 : case 'r':
1561 : case 'R':
1562 3270 : assert(yylval->sval[1] == '\'');
1563 3270 : dst = str;
1564 450025 : for (char *src = yylval->sval + 2; *src; dst++)
1565 446755 : if ((*dst = *src++) == '\'' && *src == '\'')
1566 2732 : src++;
1567 3270 : quote = '\'';
1568 3270 : *dst = 0;
1569 3270 : break;
1570 775626 : default:
1571 775626 : if (lc->raw_string_mode || lc->next_string_is_raw) {
1572 46 : dst = str;
1573 436 : for (char *src = yylval->sval + 1; *src; dst++)
1574 390 : if ((*dst = *src++) == '\'' && *src == '\'')
1575 1 : src++;
1576 46 : *dst = 0;
1577 : } else {
1578 775580 : if (GDKstrFromStr((unsigned char *)str,
1579 775580 : (unsigned char *)yylval->sval + 1,
1580 775580 : lc->yycur - lc->yysval - 1,
1581 : '\'') < 0) {
1582 1 : sql_error(c, 1, SQLSTATE(42000) "%s", GDKerrbuf);
1583 1 : return LEX_ERROR;
1584 : }
1585 : }
1586 : break;
1587 : }
1588 2078936 : yylval->sval = str;
1589 :
1590 : /* reset original */
1591 2078936 : lc->rs->buf[lc->rs->pos+lc->yycur- 1] = quote;
1592 : } else {
1593 20517633 : lc->next_string_is_raw = false;
1594 : }
1595 :
1596 : return(token);
1597 : }
1598 :
1599 : static int scanner( YYSTYPE *yylval, void *m, bool log);
1600 :
1601 : static int
1602 28000512 : scanner(YYSTYPE * yylval, void *parm, bool log)
1603 : {
1604 28000512 : int token;
1605 28000512 : mvc *c = (mvc *) parm;
1606 28000512 : struct scanner *lc = &c->scanner;
1607 28000512 : size_t pos;
1608 :
1609 : /* store position for when view's query ends */
1610 28000512 : pos = lc->rs->pos + lc->yycur;
1611 :
1612 28000512 : token = sql_get_next_token(yylval, parm);
1613 :
1614 27999091 : if (token == NOT) {
1615 74404 : int next = scanner(yylval, parm, false);
1616 :
1617 74404 : if (next == NOT) {
1618 2 : return scanner(yylval, parm, false);
1619 : } else if (next == EXISTS) {
1620 : token = NOT_EXISTS;
1621 : } else if (next == BETWEEN) {
1622 : token = NOT_BETWEEN;
1623 : } else if (next == sqlIN) {
1624 : token = NOT_IN;
1625 : } else if (next == LIKE) {
1626 : token = NOT_LIKE;
1627 : } else if (next == ILIKE) {
1628 : token = NOT_ILIKE;
1629 : } else {
1630 61650 : lc->yynext = next;
1631 : }
1632 27924687 : } else if (token == SCOLON) {
1633 : /* ignore semi-colon(s) following a semi-colon */
1634 983092 : if (lc->yylast == SCOLON) {
1635 131976 : size_t prev = lc->yycur;
1636 131977 : while ((token = sql_get_next_token(yylval, parm)) == SCOLON)
1637 1 : prev = lc->yycur;
1638 :
1639 : /* skip the skipped stuff also in the buffer */
1640 131976 : lc->rs->pos += prev;
1641 131976 : lc->yycur -= prev;
1642 : }
1643 : }
1644 :
1645 27999089 : if (lc->log && log)
1646 0 : mnstr_write(lc->log, lc->rs->buf+pos, lc->rs->pos + lc->yycur - pos, 1);
1647 :
1648 27999089 : lc->started += (token != EOF);
1649 27999089 : return token;
1650 : }
1651 :
1652 : /* also see sql_parser.y */
1653 : extern int sqllex(YYSTYPE * yylval, void *parm);
1654 :
1655 : int
1656 27926788 : sqllex(YYSTYPE * yylval, void *parm)
1657 : {
1658 27926788 : return scanner(yylval, parm, true);
1659 : }
|