125 } |
125 } |
126 if (stmt->errorcode) { |
126 if (stmt->errorcode) { |
127 printf("\nError code: %d\nError: %s\n", |
127 printf("\nError code: %d\nError: %s\n", |
128 stmt->errorcode, stmt->errormessage); |
128 stmt->errorcode, stmt->errormessage); |
129 } |
129 } |
|
130 |
|
131 // order by clause |
|
132 printf("Order by: "); |
|
133 if (stmt->orderby) { |
|
134 UCX_FOREACH(crit, stmt->orderby) { |
|
135 DavQLOrderCriterion *critdata = crit->data; |
|
136 printf("%.*s %s%s", sfmtarg(critdata->column->srctext), |
|
137 critdata->ascending ? "asc" : "desc", |
|
138 crit->next ? ", " : "\n"); |
|
139 } |
|
140 } else { |
|
141 printf("nothing\n"); |
|
142 } |
130 } |
143 } |
131 |
144 |
132 static int dav_debug_ql_expr_selected(DavQLExpression *expr) { |
145 static int dav_debug_ql_expr_selected(DavQLExpression *expr) { |
133 if (!expr) { |
146 if (!expr) { |
134 printf("Currently no expression selected.\n"); |
147 printf("Currently no expression selected.\n"); |
410 sfmtarg(*token_sstr(token)), |
423 sfmtarg(*token_sstr(token)), |
411 sfmtarg(token->next?*token_sstr(token->next):emptystring)); |
424 sfmtarg(token->next?*token_sstr(token->next):emptystring)); |
412 stmt->errormessage = errormsg.ptr; |
425 stmt->errormessage = errormsg.ptr; |
413 } |
426 } |
414 |
427 |
|
428 |
|
429 #define _step_fieldlist_ 10 // field list |
|
430 #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 |
|
433 #define _step_expect_WO 540 // expecting WHERE or ORDER BY clause |
|
434 #define _step_WHERE_ 40 // WHERE clause |
|
435 #define _step_expect_O 550 // expecting ORDER BY clause |
|
436 #define _step_expect_BY 551 // expecting the BY token for the ORDER BY clause |
|
437 #define _step_ORDER_BY_ 50 // ORDER BY clause |
|
438 #define _step_end_ 500 // expect end |
|
439 |
415 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) { |
440 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) { |
416 sstr_t tokendata = *token_sstr(token); |
441 sstr_t tokendata = *token_sstr(token); |
|
442 |
417 /* |
443 /* |
418 * 0: key |
444 * 0: key |
419 * 1: = |
445 * 1: = |
420 * 2: value |
446 * 2: value |
421 * TODO: commas |
447 * 3: comma or new clause |
422 */ |
448 */ |
423 static int parsestate = 0; |
449 static int parsestate = 0; |
424 |
450 |
425 /* |
451 /* |
426 * 1: depth |
452 * 1: depth |
444 stmt->errormessage = ucx_sprintf(_duplicated_attribute, |
470 stmt->errormessage = ucx_sprintf(_duplicated_attribute, |
445 sfmtarg(tokendata)).ptr; |
471 sfmtarg(tokendata)).ptr; |
446 } else { |
472 } else { |
447 keymask |= key; |
473 keymask |= key; |
448 } |
474 } |
449 return 0; |
475 return _step_WITH_; // continue parsing WITH clause |
450 case 1: |
476 case 1: |
451 if (sstrcmp(tokendata, S("="))) { |
477 if (sstrcmp(tokendata, S("="))) { |
452 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
478 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
453 stmt->errormessage = ucx_sprintf(_expected_token, |
479 stmt->errormessage = ucx_sprintf(_expected_token, |
454 "=", sfmtarg(tokendata)).ptr; |
480 "=", sfmtarg(tokendata)).ptr; |
455 } else { |
481 } else { |
456 parsestate = 2; |
482 parsestate = 2; |
457 } |
483 } |
458 return 0; |
484 return _step_WITH_; // continue parsing WITH clause |
459 case 2: |
485 case 2: |
460 switch (key) { |
486 switch (key) { |
461 case 1: /* depth */ |
487 case 1: /* depth */ |
462 if (!sstrcasecmp(tokendata, S("infinity"))) { |
488 if (!sstrcasecmp(tokendata, S("infinity"))) { |
463 stmt->depth = DAV_DEPTH_INFINITY; |
489 stmt->depth = DAV_DEPTH_INFINITY; |
473 } |
499 } |
474 free(conv); |
500 free(conv); |
475 } |
501 } |
476 break; |
502 break; |
477 } |
503 } |
478 parsestate = 0; |
504 parsestate = 3; |
479 return 1; |
505 return _step_WITH_; // continue parsing WITH clause |
|
506 case 3: |
|
507 // a with clause may be continued with a comma |
|
508 // or another clause may follow |
|
509 if (!sstrcmp(tokendata, S(","))) { |
|
510 parsestate = 0; // reset clause parser |
|
511 return _step_WITH_; |
|
512 } else if (!sstrcasecmp(tokendata, S("where"))) { |
|
513 return _step_WHERE_; |
|
514 } else if (!sstrcasecmp(tokendata, S("order"))) { |
|
515 return _step_expect_BY; |
|
516 } else { |
|
517 dav_parse_unexpected_token(stmt, token); |
|
518 return 0; |
|
519 } |
480 default: |
520 default: |
481 return -1; |
521 stmt->errorcode = DAVQL_ERROR_INVALID; |
482 } |
522 stmt->errormessage = strdup(_parser_state); |
|
523 return 0; |
|
524 } |
|
525 } |
|
526 |
|
527 static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) { |
|
528 // TODO: implement |
|
529 |
|
530 return _step_end_; |
|
531 } |
|
532 |
|
533 static void dav_free_order_criterion(DavQLOrderCriterion *crit) { |
|
534 if (crit->column) { // do it null-safe though column is expected to be set |
|
535 dav_free_expression(crit->column); |
|
536 } |
|
537 free(crit); |
483 } |
538 } |
484 |
539 |
485 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
540 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
486 stmt->type = DAVQL_GET; |
541 stmt->type = DAVQL_GET; |
487 |
|
488 #define _step_fieldlist_ 10 // field list |
|
489 #define _step_FROM_ 20 // FROM clause |
|
490 #define _step_expect_WWO_ 530 // expecting WITH, WHERE or ORDER BY clause |
|
491 #define _step_comma_WITH_ 531 // expecting comma for WITH clause |
|
492 #define _step_WITH_ 30 // WITH clause |
|
493 #define _step_expect_WO 540 // expecting WHERE or ORDER BY clause |
|
494 #define _step_WHERE_ 40 // WHERE clause |
|
495 #define _step_expect_O 550 // expecting ORDER BY clause |
|
496 #define _step_expect_BY 551 // expecting the BY token for the ORDER BY clause |
|
497 #define _step_ORDER_BY_ 50 // ORDER BY clause |
|
498 #define _step_end_ 500 // expect end |
|
499 |
542 |
500 int step = _step_fieldlist_; |
543 int step = _step_fieldlist_; |
501 |
544 |
502 // Variables for token sublists for expressions |
545 // Variables for token sublists for expressions |
503 UcxList *exprstart = NULL; |
546 UcxList *exprstart = NULL; |
538 step = _step_ORDER_BY_; |
581 step = _step_ORDER_BY_; |
539 } else { |
582 } else { |
540 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
583 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
541 stmt->errormessage = ucx_sprintf(_expected_by, |
584 stmt->errormessage = ucx_sprintf(_expected_by, |
542 sfmtarg(tokendata)).ptr; |
585 sfmtarg(tokendata)).ptr; |
543 } |
|
544 break; |
|
545 case _step_comma_WITH_: |
|
546 // a with clause may be continued with a comma |
|
547 // or another clause may follow |
|
548 if (!sstrcmp(tokendata, S(","))) { |
|
549 step = _step_WITH_; |
|
550 } if (!sstrcasecmp(tokendata, S("where"))) { |
|
551 step = _step_WHERE_; |
|
552 } else if (!sstrcasecmp(tokendata, S("order"))) { |
|
553 step = _step_expect_BY; |
|
554 } else { |
|
555 dav_parse_unexpected_token(stmt, token); |
|
556 } |
586 } |
557 break; |
587 break; |
558 // field list |
588 // field list |
559 case _step_fieldlist_: { |
589 case _step_fieldlist_: { |
560 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); |
590 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); |
596 step = _step_expect_WWO_; |
626 step = _step_expect_WWO_; |
597 break; |
627 break; |
598 } |
628 } |
599 // with clause |
629 // with clause |
600 case _step_WITH_: { |
630 case _step_WITH_: { |
601 int withclause_result = dav_parse_with_clause(stmt, token); |
631 step = dav_parse_with_clause(stmt, token); |
602 if (withclause_result < 0) { |
|
603 stmt->errorcode = DAVQL_ERROR_INVALID; |
|
604 stmt->errormessage = strdup(_parser_state); |
|
605 } else if (withclause_result > 0) { |
|
606 step = _step_comma_WITH_; |
|
607 } |
|
608 break; |
632 break; |
609 } |
633 } |
610 // where clause |
634 // where clause |
611 case _step_WHERE_: |
635 case _step_WHERE_: |
612 // TODO: implement |
636 // TODO: implement |
613 step = _step_end_; |
637 step = _step_end_; |
614 break; |
638 break; |
615 // order by clause |
639 // order by clause |
616 case _step_ORDER_BY_: |
640 case _step_ORDER_BY_: |
617 // TODO: implement |
641 step = dav_parse_orderby_clause(stmt, token); |
618 step = _step_end_; |
|
619 break; |
642 break; |
620 default: |
643 default: |
621 stmt->errorcode = DAVQL_ERROR_INVALID; |
644 stmt->errorcode = DAVQL_ERROR_INVALID; |
622 stmt->errormessage = strdup(_parser_state); |
645 stmt->errormessage = strdup(_parser_state); |
623 } |
646 } |