From 5e894680b6318b37b3716cc93cfa868006e3cd3c Mon Sep 17 00:00:00 2001 From: Zhiyuan Liang <132966438+Ami11111@users.noreply.github.com> Date: Mon, 21 Oct 2024 15:28:11 +0800 Subject: [PATCH] Support char_position function (#2080) ### What problem does this PR solve? - Support char_position function - Add test cases and examples ### Type of change - [x] New Feature (non-breaking change which adds functionality) - [x] Test cases --- example/functions.py | 4 + example/http/functions.sh | 16 +++ python/test_pysdk/test_select.py | 95 ++++++++++++++- src/function/builtin_functions.cpp | 2 + src/function/scalar/position.cpp | 59 +++++++++ src/function/scalar/position.cppm | 13 ++ src/function/scalar_function.cppm | 51 +++++++- src/storage/column_vector/column_vector.cppm | 5 +- .../operator/binary_operator.cppm | 114 +++++++++++++----- test/sql/dql/type/varchar.slt | 8 ++ 10 files changed, 329 insertions(+), 38 deletions(-) create mode 100644 src/function/scalar/position.cpp create mode 100644 src/function/scalar/position.cppm diff --git a/example/functions.py b/example/functions.py index a8d6086be5..0f590fe148 100644 --- a/example/functions.py +++ b/example/functions.py @@ -70,6 +70,10 @@ res = table_obj.output(["*"]).filter("trim(' abc ') = rtrim(ltrim(' abc '))").to_df() print(res) +#function char_position +res = table_obj.output(["*", "char_position(c1, 'bc')"]).filter("char_position(c1, c1) <> 0").to_df() +print(res) + res = db_obj.drop_table("function_example") infinity_obj.disconnect() \ No newline at end of file diff --git a/example/http/functions.sh b/example/http/functions.sh index 76bd4833fd..164b31a03f 100644 --- a/example/http/functions.sh +++ b/example/http/functions.sh @@ -301,6 +301,22 @@ curl --request GET \ "filter": "trim(body) = '\''this is an example for trim'\''" } ' +# show rows of 'tbl1' where char_position(body, '123') = 1 +echo -e '\n\n-- show rows of 'tbl1' where char_position(body, '123') = 1' +curl --request GET \ + --url http://localhost:23820/databases/default_db/tables/tbl1/docs \ + --header 'accept: application/json' \ + --header 'content-type: application/json' \ + --data ' + { + "output": + [ + "body" + ], + "filter": "char_position(body, '123') = 1" + } ' + + # drop tbl1 echo -e '\n\n-- drop tbl1' curl --request DELETE \ diff --git a/python/test_pysdk/test_select.py b/python/test_pysdk/test_select.py index 63d1be5f48..009a93bb25 100644 --- a/python/test_pysdk/test_select.py +++ b/python/test_pysdk/test_select.py @@ -816,8 +816,6 @@ def test_select_varchar_length(self, suffix): [{"c1": 'a', "c2": 'a'}, {"c1": 'b', "c2": 'b'}, {"c1": 'c', "c2": 'c'}, {"c1": 'd', "c2": 'd'}, {"c1": 'abc', "c2": 'abc'}, {"c1": 'bbc', "c2": 'bbc'}, {"c1": 'cbc', "c2": 'cbc'}, {"c1": 'dbc', "c2": 'dbc'}]) - - res = table_obj.output(["*"]).filter("char_length(c1) = 1").to_df() print(res) pd.testing.assert_frame_equal(res, pd.DataFrame({'c1': ('a', 'b', 'c', 'd'), @@ -852,4 +850,97 @@ def test_select_regex(self, suffix): res = db_obj.drop_table("test_select_regex"+suffix) + assert res.error_code == ErrorCode.OK + + def test_select_upper_lower(self, suffix): + db_obj = self.infinity_obj.get_database("default_db") + db_obj.drop_table("test_select_upper_lower"+suffix, ConflictType.Ignore) + db_obj.create_table("test_select_upper_lower"+suffix, + {"c1": {"type": "varchar", "constraints": ["primary key", "not null"]}, + "c2": {"type": "varchar", "constraints": ["not null"]}}, ConflictType.Error) + table_obj = db_obj.get_table("test_select_upper_lower"+suffix) + table_obj.insert( + [{"c1": 'a', "c2": 'A'}, {"c1": 'b', "c2": 'B'}, {"c1": 'c', "c2": 'C'}, {"c1": 'd', "c2": 'D'}, + {"c1": 'abc', "c2": 'ABC'}, {"c1": 'bbc', "c2": 'bbc'}, {"c1": 'cbc', "c2": 'cbc'}, {"c1": 'dbc', "c2": 'dbc'},]) + + res = table_obj.output(["*"]).filter("upper(c1) = c2").to_df() + print(res) + pd.testing.assert_frame_equal(res, pd.DataFrame({'c1': ('a', 'b', 'c', 'd', 'abc'), + 'c2': ('A', 'B', 'C', 'D', 'ABC')}) + .astype({'c1': dtype('O'), 'c2': dtype('O')})) + + + res = db_obj.drop_table("test_select_upper_lower"+suffix) + assert res.error_code == ErrorCode.OK + + def test_select_substring(self, suffix): + db_obj = self.infinity_obj.get_database("default_db") + db_obj.drop_table("test_select_substring"+suffix, ConflictType.Ignore) + db_obj.create_table("test_select_substring"+suffix, + {"c1": {"type": "varchar", "constraints": ["primary key", "not null"]}, + "c2": {"type": "varchar", "constraints": ["not null"]}}, ConflictType.Error) + table_obj = db_obj.get_table("test_select_substring"+suffix) + table_obj.insert( + [{"c1": 'a', "c2": 'A'}, {"c1": 'b', "c2": 'B'}, {"c1": 'c', "c2": 'C'}, {"c1": 'd', "c2": 'D'}, + {"c1": 'abc', "c2": 'ABC'}, {"c1": 'bbcc', "c2": 'bbc'}, {"c1": 'cbcc', "c2": 'cbc'}, {"c1": 'dbcc', "c2": 'dbc'},]) + + res = table_obj.output(["*"]).filter("substring(c1, 0, 3) = c2").to_df() + print(res) + pd.testing.assert_frame_equal(res, pd.DataFrame({'c1': ('bbcc', 'cbcc', 'dbcc'), + 'c2': ('bbc', 'cbc', 'dbc')}) + .astype({'c1': dtype('O'), 'c2': dtype('O')})) + + res = db_obj.drop_table("test_select_substring"+suffix) + assert res.error_code == ErrorCode.OK + + def test_select_trim(self, suffix): + db_obj = self.infinity_obj.get_database("default_db") + db_obj.drop_table("test_select_trim"+suffix, ConflictType.Ignore) + db_obj.create_table("test_select_trim"+suffix, + {"c1": {"type": "varchar", "constraints": ["primary key", "not null"]}, + "c2": {"type": "varchar", "constraints": ["not null"]}}, ConflictType.Error) + table_obj = db_obj.get_table("test_select_trim"+suffix) + table_obj.insert( + [{"c1": ' a', "c2": 'a'}, {"c1": ' b', "c2": 'b'}, {"c1": ' c', "c2": 'c'}, + {"c1": 'ab ', "c2": 'ab'}, {"c1": 'bcc ', "c2": 'bcc'}, {"c1": 'cbc ', "c2": 'cbc'}, {"c1": ' dbc ', "c2": 'dbc'},]) + + res = table_obj.output(["*"]).filter("ltrim(c1) = c2").to_df() + print(res) + pd.testing.assert_frame_equal(res, pd.DataFrame({'c1': (' a', ' b', ' c'), + 'c2': ('a', 'b', 'c')}) + .astype({'c1': dtype('O'), 'c2': dtype('O')})) + + res = table_obj.output(["*"]).filter("rtrim(c1) = c2").to_df() + print(res) + pd.testing.assert_frame_equal(res, pd.DataFrame({'c1': ('ab ', 'bcc ', 'cbc '), + 'c2': ('ab', 'bcc', 'cbc')}) + .astype({'c1': dtype('O'), 'c2': dtype('O')})) + + res = table_obj.output(["*"]).filter("trim(c1) = c2").to_df() + print(res) + pd.testing.assert_frame_equal(res, pd.DataFrame({'c1': (' a', ' b', ' c', 'ab ', 'bcc ', 'cbc ', ' dbc '), + 'c2': ('a', 'b', 'c', 'ab', 'bcc', 'cbc', 'dbc')}) + .astype({'c1': dtype('O'), 'c2': dtype('O')})) + + res = db_obj.drop_table("test_select_trim"+suffix) + assert res.error_code == ErrorCode.OK + + def test_select_position(self, suffix): + db_obj = self.infinity_obj.get_database("default_db") + db_obj.drop_table("test_select_position"+suffix, ConflictType.Ignore) + db_obj.create_table("test_select_position"+suffix, + {"c1": {"type": "varchar", "constraints": ["primary key", "not null"]}, + "c2": {"type": "varchar", "constraints": ["not null"]}}, ConflictType.Error) + table_obj = db_obj.get_table("test_select_position"+suffix) + table_obj.insert( + [{"c1": 'a', "c2": 'A'}, {"c1": 'b', "c2": 'B'}, {"c1": 'c', "c2": 'C'}, {"c1": 'd', "c2": 'D'}, + {"c1": 'abc', "c2": 'ABC'}, {"c1": 'bbcc', "c2": 'bbc'}, {"c1": 'cbcc', "c2": 'cbc'}, {"c1": 'dbcc', "c2": 'dbc'},]) + + res = table_obj.output(["*"]).filter("char_position(c1, c2) <> 0").to_df() + print(res) + pd.testing.assert_frame_equal(res, pd.DataFrame({'c1': ('bbcc', 'cbcc', 'dbcc'), + 'c2': ('bbc', 'cbc', 'dbc')}) + .astype({'c1': dtype('O'), 'c2': dtype('O')})) + + res = db_obj.drop_table("test_select_position"+suffix) assert res.error_code == ErrorCode.OK \ No newline at end of file diff --git a/src/function/builtin_functions.cpp b/src/function/builtin_functions.cpp index 9c9aaf6e30..e9ba363fbc 100644 --- a/src/function/builtin_functions.cpp +++ b/src/function/builtin_functions.cpp @@ -54,6 +54,7 @@ import regex; import ltrim; import rtrim; import trim; +import position; import default_values; import special_function; import internal_types; @@ -129,6 +130,7 @@ void BuiltinFunctions::RegisterScalarFunction() { RegisterLtrimFunction(catalog_ptr_); RegisterRtrimFunction(catalog_ptr_); RegisterTrimFunction(catalog_ptr_); + RegisterPositionFunction(catalog_ptr_); } void BuiltinFunctions::RegisterTableFunction() {} diff --git a/src/function/scalar/position.cpp b/src/function/scalar/position.cpp new file mode 100644 index 0000000000..8bb07f8b32 --- /dev/null +++ b/src/function/scalar/position.cpp @@ -0,0 +1,59 @@ +module; + +module position; + +import stl; +import catalog; +import status; +import infinity_exception; +import scalar_function; +import scalar_function_set; +import column_vector; + +import third_party; +import logical_type; +import internal_types; +import data_type; +import logger; + +namespace infinity { + +struct PositionFunction { + template + static inline void Run(TA &first, TB &second, TC &result, ColumnVector *first_ptr, ColumnVector *second_ptr, ColumnVector *) { + Status status = Status::NotSupport("Not implemented"); + RecoverableError(status); + } +}; + +template <> +inline void PositionFunction::Run(VarcharT &first, VarcharT &second, IntegerT &result, ColumnVector *first_ptr, ColumnVector * second_ptr, ColumnVector *) { + Span first_v = first_ptr->GetVarcharInner(first); + Span second_v = second_ptr->GetVarcharInner(second); + String first_str(first_v.data(), first_v.size()); + String second_str(second_v.data(), second_v.size()); + String::size_type pos = first_str.find(second_str); + if(pos == String::npos){ + result = 0; + }else{ + result = pos + 1; + } +} + + + +void RegisterPositionFunction(const UniquePtr &catalog_ptr) { + String func_name = "char_position"; + + SharedPtr function_set_ptr = MakeShared(func_name); + + ScalarFunction varchar_pos_int32(func_name, + {DataType(LogicalType::kVarchar), DataType(LogicalType::kVarchar)}, + {DataType(LogicalType::kInteger)}, + &ScalarFunction::BinaryFunctionVarlenToVarlen); + function_set_ptr->AddFunction(varchar_pos_int32); + + Catalog::AddFunctionSet(catalog_ptr.get(), function_set_ptr); +} + +} // namespace infinity \ No newline at end of file diff --git a/src/function/scalar/position.cppm b/src/function/scalar/position.cppm new file mode 100644 index 0000000000..bc61205dbb --- /dev/null +++ b/src/function/scalar/position.cppm @@ -0,0 +1,13 @@ +module; + +export module position; + +import stl; + +namespace infinity { + +class Catalog; + +export void RegisterPositionFunction(const UniquePtr &catalog_ptr); + +} diff --git a/src/function/scalar_function.cppm b/src/function/scalar_function.cppm index fa7e4e7eb4..32503dfa2a 100644 --- a/src/function/scalar_function.cppm +++ b/src/function/scalar_function.cppm @@ -52,7 +52,7 @@ struct UnaryOpDirectWrapper { template struct BinaryOpDirectWrapper { template - inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *, SizeT, void *) { + inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *, SizeT, void *, void *, void *) { return Operator::template Run(left, right, result); } }; @@ -81,7 +81,7 @@ struct UnaryTryOpWrapper { template struct BinaryTryOpWrapper { template - inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *nulls_ptr, SizeT idx, void *) { + inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *nulls_ptr, SizeT idx, void *, void *, void *) { if (Operator::template Run(left, right, result)) { return; } @@ -116,7 +116,7 @@ struct UnaryOpDirectToVarlenWrapper { template struct BinaryOpDirectToVarlenWrapper { template - inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *, SizeT, void *state_ptr) { + inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *, SizeT, void *, void *, void *state_ptr) { auto *function_data_ptr = (ScalarFunctionData *)(state_ptr); return Operator::template Run(left, right, result, function_data_ptr->column_vector_ptr_); } @@ -152,7 +152,7 @@ struct UnaryTryOpToVarlenWrapper { template struct BinaryTryOpToVarlenWrapper { template - inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *nulls_ptr, SizeT idx, void *state_ptr) { + inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *nulls_ptr, SizeT idx, void *, void *, void *state_ptr) { auto *function_data_ptr = (ScalarFunctionData *)(state_ptr); if (Operator::template Run(left, right, result, function_data_ptr->column_vector_ptr_)) { return; @@ -192,6 +192,17 @@ struct UnaryOpDirectVarlenToVarlenWrapper { } }; +template +struct BinaryOpDirectVarlenToVarlenWrapper { + template + inline static void Execute(LeftValueType left, RightValueType right, TargetValueType &result, Bitmask *, SizeT, void *state_ptr_left, void *state_ptr_right, void *state_ptr) { + auto *function_data_ptr_left = (ScalarFunctionData *)(state_ptr_left); + auto *function_data_ptr_right = (ScalarFunctionData *)(state_ptr_right); + auto *function_data_ptr = (ScalarFunctionData *)(state_ptr); + return Operator::template Run(left, right, result, function_data_ptr_left->column_vector_ptr_, function_data_ptr_right->column_vector_ptr_, function_data_ptr->column_vector_ptr_); + } +}; + template struct TernaryTryOpVarlenToVarlenWrapper { template @@ -351,6 +362,8 @@ public: output, input.row_count(), nullptr, + nullptr, + nullptr, true); } @@ -370,6 +383,8 @@ public: output, input.row_count(), nullptr, + nullptr, + nullptr, true); } @@ -389,6 +404,8 @@ public: input.column_vectors[1], output, input.row_count(), + nullptr, + nullptr, &function_data, true); } @@ -409,10 +426,36 @@ public: input.column_vectors[1], output, input.row_count(), + nullptr, + nullptr, &function_data, true); } + // Binary function result is varlen without any failure. + template + static inline void BinaryFunctionVarlenToVarlen(const DataBlock &input, SharedPtr &output) { + if (input.column_count() != 2) { + String error_message = "Binary function: input column count isn't two."; + UnrecoverableError(error_message); + } + if (!input.Finalized()) { + String error_message = "Input data block is finalized"; + UnrecoverableError(error_message); + } + ScalarFunctionData function_data_left(input.column_vectors[0].get()); + ScalarFunctionData function_data_right(input.column_vectors[1].get()); + ScalarFunctionData function_data(output.get()); + BinaryOperator::Execute>(input.column_vectors[0], + input.column_vectors[1], + output, + input.row_count(), + &function_data_left, + &function_data_right, + &function_data, + true); + } + // Ternary function without any failure. template static inline void TernaryFunction(const DataBlock &input, SharedPtr &output) { diff --git a/src/storage/column_vector/column_vector.cppm b/src/storage/column_vector/column_vector.cppm index 8164acee4d..95c6a49be8 100644 --- a/src/storage/column_vector/column_vector.cppm +++ b/src/storage/column_vector/column_vector.cppm @@ -1234,10 +1234,11 @@ concept PODValueType = IsAnyOf; + UuidT, + VarcharT>; export template -concept BinaryGenerateBoolean = PODValueType or IsAnyOf; +concept BinaryGenerateBoolean = PODValueType or IsAnyOf; template class ColumnVectorPtrAndIdx { diff --git a/src/storage/column_vector/operator/binary_operator.cppm b/src/storage/column_vector/operator/binary_operator.cppm index 34b081c05c..f259243376 100644 --- a/src/storage/column_vector/operator/binary_operator.cppm +++ b/src/storage/column_vector/operator/binary_operator.cppm @@ -61,7 +61,7 @@ public: auto left_ptr = ColumnValueReader(left); auto right_ptr = ColumnValueReader(right); BooleanColumnWriter result_ptr(result); - Operator::template Execute(left_ptr[0], right_ptr[0], result_ptr[0], result_null.get(), 0, state_ptr); + Operator::template Execute(left_ptr[0], right_ptr[0], result_ptr[0], result_null.get(), 0, nullptr, nullptr, state_ptr); result_null->SetAllTrue(); } else { result_null->SetAllFalse(); @@ -74,7 +74,7 @@ public: auto right_ptr = ColumnValueReader(right); BooleanColumnWriter result_ptr(result); for (SizeT i = 0; i < count; ++i) { - Operator::template Execute(left_ptr[i], right_ptr[i], result_ptr[i], result_null.get(), 0, state_ptr); + Operator::template Execute(left_ptr[i], right_ptr[i], result_ptr[i], result_null.get(), 0, nullptr, nullptr,state_ptr); } } else { ResultBooleanExecuteWithNull(left, right, result, count, state_ptr); @@ -89,7 +89,7 @@ public: auto right_ptr = ColumnValueReader(right); BooleanColumnWriter result_ptr(result); for (SizeT i = 0; i < count; ++i) { - Operator::template Execute(left_c, right_ptr[i], result_ptr[i], result_null.get(), 0, state_ptr); + Operator::template Execute(left_c, right_ptr[i], result_ptr[i], result_null.get(), 0, nullptr, nullptr,state_ptr); } } else { ResultBooleanExecuteWithNull(left_c, right, result, count, state_ptr); @@ -104,7 +104,7 @@ public: auto left_ptr = ColumnValueReader(left); BooleanColumnWriter result_ptr(result); for (SizeT i = 0; i < count; ++i) { - Operator::template Execute(left_ptr[i], right_c, result_ptr[i], result_null.get(), 0, state_ptr); + Operator::template Execute(left_ptr[i], right_c, result_ptr[i], result_null.get(), 0, nullptr, nullptr,state_ptr); } } else { ResultBooleanExecuteWithNull(left, right_c, result, count, state_ptr); @@ -131,7 +131,7 @@ private: if (row_index >= count) { return false; } - Operator::template Execute(left_ptr[row_index], right_ptr[row_index], result_ptr[row_index], result_null.get(), row_index, state_ptr); + Operator::template Execute(left_ptr[row_index], right_ptr[row_index], result_ptr[row_index], result_null.get(), row_index, nullptr, nullptr, state_ptr); return row_index + 1 < count; }); } @@ -150,7 +150,7 @@ private: if (row_index >= count) { return false; } - Operator::template Execute(left_constant, right_ptr[row_index], result_ptr[row_index], result_null.get(), row_index, state_ptr); + Operator::template Execute(left_constant, right_ptr[row_index], result_ptr[row_index], result_null.get(), row_index, nullptr, nullptr, state_ptr); return row_index + 1 < count; }); } @@ -169,7 +169,7 @@ private: if (row_index >= count) { return false; } - Operator::template Execute(left_ptr[row_index], right_constant, result_ptr[row_index], result_null.get(), row_index, state_ptr); + Operator::template Execute(left_ptr[row_index], right_constant, result_ptr[row_index], result_null.get(), row_index, nullptr, nullptr, state_ptr); return row_index + 1 < count; }); } @@ -198,7 +198,7 @@ public: right->buffer_->GetCompactBit(0), answer, result_null.get(), - 0, + 0, nullptr, nullptr, state_ptr); result->buffer_->SetCompactBit(0, answer); result_null->SetAllTrue(); @@ -215,12 +215,12 @@ public: auto right_u8 = reinterpret_cast(right->data()); auto result_u8 = reinterpret_cast(result->data()); for (SizeT i = 0; i < count_bytes; ++i) { - Operator::template Execute(left_u8[i], right_u8[i], result_u8[i], result_null.get(), 0, state_ptr); + Operator::template Execute(left_u8[i], right_u8[i], result_u8[i], result_null.get(), 0, nullptr, nullptr, state_ptr); } if (count_tail > 0) { u8 &tail_u8 = result_u8[count_bytes]; u8 ans; - Operator::template Execute(left_u8[count_bytes], right_u8[count_bytes], ans, result_null.get(), 0, state_ptr); + Operator::template Execute(left_u8[count_bytes], right_u8[count_bytes], ans, result_null.get(), 0, nullptr, nullptr, state_ptr); u8 keep_mask = u8(0xff) << count_tail; tail_u8 = (tail_u8 & keep_mask) | (ans & ~keep_mask); } @@ -240,12 +240,12 @@ public: auto right_u8 = reinterpret_cast(right->data()); auto result_u8 = reinterpret_cast(result->data()); for (SizeT i = 0; i < count_bytes; ++i) { - Operator::template Execute(left_u8, right_u8[i], result_u8[i], result_null.get(), 0, state_ptr); + Operator::template Execute(left_u8, right_u8[i], result_u8[i], result_null.get(), 0, nullptr, nullptr, state_ptr); } if (count_tail > 0) { u8 &tail_u8 = result_u8[count_bytes]; u8 ans; - Operator::template Execute(left_u8, right_u8[count_bytes], ans, result_null.get(), 0, state_ptr); + Operator::template Execute(left_u8, right_u8[count_bytes], ans, result_null.get(), 0, nullptr, nullptr, state_ptr); u8 keep_mask = u8(0xff) << count_tail; tail_u8 = (tail_u8 & keep_mask) | (ans & ~keep_mask); } @@ -265,12 +265,12 @@ public: auto left_u8 = reinterpret_cast(left->data()); auto result_u8 = reinterpret_cast(result->data()); for (SizeT i = 0; i < count_bytes; ++i) { - Operator::template Execute(left_u8[i], right_u8, result_u8[i], result_null.get(), 0, state_ptr); + Operator::template Execute(left_u8[i], right_u8, result_u8[i], result_null.get(), 0, nullptr, nullptr, state_ptr); } if (count_tail > 0) { u8 &tail_u8 = result_u8[count_bytes]; u8 ans; - Operator::template Execute(left_u8[count_bytes], right_u8, ans, result_null.get(), 0, state_ptr); + Operator::template Execute(left_u8[count_bytes], right_u8, ans, result_null.get(), 0, nullptr, nullptr, state_ptr); u8 keep_mask = u8(0xff) << count_tail; tail_u8 = (tail_u8 & keep_mask) | (ans & ~keep_mask); } @@ -304,7 +304,7 @@ private: right->buffer_->GetCompactBit(row_index), answer, result_null.get(), - row_index, + row_index, nullptr, nullptr, state_ptr); result->buffer_->SetCompactBit(row_index, answer); return row_index + 1 < count; @@ -325,7 +325,7 @@ private: return false; } BooleanT answer; - Operator::template Execute(left->buffer_->GetCompactBit(row_index), right_boolean, answer, result_null.get(), row_index, state_ptr); + Operator::template Execute(left->buffer_->GetCompactBit(row_index), right_boolean, answer, result_null.get(), row_index, nullptr, nullptr, state_ptr); result->buffer_->SetCompactBit(row_index, answer); return row_index + 1 < count; }); @@ -345,7 +345,7 @@ private: return false; } BooleanT answer; - Operator::template Execute(left_boolean, right->buffer_->GetCompactBit(row_index), answer, result_null.get(), row_index, state_ptr); + Operator::template Execute(left_boolean, right->buffer_->GetCompactBit(row_index), answer, result_null.get(), row_index, nullptr, nullptr, state_ptr); result->buffer_->SetCompactBit(row_index, answer); return row_index + 1 < count; }); @@ -361,6 +361,8 @@ public: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { String error_message = "MixedType needs to be specialized."; @@ -373,6 +375,8 @@ public: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { return BooleanResultBinaryOperator::Execute(left, right, result, count, state_ptr, nullable); @@ -384,6 +388,8 @@ public: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { switch (left->vector_type()) { @@ -396,13 +402,13 @@ public: UnrecoverableError(error_message); } case ColumnVectorType::kFlat: { - return ExecuteFlat(left, right, result, count, state_ptr, nullable); + return ExecuteFlat(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kConstant: { - return ExecuteConstant(left, right, result, count, state_ptr, nullable); + return ExecuteConstant(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kHeterogeneous: { - return ExecuteHeterogeneous(left, right, result, count, state_ptr, nullable); + return ExecuteHeterogeneous(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } } } @@ -414,6 +420,8 @@ private: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { @@ -423,13 +431,13 @@ private: UnrecoverableError(error_message); } case ColumnVectorType::kFlat: { - return ExecuteFlatFlat(left, right, result, count, state_ptr, nullable); + return ExecuteFlatFlat(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kConstant: { - return ExecuteFlatConstant(left, right, result, count, state_ptr, nullable); + return ExecuteFlatConstant(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kHeterogeneous: { - return ExecuteFlatHeterogeneous(left, right, result, count, state_ptr, nullable); + return ExecuteFlatHeterogeneous(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kCompactBit: { String error_message = "CompactBit isn't implemented."; @@ -443,6 +451,8 @@ private: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { @@ -452,13 +462,13 @@ private: UnrecoverableError(error_message); } case ColumnVectorType::kFlat: { - return ExecuteConstantFlat(left, right, result, count, state_ptr, nullable); + return ExecuteConstantFlat(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kConstant: { - return ExecuteConstantConstant(left, right, result, count, state_ptr, nullable); + return ExecuteConstantConstant(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kHeterogeneous: { - return ExecuteConstantHeterogeneous(left, right, result, count, state_ptr, nullable); + return ExecuteConstantHeterogeneous(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kCompactBit: { String error_message = "CompactBit isn't implemented."; @@ -473,6 +483,8 @@ private: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { @@ -483,13 +495,13 @@ private: break; } case ColumnVectorType::kFlat: { - return ExecuteHeterogeneousFlat(left, right, result, count, state_ptr, nullable); + return ExecuteHeterogeneousFlat(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kConstant: { - return ExecuteHeterogeneousConstant(left, right, result, count, state_ptr, nullable); + return ExecuteHeterogeneousConstant(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kHeterogeneous: { - return ExecuteHeterogeneousHeterogeneous(left, right, result, count, state_ptr, nullable); + return ExecuteHeterogeneousHeterogeneous(left, right, result, count, state_ptr_left, state_ptr_right, state_ptr, nullable); } case ColumnVectorType::kCompactBit: { String error_message = "CompactBit isn't implemented."; @@ -506,6 +518,8 @@ private: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { @@ -521,6 +535,8 @@ private: result_ptr, result_null, count, + state_ptr_left, + state_ptr_right, state_ptr); } else { result_null->SetAllTrue(); @@ -530,6 +546,8 @@ private: result_ptr[i], result_null.get(), i, + state_ptr_left, + state_ptr_right, state_ptr); } } @@ -544,6 +562,8 @@ private: ResultType *__restrict result_ptr, SharedPtr &result_null, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr) { *result_null = *left_null; result_null->MergeAnd(*right_null); @@ -556,6 +576,8 @@ private: result_ptr[row_index], result_null.get(), row_index, + state_ptr_left, + state_ptr_right, state_ptr); return row_index + 1 < count; }); @@ -566,6 +588,8 @@ private: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { const auto *left_ptr = (const LeftType *)(left->data()); @@ -580,6 +604,8 @@ private: result_ptr, result_null, count, + state_ptr_left, + state_ptr_right, state_ptr); } else { result_null->SetAllTrue(); @@ -589,6 +615,8 @@ private: result_ptr[i], result_null.get(), i, + state_ptr_left, + state_ptr_right, state_ptr); } } @@ -603,6 +631,8 @@ private: ResultType *__restrict result_ptr, SharedPtr &result_null, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr) { if (right_null->IsAllTrue()) { @@ -619,6 +649,8 @@ private: result_ptr[row_index], result_null.get(), row_index, + state_ptr_left, + state_ptr_right, state_ptr); return row_index + 1 < count; }); @@ -630,6 +662,8 @@ private: SharedPtr &, SizeT, void *, + void *, + void *, bool) { Status status = Status::NotSupport("Not implemented"); RecoverableError(status); @@ -640,6 +674,8 @@ private: const SharedPtr &right, SharedPtr &result, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { @@ -655,6 +691,8 @@ private: result_ptr, result_null, count, + state_ptr_left, + state_ptr_right, state_ptr); } else { result_null->SetAllTrue(); @@ -664,6 +702,8 @@ private: result_ptr[i], result_null.get(), i, + state_ptr_left, + state_ptr_right, state_ptr); } } @@ -678,6 +718,8 @@ private: ResultType *__restrict result_ptr, SharedPtr &result_null, SizeT count, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr) { if (left_null->IsAllTrue()) { *result_null = *right_null; @@ -694,6 +736,8 @@ private: result_ptr[row_index], result_null.get(), row_index, + state_ptr_left, + state_ptr_right, state_ptr); return row_index + 1 < count; }); @@ -704,6 +748,8 @@ private: const SharedPtr &right, SharedPtr &result, SizeT, + void *state_ptr_left, + void *state_ptr_right, void *state_ptr, bool nullable) { const auto *left_ptr = (const LeftType *)(left->data()); @@ -714,7 +760,7 @@ private: result_null->SetAllFalse(); } else { result_null->SetAllTrue(); - Operator::template Execute(left_ptr[0], right_ptr[0], result_ptr[0], result_null.get(), 0, state_ptr); + Operator::template Execute(left_ptr[0], right_ptr[0], result_ptr[0], result_null.get(), 0, state_ptr_left, state_ptr_right, state_ptr); } result->Finalize(1); } @@ -725,6 +771,8 @@ private: SharedPtr &, SizeT, void *, + void *, + void *, bool) { Status status = Status::NotSupport("Not implemented"); RecoverableError(status); @@ -736,6 +784,8 @@ private: SharedPtr &, SizeT, void *, + void *, + void *, bool) { Status status = Status::NotSupport("Not implemented"); RecoverableError(status); @@ -747,6 +797,8 @@ private: SharedPtr &, SizeT, void *, + void *, + void *, bool) { Status status = Status::NotSupport("Not implemented"); RecoverableError(status); @@ -758,6 +810,8 @@ private: SharedPtr &, SizeT, void *, + void *, + void *, bool) { Status status = Status::NotSupport("Not implemented"); RecoverableError(status); diff --git a/test/sql/dql/type/varchar.slt b/test/sql/dql/type/varchar.slt index 15635699a6..f403b783c6 100644 --- a/test/sql/dql/type/varchar.slt +++ b/test/sql/dql/type/varchar.slt @@ -135,5 +135,13 @@ SELECT *, trim(c1) FROM test_varchar_filter where trim(c1) = 'a b c'; a b c abc 8 a b c a b c abc 9 a b c +query XX +SELECT *, char_position(c1, 'abcd') FROM test_varchar_filter where char_position(c1, 'abcd') = 1; +---- +abcddddd abcddddd 1 1 +abcddddc abcddddd 2 1 +abcdddde abcddddd 3 1 +abcdddde abcdddde 4 1 + statement ok DROP TABLE test_varchar_filter;