1#include <Common/typeid_cast.h>
2#include <Common/assert_cast.h>
3#include <Columns/FilterDescription.h>
4#include <Columns/ColumnsNumber.h>
5#include <Columns/ColumnNullable.h>
6#include <Columns/ColumnConst.h>
7#include <Core/ColumnWithTypeAndName.h>
8
9
10namespace DB
11{
12
13namespace ErrorCodes
14{
15 extern const int ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER;
16}
17
18
19ConstantFilterDescription::ConstantFilterDescription(const IColumn & column)
20{
21 if (column.onlyNull())
22 {
23 always_false = true;
24 return;
25 }
26
27 if (isColumnConst(column))
28 {
29 const ColumnConst & column_const = assert_cast<const ColumnConst &>(column);
30 ColumnPtr column_nested = column_const.getDataColumnPtr()->convertToFullColumnIfLowCardinality();
31
32 if (!typeid_cast<const ColumnUInt8 *>(column_nested.get()))
33 {
34 const ColumnNullable * column_nested_nullable = checkAndGetColumn<ColumnNullable>(*column_nested);
35 if (!column_nested_nullable || !typeid_cast<const ColumnUInt8 *>(&column_nested_nullable->getNestedColumn()))
36 {
37 throw Exception("Illegal type " + column_nested->getName() + " of column for constant filter. Must be UInt8 or Nullable(UInt8).",
38 ErrorCodes::ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER);
39 }
40 }
41
42 if (column_const.getValue<UInt64>())
43 always_true = true;
44 else
45 always_false = true;
46 return;
47 }
48}
49
50
51FilterDescription::FilterDescription(const IColumn & column_)
52{
53 if (column_.lowCardinality())
54 data_holder = column_.convertToFullColumnIfLowCardinality();
55
56 const auto & column = data_holder ? *data_holder : column_;
57
58 if (const ColumnUInt8 * concrete_column = typeid_cast<const ColumnUInt8 *>(&column))
59 {
60 data = &concrete_column->getData();
61 return;
62 }
63
64 if (auto * nullable_column = checkAndGetColumn<ColumnNullable>(column))
65 {
66 ColumnPtr nested_column = nullable_column->getNestedColumnPtr();
67 MutableColumnPtr mutable_holder = (*std::move(nested_column)).mutate();
68
69 ColumnUInt8 * concrete_column = typeid_cast<ColumnUInt8 *>(mutable_holder.get());
70 if (!concrete_column)
71 throw Exception("Illegal type " + column.getName() + " of column for filter. Must be UInt8 or Nullable(UInt8).",
72 ErrorCodes::ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER);
73
74 const NullMap & null_map = nullable_column->getNullMapData();
75 IColumn::Filter & res = concrete_column->getData();
76
77 size_t size = res.size();
78 for (size_t i = 0; i < size; ++i)
79 res[i] = res[i] && !null_map[i];
80
81 data = &res;
82 data_holder = std::move(mutable_holder);
83 return;
84 }
85
86 throw Exception("Illegal type " + column.getName() + " of column for filter. Must be UInt8 or Nullable(UInt8) or Const variants of them.",
87 ErrorCodes::ILLEGAL_TYPE_OF_COLUMN_FOR_FILTER);
88}
89
90
91void checkColumnCanBeUsedAsFilter(const ColumnWithTypeAndName & column_elem)
92{
93 ConstantFilterDescription const_filter;
94 if (column_elem.column)
95 const_filter = ConstantFilterDescription(*column_elem.column);
96
97 if (!const_filter.always_false && !const_filter.always_true)
98 {
99 auto column = column_elem.column ? column_elem.column : column_elem.type->createColumn();
100 FilterDescription filter(*column);
101 }
102}
103
104}
105