From 75f6f75da38b5f7e97dfafef185d73da0ab7b91a Mon Sep 17 00:00:00 2001 From: ejurgensen Date: Mon, 7 Mar 2022 23:31:52 +0100 Subject: [PATCH] [smartpl] Fix bison parser regression, missing "starts with" syntax Also adds "ends with" syntax just for good measure. Closes #1432 --- README_SMARTPL.md | 6 +++--- src/parsers/smartpl_lexer.l | 2 ++ src/parsers/smartpl_parser.y | 10 ++++++++-- 3 files changed, 13 insertions(+), 5 deletions(-) diff --git a/README_SMARTPL.md b/README_SMARTPL.md index e6752fdc..fcffad4c 100644 --- a/README_SMARTPL.md +++ b/README_SMARTPL.md @@ -50,14 +50,14 @@ Where valid field-names (with their types) are: * `random` (special) Valid operators include: -* `is`, `includes`, `starts with` (string) +* `is`, `includes`, `starts with`, `ends with` (string) * `>`, `<`, `<=`, `>=`, `=` (int) * `after`, `before` (date) * `is` (enumeration) The `is` operator must exactly match the field value, while the `includes` operator matches a substring. -The `starts with` operator matches, if the value starts with the given prefix. -All three matches are case-insensitive. +The `starts with` operator matches, if the value starts with the given prefix, +and `ends with` matches the opposite. All these matches are case-insensitive. Valid operands include: * "string value" (string) diff --git a/src/parsers/smartpl_lexer.l b/src/parsers/smartpl_lexer.l index 8626cde6..43fd4a93 100644 --- a/src/parsers/smartpl_lexer.l +++ b/src/parsers/smartpl_lexer.l @@ -138,6 +138,8 @@ after { return (yylval->ival = SMARTPL_T_AFTER); } is { return (yylval->ival = SMARTPL_T_IS); } includes { return (yylval->ival = SMARTPL_T_INCLUDES); } +starts\ with { return (yylval->ival = SMARTPL_T_STARTSWITH); } +ends\ with { return (yylval->ival = SMARTPL_T_ENDSWITH); } = { return (yylval->ival = SMARTPL_T_EQUAL); } \<= { return (yylval->ival = SMARTPL_T_LESSEQUAL); } \< { return (yylval->ival = SMARTPL_T_LESS); } diff --git a/src/parsers/smartpl_parser.y b/src/parsers/smartpl_parser.y index dbef20ce..40801e1e 100644 --- a/src/parsers/smartpl_parser.y +++ b/src/parsers/smartpl_parser.y @@ -301,10 +301,10 @@ static void sql_append_recursive(struct smartpl_result *result, struct result_pa break; case SQL_APPEND_OPERATOR_LIKE: sql_from_ast(result, part, a->l); - sql_append(result, part, " %s '%%", is_not ? op_not : op); + sql_append(result, part, " %s '%s", is_not ? op_not : op, a->type == SMARTPL_T_STARTSWITH ? "" : "%"); sql_like_escape((char **)(&a->r->data), &escape_char); sql_from_ast(result, part, a->r); - sql_append(result, part, "%%'"); + sql_append(result, part, "%s'", a->type == SMARTPL_T_ENDSWITH ? "" : "%"); if (escape_char) sql_append(result, part, " ESCAPE '%c'", escape_char); break; @@ -379,6 +379,8 @@ static void sql_from_ast(struct smartpl_result *result, struct result_part *part case SMARTPL_T_IS: sql_append_recursive(result, part, a, "=", "!=", is_not, SQL_APPEND_OPERATOR_STR); break; case SMARTPL_T_INCLUDES: + case SMARTPL_T_STARTSWITH: + case SMARTPL_T_ENDSWITH: sql_append_recursive(result, part, a, "LIKE", "NOT LIKE", is_not, SQL_APPEND_OPERATOR_LIKE); break; case SMARTPL_T_BEFORE: sql_append_recursive(result, part, a, "<", ">=", is_not, SQL_APPEND_OPERATOR); break; @@ -517,6 +519,8 @@ static int result_set(struct smartpl_result *result, char *title, struct ast *cr set to the token value by the lexer. */ %token SMARTPL_T_IS %token SMARTPL_T_INCLUDES +%token SMARTPL_T_STARTSWITH +%token SMARTPL_T_ENDSWITH %token SMARTPL_T_EQUAL %token SMARTPL_T_LESS %token SMARTPL_T_LESSEQUAL @@ -629,6 +633,8 @@ limit: SMARTPL_T_LIMIT SMARTPL_T_NUM { $$ = ast_int(SMART strbool: SMARTPL_T_IS | SMARTPL_T_INCLUDES +| SMARTPL_T_STARTSWITH +| SMARTPL_T_ENDSWITH ; intbool: SMARTPL_T_EQUAL