DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override { if (arguments.size() != 3 && arguments.size() != 4) throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " + toString(arguments.size()) + ", should be 3 or 4", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); if (!isString(arguments[0])) throw Exception("First argument for function " + getName() + " (unit) must be String", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); if (!isDateOrDateTime(arguments[1])) throw Exception("Second argument for function " + getName() + " must be Date or DateTime", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); if (!isDateOrDateTime(arguments[2])) throw Exception("Third argument for function " + getName() + " must be Date or DateTime", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); if (arguments.size() == 4 && !isString(arguments[3])) throw Exception("Fourth argument for function " + getName() + " (timezone) must be String", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); return std::make_shared<DataTypeInt64>(); }
SumMapArgs parseArguments(const std::string & name, const DataTypes & arguments) { if (arguments.size() < 2) throw Exception("Aggregate function " + name + " requires at least two arguments of Array type.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); const auto * array_type = checkAndGetDataType<DataTypeArray>(arguments[0].get()); if (!array_type) throw Exception("First argument for function " + name + " must be an array.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); DataTypePtr keys_type = array_type->getNestedType(); DataTypes values_types; values_types.reserve(arguments.size() - 1); for (size_t i = 1; i < arguments.size(); ++i) { array_type = checkAndGetDataType<DataTypeArray>(arguments[i].get()); if (!array_type) throw Exception("Argument #" + toString(i) + " for function " + name + " must be an array.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); values_types.push_back(array_type->getNestedType()); } return {std::move(keys_type), std::move(values_types)}; }
DataTypePtr getReturnType(const DataTypes & arguments) const override { if (arguments.size() != 3) throw Exception("Number of arguments for function " + getName() + " doesn't match: passed " + toString(arguments.size()) + ", should be 3.", ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); for (size_t i : ext::range(0, 3)) if (!typeid_cast<const DataTypeString *>(&*arguments[i])) throw Exception("Illegal type " + arguments[i]->getName() + " of argument of function " + getName() + ", must be String", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); return std::make_shared<DataTypeString>(); }
void DictionaryStructure::validateKeyTypes(const DataTypes & key_types) const { if (key_types.size() != key.value().size()) throw Exception{ "Key structure does not match, expected " + getKeyDescription(), ErrorCodes::TYPE_MISMATCH}; for (const auto i : ext::range(0, key_types.size())) { const auto & expected_type = (*key)[i].type->getName(); const auto & actual_type = key_types[i]->getName(); if (expected_type != actual_type) throw Exception{ "Key type at position " + std::to_string(i) + " does not match, expected " + expected_type + ", found " + actual_type, ErrorCodes::TYPE_MISMATCH}; } }
DataTypePtr FunctionCoalesce::getReturnTypeImpl(const DataTypes & arguments) const { DataTypes new_args; for (size_t i = 0; i < arguments.size(); ++i) { new_args.push_back(std::make_shared<DataTypeUInt8>()); new_args.push_back(arguments[i]); } new_args.push_back(std::make_shared<DataTypeNull>()); return FunctionMultiIf{}.getReturnTypeImpl(new_args); }
DataTypePtr FunctionCoalesce::getReturnTypeImpl(const DataTypes & arguments) const { /// Skip all NULL arguments. If any argument is non-Nullable, skip all next arguments. DataTypes filtered_args; filtered_args.reserve(arguments.size()); for (const auto & arg : arguments) { if (arg->onlyNull()) continue; filtered_args.push_back(arg); if (!arg->isNullable()) break; } DataTypes new_args; for (size_t i = 0; i < filtered_args.size(); ++i) { bool is_last = i + 1 == filtered_args.size(); if (is_last) { new_args.push_back(filtered_args[i]); } else { new_args.push_back(std::make_shared<DataTypeUInt8>()); new_args.push_back(removeNullable(filtered_args[i])); } } if (new_args.empty()) return std::make_shared<DataTypeNullable>(std::make_shared<DataTypeNothing>()); if (new_args.size() == 1) return new_args.front(); auto res = FunctionMultiIf{context}.getReturnTypeImpl(new_args); /// if last argument is not nullable, result should be also not nullable if (!new_args.back()->isNullable() && res->isNullable()) res = removeNullable(res); return res; }
DataTypePtr getReturnTypeImpl(const DataTypes & args) const override { /// Arguments are the following: cond1, then1, cond2, then2, ... condN, thenN, else. auto for_conditions = [&args](auto && f) { size_t conditions_end = args.size() - 1; for (size_t i = 0; i < conditions_end; i += 2) f(args[i]); }; auto for_branches = [&args](auto && f) { size_t branches_end = args.size(); for (size_t i = 1; i < branches_end; i += 2) f(args[i]); f(args.back()); }; if (!(args.size() >= 3 && args.size() % 2 == 1)) throw Exception{"Invalid number of arguments for function " + getName(), ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH}; /// Conditions must be UInt8, Nullable(UInt8) or Null. If one of conditions is Nullable, the result is also Nullable. bool have_nullable_condition = false; for_conditions([&](const DataTypePtr & arg) { const IDataType * nested_type; if (arg->isNullable()) { have_nullable_condition = true; if (arg->onlyNull()) return; const DataTypeNullable & nullable_type = static_cast<const DataTypeNullable &>(*arg); nested_type = nullable_type.getNestedType().get(); } else { nested_type = arg.get(); } if (!WhichDataType(nested_type).isUInt8()) throw Exception{"Illegal type " + arg->getName() + " of argument (condition) " "of function " + getName() + ". Must be UInt8.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT}; }); DataTypes types_of_branches; types_of_branches.reserve(args.size() / 2 + 1); for_branches([&](const DataTypePtr & arg) { types_of_branches.emplace_back(arg); }); DataTypePtr common_type_of_branches = getLeastSupertype(types_of_branches); return have_nullable_condition ? makeNullable(common_type_of_branches) : common_type_of_branches; }
AggregateFunctionPtr AggregateFunctionFactory::get(const String & name, const DataTypes & argument_types, int recursion_level) const { auto it = aggregate_functions.find(name); if (it != aggregate_functions.end()) { const auto & desc = it->second; const auto & creator = desc.creator; return creator(name, argument_types); } else if ((recursion_level == 0) && endsWith<SuffixState>(name)) { /// Для агрегатных функций вида aggState, где agg - имя другой агрегатной функции. AggregateFunctionPtr nested = get(trimRight<SuffixState>(name), argument_types, recursion_level + 1); return createAggregateFunctionState(nested); } else if ((recursion_level <= 1) && endsWith<SuffixMerge>(name)) { /// Для агрегатных функций вида aggMerge, где agg - имя другой агрегатной функции. if (argument_types.size() != 1) throw Exception("Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH); const DataTypeAggregateFunction * function = typeid_cast<const DataTypeAggregateFunction *>(&*argument_types[0]); if (!function) throw Exception("Illegal type " + argument_types[0]->getName() + " of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); AggregateFunctionPtr nested = get(trimRight<SuffixMerge>(name), function->getArgumentsDataTypes(), recursion_level + 1); if (nested->getName() != function->getFunctionName()) throw Exception("Illegal type " + argument_types[0]->getName() + " of argument for aggregate function " + name, ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); return createAggregateFunctionMerge(nested); } else if ((recursion_level <= 2) && endsWith<SuffixIf>(name)) { if (argument_types.empty()) throw Exception{ "Incorrect number of arguments for aggregate function " + name, ErrorCodes::NUMBER_OF_ARGUMENTS_DOESNT_MATCH }; /// Для агрегатных функций вида aggIf, где agg - имя другой агрегатной функции. DataTypes nested_dt = argument_types; nested_dt.pop_back(); AggregateFunctionPtr nested = get(trimRight<SuffixIf>(name), nested_dt, recursion_level + 1); return createAggregateFunctionIf(nested); } else if ((recursion_level <= 3) && endsWith<SuffixArray>(name)) { /// Для агрегатных функций вида aggArray, где agg - имя другой агрегатной функции. size_t num_agruments = argument_types.size(); DataTypes nested_arguments; for (size_t i = 0; i < num_agruments; ++i) { if (const DataTypeArray * array = typeid_cast<const DataTypeArray *>(&*argument_types[i])) nested_arguments.push_back(array->getNestedType()); else throw Exception("Illegal type " + argument_types[i]->getName() + " of argument #" + toString(i + 1) + " for aggregate function " + name + ". Must be array.", ErrorCodes::ILLEGAL_TYPE_OF_ARGUMENT); } /// + 3, чтобы ни один другой модификатор не мог идти перед Array AggregateFunctionPtr nested = get(trimRight<SuffixArray>(name), nested_arguments, recursion_level + 3); return createAggregateFunctionArray(nested); } else throw Exception("Unknown aggregate function " + name, ErrorCodes::UNKNOWN_AGGREGATE_FUNCTION); }