388 #define _error_invalid_expr "invalid expression " _error_context |
388 #define _error_invalid_expr "invalid expression " _error_context |
389 #define _error_invalid_unary_op "invalid unary operator " _error_context |
389 #define _error_invalid_unary_op "invalid unary operator " _error_context |
390 #define _error_invalid_logical_op "invalid logical operator " _error_context |
390 #define _error_invalid_logical_op "invalid logical operator " _error_context |
391 #define _error_invalid_fmtspec "invalid format specifier " _error_context |
391 #define _error_invalid_fmtspec "invalid format specifier " _error_context |
392 #define _error_invalid_string "string expected " _error_context |
392 #define _error_invalid_string "string expected " _error_context |
|
393 #define _error_invalid_order_criterion "invalid order criterion " _error_context |
393 |
394 |
394 #define token_sstr(token) (((DavQLToken*)(token)->data)->value) |
395 #define token_sstr(token) (((DavQLToken*)(token)->data)->value) |
395 |
396 |
396 static void dav_error_in_context(int errorcode, const char *errormsg, |
397 static void dav_error_in_context(int errorcode, const char *errormsg, |
397 DavQLStatement *stmt, UcxList *token) { |
398 DavQLStatement *stmt, UcxList *token) { |
1315 } |
1316 } |
1316 |
1317 |
1317 return total_consumed; |
1318 return total_consumed; |
1318 } |
1319 } |
1319 |
1320 |
|
1321 static int dav_parse_order_crit(DavQLStatement *stmt, UcxList *token, |
|
1322 DavQLOrderCriterion *crit) { |
|
1323 |
|
1324 // RULE: (Identifier | Number), [" asc"|" desc"]; |
|
1325 DavQLExpression expr; |
|
1326 memset(&expr, 0, sizeof(DavQLExpression)); |
|
1327 int consumed = dav_parse_expression(stmt, token, &expr); |
|
1328 if (stmt->errorcode || !consumed) { |
|
1329 return 0; |
|
1330 } |
|
1331 |
|
1332 if (expr.type != DAVQL_IDENTIFIER && expr.type != DAVQL_NUMBER) { |
|
1333 dav_error_in_context(DAVQL_ERROR_INVALID_ORDER_CRITERION, |
|
1334 _error_invalid_order_criterion, stmt, token); |
|
1335 return 0; |
|
1336 } |
|
1337 |
|
1338 crit->column = malloc(sizeof(DavQLExpression)); |
|
1339 memcpy(crit->column, &expr, sizeof(DavQLExpression)); |
|
1340 |
|
1341 token = ucx_list_get(token, consumed); |
|
1342 if (token_is(token, DAVQL_TOKEN_KEYWORD) && ( |
|
1343 tokenvalue_is(token, "asc") || tokenvalue_is(token, "desc"))) { |
|
1344 |
|
1345 crit->descending = tokenvalue_is(token, "desc"); |
|
1346 |
|
1347 return consumed+1; |
|
1348 } else { |
|
1349 crit->descending = 0; |
|
1350 return consumed; |
|
1351 } |
|
1352 } |
|
1353 |
1320 static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) { |
1354 static int dav_parse_orderby_clause(DavQLStatement *stmt, UcxList *token) { |
1321 |
1355 |
|
1356 int total_consumed = 0, consumed; |
|
1357 |
|
1358 DavQLOrderCriterion crit; |
|
1359 |
1322 // RULE: OrderByCriterion, {",", OrderByCriterion}; |
1360 // RULE: OrderByCriterion, {",", OrderByCriterion}; |
1323 // OrderByCriterion = (Identifier | Number), [" asc"|" desc"]; |
1361 do { |
1324 return 0; |
1362 consumed = dav_parse_order_crit(stmt, token, &crit); |
|
1363 if (stmt->errorcode) { |
|
1364 return 0; |
|
1365 } |
|
1366 if (!consumed) { |
|
1367 dav_error_in_context(DAVQL_ERROR_MISSING_EXPR, _error_missing_expr, |
|
1368 stmt, token); |
|
1369 return 0; |
|
1370 } |
|
1371 token = ucx_list_get(token, consumed); |
|
1372 total_consumed += consumed; |
|
1373 |
|
1374 DavQLOrderCriterion *criterion = malloc(sizeof(DavQLOrderCriterion)); |
|
1375 memcpy(criterion, &crit, sizeof(DavQLOrderCriterion)); |
|
1376 stmt->orderby = ucx_list_append(stmt->orderby, criterion); |
|
1377 |
|
1378 if (token_is(token, DAVQL_TOKEN_COMMA)) { |
|
1379 total_consumed++; |
|
1380 token = token->next; |
|
1381 } else { |
|
1382 consumed = 0; |
|
1383 } |
|
1384 } while (consumed); |
|
1385 |
|
1386 return total_consumed; |
1325 } |
1387 } |
1326 |
1388 |
1327 /** |
1389 /** |
1328 * Parser of a get statement. |
1390 * Parser of a get statement. |
1329 * @param stmt the statement object that shall contain the syntax tree |
1391 * @param stmt the statement object that shall contain the syntax tree |