libidav/davqlexec.c

changeset 128
649eb328674a
parent 127
7072a2b4ae35
child 133
8c37028f5024
--- a/libidav/davqlexec.c	Tue Jun 02 10:07:20 2015 +0200
+++ b/libidav/davqlexec.c	Tue Jun 02 20:57:23 2015 +0200
@@ -33,17 +33,19 @@
 #include <ucx/utils.h>
 #include "davqlexec.h"
 #include "utils.h"
+#include "methods.h"
+#include "session.h"
 
-DavQLResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) {
+DavResult* dav_statement_exec(DavSession *sn, DavQLStatement *st, ...) {
     va_list ap;
     va_start(ap, st);
-    DavQLResult *result = dav_statement_execv(sn, st, ap);
+    DavResult *result = dav_statement_execv(sn, st, ap);
     va_end(ap);
     return result;
 }
 
-DavQLResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap) {
-    DavQLResult *result = dav_session_malloc(sn, sizeof(DavQLResult));
+DavResult* dav_statement_execv(DavSession *sn, DavQLStatement *st, va_list ap) {
+    DavResult *result = dav_session_malloc(sn, sizeof(DavResult));
     result->result = NULL;
     result->status = 1;
     
@@ -57,7 +59,7 @@
     sstr_t path = dav_format_string(sn->mp->allocator, st->path, ap, &error);
     
     if(st->type == DAVQL_SELECT) {
-        dav_exec_get(sn, st, path.ptr, ap);
+        *result = dav_exec_select(sn, st, path.ptr, ap);
     } else {
         // TODO
     }
@@ -126,23 +128,128 @@
     return sstrdup_a(a, sstrn(buf->space, buf->size));
 }
 
-void dav_exec_get(DavSession *sn, DavQLStatement *st, char* path, va_list ap) {
-    // execute a davql get statement
+/*
+ * execute a davql select statement
+ */
+DavResult dav_exec_select(DavSession *sn, DavQLStatement *st, char* path, va_list ap) {
     UcxMempool *mp = ucx_mempool_new(128);
     
     // TODO: get property list
+    UcxBuffer *rqbuf = create_allprop_propfind_request();
     
-    UcxBuffer *bcode = dav_compile_expr(mp->allocator, st->where, ap);
+    UcxBuffer *where = dav_compile_expr(sn->context, mp->allocator, st->where, ap);
+    
+    DavResource *selroot = dav_resource_new(sn, path);
+    DavResult result;
+    result.result = selroot;
+    result.status = 0;
+    
     
-    //print_bytecode(bcode);
+    UcxList *stack = NULL; // stack with DavResource* elements
+    // initialize the stack with the requested resource
+    DavQLRes *r = ucx_mempool_malloc(mp, sizeof(DavQLRes));
+    r->resource = selroot;
+    r->depth = 0;
+    stack = ucx_list_prepend(stack, r);
+    
+    // reuseable response buffer
+    UcxBuffer *rpbuf = ucx_buffer_new(NULL, 4096, UCX_BUFFER_AUTOEXTEND);
     
-    DavResource *res = dav_resource_new(sn, "/test.txt");
-    dav_set_property_ns(res, "DAV:", "string", "value");
-    dav_set_property_ns(res, "DAV:", "integer", "1337");
-    res->lastmodified = 100;
+    // do a propfind request for each resource on the stack
+    while(stack) {
+        DavQLRes *sr = stack->data; // get first element from the stack
+        stack = ucx_list_remove(stack, stack); // remove first element
+        DavResource *root = sr->resource;
+        
+        util_set_url(sn, dav_resource_get_href(sr->resource));
+        CURLcode ret = do_propfind_request(sn->handle, rqbuf, rpbuf);
+        int http_status = 0;
+        curl_easy_getinfo (sn->handle, CURLINFO_RESPONSE_CODE, &http_status);
+        
+        if(ret == CURLE_OK && http_status == 207) {
+            // propfind request successful, now parse the response
+            char *url = "http://url/";
+            PropfindParser *parser = create_propfind_parser(rpbuf, url);
+            ResponseTag response;
+            int r;
+            while((r = get_propfind_response(parser, &response)) != 0) {
+                if(r == -1) {
+                    // error
+                    result.status = -1;
+                    // TODO: free resources
+                    break;
+                }
+                
+                // the propfind multistatus response contains responses
+                // for the requsted resource and all childs
+                // determine if the response is a child or not
+                if(hrefeq(sn, root->href, response.href)) {
+                    // response is the currently requested resource
+                    // and not a child
+                    
+                    // add properties
+                    add_properties(root, &response);
+                    
+                    if(root == selroot) {
+                        // The current root is the root of the select query.
+                        // In this case we have to check the where clause.
+                        // If root is not selroot, the where clause was
+                        // already checked for the resource before it was
+                        // added to the stack.
+                        DavQLStackObj where_result;
+                        if(!dav_exec_expr(where, root, &where_result)) {
+                            if(where_result.data.integer != 0) {
+                                continue;
+                            }
+                        } else {
+                            result.status = -1;
+                        }
+                        dav_resource_free_all(selroot);
+                        ucx_list_free(stack);
+                        break;
+                    }
+                } else {
+                    DavResource *child = response2resource(
+                            sn,
+                            &response,
+                            root->path);
+                    // check where clause
+                    DavQLStackObj where_result;
+                    if(!dav_exec_expr(where, child, &where_result)) {
+                        if(where_result.data.integer != 0) {
+                            resource_add_child(root, child);
+                            if(child->iscollection &&
+                                (st->depth < 0 || st->depth > sr->depth+1))
+                            {
+                                DavQLRes *rs = ucx_mempool_malloc(
+                                        mp,
+                                        sizeof(DavQLRes));
+                                rs->resource = child;
+                                rs->depth = sr->depth + 1;
+                                stack = ucx_list_prepend(stack, rs);
+                            }
+                        } else {
+                            dav_resource_free(child);
+                        }
+                    }
+                }    
+            }
+            
+        } else  {
+            dav_session_set_error(sn, ret, http_status);
+            result.status = -1;
+            dav_resource_free_all(selroot);
+            break;
+        }
+        
+        // reset response buffer
+        ucx_buffer_seek(rpbuf, SEEK_SET, 0);
+    }
     
-    DavQLStackObj result;
-    dav_exec_expr(bcode, res, &result);
+    ucx_mempool_destroy(mp);
+    
+    result.result = selroot;
+    return result;
 }
 
 static int count_func_args(DavQLExpression *expr) {
@@ -159,21 +266,7 @@
     return count;
 }
 
-static int identifier2propname(UcxAllocator *a, sstr_t id, DavPropName *propname) {
-    ssize_t count;
-    sstr_t *s = sstrsplit_a(a, id, S(":"), &count);
-    if(count == 2) {
-        sstr_t ns = s[0];
-        sstr_t name = s[1];
-        propname->ns = ns.ptr;
-        propname->name = name.ptr;
-        return 0;
-    } else {
-        return 1;
-    }
-}
-
-static int add_cmd(UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) {
+static int add_cmd(DavContext *ctx, UcxAllocator *a, UcxBuffer *bcode, DavQLExpression *expr, va_list ap) {
     if(!expr) {
         return 0;
     }
@@ -219,7 +312,17 @@
             cmd.type = DAVQL_CMD_RES_IDENTIFIER;
             if(propertyname.length > 0) {
                 cmd.type = DAVQL_CMD_PROP_IDENTIFIER;
-                if(identifier2propname(a, src, &cmd.data.property)) {
+                char *ns;
+                char *name;
+                dav_get_property_namespace(
+                        ctx,
+                        sstrdup_a(a, src).ptr,
+                        &ns,
+                        &name);
+                if(ns && name) {
+                    cmd.data.property.ns = ns;
+                    cmd.data.property.name = name;
+                } else {
                     // error
                     return -1;
                 }
@@ -253,27 +356,29 @@
             break;
         }
         case DAVQL_UNARY: {
-            numcmd += add_cmd(a, bcode, expr->left, ap);
+            numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
             switch(expr->op) {
                 case DAVQL_ADD: {
-                    cmd.type = DAVQL_CMD_OP_UNARY_ADD;
+                    // noop
+                    numcmd = 0;
                     break;
                 }
                 case DAVQL_SUB: {
                     cmd.type = DAVQL_CMD_OP_UNARY_SUB;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
                 case DAVQL_NEG: {
                     cmd.type = DAVQL_CMD_OP_UNARY_NEG;
+                    ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
                 }
             }
-            ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
             break;
         }
         case DAVQL_BINARY: {
-            numcmd += add_cmd(a, bcode, expr->left, ap);
-            numcmd += add_cmd(a, bcode, expr->right, ap);
+            numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
+            numcmd += add_cmd(ctx, a, bcode, expr->right, ap);
             switch(expr->op) {
                 case DAVQL_ADD: {
                     cmd.type = DAVQL_CMD_OP_BINARY_ADD;
@@ -309,13 +414,13 @@
         }
         case DAVQL_LOGICAL: {
             if(expr->left && expr->right && expr->op != DAVQL_LOR) {
-                numcmd += add_cmd(a, bcode, expr->left, ap);
-                numcmd += add_cmd(a, bcode, expr->right, ap);
+                numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
+                numcmd += add_cmd(ctx, a, bcode, expr->right, ap);
             }
             
             switch(expr->op) {
                 case DAVQL_NOT: {
-                    numcmd += add_cmd(a, bcode, expr->left, ap);
+                    numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
                     cmd.type = DAVQL_CMD_OP_LOGICAL_NOT;
                     ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     break;
@@ -326,13 +431,13 @@
                     break;
                 }
                 case DAVQL_LOR: {
-                    int nleft = add_cmd(a, bcode, expr->left, ap);
+                    int nleft = add_cmd(ctx, a, bcode, expr->left, ap);
                     
                     cmd.type = DAVQL_CMD_OP_LOGICAL_OR_L;
                     DavQLCmd *or_l = (DavQLCmd*)(bcode->space + bcode->pos);
                     ucx_buffer_write(&cmd, sizeof(cmd), 1, bcode);
                     
-                    int nright = add_cmd(a, bcode, expr->right, ap);
+                    int nright = add_cmd(ctx, a, bcode, expr->right, ap);
                     or_l->data.integer = nright + 1;
                     
                     cmd.type = DAVQL_CMD_OP_LOGICAL_OR;
@@ -393,7 +498,7 @@
         case DAVQL_FUNCCALL: {
             switch(expr->op) {
                 case DAVQL_CALL: {
-                    int nright = add_cmd(a, bcode, expr->right, ap);
+                    int nright = add_cmd(ctx, a, bcode, expr->right, ap);
                     // TODO: count args
                     DavQLExpression *funcid = expr->left;
                     if(!funcid && funcid->type != DAVQL_IDENTIFIER) {
@@ -417,8 +522,8 @@
                 }
                 case DAVQL_ARGLIST: {
                     numcmd = 0;
-                    numcmd += add_cmd(a, bcode, expr->left, ap);
-                    numcmd += add_cmd(a, bcode, expr->right, ap);
+                    numcmd += add_cmd(ctx, a, bcode, expr->left, ap);
+                    numcmd += add_cmd(ctx, a, bcode, expr->right, ap);
                     break;
                 }
             }
@@ -428,13 +533,13 @@
     return numcmd;
 }
 
-UcxBuffer* dav_compile_expr(UcxAllocator *a, DavQLExpression *lexpr, va_list ap) {
+UcxBuffer* dav_compile_expr(DavContext *ctx, UcxAllocator *a, DavQLExpression *lexpr, va_list ap) {
     UcxBuffer *bcode = ucx_buffer_new(NULL, 512, UCX_BUFFER_AUTOEXTEND);
     if(!bcode) {
         return NULL;
     }
     
-    if(add_cmd(a, bcode, lexpr, ap) <= 0) {
+    if(add_cmd(ctx, a, bcode, lexpr, ap) <= 0) {
         ucx_buffer_free(bcode);
         return NULL;
     }
@@ -678,15 +783,15 @@
         }
     }
     
-    for(int i=0;i<stpos;i++) {
-        DavQLStackObj obj = stack[i];
-        if(obj.type == 0) {
-            printf("stack: int=%lld\n", obj.data.integer);
-        } else {
-            printf("stack: string=\"%.*s\"\n", obj.length, obj.data.string);
-        }
+    int ret = 0;
+    if(stpos == 1) {
+        *result = stack[0];
+    } else {
+        ret = -1;
     }
-    return 0;
+    free(stack);
+    
+    return ret;
 }
 
 

mercurial