#include #include #include #include #include #include #include #include #include namespace DB { namespace ErrorCodes { extern const int ILLEGAL_COLUMN; extern const int NUMBER_OF_ARGUMENTS_DOESNT_MATCH; } const ColumnConst * checkAndGetColumnConstStringOrFixedString(const IColumn * column) { if (!isColumnConst(*column)) return {}; const ColumnConst * res = assert_cast(column); if (checkColumn(&res->getDataColumn()) || checkColumn(&res->getDataColumn())) return res; return {}; } Columns convertConstTupleToConstantElements(const ColumnConst & column) { const ColumnTuple & src_tuple = assert_cast(column.getDataColumn()); const auto & src_tuple_columns = src_tuple.getColumns(); size_t tuple_size = src_tuple_columns.size(); size_t rows = column.size(); Columns res(tuple_size); for (size_t i = 0; i < tuple_size; ++i) res[i] = ColumnConst::create(src_tuple_columns[i], rows); return res; } static Block createBlockWithNestedColumnsImpl(const Block & block, const std::unordered_set & args) { Block res; size_t columns = block.columns(); for (size_t i = 0; i < columns; ++i) { const auto & col = block.getByPosition(i); if (args.count(i) && col.type->isNullable()) { const DataTypePtr & nested_type = static_cast(*col.type).getNestedType(); if (!col.column) { res.insert({nullptr, nested_type, col.name}); } else if (auto * nullable = checkAndGetColumn(*col.column)) { const auto & nested_col = nullable->getNestedColumnPtr(); res.insert({nested_col, nested_type, col.name}); } else if (auto * const_column = checkAndGetColumn(*col.column)) { const auto & nested_col = checkAndGetColumn(const_column->getDataColumn())->getNestedColumnPtr(); res.insert({ ColumnConst::create(nested_col, col.column->size()), nested_type, col.name}); } else throw Exception("Illegal column for DataTypeNullable", ErrorCodes::ILLEGAL_COLUMN); } else res.insert(col); } return res; } Block createBlockWithNestedColumns(const Block & block, const ColumnNumbers & args) { std::unordered_set args_set(args.begin(), args.end()); return createBlockWithNestedColumnsImpl(block, args_set); } Block createBlockWithNestedColumns(const Block & block, const ColumnNumbers & args, size_t result) { std::unordered_set args_set(args.begin(), args.end()); args_set.insert(result); return createBlockWithNestedColumnsImpl(block, args_set); } void validateArgumentType(const IFunction & func, const DataTypes & arguments, size_t argument_index, bool (* validator_func)(const IDataType &), const char * expected_type_description) { if (arguments.size() <= argument_index) throw Exception("Incorrect number of arguments of function " + func.getName(), ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); const auto & argument = arguments[argument_index]; if (validator_func(*argument) == false) throw Exception("Illegal type " + argument->getName() + " of " + std::to_string(argument_index) + " argument of function " + func.getName() + " expected " + expected_type_description, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } namespace { void validateArgumentsImpl(const IFunction & func, const ColumnsWithTypeAndName & arguments, size_t argument_offset, const FunctionArgumentTypeValidators & validators) { for (size_t i = 0; i < validators.size(); ++i) { const auto argument_index = i + argument_offset; if (argument_index >= arguments.size()) { break; } const auto & arg = arguments[i + argument_offset]; const auto validator = validators[i]; if (validator.validator_func(*arg.type) == false) throw Exception("Illegal type " + arg.type->getName() + " of " + std::to_string(i) + " argument of function " + func.getName() + " expected " + validator.expected_type_description, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } } } void validateFunctionArgumentTypes(const IFunction & func, const ColumnsWithTypeAndName & arguments, const FunctionArgumentTypeValidators & mandatory_args, const FunctionArgumentTypeValidators & optional_args) { if (arguments.size() < mandatory_args.size()) throw Exception("Incorrect number of arguments of function " + func.getName() + " provided: " + std::to_string(arguments.size()) + " expected: " + std::to_string(mandatory_args.size()) + (optional_args.size() ? " or " + std::to_string(mandatory_args.size() + optional_args.size()) : ""), ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); validateArgumentsImpl(func, arguments, 0, mandatory_args); if (optional_args.size()) { validateArgumentsImpl(func, arguments, mandatory_args.size(), optional_args); } } }