Skip to content

Commit 92fd6b3

Browse files
committed
Updated bloom filter index for map type to work with mapKeys function
1 parent 1f74a98 commit 92fd6b3

File tree

5 files changed

+66
-53
lines changed

5 files changed

+66
-53
lines changed

src/Interpreters/BloomFilter.cpp

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,9 @@
11
#include <Interpreters/BloomFilter.h>
22
#include <city.h>
33
#include <Columns/ColumnArray.h>
4-
#include <Columns/ColumnMap.h>
54
#include <Columns/ColumnNullable.h>
65
#include <Columns/ColumnLowCardinality.h>
76
#include <DataTypes/DataTypeArray.h>
8-
#include <DataTypes/DataTypeMap.h>
97
#include <DataTypes/DataTypeNullable.h>
108
#include <DataTypes/DataTypeLowCardinality.h>
119

@@ -126,14 +124,6 @@ DataTypePtr BloomFilter::getPrimitiveType(const DataTypePtr & data_type)
126124
throw Exception("Unexpected type " + data_type->getName() + " of bloom filter index.", ErrorCodes::BAD_ARGUMENTS);
127125
}
128126

129-
if (const auto * map_type = typeid_cast<const DataTypeMap *>(data_type.get()))
130-
{
131-
if (!typeid_cast<const DataTypeMap *>(map_type->getKeyType().get()))
132-
return getPrimitiveType(map_type->getKeyType());
133-
else
134-
throw Exception("Unexpected key type " + data_type->getName() + " of bloom filter index for map.", ErrorCodes::BAD_ARGUMENTS);
135-
}
136-
137127
if (const auto * nullable_type = typeid_cast<const DataTypeNullable *>(data_type.get()))
138128
return getPrimitiveType(nullable_type->getNestedType());
139129

@@ -148,9 +138,6 @@ ColumnPtr BloomFilter::getPrimitiveColumn(const ColumnPtr & column)
148138
if (const auto * array_col = typeid_cast<const ColumnArray *>(column.get()))
149139
return getPrimitiveColumn(array_col->getDataPtr());
150140

151-
if (const auto * map_col = typeid_cast<const ColumnMap *>(column.get()))
152-
return getPrimitiveColumn(map_col->getNestedData().getColumnPtr(0));
153-
154141
if (const auto * nullable_col = typeid_cast<const ColumnNullable *>(column.get()))
155142
return getPrimitiveColumn(nullable_col->getNestedColumnPtr());
156143

src/Interpreters/BloomFilterHash.h

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
#include <Columns/IColumn.h>
66
#include <Columns/ColumnArray.h>
77
#include <Columns/ColumnConst.h>
8-
#include <Columns/ColumnMap.h>
98
#include <Columns/ColumnNullable.h>
109
#include <Columns/ColumnsNumber.h>
1110
#include <Columns/ColumnString.h>
@@ -124,26 +123,6 @@ struct BloomFilterHash
124123
}
125124
}
126125

127-
if (which.isMap())
128-
{
129-
const auto * map_col = typeid_cast<const ColumnMap *>(column.get());
130-
const auto & keys_data = map_col->getNestedData().getColumn(0);
131-
if (checkAndGetColumn<ColumnNullable>(keys_data))
132-
throw Exception("Unexpected key type " + data_type->getName() + " of bloom filter index.", ErrorCodes::BAD_ARGUMENTS);
133-
134-
const auto & offsets = map_col->getNestedColumn().getOffsets();
135-
limit = offsets[pos + limit - 1] - offsets[pos - 1]; /// PaddedPODArray allows access on index -1.
136-
pos = offsets[pos - 1];
137-
138-
if (limit == 0)
139-
{
140-
auto index_column = ColumnUInt64::create(1);
141-
ColumnUInt64::Container & index_column_vec = index_column->getData();
142-
index_column_vec[0] = 0;
143-
return index_column;
144-
}
145-
}
146-
147126
const ColumnPtr actual_col = BloomFilter::getPrimitiveColumn(column);
148127
const DataTypePtr actual_type = BloomFilter::getPrimitiveType(data_type);
149128

src/Storages/MergeTree/MergeTreeIndexConditionBloomFilter.cpp

