simplified with clause parsing + added order by to data structure and debugger (TODO: implement)

Fri, 17 Apr 2015 13:11:58 +0200

author
Mike Becker <universe@uap-core.de>
date
Fri, 17 Apr 2015 13:11:58 +0200
changeset 95
8ed7d8df6427
parent 94
8822f7c08843
child 96
896022673e0e

simplified with clause parsing + added order by to data structure and debugger (TODO: implement)

libidav/davqlparser.c file | annotate | diff | comparison | revisions
libidav/davqlparser.h file | annotate | diff | comparison | revisions
--- a/libidav/davqlparser.c	Wed Apr 15 08:57:46 2015 +0200
+++ b/libidav/davqlparser.c	Fri Apr 17 13:11:58 2015 +0200
@@ -127,6 +127,19 @@
         printf("\nError code: %d\nError: %s\n",
             stmt->errorcode, stmt->errormessage);
     }
+    
+    // order by clause
+    printf("Order by: ");
+    if (stmt->orderby) {
+        UCX_FOREACH(crit, stmt->orderby) {
+            DavQLOrderCriterion *critdata = crit->data;
+            printf("%.*s %s%s", sfmtarg(critdata->column->srctext),
+                critdata->ascending ? "asc" : "desc",
+                crit->next ? ", " : "\n");
+        }
+    } else {
+        printf("nothing\n");
+    }
 }
 
 static int dav_debug_ql_expr_selected(DavQLExpression *expr) {
@@ -412,13 +425,26 @@
     stmt->errormessage = errormsg.ptr;
 }
 
+    
+#define _step_fieldlist_    10 // field list
+#define _step_FROM_         20 // FROM clause
+#define _step_expect_WWO_  530 // expecting WITH, WHERE or ORDER BY clause
+#define _step_WITH_         30 // WITH clause
+#define _step_expect_WO    540 // expecting WHERE or ORDER BY clause
+#define _step_WHERE_        40 // WHERE clause
+#define _step_expect_O     550 // expecting ORDER BY clause
+#define _step_expect_BY    551 // expecting the BY token for the ORDER BY clause
+#define _step_ORDER_BY_     50 // ORDER BY clause
+#define _step_end_         500 // expect end
+
 static int dav_parse_with_clause(DavQLStatement *stmt, UcxList *token) {
     sstr_t tokendata = *token_sstr(token);
+    
     /*
      * 0: key
      * 1: =
      * 2: value
-     * TODO: commas
+     * 3: comma or new clause
      */
     static int parsestate = 0;
 
@@ -446,7 +472,7 @@
         } else {
             keymask |= key;
         }
-        return 0;
+        return _step_WITH_; // continue parsing WITH clause
     case 1:
         if (sstrcmp(tokendata, S("="))) {
             stmt->errorcode = DAVQL_ERROR_UNEXPECTED_TOKEN;
@@ -455,7 +481,7 @@
         } else {
             parsestate = 2;
         }
-        return 0;
+        return _step_WITH_; // continue parsing WITH clause
     case 2:
         switch (key) {
         case 1: /* depth */
@@ -475,27 +501,44 @@
             }
             break;
         }
-        parsestate = 0;
-        return 1;
+        parsestate = 3;
+        return _step_WITH_; // continue parsing WITH clause
+    case 3:
+        // a with clause may be continued with a comma
+        // or another clause may follow
+        if (!sstrcmp(tokendata, S(","))) {
+            parsestate = 0; // reset clause parser
+            return _step_WITH_;
+        } else if (!sstrcasecmp(tokendata, S("where"))) {
+            return _step_WHERE_;
+        } else if (!sstrcasecmp(tokendata, S("order"))) {
+            return _step_expect_BY;
+        } else {
+            dav_parse_unexpected_token(stmt, token);
+            return 0;
+        }
     default:
-        return -1;
+        stmt->errorcode = DAVQL_ERROR_INVALID;
+        stmt->errormessage = strdup(_parser_state);
+        return 0;
     }
 }
 
