1#include <Functions/IFunctionImpl.h>
2#include <Functions/FunctionFactory.h>
3#include <DataTypes/DataTypesNumber.h>
4#include <DataTypes/DataTypeLowCardinality.h>
5#include <Columns/ColumnsNumber.h>
6#include <Columns/ColumnLowCardinality.h>
7#include <Common/typeid_cast.h>
8
9
10namespace DB
11{
12
13class FunctionToLowCardinality: public IFunction
14{
15public:
16 static constexpr auto name = "toLowCardinality";
17 static FunctionPtr create(const Context &) { return std::make_shared<FunctionToLowCardinality>(); }
18
19 String getName() const override { return name; }
20
21 size_t getNumberOfArguments() const override { return 1; }
22
23 bool useDefaultImplementationForNulls() const override { return false; }
24 bool useDefaultImplementationForConstants() const override { return true; }
25 bool useDefaultImplementationForLowCardinalityColumns() const override { return false; }
26
27 DataTypePtr getReturnTypeImpl(const DataTypes & arguments) const override
28 {
29 if (arguments[0]->lowCardinality())
30 return arguments[0];
31
32 return std::make_shared<DataTypeLowCardinality>(arguments[0]);
33 }
34
35 void executeImpl(Block & block, const ColumnNumbers & arguments, size_t result, size_t /*input_rows_count*/) override
36 {
37 auto arg_num = arguments[0];
38 const auto & arg = block.getByPosition(arg_num);
39 auto & res = block.getByPosition(result);
40
41 if (arg.type->lowCardinality())
42 res.column = arg.column;
43 else
44 {
45 auto column = res.type->createColumn();
46 typeid_cast<ColumnLowCardinality &>(*column).insertRangeFromFullColumn(*arg.column, 0, arg.column->size());
47 res.column = std::move(column);
48 }
49 }
50};
51
52
53void registerFunctionToLowCardinality(FunctionFactory & factory)
54{
55 factory.registerFunction<FunctionToLowCardinality>();
56}
57
58}
59