Skip to content

Commit aa02e42

Browse files
Merge pull request ClickHouse#80596 from ClickHouse/fix-const-tuple
Fix analyzer: constant tuple in distributed query should use CAST.
2 parents 50324cd + 29eee06 commit aa02e42

File tree

4 files changed

+38
-53
lines changed

4 files changed

+38
-53
lines changed

src/Analyzer/ConstantNode.cpp

Lines changed: 12 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -55,58 +55,10 @@ String ConstantNode::getValueStringRepresentation() const
5555
return applyVisitor(FieldVisitorToString(), getValue());
5656
}
5757

58-
bool ConstantNode::requiresCastCall(Field::Types::Which type, const DataTypePtr & field_type, const DataTypePtr & data_type)
59-
{
60-
bool need_to_add_cast_function = false;
61-
WhichDataType constant_value_type(data_type);
62-
63-
switch (type)
64-
{
65-
case Field::Types::String:
66-
{
67-
need_to_add_cast_function = !constant_value_type.isString();
68-
break;
69-
}
70-
case Field::Types::UInt64:
71-
case Field::Types::Int64:
72-
case Field::Types::Float64:
73-
{
74-
WhichDataType constant_value_field_type(field_type);
75-
need_to_add_cast_function = constant_value_field_type.idx != constant_value_type.idx;
76-
break;
77-
}
78-
case Field::Types::Int128:
79-
case Field::Types::UInt128:
80-
case Field::Types::Int256:
81-
case Field::Types::UInt256:
82-
case Field::Types::Decimal32:
83-
case Field::Types::Decimal64:
84-
case Field::Types::Decimal128:
85-
case Field::Types::Decimal256:
86-
case Field::Types::AggregateFunctionState:
87-
case Field::Types::Array:
88-
case Field::Types::Tuple:
89-
case Field::Types::Map:
90-
case Field::Types::UUID:
91-
case Field::Types::Bool:
92-
case Field::Types::Object:
93-
case Field::Types::IPv4:
94-
case Field::Types::IPv6:
95-
case Field::Types::Null:
96-
case Field::Types::CustomType:
97-
{
98-
need_to_add_cast_function = true;
99-
break;
100-
}
101-
}
102-
103-
return need_to_add_cast_function;
104-
}
105-
10658
bool ConstantNode::requiresCastCall(const DataTypePtr & field_type, const DataTypePtr & data_type)
10759
{
10860
WhichDataType which_field_type(field_type);
109-
if (which_field_type.isNullable() || which_field_type.isArray())
61+
if (which_field_type.isNullable() || which_field_type.isArray() || which_field_type.isTuple())
11062
return true;
11163

11264
return field_type->getTypeId() != data_type->getTypeId();
@@ -203,21 +155,29 @@ ASTPtr ConstantNode::toASTImpl(const ConvertToASTOptions & options) const
203155
return std::make_shared<ASTLiteral>(getFieldFromColumnForASTLiteral(constant_value.getColumn(), 0, constant_value.getType()));
204156

205157
const auto & constant_value_type = constant_value.getType();
206-
auto constant_value_ast = std::make_shared<ASTLiteral>(getValue());
207158

208159
// Add cast if constant was created as a result of constant folding.
209160
// Constant folding may lead to type transformation and literal on shard
210161
// may have a different type.
211-
if (source_expression != nullptr || requiresCastCall(constant_value_ast->value.getType(), applyVisitor(FieldToDataType(), constant_value_ast->value), getResultType()))
162+
163+
auto requires_cast = [this]()
164+
{
165+
const auto & [_, type] = getValueNameAndType();
166+
return requiresCastCall(type, getResultType());
167+
};
168+
169+
if (source_expression != nullptr || requires_cast())
212170
{
213171
/// For some types we cannot just get a field from a column, because it can loose type information during serialization/deserialization of the literal.
214172
/// For example, DateTime64 will return Field with Decimal64 and we won't be able to parse it to DateTine64 back in some cases.
215173
/// Also for Dynamic and Object types we can loose types information, so we need to create a Field carefully.
216-
constant_value_ast = std::make_shared<ASTLiteral>(getFieldFromColumnForASTLiteral(constant_value.getColumn(), 0, constant_value.getType()));
174+
auto constant_value_ast = std::make_shared<ASTLiteral>(getFieldFromColumnForASTLiteral(constant_value.getColumn(), 0, constant_value.getType()));
217175
auto constant_type_name_ast = std::make_shared<ASTLiteral>(constant_value_type->getName());
218176
return makeASTFunction("_CAST", std::move(constant_value_ast), std::move(constant_type_name_ast));
219177
}
220178

179+
auto constant_value_ast = std::make_shared<ASTLiteral>(getValue());
180+
221181
if (isBool(constant_value_type))
222182
constant_value_ast->custom_type = constant_value_type;
223183

src/Analyzer/ConstantNode.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,6 @@ class ConstantNode final : public IQueryTreeNode
9191
}
9292

9393
/// Check if conversion to AST requires wrapping with _CAST function.
94-
static bool requiresCastCall(Field::Types::Which type, const DataTypePtr & field_type, const DataTypePtr & data_type);
9594
static bool requiresCastCall(const DataTypePtr & field_type, const DataTypePtr & data_type);
9695

9796
/// Check if constant is a result of _CAST function constant folding.
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
2 (-9,0)
2+
2 (-8,1)
3+
2 {1:1}
4+
2 {1:2}
5+
(1,2)
6+
(3,4)
7+
(1,2)
8+
(1,2)
9+
1 ('dete','ok') ('dete','ok')
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
set enable_analyzer=1;
2+
3+
DROP TABLE IF EXISTS test, src;
4+
5+
SELECT count(), plus((-9, 0), (number, number)) AS k FROM remote('127.0.0.{3,2}', numbers(2)) GROUP BY k ORDER BY k;
6+
SELECT count(), mapAdd(map(1::UInt128, 1), map(1::UInt128 ,number)) AS k FROM remote('127.0.0.{3,2}', numbers(2)) GROUP BY k ORDER BY k;
7+
8+
CREATE TABLE test (s String) ORDER BY ();
9+
INSERT INTO test VALUES ('a'), ('b');
10+
SELECT transform(s, ['a', 'b'], [(1, 2), (3, 4)], (0, 0)) AS k FROM test ORDER BY k;
11+
SELECT s != '' ? (1,2) : (0,0) AS k FROM test ORDER BY k;
12+
13+
CREATE TABLE src (id UInt32, type String, data String) ENGINE=MergeTree ORDER BY tuple();
14+
INSERT INTO src VALUES (1, 'ok', 'data');
15+
SELECT id, tuple(replaceAll(data, 'a', 'e') AS col_a, type) AS a, tuple(replaceAll(data, 'a', 'e') AS col_b, type) AS b FROM src;
16+
17+
DROP TABLE IF EXISTS test, src;

0 commit comments

Comments
 (0)