+static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) {
+    // TODO: implement
+    
+    return _step_end_;
+}
+
+static void dav_free_order_criterion(DavQLOrderCriterion *crit) {
+    if (crit->column) { // do it null-safe though column is expected to be set
+        dav_free_expression(crit->column);
+    }
+    free(crit);
+}
+
 static void dav_parse_get_statement(DavQLStatement *stmt, UcxList *tokens) {
     stmt->type = DAVQL_GET;
-    
-#define _step_fieldlist_    10 // field list
-#define _step_FROM_         20 // FROM clause
-#define _step_expect_WWO_  530 // expecting WITH, WHERE or ORDER BY clause
-#define _step_comma_WITH_  531 // expecting comma for WITH clause
-#define _step_WITH_         30 // WITH clause
-#define _step_expect_WO    540 // expecting WHERE or ORDER BY clause
-#define _step_WHERE_        40 // WHERE clause
-#define _step_expect_O     550 // expecting ORDER BY clause
-#define _step_expect_BY    551 // expecting the BY token for the ORDER BY clause
-#define _step_ORDER_BY_     50 // ORDER BY clause
-#define _step_end_         500 // expect end
 
     int step = _step_fieldlist_;
     
@@ -542,19 +585,6 @@
                     sfmtarg(tokendata)).ptr;
             }
             break;
-        case _step_comma_WITH_:
-            // a with clause may be continued with a comma
-            // or another clause may follow
-            if (!sstrcmp(tokendata, S(","))) {
-                step = _step_WITH_;
-            } if (!sstrcasecmp(tokendata, S("where"))) {
-                step = _step_WHERE_;
-            } else if (!sstrcasecmp(tokendata, S("order"))) {
-                step = _step_expect_BY;
-            } else {
-                dav_parse_unexpected_token(stmt, token);
-            }
-            break;
         // field list
         case _step_fieldlist_: {
             _Bool fromkeyword = !sstrcasecmp(tokendata, S("from"));
@@ -598,13 +628,7 @@
         }
         // with clause
         case _step_WITH_: {
-            int withclause_result = dav_parse_with_clause(stmt, token);
-            if (withclause_result < 0) {
-                stmt->errorcode = DAVQL_ERROR_INVALID;
-                stmt->errormessage = strdup(_parser_state);
-            } else if (withclause_result > 0) {
-                step = _step_comma_WITH_;
-            }
+            step = dav_parse_with_clause(stmt, token);
             break;
         }
         // where clause
@@ -614,8 +638,7 @@
             break;
         // order by clause
         case _step_ORDER_BY_:
-            // TODO: implement
-            step = _step_end_;
+            step = dav_parse_orderby_clause(stmt, token);
             break;
         default:
             stmt->errorcode = DAVQL_ERROR_INVALID;
@@ -702,5 +725,9 @@
     if (stmt->errormessage) {
         free(stmt->errormessage);
     }
+    UCX_FOREACH(crit, stmt->orderby) {
+        dav_free_order_criterion(crit->data);
+    }
+    ucx_list_free(stmt->orderby);
     free(stmt);
 }
--- a/libidav/davqlparser.h	Wed Apr 15 08:57:46 2015 +0200
+++ b/libidav/davqlparser.h	Fri Apr 17 13:11:58 2015 +0200
@@ -82,7 +82,6 @@
     davqlexprtype_t type;
     /**
      * Operator.
-     * 
      */
     davqloperator_t op;
     /**
@@ -97,6 +96,20 @@
     DavQLExpression *right;
 };
 
+/**
+ * A tuple representing an order criterion.
+ */
+typedef struct {
+    /**
+     * The column.
+     */
+    DavQLExpression *column;
+    /**
+     * True, if the result shall be sorted ascending, false otherwise.
+     */
+    _Bool ascending;
+} DavQLOrderCriterion;
+
 
 /**
  * Query statement object.
@@ -203,6 +216,12 @@
      */
     DavQLExpression* where;
     /**
+     * The list of DavQLOrderCriterions.
+     * This is <code>NULL</code> for SET queries and may be <code>NULL</code>
+     * if the result doesn't need to be sorted.
+     */
+    UcxList* orderby;
+    /**
      * The recursion depth for the statement.
      * Defaults to 1.
      */

mercurial