1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29 #include "davqlparser.h"
30 #include <cx/utils.h>
31 #include <cx/linked_list.h>
32 #include <cx/printf.h>
33 #include <string.h>
34 #include <stdio.h>
35 #include <ctype.h>
36
37 #define sfmtarg(s) ((
int)(s).length), (s).ptr
38
39
40
41
42
43 static const char* _map_querytype(
davqltype_t type) {
44 switch(type) {
45 case DAVQL_ERROR:
return "ERROR";
46 case DAVQL_SELECT:
return "SELECT";
47 case DAVQL_SET:
return "SET";
48 default:
return "unknown";
49 }
50 }
51
52 static const char* _map_exprtype(
davqlexprtype_t type) {
53 switch(type) {
54 case DAVQL_UNDEFINED_TYPE:
return "undefined";
55 case DAVQL_NUMBER:
return "NUMBER";
56 case DAVQL_STRING:
return "STRING";
57 case DAVQL_TIMESTAMP:
return "TIMESTAMP";
58 case DAVQL_IDENTIFIER:
return "IDENTIFIER";
59 case DAVQL_UNARY:
return "UNARY";
60 case DAVQL_BINARY:
return "BINARY";
61 case DAVQL_LOGICAL:
return "LOGICAL";
62 case DAVQL_FUNCCALL:
return "FUNCCALL";
63 default:
return "unknown";
64 }
65 }
66
67 static const char* _map_specialfield(
int info) {
68 switch(info) {
69 case 0:
return "";
70 case 1:
return "with wildcard";
71 case 2:
return "(resource data only)";
72 default:
return "with mysterious identifier";
73 }
74 }
75
76 static const char* _map_operator(
davqloperator_t op) {
77
78 switch(op) {
79 case DAVQL_NOOP:
return "no operator";
80 case DAVQL_CALL:
return "function call";
case DAVQL_ARGLIST:
return ",";
81 case DAVQL_ADD:
return "+";
case DAVQL_SUB:
return "-";
82 case DAVQL_MUL:
return "*";
case DAVQL_DIV:
return "/";
83 case DAVQL_AND:
return "&";
case DAVQL_OR:
return "|";
84 case DAVQL_XOR:
return "^";
case DAVQL_NEG:
return "~";
85 case DAVQL_NOT:
return "NOT";
case DAVQL_LAND:
return "AND";
86 case DAVQL_LOR:
return "OR";
case DAVQL_LXOR:
return "XOR";
87 case DAVQL_EQ:
return "=";
case DAVQL_NEQ:
return "!=";
88 case DAVQL_LT:
return "<";
case DAVQL_GT:
return ">";
89 case DAVQL_LE:
return "<=";
case DAVQL_GE:
return ">=";
90 case DAVQL_LIKE:
return "LIKE";
case DAVQL_UNLIKE:
return "UNLIKE";
91 default:
return "unknown";
92 }
93 }
94
95 static void dav_debug_ql_fnames_print(DavQLStatement *stmt) {
96 if (stmt->fields) {
97 printf(
"Field names: ");
98 CxIterator i = cxListIterator(stmt->fields);
99 cx_foreach(DavQLField *, f, i) {
100 printf(
"%.*s, ", (
int)f->name.length, f->name.ptr);
101 }
102 printf(
"\b\b \b\b\n");
103 }
104 }
105
106 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) {
107
108 size_t fieldcount = stmt->fields ? stmt->fields->size :
0;
109 int specialfield =
0;
110 if (stmt->fields && stmt->fields->size >
0) {
111 DavQLField* firstfield = (DavQLField*)cxListAt(stmt->fields,
0);
112 if (firstfield->expr->type ==
DAVQL_IDENTIFIER) {
113 switch (firstfield->expr->srctext.ptr[
0]) {
114 case '*': specialfield =
1;
break;
115 case '-': specialfield =
2;
break;
116 }
117 }
118 }
119 if (specialfield) {
120 fieldcount--;
121 }
122 printf(
"Statement: %.*s\nType: %s\nField count: %zu %s\n",
123 (
int)stmt->srctext.length, stmt->srctext.ptr,
124 _map_querytype(stmt->type),
125 fieldcount,
126 _map_specialfield(specialfield));
127
128 dav_debug_ql_fnames_print(stmt);
129 printf(
"Path: %.*s\nHas where clause: %s\n",
130 (
int)stmt->path.length, stmt->path.ptr,
131 stmt->where ?
"yes" :
"no");
132
133
134 if (stmt->depth ==
DAV_DEPTH_INFINITY) {
135 printf(
"Depth: infinity\n");
136 }
else if (stmt->depth ==
DAV_DEPTH_PLACEHOLDER) {
137 printf(
"Depth: placeholder\n");
138 }
else {
139 printf(
"Depth: %d\n", stmt->depth);
140 }
141
142
143 printf(
"Order by: ");
144 if (stmt->orderby) {
145 CxIterator i = cxListIterator(stmt->orderby);
146 cx_foreach(DavQLOrderCriterion*, critdata, i) {
147 printf(
"%.*s %s%s", (
int)critdata->column->srctext.length, critdata->column->srctext.ptr,
148 critdata->descending ?
"desc" :
"asc",
149 i.index+
1 < stmt->orderby->size ?
", " :
"\n");
150 }
151 }
else {
152 printf(
"nothing\n");
153 }
154
155
156 if (stmt->errorcode) {
157 printf(
"\nError code: %d\nError: %s\n",
158 stmt->errorcode, stmt->errormessage);
159 }
160 }
161
162 static int dav_debug_ql_expr_selected(DavQLExpression *expr) {
163 if (!expr) {
164 printf(
"Currently no expression selected.\n");
165 return 0;
166 }
else {
167 return 1;
168 }
169 }
170
171 static void dav_debug_ql_expr_print(DavQLExpression *expr) {
172 if (dav_debug_ql_expr_selected(expr)) {
173 cxstring empty =
CX_STR(
"(empty)");
174 printf(
175 "Text: %.*s\nType: %s\nOperator: %s\n",
176 sfmtarg(expr->srctext),
177 _map_exprtype(expr->type),
178 _map_operator(expr->op));
179 if (expr->left || expr->right) {
180 printf(
"Left hand: %.*s\nRight hand: %.*s\n",
181 sfmtarg(expr->left?expr->left->srctext:empty),
182 sfmtarg(expr->right?expr->right->srctext:empty));
183 }
184 }
185 }
186
187 static void dav_debug_ql_field_print(DavQLField *field) {
188 if (field) {
189 printf(
"Name: %.*s\n", sfmtarg(field->name));
190 if (field->expr) {
191 dav_debug_ql_expr_print(field->expr);
192 }
else {
193 printf(
"No expression.\n");
194 }
195 }
else {
196 printf(
"No field selected.\n");
197 }
198 }
199
200 static void dav_debug_ql_tree_print(DavQLExpression *expr,
int depth) {
201 if (expr) {
202 if (expr->left) {
203 printf(
"%*c%s\n", depth,
' ', _map_operator(expr->op));
204 dav_debug_ql_tree_print(expr->left, depth+
1);
205 dav_debug_ql_tree_print(expr->right, depth+
1);
206 }
else if (expr->type ==
DAVQL_UNARY) {
207 printf(
"%*c%s %.*s\n", depth,
' ', _map_operator(expr->op),
208 sfmtarg(expr->srctext));
209 }
else {
210 printf(
"%*c%.*s\n", depth,
' ', sfmtarg(expr->srctext));
211 }
212 }
213 }
214
215 #define DQLD_CMD_Q 0
216 #define DQLD_CMD_PS 1
217 #define DQLD_CMD_PE 2
218 #define DQLD_CMD_PF 3
219 #define DQLD_CMD_PT 4
220 #define DQLD_CMD_F 10
221 #define DQLD_CMD_W 11
222 #define DQLD_CMD_O 12
223 #define DQLD_CMD_L 21
224 #define DQLD_CMD_R 22
225 #define DQLD_CMD_N 23
226 #define DQLD_CMD_P 24
227 #define DQLD_CMD_H 100
228
229 static int dav_debug_ql_command() {
230 printf(
"> ");
231
232 char buffer[
8];
233 fgets(buffer,
8, stdin);
234
235 if (!strchr(buffer,
'\n')) {
236 int chr;
237 while ((chr = fgetc(stdin) !=
'\n') && chr !=
EOF);
238 }
239
240 if (!strcmp(buffer,
"q\n")) {
241 return DQLD_CMD_Q;
242 }
else if (!strcmp(buffer,
"ps\n")) {
243 return DQLD_CMD_PS;
244 }
else if (!strcmp(buffer,
"pe\n")) {
245 return DQLD_CMD_PE;
246 }
else if (!strcmp(buffer,
"pf\n")) {
247 return DQLD_CMD_PF;
248 }
else if (!strcmp(buffer,
"pt\n")) {
249 return DQLD_CMD_PT;
250 }
else if (!strcmp(buffer,
"l\n")) {
251 return DQLD_CMD_L;
252 }
else if (!strcmp(buffer,
"r\n")) {
253 return DQLD_CMD_R;
254 }
else if (!strcmp(buffer,
"h\n")) {
255 return DQLD_CMD_H;
256 }
else if (!strcmp(buffer,
"f\n")) {
257 return DQLD_CMD_F;
258 }
else if (!strcmp(buffer,
"w\n")) {
259 return DQLD_CMD_W;
260 }
else if (!strcmp(buffer,
"o\n")) {
261 return DQLD_CMD_O;
262 }
else if (!strcmp(buffer,
"n\n")) {
263 return DQLD_CMD_N;
264 }
else if (!strcmp(buffer,
"p\n")) {
265 return DQLD_CMD_P;
266 }
else {
267 return -
1;
268 }
269 }
270
271 void dav_debug_statement(DavQLStatement *stmt) {
272 if (!stmt) {
273 fprintf(stderr,
"Debug DavQLStatement failed: null pointer");
274 return;
275 }
276
277 printf(
"Starting DavQL debugger (type ''h'' for help)...\n\n");
278 dav_debug_ql_stmt_print(stmt);
279
280 if (stmt->errorcode) {
281 return;
282 }
283
284 DavQLExpression *examineexpr =
NULL;
285 CxList *examineelem =
NULL;
286 int examineclause =
0;
287
288 while(
1) {
289 int cmd = dav_debug_ql_command();
290 switch (cmd) {
291 case DQLD_CMD_Q:
return;
292 case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt);
break;
293 case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr);
break;
294 case DQLD_CMD_PT: dav_debug_ql_tree_print(examineexpr,
1);
break;
295 case DQLD_CMD_PF: dav_debug_ql_fnames_print(stmt);
break;
296 case DQLD_CMD_F:
297 examineclause =
DQLD_CMD_F;
298 examineelem = stmt->fields;
299 if (stmt->fields && stmt->fields->size >
0) {
300 DavQLField* field = cxListAt(stmt->fields,
0);
301 examineexpr = field->expr;
302 dav_debug_ql_field_print(field);
303 }
else {
304 examineexpr =
NULL;
305 }
306 break;
307 case DQLD_CMD_W:
308 examineclause =
0; examineelem =
NULL;
309 examineexpr = stmt->where;
310 dav_debug_ql_expr_print(examineexpr);
311 break;
312 case DQLD_CMD_O:
313 examineclause =
DQLD_CMD_O;
314 examineelem = stmt->orderby;
315 examineexpr = stmt->orderby && stmt->orderby->size >
0 ?
316 ((DavQLOrderCriterion*)cxListAt(stmt->orderby,
0))->column :
NULL;
317 dav_debug_ql_expr_print(examineexpr);
318 break;
319 case DQLD_CMD_N:
320 case DQLD_CMD_P:
321 printf(
"TODO: port code to ucx 3\n");
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346 break;
347 case DQLD_CMD_L:
348 if (dav_debug_ql_expr_selected(examineexpr)) {
349 if (examineexpr->left) {
350 examineexpr = examineexpr->left;
351 dav_debug_ql_expr_print(examineexpr);
352 }
else {
353 printf(
"There is no left subtree.\n");
354 }
355 }
356 break;
357 case DQLD_CMD_R:
358 if (dav_debug_ql_expr_selected(examineexpr)) {
359 if (examineexpr->right) {
360 examineexpr = examineexpr->right;
361 dav_debug_ql_expr_print(examineexpr);
362 }
else {
363 printf(
"There is no right subtree.\n");
364 }
365 }
366 break;
367 case DQLD_CMD_H:
368 printf(
369 "\nCommands:\n"
370 "ps: print statement information\n"
371 "o: examine order by clause\n"
372 "f: examine field list\n"
373 "pf: print field names\n"
374 "w: examine where clause\n"
375 "n: examine next expression "
376 "(in order by clause or field list)\n"
377 "p: examine previous expression "
378 "(in order by clause or field list)\n"
379 "q: quit\n\n"
380 "\nExpression examination:\n"
381 "pe: print expression information\n"
382 "pt: print full syntax tree of current (sub-)expression\n"
383 "l: enter left subtree\n"
384 "r: enter right subtree\n");
385 break;
386 default: printf(
"unknown command\n");
387 }
388 }
389 }
390
391
392
393
394
395 #define _error_context
"(%.*s[->]%.*s%.*s)"
396 #define _error_invalid
"invalid statement"
397 #define _error_out_of_memory
"out of memory"
398 #define _error_unexpected_token
"unexpected token " _error_context
399 #define _error_invalid_token
"invalid token " _error_context
400 #define _error_missing_path
"expected path " _error_context
401 #define _error_missing_from
"expecting FROM keyword " _error_context
402 #define _error_missing_at
"expecting AT keyword " _error_context
403 #define _error_missing_by
"expecting BY keyword " _error_context
404 #define _error_missing_as
"expecting alias (''as <identifier>'') " _error_context
405 #define _error_missing_identifier
"expecting identifier " _error_context
406 #define _error_missing_par
"missing closed parenthesis " _error_context
407 #define _error_missing_assign
"expecting assignment (''='') " _error_context
408 #define _error_missing_where
"SET statements must have a WHERE clause or " \
409 "explicitly use ANYWHERE " _error_context
410 #define _error_invalid_depth
"invalid depth " _error_context
411 #define _error_missing_expr
"missing expression " _error_context
412 #define _error_invalid_expr
"invalid expression " _error_context
413 #define _error_invalid_unary_op
"invalid unary operator " _error_context
414 #define _error_invalid_logical_op
"invalid logical operator " _error_context
415 #define _error_invalid_fmtspec
"invalid format specifier " _error_context
416 #define _error_invalid_string
"string expected " _error_context
417 #define _error_invalid_order_criterion
"invalid order criterion " _error_context
418
419 #define token_sstr(token) ((token)->value)
420
421 static void dav_error_in_context(
int errorcode,
const char *errormsg,
422 DavQLStatement *stmt, DavQLToken *token) {
423
424
425
426 cxstring emptystring =
CX_STR(
"");
427 cxstring prev = token->prev ? (token->prev->prev ?
428 token_sstr(token->prev->prev) : token_sstr(token->prev))
429 : emptystring;
430 cxstring tokenstr = token_sstr(token);
431 cxstring next = token->next ? (token->next->next ?
432 token_sstr(token->next->next) : token_sstr(token->next))
433 : emptystring;
434
435 int lp = prev.length ==
0 ?
0 : tokenstr.ptr-prev.ptr;
436 const char *pn = tokenstr.ptr + tokenstr.length;
437 int ln = next.ptr+next.length - pn;
438
439 stmt->errorcod
= errorcode;
440 stmt->errormessage = cx_asprintf(errormsg,
441 lp, prev.ptr,
442 sfmtarg(tokenstr),
443 ln, pn).ptr;
444 }
445
446 #define dqlsec_alloc_failed(ptr, stmt) \
447 if (!(ptr))
do { \
448 (stmt)->errorcode =
DAVQL_ERROR_OUT_OF_MEMORY; \
449 return 0; \
450 }
while(
0)
451 #define dqlsec_malloc(stmt, ptr, type) \
452 dqlsec_alloc_failed(ptr = malloc(
sizeof(type)), stmt)
453 #define dqlsec_mallocz(stmt, ptr, type) \
454 dqlsec_alloc_failed(ptr = calloc(
1,
sizeof(type)), stmt)
455
456
457
458 static const char *special_token_symbols =
",()+-*/&|^~=!<>";
459
460 static _Bool iskeyword(DavQLToken *token) {
461 cxstring keywords[] ={
CX_STR(
"select"),
CX_STR(
"set"),
CX_STR(
"from"),
CX_STR(
"at"),
CX_STR(
"as"),
462 CX_STR(
"where"),
CX_STR(
"anywhere"),
CX_STR(
"like"),
CX_STR(
"unlike"),
CX_STR(
"and"),
463 CX_STR(
"or"),
CX_STR(
"not"),
CX_STR(
"xor"),
CX_STR(
"with"),
CX_STR(
"infinity"),
464 CX_STR(
"order"),
CX_STR(
"by"),
CX_STR(
"asc"),
CX_STR(
"desc")
465 };
466 for (
int i =
0 ; i <
sizeof(keywords)/
sizeof(cxstring) ; i++) {
467 if (!cx_strcasecmp(token->value, keywords[i])) {
468 return 1;
469 }
470 }
471 return 0;
472 }
473
474 static _Bool islongoperator(DavQLToken *token) {
475 cxstring operators[] = {
CX_STR(
"and"),
CX_STR(
"or"),
CX_STR(
"not"),
CX_STR(
"xor"),
476 CX_STR(
"like"),
CX_STR(
"unlike")
477 };
478 for (
int i =
0 ; i <
sizeof(operators)/
sizeof(cxstring) ; i++) {
479 if (!cx_strcasecmp(token->value, operators[i])) {
480 return 1;
481 }
482 }
483 return 0;
484 }
485
486 static int dav_stmt_add_field(DavQLStatement *stmt, DavQLField *field) {
487 if(!stmt->fields) {
488 stmt->fields = cxLinkedListCreateSimple(
CX_STORE_POINTERS);
489 if(!stmt->fields) {
490 stmt->errorcode =
DAVQL_ERROR_OUT_OF_MEMORY;
491 return 1;
492 }
493 }
494
495 if(cxListAdd(stmt->fields, field)) {
496 stmt->errorcode =
DAVQL_ERROR_OUT_OF_MEMORY;
497 return 1;
498 }
499
500 return 0;
501 }
502
503
504 static void tokenlist_free(DavQLToken *tokenlist) {
505 DavQLToken *token = tokenlist;
506 while(token) {
507 DavQLToken *next = token->next;
508 free(token);
509 token = next;
510 }
511 }
512
513 static int dav_parse_add_token(DavQLToken **begin, DavQLToken **end, DavQLToken *token) {
514
515
516 char firstchar = token->value.ptr[
0];
517
518 if (isdigit(firstchar)) {
519 token->tokenclass =
DAVQL_TOKEN_NUMBER;
520
521 for (
size_t i =
1 ; i < token->value.length ; i++) {
522 if (!isdigit(token->value.ptr[i])) {
523 token->tokenclass =
DAVQL_TOKEN_INVALID;
524 break;
525 }
526 }
527 }
else if (firstchar ==
'%') {
528 token->tokenclass =
DAVQL_TOKEN_FMTSPEC;
529 }
else if (token->value.length ==
1) {
530 switch (firstchar) {
531 case '(': token->tokenclass =
DAVQL_TOKEN_OPENP;
break;
532 case ')': token->tokenclass =
DAVQL_TOKEN_CLOSEP;
break;
533 case ',': token->tokenclass =
DAVQL_TOKEN_COMMA;
break;
534 default:
535 token->tokenclass = strchr(special_token_symbols, firstchar) ?
536 DAVQL_TOKEN_OPERATOR :
DAVQL_TOKEN_IDENTIFIER;
537 }
538 }
else if (islongoperator(token)) {
539 token->tokenclass =
DAVQL_TOKEN_OPERATOR;
540 }
else if (firstchar ==
'\'') {
541 token->tokenclass =
DAVQL_TOKEN_STRING;
542 }
else if (firstchar ==
'`') {
543 token->tokenclass =
DAVQL_TOKEN_IDENTIFIER;
544 }
else if (iskeyword(token)) {
545 token->tokenclass =
DAVQL_TOKEN_KEYWORD;
546 }
else {
547 token->tokenclass =
DAVQL_TOKEN_IDENTIFIER;
548 ,
1216 _error_invalid_string, stmt, token);
1217 return 0;
1218 }
1219 }
1220
1221 else if (token_is(optok,
DAVQL_TOKEN_OPERATOR) && (
1222 tokenvalue_is(optok,
"=") || tokenvalue_is(optok,
"!") ||
1223 tokenvalue_is(optok,
"<") || tokenvalue_is(optok,
">"))) {
1224
1225 total_consumed++;
1226 token = token->next;
1227
1228 if (tokenvalue_is(optok,
"=")) {
1229 expr->op =
DAVQL_EQ;
1230 }
else {
1231 if (tokenvalue_is(token,
"=")) {
1232 if (tokenvalue_is(optok,
"!")) {
1233 expr->op =
DAVQL_NEQ;
1234 }
else if (tokenvalue_is(optok,
"<")) {
1235 expr->op =
DAVQL_LE;
1236 }
else if (tokenvalue_is(optok,
">")) {
1237 expr->op =
DAVQL_GE;
1238 }
1239 total_consumed++;
1240 token = token->next;
1241 }
else {
1242 if (tokenvalue_is(optok,
"<")) {
1243 expr->op =
DAVQL_LT;
1244 }
else if (tokenvalue_is(optok,
">")) {
1245 expr->op =
DAVQL_GT;
1246 }
1247 }
1248 }
1249
1250 DavQLExpression rexpr;
1251 memset(&rexpr,
0,
sizeof(DavQLExpression));
1252 int consumed = dav_parse_expression(stmt, token, &rexpr);
1253 if (stmt->errorcode) {
1254 return 0;
1255 }
1256 if (!consumed) {
1257 dav_error_in_context(
1258 DAVQL_ERROR_MISSING_EXPR, _error_missing_expr,
1259 stmt, token);
1260 return 0;
1261 }
1262
1263 total_consumed += consumed;
1264 dqlsec_malloc(stmt, expr->left, DavQLExpression);
1265 memcpy(expr->left, &bexpr,
sizeof(DavQLExpression));
1266 dqlsec_malloc(stmt, expr->right, DavQLExpression);
1267 memcpy(expr->right, &rexpr,
sizeof(DavQLExpression));
1268
1269 expr->srctext.length = expr->right->srctext.ptr -
1270 expr->srctext.ptr + expr->right->srctext.length;
1271
1272 return total_consumed;
1273 }
1274
1275 else if (bexpr.type ==
DAVQL_FUNCCALL || bexpr.type ==
DAVQL_IDENTIFIER) {
1276 memcpy(expr, &bexpr,
sizeof(DavQLExpression));
1277
1278 return total_consumed;
1279 }
else {
1280 return 0;
1281 }
1282 }
1283
1284 static int dav_parse_bool_expr(DavQLStatement *stmt, DavQLToken *token,
1285 DavQLExpression *expr) {
1286
1287
1288 if (token_is(token,
DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token,
"not")) {
1289 expr->type =
DAVQL_LOGICAL;
1290 expr->op =
DAVQL_NOT;
1291 dqlsec_mallocz(stmt, expr->left, DavQLExpression);
1292 expr->srctext = token_sstr(token);
1293
1294 token = token->next;
1295 int consumed = dav_parse_bool_expr(stmt, token, expr->left);
1296 if (stmt->errorcode) {
1297 return 0;
1298 }
1299 if (consumed) {
1300 cxstring lasttok = token_sstr((DavQLToken*)cx_linked_list_at(token,
0, offsetof(DavQLToken, next), consumed-
1));
1301 expr->srctext.length =
1302 lasttok.ptr - expr->srctext.ptr + lasttok.length;
1303 return consumed +
1;
1304 }
else {
1305 dav_error_in_context(
DAVQL_ERROR_MISSING_EXPR,
1306 _error_missing_expr, stmt, token);
1307 return 0;
1308 }
1309 }
1310
1311 else if (token_is(token,
DAVQL_TOKEN_OPENP)) {
1312 int consumed = dav_parse_logical_expr(stmt, token->next, expr);
1313 if (consumed) {
1314 token = cx_linked_list_at(token,
0, offsetof(DavQLToken, next), consumed);
1315
1316 if (token_is(token,
DAVQL_TOKEN_CLOSEP)) {
1317 token = token->next;
1318 return consumed +
2;
1319 }
else {
1320 dav_error_in_context(
DAVQL_ERROR_MISSING_PAR, _error_missing_par,
1321 stmt, token);
1322 return 0;
1323 }
1324 }
else {
1325
1326 stmt->errorcode =
0;
1327 if (stmt->errormessage) {
1328 free(stmt->errormessage);
1329 }
1330 }
1331 }
1332
1333
1334 return dav_parse_bool_prim(stmt, token, expr);
1335 }
1336
1337 static int dav_parse_logical_expr(DavQLStatement *stmt, DavQLToken *token,
1338 DavQLExpression *expr) {
1339
1340 DavQLToken *firsttoken = token;
1341 int total_consumed =
0;
1342
1343
1344 DavQLExpression left, right;
1345 memset(&left,
0,
sizeof(DavQLExpression));
1346 int consumed = dav_parse_bool_expr(stmt, token, &left);
1347 if (stmt->errorcode) {
1348 return 0;
1349 }
1350 if (!consumed) {
1351 dav_error_in_context(
DAVQL_ERROR_MISSING_EXPR,
1352 _error_missing_expr, stmt, token);
1353 return 0;
1354 }
1355 total_consumed += consumed;
1356 token = cx_linked_list_at(token,
0, offsetof(DavQLToken, next), consumed);
1357
1358 if (token_is(token,
DAVQL_TOKEN_OPERATOR)) {
1359 expr->type =
DAVQL_LOGICAL;
1360
1361 davqloperator_t op =
DAVQL_NOOP;
1362 if (tokenvalue_is(token,
"and")) {
1363 op =
DAVQL_LAND;
1364 }
else if (tokenvalue_is(token,
"or")) {
1365 op =
DAVQL_LOR;
1366 }
else if (tokenvalue_is(token,
"xor")) {
1367 op =
DAVQL_LXOR;
1368 }
1369
1370 if (op ==
DAVQL_NOOP) {
1371 dav_error_in_context(
DAVQL_ERROR_INVALID_LOGICAL_OP,
1372 _error_invalid_logical_op, stmt, token);
1373 return 0;
1374 }
else {
1375 expr->op = op;
1376 total_consumed++;
1377 token = token->next;
1378
1379 memset(&right,
0,
sizeof(DavQLExpression));
1380 consumed = dav_parse_logical_expr(stmt, token, &right);
1381 if (stmt->errorcode) {
1382 return 0;
1383 }
1384 if (!consumed) {
1385 dav_error_in_context(
DAVQL_ERROR_MISSING_EXPR,
1386 _error_missing_expr, stmt, token);
1387 return 0;
1388 }
1389 total_consumed += consumed;
1390 token = cx_linked_list_at(token,
0, offsetof(DavQLToken, next), consumed);
1391
1392 dqlsec_malloc(stmt, expr->left, DavQLExpression);
1393 memcpy(expr->left, &left,
sizeof(DavQLExpression));
1394 dqlsec_malloc(stmt, expr->right, DavQLExpression);
1395 memcpy(expr->right, &right,
sizeof(DavQLExpression));
1396 }
1397 }
else {
1398 memcpy(expr, &left,
sizeof(DavQLExpression));
1399 }
1400
1401
1402 if (total_consumed >
0) {
1403 expr->srctext.ptr = token_sstr(firsttoken).ptr;
1404 cxstring lasttok = token_sstr((DavQLToken*)cx_linked_list_at(firsttoken,
0, offsetof(DavQLToken, next), total_consumed-
1));
1405 expr->srctext.length = lasttok.ptr-expr->srctext.ptr+lasttok.length;
1406 }
1407
1408 return total_consumed;
1409 }
1410
1411 static int dav_parse_where_clause(DavQLStatement *stmt, DavQLToken *token) {
1412 dqlsec_mallocz(stmt, stmt->where, DavQLExpression);
1413
1414 return dav_parse_logical_expr(stmt, token, stmt->where);
1415 }
1416
1417 static int dav_parse_with_clause(DavQLStatement *stmt, DavQLToken *token) {
1418
1419 int total_consumed =
0;
1420
1421
1422 if (tokenvalue_is(token,
"depth")) {
1423 token = token->next; total_consumed++;
1424 if (tokenvalue_is(token,
"=")) {
1425 token = token->next; total_consumed++;
1426 if (tokenvalue_is(token,
"infinity")) {
1427 stmt->depth =
DAV_DEPTH_INFINITY;
1428 token = token->next; total_consumed++;
1429 }
else {
1430 DavQLExpression *depthexpr;
1431 dqlsec_mallocz(stmt, depthexpr, DavQLExpression);
1432
1433 int consumed = dav_parse_expression(stmt, token, depthexpr);
1434
1435 if (consumed) {
1436 if (depthexpr->type ==
DAVQL_NUMBER) {
1437 if (depthexpr->srctext.ptr[
0] ==
'%') {
1438 stmt->depth =
DAV_DEPTH_PLACEHOLDER;
1439 }
else {
1440 cxstring depthstr = depthexpr->srctext;
1441 char *conv = malloc(depthstr.length+
1);
1442 if (!conv) {
1443 dav_free_expression(depthexpr);
1444 stmt->errorcode =
DAVQL_ERROR_OUT_OF_MEMORY;
1445 return 0;
1446 }
1447 char *chk;
1448 memcpy(conv, depthstr.ptr, depthstr.length);
1449 conv[depthstr.length] =
'\0';
1450 stmt->depth = strtol(conv, &chk,
10);
1451 if (*chk || stmt->depth < -
1) {
1452 dav_error_in_context(
DAVQL_ERROR_INVALID_DEPTH,
1453 _error_invalid_depth, stmt, token);
1454 }
1455 free(conv);
1456 }
1457 total_consumed += consumed;
1458 }
else {
1459 dav_error_in_context(
DAVQL_ERROR_INVALID_DEPTH,
1460 _error_invalid_depth, stmt, token);
1461 }
1462 }
1463
1464 dav_free_expression(depthexpr);
1465 }
1466 }
1467 }
1468
1469 return total_consumed;
1470 }
1471
1472 static int dav_parse_order_crit(DavQLStatement *stmt, DavQLToken *token,
1473 DavQLOrderCriterion *crit) {
1474
1475
1476 DavQLExpression expr;
1477 memset(&expr,
0,
sizeof(DavQLExpression));
1478 int consumed = dav_parse_expression(stmt, token, &expr);
1479 if (stmt->errorcode || !consumed) {
1480 return 0;
1481 }
1482
1483 if (expr.type !=
DAVQL_IDENTIFIER && expr.type !=
DAVQL_NUMBER) {
1484 dav_error_in_context(
DAVQL_ERROR_INVALID_ORDER_CRITERION,
1485 _error_invalid_order_criterion, stmt, token);
1486 return 0;
1487 }
1488
1489 dqlsec_malloc(stmt, crit->column, DavQLExpression);
1490 memcpy(crit->column, &expr,
sizeof(DavQLExpression));
1491
1492 token = cx_linked_list_at(token,
0, offsetof(DavQLToken, next), consumed);
1493 if (token_is(token,
DAVQL_TOKEN_KEYWORD) && (
1494 tokenvalue_is(token,
"asc") || tokenvalue_is(token,
"desc"))) {
1495
1496 crit->descending = tokenvalue_is(token,
"desc");
1497
1498 return consumed+
1;
1499 }
else {
1500 crit->descending =
0;
1501 return consumed;
1502 }
1503 }
1504
1505 static int dav_parse_orderby_clause(DavQLStatement *stmt, DavQLToken *token) {
1506
1507 int total_consumed =
0, consumed;
1508
1509 DavQLOrderCriterion crit;
1510
1511 if(!stmt->orderby) {
1512 stmt->orderby = cxLinkedListCreateSimple(
sizeof(DavQLOrderCriterion));
1513 if(!stmt->orderby) {
1514 return 0;
1515 }
1516 }
1517
1518
1519 do {
1520 consumed = dav_parse_order_crit(stmt, token, &crit);
1521 if (stmt->errorcode) {
1522 return 0;
1523 }
1524 if (!consumed) {
1525 dav_error_in_context(
DAVQL_ERROR_MISSING_EXPR, _error_missing_expr,
1526 stmt, token);
1527 return 0;
1528 }
1529 token = cx_linked_list_at(token,
0, offsetof(DavQLToken, next), consumed);
1530 total_consumed += consumed;
1531
1532 if(cxListAdd(stmt->orderby, &crit)) {
1533 stmt->errorcode =
DAVQL_ERROR_OUT_OF_MEMORY;
1534 return 0;
1535 }
1536
1537 if (token_is(token,
DAVQL_TOKEN_COMMA)) {
1538 total_consumed++;
1539 token = token->next;
1540 }
else {
1541 consumed =
0;
1542 }
1543 }
while (consumed);
1544
1545 return total_consumed;
1546 }
1547
1548
1549 static int dav_parse_assignments(DavQLStatement *stmt, DavQLToken *token) {
1550
1551
1552 int total_consumed =
0, consumed;
1553 do {
1554
1555 if (token_is(token,
DAVQL_TOKEN_IDENTIFIER)) {
1556
1557
1558 DavQLField *field;
1559 dqlsec_malloc(stmt, field, DavQLField);
1560 field->name = token_sstr(token);
1561 total_consumed++;
1562 token = token->next;
1563
1564
1565 if (!token_is(token,
DAVQL_TOKEN_OPERATOR)
1566 || !tokenvalue_is(token,
"=")) {
1567 dav_free_field(field);
1568
1569 dav_error_in_context(
DAVQL_ERROR_MISSING_ASSIGN,
1570 _error_missing_assign, stmt, token);
1571 return total_consumed;
1572 }
1573 total_consumed++;
1574 token = token->next;
1575
1576
1577 dqlsec_mallocz(stmt, field->expr, DavQLExpression);
1578 consumed = dav_parse_expression(stmt, token, field->expr);
1579 if (stmt->errorcode) {
1580 dav_free_field(field);
1581 return total_consumed;
1582 }
1583 token = cx_linked_list_at(token,
0, offsetof(DavQLToken, next), consumed);
1584 total_consumed += consumed;
1585
1586
1587 if(dav_stmt_add_field(stmt, field)) {
1588 free(field);
1589 return 0;
1590 }
1591 consumed = token_is(token,
DAVQL_TOKEN_COMMA) ?
1 :
0;
1592 if (consumed) {
1593 token = token->next;
1594 total_consumed++;
1595 }
1596 }
else {
1597 dav_error_in_context(
DAVQL_ERROR_MISSING_TOKEN,
1598 _error_missing_identifier, stmt, token);
1599 return total_consumed;
1600 }
1601 }
while (consumed);
1602
1603 return total_consumed;
1604 }
1605
1606 static int dav_parse_path(DavQLStatement *stmt, DavQLToken *tokens) {
1607 if (token_is(tokens,
DAVQL_TOKEN_STRING)) {
1608 stmt->path = token_sstr(tokens);
1609 tokens = tokens->next;
1610 return 1;
1611 }
else if (token_is(tokens,
DAVQL_TOKEN_OPERATOR)
1612 && tokenvalue_is(tokens,
"/")) {
1613 stmt->path = token_sstr(tokens);
1614 tokens = tokens->next;
1615 int consumed =
1;
1616 while (!token_is(tokens,
DAVQL_TOKEN_KEYWORD) &&
1617 !token_is(tokens,
DAVQL_TOKEN_END)) {
1618 cxstring toksstr = token_sstr(tokens);
1619 stmt->path.length = toksstr.ptr-stmt->path.ptr+toksstr.length;
1620 tokens = tokens->next;
1621 consumed++;
1622 }
1623 return consumed;
1624 }
else if (token_is(tokens,
DAVQL_TOKEN_FMTSPEC) &&
1625 tokenvalue_is(tokens,
"%s")) {
1626 stmt->path = token_sstr(tokens);
1627 tokens = tokens->next;
1628 fmt_args_add(stmt, (
void*)(
intptr_t)
's');
1629 return 1;
1630 }
else {
1631 dav_error_in_context(
DAVQL_ERROR_MISSING_TOKEN,
1632 _error_missing_path, stmt, tokens);
1633 return 0;
1634 }
1635 }
1636
1637
1638
1639
1640
1641
1642 static void dav_parse_select_statement(DavQLStatement *stmt, DavQLToken *tokens) {
1643 stmt->type =
DAVQL_SELECT;
1644
1645
1646 tokens = cx_linked_list_at(tokens,
0, offsetof(DavQLToken, next), dav_parse_fieldlist(stmt, tokens));
1647 if (stmt->errorcode) {
1648 return;
1649 }
1650
1651
1652 if (token_is(tokens,
DAVQL_TOKEN_KEYWORD)
1653 && tokenvalue_is(tokens,
"from")) {
1654 tokens = tokens->next;
1655 }
else {
1656 dav_error_in_context(
DAVQL_ERROR_MISSING_TOKEN,
1657 _error_missing_from, stmt, tokens);
1658 return;
1659 }
1660
1661
1662 tokens = cx_linked_list_at(tokens,
0, offsetof(DavQLToken, next), dav_parse_path(stmt, tokens));
1663 if (stmt->errorcode) {
1664 return;
1665 }
1666
1667
1668
1669 if (token_is(tokens,
DAVQL_TOKEN_KEYWORD)
1670 && tokenvalue_is(tokens,
"with")) {
1671 tokens = tokens->next;
1672 tokens = cx_linked_list_at(tokens,
0, offsetof(DavQLToken, next),
1673 dav_parse_with_clause(stmt, tokens));
1674 }
1675 if (stmt->errorcode) {
1676 return;
1677 }
1678
1679
1680 if (token_is(tokens,
DAVQL_TOKEN_KEYWORD)
1681 && tokenvalue_is(tokens,
"where")) {
1682 tokens = tokens->next;
1683 tokens = cx_linked_list_at(tokens,
0, offsetof(DavQLToken, next),
1684 dav_parse_where_clause(stmt, tokens));
1685 }
else if (token_is(tokens,
DAVQL_TOKEN_KEYWORD)
1686 && tokenvalue_is(tokens,
"anywhere")) {
1687
1688 tokens = tokens->next;
1689 stmt->where =
NULL;
1690 }
1691 if (stmt->errorcode) {
1692 return;
1693 }
1694
1695
1696 if (token_is(tokens,
DAVQL_TOKEN_KEYWORD)
1697 && tokenvalue_is(tokens,
"order")) {
1698 tokens = tokens->next;
1699 if (token_is(tokens,
DAVQL_TOKEN_KEYWORD)
1700 && tokenvalue_is(tokens,
"by")) {
1701 tokens = tokens->next;
1702 tokens = cx_linked_list_at(tokens,
0, offsetof(DavQLToken, next),
1703 dav_parse_orderby_clause(stmt, tokens));
1704 }
else {
1705 dav_error_in_context(
DAVQL_ERROR_MISSING_TOKEN,
1706 _error_missing_by, stmt, tokens);
1707 return;
1708 }
1709 }
1710 if (stmt->errorcode) {
1711 return;
1712 }
1713
1714
1715 if (tokens) {
1716 if (token_is(tokens,
DAVQL_TOKEN_INVALID)) {
1717 dav_error_in_context(
DAVQL_ERROR_INVALID_TOKEN,
1718 _error_invalid_token, stmt, tokens);
1719 }
else if (!token_is(tokens,
DAVQL_TOKEN_END)) {
1720 dav_error_in_context(
DAVQL_ERROR_UNEXPECTED_TOKEN,
1721 _error_unexpected_token, stmt, tokens);
1722 }
1723 }
1724 }
1725
1726 static void dav_parse_set_statement(DavQLStatement *stmt, DavQLToken *tokens) {
1727 stmt->type =
DAVQL_SET;
1728
1729
1730 tokens = cx_linked_list_at(tokens,
0, offsetof(DavQLToken, next), dav_parse_assignments(stmt, tokens));
1731 if (stmt->errorcode) {
1732 return;
1733 }
1734
1735
1736 if (token_is(tokens,
DAVQL_TOKEN_KEYWORD)
1737 && tokenvalue_is(tokens,
"at")) {
1738 tokens = tokens->next;
1739 }
else {
1740 dav_error_in_context(
DAVQL_ERROR_MISSING_TOKEN,
1741 _error_missing_at, stmt, tokens);
1742 return;
1743 }
1744
1745