mirror of
https://github.com/ClickHouse/ClickHouse.git
synced 2024-11-22 15:42:02 +00:00
Support nullable columns (with default behavior) in jitted functions
This commit is contained in:
parent
4bd0906613
commit
1bece1de46
@ -1,3 +1,7 @@
|
||||
#include <Columns/ColumnVector.h>
|
||||
#include <Common/typeid_cast.h>
|
||||
#include <DataTypes/DataTypeNullable.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <Interpreters/ExpressionJIT.h>
|
||||
|
||||
#include <llvm/IR/BasicBlock.h>
|
||||
@ -32,6 +36,14 @@ namespace ErrorCodes
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static bool typeIsA(const DataTypePtr & type)
|
||||
{
|
||||
if (auto * nullable = typeid_cast<const DataTypeNullable *>(type.get()))
|
||||
return typeIsA<T>(nullable->getNestedType());
|
||||
return typeid_cast<const T *>(type.get());;
|
||||
}
|
||||
|
||||
struct LLVMContext::Data
|
||||
{
|
||||
llvm::LLVMContext context;
|
||||
@ -57,17 +69,17 @@ struct LLVMContext::Data
|
||||
llvm::Type * toNativeType(const DataTypePtr & type)
|
||||
{
|
||||
// LLVM doesn't have unsigned types, it has unsigned instructions.
|
||||
if (type->equals(DataTypeInt8{}) || type->equals(DataTypeUInt8{}))
|
||||
if (typeIsA<DataTypeInt8>(type) || typeIsA<DataTypeUInt8>(type))
|
||||
return builder.getInt8Ty();
|
||||
if (type->equals(DataTypeInt16{}) || type->equals(DataTypeUInt16{}))
|
||||
if (typeIsA<DataTypeInt16>(type) || typeIsA<DataTypeUInt16>(type))
|
||||
return builder.getInt16Ty();
|
||||
if (type->equals(DataTypeInt32{}) || type->equals(DataTypeUInt32{}))
|
||||
if (typeIsA<DataTypeInt32>(type) || typeIsA<DataTypeUInt32>(type))
|
||||
return builder.getInt32Ty();
|
||||
if (type->equals(DataTypeInt64{}) || type->equals(DataTypeUInt64{}))
|
||||
if (typeIsA<DataTypeInt64>(type) || typeIsA<DataTypeUInt64>(type))
|
||||
return builder.getInt64Ty();
|
||||
if (type->equals(DataTypeFloat32{}))
|
||||
if (typeIsA<DataTypeFloat32>(type))
|
||||
return builder.getFloatTy();
|
||||
if (type->equals(DataTypeFloat64{}))
|
||||
if (typeIsA<DataTypeFloat64>(type))
|
||||
return builder.getDoubleTy();
|
||||
return nullptr;
|
||||
}
|
||||
@ -115,6 +127,36 @@ LLVMPreparedFunction::LLVMPreparedFunction(LLVMContext context, std::shared_ptr<
|
||||
: parent(parent), context(context), function(context->lookup(parent->getName()))
|
||||
{}
|
||||
|
||||
static MutableColumnPtr createNonNullableColumn(const DataTypePtr & type)
|
||||
{
|
||||
if (auto * nullable = typeid_cast<const DataTypeNullable *>(type.get()))
|
||||
return createNonNullableColumn(nullable->getNestedType());
|
||||
return type->createColumn();
|
||||
}
|
||||
|
||||
void LLVMPreparedFunction::executeImpl(Block & block, const ColumnNumbers & arguments, size_t result)
|
||||
{
|
||||
size_t block_size = 0;
|
||||
std::vector<const void *> columns(arguments.size());
|
||||
std::vector<char> is_const(arguments.size());
|
||||
for (size_t i = 0; i < arguments.size(); i++)
|
||||
{
|
||||
auto * column = block.getByPosition(arguments[i]).column.get();
|
||||
if (column->size())
|
||||
// assume the column is a `ColumnVector<T>`. there's probably no good way to actually
|
||||
// check that at runtime, so let's just hope it's always true for columns containing types
|
||||
// for which `LLVMContext::Data::toNativeType` returns non-null.
|
||||
columns[i] = column->getDataAt(0).data;
|
||||
is_const[i] = column->isColumnConst();
|
||||
block_size = column->size();
|
||||
}
|
||||
// assuming that the function has default behavior on NULL, the column will be wrapped by `PreparedFunctionImpl::execute`.
|
||||
auto col_res = createNonNullableColumn(parent->getReturnType())->cloneResized(block_size);
|
||||
if (block_size)
|
||||
function(columns.data(), is_const.data(), const_cast<char *>(col_res->getDataAt(0).data), block_size);
|
||||
block.getByPosition(result).column = std::move(col_res);
|
||||
};
|
||||
|
||||
LLVMFunction::LLVMFunction(ExpressionActions::Actions actions_, LLVMContext context)
|
||||
: actions(std::move(actions_)), context(context)
|
||||
{
|
||||
|
@ -1,7 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include <Columns/ColumnVector.h>
|
||||
#include <DataTypes/DataTypesNumber.h>
|
||||
#include <Functions/IFunction.h>
|
||||
|
||||
#include <Interpreters/ExpressionActions.h>
|
||||
@ -9,11 +7,6 @@
|
||||
namespace DB
|
||||
{
|
||||
|
||||
namespace ErrorCodes
|
||||
{
|
||||
extern const int LOGICAL_ERROR;
|
||||
}
|
||||
|
||||
class LLVMContext
|
||||
{
|
||||
struct Data;
|
||||
@ -45,54 +38,7 @@ public:
|
||||
|
||||
String getName() const override { return parent->getName(); }
|
||||
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override
|
||||
{
|
||||
size_t block_size = 0;
|
||||
std::vector<const void *> columns(arguments.size());
|
||||
std::vector<char> is_const(arguments.size());
|
||||
for (size_t i = 0; i < arguments.size(); i++)
|
||||
{
|
||||
auto * column = block.getByPosition(arguments[i]).column.get();
|
||||
if (column->size())
|
||||
// assume the column is a `ColumnVector<T>`. there's probably no good way to actually
|
||||
// check that at runtime, so let's just hope it's always true for columns containing types
|
||||
// for which `LLVMContext::Data::toNativeType` returns non-null.
|
||||
columns[i] = column->getDataAt(0).data;
|
||||
is_const[i] = column->isColumnConst();
|
||||
block_size = column->size();
|
||||
}
|
||||
auto col_res = createColumn(parent->getReturnType(), block_size);
|
||||
if (block_size)
|
||||
function(columns.data(), is_const.data(), const_cast<char *>(col_res->getDataAt(0).data), block_size);
|
||||
block.getByPosition(result).column = std::move(col_res);
|
||||
};
|
||||
|
||||
private:
|
||||
static IColumn::Ptr createColumn(const DataTypePtr & type, size_t size)
|
||||
{
|
||||
if (type->equals(DataTypeInt8{}))
|
||||
return ColumnVector<Int8>::create(size);
|
||||
if (type->equals(DataTypeInt16{}))
|
||||
return ColumnVector<Int16>::create(size);
|
||||
if (type->equals(DataTypeInt32{}))
|
||||
return ColumnVector<Int32>::create(size);
|
||||
if (type->equals(DataTypeInt64{}))
|
||||
return ColumnVector<Int64>::create(size);
|
||||
if (type->equals(DataTypeUInt8{}))
|
||||
return ColumnVector<UInt8>::create(size);
|
||||
if (type->equals(DataTypeUInt16{}))
|
||||
return ColumnVector<UInt16>::create(size);
|
||||
if (type->equals(DataTypeUInt32{}))
|
||||
return ColumnVector<UInt32>::create(size);
|
||||
if (type->equals(DataTypeUInt64{}))
|
||||
return ColumnVector<UInt64>::create(size);
|
||||
if (type->equals(DataTypeFloat32{}))
|
||||
return ColumnVector<Float32>::create(size);
|
||||
if (type->equals(DataTypeFloat64{}))
|
||||
return ColumnVector<Float64>::create(size);
|
||||
throw Exception("LLVMPreparedFunction::createColumn received an unsupported data type; check "
|
||||
"that the list is consistent with LLVMContext::Data::toNativeType", ErrorCodes::LOGICAL_ERROR);
|
||||
}
|
||||
void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result) override;
|
||||
};
|
||||
|
||||
class LLVMFunction : public std::enable_shared_from_this<LLVMFunction>, public IFunctionBase
|
||||
|
Loading…
Reference in New Issue
Block a user