diff -r 451607eeff05 -r 246c50447ebf libidav/davqlparser.c --- a/libidav/davqlparser.c Fri May 29 09:48:10 2015 +0200 +++ b/libidav/davqlparser.c Fri May 29 10:15:12 2015 +0200 @@ -390,6 +390,7 @@ #define _error_invalid_logical_op "invalid logical operator " _error_context #define _error_invalid_fmtspec "invalid format specifier " _error_context #define _error_invalid_string "string expected " _error_context +#define _error_invalid_order_criterion "invalid order criterion " _error_context #define token_sstr(token) (((DavQLToken*)(token)->data)->value) @@ -1317,11 +1318,72 @@ return total_consumed; } +static int dav_parse_order_crit(DavQLStatement *stmt, UcxList *token, + DavQLOrderCriterion *crit) { + + // RULE: (Identifier | Number), [" asc"|" desc"]; + DavQLExpression expr; + memset(&expr, 0, sizeof(DavQLExpression)); + int consumed = dav_parse_expression(stmt, token, &expr); + if (stmt->errorcode || !consumed) { + return 0; + } + + if (expr.type != DAVQL_IDENTIFIER && expr.type != DAVQL_NUMBER) { + dav_error_in_context(DAVQL_ERROR_INVALID_ORDER_CRITERION, + _error_invalid_order_criterion, stmt, token); + return 0; + } + + crit->column = malloc(sizeof(DavQLExpression)); + memcpy(crit->column, &expr, sizeof(DavQLExpression)); + + token = ucx_list_get(token, consumed); + if (token_is(token, DAVQL_TOKEN_KEYWORD) && ( + tokenvalue_is(token, "asc") || tokenvalue_is(token, "desc"))) { + + crit->descending = tokenvalue_is(token, "desc"); + + return consumed+1; + } else { + crit->descending = 0; + return consumed; + } +} + static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) { + int total_consumed = 0, consumed; + + DavQLOrderCriterion crit; + // RULE: OrderByCriterion, {",", OrderByCriterion}; - // OrderByCriterion = (Identifier | Number), [" asc"|" desc"]; - return 0; + do { + consumed = dav_parse_order_crit(stmt, token, &crit); + if (stmt->errorcode) { + return 0; + } + if (!consumed) { + dav_error_in_context(DAVQL_ERROR_MISSING_EXPR, _error_missing_expr, + stmt, token); + return 0; + } + token = ucx_list_get(token, consumed); + total_consumed += consumed; + + DavQLOrderCriterion *criterion = malloc(sizeof(DavQLOrderCriterion)); + memcpy(criterion, &crit, sizeof(DavQLOrderCriterion)); + stmt->orderby = ucx_list_append(stmt->orderby, criterion); + + if (token_is(token, DAVQL_TOKEN_COMMA)) { + total_consumed++; + token = token->next; + } else { + consumed = 0; + } + } while (consumed); + + return total_consumed; } /**