Skip to content

Commit e35cc54

Browse files
Merge pull request ClickHouse#89900 from ClickHouse/backport/25.8/89850
Backport ClickHouse#89850 to 25.8: Fix logical error with empty tuple inside IN function
2 parents f20dc25 + 4f5c320 commit e35cc54

File tree

7 files changed

+168
-10
lines changed

7 files changed

+168
-10
lines changed

src/Analyzer/SetUtils.cpp

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -42,16 +42,13 @@ size_t getCompoundTypeDepth(const IDataType & type)
4242
else if (which_type.isTuple())
4343
{
4444
const auto & tuple_elements = assert_cast<const DataTypeTuple &>(*current_type).getElements();
45+
++result;
4546
if (!tuple_elements.empty())
4647
current_type = tuple_elements.at(0).get();
4748
else
4849
{
49-
/// Special case: tuple with no element - tuple(). In this case, what's the compound type depth?
50-
/// I'm not certain about the theoretical answer, but from experiment, 1 is the most reasonable choice.
51-
return 1;
50+
break;
5251
}
53-
54-
++result;
5552
}
5653
else
5754
{
@@ -162,7 +159,8 @@ ColumnsWithTypeAndName getSetElementsForConstantValue(const DataTypePtr & expres
162159
DataTypes set_element_types = {expression_type};
163160
const auto * lhs_tuple_type = typeid_cast<const DataTypeTuple *>(expression_type.get());
164161

165-
if (lhs_tuple_type && lhs_tuple_type->getElements().size() != 1)
162+
/// Do not unpack if empty tuple or single element tuple
163+
if (lhs_tuple_type && lhs_tuple_type->getElements().size() > 1)
166164
set_element_types = lhs_tuple_type->getElements();
167165

168166
for (auto & set_element_type : set_element_types)

src/Interpreters/ActionsVisitor.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -461,7 +461,9 @@ FutureSetPtr makeExplicitSet(
461461

462462
DataTypes set_element_types = {left_arg_type};
463463
const auto * left_tuple_type = typeid_cast<const DataTypeTuple *>(left_arg_type.get());
464-
if (left_tuple_type && left_tuple_type->getElements().size() != 1)
464+
465+
/// Do not unpack if empty tuple or single element tuple.
466+
if (left_tuple_type && left_tuple_type->getElements().size() > 1)
465467
set_element_types = left_tuple_type->getElements();
466468

467469
auto set_element_keys = Set::getElementTypes(set_element_types, context->getSettingsRef()[Setting::transform_null_in]);

src/Planner/CollectSets.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,9 @@ class CollectSetsVisitor : public ConstInDepthQueryTreeVisitor<CollectSetsVisito
8181

8282
DataTypes set_element_types = {in_first_argument->getResultType()};
8383
const auto * left_tuple_type = typeid_cast<const DataTypeTuple *>(set_element_types.front().get());
84-
if (left_tuple_type && left_tuple_type->getElements().size() != 1)
84+
85+
/// Do not unpack if empty tuple or single element tuple
86+
if (left_tuple_type && left_tuple_type->getElements().size() > 1)
8587
set_element_types = left_tuple_type->getElements();
8688

8789
set_element_types = Set::getElementTypes(std::move(set_element_types), settings[Setting::transform_null_in]);

src/Planner/PlannerActionsVisitor.cpp

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -947,7 +947,9 @@ PlannerActionsVisitorImpl::NodeNameAndNodeMinLevel PlannerActionsVisitorImpl::ma
947947
{
948948
set_element_types = {in_first_argument->getResultType()};
949949
const auto * left_tuple_type = typeid_cast<const DataTypeTuple *>(set_element_types.front().get());
950-
if (left_tuple_type && left_tuple_type->getElements().size() != 1)
950+
951+
/// Do not unpack if empty tuple or single element tuple
952+
if (left_tuple_type && left_tuple_type->getElements().size() > 1)
951953
set_element_types = left_tuple_type->getElements();
952954

953955
set_element_types
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
SELECT tuple() IN tuple(1) SETTINGS allow_experimental_map_type = 1; -- { serverError INCORRECT_ELEMENT_OF_SET }
1+
SELECT tuple() IN tuple(1) SETTINGS allow_experimental_map_type = 1; -- { serverError TYPE_MISMATCH }
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
1
2+
1
3+
1
4+
0
5+
1
6+
1
7+
1
8+
1
9+
1
10+
1
11+
1
12+
()
13+
()
14+
()
15+
()
16+
()
17+
()
18+
()
19+
()
20+
()
21+
()
22+
()
23+
()
24+
()
25+
()
26+
()
27+
()
28+
()
29+
()
30+
3
31+
1
32+
1
33+
1
34+
1
35+
1
36+
0
37+
1
38+
1
39+
1
40+
1
41+
1
42+
1
43+
1
44+
()
45+
()
46+
()
47+
()
48+
()
49+
()
50+
()
51+
()
52+
()
53+
()
54+
()
55+
()
56+
()
57+
()
58+
()
59+
()
60+
()
61+
()
62+
3
63+
1
64+
1
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
SELECT CAST(tuple(), 'Tuple()') IN (tuple());
2+
3+
SELECT CAST(tuple(), 'Tuple()') IN [tuple()];
4+
5+
SELECT CAST(tuple(), 'Tuple()') IN [tuple(), tuple()];
6+
7+
SELECT CAST(tuple(), 'Tuple()') NOT IN (tuple());
8+
9+
SELECT CAST(tuple(), 'Tuple()') IN (tuple(1));-- { serverError TYPE_MISMATCH }
10+
11+
SELECT CAST(tuple(), 'Tuple()') IN [()];
12+
13+
SELECT CAST(tuple(), 'Tuple()') IN (());
14+
15+
SELECT tuple() IN (tuple());
16+
17+
SELECT [tuple()] IN [[tuple()], [tuple()]];
18+
19+
SELECT [tuple()] IN [()];
20+
21+
SELECT tuple() IN (((tuple())));
22+
23+
SELECT tuple() IN [(((tuple())))];
24+
25+
DROP TABLE IF EXISTS test_empty_tuple;
26+
CREATE TABLE test_empty_tuple (t Tuple()) ENGINE = Memory;
27+
INSERT INTO test_empty_tuple VALUES (tuple()), (tuple()), (tuple());
28+
29+
SELECT t FROM test_empty_tuple WHERE t IN (tuple());
30+
31+
SELECT t FROM test_empty_tuple WHERE t IN [tuple()];
32+
33+
SELECT t FROM test_empty_tuple WHERE t IN [()];
34+
35+
SELECT t FROM test_empty_tuple WHERE t IN [tuple(), tuple()];
36+
37+
SELECT t FROM test_empty_tuple WHERE t IN tuple();
38+
39+
SELECT t FROM test_empty_tuple WHERE [t] IN [tuple()];
40+
41+
SELECT count() FROM test_empty_tuple WHERE t IN [tuple()];
42+
43+
SELECT arrayJoin([tuple(), tuple()]) IN (tuple());
44+
45+
46+
SET enable_analyzer = 0;
47+
48+
SELECT CAST(tuple(), 'Tuple()') IN (tuple());
49+
50+
SELECT CAST(tuple(), 'Tuple()') IN [tuple()];
51+
52+
SELECT CAST(tuple(), 'Tuple()') IN [tuple(), tuple()];
53+
54+
SELECT CAST(tuple(), 'Tuple()') NOT IN (tuple());
55+
56+
SELECT CAST(tuple(), 'Tuple()') IN (tuple(1));-- { serverError TYPE_MISMATCH }
57+
58+
SELECT CAST(tuple(), 'Tuple()') IN [()];
59+
60+
SELECT CAST(tuple(), 'Tuple()') IN (());
61+
62+
SELECT tuple() IN (tuple());
63+
64+
SELECT [tuple()] IN [[tuple()], [tuple()]];
65+
66+
SELECT [tuple()] IN [()];
67+
68+
SELECT tuple() IN (((tuple())));
69+
70+
SELECT tuple() IN [(((tuple())))];
71+
72+
DROP TABLE IF EXISTS test_empty_tuple;
73+
CREATE TABLE test_empty_tuple (t Tuple()) ENGINE = Memory;
74+
INSERT INTO test_empty_tuple VALUES (tuple()), (tuple()), (tuple());
75+
76+
SELECT t FROM test_empty_tuple WHERE t IN (tuple());
77+
78+
SELECT t FROM test_empty_tuple WHERE t IN [tuple()];
79+
80+
SELECT t FROM test_empty_tuple WHERE t IN [()];
81+
82+
SELECT t FROM test_empty_tuple WHERE t IN [tuple(), tuple()];
83+
84+
SELECT t FROM test_empty_tuple WHERE t IN tuple();
85+
86+
SELECT t FROM test_empty_tuple WHERE [t] IN [tuple()];
87+
88+
SELECT count() FROM test_empty_tuple WHERE t IN [tuple()];
89+
90+
SELECT arrayJoin([tuple(), tuple()]) IN (tuple());

0 commit comments

Comments
 (0)