427 #define dqlsec_malloc(stmt, ptr, type) ptr = malloc(sizeof(type)); \ |
427 #define dqlsec_malloc(stmt, ptr, type) ptr = malloc(sizeof(type)); \ |
428 dqlsec_alloc_failed(ptr, stmt); |
428 dqlsec_alloc_failed(ptr, stmt); |
429 #define dqlsec_mallocz(stmt, ptr, type) ptr = calloc(1, sizeof(type)); \ |
429 #define dqlsec_mallocz(stmt, ptr, type) ptr = calloc(1, sizeof(type)); \ |
430 dqlsec_alloc_failed(ptr, stmt); |
430 dqlsec_alloc_failed(ptr, stmt); |
431 |
431 |
|
432 #define dqlsec_list_append(stmt, list, data) \ |
|
433 { \ |
|
434 UcxList *_dqlsecbak_ = list; \ |
|
435 list = ucx_list_append(list, data); \ |
|
436 if (!list) { \ |
|
437 (stmt)->errorcode = DAVQL_ERROR_OUT_OF_MEMORY; \ |
|
438 list = _dqlsecbak_; \ |
|
439 } \ |
|
440 } |
432 |
441 |
433 // special symbols are single tokens - the % sign MUST NOT be a special symbol |
442 // special symbols are single tokens - the % sign MUST NOT be a special symbol |
434 static const char *special_token_symbols = ",()+-*/&|^~=!<>"; |
443 static const char *special_token_symbols = ",()+-*/&|^~=!<>"; |
435 |
444 |
436 static _Bool iskeyword(DavQLToken *token) { |
445 static _Bool iskeyword(DavQLToken *token) { |
501 token->tokenclass = DAVQL_TOKEN_INVALID; |
510 token->tokenclass = DAVQL_TOKEN_INVALID; |
502 } |
511 } |
503 } |
512 } |
504 |
513 |
505 |
514 |
506 return ucx_list_append(tokenlist, token); |
515 UcxList *ret = ucx_list_append(tokenlist, token); |
|
516 if (ret) { |
|
517 return ret; |
|
518 } else { |
|
519 ucx_list_free(tokenlist); |
|
520 return NULL; |
|
521 } |
507 } |
522 } |
508 |
523 |
509 static UcxList* dav_parse_tokenize(sstr_t src) { |
524 static UcxList* dav_parse_tokenize(sstr_t src) { |
510 #define alloc_token token = malloc(sizeof(DavQLToken));\ |
525 #define alloc_token token = malloc(sizeof(DavQLToken));\ |
511 if(!token) {ucx_list_free(tokens); return NULL;} |
526 if(!token) {ucx_list_free(tokens); return NULL;} |
|
527 #define add_token tokens = dav_parse_add_token(tokens, token); \ |
|
528 if(!tokens) {return NULL;} |
512 UcxList *tokens = NULL; |
529 UcxList *tokens = NULL; |
513 |
530 |
514 DavQLToken *token = NULL; |
531 DavQLToken *token = NULL; |
515 char insequence = '\0'; |
532 char insequence = '\0'; |
516 for (size_t i = 0 ; i < src.length ; i++) { |
533 for (size_t i = 0 ; i < src.length ; i++) { |
523 token->value.length += 3; |
540 token->value.length += 3; |
524 i += 2; |
541 i += 2; |
525 } else { |
542 } else { |
526 // add quoted token to list |
543 // add quoted token to list |
527 token->value.length++; |
544 token->value.length++; |
528 tokens = dav_parse_add_token(tokens, token); |
545 add_token |
529 token = NULL; |
546 token = NULL; |
530 insequence = '\0'; |
547 insequence = '\0'; |
531 } |
548 } |
532 } else if (insequence == '\0') { |
549 } else if (insequence == '\0') { |
533 insequence = src.ptr[i]; |
550 insequence = src.ptr[i]; |
534 // always create new token for quoted strings |
551 // always create new token for quoted strings |
535 if (token) { |
552 if (token) { |
536 tokens = dav_parse_add_token(tokens, token); |
553 add_token |
537 } |
554 } |
538 alloc_token |
555 alloc_token |
539 token->value.ptr = src.ptr + i; |
556 token->value.ptr = src.ptr + i; |
540 token->value.length = 1; |
557 token->value.length = 1; |
541 } else { |
558 } else { |
545 } else if (insequence) { |
562 } else if (insequence) { |
546 token->value.length++; |
563 token->value.length++; |
547 } else if (isspace(src.ptr[i])) { |
564 } else if (isspace(src.ptr[i])) { |
548 // add token before spaces to list (if any) |
565 // add token before spaces to list (if any) |
549 if (token) { |
566 if (token) { |
550 tokens = dav_parse_add_token(tokens, token); |
567 add_token |
551 token = NULL; |
568 token = NULL; |
552 } |
569 } |
553 } else if (strchr(special_token_symbols, src.ptr[i])) { |
570 } else if (strchr(special_token_symbols, src.ptr[i])) { |
554 // add token before special symbol to list (if any) |
571 // add token before special symbol to list (if any) |
555 if (token) { |
572 if (token) { |
556 tokens = dav_parse_add_token(tokens, token); |
573 add_token |
557 token = NULL; |
574 token = NULL; |
558 } |
575 } |
559 // add special symbol as single token to list |
576 // add special symbol as single token to list |
560 alloc_token |
577 alloc_token |
561 token->value.ptr = src.ptr + i; |
578 token->value.ptr = src.ptr + i; |
562 token->value.length = 1; |
579 token->value.length = 1; |
563 tokens = dav_parse_add_token(tokens, token); |
580 add_token |
564 // set tokenizer ready to read more tokens |
581 // set tokenizer ready to read more tokens |
565 token = NULL; |
582 token = NULL; |
566 } else { |
583 } else { |
567 // if this is a new token, create memory for it |
584 // if this is a new token, create memory for it |
568 if (!token) { |
585 if (!token) { |
574 token->value.length++; |
591 token->value.length++; |
575 } |
592 } |
576 } |
593 } |
577 |
594 |
578 if (token) { |
595 if (token) { |
579 tokens = dav_parse_add_token(tokens, token); |
596 add_token |
580 } |
597 } |
581 |
598 |
582 alloc_token |
599 alloc_token |
583 token->tokenclass = DAVQL_TOKEN_END; |
600 token->tokenclass = DAVQL_TOKEN_END; |
584 token->value = S(""); |
601 token->value = S(""); |
585 return ucx_list_append(tokens, token); |
602 UcxList *ret = ucx_list_append(tokens, token); |
|
603 if (ret) { |
|
604 return ret; |
|
605 } else { |
|
606 ucx_list_free(tokens); |
|
607 return NULL; |
|
608 } |
586 #undef alloc_token |
609 #undef alloc_token |
|
610 #undef add_token |
587 } |
611 } |
588 |
612 |
589 static void dav_free_expression(DavQLExpression *expr) { |
613 static void dav_free_expression(DavQLExpression *expr) { |
590 if (expr) { |
614 if (expr) { |
591 if (expr->left) { |
615 if (expr->left) { |
966 DavQLField *field; |
990 DavQLField *field; |
967 dqlsec_malloc(stmt, field, DavQLField); |
991 dqlsec_malloc(stmt, field, DavQLField); |
968 dqlsec_mallocz(stmt, field->expr, DavQLExpression); |
992 dqlsec_mallocz(stmt, field->expr, DavQLExpression); |
969 field->expr->type = DAVQL_IDENTIFIER; |
993 field->expr->type = DAVQL_IDENTIFIER; |
970 field->expr->srctext = field->name = token_sstr(token); |
994 field->expr->srctext = field->name = token_sstr(token); |
971 stmt->fields = ucx_list_append(stmt->fields, field); |
995 dqlsec_list_append(stmt, stmt->fields, field); |
972 return 1; |
996 return 1; |
973 } |
997 } |
974 |
998 |
975 // RULE: "*", {",", NamedExpression} |
999 // RULE: "*", {",", NamedExpression} |
976 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) { |
1000 if (token_is(token, DAVQL_TOKEN_OPERATOR) && tokenvalue_is(token, "*")) { |
977 DavQLField *field; |
1001 DavQLField *field; |
978 dqlsec_malloc(stmt, field, DavQLField); |
1002 dqlsec_malloc(stmt, field, DavQLField); |
979 dqlsec_mallocz(stmt, field->expr, DavQLExpression); |
1003 dqlsec_mallocz(stmt, field->expr, DavQLExpression); |
980 field->expr->type = DAVQL_IDENTIFIER; |
1004 field->expr->type = DAVQL_IDENTIFIER; |
981 field->expr->srctext = field->name = token_sstr(token); |
1005 field->expr->srctext = field->name = token_sstr(token); |
982 stmt->fields = ucx_list_append(stmt->fields, field); |
1006 dqlsec_list_append(stmt, stmt->fields, field); |
983 |
1007 |
984 int total_consumed = 0; |
1008 int total_consumed = 0; |
985 int consumed = 1; |
1009 int consumed = 1; |
986 |
1010 |
987 do { |
1011 do { |
994 consumed = dav_parse_named_field(stmt, token, &localfield); |
1018 consumed = dav_parse_named_field(stmt, token, &localfield); |
995 if (!stmt->errorcode && consumed) { |
1019 if (!stmt->errorcode && consumed) { |
996 DavQLField *field; |
1020 DavQLField *field; |
997 dqlsec_malloc(stmt, field, DavQLField); |
1021 dqlsec_malloc(stmt, field, DavQLField); |
998 memcpy(field, &localfield, sizeof(DavQLField)); |
1022 memcpy(field, &localfield, sizeof(DavQLField)); |
999 stmt->fields = ucx_list_append(stmt->fields, field); |
1023 dqlsec_list_append(stmt, stmt->fields, field); |
1000 } |
1024 } |
1001 } else { |
1025 } else { |
1002 consumed = 0; |
1026 consumed = 0; |
1003 } |
1027 } |
1004 } while (consumed > 0); |
1028 } while (consumed > 0); |
1015 consumed = dav_parse_named_field(stmt, token, &localfield); |
1039 consumed = dav_parse_named_field(stmt, token, &localfield); |
1016 if (consumed) { |
1040 if (consumed) { |
1017 DavQLField *field; |
1041 DavQLField *field; |
1018 dqlsec_malloc(stmt, field, DavQLField); |
1042 dqlsec_malloc(stmt, field, DavQLField); |
1019 memcpy(field, &localfield, sizeof(DavQLField)); |
1043 memcpy(field, &localfield, sizeof(DavQLField)); |
1020 stmt->fields = ucx_list_append(stmt->fields, field); |
1044 dqlsec_list_append(stmt, stmt->fields, field); |
1021 token = ucx_list_get(token, consumed); |
1045 token = ucx_list_get(token, consumed); |
1022 total_consumed += consumed; |
1046 total_consumed += consumed; |
1023 } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER) |
1047 } else if (token_is(token, DAVQL_TOKEN_IDENTIFIER) |
1024 // look ahead, if the field is JUST the identifier |
1048 // look ahead, if the field is JUST the identifier |
1025 && (token_is(token->next, DAVQL_TOKEN_COMMA) || |
1049 && (token_is(token->next, DAVQL_TOKEN_COMMA) || |
1028 DavQLField *field; |
1052 DavQLField *field; |
1029 dqlsec_malloc(stmt, field, DavQLField); |
1053 dqlsec_malloc(stmt, field, DavQLField); |
1030 dqlsec_mallocz(stmt, field->expr, DavQLExpression); |
1054 dqlsec_mallocz(stmt, field->expr, DavQLExpression); |
1031 field->expr->type = DAVQL_IDENTIFIER; |
1055 field->expr->type = DAVQL_IDENTIFIER; |
1032 field->expr->srctext = field->name = token_sstr(token); |
1056 field->expr->srctext = field->name = token_sstr(token); |
1033 stmt->fields = ucx_list_append(stmt->fields, field); |
1057 dqlsec_list_append(stmt, stmt->fields, field); |
1034 |
1058 |
1035 consumed = 1; |
1059 consumed = 1; |
1036 total_consumed++; |
1060 total_consumed++; |
1037 token = token->next; |
1061 token = token->next; |
1038 |
1062 |
1412 total_consumed += consumed; |
1436 total_consumed += consumed; |
1413 |
1437 |
1414 DavQLOrderCriterion *criterion; |
1438 DavQLOrderCriterion *criterion; |
1415 dqlsec_malloc(stmt, criterion, DavQLOrderCriterion); |
1439 dqlsec_malloc(stmt, criterion, DavQLOrderCriterion); |
1416 memcpy(criterion, &crit, sizeof(DavQLOrderCriterion)); |
1440 memcpy(criterion, &crit, sizeof(DavQLOrderCriterion)); |
1417 stmt->orderby = ucx_list_append(stmt->orderby, criterion); |
1441 dqlsec_list_append(stmt, stmt->orderby, criterion); |
1418 |
1442 |
1419 if (token_is(token, DAVQL_TOKEN_COMMA)) { |
1443 if (token_is(token, DAVQL_TOKEN_COMMA)) { |
1420 total_consumed++; |
1444 total_consumed++; |
1421 token = token->next; |
1445 token = token->next; |
1422 } else { |
1446 } else { |
1553 stmt->depth = 1; |
1577 stmt->depth = 1; |
1554 |
1578 |
1555 // save trimmed source text |
1579 // save trimmed source text |
1556 stmt->srctext = sstrtrim(srctext); |
1580 stmt->srctext = sstrtrim(srctext); |
1557 |
1581 |
1558 // tokenization |
1582 if (stmt->srctext.length) { |
1559 UcxList* tokens = dav_parse_tokenize(stmt->srctext); |
1583 // tokenization |
1560 |
1584 UcxList* tokens = dav_parse_tokenize(stmt->srctext); |
1561 if (tokens) { |
1585 |
1562 // use first token to determine query type |
1586 if (tokens) { |
1563 |
1587 // use first token to determine query type |
1564 if (tokenvalue_is(tokens, "select")) { |
1588 |
1565 dav_parse_select_statement(stmt, tokens->next); |
1589 if (tokenvalue_is(tokens, "select")) { |
1566 } else if (tokenvalue_is(tokens, "set")) { |
1590 dav_parse_select_statement(stmt, tokens->next); |
1567 dav_parse_set_statement(stmt, tokens->next); |
1591 } else if (tokenvalue_is(tokens, "set")) { |
|
1592 dav_parse_set_statement(stmt, tokens->next); |
|
1593 } else { |
|
1594 stmt->type = DAVQL_ERROR; |
|
1595 stmt->errorcode = DAVQL_ERROR_INVALID; |
|
1596 stmt->errormessage = strdup(_error_invalid); |
|
1597 } |
|
1598 |
|
1599 // free token data |
|
1600 UCX_FOREACH(token, tokens) { |
|
1601 free(token->data); |
|
1602 } |
|
1603 ucx_list_free(tokens); |
1568 } else { |
1604 } else { |
1569 stmt->type = DAVQL_ERROR; |
1605 stmt->errorcode = DAVQL_ERROR_OUT_OF_MEMORY; |
1570 stmt->errorcode = DAVQL_ERROR_INVALID; |
1606 } |
1571 stmt->errormessage = strdup(_error_invalid); |
|
1572 } |
|
1573 |
|
1574 // free token data |
|
1575 UCX_FOREACH(token, tokens) { |
|
1576 free(token->data); |
|
1577 } |
|
1578 ucx_list_free(tokens); |
|
1579 } else { |
1607 } else { |
1580 stmt->type = DAVQL_ERROR; |
1608 stmt->type = DAVQL_ERROR; |
1581 stmt->errorcode = DAVQL_ERROR_INVALID; |
1609 stmt->errorcode = DAVQL_ERROR_INVALID; |
1582 stmt->errormessage = strdup(_error_invalid); |
1610 stmt->errormessage = strdup(_error_invalid); |
1583 } |
1611 } |