From 5ff661970aae22afb84d042fa906d892c011df72 Mon Sep 17 00:00:00 2001 From: YBRua Date: Tue, 8 Nov 2022 14:12:47 +0800 Subject: [PATCH 1/8] enabled legacy string LOWER funcs --- .../plan/parser/SubstraitToAnalyzerExpr.cpp | 6 +- cider/tests/functionality/CiderStringTest.cpp | 82 +++++++++++++- .../substrait_plan_files/string_lower.json | 105 ++++++++++++++++++ cider/type/plan/Analyzer.cpp | 5 + 4 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 cider/tests/substrait_plan_files/string_lower.json diff --git a/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp b/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp index 600551574..743325067 100644 --- a/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp +++ b/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp @@ -37,7 +37,7 @@ bool getExprUpdatable(std::unordered_map, bool> } bool isStringFunction(std::string function_name) { - std::unordered_set supportedStrFunctionSet{"substring"}; + std::unordered_set supportedStrFunctionSet{"substring", "lower"}; return supportedStrFunctionSet.find(function_name) != supportedStrFunctionSet.end(); } @@ -799,8 +799,8 @@ std::shared_ptr Substrait2AnalyzerExprConverter::buildStrExpr( function_name.begin(), function_name.end(), function_name.begin(), ::toupper); auto string_op_kind = name_to_string_op_kind(function_name); switch (string_op_kind) { - // case SqlStringOpKind::LOWER: - // return makeExpr(args); + case SqlStringOpKind::LOWER: + return makeExpr(args); // case SqlStringOpKind::UPPER: // return makeExpr(args); // case SqlStringOpKind::INITCAP: diff --git a/cider/tests/functionality/CiderStringTest.cpp b/cider/tests/functionality/CiderStringTest.cpp index cd62bfe27..7abb812de 100644 --- a/cider/tests/functionality/CiderStringTest.cpp +++ b/cider/tests/functionality/CiderStringTest.cpp @@ -120,7 +120,7 @@ class CiderStringNullableTestArrow : public CiderTestBase { QueryArrowDataGenerator::generateBatchByTypes( schema_, array_, - 30, + 50, {"col_1", "col_2"}, {CREATE_SUBSTRAIT_TYPE(I32), CREATE_SUBSTRAIT_TYPE(Varchar)}, {2, 2}, @@ -358,10 +358,88 @@ TEST_F(CiderStringRandomTestArrow, ArrowSubstringNestTest) { assertQueryArrow("SELECT * FROM test WHERE SUBSTRING(col_2, 1, 3) = 'aaa'"); assertQueryArrow("SELECT * FROM test WHERE SUBSTRING(col_2, 1, 3) <> 'bbb'"); assertQueryArrow("SELECT * FROM test WHERE SUBSTRING(col_2, 1, 3) > 'aaa'"); - assertQueryArrow("SELECT SUBSTRING(SUBSTRING(col_2, 1, 8), 1, 4) FROM test "); } +TEST_F(CiderStringNullableTestArrow, ArrowBasicStringTest) { + assertQueryArrow("SELECT col_2 FROM test "); + assertQueryArrow("SELECT col_1, col_2 FROM test "); + assertQueryArrow("SELECT * FROM test "); + assertQueryArrow("SELECT col_2 FROM test where col_2 = 'aaaa'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 = '0000000000'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 <> '0000000000'"); + assertQueryArrow("SELECT col_1 FROM test where col_2 <> '1111111111'"); + assertQueryArrow("SELECT col_1, col_2 FROM test where col_2 <> '2222222222'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 <> 'aaaaaaaaaaa'"); + assertQueryArrow("SELECT * FROM test where col_2 <> 'abcdefghijklmn'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 IS NOT NULL"); + assertQueryArrow("SELECT col_2 FROM test where col_2 < 'uuu'"); +} + +TEST_F(CiderStringNullableTestArrow, ArrowBasicStringLikeTest) { + assertQueryArrow("SELECT col_2 FROM test where col_2 LIKE '%1111'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 LIKE '1111%'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 LIKE '%1111%'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 LIKE '%1234%'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 LIKE '22%22'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 LIKE '_33%'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 LIKE '44_%'"); + + assertQueryArrow( + "SELECT col_2 FROM test where col_2 LIKE '5555%' OR col_2 LIKE '%6666'"); + assertQueryArrow( + "SELECT col_2 FROM test where col_2 LIKE '7777%' AND col_2 LIKE '%8888'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 LIKE '%1111'", + "like_wo_cast.json"); + assertQueryArrow("SELECT col_2 FROM test where col_2 NOT LIKE '1111%'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 NOT LIKE '44_4444444'"); + assertQueryArrow( + "SELECT col_2 FROM test where col_2 NOT LIKE '44_4%' and col_2 NOT LIKE '%111%'"); +} + +TEST_F(CiderStringNullableTestArrow, ArrowSubstringTest) { + // variable source string + assertQueryArrow("SELECT SUBSTRING(col_2, 1, 10) FROM test "); + assertQueryArrow("SELECT SUBSTRING(col_2, 1, 5) FROM test "); + + // out of range + assertQueryArrow("SELECT SUBSTRING(col_2, 4, 8) FROM test "); + assertQueryArrow("SELECT SUBSTRING(col_2, 0, 12) FROM test "); + assertQueryArrow("SELECT SUBSTRING(col_2, 12, 0) FROM test "); + assertQueryArrow("SELECT SUBSTRING(col_2, 12, 2) FROM test "); + + // from for + assertQueryArrow("SELECT SUBSTRING(col_2 from 2 for 8) FROM test "); + + // zero length + assertQueryArrow("SELECT SUBSTRING(col_2, 4, 0) FROM test "); + + // negative wrap + assertQueryArrow("SELECT SUBSTRING(col_2, -4, 2) FROM test "); +} + +TEST_F(CiderStringNullableTestArrow, ArrowLowerTest) { + // select + assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "string_lower.json"); + // literal LOWER + // select literal LOWER +} + +TEST_F(CiderStringTestArrow, ArrowBasicStringTest) { + assertQueryArrow("SELECT col_2 FROM test "); + assertQueryArrow("SELECT col_1, col_2 FROM test "); + assertQueryArrow("SELECT * FROM test "); + assertQueryArrow("SELECT col_2 FROM test where col_2 = 'aaaa'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 = '0000000000'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 <> '0000000000'"); + assertQueryArrow("SELECT col_1 FROM test where col_2 <> '1111111111'"); + assertQueryArrow("SELECT col_1, col_2 FROM test where col_2 <> '2222222222'"); + assertQueryArrow("SELECT * FROM test where col_2 <> 'aaaaaaaaaaa'"); + assertQueryArrow("SELECT * FROM test where col_2 <> 'abcdefghijklmn'"); + assertQueryArrow("SELECT col_2 FROM test where col_2 IS NOT NULL"); + assertQueryArrow("SELECT col_2 FROM test where col_2 < 'uuu'"); +} + TEST_F(CiderStringNullableTestArrow, ArrowSubstringNestTest) { assertQueryArrow("SELECT * FROM test WHERE SUBSTRING(col_2, 1, 3) = 'aaa'"); assertQueryArrow("SELECT * FROM test WHERE SUBSTRING(col_2, 1, 3) <> 'bbb'"); diff --git a/cider/tests/substrait_plan_files/string_lower.json b/cider/tests/substrait_plan_files/string_lower.json new file mode 100644 index 000000000..0242bbee8 --- /dev/null +++ b/cider/tests/substrait_plan_files/string_lower.json @@ -0,0 +1,105 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "lower:vchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [2, 3] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": ["COL_1", "COL_2"], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": ["TEST"] + } + } + }, + "expressions": [ + { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + }, + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + "arguments": [ + { + "value": { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + } + ] + } + } + ] + } + }, + "names": ["COL_2", "EXPR$1"] + } + } + ], + "expectedTypeUrls": [] +} diff --git a/cider/type/plan/Analyzer.cpp b/cider/type/plan/Analyzer.cpp index 138a5d52c..2956a5698 100644 --- a/cider/type/plan/Analyzer.cpp +++ b/cider/type/plan/Analyzer.cpp @@ -397,6 +397,11 @@ std::shared_ptr SubstringStringOper::deep_copy() const { std::dynamic_pointer_cast(StringOper::deep_copy())); } +std::shared_ptr LowerStringOper::deep_copy() const { + return makeExpr( + std::dynamic_pointer_cast(StringOper::deep_copy())); +} + std::shared_ptr TryStringCastOper::deep_copy() const { return makeExpr( std::dynamic_pointer_cast(StringOper::deep_copy())); From fe35e206adcbb2015c28171b02ff01b2d980f740 Mon Sep 17 00:00:00 2001 From: YBRua Date: Tue, 8 Nov 2022 15:09:58 +0800 Subject: [PATCH 2/8] added more LOWER test --- cider/tests/functionality/CiderStringTest.cpp | 19 +++- .../string_lower_literal.json | 101 ++++++++++++++++++ 2 files changed, 117 insertions(+), 3 deletions(-) create mode 100644 cider/tests/substrait_plan_files/string_lower_literal.json diff --git a/cider/tests/functionality/CiderStringTest.cpp b/cider/tests/functionality/CiderStringTest.cpp index 7abb812de..865583e60 100644 --- a/cider/tests/functionality/CiderStringTest.cpp +++ b/cider/tests/functionality/CiderStringTest.cpp @@ -419,10 +419,23 @@ TEST_F(CiderStringNullableTestArrow, ArrowSubstringTest) { } TEST_F(CiderStringNullableTestArrow, ArrowLowerTest) { - // select + // SELECT LOWER(column) FROM table assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "string_lower.json"); - // literal LOWER - // select literal LOWER + + /// NOTE: (YBRua) Skipped for now because we dont expect queries without FROM clauses. + /// 1. Behaviors of Cider and DuckDb are different w.r.t. this query. + /// DuckDb produces only 1 row, while Cider produces input_row_num rows. + /// Because the compiled row_func IR always runs for input_row_num times + /// at runtime in current implementation of Cider. + /// 2. If no input table (no FROM clause) is given, the generated Substrait plan will + /// have a "virtualTable" (instead of a "namedTable") as a placeholder input. + /// + // SELECT LOWER(literal) + // assertQueryArrow("SELECT LOWER('ABCDEFG');"); + + // SELECT LOWER(literal) FROM table + assertQueryArrow("SELECT LOWER('aAbBcCdDeEfFgG12345') FROM test;", + "string_lower_literal.json"); } TEST_F(CiderStringTestArrow, ArrowBasicStringTest) { diff --git a/cider/tests/substrait_plan_files/string_lower_literal.json b/cider/tests/substrait_plan_files/string_lower_literal.json new file mode 100644 index 000000000..21cd4c3ea --- /dev/null +++ b/cider/tests/substrait_plan_files/string_lower_literal.json @@ -0,0 +1,101 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "lower:fchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "expressions": [ + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "varchar": { + "length": 19, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "literal": { + "fixedChar": "aAbBcCdDeEfFgG12345", + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + ] + } + }, + "names": [ + "EXPR$0" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file From 678766f09230189a5091f22aabaaeb54df39ccae Mon Sep 17 00:00:00 2001 From: YBRua Date: Tue, 8 Nov 2022 15:48:17 +0800 Subject: [PATCH 3/8] added UPPER & improved json file names --- .../plan/parser/SubstraitToAnalyzerExpr.cpp | 6 +- cider/tests/functionality/CiderStringTest.cpp | 41 ++++++- .../substrait_plan_files/stringop_lower.json | 116 ++++++++++++++++++ .../stringop_lower_literal.json | 101 +++++++++++++++ ....json => stringop_lower_literal_null.json} | 4 +- ...ng_lower.json => stringop_lower_null.json} | 21 +++- .../substrait_plan_files/stringop_upper.json | 116 ++++++++++++++++++ .../stringop_upper_literal.json | 101 +++++++++++++++ .../stringop_upper_literal_null.json | 101 +++++++++++++++ .../stringop_upper_null.json | 116 ++++++++++++++++++ cider/type/plan/Analyzer.cpp | 13 +- cider/type/plan/Analyzer.h | 30 +++++ 12 files changed, 746 insertions(+), 20 deletions(-) create mode 100644 cider/tests/substrait_plan_files/stringop_lower.json create mode 100644 cider/tests/substrait_plan_files/stringop_lower_literal.json rename cider/tests/substrait_plan_files/{string_lower_literal.json => stringop_lower_literal_null.json} (96%) rename cider/tests/substrait_plan_files/{string_lower.json => stringop_lower_null.json} (88%) create mode 100644 cider/tests/substrait_plan_files/stringop_upper.json create mode 100644 cider/tests/substrait_plan_files/stringop_upper_literal.json create mode 100644 cider/tests/substrait_plan_files/stringop_upper_literal_null.json create mode 100644 cider/tests/substrait_plan_files/stringop_upper_null.json diff --git a/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp b/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp index 743325067..0415c6c74 100644 --- a/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp +++ b/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp @@ -37,7 +37,7 @@ bool getExprUpdatable(std::unordered_map, bool> } bool isStringFunction(std::string function_name) { - std::unordered_set supportedStrFunctionSet{"substring", "lower"}; + std::unordered_set supportedStrFunctionSet{"substring", "lower", "upper"}; return supportedStrFunctionSet.find(function_name) != supportedStrFunctionSet.end(); } @@ -801,8 +801,8 @@ std::shared_ptr Substrait2AnalyzerExprConverter::buildStrExpr( switch (string_op_kind) { case SqlStringOpKind::LOWER: return makeExpr(args); - // case SqlStringOpKind::UPPER: - // return makeExpr(args); + case SqlStringOpKind::UPPER: + return makeExpr(args); // case SqlStringOpKind::INITCAP: // return makeExpr(args); // case SqlStringOpKind::REVERSE: diff --git a/cider/tests/functionality/CiderStringTest.cpp b/cider/tests/functionality/CiderStringTest.cpp index 865583e60..af214d9e4 100644 --- a/cider/tests/functionality/CiderStringTest.cpp +++ b/cider/tests/functionality/CiderStringTest.cpp @@ -82,7 +82,7 @@ class CiderStringTestArrow : public CiderTestBase { QueryArrowDataGenerator::generateBatchByTypes( schema_, array_, - 30, + 50, {"col_1", "col_2"}, {CREATE_SUBSTRAIT_TYPE(I32), CREATE_SUBSTRAIT_TYPE(Varchar)}, {0, 0}, @@ -350,7 +350,6 @@ TEST_F(CiderStringTestArrow, ArrowSubstringNestTest) { assertQueryArrow("SELECT * FROM test WHERE SUBSTRING(col_2, 1, 3) = 'aaa'"); assertQueryArrow("SELECT * FROM test WHERE SUBSTRING(col_2, 1, 3) <> 'bbb'"); assertQueryArrow("SELECT * FROM test WHERE SUBSTRING(col_2, 1, 3) > 'aaa'"); - assertQueryArrow("SELECT SUBSTRING(SUBSTRING(col_2, 1, 8), 1, 4) FROM test "); } @@ -418,9 +417,9 @@ TEST_F(CiderStringNullableTestArrow, ArrowSubstringTest) { assertQueryArrow("SELECT SUBSTRING(col_2, -4, 2) FROM test "); } -TEST_F(CiderStringNullableTestArrow, ArrowLowerTest) { +TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { // SELECT LOWER(column) FROM table - assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "string_lower.json"); + assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "stringop_lower_null.json"); /// NOTE: (YBRua) Skipped for now because we dont expect queries without FROM clauses. /// 1. Behaviors of Cider and DuckDb are different w.r.t. this query. @@ -434,8 +433,17 @@ TEST_F(CiderStringNullableTestArrow, ArrowLowerTest) { // assertQueryArrow("SELECT LOWER('ABCDEFG');"); // SELECT LOWER(literal) FROM table - assertQueryArrow("SELECT LOWER('aAbBcCdDeEfFgG12345') FROM test;", - "string_lower_literal.json"); + assertQueryArrow("SELECT LOWER('aAbBcCdD12') FROM test;", + "stringop_lower_literal_null.json"); + + // SELECT UPPER(column) FROM table + assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper_null.json"); + + // SELECT UPPER(literal) + // assertQueryArrow("SELECT UPPER('abcdefg');"); + + assertQueryArrow("SELECT UPPER('aAbBcCdD12') FROM test;", + "stringop_upper_literal_null.json"); } TEST_F(CiderStringTestArrow, ArrowBasicStringTest) { @@ -461,6 +469,27 @@ TEST_F(CiderStringNullableTestArrow, ArrowSubstringNestTest) { assertQueryArrow("SELECT SUBSTRING(SUBSTRING(col_2, 1, 8), 1, 4) FROM test "); } +TEST_F(CiderStringTestArrow, ArrowCaseConvertionTest) { + // SELECT LOWER(column) FROM table + assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "stringop_lower.json"); + + // SELECT LOWER(literal) + // assertQueryArrow("SELECT LOWER('ABCDEFG');"); + + // SELECT LOWER(literal) FROM table + assertQueryArrow("SELECT LOWER('aAbBcCdD12') FROM test;", + "stringop_lower_literal.json"); + + // SELECT UPPER(column) FROM table + assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper.json"); + + // SELECT UPPER(literal) + // assertQueryArrow("SELECT UPPER('abcdefg');"); + + assertQueryArrow("SELECT UPPER('aAbBcCdD12') FROM test;", + "stringop_upper_literal.json"); +} + class CiderConstantStringTest : public CiderTestBase { public: CiderConstantStringTest() { diff --git a/cider/tests/substrait_plan_files/stringop_lower.json b/cider/tests/substrait_plan_files/stringop_lower.json new file mode 100644 index 000000000..0364d0991 --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_lower.json @@ -0,0 +1,116 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "lower:vchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2, + 3 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "expressions": [ + { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + }, + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + } + ] + } + } + ] + } + }, + "names": [ + "COL_2", + "EXPR$1" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_lower_literal.json b/cider/tests/substrait_plan_files/stringop_lower_literal.json new file mode 100644 index 000000000..c98ee4928 --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_lower_literal.json @@ -0,0 +1,101 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "lower:fchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "expressions": [ + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "literal": { + "fixedChar": "aAbBcCdD12", + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + ] + } + }, + "names": [ + "EXPR$0" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/string_lower_literal.json b/cider/tests/substrait_plan_files/stringop_lower_literal_null.json similarity index 96% rename from cider/tests/substrait_plan_files/string_lower_literal.json rename to cider/tests/substrait_plan_files/stringop_lower_literal_null.json index 21cd4c3ea..ff5be8a7b 100644 --- a/cider/tests/substrait_plan_files/string_lower_literal.json +++ b/cider/tests/substrait_plan_files/stringop_lower_literal_null.json @@ -70,7 +70,7 @@ "args": [], "outputType": { "varchar": { - "length": 19, + "length": 10, "typeVariationReference": 0, "nullability": "NULLABILITY_REQUIRED" } @@ -79,7 +79,7 @@ { "value": { "literal": { - "fixedChar": "aAbBcCdDeEfFgG12345", + "fixedChar": "aAbBcCdD12", "nullable": false, "typeVariationReference": 0 } diff --git a/cider/tests/substrait_plan_files/string_lower.json b/cider/tests/substrait_plan_files/stringop_lower_null.json similarity index 88% rename from cider/tests/substrait_plan_files/string_lower.json rename to cider/tests/substrait_plan_files/stringop_lower_null.json index 0242bbee8..ce2af2525 100644 --- a/cider/tests/substrait_plan_files/string_lower.json +++ b/cider/tests/substrait_plan_files/stringop_lower_null.json @@ -21,7 +21,10 @@ "project": { "common": { "emit": { - "outputMapping": [2, 3] + "outputMapping": [ + 2, + 3 + ] } }, "input": { @@ -30,7 +33,10 @@ "direct": {} }, "baseSchema": { - "names": ["COL_1", "COL_2"], + "names": [ + "COL_1", + "COL_2" + ], "struct": { "types": [ { @@ -52,7 +58,9 @@ } }, "namedTable": { - "names": ["TEST"] + "names": [ + "TEST" + ] } } }, @@ -97,9 +105,12 @@ ] } }, - "names": ["COL_2", "EXPR$1"] + "names": [ + "COL_2", + "EXPR$1" + ] } } ], "expectedTypeUrls": [] -} +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_upper.json b/cider/tests/substrait_plan_files/stringop_upper.json new file mode 100644 index 000000000..f3d9c88fd --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_upper.json @@ -0,0 +1,116 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "upper:vchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2, + 3 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "expressions": [ + { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + }, + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + } + ] + } + } + ] + } + }, + "names": [ + "COL_2", + "EXPR$1" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_upper_literal.json b/cider/tests/substrait_plan_files/stringop_upper_literal.json new file mode 100644 index 000000000..b528e571c --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_upper_literal.json @@ -0,0 +1,101 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "upper:fchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "expressions": [ + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "literal": { + "fixedChar": "aAbBcCdD12", + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + ] + } + }, + "names": [ + "EXPR$0" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_upper_literal_null.json b/cider/tests/substrait_plan_files/stringop_upper_literal_null.json new file mode 100644 index 000000000..f77a50912 --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_upper_literal_null.json @@ -0,0 +1,101 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "upper:fchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "expressions": [ + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "literal": { + "fixedChar": "aAbBcCdD12", + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + ] + } + }, + "names": [ + "EXPR$0" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_upper_null.json b/cider/tests/substrait_plan_files/stringop_upper_null.json new file mode 100644 index 000000000..749d52d74 --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_upper_null.json @@ -0,0 +1,116 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "upper:vchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2, + 3 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "expressions": [ + { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + }, + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + "arguments": [ + { + "value": { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + } + ] + } + } + ] + } + }, + "names": [ + "COL_2", + "EXPR$1" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/type/plan/Analyzer.cpp b/cider/type/plan/Analyzer.cpp index 2956a5698..3c5c0757a 100644 --- a/cider/type/plan/Analyzer.cpp +++ b/cider/type/plan/Analyzer.cpp @@ -392,13 +392,18 @@ void StringOper::check_operand_types( } } -std::shared_ptr SubstringStringOper::deep_copy() const { - return makeExpr( +std::shared_ptr LowerStringOper::deep_copy() const { + return makeExpr( std::dynamic_pointer_cast(StringOper::deep_copy())); } -std::shared_ptr LowerStringOper::deep_copy() const { - return makeExpr( +std::shared_ptr UpperStringOper::deep_copy() const { + return makeExpr( + std::dynamic_pointer_cast(StringOper::deep_copy())); +} + +std::shared_ptr SubstringStringOper::deep_copy() const { + return makeExpr( std::dynamic_pointer_cast(StringOper::deep_copy())); } diff --git a/cider/type/plan/Analyzer.h b/cider/type/plan/Analyzer.h index 662f14088..ed8aea390 100644 --- a/cider/type/plan/Analyzer.h +++ b/cider/type/plan/Analyzer.h @@ -1784,6 +1784,36 @@ class LowerStringOper : public StringOper { std::vector getArgNames() const override { return {"operand"}; } }; +class UpperStringOper : public StringOper { + public: + UpperStringOper(const std::shared_ptr& operand) + : StringOper(SqlStringOpKind::UPPER, + {operand}, + getMinArgs(), + getExpectedTypeFamilies(), + getArgNames()) {} + + UpperStringOper(const std::vector>& operands) + : StringOper(SqlStringOpKind::UPPER, + operands, + getMinArgs(), + getExpectedTypeFamilies(), + getArgNames()) {} + + UpperStringOper(const std::shared_ptr& string_oper) + : StringOper(string_oper) {} + + std::shared_ptr deep_copy() const override; + + size_t getMinArgs() const override { return 1UL; } + + std::vector getExpectedTypeFamilies() const override { + return {OperandTypeFamily::STRING_FAMILY}; + } + + std::vector getArgNames() const override { return {"operand"}; } +}; + class SubstringStringOper : public StringOper { public: SubstringStringOper(const std::shared_ptr& operand, From 4e3010a9bafc77f43d8bc2530787be77822c86ae Mon Sep 17 00:00:00 2001 From: YBRua Date: Thu, 10 Nov 2022 16:26:24 +0800 Subject: [PATCH 4/8] updated stringop uts --- cider/tests/functionality/CiderStringTest.cpp | 45 +++-- .../substrait_plan_files/stringop_lower.json | 2 +- .../stringop_lower_condition.json | 160 ++++++++++++++++++ .../stringop_lower_condition_null.json | 160 ++++++++++++++++++ .../stringop_lower_constexpr_null.json | 101 +++++++++++ .../stringop_lower_literal.json | 4 +- .../stringop_lower_literal_null.json | 4 +- .../stringop_lower_null.json | 2 +- .../substrait_plan_files/stringop_upper.json | 2 +- .../stringop_upper_condition.json | 160 ++++++++++++++++++ .../stringop_upper_condition_null.json | 160 ++++++++++++++++++ .../stringop_upper_constexpr_null.json | 101 +++++++++++ .../stringop_upper_literal.json | 4 +- .../stringop_upper_literal_null.json | 4 +- .../stringop_upper_null.json | 2 +- 15 files changed, 876 insertions(+), 35 deletions(-) create mode 100644 cider/tests/substrait_plan_files/stringop_lower_condition.json create mode 100644 cider/tests/substrait_plan_files/stringop_lower_condition_null.json create mode 100644 cider/tests/substrait_plan_files/stringop_lower_constexpr_null.json create mode 100644 cider/tests/substrait_plan_files/stringop_upper_condition.json create mode 100644 cider/tests/substrait_plan_files/stringop_upper_condition_null.json create mode 100644 cider/tests/substrait_plan_files/stringop_upper_constexpr_null.json diff --git a/cider/tests/functionality/CiderStringTest.cpp b/cider/tests/functionality/CiderStringTest.cpp index af214d9e4..faf716159 100644 --- a/cider/tests/functionality/CiderStringTest.cpp +++ b/cider/tests/functionality/CiderStringTest.cpp @@ -418,8 +418,9 @@ TEST_F(CiderStringNullableTestArrow, ArrowSubstringTest) { } TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { - // SELECT LOWER(column) FROM table + // select column from table assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "stringop_lower_null.json"); + assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper_null.json"); /// NOTE: (YBRua) Skipped for now because we dont expect queries without FROM clauses. /// 1. Behaviors of Cider and DuckDb are different w.r.t. this query. @@ -429,21 +430,22 @@ TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { /// 2. If no input table (no FROM clause) is given, the generated Substrait plan will /// have a "virtualTable" (instead of a "namedTable") as a placeholder input. /// - // SELECT LOWER(literal) - // assertQueryArrow("SELECT LOWER('ABCDEFG');"); + // select literal + // assertQueryArrow("SELECT LOWER('ABCDEFG');", "stringop_lower_constexpr_null.json"); + // assertQueryArrow("SELECT UPPER('abcdefg');", "stringop_upper_constexpr_null.json"); - // SELECT LOWER(literal) FROM table + // select literal from table assertQueryArrow("SELECT LOWER('aAbBcCdD12') FROM test;", "stringop_lower_literal_null.json"); - - // SELECT UPPER(column) FROM table - assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper_null.json"); - - // SELECT UPPER(literal) - // assertQueryArrow("SELECT UPPER('abcdefg');"); - assertQueryArrow("SELECT UPPER('aAbBcCdD12') FROM test;", "stringop_upper_literal_null.json"); + + // string op on filter clause + assertQueryArrow("SELECT col_2 FROM test WHERE LOWER(col_2) = 'aaaaaaaaa'", + "stringop_lower_condition_null.json"); + assertQueryArrow("SELECT col_2 FROM test WHERE UPPER(col_2) = 'AAAAAAAAAA'", + "stringop_upper_condition_null.json"); + } TEST_F(CiderStringTestArrow, ArrowBasicStringTest) { @@ -470,24 +472,21 @@ TEST_F(CiderStringNullableTestArrow, ArrowSubstringNestTest) { } TEST_F(CiderStringTestArrow, ArrowCaseConvertionTest) { - // SELECT LOWER(column) FROM table + // select column from table assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "stringop_lower.json"); + assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper.json"); - // SELECT LOWER(literal) - // assertQueryArrow("SELECT LOWER('ABCDEFG');"); - - // SELECT LOWER(literal) FROM table + // select literal from table assertQueryArrow("SELECT LOWER('aAbBcCdD12') FROM test;", "stringop_lower_literal.json"); - - // SELECT UPPER(column) FROM table - assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper.json"); - - // SELECT UPPER(literal) - // assertQueryArrow("SELECT UPPER('abcdefg');"); - assertQueryArrow("SELECT UPPER('aAbBcCdD12') FROM test;", "stringop_upper_literal.json"); + + // string op on filter clause + assertQueryArrow("SELECT col_2 FROM test WHERE LOWER(col_2) = 'aaaaaaaaa'", + "stringop_lower_condition.json"); + assertQueryArrow("SELECT col_2 FROM test WHERE UPPER(col_2) = 'AAAAAAAAAA'", + "stringop_upper_condition.json"); } class CiderConstantStringTest : public CiderTestBase { diff --git a/cider/tests/substrait_plan_files/stringop_lower.json b/cider/tests/substrait_plan_files/stringop_lower.json index 0364d0991..3dad837f9 100644 --- a/cider/tests/substrait_plan_files/stringop_lower.json +++ b/cider/tests/substrait_plan_files/stringop_lower.json @@ -10,7 +10,7 @@ "extensionFunction": { "extensionUriReference": 1, "functionAnchor": 0, - "name": "lower:vchar" + "name": "lower:opt_vchar" } } ], diff --git a/cider/tests/substrait_plan_files/stringop_lower_condition.json b/cider/tests/substrait_plan_files/stringop_lower_condition.json new file mode 100644 index 000000000..7aef02f8f --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_lower_condition.json @@ -0,0 +1,160 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 2, + "uri": "/functions_string.yaml" + }, + { + "extensionUriAnchor": 1, + "uri": "/functions_comparison.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "equal:any_any" + } + }, + { + "extensionFunction": { + "extensionUriReference": 2, + "functionAnchor": 1, + "name": "lower:opt_vchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2 + ] + } + }, + "input": { + "filter": { + "common": { + "direct": {} + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "condition": { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "bool": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "scalarFunction": { + "functionReference": 1, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + } + ] + } + } + }, + { + "value": { + "literal": { + "varChar": { + "value": "AAAAAAAAAA", + "length": 10 + }, + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + } + }, + "expressions": [ + { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + ] + } + }, + "names": [ + "COL_2" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_lower_condition_null.json b/cider/tests/substrait_plan_files/stringop_lower_condition_null.json new file mode 100644 index 000000000..b14475e71 --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_lower_condition_null.json @@ -0,0 +1,160 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 2, + "uri": "/functions_string.yaml" + }, + { + "extensionUriAnchor": 1, + "uri": "/functions_comparison.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "equal:any_any" + } + }, + { + "extensionFunction": { + "extensionUriReference": 2, + "functionAnchor": 1, + "name": "lower:opt_vchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2 + ] + } + }, + "input": { + "filter": { + "common": { + "direct": {} + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "condition": { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "bool": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + "arguments": [ + { + "value": { + "scalarFunction": { + "functionReference": 1, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + "arguments": [ + { + "value": { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + } + ] + } + } + }, + { + "value": { + "literal": { + "varChar": { + "value": "aaaaaaaaa", + "length": 10 + }, + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + } + }, + "expressions": [ + { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + ] + } + }, + "names": [ + "COL_2" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_lower_constexpr_null.json b/cider/tests/substrait_plan_files/stringop_lower_constexpr_null.json new file mode 100644 index 000000000..0d4e6a45d --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_lower_constexpr_null.json @@ -0,0 +1,101 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "lower:opt_fchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 1 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "ZERO" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "virtualTable": { + "values": [ + { + "fields": [ + { + "i32": 0, + "nullable": false, + "typeVariationReference": 0 + } + ] + } + ] + } + } + }, + "expressions": [ + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "fixedChar": { + "length": 7, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "literal": { + "fixedChar": "ABCDEFG", + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + ] + } + }, + "names": [ + "EXPR$0" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_lower_literal.json b/cider/tests/substrait_plan_files/stringop_lower_literal.json index c98ee4928..eabcf3c01 100644 --- a/cider/tests/substrait_plan_files/stringop_lower_literal.json +++ b/cider/tests/substrait_plan_files/stringop_lower_literal.json @@ -10,7 +10,7 @@ "extensionFunction": { "extensionUriReference": 1, "functionAnchor": 0, - "name": "lower:fchar" + "name": "lower:opt_fchar" } } ], @@ -69,7 +69,7 @@ "functionReference": 0, "args": [], "outputType": { - "varchar": { + "fixedChar": { "length": 10, "typeVariationReference": 0, "nullability": "NULLABILITY_REQUIRED" diff --git a/cider/tests/substrait_plan_files/stringop_lower_literal_null.json b/cider/tests/substrait_plan_files/stringop_lower_literal_null.json index ff5be8a7b..622386d61 100644 --- a/cider/tests/substrait_plan_files/stringop_lower_literal_null.json +++ b/cider/tests/substrait_plan_files/stringop_lower_literal_null.json @@ -10,7 +10,7 @@ "extensionFunction": { "extensionUriReference": 1, "functionAnchor": 0, - "name": "lower:fchar" + "name": "lower:opt_fchar" } } ], @@ -69,7 +69,7 @@ "functionReference": 0, "args": [], "outputType": { - "varchar": { + "fixedChar": { "length": 10, "typeVariationReference": 0, "nullability": "NULLABILITY_REQUIRED" diff --git a/cider/tests/substrait_plan_files/stringop_lower_null.json b/cider/tests/substrait_plan_files/stringop_lower_null.json index ce2af2525..10287c03b 100644 --- a/cider/tests/substrait_plan_files/stringop_lower_null.json +++ b/cider/tests/substrait_plan_files/stringop_lower_null.json @@ -10,7 +10,7 @@ "extensionFunction": { "extensionUriReference": 1, "functionAnchor": 0, - "name": "lower:vchar" + "name": "lower:opt_vchar" } } ], diff --git a/cider/tests/substrait_plan_files/stringop_upper.json b/cider/tests/substrait_plan_files/stringop_upper.json index f3d9c88fd..b7c7558c9 100644 --- a/cider/tests/substrait_plan_files/stringop_upper.json +++ b/cider/tests/substrait_plan_files/stringop_upper.json @@ -10,7 +10,7 @@ "extensionFunction": { "extensionUriReference": 1, "functionAnchor": 0, - "name": "upper:vchar" + "name": "upper:opt_vchar" } } ], diff --git a/cider/tests/substrait_plan_files/stringop_upper_condition.json b/cider/tests/substrait_plan_files/stringop_upper_condition.json new file mode 100644 index 000000000..e065067b7 --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_upper_condition.json @@ -0,0 +1,160 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 2, + "uri": "/functions_string.yaml" + }, + { + "extensionUriAnchor": 1, + "uri": "/functions_comparison.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "equal:any_any" + } + }, + { + "extensionFunction": { + "extensionUriReference": 2, + "functionAnchor": 1, + "name": "upper:opt_vchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2 + ] + } + }, + "input": { + "filter": { + "common": { + "direct": {} + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "condition": { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "bool": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "scalarFunction": { + "functionReference": 1, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + } + ] + } + } + }, + { + "value": { + "literal": { + "varChar": { + "value": "AAAAAAAAAA", + "length": 10 + }, + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + } + }, + "expressions": [ + { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + ] + } + }, + "names": [ + "COL_2" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_upper_condition_null.json b/cider/tests/substrait_plan_files/stringop_upper_condition_null.json new file mode 100644 index 000000000..18dc8de94 --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_upper_condition_null.json @@ -0,0 +1,160 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 2, + "uri": "/functions_string.yaml" + }, + { + "extensionUriAnchor": 1, + "uri": "/functions_comparison.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "equal:any_any" + } + }, + { + "extensionFunction": { + "extensionUriReference": 2, + "functionAnchor": 1, + "name": "upper:opt_vchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 2 + ] + } + }, + "input": { + "filter": { + "common": { + "direct": {} + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "COL_1", + "COL_2" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "namedTable": { + "names": [ + "TEST" + ] + } + } + }, + "condition": { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "bool": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + "arguments": [ + { + "value": { + "scalarFunction": { + "functionReference": 1, + "args": [], + "outputType": { + "varchar": { + "length": 10, + "typeVariationReference": 0, + "nullability": "NULLABILITY_NULLABLE" + } + }, + "arguments": [ + { + "value": { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + } + ] + } + } + }, + { + "value": { + "literal": { + "varChar": { + "value": "AAAAAAAAAA", + "length": 10 + }, + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + } + }, + "expressions": [ + { + "selection": { + "directReference": { + "structField": { + "field": 1 + } + }, + "rootReference": {} + } + } + ] + } + }, + "names": [ + "COL_2" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_upper_constexpr_null.json b/cider/tests/substrait_plan_files/stringop_upper_constexpr_null.json new file mode 100644 index 000000000..0ceec66ab --- /dev/null +++ b/cider/tests/substrait_plan_files/stringop_upper_constexpr_null.json @@ -0,0 +1,101 @@ +{ + "extensionUris": [ + { + "extensionUriAnchor": 1, + "uri": "/functions_string.yaml" + } + ], + "extensions": [ + { + "extensionFunction": { + "extensionUriReference": 1, + "functionAnchor": 0, + "name": "upper:opt_fchar" + } + } + ], + "relations": [ + { + "root": { + "input": { + "project": { + "common": { + "emit": { + "outputMapping": [ + 1 + ] + } + }, + "input": { + "read": { + "common": { + "direct": {} + }, + "baseSchema": { + "names": [ + "ZERO" + ], + "struct": { + "types": [ + { + "i32": { + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + } + ], + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "virtualTable": { + "values": [ + { + "fields": [ + { + "i32": 0, + "nullable": false, + "typeVariationReference": 0 + } + ] + } + ] + } + } + }, + "expressions": [ + { + "scalarFunction": { + "functionReference": 0, + "args": [], + "outputType": { + "fixedChar": { + "length": 7, + "typeVariationReference": 0, + "nullability": "NULLABILITY_REQUIRED" + } + }, + "arguments": [ + { + "value": { + "literal": { + "fixedChar": "abcdefg", + "nullable": false, + "typeVariationReference": 0 + } + } + } + ] + } + } + ] + } + }, + "names": [ + "EXPR$0" + ] + } + } + ], + "expectedTypeUrls": [] +} \ No newline at end of file diff --git a/cider/tests/substrait_plan_files/stringop_upper_literal.json b/cider/tests/substrait_plan_files/stringop_upper_literal.json index b528e571c..b9de82845 100644 --- a/cider/tests/substrait_plan_files/stringop_upper_literal.json +++ b/cider/tests/substrait_plan_files/stringop_upper_literal.json @@ -10,7 +10,7 @@ "extensionFunction": { "extensionUriReference": 1, "functionAnchor": 0, - "name": "upper:fchar" + "name": "upper:opt_fchar" } } ], @@ -69,7 +69,7 @@ "functionReference": 0, "args": [], "outputType": { - "varchar": { + "fixedChar": { "length": 10, "typeVariationReference": 0, "nullability": "NULLABILITY_REQUIRED" diff --git a/cider/tests/substrait_plan_files/stringop_upper_literal_null.json b/cider/tests/substrait_plan_files/stringop_upper_literal_null.json index f77a50912..b32217992 100644 --- a/cider/tests/substrait_plan_files/stringop_upper_literal_null.json +++ b/cider/tests/substrait_plan_files/stringop_upper_literal_null.json @@ -10,7 +10,7 @@ "extensionFunction": { "extensionUriReference": 1, "functionAnchor": 0, - "name": "upper:fchar" + "name": "upper:opt_fchar" } } ], @@ -69,7 +69,7 @@ "functionReference": 0, "args": [], "outputType": { - "varchar": { + "fixedChar": { "length": 10, "typeVariationReference": 0, "nullability": "NULLABILITY_REQUIRED" diff --git a/cider/tests/substrait_plan_files/stringop_upper_null.json b/cider/tests/substrait_plan_files/stringop_upper_null.json index 749d52d74..cd1e876b8 100644 --- a/cider/tests/substrait_plan_files/stringop_upper_null.json +++ b/cider/tests/substrait_plan_files/stringop_upper_null.json @@ -10,7 +10,7 @@ "extensionFunction": { "extensionUriReference": 1, "functionAnchor": 0, - "name": "upper:vchar" + "name": "upper:opt_vchar" } } ], From 99ecd1f225955baf24222841bea5abaf04060b79 Mon Sep 17 00:00:00 2001 From: YBRua Date: Thu, 10 Nov 2022 16:30:33 +0800 Subject: [PATCH 5/8] moved tests --- cider/tests/functionality/CiderStringTest.cpp | 62 +++++++++---------- 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/cider/tests/functionality/CiderStringTest.cpp b/cider/tests/functionality/CiderStringTest.cpp index faf716159..94c5ad72f 100644 --- a/cider/tests/functionality/CiderStringTest.cpp +++ b/cider/tests/functionality/CiderStringTest.cpp @@ -417,37 +417,6 @@ TEST_F(CiderStringNullableTestArrow, ArrowSubstringTest) { assertQueryArrow("SELECT SUBSTRING(col_2, -4, 2) FROM test "); } -TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { - // select column from table - assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "stringop_lower_null.json"); - assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper_null.json"); - - /// NOTE: (YBRua) Skipped for now because we dont expect queries without FROM clauses. - /// 1. Behaviors of Cider and DuckDb are different w.r.t. this query. - /// DuckDb produces only 1 row, while Cider produces input_row_num rows. - /// Because the compiled row_func IR always runs for input_row_num times - /// at runtime in current implementation of Cider. - /// 2. If no input table (no FROM clause) is given, the generated Substrait plan will - /// have a "virtualTable" (instead of a "namedTable") as a placeholder input. - /// - // select literal - // assertQueryArrow("SELECT LOWER('ABCDEFG');", "stringop_lower_constexpr_null.json"); - // assertQueryArrow("SELECT UPPER('abcdefg');", "stringop_upper_constexpr_null.json"); - - // select literal from table - assertQueryArrow("SELECT LOWER('aAbBcCdD12') FROM test;", - "stringop_lower_literal_null.json"); - assertQueryArrow("SELECT UPPER('aAbBcCdD12') FROM test;", - "stringop_upper_literal_null.json"); - - // string op on filter clause - assertQueryArrow("SELECT col_2 FROM test WHERE LOWER(col_2) = 'aaaaaaaaa'", - "stringop_lower_condition_null.json"); - assertQueryArrow("SELECT col_2 FROM test WHERE UPPER(col_2) = 'AAAAAAAAAA'", - "stringop_upper_condition_null.json"); - -} - TEST_F(CiderStringTestArrow, ArrowBasicStringTest) { assertQueryArrow("SELECT col_2 FROM test "); assertQueryArrow("SELECT col_1, col_2 FROM test "); @@ -489,6 +458,37 @@ TEST_F(CiderStringTestArrow, ArrowCaseConvertionTest) { "stringop_upper_condition.json"); } +TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { + // select column from table + assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "stringop_lower_null.json"); + assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper_null.json"); + + /// NOTE: (YBRua) Skipped for now because we dont expect queries without FROM clauses. + /// 1. Behaviors of Cider and DuckDb are different w.r.t. this query. + /// DuckDb produces only 1 row, while Cider produces input_row_num rows. + /// Because the compiled row_func IR always runs for input_row_num times + /// at runtime in current implementation of Cider. + /// 2. If no input table (no FROM clause) is given, the generated Substrait plan will + /// have a "virtualTable" (instead of a "namedTable") as a placeholder input. + /// + // select literal + // assertQueryArrow("SELECT LOWER('ABCDEFG');", "stringop_lower_constexpr_null.json"); + // assertQueryArrow("SELECT UPPER('abcdefg');", "stringop_upper_constexpr_null.json"); + + // select literal from table + assertQueryArrow("SELECT LOWER('aAbBcCdD12') FROM test;", + "stringop_lower_literal_null.json"); + assertQueryArrow("SELECT UPPER('aAbBcCdD12') FROM test;", + "stringop_upper_literal_null.json"); + + // string op on filter clause + assertQueryArrow("SELECT col_2 FROM test WHERE LOWER(col_2) = 'aaaaaaaaa'", + "stringop_lower_condition_null.json"); + assertQueryArrow("SELECT col_2 FROM test WHERE UPPER(col_2) = 'AAAAAAAAAA'", + "stringop_upper_condition_null.json"); + +} + class CiderConstantStringTest : public CiderTestBase { public: CiderConstantStringTest() { From 74416567b68f5daa512ff288145f10688302aab2 Mon Sep 17 00:00:00 2001 From: YBRua Date: Thu, 10 Nov 2022 17:11:06 +0800 Subject: [PATCH 6/8] fixed typo in test case --- cider/tests/functionality/CiderStringTest.cpp | 16 ++++++++-------- .../stringop_lower_condition.json | 2 +- .../stringop_lower_condition_null.json | 2 +- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/cider/tests/functionality/CiderStringTest.cpp b/cider/tests/functionality/CiderStringTest.cpp index 94c5ad72f..2ed6e68f3 100644 --- a/cider/tests/functionality/CiderStringTest.cpp +++ b/cider/tests/functionality/CiderStringTest.cpp @@ -452,16 +452,10 @@ TEST_F(CiderStringTestArrow, ArrowCaseConvertionTest) { "stringop_upper_literal.json"); // string op on filter clause - assertQueryArrow("SELECT col_2 FROM test WHERE LOWER(col_2) = 'aaaaaaaaa'", + assertQueryArrow("SELECT col_2 FROM test WHERE LOWER(col_2) = 'aaaaaaaaaa'", "stringop_lower_condition.json"); assertQueryArrow("SELECT col_2 FROM test WHERE UPPER(col_2) = 'AAAAAAAAAA'", "stringop_upper_condition.json"); -} - -TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { - // select column from table - assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "stringop_lower_null.json"); - assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper_null.json"); /// NOTE: (YBRua) Skipped for now because we dont expect queries without FROM clauses. /// 1. Behaviors of Cider and DuckDb are different w.r.t. this query. @@ -474,6 +468,12 @@ TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { // select literal // assertQueryArrow("SELECT LOWER('ABCDEFG');", "stringop_lower_constexpr_null.json"); // assertQueryArrow("SELECT UPPER('abcdefg');", "stringop_upper_constexpr_null.json"); +} + +TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { + // select column from table + assertQueryArrow("SELECT col_2, LOWER(col_2) FROM test;", "stringop_lower_null.json"); + assertQueryArrow("SELECT col_2, UPPER(col_2) FROM test;", "stringop_upper_null.json"); // select literal from table assertQueryArrow("SELECT LOWER('aAbBcCdD12') FROM test;", @@ -482,7 +482,7 @@ TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { "stringop_upper_literal_null.json"); // string op on filter clause - assertQueryArrow("SELECT col_2 FROM test WHERE LOWER(col_2) = 'aaaaaaaaa'", + assertQueryArrow("SELECT col_2 FROM test WHERE LOWER(col_2) = 'aaaaaaaaaa'", "stringop_lower_condition_null.json"); assertQueryArrow("SELECT col_2 FROM test WHERE UPPER(col_2) = 'AAAAAAAAAA'", "stringop_upper_condition_null.json"); diff --git a/cider/tests/substrait_plan_files/stringop_lower_condition.json b/cider/tests/substrait_plan_files/stringop_lower_condition.json index 7aef02f8f..99f48b4e3 100644 --- a/cider/tests/substrait_plan_files/stringop_lower_condition.json +++ b/cider/tests/substrait_plan_files/stringop_lower_condition.json @@ -123,7 +123,7 @@ "value": { "literal": { "varChar": { - "value": "AAAAAAAAAA", + "value": "aaaaaaaaaa", "length": 10 }, "nullable": false, diff --git a/cider/tests/substrait_plan_files/stringop_lower_condition_null.json b/cider/tests/substrait_plan_files/stringop_lower_condition_null.json index b14475e71..4ef586003 100644 --- a/cider/tests/substrait_plan_files/stringop_lower_condition_null.json +++ b/cider/tests/substrait_plan_files/stringop_lower_condition_null.json @@ -123,7 +123,7 @@ "value": { "literal": { "varChar": { - "value": "aaaaaaaaa", + "value": "aaaaaaaaaa", "length": 10 }, "nullable": false, From 4e76163526db0c9fb7482a234b39bca29b15faa6 Mon Sep 17 00:00:00 2001 From: YBRua Date: Thu, 10 Nov 2022 17:13:27 +0800 Subject: [PATCH 7/8] fixed lint & format --- cider/tests/functionality/CiderStringTest.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/cider/tests/functionality/CiderStringTest.cpp b/cider/tests/functionality/CiderStringTest.cpp index 2ed6e68f3..17c5463ef 100644 --- a/cider/tests/functionality/CiderStringTest.cpp +++ b/cider/tests/functionality/CiderStringTest.cpp @@ -486,7 +486,6 @@ TEST_F(CiderStringNullableTestArrow, ArrowCaseConvertionTest) { "stringop_lower_condition_null.json"); assertQueryArrow("SELECT col_2 FROM test WHERE UPPER(col_2) = 'AAAAAAAAAA'", "stringop_upper_condition_null.json"); - } class CiderConstantStringTest : public CiderTestBase { From bbd6e685144db81d10a11f3b689b03f77472b26c Mon Sep 17 00:00:00 2001 From: YBRua Date: Thu, 10 Nov 2022 17:18:59 +0800 Subject: [PATCH 8/8] added const ref to string param --- cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp b/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp index 0415c6c74..f44aafd12 100644 --- a/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp +++ b/cider/exec/plan/parser/SubstraitToAnalyzerExpr.cpp @@ -36,7 +36,7 @@ bool getExprUpdatable(std::unordered_map, bool> return map.find(expr) == map.end() || !map.find(expr)->second; } -bool isStringFunction(std::string function_name) { +bool isStringFunction(const std::string& function_name) { std::unordered_set supportedStrFunctionSet{"substring", "lower", "upper"}; return supportedStrFunctionSet.find(function_name) != supportedStrFunctionSet.end(); }