libidav/davqlparser.c

changeset 96
896022673e0e
parent 95
8ed7d8df6427
child 97
f82cb65a78ec
equal deleted inserted replaced
95:8ed7d8df6427 96:896022673e0e
47 } 47 }
48 } 48 }
49 49
50 static const char* _map_exprtype(davqlexprtype_t type) { 50 static const char* _map_exprtype(davqlexprtype_t type) {
51 switch(type) { 51 switch(type) {
52 case DAVQL_LITERAL: return "LITERAL"; 52 case DAVQL_NUMBER: return "NUMBER";
53 case DAVQL_STRING: return "STRING";
54 case DAVQL_TIMESTAMP: return "TIMESTAMP";
53 case DAVQL_IDENTIFIER: return "IDENTIFIER"; 55 case DAVQL_IDENTIFIER: return "IDENTIFIER";
54 case DAVQL_UNARY: return "UNARY"; 56 case DAVQL_UNARY: return "UNARY";
55 case DAVQL_BINARY: return "BINARY"; 57 case DAVQL_BINARY: return "BINARY";
56 case DAVQL_LOGICAL: return "LOGICAL"; 58 case DAVQL_LOGICAL: return "LOGICAL";
57 case DAVQL_FUNCCALL: return "FUNCCALL"; 59 case DAVQL_FUNCCALL: return "FUNCCALL";
116 ucx_list_size(stmt->fields) == ucx_list_size(stmt->setvalues) 118 ucx_list_size(stmt->fields) == ucx_list_size(stmt->setvalues)
117 ? "yes" : "no"); 119 ? "yes" : "no");
118 } 120 }
119 121
120 // WITH attributes 122 // WITH attributes
121 if (stmt->depth < 0) { 123 if (stmt->depth == DAV_DEPTH_INFINITY) {
122 printf("Depth: infinity\n"); 124 printf("Depth: infinity\n");
125 } else if (stmt->depth == DAV_DEPTH_PLACEHOLDER) {
126 printf("Depth: placeholder\n");
123 } else { 127 } else {
124 printf("Depth: %d\n", stmt->depth); 128 printf("Depth: %d\n", stmt->depth);
125 }
126 if (stmt->errorcode) {
127 printf("\nError code: %d\nError: %s\n",
128 stmt->errorcode, stmt->errormessage);
129 } 129 }
130 130
131 // order by clause 131 // order by clause
132 printf("Order by: "); 132 printf("Order by: ");
133 if (stmt->orderby) { 133 if (stmt->orderby) {
134 UCX_FOREACH(crit, stmt->orderby) { 134 UCX_FOREACH(crit, stmt->orderby) {
135 DavQLOrderCriterion *critdata = crit->data; 135 DavQLOrderCriterion *critdata = crit->data;
136 printf("%.*s %s%s", sfmtarg(critdata->column->srctext), 136 printf("%.*s %s%s", sfmtarg(critdata->column->srctext),
137 critdata->ascending ? "asc" : "desc", 137 critdata->descending ? "desc" : "asc",
138 crit->next ? ", " : "\n"); 138 crit->next ? ", " : "\n");
139 } 139 }
140 } else { 140 } else {
141 printf("nothing\n"); 141 printf("nothing\n");
142 }
143
144 // error messages
145 if (stmt->errorcode) {
146 printf("\nError code: %d\nError: %s\n",
147 stmt->errorcode, stmt->errormessage);
142 } 148 }
143 } 149 }
144 150
145 static int dav_debug_ql_expr_selected(DavQLExpression *expr) { 151 static int dav_debug_ql_expr_selected(DavQLExpression *expr) {
146 if (!expr) { 152 if (!expr) {
258 #define _unexpected_end_msg "unexpected end of statement" 264 #define _unexpected_end_msg "unexpected end of statement"
259 #define _invalid_msg "invalid statement" 265 #define _invalid_msg "invalid statement"
260 #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)" 266 #define _unexpected_token "unexpected token (%.*s [->]%.*s %.*s)"
261 #define _expected_token "expected token '%s' before '%.*s'" 267 #define _expected_token "expected token '%s' before '%.*s'"
262 #define _expected_by "expected 'by' after 'order' (order [->]%.*s)" 268 #define _expected_by "expected 'by' after 'order' (order [->]%.*s)"
269 #define _missing_fmtspec "format specifier missing (%.*s [->]%.*s %.*s)"
270 #define _invalid_fmtspec "invalid format specifier (%.*s [->]%.*s %.*s)"
271 #define _unknown_fmtspec "unknown format specifier (%.*s [->]%.*s %.*s)"
263 #define _missing_quote "missing closing quote symbol (%.*s)" 272 #define _missing_quote "missing closing quote symbol (%.*s)"
264 #define _parser_state "parser reached invalid state" 273 #define _parser_state "parser reached invalid state"
265 #define _unknown_attribute "unknown attribute '%.*s'" 274 #define _unknown_attribute "unknown attribute '%.*s'"
266 #define _duplicated_attribute "duplicated attribute '%.*s'" 275 #define _duplicated_attribute "duplicated attribute '%.*s'"
267 #define _invalid_depth "invalid depth" 276 #define _invalid_depth "invalid depth"
268 #define _identifier_expected "identifier expected, but found: %.*s" 277 #define _invalid_path "invalid path"
269 278
279 #define _identifier_expected "identifier expected (%.*s [->]%.*s %.*s)"
280 #define _idornum_expected "identifier or number expected (%.*s [->]%.*s %.*s)"
281 #define _idorstr_expected "identifier or string expected (%.*s [->]%.*s %.*s)"
282 #define _idorts_expected "identifier or timestamp expected (%.*s [->]%.*s %.*s)"
283
284 #define token_sstr(listelem) ((sstr_t*)(listelem)->data)
285
286 static void dav_error_in_context(int errorcode, const char *errormsg,
287 DavQLStatement *stmt, UcxList *token) {
288 sstr_t emptystring = ST("");
289 stmt->errorcode = errorcode;
290 stmt->errormessage = ucx_sprintf(errormsg,
291 sfmtarg(token->prev?*token_sstr(token->prev):emptystring),
292 sfmtarg(*token_sstr(token)),
293 sfmtarg(token->next?*token_sstr(token->next):emptystring)).ptr;
294 }
295
296 // special symbols are single tokens - the % sign MUST NOT be a special symbol
270 static const char *special_token_symbols = ",()+-*/&|^~=!<>"; 297 static const char *special_token_symbols = ",()+-*/&|^~=!<>";
271 298
272 static UcxList* dav_parse_tokenize(sstr_t src) { 299 static UcxList* dav_parse_tokenize(sstr_t src) {
273 UcxList *tokens = NULL; 300 UcxList *tokens = NULL;
274 301
334 } 361 }
335 362
336 return tokens; 363 return tokens;
337 } 364 }
338 365
339 #define token_sstr(listelem) ((sstr_t*)(listelem)->data)
340 static DavQLExpression* dav_parse_expression( 366 static DavQLExpression* dav_parse_expression(
341 DavQLStatement* stmt, UcxList* starttoken, size_t n) { 367 DavQLStatement* stmt, UcxList* starttoken, size_t n) {
342 if (n == 0) { 368 if (n == 0) {
343 return NULL; 369 return NULL;
344 } 370 }
351 // special case - only one token 377 // special case - only one token
352 if (n == 1) { 378 if (n == 1) {
353 expr->srctext.length = token_sstr(starttoken)->length; 379 expr->srctext.length = token_sstr(starttoken)->length;
354 char firstchar = expr->srctext.ptr[0]; 380 char firstchar = expr->srctext.ptr[0];
355 char lastchar = expr->srctext.ptr[expr->srctext.length-1]; 381 char lastchar = expr->srctext.ptr[expr->srctext.length-1];
356 if (firstchar == '\'' || isdigit(firstchar)) { 382 if (firstchar == '\'') {
357 expr->type = DAVQL_LITERAL; 383 expr->type = DAVQL_STRING;
384 } else if (isdigit(firstchar)) {
385 expr->type = DAVQL_NUMBER;
386 } else if (firstchar == '%') {
387 if (expr->srctext.length == 1) {
388 dav_error_in_context(DAVQL_ERROR_MISSING_FMTSPEC,
389 _missing_fmtspec, stmt, starttoken);
390 } else if (expr->srctext.length == 2) {
391 switch (expr->srctext.ptr[1]) {
392 case 'd': expr->type = DAVQL_NUMBER; break;
393 case 's': expr->type = DAVQL_STRING; break;
394 case 't': expr->type = DAVQL_TIMESTAMP; break;
395 default:
396 dav_error_in_context(DAVQL_ERROR_UNKNOWN_FMTSPEC,
397 _unknown_fmtspec, stmt, starttoken);
398 }
399 } else {
400 dav_error_in_context(DAVQL_ERROR_INVALID_FMTSPEC,
401 _invalid_fmtspec, stmt, starttoken);
402 }
358 } else { 403 } else {
359 expr->type = DAVQL_IDENTIFIER; 404 expr->type = DAVQL_IDENTIFIER;
360 } 405 }
361 // remove quotes (if any) 406 // remove quotes (if any)
362 if (firstchar == '\'' || firstchar == '`') { 407 if (firstchar == '\'' || firstchar == '`') {
412 if (expr->right) { 457 if (expr->right) {
413 dav_free_expression(expr->right); 458 dav_free_expression(expr->right);
414 } 459 }
415 free(expr); 460 free(expr);
416 } 461 }
417
418 static void dav_parse_unexpected_token(DavQLStatement *stmt, UcxList *token) {
419 sstr_t emptystring = ST("");
420 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN;
421 sstr_t errormsg = ucx_sprintf(_unexpected_token,
422 sfmtarg(token->prev?*token_sstr(token->prev):emptystring),
423 sfmtarg(*token_sstr(token)),
424 sfmtarg(token->next?*token_sstr(token->next):emptystring));
425 stmt->errormessage = errormsg.ptr;
426 }
427
428 462
429 #define _step_fieldlist_ 10 // field list 463 #define _step_fieldlist_ 10 // field list
430 #define _step_FROM_ 20 // FROM clause 464 #define _step_FROM_ 20 // FROM clause
431 #define _step_expect_WWO_ 530 // expecting WITH, WHERE or ORDER BY clause
432 #define _step_WITH_ 30 // WITH clause 465 #define _step_WITH_ 30 // WITH clause
433 #define _step_expect_WO 540 // expecting WHERE or ORDER BY clause
434 #define _step_WHERE_ 40 // WHERE clause 466 #define _step_WHERE_ 40 // WHERE clause
435 #define _step_expect_O 550 // expecting ORDER BY clause 467 #define _step_ORDER_BYopt_ 552 // expecting more ORDER BY details or end
436 #define _step_expect_BY 551 // expecting the BY token for the ORDER BY clause
437 #define _step_ORDER_BY_ 50 // ORDER BY clause 468 #define _step_ORDER_BY_ 50 // ORDER BY clause
438 #define _step_end_ 500 // expect end 469 #define _step_end_ 500 // expect end
470
471 static int dav_parse_from(DavQLStatement *stmt, UcxList *token) {
472 sstr_t tokendata = *token_sstr(token);
473
474 if (!sstrcasecmp(tokendata, S("with"))) {
475 return _step_WITH_;
476 } else if (!sstrcasecmp(tokendata, S("where"))) {
477 return _step_WHERE_;
478 } else if (!sstrcasecmp(tokendata, S("order"))) {
479 return _step_ORDER_BY_;
480 } else {
481 if (stmt->path.ptr) {
482 if (stmt->path.ptr[0] == '/') {
483 char *end = tokendata.ptr+tokendata.length;
484 stmt->path.length = end - stmt->path.ptr;
485 } else {
486 stmt->errorcode = DAVQL_ERROR_INVALID_PATH;
487 stmt->errormessage = strdup(_invalid_path);
488 }
489 } else {
490 if (tokendata.ptr[0] == '/' || !sstrcmp(tokendata, S("%s"))) {
491 stmt->path = tokendata;
492 } else {
493 stmt->errorcode = DAVQL_ERROR_INVALID_PATH;
494 stmt->errormessage = strdup(_invalid_path);
495 }
496 }
497 return _step_FROM_;
498 }
499 }
439 500
440 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) { 501 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) {
441 sstr_t tokendata = *token_sstr(token); 502 sstr_t tokendata = *token_sstr(token);
442 503
443 /* 504 /*
486 switch (key) { 547 switch (key) {
487 case 1: /* depth */ 548 case 1: /* depth */
488 if (!sstrcasecmp(tokendata, S("infinity"))) { 549 if (!sstrcasecmp(tokendata, S("infinity"))) {
489 stmt->depth = DAV_DEPTH_INFINITY; 550 stmt->depth = DAV_DEPTH_INFINITY;
490 } else { 551 } else {
491 char *conv = malloc(tokendata.length+1); 552 DavQLExpression *depthexpr =
492 char *chk; 553 dav_parse_expression(stmt, token, 1);
493 memcpy(conv, tokendata.ptr, tokendata.length); 554
494 conv[tokendata.length] = '\0'; 555 if (depthexpr->type == DAVQL_NUMBER) {
495 stmt->depth = strtol(conv, &chk, 10); 556 if (depthexpr->srctext.ptr[0] == '%') {
496 if (*chk || stmt->depth < -1) { 557 stmt->depth = DAV_DEPTH_PLACEHOLDER;
558 } else {
559 sstr_t depthstr = depthexpr->srctext;
560 char *conv = malloc(depthstr.length+1);
561 char *chk;
562 memcpy(conv, depthstr.ptr, depthstr.length);
563 conv[depthstr.length] = '\0';
564 stmt->depth = strtol(conv, &chk, 10);
565 if (*chk || stmt->depth < -1) {
566 stmt->errorcode = DAVQL_ERROR_INVALID_DEPTH;
567 stmt->errormessage = strdup(_invalid_depth);
568 }
569 free(conv);
570 }
571 } else {
497 stmt->errorcode = DAVQL_ERROR_INVALID_DEPTH; 572 stmt->errorcode = DAVQL_ERROR_INVALID_DEPTH;
498 stmt->errormessage = strdup(_invalid_depth); 573 stmt->errormessage = strdup(_invalid_depth);
499 } 574 }
500 free(conv); 575
576 dav_free_expression(depthexpr);
501 } 577 }
502 break; 578 break;
503 } 579 }
504 parsestate = 3; 580 parsestate = 3;
505 return _step_WITH_; // continue parsing WITH clause 581 return _step_WITH_; // continue parsing WITH clause
510 parsestate = 0; // reset clause parser 586 parsestate = 0; // reset clause parser
511 return _step_WITH_; 587 return _step_WITH_;
512 } else if (!sstrcasecmp(tokendata, S("where"))) { 588 } else if (!sstrcasecmp(tokendata, S("where"))) {
513 return _step_WHERE_; 589 return _step_WHERE_;
514 } else if (!sstrcasecmp(tokendata, S("order"))) { 590 } else if (!sstrcasecmp(tokendata, S("order"))) {
515 return _step_expect_BY; 591 return _step_ORDER_BY_;
516 } else { 592 } else {
517 dav_parse_unexpected_token(stmt, token); 593 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN,
594 _unexpected_token, stmt, token);
518 return 0; 595 return 0;
519 } 596 }
520 default: 597 default:
521 stmt->errorcode = DAVQL_ERROR_INVALID; 598 stmt->errorcode = DAVQL_ERROR_INVALID;
522 stmt->errormessage = strdup(_parser_state); 599 stmt->errormessage = strdup(_parser_state);
523 return 0; 600 return 0;
524 } 601 }
525 } 602 }
526 603
527 static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) { 604 static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) {
528 // TODO: implement 605
606 sstr_t tokendata = *token_sstr(token);
607 /*
608 * 0: expect by keyword
609 * 1: expect identifier / number
610 * 2: expect asc / desc or comma
611 * 3: expect comma
612 */
613 static int state = 0;
614 static DavQLOrderCriterion *crit = NULL;
615
616 switch (state) {
617 case 0:
618 if (!sstrcasecmp(tokendata, S("by"))) {
619 state++;
620 } else {
621 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN;
622 stmt->errormessage = ucx_sprintf(_expected_by,
623 sfmtarg(tokendata)).ptr;
624 }
625 return _step_ORDER_BY_;
626 case 1:
627 crit = malloc(sizeof(DavQLOrderCriterion));
628 crit->column = dav_parse_expression(stmt, token, 1);
629 crit->descending = 0;
630
631 if (!crit->column || (
632 crit->column->type != DAVQL_NUMBER &&
633 crit->column->type != DAVQL_IDENTIFIER)) {
634 free(crit);
635 dav_error_in_context(DAVQL_ERROR_IDORNUM_EXPECTED,
636 _idornum_expected, stmt, token);
637 } else {
638 stmt->orderby = ucx_list_append(stmt->orderby, crit);
639 }
640
641 // continue parsing clause, if more tokens available
642 state++;
643 return _step_ORDER_BYopt_;
644 case 2:
645 if (!sstrcasecmp(tokendata, S("desc"))) {
646 crit->descending = 1;
647 } else if (!sstrcasecmp(tokendata, S("asc"))) {
648 crit->descending = 0;
649 } else if (!sstrcmp(tokendata, S(","))) {
650 state = 1; // reset clause parser
651 return _step_ORDER_BY_; // statement must not end now
652 } else {
653 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN,
654 _unexpected_token, stmt, token);
655 return 0;
656 }
657 // continue parsing clause, if more tokens available
658 state++;
659 return _step_ORDER_BYopt_;
660 case 3:
661 if (!sstrcmp(tokendata, S(","))) {
662 state = 1; // reset clause parser
663 return _step_ORDER_BY_; // statement must not end now
664 } else {
665 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN,
666 _unexpected_token, stmt, token);
667 return 0;
668 }
669 }
529 670
530 return _step_end_; 671 return _step_end_;
531 } 672 }
532 673
533 static void dav_free_order_criterion(DavQLOrderCriterion *crit) { 674 static void dav_free_order_criterion(DavQLOrderCriterion *crit) {
541 stmt->type = DAVQL_GET; 682 stmt->type = DAVQL_GET;
542 683
543 int step = _step_fieldlist_; 684 int step = _step_fieldlist_;
544 685
545 // Variables for token sublists for expressions 686 // Variables for token sublists for expressions
687 // TODO: this is deprecated and won't work with function calls
546 UcxList *exprstart = NULL; 688 UcxList *exprstart = NULL;
547 size_t exprlen = 0; 689 size_t exprlen = 0;
548 690
549 // Process tokens 691 // Process tokens
550 UCX_FOREACH(token, tokens) { 692 UCX_FOREACH(token, tokens) {
551 sstr_t tokendata = *token_sstr(token); 693 sstr_t tokendata = *token_sstr(token);
552 694
553 switch (step) { 695 switch (step) {
554 // too much input data 696 // too much input data
555 case _step_end_: 697 case _step_end_:
556 dav_parse_unexpected_token(stmt, token); 698 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN,
557 break; 699 _unexpected_token, stmt, token);
558 // optional clauses
559 case _step_expect_WWO_:
560 if (!sstrcasecmp(tokendata, S("with"))) {
561 step = _step_WITH_;
562 continue;
563 }
564 /* no break and no else*/
565 case _step_expect_WO:
566 if (!sstrcasecmp(tokendata, S("where"))) {
567 step = _step_WHERE_;
568 continue;
569 }
570 /* no break and no else*/
571 case _step_expect_O:
572 if (!sstrcasecmp(tokendata, S("order"))) {
573 step = _step_expect_BY;
574 continue;
575 } else { // last possible clause checked and not present
576 dav_parse_unexpected_token(stmt, token);
577 }
578 break;
579 case _step_expect_BY:
580 if (!sstrcasecmp(tokendata, S("by"))) {
581 step = _step_ORDER_BY_;
582 } else {
583 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN;
584 stmt->errormessage = ucx_sprintf(_expected_by,
585 sfmtarg(tokendata)).ptr;
586 }
587 break; 700 break;
588 // field list 701 // field list
589 case _step_fieldlist_: { 702 case _step_fieldlist_: {
590 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); 703 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from"));
591 if (fromkeyword || !sstrcmp(tokendata, S(","))) { 704 if (fromkeyword || !sstrcmp(tokendata, S(","))) {
597 710
598 if (fromkeyword) { 711 if (fromkeyword) {
599 step = _step_FROM_; 712 step = _step_FROM_;
600 } 713 }
601 } else { 714 } else {
602 dav_parse_unexpected_token(stmt, token); 715 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN,
716 _unexpected_token, stmt, token);
603 } 717 }
604 } else { 718 } else {
605 // collect tokens for field expression 719 // collect tokens for field expression
606 if (exprstart) { 720 if (exprstart) {
607 exprlen++; 721 exprlen++;
612 } 726 }
613 break; 727 break;
614 } 728 }
615 // from clause 729 // from clause
616 case _step_FROM_: { 730 case _step_FROM_: {
617 DavQLExpression *expr = dav_parse_expression(stmt, token, 1); 731 step = dav_parse_from(stmt, token);
618 stmt->path = expr->srctext;
619 int exprtype = expr->type;
620 dav_free_expression(expr);
621 if (exprtype != DAVQL_IDENTIFIER) {
622 stmt->errorcode = DAVQL_ERROR_IDENTIFIER_EXPECTED;
623 stmt->errormessage = ucx_sprintf(_identifier_expected,
624 sfmtarg(tokendata)).ptr;
625 }
626 step = _step_expect_WWO_;
627 break; 732 break;
628 } 733 }
629 // with clause 734 // with clause
630 case _step_WITH_: { 735 case _step_WITH_: {
631 step = dav_parse_with_clause(stmt, token); 736 step = dav_parse_with_clause(stmt, token);
636 // TODO: implement 741 // TODO: implement
637 step = _step_end_; 742 step = _step_end_;
638 break; 743 break;
639 // order by clause 744 // order by clause
640 case _step_ORDER_BY_: 745 case _step_ORDER_BY_:
746 case _step_ORDER_BYopt_:
641 step = dav_parse_orderby_clause(stmt, token); 747 step = dav_parse_orderby_clause(stmt, token);
642 break; 748 break;
643 default: 749 default:
644 stmt->errorcode = DAVQL_ERROR_INVALID; 750 stmt->errorcode = DAVQL_ERROR_INVALID;
645 stmt->errormessage = strdup(_parser_state); 751 stmt->errormessage = strdup(_parser_state);

mercurial