Skip to content

Commit 0a29f83

Browse files
Merge pull request ClickHouse#92133 from ClickHouse/backport/25.8/91420
Backport ClickHouse#91420 to 25.8: Fix crash in `dictGetDescendants` caused by `NULL` when dictionary type has Hierarchy support but no column is `HIERARCHICAL`
2 parents 42c88e6 + 3b3470c commit 0a29f83

File tree

3 files changed

+115
-1
lines changed

3 files changed

+115
-1
lines changed

src/Functions/FunctionsExternalDictionaries.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,7 @@ class FunctionDictHelper : public WithContext
9494
return getDictionary(dict_name_col->getValue<String>());
9595
}
9696

97-
static const DictionaryAttribute & getDictionaryHierarchicalAttribute(const std::shared_ptr<const IDictionary> & dictionary)
97+
static void checkDictionaryHierarchySupport(const std::shared_ptr<const IDictionary> & dictionary)
9898
{
9999
const auto & dictionary_structure = dictionary->getStructure();
100100
auto hierarchical_attribute_index_optional = dictionary_structure.hierarchical_attribute_index;
@@ -103,6 +103,14 @@ class FunctionDictHelper : public WithContext
103103
throw Exception(ErrorCodes::UNSUPPORTED_METHOD,
104104
"Dictionary {} does not support hierarchy",
105105
dictionary->getFullName());
106+
}
107+
108+
static const DictionaryAttribute & getDictionaryHierarchicalAttribute(const std::shared_ptr<const IDictionary> & dictionary)
109+
{
110+
checkDictionaryHierarchySupport(dictionary);
111+
112+
const auto & dictionary_structure = dictionary->getStructure();
113+
auto hierarchical_attribute_index_optional = dictionary_structure.hierarchical_attribute_index;
106114

107115
size_t hierarchical_attribute_index = *hierarchical_attribute_index_optional;
108116
const auto & hierarchical_attribute = dictionary_structure.attributes[hierarchical_attribute_index];
@@ -1316,6 +1324,9 @@ class FunctionDictGetDescendantsOverloadResolverImpl final : public IFunctionOve
13161324
FunctionBasePtr buildImpl(const ColumnsWithTypeAndName & arguments, const DataTypePtr & result_type) const override
13171325
{
13181326
auto dictionary = dictionary_helper->getDictionary(arguments[0].column);
1327+
1328+
FunctionDictHelper::checkDictionaryHierarchySupport(dictionary);
1329+
13191330
auto hierarchical_parent_to_child_index = dictionary->getHierarchicalIndex();
13201331

13211332
size_t level = Strategy::default_level;
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
-- {echoOn }
2+
3+
DROP DICTIONARY IF EXISTS d0;
4+
CREATE DICTIONARY d0 (c0 Int) PRIMARY KEY (c0) SOURCE(NULL()) LAYOUT(FLAT()) LIFETIME(1);
5+
SELECT dictGetDescendants('d0', 'c0', 1); -- { serverError UNSUPPORTED_METHOD }
6+
SELECT dictGetDescendants('d0', 'c0', NULL); -- { serverError UNSUPPORTED_METHOD }
7+
SELECT dictGetDescendants('d0', NULL, 1); -- { serverError UNSUPPORTED_METHOD }
8+
SELECT dictGetChildren('d0', 'c0'); -- { serverError UNSUPPORTED_METHOD }
9+
SELECT dictGetChildren('d0', NULL); -- { serverError UNSUPPORTED_METHOD }
10+
SELECT dictGetChildren(NULL, NULL); -- { serverError UNSUPPORTED_METHOD }
11+
DROP DICTIONARY IF EXISTS hierarchical_dictionary;
12+
DROP TABLE IF EXISTS hierarchy_source;
13+
CREATE TABLE hierarchy_source
14+
(
15+
id UInt64,
16+
parent_id UInt64,
17+
name String
18+
) ENGINE = Memory;
19+
INSERT INTO hierarchy_source VALUES
20+
(0, 0, 'Root'),
21+
(1, 0, 'Level 1 - Node 1'),
22+
(2, 1, 'Level 2 - Node 2'),
23+
(3, 1, 'Level 2 - Node 3'),
24+
(4, 2, 'Level 3 - Node 4'),
25+
(5, 2, 'Level 3 - Node 5'),
26+
(6, 3, 'Level 3 - Node 6');
27+
CREATE DICTIONARY hierarchical_dictionary
28+
(
29+
id UInt64,
30+
parent_id UInt64 HIERARCHICAL,
31+
name String
32+
)
33+
PRIMARY KEY id
34+
SOURCE(CLICKHOUSE(TABLE 'hierarchy_source'))
35+
LAYOUT(HASHED())
36+
LIFETIME(0);
37+
SELECT dictGetDescendants('hierarchical_dictionary', 1, 1);
38+
[3,2]
39+
SELECT dictGetDescendants('hierarchical_dictionary', NULL, 1);
40+
\N
41+
SELECT dictGetDescendants('hierarchical_dictionary', 1, NULL); -- { serverError BAD_ARGUMENTS }
42+
SELECT dictGetChildren('hierarchical_dictionary', 1);
43+
[3,2]
44+
SELECT dictGetChildren('hierarchical_dictionary', NULL);
45+
\N
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
-- {echoOn }
2+
3+
DROP DICTIONARY IF EXISTS d0;
4+
CREATE DICTIONARY d0 (c0 Int) PRIMARY KEY (c0) SOURCE(NULL()) LAYOUT(FLAT()) LIFETIME(1);
5+
6+
SELECT dictGetDescendants('d0', 'c0', 1); -- { serverError UNSUPPORTED_METHOD }
7+
8+
SELECT dictGetDescendants('d0', 'c0', NULL); -- { serverError UNSUPPORTED_METHOD }
9+
10+
SELECT dictGetDescendants('d0', NULL, 1); -- { serverError UNSUPPORTED_METHOD }
11+
12+
SELECT dictGetChildren('d0', 'c0'); -- { serverError UNSUPPORTED_METHOD }
13+
14+
SELECT dictGetChildren('d0', NULL); -- { serverError UNSUPPORTED_METHOD }
15+
16+
SELECT dictGetChildren(NULL, NULL); -- { serverError UNSUPPORTED_METHOD }
17+
18+
19+
DROP DICTIONARY IF EXISTS hierarchical_dictionary;
20+
DROP TABLE IF EXISTS hierarchy_source;
21+
22+
CREATE TABLE hierarchy_source
23+
(
24+
id UInt64,
25+
parent_id UInt64,
26+
name String
27+
) ENGINE = Memory;
28+
29+
INSERT INTO hierarchy_source VALUES
30+
(0, 0, 'Root'),
31+
(1, 0, 'Level 1 - Node 1'),
32+
(2, 1, 'Level 2 - Node 2'),
33+
(3, 1, 'Level 2 - Node 3'),
34+
(4, 2, 'Level 3 - Node 4'),
35+
(5, 2, 'Level 3 - Node 5'),
36+
(6, 3, 'Level 3 - Node 6');
37+
38+
39+
CREATE DICTIONARY hierarchical_dictionary
40+
(
41+
id UInt64,
42+
parent_id UInt64 HIERARCHICAL,
43+
name String
44+
)
45+
PRIMARY KEY id
46+
SOURCE(CLICKHOUSE(TABLE 'hierarchy_source'))
47+
LAYOUT(HASHED())
48+
LIFETIME(0);
49+
50+
SELECT dictGetDescendants('hierarchical_dictionary', 1, 1);
51+
52+
SELECT dictGetDescendants('hierarchical_dictionary', NULL, 1);
53+
54+
SELECT dictGetDescendants('hierarchical_dictionary', 1, NULL); -- { serverError BAD_ARGUMENTS }
55+
56+
SELECT dictGetChildren('hierarchical_dictionary', 1);
57+
58+
SELECT dictGetChildren('hierarchical_dictionary', NULL);

0 commit comments

Comments
 (0)