87 case DAVQL_LIKE: return "LIKE"; case DAVQL_UNLIKE: return "UNLIKE"; |
87 case DAVQL_LIKE: return "LIKE"; case DAVQL_UNLIKE: return "UNLIKE"; |
88 default: return "unknown"; |
88 default: return "unknown"; |
89 } |
89 } |
90 } |
90 } |
91 |
91 |
|
92 static void dav_debug_ql_fnames_print(DavQLStatement *stmt) { |
|
93 printf("Field names: "); |
|
94 UCX_FOREACH(field, stmt->fields) { |
|
95 DavQLField *f = field->data; |
|
96 printf("%.*s, ", sfmtarg(f->name)); |
|
97 } |
|
98 printf("\b\b \b\b\n"); |
|
99 } |
|
100 |
92 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { |
101 static void dav_debug_ql_stmt_print(DavQLStatement *stmt) { |
93 // Basic information |
102 // Basic information |
94 size_t fieldcount = ucx_list_size(stmt->fields); |
103 size_t fieldcount = ucx_list_size(stmt->fields); |
95 int specialfield = 0; |
104 int specialfield = 0; |
96 if (stmt->fields) { |
105 if (stmt->fields) { |
103 } |
112 } |
104 } |
113 } |
105 if (specialfield) { |
114 if (specialfield) { |
106 fieldcount--; |
115 fieldcount--; |
107 } |
116 } |
108 printf("Statement: %.*s\nType: %s\nField count: %zu %s\nPath: %.*s\n" |
117 printf("Statement: %.*s\nType: %s\nField count: %zu %s\n", |
109 "Has where clause: %s\n", |
|
110 sfmtarg(stmt->srctext), |
118 sfmtarg(stmt->srctext), |
111 _map_querytype(stmt->type), |
119 _map_querytype(stmt->type), |
112 fieldcount, |
120 fieldcount, |
113 _map_specialfield(specialfield), |
121 _map_specialfield(specialfield)); |
|
122 |
|
123 dav_debug_ql_fnames_print(stmt); |
|
124 printf("Path: %.*s\nHas where clause: %s\n", |
114 sfmtarg(stmt->path), |
125 sfmtarg(stmt->path), |
115 stmt->where ? "yes" : "no"); |
126 stmt->where ? "yes" : "no"); |
116 |
127 |
117 // WITH attributes |
128 // WITH attributes |
118 if (stmt->depth == DAV_DEPTH_INFINITY) { |
129 if (stmt->depth == DAV_DEPTH_INFINITY) { |
169 } |
180 } |
170 |
181 |
171 #define DQLD_CMD_Q 0 |
182 #define DQLD_CMD_Q 0 |
172 #define DQLD_CMD_PS 1 |
183 #define DQLD_CMD_PS 1 |
173 #define DQLD_CMD_PE 2 |
184 #define DQLD_CMD_PE 2 |
|
185 #define DQLD_CMD_PF 3 |
174 #define DQLD_CMD_F 10 |
186 #define DQLD_CMD_F 10 |
175 #define DQLD_CMD_W 11 |
187 #define DQLD_CMD_W 11 |
176 #define DQLD_CMD_O 12 |
188 #define DQLD_CMD_O 12 |
177 #define DQLD_CMD_L 21 |
189 #define DQLD_CMD_L 21 |
178 #define DQLD_CMD_R 22 |
190 #define DQLD_CMD_R 22 |
195 return DQLD_CMD_Q; |
207 return DQLD_CMD_Q; |
196 } else if (!strcmp(buffer, "ps\n")) { |
208 } else if (!strcmp(buffer, "ps\n")) { |
197 return DQLD_CMD_PS; |
209 return DQLD_CMD_PS; |
198 } else if (!strcmp(buffer, "pe\n")) { |
210 } else if (!strcmp(buffer, "pe\n")) { |
199 return DQLD_CMD_PE; |
211 return DQLD_CMD_PE; |
|
212 } else if (!strcmp(buffer, "pf\n")) { |
|
213 return DQLD_CMD_PF; |
200 } else if (!strcmp(buffer, "l\n")) { |
214 } else if (!strcmp(buffer, "l\n")) { |
201 return DQLD_CMD_L; |
215 return DQLD_CMD_L; |
202 } else if (!strcmp(buffer, "r\n")) { |
216 } else if (!strcmp(buffer, "r\n")) { |
203 return DQLD_CMD_R; |
217 return DQLD_CMD_R; |
204 } else if (!strcmp(buffer, "h\n")) { |
218 } else if (!strcmp(buffer, "h\n")) { |
239 int cmd = dav_debug_ql_command(); |
253 int cmd = dav_debug_ql_command(); |
240 switch (cmd) { |
254 switch (cmd) { |
241 case DQLD_CMD_Q: return; |
255 case DQLD_CMD_Q: return; |
242 case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break; |
256 case DQLD_CMD_PS: dav_debug_ql_stmt_print(stmt); break; |
243 case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break; |
257 case DQLD_CMD_PE: dav_debug_ql_expr_print(examineexpr); break; |
|
258 case DQLD_CMD_PF: dav_debug_ql_fnames_print(stmt); break; |
244 case DQLD_CMD_F: |
259 case DQLD_CMD_F: |
245 if (examineclause != DQLD_CMD_F) { |
260 if (examineclause != DQLD_CMD_F) { |
246 examineclause = DQLD_CMD_F; |
261 examineclause = DQLD_CMD_F; |
247 examineelem = stmt->fields; |
262 examineelem = stmt->fields; |
248 examineexpr = stmt->fields ? |
263 examineexpr = stmt->fields ? |
311 printf( |
326 printf( |
312 "\nCommands:\n" |
327 "\nCommands:\n" |
313 "ps: print statement information\n" |
328 "ps: print statement information\n" |
314 "o: examine order by clause\n" |
329 "o: examine order by clause\n" |
315 "f: examine field list\n" |
330 "f: examine field list\n" |
|
331 "pf: print field names\n" |
316 "w: examine where clause\n" |
332 "w: examine where clause\n" |
317 "n: examine next expression " |
333 "n: examine next expression " |
318 "(in order by clause or field list)\n" |
334 "(in order by clause or field list)\n" |
319 "p: examine previous expression " |
335 "p: examine previous expression " |
320 "(in order by clause or field list)\n" |
336 "(in order by clause or field list)\n" |
534 } |
550 } |
535 |
551 |
536 #define _step_fieldlist_ 10 // field list |
552 #define _step_fieldlist_ 10 // field list |
537 #define _step_FROM_ 20 // FROM clause |
553 #define _step_FROM_ 20 // FROM clause |
538 #define _step_WITH_ 30 // WITH clause |
554 #define _step_WITH_ 30 // WITH clause |
|
555 #define _step_WITHopt_ 530 // expecting more WITH details or end |
539 #define _step_WHERE_ 40 // WHERE clause |
556 #define _step_WHERE_ 40 // WHERE clause |
540 #define _step_ORDER_BYopt_ 552 // expecting more ORDER BY details or end |
|
541 #define _step_ORDER_BY_ 50 // ORDER BY clause |
557 #define _step_ORDER_BY_ 50 // ORDER BY clause |
|
558 #define _step_ORDER_BYopt_ 550 // expecting more ORDER BY details or end |
542 #define _step_end_ 500 // expect end |
559 #define _step_end_ 500 // expect end |
543 |
560 |
544 struct fieldlist_parser_state { |
561 struct fieldlist_parser_state { |
545 UcxList *expr_firsttoken; |
562 UcxList *expr_firsttoken; |
546 DavQLField *currentfield; |
563 DavQLField *currentfield; |
800 dav_free_expression(depthexpr); |
817 dav_free_expression(depthexpr); |
801 } |
818 } |
802 break; |
819 break; |
803 } |
820 } |
804 state->step = 3; |
821 state->step = 3; |
805 return _step_WITH_; // continue parsing WITH clause |
822 return _step_WITHopt_; // continue parsing WITH clause |
806 case 3: |
823 case 3: |
807 // a with clause may be continued with a comma |
824 // a with clause may be continued with a comma |
808 // or another clause may follow |
825 // or another clause may follow |
809 if (!sstrcmp(tokendata, S(","))) { |
826 if (!sstrcmp(tokendata, S(","))) { |
810 state->step = 0; // reset clause parser |
827 state->step = 0; // reset clause parser |
904 dav_free_expression(crit->column); |
921 dav_free_expression(crit->column); |
905 } |
922 } |
906 free(crit); |
923 free(crit); |
907 } |
924 } |
908 |
925 |
|
926 /** |
|
927 * Semantic analysis of a get statement. |
|
928 * @param stmt the statement to analyze. |
|
929 */ |
|
930 static void dav_analyze_get_statement(DavQLStatement *stmt) { |
|
931 // TODO: make it so |
|
932 } |
|
933 |
|
934 |
|
935 /** |
|
936 * Parser of a get statement. |
|
937 * @param stmt the statement object that shall contain the syntax tree |
|
938 * @param tokens the token list |
|
939 */ |
909 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
940 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) { |
910 stmt->type = DAVQL_GET; |
941 stmt->type = DAVQL_GET; |
911 |
942 |
912 int step = _step_fieldlist_; |
943 int step = _step_fieldlist_; |
913 |
944 |
960 if (stmt->errorcode) { |
992 if (stmt->errorcode) { |
961 break; |
993 break; |
962 } |
994 } |
963 } |
995 } |
964 |
996 |
965 if (!stmt->errorcode && step < _step_end_) { |
997 if (!stmt->errorcode) { |
966 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END; |
998 if (step < _step_end_) { |
967 stmt->errormessage = strdup(_unexpected_end_msg); |
999 stmt->errorcode = DAVQL_ERROR_UNEXPECTED_END; |
|
1000 stmt->errormessage = strdup(_unexpected_end_msg); |
|
1001 } else { |
|
1002 dav_analyze_get_statement(stmt); |
|
1003 } |
968 } |
1004 } |
969 } |
1005 } |
970 |
1006 |
971 static void dav_parse_set_statement(DavQLStatement *stmt, UcxList *tokens) { |
1007 static void dav_parse_set_statement(DavQLStatement *stmt, UcxList *tokens) { |
972 stmt->type = DAVQL_SET; |
1008 stmt->type = DAVQL_SET; |