libidav/davqlexec.c

changeset 128
649eb328674a
parent 127
7072a2b4ae35
child 133
8c37028f5024
equal deleted inserted replaced
127:7072a2b4ae35 128:649eb328674a
31 #include <string.h> 31 #include <string.h>
32 32
33 #include <ucx/utils.h> 33 #include <ucx/utils.h>
34 #include "davqlexec.h" 34 #include "davqlexec.h"
35 #include "utils.h" 35 #include "utils.h"
36 36 #include "methods.h"
37 DavQLResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) { 37 #include "session.h"
38
39 DavResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) {
38 va_list ap; 40 va_list ap;
39 va_start(ap, st); 41 va_start(ap, st);
40 DavQLResult *result = dav_statement_execv(sn, st, ap); 42 DavResult *result = dav_statement_execv(sn, st, ap);
41 va_end(ap); 43 va_end(ap);
42 return result; 44 return result;
43 } 45 }
44 46
45 DavQLResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap) { 47 DavResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap) {
46 DavQLResult *result = dav_session_malloc(sn, sizeof(DavQLResult)); 48 DavResult *result = dav_session_malloc(sn, sizeof(DavResult));
47 result->result = NULL; 49 result->result = NULL;
48 result->status = 1; 50 result->status = 1;
49 51
50 // make sure the statement was successfully parsed 52 // make sure the statement was successfully parsed
51 if(st->type == DAVQL_ERROR) { 53 if(st->type == DAVQL_ERROR) {
55 // get path string 57 // get path string
56 davqlerror_t error; 58 davqlerror_t error;
57 sstr_t path = dav_format_string(sn->mp->allocator, st->path, ap, &error); 59 sstr_t path = dav_format_string(sn->mp->allocator, st->path, ap, &error);
58 60
59 if(st->type == DAVQL_SELECT) { 61 if(st->type == DAVQL_SELECT) {
60 dav_exec_get(sn, st, path.ptr, ap); 62 *result = dav_exec_select(sn, st, path.ptr, ap);
61 } else { 63 } else {
62 // TODO 64 // TODO
63 } 65 }
64 66
65 return result; 67 return result;
124 *error = DAVQL_OK; 126 *error = DAVQL_OK;
125 127
126 return sstrdup_a(a, sstrn(buf->space, buf->size)); 128 return sstrdup_a(a, sstrn(buf->space, buf->size));
127 } 129 }
128 130
129 void dav_exec_get(DavSession *sn, DavQLStatement *st, char* path, va_list ap) { 131 /*
130 // execute a davql get statement 132 * execute a davql select statement
133 */
134 DavResult dav_exec_select(DavSession *sn, DavQLStatement *st, char* path, va_list ap) {
131 UcxMempool *mp = ucx_mempool_new(128); 135 UcxMempool *mp = ucx_mempool_new(128);
132 136
133 // TODO: get property list 137 // TODO: get property list
134 138 UcxBuffer *rqbuf = create_allprop_propfind_request();
135 UcxBuffer *bcode = dav_compile_expr(mp->allocator, st->where, ap); 139
136 140 UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, ap);
137 //print_bytecode(bcode); 141
138 142 DavResource *selroot = dav_resource_new(sn, path);
139 DavResource *res = dav_resource_new(sn, "/test.txt"); 143 DavResult result;
140 dav_set_property_ns(res, "DAV:", "string", "value"); 144 result.result = selroot;
141 dav_set_property_ns(res, "DAV:", "integer", "1337"); 145 result.status = 0;
142 res->lastmodified = 100; 146
143 147
144 DavQLStackObj result; 148 UcxList *stack = NULL; // stack with DavResource* elements
145 dav_exec_expr(bcode, res, &result); 149 // initialize the stack with the requested resource
150 DavQLRes *r = ucx_mempool_malloc(mp, sizeof(DavQLRes));
151 r->resource = selroot;
152 r->depth = 0;
153 stack = ucx_list_prepend(stack, r);
154
155 // reuseable response buffer
156 UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND);
157
158 // do a propfind request for each resource on the stack
159 while(stack) {
160 DavQLRes *sr = stack->data; // get first element from the stack
161 stack = ucx_list_remove(stack, stack); // remove first element
162 DavResource *root = sr->resource;
163
164 util_set_url(sn, dav_resource_get_href(sr->resource));
165 CURLcode ret = do_propfind_request(sn->handle, rqbuf, rpbuf);
166 int http_status = 0;
167 curl_easy_getinfo (sn->handle, CURLINFO_RESPONSE_CODE, &http_status);
168
169 if(ret == CURLE_OK && http_status == 207) {
170 // propfind request successful, now parse the response
171 char *url = "http://url/";
172 PropfindParser *parser = create_propfind_parser(rpbuf, url);
173 ResponseTag response;
174 int r;
175 while((r = get_propfind_response(parser, &response)) != 0) {
176 if(r == -1) {
177 // error
178 result.status = -1;
179 // TODO: free resources
180 break;
181 }
182
183 // the propfind multistatus response contains responses
184 // for the requsted resource and all childs
185 // determine if the response is a child or not
186 if(hrefeq(sn, root->href, response.href)) {
187 // response is the currently requested resource
188 // and not a child
189
190 // add properties
191 add_properties(root, &response);
192
193 if(root == selroot) {
194 // The current root is the root of the select query.
195 // In this case we have to check the where clause.
196 // If root is not selroot, the where clause was
197 // already checked for the resource before it was
198 // added to the stack.
199 DavQLStackObj where_result;
200 if(!dav_exec_expr(where, root, &where_result)) {
201 if(where_result.data.integer != 0) {
202 continue;
203 }
204 } else {
205 result.status = -1;
206 }
207 dav_resource_free_all(selroot);
208 ucx_list_free(stack);
209 break;
210 }
211 } else {
212 DavResource *child = response2resource(
213 sn,
214 &response,
215 root->path);
216 // check where clause
217 DavQLStackObj where_result;
218 if(!dav_exec_expr(where, child, &where_result)) {
219 if(where_result.data.integer != 0) {
220 resource_add_child(root, child);
221 if(child->iscollection &&
222 (st->depth < 0 || st->depth > sr->depth+1))
223 {
224 DavQLRes *rs = ucx_mempool_malloc(
225 mp,
226 sizeof(DavQLRes));
227 rs->resource = child;
228 rs->depth = sr->depth + 1;
229 stack = ucx_list_prepend(stack, rs);
230 }
231 } else {
232 dav_resource_free(child);
233 }
234 }
235 }
236 }
237
238 } else {
239 dav_session_set_error(sn, ret, http_status);
240 result.status = -1;
241 dav_resource_free_all(selroot);
242 break;
243 }
244
245 // reset response buffer
246 ucx_buffer_seek(rpbuf, SEEK_SET, 0);
247 }
248
249 ucx_mempool_destroy(mp);
250
251 result.result = selroot;
252 return result;
146 } 253 }
147 254
148 static int count_func_args(DavQLExpression *expr) { 255 static int count_func_args(DavQLExpression *expr) {
149 int count = 0; 256 int count = 0;
150 DavQLExpression *arg = expr->right; 257 DavQLExpression *arg = expr->right;
157 } 264 }
158 } 265 }
159 return count; 266 return count;
160 } 267 }
161 268
162 static int identifier2propname(UcxAllocator *a, sstr_t id, DavPropName *propname) { 269 static int add_cmd(DavContext *ctx, UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) {
163 ssize_t count;
164 sstr_t *s = sstrsplit_a(a, id, S(":"), &count);
165 if(count == 2) {
166 sstr_t ns = s[0];
167 sstr_t name = s[1];
168 propname->ns = ns.ptr;
169 propname->name = name.ptr;
170 return 0;
171 } else {
172 return 1;
173 }
174 }
175
176 static int add_cmd(UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) {
177 if(!expr) { 270 if(!expr) {
178 return 0; 271 return 0;
179 } 272 }
180 273
181 int numcmd = 1; 274 int numcmd = 1;
217 case DAVQL_IDENTIFIER: { 310 case DAVQL_IDENTIFIER: {
218 sstr_t propertyname = sstrchr(src, ':'); 311 sstr_t propertyname = sstrchr(src, ':');
219 cmd.type = DAVQL_CMD_RES_IDENTIFIER; 312 cmd.type = DAVQL_CMD_RES_IDENTIFIER;
220 if(propertyname.length > 0) { 313 if(propertyname.length > 0) {
221 cmd.type = DAVQL_CMD_PROP_IDENTIFIER; 314 cmd.type = DAVQL_CMD_PROP_IDENTIFIER;
222 if(identifier2propname(a, src, &cmd.data.property)) { 315 char *ns;
316 char *name;
317 dav_get_property_namespace(
318 ctx,
319 sstrdup_a(a, src).ptr,
320 &ns,
321 &name);
322 if(ns && name) {
323 cmd.data.property.ns = ns;
324 cmd.data.property.name = name;
325 } else {
223 // error 326 // error
224 return -1; 327 return -1;
225 } 328 }
226 } else if(!sstrcmp(src, S("name"))) { 329 } else if(!sstrcmp(src, S("name"))) {
227 cmd.data.resprop = DAVQL_RES_NAME; 330 cmd.data.resprop = DAVQL_RES_NAME;
251 } 354 }
252 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 355 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
253 break; 356 break;
254 } 357 }
255 case DAVQL_UNARY: { 358 case DAVQL_UNARY: {
256 numcmd += add_cmd(a, bcode, expr->left, ap); 359 numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
257 switch(expr->op) { 360 switch(expr->op) {
258 case DAVQL_ADD: { 361 case DAVQL_ADD: {
259 cmd.type = DAVQL_CMD_OP_UNARY_ADD; 362 // noop
363 numcmd = 0;
260 break; 364 break;
261 } 365 }
262 case DAVQL_SUB: { 366 case DAVQL_SUB: {
263 cmd.type = DAVQL_CMD_OP_UNARY_SUB; 367 cmd.type = DAVQL_CMD_OP_UNARY_SUB;
368 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
264 break; 369 break;
265 } 370 }
266 case DAVQL_NEG: { 371 case DAVQL_NEG: {
267 cmd.type = DAVQL_CMD_OP_UNARY_NEG; 372 cmd.type = DAVQL_CMD_OP_UNARY_NEG;
268 break; 373 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
269 } 374 break;
270 } 375 }
271 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 376 }
272 break; 377 break;
273 } 378 }
274 case DAVQL_BINARY: { 379 case DAVQL_BINARY: {
275 numcmd += add_cmd(a, bcode, expr->left, ap); 380 numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
276 numcmd += add_cmd(a, bcode, expr->right, ap); 381 numcmd += add_cmd(ctx, a, bcode, expr->right, ap);
277 switch(expr->op) { 382 switch(expr->op) {
278 case DAVQL_ADD: { 383 case DAVQL_ADD: {
279 cmd.type = DAVQL_CMD_OP_BINARY_ADD; 384 cmd.type = DAVQL_CMD_OP_BINARY_ADD;
280 break; 385 break;
281 } 386 }
307 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 412 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
308 break; 413 break;
309 } 414 }
310 case DAVQL_LOGICAL: { 415 case DAVQL_LOGICAL: {
311 if(expr->left && expr->right && expr->op != DAVQL_LOR) { 416 if(expr->left && expr->right && expr->op != DAVQL_LOR) {
312 numcmd += add_cmd(a, bcode, expr->left, ap); 417 numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
313 numcmd += add_cmd(a, bcode, expr->right, ap); 418 numcmd += add_cmd(ctx, a, bcode, expr->right, ap);
314 } 419 }
315 420
316 switch(expr->op) { 421 switch(expr->op) {
317 case DAVQL_NOT: { 422 case DAVQL_NOT: {
318 numcmd += add_cmd(a, bcode, expr->left, ap); 423 numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
319 cmd.type = DAVQL_CMD_OP_LOGICAL_NOT; 424 cmd.type = DAVQL_CMD_OP_LOGICAL_NOT;
320 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 425 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
321 break; 426 break;
322 } 427 }
323 case DAVQL_LAND: { 428 case DAVQL_LAND: {
324 cmd.type = DAVQL_CMD_OP_LOGICAL_AND; 429 cmd.type = DAVQL_CMD_OP_LOGICAL_AND;
325 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 430 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
326 break; 431 break;
327 } 432 }
328 case DAVQL_LOR: { 433 case DAVQL_LOR: {
329 int nleft = add_cmd(a, bcode, expr->left, ap); 434 int nleft = add_cmd(ctx, a, bcode, expr->left, ap);
330 435
331 cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L; 436 cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L;
332 DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos); 437 DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos);
333 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 438 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
334 439
335 int nright = add_cmd(a, bcode, expr->right, ap); 440 int nright = add_cmd(ctx, a, bcode, expr->right, ap);
336 or_l->data.integer = nright + 1; 441 or_l->data.integer = nright + 1;
337 442
338 cmd.type = DAVQL_CMD_OP_LOGICAL_OR; 443 cmd.type = DAVQL_CMD_OP_LOGICAL_OR;
339 cmd.data.integer = 0; 444 cmd.data.integer = 0;
340 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode); 445 ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
391 break; 496 break;
392 } 497 }
393 case DAVQL_FUNCCALL: { 498 case DAVQL_FUNCCALL: {
394 switch(expr->op) { 499 switch(expr->op) {
395 case DAVQL_CALL: { 500 case DAVQL_CALL: {
396 int nright = add_cmd(a, bcode, expr->right, ap); 501 int nright = add_cmd(ctx, a, bcode, expr->right, ap);
397 // TODO: count args 502 // TODO: count args
398 DavQLExpression *funcid = expr->left; 503 DavQLExpression *funcid = expr->left;
399 if(!funcid && funcid->type != DAVQL_IDENTIFIER) { 504 if(!funcid && funcid->type != DAVQL_IDENTIFIER) {
400 // fail 505 // fail
401 return -1; 506 return -1;
415 numcmd += nright; 520 numcmd += nright;
416 break; 521 break;
417 } 522 }
418 case DAVQL_ARGLIST: { 523 case DAVQL_ARGLIST: {
419 numcmd = 0; 524 numcmd = 0;
420 numcmd += add_cmd(a, bcode, expr->left, ap); 525 numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
421 numcmd += add_cmd(a, bcode, expr->right, ap); 526 numcmd += add_cmd(ctx, a, bcode, expr->right, ap);
422 break; 527 break;
423 } 528 }
424 } 529 }
425 break; 530 break;
426 } 531 }
427 } 532 }
428 return numcmd; 533 return numcmd;
429 } 534 }
430 535
431 UcxBuffer* dav_compile_expr(UcxAllocator *a, DavQLExpression *lexpr, va_list ap) { 536 UcxBuffer* dav_compile_expr(DavContext *ctx, UcxAllocator *a, DavQLExpression *lexpr, va_list ap) {
432 UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND); 537 UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND);
433 if(!bcode) { 538 if(!bcode) {
434 return NULL; 539 return NULL;
435 } 540 }
436 541
437 if(add_cmd(a, bcode, lexpr, ap) <= 0) { 542 if(add_cmd(ctx, a, bcode, lexpr, ap) <= 0) {
438 ucx_buffer_free(bcode); 543 ucx_buffer_free(bcode);
439 return NULL; 544 return NULL;
440 } 545 }
441 546
442 return bcode; 547 return bcode;
676 break; 781 break;
677 } 782 }
678 } 783 }
679 } 784 }
680 785
681 for(int i=0;i<stpos;i++) { 786 int ret = 0;
682 DavQLStackObj obj = stack[i]; 787 if(stpos == 1) {
683 if(obj.type == 0) { 788 *result = stack[0];
684 printf("stack: int=%lld\n", obj.data.integer); 789 } else {
685 } else { 790 ret = -1;
686 printf("stack: string=\"%.*s\"\n", obj.length, obj.data.string); 791 }
687 } 792 free(stack);
688 } 793
689 return 0; 794 return ret;
690 } 795 }
691 796
692 797
693 void print_bytecode(UcxBuffer *bcode) { 798 void print_bytecode(UcxBuffer *bcode) {
694 bcode->pos = 0; 799 bcode->pos = 0;

mercurial