Lines changed: 24 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -512,32 +512,37 @@ bool MergeTreeIndexConditionBloomFilter::traverseASTEquals(
512512

513513
if (function->name == "arrayElement")
514514
{
515+
/** Try to parse arrayElement for mapKeys index.
516+
* It is important to ignore keys like column_map['Key'] = '' because if key does not exists in map
517+
* we return default value for arrayElement.
518+
*
519+
* We cannot skip keys that does not exist in map if comparison is with default type value because
520+
* that way we skip necessary granules where map key does not exists.
521+
*/
522+
if (value_field == value_type->getDefault())
523+
return false;
524+
515525
const auto & col_name = assert_cast<ASTIdentifier *>(function->arguments.get()->children[0].get())->name();
516526

517-
if (header.has(col_name))
527+
auto map_keys_index_column_name = fmt::format("mapKeys({})", col_name);
528+
529+
if (header.has(map_keys_index_column_name))
518530
{
519-
size_t position = header.getPositionByName(col_name);
531+
size_t position = header.getPositionByName(map_keys_index_column_name);
520532
const DataTypePtr & index_type = header.getByPosition(position).type;
521-
const auto * map_type = typeid_cast<const DataTypeMap *>(index_type.get());
522-
if (map_type)
523-
{
524-
out.function = function_name == "equals" ? RPNElement::FUNCTION_EQUALS : RPNElement::FUNCTION_NOT_EQUALS;
525-
526-
auto & argument = function->arguments.get()->children[1];
527-
528-
if (const auto * literal = argument->as<ASTLiteral>())
529-
{
530-
auto element_key = literal->value;
531-
const DataTypePtr actual_type = BloomFilter::getPrimitiveType(index_type);
532-
out.predicate.emplace_back(std::make_pair(position, BloomFilterHash::hashWithField(actual_type.get(), element_key)));
533-
}
534-
else
535-
{
536-
return false;
537-
}
533+
out.function = function_name == "equals" ? RPNElement::FUNCTION_EQUALS : RPNElement::FUNCTION_NOT_EQUALS;
538534

535+
auto & argument = function->arguments.get()->children[1];
536+
537+
if (const auto * literal = argument->as<ASTLiteral>())
538+
{
539+
auto element_key = literal->value;
540+
const DataTypePtr actual_type = BloomFilter::getPrimitiveType(index_type);
541+
out.predicate.emplace_back(std::make_pair(position, BloomFilterHash::hashWithField(actual_type.get(), element_key)));
539542
return true;
540543
}
544+
545+
return false;
541546
}
542547
}
543548
}
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
Equals with existing key
2+
0 {'K0':'V0'}
3+
Equals with non existing key
4+
Equals with default value
5+
0 {'K0':'V0'}
6+
1 {'K1':'V1'}
7+
Not equals with existing key
8+
1 {'K1':'V1'}
9+
Not equals with non existing key
10+
0 {'K0':'V0'}
11+
1 {'K1':'V1'}
12+
Not equals with default value
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
DROP TABLE IF EXISTS map_test;
2+
3+
CREATE TABLE map_test
4+
(
5+
row_id UInt32,
6+
map Map(String, String),
7+
INDEX map_bloom_filter_keys mapKeys(map) TYPE bloom_filter GRANULARITY 1
8+
) Engine=MergeTree() ORDER BY row_id;
9+
10+
INSERT INTO map_test VALUES (0, {'K0':'V0'}), (1, {'K1':'V1'});
11+
12+
SELECT 'Equals with existing key';
13+
SELECT * FROM map_test WHERE map['K0'] = 'V0';
14+
15+
SELECT 'Equals with non existing key';
16+
SELECT * FROM map_test WHERE map['K2'] = 'V2';
17+
18+
SELECT 'Equals with default value';
19+
SELECT * FROM map_test WHERE map['K3'] = '';
20+
21+
SELECT 'Not equals with existing key';
22+
SELECT * FROM map_test WHERE map['K0'] != 'V0';
23+
24+
SELECT 'Not equals with non existing key';
25+
SELECT * FROM map_test WHERE map['K2'] != 'V2';
26+
27+
SELECT 'Not equals with default value';
28+
SELECT * FROM map_test WHERE map['K3'] != '';
29+
30+
DROP TABLE map_test;

0 commit comments

Comments
 (0)