496 } |
496 } |
497 return _step_FROM_; |
497 return _step_FROM_; |
498 } |
498 } |
499 } |
499 } |
500 |
500 |
501 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) { |
501 struct with_parser_state { |
502 sstr_t tokendata = *token_sstr(token); |
|
503 |
|
504 /* |
502 /* |
505 * 0: key |
503 * 0: key |
506 * 1: = |
504 * 1: = |
507 * 2: value |
505 * 2: value |
508 * 3: comma or new clause |
506 * 3: comma or new clause |
509 */ |
507 */ |
510 static int parsestate = 0; |
508 int step; |
511 |
|
512 /* |
509 /* |
513 * 1: depth |
510 * 1: depth |
514 */ |
511 */ |
515 static int key = 0; |
512 int key; |
516 static int keymask = 0; |
513 int keymask; |
517 |
514 }; |
518 switch (parsestate) { |
515 |
|
516 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token, |
|
517 struct with_parser_state *state) { |
|
518 sstr_t tokendata = *token_sstr(token); |
|
519 |
|
520 switch (state->step) { |
519 case 0: |
521 case 0: |
520 if (!sstrcasecmp(tokendata, S("depth"))) { |
522 if (!sstrcasecmp(tokendata, S("depth"))) { |
521 key = 1; |
523 state->key = 1; |
522 parsestate = 1; |
524 state->step = 1; |
523 } else { |
525 } else { |
524 stmt->errorcode = DAVQL_ERROR_UNKNOWN_ATTRIBUTE; |
526 stmt->errorcode = DAVQL_ERROR_UNKNOWN_ATTRIBUTE; |
525 stmt->errormessage = ucx_sprintf(_unknown_attribute, |
527 stmt->errormessage = ucx_sprintf(_unknown_attribute, |
526 sfmtarg(tokendata)).ptr; |
528 sfmtarg(tokendata)).ptr; |
527 break; |
529 break; |
528 } |
530 } |
529 if (keymask & key) { |
531 if (state->keymask & state->key) { |
530 stmt->errorcode = DAVQL_ERROR_DUPLICATED_ATTRIBUTE; |
532 stmt->errorcode = DAVQL_ERROR_DUPLICATED_ATTRIBUTE; |
531 stmt->errormessage = ucx_sprintf(_duplicated_attribute, |
533 stmt->errormessage = ucx_sprintf(_duplicated_attribute, |
532 sfmtarg(tokendata)).ptr; |
534 sfmtarg(tokendata)).ptr; |
533 } else { |
535 } else { |
534 keymask |= key; |
536 state->keymask |= state->key; |
535 } |
537 } |
536 return _step_WITH_; // continue parsing WITH clause |
538 return _step_WITH_; // continue parsing WITH clause |
537 case 1: |
539 case 1: |
538 if (sstrcmp(tokendata, S("="))) { |
540 if (sstrcmp(tokendata, S("="))) { |
539 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
541 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
540 stmt->errormessage = ucx_sprintf(_expected_token, |
542 stmt->errormessage = ucx_sprintf(_expected_token, |
541 "=", sfmtarg(tokendata)).ptr; |
543 "=", sfmtarg(tokendata)).ptr; |
542 } else { |
544 } else { |
543 parsestate = 2; |
545 state->step = 2; |
544 } |
546 } |
545 return _step_WITH_; // continue parsing WITH clause |
547 return _step_WITH_; // continue parsing WITH clause |
546 case 2: |
548 case 2: |
547 switch (key) { |
549 switch (state->key) { |
548 case 1: /* depth */ |
550 case 1: /* depth */ |
549 if (!sstrcasecmp(tokendata, S("infinity"))) { |
551 if (!sstrcasecmp(tokendata, S("infinity"))) { |
550 stmt->depth = DAV_DEPTH_INFINITY; |
552 stmt->depth = DAV_DEPTH_INFINITY; |
551 } else { |
553 } else { |
552 DavQLExpression *depthexpr = |
554 DavQLExpression *depthexpr = |
575 |
577 |
576 dav_free_expression(depthexpr); |
578 dav_free_expression(depthexpr); |
577 } |
579 } |
578 break; |
580 break; |
579 } |
581 } |
580 parsestate = 3; |
582 state->step = 3; |
581 return _step_WITH_; // continue parsing WITH clause |
583 return _step_WITH_; // continue parsing WITH clause |
582 case 3: |
584 case 3: |
583 // a with clause may be continued with a comma |
585 // a with clause may be continued with a comma |
584 // or another clause may follow |
586 // or another clause may follow |
585 if (!sstrcmp(tokendata, S(","))) { |
587 if (!sstrcmp(tokendata, S(","))) { |
586 parsestate = 0; // reset clause parser |
588 state->step = 0; // reset clause parser |
587 return _step_WITH_; |
589 return _step_WITH_; |
588 } else if (!sstrcasecmp(tokendata, S("where"))) { |
590 } else if (!sstrcasecmp(tokendata, S("where"))) { |
589 return _step_WHERE_; |
591 return _step_WHERE_; |
590 } else if (!sstrcasecmp(tokendata, S("order"))) { |
592 } else if (!sstrcasecmp(tokendata, S("order"))) { |
591 return _step_ORDER_BY_; |
593 return _step_ORDER_BY_; |
599 stmt->errormessage = strdup(_parser_state); |
601 stmt->errormessage = strdup(_parser_state); |
600 return 0; |
602 return 0; |
601 } |
603 } |
602 } |
604 } |
603 |
605 |
604 static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) { |
606 struct orderby_parser_state { |
605 |
|
606 sstr_t tokendata = *token_sstr(token); |
|
607 /* |
607 /* |
608 * 0: expect by keyword |
608 * 0: expect by keyword |
609 * 1: expect identifier / number |
609 * 1: expect identifier / number |
610 * 2: expect asc / desc or comma |
610 * 2: expect asc / desc or comma |
611 * 3: expect comma |
611 * 3: expect comma |
612 */ |
612 */ |
613 static int state = 0; |
613 int step; |
614 static DavQLOrderCriterion *crit = NULL; |
614 DavQLOrderCriterion *crit; |
615 |
615 }; |
616 switch (state) { |
616 |
|
617 static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token, |
|
618 struct orderby_parser_state *state) { |
|
619 |
|
620 sstr_t tokendata = *token_sstr(token); |
|
621 |
|
622 switch (state->step) { |
617 case 0: |
623 case 0: |
618 if (!sstrcasecmp(tokendata, S("by"))) { |
624 if (!sstrcasecmp(tokendata, S("by"))) { |
619 state++; |
625 state->step++; |
620 } else { |
626 } else { |
621 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
627 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
622 stmt->errormessage = ucx_sprintf(_expected_by, |
628 stmt->errormessage = ucx_sprintf(_expected_by, |
623 sfmtarg(tokendata)).ptr; |
629 sfmtarg(tokendata)).ptr; |
624 } |
630 } |
625 return _step_ORDER_BY_; |
631 return _step_ORDER_BY_; |
626 case 1: |
632 case 1: |
627 crit = malloc(sizeof(DavQLOrderCriterion)); |
633 state->crit = malloc(sizeof(DavQLOrderCriterion)); |
628 crit->column = dav_parse_expression(stmt, token, 1); |
634 state->crit->column = dav_parse_expression(stmt, token, 1); |
629 crit->descending = 0; |
635 state->crit->descending = 0; |
630 |
636 |
631 if (!crit->column || ( |
637 if (!state->crit->column || ( |
632 crit->column->type != DAVQL_NUMBER && |
638 state->crit->column->type != DAVQL_NUMBER && |
633 crit->column->type != DAVQL_IDENTIFIER)) { |
639 state->crit->column->type != DAVQL_IDENTIFIER)) { |
634 free(crit); |
640 free(state->crit); |
635 dav_error_in_context(DAVQL_ERROR_IDORNUM_EXPECTED, |
641 dav_error_in_context(DAVQL_ERROR_IDORNUM_EXPECTED, |
636 _idornum_expected, stmt, token); |
642 _idornum_expected, stmt, token); |
637 } else { |
643 } else { |
638 stmt->orderby = ucx_list_append(stmt->orderby, crit); |
644 stmt->orderby = ucx_list_append(stmt->orderby, state->crit); |
639 } |
645 } |
640 |
646 |
641 // continue parsing clause, if more tokens available |
647 // continue parsing clause, if more tokens available |
642 state++; |
648 state->step++; |
643 return _step_ORDER_BYopt_; |
649 return _step_ORDER_BYopt_; |
644 case 2: |
650 case 2: |
645 if (!sstrcasecmp(tokendata, S("desc"))) { |
651 if (!sstrcasecmp(tokendata, S("desc"))) { |
646 crit->descending = 1; |
652 state->crit->descending = 1; |
647 } else if (!sstrcasecmp(tokendata, S("asc"))) { |
653 } else if (!sstrcasecmp(tokendata, S("asc"))) { |
648 crit->descending = 0; |
654 state->crit->descending = 0; |
649 } else if (!sstrcmp(tokendata, S(","))) { |
655 } else if (!sstrcmp(tokendata, S(","))) { |
650 state = 1; // reset clause parser |
656 state->step = 1; // reset clause parser |
651 return _step_ORDER_BY_; // statement must not end now |
657 return _step_ORDER_BY_; // statement must not end now |
652 } else { |
658 } else { |
653 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
659 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
654 _unexpected_token, stmt, token); |
660 _unexpected_token, stmt, token); |
655 return 0; |
661 return 0; |
657 // continue parsing clause, if more tokens available |
663 // continue parsing clause, if more tokens available |
658 state++; |
664 state++; |
659 return _step_ORDER_BYopt_; |
665 return _step_ORDER_BYopt_; |
660 case 3: |
666 case 3: |
661 if (!sstrcmp(tokendata, S(","))) { |
667 if (!sstrcmp(tokendata, S(","))) { |
662 state = 1; // reset clause parser |
668 state->step = 1; // reset clause parser |
663 return _step_ORDER_BY_; // statement must not end now |
669 return _step_ORDER_BY_; // statement must not end now |
664 } else { |
670 } else { |
665 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
671 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
666 _unexpected_token, stmt, token); |
672 _unexpected_token, stmt, token); |
667 return 0; |
673 return 0; |
680 |
686 |
681 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
687 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
682 stmt->type = DAVQL_GET; |
688 stmt->type = DAVQL_GET; |
683 |
689 |
684 int step = _step_fieldlist_; |
690 int step = _step_fieldlist_; |
|
691 |
|
692 struct with_parser_state state_with; |
|
693 memset(&state_with, 0, sizeof(struct with_parser_state)); |
|
694 struct orderby_parser_state state_orderby; |
|
695 memset(&state_orderby, 0, sizeof(struct orderby_parser_state)); |
685 |
696 |
686 // Variables for token sublists for expressions |
697 // Variables for token sublists for expressions |
687 // TODO: this is deprecated and won't work with function calls |
698 // TODO: this is deprecated and won't work with function calls |
688 UcxList *exprstart = NULL; |
699 UcxList *exprstart = NULL; |
689 size_t exprlen = 0; |
700 size_t exprlen = 0; |
731 step = dav_parse_from(stmt, token); |
742 step = dav_parse_from(stmt, token); |
732 break; |
743 break; |
733 } |
744 } |
734 // with clause |
745 // with clause |
735 case _step_WITH_: { |
746 case _step_WITH_: { |
736 step = dav_parse_with_clause(stmt, token); |
747 step = dav_parse_with_clause(stmt, token, &state_with); |
737 break; |
748 break; |
738 } |
749 } |
739 // where clause |
750 // where clause |
740 case _step_WHERE_: |
751 case _step_WHERE_: |
741 // TODO: implement |
752 // TODO: implement |
742 step = _step_end_; |
753 step = _step_end_; |
743 break; |
754 break; |
744 // order by clause |
755 // order by clause |
745 case _step_ORDER_BY_: |
756 case _step_ORDER_BY_: |
746 case _step_ORDER_BYopt_: |
757 case _step_ORDER_BYopt_: |
747 step = dav_parse_orderby_clause(stmt, token); |
758 step = dav_parse_orderby_clause(stmt, token, &state_orderby); |
748 break; |
759 break; |
749 default: |
760 default: |
750 stmt->errorcode = DAVQL_ERROR_INVALID; |
761 stmt->errorcode = DAVQL_ERROR_INVALID; |
751 stmt->errormessage = strdup(_parser_state); |
762 stmt->errormessage = strdup(_parser_state); |
752 } |
763 } |