Fix PREWHERE with row-level filters (when row filter is always true/false)

In case of row-level filters optimized out, i.e. converted to
always true/false, it is possible for MergeTreeRangeReader to reuse
incorrect statistics for the filter (countBytesInResultFilter()), and
because of this it simply does not apply other filters, since it assume
that this filter does not need to filter anything.

Fixes: #40956
Signed-off-by: Azat Khuzhin <a.khuzhin@semrush.com>
This commit is contained in:
Azat Khuzhin 2022-09-29 15:35:37 +02:00 committed by Alexander Gololobov
parent bf64e3eaca
commit 31a88d4eae
4 changed files with 19 additions and 1 deletions

View File

@ -320,9 +320,18 @@ void MergeTreeRangeReader::ReadResult::clear()
num_rows_to_skip_in_last_granule += rows_per_granule.back();
rows_per_granule.assign(rows_per_granule.size(), 0);
total_rows_per_granule = 0;
if (filter)
filter_bytes_map.erase(&filter->getData());
filter_holder = nullptr;
filter = nullptr;
}
void MergeTreeRangeReader::ReadResult::clearFilter()
{
if (!filter)
return;
filter_bytes_map.erase(&filter->getData());
filter = nullptr;
}
void MergeTreeRangeReader::ReadResult::shrink(Columns & old_columns)
{

View File

@ -198,8 +198,8 @@ public:
void optimize(bool can_read_incomplete_granules, bool allow_filter_columns);
/// Remove all rows from granules.
void clear();
void clearFilter();
void clearFilter() { filter = nullptr; }
void setFilterConstTrue();
void setFilterConstFalse();

View File

@ -0,0 +1,9 @@
-- https://github.com/ClickHouse/ClickHouse/issues/40956#issuecomment-1262096612
DROP TABLE IF EXISTS row_level_policy_prewhere;
DROP ROW POLICY IF EXISTS row_level_policy_prewhere_policy0 ON row_level_policy_prewhere;
CREATE TABLE row_level_policy_prewhere (x Int16, y String) ENGINE = MergeTree ORDER BY x;
INSERT INTO row_level_policy_prewhere(y, x) VALUES ('A',1), ('B',2), ('C',3);
CREATE ROW POLICY row_level_policy_prewhere_policy0 ON row_level_policy_prewhere FOR SELECT USING x >= 0 TO default;
SELECT * FROM row_level_policy_prewhere PREWHERE y = 'foo';
DROP TABLE row_level_policy_prewhere;