542 #define _step_ORDER_BY_ 50 // ORDER BY clause |
541 #define _step_ORDER_BY_ 50 // ORDER BY clause |
543 #define _step_end_ 500 // expect end |
542 #define _step_end_ 500 // expect end |
544 |
543 |
545 struct fieldlist_parser_state { |
544 struct fieldlist_parser_state { |
546 UcxList *expr_firsttoken; |
545 UcxList *expr_firsttoken; |
|
546 DavQLField *currentfield; |
547 size_t expr_len; |
547 size_t expr_len; |
548 /* |
548 /* |
549 * 0: begin of field list - may encounter "*" or "-" special fields |
549 * 0: begin of field list - may encounter "*" or "-" special fields |
550 * 1: collect expression token |
550 * 1: collect expression token |
551 * switch to step 2 on keyword "as" |
551 * switch to step 2 on keyword "as" |
552 * expect "," only if expr_len is 1 (add expr to list and continue) |
552 * expect "," or "from" only if expr_len is 1 (add to list and continue) |
553 * 2: expect one token (identifier) and a "," - continue with step 1 |
553 * 2: expect one token (identifier) for as clause |
|
554 * 3: expect a ",": continue with step 1 |
|
555 * or a "from": leave field list parser |
|
556 * 4: expect end of field list (i.e. a "from" keyword) |
554 */ |
557 */ |
555 int step; |
558 int step; |
556 }; |
559 }; |
557 |
560 |
|
561 static void dav_free_field(DavQLField *field) { |
|
562 dav_free_expression(field->expr); |
|
563 free(field); |
|
564 } |
|
565 |
558 static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token, |
566 static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token, |
559 struct fieldlist_parser_state *state) { |
567 struct fieldlist_parser_state *state) { |
560 sstr_t tokendata = *token_sstr(token); |
568 sstr_t tokendata = *token_sstr(token); |
|
569 |
|
570 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); |
|
571 _Bool comma = !sstrcmp(tokendata, S(",")); |
561 |
572 |
562 switch (state->step) { |
573 switch (state->step) { |
563 case 0: |
574 case 0: |
|
575 if (!sstrcmp(tokendata, S("*")) || !sstrcmp(tokendata, S("-"))) { |
|
576 DavQLField *field = malloc(sizeof(DavQLField)); |
|
577 field->name = tokendata; |
|
578 field->expr = calloc(1, sizeof(DavQLExpression)); |
|
579 field->expr->type = DAVQL_IDENTIFIER; |
|
580 field->expr->srctext = tokendata; |
|
581 stmt->fields = ucx_list_append(stmt->fields, field); |
|
582 |
|
583 if (tokendata.ptr[0] == '-') { |
|
584 // no further fields may follow, if dash symbol has been found |
|
585 state->step = 4; |
|
586 } else { |
|
587 state->step = 3; |
|
588 } |
|
589 return _step_fieldlist_; |
|
590 } |
564 // did not encounter special field, fall through to step 1 |
591 // did not encounter special field, fall through to step 1 |
|
592 state->step = 1; |
565 case 1: |
593 case 1: |
566 break; |
594 if (fromkeyword || comma) { |
567 } |
595 // add possible identifier to list |
568 |
596 if (state->expr_firsttoken) { |
569 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); |
597 // TODO: skip comma in function call) |
570 if (fromkeyword || !sstrcmp(tokendata, S(","))) { |
598 if (state->expr_len > 1) { |
571 if (state->expr_firsttoken) { |
599 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
572 DavQLField *field = malloc(sizeof(DavQLField)); |
600 stmt->errormessage = ucx_sprintf(_expected_token, |
573 field->expr = dav_parse_expression( |
601 "AS", sfmtarg(tokendata)).ptr; |
|
602 return 0; |
|
603 } |
|
604 |
|
605 DavQLExpression *expr = dav_parse_expression( |
|
606 stmt, state->expr_firsttoken, state->expr_len); |
|
607 |
|
608 if (expr->type != DAVQL_IDENTIFIER) { |
|
609 dav_free_expression(expr); |
|
610 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
|
611 stmt->errormessage = ucx_sprintf(_expected_token, |
|
612 "AS", sfmtarg(tokendata)).ptr; |
|
613 return 0; |
|
614 } // TODO: do not allow identifier when wildcard is present |
|
615 |
|
616 DavQLField *field = malloc(sizeof(DavQLField)); |
|
617 field->expr = expr; |
|
618 field->name = field->expr->srctext; |
|
619 stmt->fields = ucx_list_append(stmt->fields, field); |
|
620 |
|
621 state->expr_firsttoken = NULL; |
|
622 state->expr_len = 0; |
|
623 |
|
624 if (fromkeyword) { |
|
625 return _step_FROM_; |
|
626 } |
|
627 } else { |
|
628 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
|
629 _unexpected_token, stmt, token); |
|
630 return 0; |
|
631 } |
|
632 } else if (!sstrcasecmp(tokendata, S("as"))) { |
|
633 // TODO: return error, if expr_first_token is NULL |
|
634 state->currentfield = malloc(sizeof(DavQLField)); |
|
635 state->currentfield->expr = dav_parse_expression( |
574 stmt, state->expr_firsttoken, state->expr_len); |
636 stmt, state->expr_firsttoken, state->expr_len); |
575 field->name = field->expr->srctext; |
637 |
576 stmt->fields = ucx_list_append(stmt->fields, field); |
|
577 state->expr_firsttoken = NULL; |
638 state->expr_firsttoken = NULL; |
578 state->expr_len = 0; |
639 state->expr_len = 0; |
579 |
640 |
580 if (fromkeyword) { |
641 state->step = 2; |
581 return _step_FROM_; |
642 } else { |
582 } |
643 // collect tokens for field expression |
|
644 if (state->expr_firsttoken) { |
|
645 state->expr_len++; |
|
646 } else { |
|
647 state->expr_firsttoken = token; |
|
648 state->expr_len = 1; |
|
649 } |
|
650 } |
|
651 |
|
652 return _step_fieldlist_; |
|
653 case 2: { |
|
654 DavQLExpression *expr = dav_parse_expression(stmt, token, 1); |
|
655 if (expr->type == DAVQL_IDENTIFIER) { |
|
656 state->currentfield->name = expr->srctext; |
|
657 stmt->fields = ucx_list_append(stmt->fields, state->currentfield); |
|
658 state->currentfield = NULL; |
|
659 } else { |
|
660 dav_free_field(state->currentfield); |
|
661 dav_error_in_context(DAVQL_ERROR_IDENTIFIER_EXPECTED, |
|
662 _identifier_expected, stmt, token); |
|
663 |
|
664 } |
|
665 dav_free_expression(expr); |
|
666 state->step = 3; |
|
667 |
|
668 return _step_fieldlist_; |
|
669 } |
|
670 case 3: |
|
671 if (fromkeyword) { |
|
672 return _step_FROM_; |
|
673 } else if (comma) { |
|
674 state->step = 1; |
|
675 return _step_fieldlist_; |
583 } else { |
676 } else { |
584 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
677 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
585 _unexpected_token, stmt, token); |
678 _unexpected_token, stmt, token); |
586 } |
679 return 0; |
587 } else { |
680 } |
588 // collect tokens for field expression |
681 case 4: |
589 if (state->expr_firsttoken) { |
682 if (fromkeyword) { |
590 state->expr_len++; |
683 return _step_FROM_; |
591 } else { |
684 } else { |
592 state->expr_firsttoken = token; |
685 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN; |
593 state->expr_len = 1; |
686 stmt->errormessage = ucx_sprintf(_expected_token, |
594 } |
687 "FROM", sfmtarg(tokendata)).ptr; |
595 } |
688 return 0; |
596 |
689 } |
597 return _step_fieldlist_; |
690 } |
598 } |
|
599 |
|
600 static void dav_free_field(DavQLField *field) { |
|
601 dav_free_expression(field->expr); |
|
602 free(field); |
|
603 } |
691 } |
604 |
692 |
605 static int dav_parse_from(DavQLStatement *stmt, UcxList *token) { |
693 static int dav_parse_from(DavQLStatement *stmt, UcxList *token) { |
606 sstr_t tokendata = *token_sstr(token); |
694 sstr_t tokendata = *token_sstr(token); |
607 |
695 |