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_UNDEFINED_TYP: return "undefined"; |
52 case DAVQL_NUMBER: return "NUMBER"; |
53 case DAVQL_NUMBER: return "NUMBER"; |
53 case DAVQL_STRING: return "STRING"; |
54 case DAVQL_STRING: return "STRING"; |
54 case DAVQL_TIMESTAMP: return "TIMESTAMP"; |
55 case DAVQL_TIMESTAMP: return "TIMESTAMP"; |
55 case DAVQL_IDENTIFIER: return "IDENTIFIER"; |
56 case DAVQL_IDENTIFIER: return "IDENTIFIER"; |
56 case DAVQL_UNARY: return "UNARY"; |
57 case DAVQL_UNARY: return "UNARY"; |
90 |
91 |
91 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { |
92 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { |
92 // Basic information |
93 // Basic information |
93 size_t fieldcount = ucx_list_size(stmt->fields); |
94 size_t fieldcount = ucx_list_size(stmt->fields); |
94 int specialfield = 0; |
95 int specialfield = 0; |
95 UCX_FOREACH(elm, stmt->fields) { |
96 if (stmt->fields) { |
96 DavQLExpression* expr = (DavQLExpression*)elm->data; |
97 DavQLField* firstfield = (DavQLField*)stmt->fields->data; |
97 if (expr->type == DAVQL_IDENTIFIER && expr->srctext.length == 1) { |
98 if (firstfield->expr->type == DAVQL_IDENTIFIER) { |
98 if (expr->srctext.ptr[0] == '*') { |
99 switch (firstfield->expr->srctext.ptr[0]) { |
99 specialfield = 1; |
100 case '*': specialfield = 1; break; |
100 } else if (expr->srctext.ptr[0] == '-') { |
101 case '-': specialfield = 2; break; |
101 specialfield = 2; |
|
102 } |
102 } |
103 } |
103 } |
104 } |
104 } |
105 if (specialfield) { |
105 if (specialfield) { |
106 fieldcount--; |
106 fieldcount--; |
111 _map_querytype(stmt->type), |
111 _map_querytype(stmt->type), |
112 fieldcount, |
112 fieldcount, |
113 _map_specialfield(specialfield), |
113 _map_specialfield(specialfield), |
114 sfmtarg(stmt->path), |
114 sfmtarg(stmt->path), |
115 stmt->where ? "yes" : "no"); |
115 stmt->where ? "yes" : "no"); |
116 if (stmt->type == DAVQL_SET) { |
|
117 printf("Value list size matches: %s", |
|
118 ucx_list_size(stmt->fields) == ucx_list_size(stmt->setvalues) |
|
119 ? "yes" : "no"); |
|
120 } |
|
121 |
116 |
122 // WITH attributes |
117 // WITH attributes |
123 if (stmt->depth == DAV_DEPTH_INFINITY) { |
118 if (stmt->depth == DAV_DEPTH_INFINITY) { |
124 printf("Depth: infinity\n"); |
119 printf("Depth: infinity\n"); |
125 } else if (stmt->depth == DAV_DEPTH_PLACEHOLDER) { |
120 } else if (stmt->depth == DAV_DEPTH_PLACEHOLDER) { |
159 |
154 |
160 static void dav_debug_ql_expr_print(DavQLExpression *expr) { |
155 static void dav_debug_ql_expr_print(DavQLExpression *expr) { |
161 if (dav_debug_ql_expr_selected(expr)) { |
156 if (dav_debug_ql_expr_selected(expr)) { |
162 sstr_t empty = ST("(empty)"); |
157 sstr_t empty = ST("(empty)"); |
163 printf( |
158 printf( |
164 "Text: %.*s\nType: %s\nOperator: %s\n" |
159 "Text: %.*s\nType: %s\nOperator: %s\n", |
165 "Left hand: %.*s\nRight hand: %.*s\n", |
|
166 sfmtarg(expr->srctext), |
160 sfmtarg(expr->srctext), |
167 _map_exprtype(expr->type), |
161 _map_exprtype(expr->type), |
168 _map_operator(expr->op), |
162 _map_operator(expr->op)); |
169 sfmtarg(expr->left?expr->left->srctext:empty), |
163 if (expr->left || expr->right) { |
170 sfmtarg(expr->right?expr->right->srctext:empty)); |
164 printf("Left hand: %.*s\nRight hand: %.*s\n", |
|
165 sfmtarg(expr->left?expr->left->srctext:empty), |
|
166 sfmtarg(expr->right?expr->right->srctext:empty)); |
|
167 } |
171 } |
168 } |
172 } |
169 } |
173 |
170 |
174 #define DQLD_CMD_Q 0 |
171 #define DQLD_CMD_Q 0 |
175 #define DQLD_CMD_PS 1 |
172 #define DQLD_CMD_PS 1 |
176 #define DQLD_CMD_PE 2 |
173 #define DQLD_CMD_PE 2 |
177 #define DQLD_CMD_P 10 |
174 #define DQLD_CMD_F 10 |
|
175 #define DQLD_CMD_W 11 |
|
176 #define DQLD_CMD_O 12 |
178 #define DQLD_CMD_L 21 |
177 #define DQLD_CMD_L 21 |
179 #define DQLD_CMD_R 22 |
178 #define DQLD_CMD_R 22 |
|
179 #define DQLD_CMD_N 23 |
|
180 #define DQLD_CMD_P 24 |
180 #define DQLD_CMD_H 100 |
181 #define DQLD_CMD_H 100 |
181 |
182 |
182 static int dav_debug_ql_command() { |
183 static int dav_debug_ql_command() { |
183 printf("> "); |
184 printf("> "); |
184 |
185 |
185 char buffer[16]; |
186 char buffer[8]; |
186 fgets(buffer, 16, stdin); |
187 fgets(buffer, 8, stdin); |
|
188 // discard remaining chars |
|
189 if (!strchr(buffer, '\n')) { |
|
190 int chr; |
|
191 while ((chr = fgetc(stdin) != '\n') && chr != EOF); |
|
192 } |
|
193 |
187 if (!strcmp(buffer, "q\n")) { |
194 if (!strcmp(buffer, "q\n")) { |
188 return DQLD_CMD_Q; |
195 return DQLD_CMD_Q; |
189 } else if (!strcmp(buffer, "ps\n")) { |
196 } else if (!strcmp(buffer, "ps\n")) { |
190 return DQLD_CMD_PS; |
197 return DQLD_CMD_PS; |
191 } else if (!strcmp(buffer, "pe\n")) { |
198 } else if (!strcmp(buffer, "pe\n")) { |
194 return DQLD_CMD_L; |
201 return DQLD_CMD_L; |
195 } else if (!strcmp(buffer, "r\n")) { |
202 } else if (!strcmp(buffer, "r\n")) { |
196 return DQLD_CMD_R; |
203 return DQLD_CMD_R; |
197 } else if (!strcmp(buffer, "h\n")) { |
204 } else if (!strcmp(buffer, "h\n")) { |
198 return DQLD_CMD_H; |
205 return DQLD_CMD_H; |
|
206 } else if (!strcmp(buffer, "f\n")) { |
|
207 return DQLD_CMD_F; |
|
208 } else if (!strcmp(buffer, "w\n")) { |
|
209 return DQLD_CMD_W; |
|
210 } else if (!strcmp(buffer, "o\n")) { |
|
211 return DQLD_CMD_O; |
|
212 } else if (!strcmp(buffer, "n\n")) { |
|
213 return DQLD_CMD_N; |
|
214 } else if (!strcmp(buffer, "p\n")) { |
|
215 return DQLD_CMD_P; |
199 } else { |
216 } else { |
200 return -1; |
217 return -1; |
201 } |
218 } |
202 } |
219 } |
203 |
220 |
213 if (stmt->errorcode) { |
230 if (stmt->errorcode) { |
214 return; |
231 return; |
215 } |
232 } |
216 |
233 |
217 DavQLExpression *examineexpr = NULL; |
234 DavQLExpression *examineexpr = NULL; |
|
235 UcxList *examineelem = NULL; |
|
236 int examineclause = 0; |
218 |
237 |
219 while(1) { |
238 while(1) { |
220 int cmd = dav_debug_ql_command(); |
239 int cmd = dav_debug_ql_command(); |
221 switch (cmd) { |
240 switch (cmd) { |
222 case DQLD_CMD_Q: return; |
241 case DQLD_CMD_Q: return; |
223 case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break; |
242 case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break; |
224 case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break; |
243 case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break; |
|
244 case DQLD_CMD_F: |
|
245 if (examineclause != DQLD_CMD_F) { |
|
246 examineclause = DQLD_CMD_F; |
|
247 examineelem = stmt->fields; |
|
248 examineexpr = stmt->fields ? |
|
249 ((DavQLField*)stmt->fields->data)->expr : NULL; |
|
250 dav_debug_ql_expr_print(examineexpr); |
|
251 } |
|
252 break; |
|
253 case DQLD_CMD_W: |
|
254 examineclause = 0; examineelem = NULL; |
|
255 examineexpr = stmt->where; |
|
256 dav_debug_ql_expr_print(examineexpr); |
|
257 break; |
|
258 case DQLD_CMD_O: |
|
259 if (examineclause != DQLD_CMD_O) { |
|
260 examineclause = DQLD_CMD_O; |
|
261 examineelem = stmt->orderby; |
|
262 examineexpr = stmt->orderby ? |
|
263 ((DavQLOrderCriterion*)stmt->orderby->data)->column : NULL; |
|
264 dav_debug_ql_expr_print(examineexpr); |
|
265 } |
|
266 break; |
|
267 case DQLD_CMD_N: |
|
268 case DQLD_CMD_P: |
|
269 if (examineelem) { |
|
270 UcxList *newelem = (cmd == DQLD_CMD_N ? |
|
271 examineelem->next : examineelem->prev); |
|
272 if (newelem) { |
|
273 examineelem = newelem; |
|
274 if (examineclause == DQLD_CMD_O) { |
|
275 examineexpr = ((DavQLOrderCriterion*) |
|
276 examineelem->data)->column; |
|
277 } else if (examineclause == DQLD_CMD_F) { |
|
278 examineexpr = ((DavQLField*)examineelem->data)->expr; |
|
279 } else { |
|
280 printf("Examining unknown clause type."); |
|
281 } |
|
282 dav_debug_ql_expr_print(examineexpr); |
|
283 } else { |
|
284 printf("Reached end of list.\n"); |
|
285 } |
|
286 } else { |
|
287 printf("Currently not examining an expression list.\n"); |
|
288 } |
|
289 break; |
225 case DQLD_CMD_L: |
290 case DQLD_CMD_L: |
226 if (dav_debug_ql_expr_selected(examineexpr)) { |
291 if (dav_debug_ql_expr_selected(examineexpr)) { |
227 if (examineexpr->left) { |
292 if (examineexpr->left) { |
228 examineexpr = examineexpr->left; |
293 examineexpr = examineexpr->left; |
229 dav_debug_ql_expr_print(examineexpr); |
294 dav_debug_ql_expr_print(examineexpr); |
244 break; |
309 break; |
245 case DQLD_CMD_H: |
310 case DQLD_CMD_H: |
246 printf( |
311 printf( |
247 "\nCommands:\n" |
312 "\nCommands:\n" |
248 "ps: print statement information\n" |
313 "ps: print statement information\n" |
|
314 "o: examine order by clause\n" |
|
315 "f: examine field list\n" |
|
316 "w: examine where clause\n" |
|
317 "n: examine next expression " |
|
318 "(in order by clause or field list)\n" |
|
319 "p: examine previous expression " |
|
320 "(in order by clause or field list)\n" |
249 "q: quit\n\n" |
321 "q: quit\n\n" |
250 "\nExpression examination:\n" |
322 "\nExpression examination:\n" |
251 "pe: print expression information\n" |
323 "pe: print expression information\n" |
252 "l: enter left subtree\n" |
324 "l: enter left subtree\n" |
253 "r: enter right subtree\n"); |
325 "r: enter right subtree\n"); |
465 #define _step_WITH_ 30 // WITH clause |
539 #define _step_WITH_ 30 // WITH clause |
466 #define _step_WHERE_ 40 // WHERE clause |
540 #define _step_WHERE_ 40 // WHERE clause |
467 #define _step_ORDER_BYopt_ 552 // expecting more ORDER BY details or end |
541 #define _step_ORDER_BYopt_ 552 // expecting more ORDER BY details or end |
468 #define _step_ORDER_BY_ 50 // ORDER BY clause |
542 #define _step_ORDER_BY_ 50 // ORDER BY clause |
469 #define _step_end_ 500 // expect end |
543 #define _step_end_ 500 // expect end |
|
544 |
|
545 struct fieldlist_parser_state { |
|
546 UcxList *expr_firsttoken; |
|
547 size_t expr_len; |
|
548 /* |
|
549 * 0: begin of field list - may encounter "*" or "-" special fields |
|
550 * 1: collect expression token |
|
551 * switch to step 2 on keyword "as" |
|
552 * expect "," only if expr_len is 1 (add expr to list and continue) |
|
553 * 2: expect one token (identifier) and a "," - continue with step 1 |
|
554 */ |
|
555 int step; |
|
556 }; |
|
557 |
|
558 static int dav_parse_fieldlist(DavQLStatement *stmt, UcxList *token, |
|
559 struct fieldlist_parser_state *state) { |
|
560 sstr_t tokendata = *token_sstr(token); |
|
561 |
|
562 switch (state->step) { |
|
563 case 0: |
|
564 // did not encounter special field, fall through to step 1 |
|
565 case 1: |
|
566 break; |
|
567 } |
|
568 |
|
569 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); |
|
570 if (fromkeyword || !sstrcmp(tokendata, S(","))) { |
|
571 if (state->expr_firsttoken) { |
|
572 DavQLField *field = malloc(sizeof(DavQLField)); |
|
573 field->expr = dav_parse_expression( |
|
574 stmt, state->expr_firsttoken, state->expr_len); |
|
575 field->name = field->expr->srctext; |
|
576 stmt->fields = ucx_list_append(stmt->fields, field); |
|
577 state->expr_firsttoken = NULL; |
|
578 state->expr_len = 0; |
|
579 |
|
580 if (fromkeyword) { |
|
581 return _step_FROM_; |
|
582 } |
|
583 } else { |
|
584 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
|
585 _unexpected_token, stmt, token); |
|
586 } |
|
587 } else { |
|
588 // collect tokens for field expression |
|
589 if (state->expr_firsttoken) { |
|
590 state->expr_len++; |
|
591 } else { |
|
592 state->expr_firsttoken = token; |
|
593 state->expr_len = 1; |
|
594 } |
|
595 } |
|
596 |
|
597 return _step_fieldlist_; |
|
598 } |
|
599 |
|
600 static void dav_free_field(DavQLField *field) { |
|
601 dav_free_expression(field->expr); |
|
602 free(field); |
|
603 } |
470 |
604 |
471 static int dav_parse_from(DavQLStatement *stmt, UcxList *token) { |
605 static int dav_parse_from(DavQLStatement *stmt, UcxList *token) { |
472 sstr_t tokendata = *token_sstr(token); |
606 sstr_t tokendata = *token_sstr(token); |
473 |
607 |
474 if (!sstrcasecmp(tokendata, S("with"))) { |
608 if (!sstrcasecmp(tokendata, S("with"))) { |
691 |
825 |
692 struct with_parser_state state_with; |
826 struct with_parser_state state_with; |
693 memset(&state_with, 0, sizeof(struct with_parser_state)); |
827 memset(&state_with, 0, sizeof(struct with_parser_state)); |
694 struct orderby_parser_state state_orderby; |
828 struct orderby_parser_state state_orderby; |
695 memset(&state_orderby, 0, sizeof(struct orderby_parser_state)); |
829 memset(&state_orderby, 0, sizeof(struct orderby_parser_state)); |
696 |
830 struct fieldlist_parser_state state_fieldlist; |
697 // Variables for token sublists for expressions |
831 memset(&state_fieldlist, 0, sizeof(struct fieldlist_parser_state)); |
698 // TODO: this is deprecated and won't work with function calls |
|
699 UcxList *exprstart = NULL; |
|
700 size_t exprlen = 0; |
|
701 |
832 |
702 // Process tokens |
833 // Process tokens |
703 UCX_FOREACH(token, tokens) { |
834 UCX_FOREACH(token, tokens) { |
704 sstr_t tokendata = *token_sstr(token); |
|
705 |
|
706 switch (step) { |
835 switch (step) { |
707 // too much input data |
836 // too much input data |
708 case _step_end_: |
837 case _step_end_: |
709 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
838 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
710 _unexpected_token, stmt, token); |
839 _unexpected_token, stmt, token); |
711 break; |
840 break; |
712 // field list |
841 // field list |
713 case _step_fieldlist_: { |
842 case _step_fieldlist_: { |
714 _Bool fromkeyword = !sstrcasecmp(tokendata, S("from")); |
843 step = dav_parse_fieldlist(stmt, token, &state_fieldlist); |
715 if (fromkeyword || !sstrcmp(tokendata, S(","))) { |
|
716 if (exprstart) { |
|
717 stmt->fields = ucx_list_append(stmt->fields, |
|
718 dav_parse_expression(stmt, exprstart, exprlen)); |
|
719 exprstart = NULL; |
|
720 exprlen = 0; |
|
721 |
|
722 if (fromkeyword) { |
|
723 step = _step_FROM_; |
|
724 } |
|
725 } else { |
|
726 dav_error_in_context(DAVQL_ERROR_UNEXPECTED_TOKEN, |
|
727 _unexpected_token, stmt, token); |
|
728 } |
|
729 } else { |
|
730 // collect tokens for field expression |
|
731 if (exprstart) { |
|
732 exprlen++; |
|
733 } else { |
|
734 exprstart = token; |
|
735 exprlen = 1; |
|
736 } |
|
737 } |
|
738 break; |
844 break; |
739 } |
845 } |
740 // from clause |
846 // from clause |
741 case _step_FROM_: { |
847 case _step_FROM_: { |
742 step = dav_parse_from(stmt, token); |
848 step = dav_parse_from(stmt, token); |
826 return stmt; |
932 return stmt; |
827 } |
933 } |
828 |
934 |
829 void dav_free_statement(DavQLStatement *stmt) { |
935 void dav_free_statement(DavQLStatement *stmt) { |
830 UCX_FOREACH(expr, stmt->fields) { |
936 UCX_FOREACH(expr, stmt->fields) { |
831 dav_free_expression(expr->data); |
937 dav_free_field(expr->data); |
832 } |
938 } |
833 ucx_list_free(stmt->fields); |
939 ucx_list_free(stmt->fields); |
834 UCX_FOREACH(expr, stmt->setvalues) { |
|
835 dav_free_expression(expr->data); |
|
836 } |
|
837 ucx_list_free(stmt->setvalues); |
|
838 |
940 |
839 if (stmt->where) { |
941 if (stmt->where) { |
840 dav_free_expression(stmt->where); |
942 dav_free_expression(stmt->where); |
841 } |
943 } |
842 if (stmt->errormessage) { |
944 if (stmt->errormessage) { |