This is an automated email from the ASF dual-hosted git repository.
lihaopeng pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new b95cd7eca2 [Refactor](function) Reconstruct default logic for const
args. (#17830)
b95cd7eca2 is described below
commit b95cd7eca2e67ec62fb96b670754daf56fa2f336
Author: ZhaoChangle <[email protected]>
AuthorDate: Fri Mar 17 11:13:13 2023 +0800
[Refactor](function) Reconstruct default logic for const args. (#17830)
---
be/src/vec/functions/date_time_transforms.h | 12 ++--
be/src/vec/functions/function.cpp | 77 ++++++++++------------
be/src/vec/functions/function.h | 6 +-
.../functions/function_datetime_string_to_string.h | 21 +++---
be/src/vec/functions/function_string.h | 1 +
be/src/vec/functions/round.h | 17 +++--
6 files changed, 63 insertions(+), 71 deletions(-)
diff --git a/be/src/vec/functions/date_time_transforms.h
b/be/src/vec/functions/date_time_transforms.h
index 0f70d446ff..94ee40221c 100644
--- a/be/src/vec/functions/date_time_transforms.h
+++ b/be/src/vec/functions/date_time_transforms.h
@@ -280,12 +280,12 @@ template <typename Transform>
struct TransformerToStringTwoArgument {
static void vector_constant(FunctionContext* context,
const PaddedPODArray<typename
Transform::FromType>& ts,
- const std::string& format,
ColumnString::Chars& res_data,
+ const StringRef& format, ColumnString::Chars&
res_data,
ColumnString::Offsets& res_offsets,
PaddedPODArray<UInt8>& null_map) {
auto len = ts.size();
res_offsets.resize(len);
- res_data.reserve(len * format.size() + len);
+ res_data.reserve(len * format.size + len);
null_map.resize_fill(len, false);
size_t offset = 0;
@@ -294,12 +294,10 @@ struct TransformerToStringTwoArgument {
size_t new_offset;
bool is_null;
if constexpr (is_specialization_of_v<Transform, FromUnixTimeImpl>)
{
- std::tie(new_offset, is_null) =
- Transform::execute(t, StringRef(format.c_str(),
format.size()), res_data,
- offset,
context->state()->timezone_obj());
- } else {
std::tie(new_offset, is_null) = Transform::execute(
- t, StringRef(format.c_str(), format.size()), res_data,
offset);
+ t, format, res_data, offset,
context->state()->timezone_obj());
+ } else {
+ std::tie(new_offset, is_null) = Transform::execute(t, format,
res_data, offset);
}
res_offsets[i] = new_offset;
null_map[i] = is_null;
diff --git a/be/src/vec/functions/function.cpp
b/be/src/vec/functions/function.cpp
index 91ab3f71ed..cdeff0678a 100644
--- a/be/src/vec/functions/function.cpp
+++ b/be/src/vec/functions/function.cpp
@@ -128,8 +128,8 @@ NullPresence get_null_presence(const Block& block, const
ColumnNumbers& args) {
return res;
}
-bool allArgumentsAreConstants(const Block& block, const ColumnNumbers& args) {
- for (auto arg : args) {
+bool all_arguments_are_constant(const Block& block, const ColumnNumbers& args)
{
+ for (const auto& arg : args) {
if (!is_column_const(*block.get_by_position(arg).column)) {
return false;
}
@@ -138,53 +138,51 @@ bool allArgumentsAreConstants(const Block& block, const
ColumnNumbers& args) {
}
} // namespace
+inline Status PreparedFunctionImpl::_execute_skipped_constant_deal(
+ FunctionContext* context, Block& block, const ColumnNumbers& args,
size_t result,
+ size_t input_rows_count, bool dry_run) {
+ bool executed = false;
+ RETURN_IF_ERROR(default_implementation_for_nulls(context, block, args,
result, input_rows_count,
+ dry_run, &executed));
+ if (executed) {
+ return Status::OK();
+ }
+
+ if (dry_run) {
+ return execute_impl_dry_run(context, block, args, result,
input_rows_count);
+ } else {
+ return execute_impl(context, block, args, result, input_rows_count);
+ }
+}
+
Status PreparedFunctionImpl::default_implementation_for_constant_arguments(
FunctionContext* context, Block& block, const ColumnNumbers& args,
size_t result,
size_t input_rows_count, bool dry_run, bool* executed) {
*executed = false;
- ColumnNumbers arguments_to_remain_constants =
get_arguments_that_are_always_constant();
+ ColumnNumbers args_expect_const = get_arguments_that_are_always_constant();
- /// Check that these arguments are really constant.
- for (auto arg_num : arguments_to_remain_constants) {
+ // Check that these arguments are really constant.
+ for (auto arg_num : args_expect_const) {
if (arg_num < args.size() &&
!is_column_const(*block.get_by_position(args[arg_num]).column)) {
- return Status::RuntimeError("Argument at index {} for function {}
must be constant",
- arg_num, get_name());
+ return Status::InvalidArgument("Argument at index {} for function
{} must be constant",
+ arg_num, get_name());
}
}
if (args.empty() || !use_default_implementation_for_constants() ||
- !allArgumentsAreConstants(block, args)) {
+ !all_arguments_are_constant(block, args)) {
return Status::OK();
}
-
+ // now all columns is const.
Block temporary_block;
- bool have_converted_columns = false;
size_t arguments_size = args.size();
for (size_t arg_num = 0; arg_num < arguments_size; ++arg_num) {
const ColumnWithTypeAndName& column =
block.get_by_position(args[arg_num]);
-
- if (arguments_to_remain_constants.end() !=
std::find(arguments_to_remain_constants.begin(),
-
arguments_to_remain_constants.end(),
- arg_num)) {
- temporary_block.insert({column.column->clone_resized(1),
column.type, column.name});
- } else {
- have_converted_columns = true;
- temporary_block.insert(
- {assert_cast<const
ColumnConst*>(column.column.get())->get_data_column_ptr(),
- column.type, column.name});
- }
- }
-
- /** When using default implementation for constants, the function requires
at least one argument
- * not in "arguments_to_remain_constants" set. Otherwise we get infinite
recursion.
- */
- if (!have_converted_columns) {
- return Status::RuntimeError(
- "Number of arguments for function {} doesn't match: the
function "
- "requires more arguments",
- get_name());
+ temporary_block.insert(
+ {assert_cast<const
ColumnConst*>(column.column.get())->get_data_column_ptr(),
+ column.type, column.name});
}
temporary_block.insert(block.get_by_position(result));
@@ -194,9 +192,9 @@ Status
PreparedFunctionImpl::default_implementation_for_constant_arguments(
temporary_argument_numbers[i] = i;
}
- RETURN_IF_ERROR(execute_without_low_cardinality_columns(
- context, temporary_block, temporary_argument_numbers,
arguments_size,
- temporary_block.rows(), dry_run));
+ RETURN_IF_ERROR(_execute_skipped_constant_deal(context, temporary_block,
+ temporary_argument_numbers,
arguments_size,
+ temporary_block.rows(),
dry_run));
ColumnPtr result_column;
/// extremely rare case, when we have function with completely const
arguments
@@ -248,21 +246,14 @@ Status
PreparedFunctionImpl::execute_without_low_cardinality_columns(
FunctionContext* context, Block& block, const ColumnNumbers& args,
size_t result,
size_t input_rows_count, bool dry_run) {
bool executed = false;
+
RETURN_IF_ERROR(default_implementation_for_constant_arguments(
context, block, args, result, input_rows_count, dry_run,
&executed));
if (executed) {
return Status::OK();
}
- RETURN_IF_ERROR(default_implementation_for_nulls(context, block, args,
result, input_rows_count,
- dry_run, &executed));
- if (executed) {
- return Status::OK();
- }
- if (dry_run)
- return execute_impl_dry_run(context, block, args, result,
input_rows_count);
- else
- return execute_impl(context, block, args, result, input_rows_count);
+ return _execute_skipped_constant_deal(context, block, args, result,
input_rows_count, dry_run);
}
Status PreparedFunctionImpl::execute(FunctionContext* context, Block& block,
diff --git a/be/src/vec/functions/function.h b/be/src/vec/functions/function.h
index a002e90760..5af021656d 100644
--- a/be/src/vec/functions/function.h
+++ b/be/src/vec/functions/function.h
@@ -90,7 +90,7 @@ protected:
/** If the function have non-zero number of arguments,
* and if all arguments are constant, that we could automatically
provide default implementation:
- * arguments are converted to ordinary columns with single value, then
function is executed as usual,
+ * arguments are converted to ordinary columns with single value which
is not const, then function is executed as usual,
* and then the result is converted to constant column.
*/
virtual bool use_default_implementation_for_constants() const { return
false; }
@@ -102,6 +102,7 @@ protected:
virtual bool use_default_implementation_for_low_cardinality_columns()
const { return true; }
/** Some arguments could remain constant during this implementation.
+ * Every argument required const must write here and no checks elsewhere.
*/
virtual ColumnNumbers get_arguments_that_are_always_constant() const {
return {}; }
@@ -116,6 +117,9 @@ private:
Status execute_without_low_cardinality_columns(FunctionContext* context,
Block& block,
const ColumnNumbers&
arguments, size_t result,
size_t input_rows_count,
bool dry_run);
+ Status _execute_skipped_constant_deal(FunctionContext* context, Block&
block,
+ const ColumnNumbers& args, size_t
result,
+ size_t input_rows_count, bool
dry_run);
};
/// Function with known arguments and return type.
diff --git a/be/src/vec/functions/function_datetime_string_to_string.h
b/be/src/vec/functions/function_datetime_string_to_string.h
index 3e14c38ef4..a5cde61268 100644
--- a/be/src/vec/functions/function_datetime_string_to_string.h
+++ b/be/src/vec/functions/function_datetime_string_to_string.h
@@ -20,6 +20,7 @@
#include "vec/columns/column_const.h"
#include "vec/columns/column_nullable.h"
#include "vec/columns/columns_number.h"
+#include "vec/common/string_ref.h"
#include "vec/data_types/data_type_date.h"
#include "vec/data_types/data_type_date_time.h"
#include "vec/data_types/data_type_nullable.h"
@@ -72,21 +73,15 @@ public:
if (arguments.size() == 2) {
const IColumn& source_col1 =
*block.get_by_position(arguments[1]).column;
- if (const auto* delta_const_column =
- typeid_cast<const ColumnConst*>(&source_col1)) {
- TransformerToStringTwoArgument<Transform>::vector_constant(
- context, sources->get_data(),
- delta_const_column->get_field().get<String>(),
col_res->get_chars(),
- col_res->get_offsets(), vec_null_map_to);
- } else {
- return Status::InternalError(
- "Illegal column {} is not const {}",
-
block.get_by_position(arguments[1]).column->get_name(), name);
- }
- } else {
+ StringRef formatter =
+ source_col1.get_data_at(0); // for both ColumnString
or ColumnConst.
TransformerToStringTwoArgument<Transform>::vector_constant(
- context, sources->get_data(), "%Y-%m-%d %H:%i:%s",
col_res->get_chars(),
+ context, sources->get_data(), formatter,
col_res->get_chars(),
col_res->get_offsets(), vec_null_map_to);
+ } else { //default argument
+ TransformerToStringTwoArgument<Transform>::vector_constant(
+ context, sources->get_data(), StringRef("%Y-%m-%d
%H:%i:%s"),
+ col_res->get_chars(), col_res->get_offsets(),
vec_null_map_to);
}
if (nullable_column) {
diff --git a/be/src/vec/functions/function_string.h
b/be/src/vec/functions/function_string.h
index 4524c2f718..855f15a611 100644
--- a/be/src/vec/functions/function_string.h
+++ b/be/src/vec/functions/function_string.h
@@ -1762,6 +1762,7 @@ private:
}
}
+ //TODO: need to be rewrited in a more efficient way. compare BMH/KMP/...
size_t split_str(size_t& pos, const StringRef str_ref, StringRef
delimiter_ref) {
size_t old_size = pos;
size_t str_size = str_ref.size;
diff --git a/be/src/vec/functions/round.h b/be/src/vec/functions/round.h
index 456d6264a2..591c9e4387 100644
--- a/be/src/vec/functions/round.h
+++ b/be/src/vec/functions/round.h
@@ -20,6 +20,8 @@
#pragma once
+#include "vec/columns/column_const.h"
+#include "vec/columns/columns_number.h"
#ifdef __SSE4_1__
#include <smmintrin.h>
#else
@@ -500,17 +502,18 @@ public:
static Status get_scale_arg(const ColumnWithTypeAndName& arguments, Int16*
scale) {
const IColumn& scale_column = *arguments.column;
- if (!is_column_const(scale_column)) {
- return Status::InvalidArgument("2nd argument for function {}
should be constant", name);
- }
- Field scale_field = assert_cast<const
ColumnConst&>(scale_column).get_field();
+ Int32 scale64 = static_cast<const ColumnInt32*>(
+ &(is_column_const(scale_column)
+ ? static_cast<const
ColumnConst*>(&scale_column)
+ ->get_data_column()
+ : scale_column))
+ ->get_element(0);
- Int64 scale64 = scale_field.get<Int64>();
if (scale64 > std::numeric_limits<Int16>::max() ||
scale64 < std::numeric_limits<Int16>::min()) {
- return Status::InvalidArgument("Scale argument for function {} is
too large: {}", name,
- scale64);
+ return Status::InvalidArgument("Scale argument for function {} is
out of bound: {}",
+ name, scale64);
}
*scale = scale64;
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]