From a722215bfbfbc620abe819fb97cc0219f1b9237f Mon Sep 17 00:00:00 2001 From: Aleksandr Cupacenko Date: Sat, 14 Sep 2024 15:08:46 +0300 Subject: [PATCH] stream_processor: fix operator precedence for logical operations Signed-off-by: Aleksandr Cupacenko revert definition removal Signed-off-by: Aleksandr Cupacenko add operator precedence unit tests correct precedencer order add not_and precedent check correct function references ai suggestion --- src/stream_processor/parser/sql.y | 8 +++++-- tests/internal/include/sp_cb_functions.h | 30 ++++++++++++++++++++++++ tests/internal/include/sp_select_keys.h | 20 ++++++++++++++++ 3 files changed, 56 insertions(+), 2 deletions(-) diff --git a/src/stream_processor/parser/sql.y b/src/stream_processor/parser/sql.y index 866f95cc023..eb6ceec03a7 100644 --- a/src/stream_processor/parser/sql.y +++ b/src/stream_processor/parser/sql.y @@ -1,4 +1,4 @@ -%name-prefix="flb_sp_" // replace with %define api.prefix {flb_sp_} +%name-prefix "flb_sp_" // replace with %define api.prefix {flb_sp_} %define api.pure full %define parse.error verbose %parse-param { struct flb_sp_cmd *cmd }; @@ -98,6 +98,10 @@ void yyerror(struct flb_sp_cmd *cmd, const char *query, void *scanner, const cha %type aggregate_func %type COUNT AVG SUM MAX MIN TIMESERIES_FORECAST +/* Define operator precedence and associativity for logical operations in conditions */ +%left OR // Lowest precedence for OR +%left AND // Middle precedence for AND +%right NOT // Highest precedence for NOT %destructor { flb_free ($$); } IDENTIFIER @@ -293,7 +297,7 @@ select: SELECT keys FROM source window where groupby limit ';' $$ = flb_sp_cmd_operation(cmd, $2, NULL, FLB_EXP_PAR); } | - NOT condition + NOT condition %prec NOT { $$ = flb_sp_cmd_operation(cmd, $2, NULL, FLB_EXP_NOT); } diff --git a/tests/internal/include/sp_cb_functions.h b/tests/internal/include/sp_cb_functions.h index 346a4bb7e12..bc106db695a 100644 --- a/tests/internal/include/sp_cb_functions.h +++ b/tests/internal/include/sp_cb_functions.h @@ -206,6 +206,36 @@ static void cb_record_not_contains(int id, struct task_check *check, TEST_CHECK(ret == 0); } +static void cb_select_and_or_precedence(int id, struct task_check *check, + char *buf, size_t size) +{ + int ret; + + /* Expect all 11 rows */ + ret = mp_count_rows(buf, size); + TEST_CHECK_(ret == 11, "expected 11 rows but got %d", ret); +} + +static void cb_select_not_or_precedence(int id, struct task_check *check, + char *buf, size_t size) +{ + int ret; + + /* Expect all 11 rows */ + ret = mp_count_rows(buf, size); + TEST_CHECK_(ret == 11, "expected 11 rows but got %d", ret); +} + +static void cb_select_not_and_precedence(int id, struct task_check *check, + char *buf, size_t size) +{ + int ret; + + /* Expect 0 rows */ + ret = mp_count_rows(buf, size); + TEST_CHECK_(ret == 0, "expected 0 rows but got %d", ret); +} + /* Callback functions to perform checks over results */ static void cb_select_sub_blue(int id, struct task_check *check, char *buf, size_t size) diff --git a/tests/internal/include/sp_select_keys.h b/tests/internal/include/sp_select_keys.h index ba3c809f3ad..f1b692a97d4 100644 --- a/tests/internal/include/sp_select_keys.h +++ b/tests/internal/include/sp_select_keys.h @@ -126,6 +126,26 @@ struct task_check select_keys_checks[] = { "SELECT id FROM TAG:'samples' WHERE @record.contains(x);", cb_record_not_contains, }, + + /* Operator precedence */ + { + 18, 0, 0, 0, + "and_or_precedence", + "SELECT id FROM STREAM:FLB WHERE false AND true OR true;", + cb_select_and_or_precedence, + }, + { + 19, 0, 0, 0, + "not_or_precedence", + "SELECT id FROM STREAM:FLB WHERE NOT true OR true;", + cb_select_not_or_precedence, + }, + { + 20, 0, 0, 0, + "not_and_precedence", + "SELECT id FROM STREAM:FLB WHERE NOT true AND false;", + cb_select_not_and_precedence, + }, }; #endif