# HG changeset patch # User Mike Becker # Date 1429269118 -7200 # Node ID 8ed7d8df6427f93b03f4f29fd292064d14ca15ba # Parent 8822f7c08843347e50c9eaec3b6385f0b884eb2e simplified with clause parsing + added order by to data structure and debugger (TODO: implement) diff -r 8822f7c08843 -r 8ed7d8df6427 libidav/davqlparser.c --- 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); } diff -r 8822f7c08843 -r 8ed7d8df6427 libidav/davqlparser.h --- 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 NULL for SET queries and may be NULL + * if the result doesn't need to be sorted. + */ + UcxList* orderby; + /** * The recursion depth for the statement. * Defaults to 1. */