From 9ecfa8e8f6fb2badba240d3355090a9eaa028025 Mon Sep 17 00:00:00 2001 From: Pedro Date: Tue, 7 Mar 2017 02:49:29 +0100 Subject: [PATCH] Allow function expressions to have variable length of parameters --- src/parser/bison_parser.y | 2 +- src/sql/Expr.cpp | 4 ++-- src/sql/Expr.h | 4 +++- test/queries/tpc-h-02.sql | 2 +- test/queries/tpc-h-09.sql | 2 +- test/select_tests.cpp | 39 +++++++++++++++++++++++++++++++++++++++ test/valid_queries.sql | 1 + 7 files changed, 48 insertions(+), 6 deletions(-) diff --git a/src/parser/bison_parser.y b/src/parser/bison_parser.y index 88d5e23..27c12c0 100644 --- a/src/parser/bison_parser.y +++ b/src/parser/bison_parser.y @@ -644,7 +644,7 @@ comp_expr: ; function_expr: - IDENTIFIER '(' opt_distinct expr ')' { $$ = Expr::makeFunctionRef($1, $4, $3); } + IDENTIFIER '(' opt_distinct expr_list ')' { $$ = Expr::makeFunctionRef($1, $4, $3); } ; column_name: diff --git a/src/sql/Expr.cpp b/src/sql/Expr.cpp index dab4cdf..9035884 100644 --- a/src/sql/Expr.cpp +++ b/src/sql/Expr.cpp @@ -79,10 +79,10 @@ namespace hsql { return e; } - Expr* Expr::makeFunctionRef(char* func_name, Expr* expr, bool distinct) { + Expr* Expr::makeFunctionRef(char* func_name, std::vector* exprList, bool distinct) { Expr* e = new Expr(kExprFunctionRef); e->name = func_name; - e->expr = expr; + e->exprList = exprList; e->distinct = distinct; return e; } diff --git a/src/sql/Expr.h b/src/sql/Expr.h index 9be9ed1..bd2b8d0 100644 --- a/src/sql/Expr.h +++ b/src/sql/Expr.h @@ -3,6 +3,7 @@ #include #include +#include namespace hsql { @@ -61,6 +62,7 @@ namespace hsql { Expr* expr; Expr* expr2; + std::vector* exprList; char* name; char* table; char* alias; @@ -107,7 +109,7 @@ namespace hsql { static Expr* makeColumnRef(char* table, char* name); - static Expr* makeFunctionRef(char* func_name, Expr* expr, bool distinct); + static Expr* makeFunctionRef(char* func_name, std::vector* exprList, bool distinct); static Expr* makePlaceholder(int id); }; diff --git a/test/queries/tpc-h-02.sql b/test/queries/tpc-h-02.sql index c40be73..5fd5b50 100644 --- a/test/queries/tpc-h-02.sql +++ b/test/queries/tpc-h-02.sql @@ -1,6 +1,6 @@ -- http://www.sqlserver-dba.com/2011/09/this-is-a-followup-on-my-earlier-post-of-sql-server-test-data-generation-testing-tools-i-had-some-requests-for-my-set-up-pr.html SELECT TOP 100 S_ACCTBAL, S_NAME, N_NAME, P_PARTKEY, P_MFGR, S_ADDRESS, S_PHONE, S_COMMENT -FROM PART, SUPPLIER, PARTSUPP, NATION, REGION +FROM "PART", SUPPLIER, PARTSUPP, NATION, REGION WHERE P_PARTKEY = PS_PARTKEY AND S_SUPPKEY = PS_SUPPKEY AND P_SIZE = 15 AND P_TYPE LIKE '%%BRASS' AND S_NATIONKEY = N_NATIONKEY AND N_REGIONKEY = R_REGIONKEY AND R_NAME = 'EUROPE' AND diff --git a/test/queries/tpc-h-09.sql b/test/queries/tpc-h-09.sql index a5856e0..bb9fd6f 100644 --- a/test/queries/tpc-h-09.sql +++ b/test/queries/tpc-h-09.sql @@ -2,7 +2,7 @@ SELECT NATION, O_YEAR, SUM(AMOUNT) AS SUM_PROFIT FROM (SELECT N_NAME AS NATION, datepart(yy, O_ORDERDATE) AS O_YEAR, L_EXTENDEDPRICE*(1-L_DISCOUNT)-PS_SUPPLYCOST*L_QUANTITY AS AMOUNT - FROM PART, SUPPLIER, LINEITEM, PARTSUPP, ORDERS, NATION + FROM "PART", SUPPLIER, LINEITEM, PARTSUPP, ORDERS, NATION WHERE S_SUPPKEY = L_SUPPKEY AND PS_SUPPKEY= L_SUPPKEY AND PS_PARTKEY = L_PARTKEY AND P_PARTKEY= L_PARTKEY AND O_ORDERKEY = L_ORDERKEY AND S_NATIONKEY = N_NATIONKEY AND P_NAME LIKE '%%green%%') AS PROFIT diff --git a/test/select_tests.cpp b/test/select_tests.cpp index dead654..62e5d55 100644 --- a/test/select_tests.cpp +++ b/test/select_tests.cpp @@ -20,6 +20,45 @@ TEST(SelectTest) { delete result; } +TEST(SelectExprTest) { + TEST_PARSE_SINGLE_SQL( + "SELECT a, MAX(b), CUSTOM(c, F(un)) FROM students;", + kStmtSelect, + SelectStatement, + result, + stmt); + + ASSERT_NULL(stmt->whereClause); + ASSERT_NULL(stmt->groupBy); + + ASSERT_EQ(stmt->selectList->size(), 3); + + ASSERT(stmt->selectList->at(0)->isType(kExprColumnRef)); + ASSERT_STREQ(stmt->selectList->at(0)->getName(), "a"); + + ASSERT(stmt->selectList->at(1)->isType(kExprFunctionRef)); + ASSERT_STREQ(stmt->selectList->at(1)->getName(), "MAX"); + ASSERT_NOTNULL(stmt->selectList->at(1)->exprList); + ASSERT_EQ(stmt->selectList->at(1)->exprList->size(), 1); + ASSERT(stmt->selectList->at(1)->exprList->at(0)->isType(kExprColumnRef)); + ASSERT_STREQ(stmt->selectList->at(1)->exprList->at(0)->getName(), "b"); + + ASSERT(stmt->selectList->at(2)->isType(kExprFunctionRef)); + ASSERT_STREQ(stmt->selectList->at(2)->getName(), "CUSTOM"); + ASSERT_NOTNULL(stmt->selectList->at(2)->exprList); + ASSERT_EQ(stmt->selectList->at(2)->exprList->size(), 2); + ASSERT(stmt->selectList->at(2)->exprList->at(0)->isType(kExprColumnRef)); + ASSERT_STREQ(stmt->selectList->at(2)->exprList->at(0)->getName(), "c"); + + ASSERT(stmt->selectList->at(2)->exprList->at(1)->isType(kExprFunctionRef)); + ASSERT_STREQ(stmt->selectList->at(2)->exprList->at(1)->getName(), "F"); + ASSERT_EQ(stmt->selectList->at(2)->exprList->at(1)->exprList->size(), 1); + ASSERT(stmt->selectList->at(2)->exprList->at(1)->exprList->at(0)->isType(kExprColumnRef)); + ASSERT_STREQ(stmt->selectList->at(2)->exprList->at(1)->exprList->at(0)->getName(), "un"); + + delete result; +} + TEST(SelectHavingTest) { TEST_PARSE_SINGLE_SQL( diff --git a/test/valid_queries.sql b/test/valid_queries.sql index dfece3d..cbd9584 100644 --- a/test/valid_queries.sql +++ b/test/valid_queries.sql @@ -9,6 +9,7 @@ SELECT * FROM t1 UNION SELECT * FROM t2 ORDER BY col1; SELECT * FROM (SELECT * FROM t1); SELECT * FROM t1 UNION (SELECT * FROM t2 UNION SELECT * FROM t3) ORDER BY col1; SELECT TOP 10 * FROM t1 ORDER BY col1, col2; +SELECT a, MAX(b), MAX(c, d), CUSTOM(q, UP(r)) AS f FROM t1; # JOIN SELECT t1.a, t1.b, t2.c FROM "table" AS t1 JOIN (SELECT * FROM foo JOIN bar ON foo.id = bar.id) t2 ON t1.a = t2.b WHERE (t1.b OR NOT t1.a) AND t2.c = 12.5 SELECT * FROM t1 JOIN t2 ON c1 = c2;