#pragma once #include #include #include #include #include #include namespace DB { /// Methods, that helps dispatching over real column types. template const Type * checkAndGetDataType(const IDataType * data_type) { return typeid_cast(data_type); } template bool checkDataType(const IDataType * data_type) { return checkAndGetDataType(data_type); } template const Type * checkAndGetColumn(const IColumn * column) { return typeid_cast(column); } template bool checkColumn(const IColumn * column) { return checkAndGetColumn(column); } template const ColumnConst * checkAndGetColumnConst(const IColumn * column) { if (!column || !column->isColumnConst()) return {}; const ColumnConst * res = static_cast(column); if (!checkColumn(&res->getDataColumn())) return {}; return res; } template const Type * checkAndGetColumnConstData(const IColumn * column) { const ColumnConst * res = checkAndGetColumnConst(column); if (!res) return {}; return static_cast(&res->getDataColumn()); } template bool checkColumnConst(const IColumn * column) { return checkAndGetColumnConst(column); } /// Returns non-nullptr if column is ColumnConst with ColumnString or ColumnFixedString inside. const ColumnConst * checkAndGetColumnConstStringOrFixedString(const IColumn * column); /// Transform anything to Field. template inline std::enable_if_t, Field> toField(const T & x) { return Field(typename NearestFieldType::Type(x)); } template inline std::enable_if_t, Field> toField(const T & x, UInt32 scale) { return Field(typename NearestFieldType::Type(x, scale)); } Columns convertConstTupleToConstantElements(const ColumnConst & column); /// Returns the copy of a given block in which each column specified in /// the "arguments" parameter is replaced with its respective nested /// column if it is nullable. Block createBlockWithNestedColumns(const Block & block, const ColumnNumbers & args); /// Similar function as above. Additionally transform the result type if needed. Block createBlockWithNestedColumns(const Block & block, const ColumnNumbers & args, size_t result); template struct TypePair { using LeftType = T; using RightType = U; }; template bool callOnBasicType(TypeIndex number, F && f) { if constexpr (_int) { switch (number) { case TypeIndex::UInt8: return f(TypePair()); case TypeIndex::UInt16: return f(TypePair()); case TypeIndex::UInt32: return f(TypePair()); case TypeIndex::UInt64: return f(TypePair()); //case TypeIndex::UInt128>: return f(TypePair()); case TypeIndex::Int8: return f(TypePair()); case TypeIndex::Int16: return f(TypePair()); case TypeIndex::Int32: return f(TypePair()); case TypeIndex::Int64: return f(TypePair()); case TypeIndex::Int128: return f(TypePair()); default: break; } } if constexpr (_dec) { switch (number) { case TypeIndex::Decimal32: return f(TypePair()); case TypeIndex::Decimal64: return f(TypePair()); case TypeIndex::Decimal128: return f(TypePair()); default: break; } } if constexpr (_float) { switch (number) { case TypeIndex::Float32: return f(TypePair()); case TypeIndex::Float64: return f(TypePair()); default: break; } } return false; } /// Unroll template using TypeIndex template inline bool callOnBasicTypes(TypeIndex type_num1, TypeIndex type_num2, F && f) { if constexpr (_int) { switch (type_num1) { case TypeIndex::UInt8: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::UInt16: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::UInt32: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::UInt64: return callOnBasicType(type_num2, std::forward(f)); //case TypeIndex::UInt128: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::Int8: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::Int16: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::Int32: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::Int64: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::Int128: return callOnBasicType(type_num2, std::forward(f)); default: break; } } if constexpr (_dec) { switch (type_num1) { case TypeIndex::Decimal32: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::Decimal64: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::Decimal128: return callOnBasicType(type_num2, std::forward(f)); default: break; } } if constexpr (_float) { switch (type_num1) { case TypeIndex::Float32: return callOnBasicType(type_num2, std::forward(f)); case TypeIndex::Float64: return callOnBasicType(type_num2, std::forward(f)); default: break; } } return false; } class DataTypeDate; class DataTypeDateTime; class DataTypeString; class DataTypeFixedString; class DataTypeUUID; template class DataTypeEnum; template class DataTypeNumber; template class DataTypeDecimal; template bool callOnIndexAndDataType(TypeIndex number, F && f) { switch (number) { case TypeIndex::UInt8: return f(TypePair, T>()); case TypeIndex::UInt16: return f(TypePair, T>()); case TypeIndex::UInt32: return f(TypePair, T>()); case TypeIndex::UInt64: return f(TypePair, T>()); case TypeIndex::Int8: return f(TypePair, T>()); case TypeIndex::Int16: return f(TypePair, T>()); case TypeIndex::Int32: return f(TypePair, T>()); case TypeIndex::Int64: return f(TypePair, T>()); case TypeIndex::Float32: return f(TypePair, T>()); case TypeIndex::Float64: return f(TypePair, T>()); case TypeIndex::Decimal32: return f(TypePair, T>()); case TypeIndex::Decimal64: return f(TypePair, T>()); case TypeIndex::Decimal128: return f(TypePair, T>()); case TypeIndex::Date: return f(TypePair()); case TypeIndex::DateTime: return f(TypePair()); case TypeIndex::String: return f(TypePair()); case TypeIndex::FixedString: return f(TypePair()); case TypeIndex::Enum8: return f(TypePair, T>()); case TypeIndex::Enum16: return f(TypePair, T>()); case TypeIndex::UUID: return f(TypePair()); default: break; } return false; } }