diff --git a/dbms/src/Interpreters/InterpreterSelectQuery.cpp b/dbms/src/Interpreters/InterpreterSelectQuery.cpp index 175059b53da94f6ea146ca86fefad8ba36a30607..b76317e8cd23b12e3b399040d6737735618d31e5 100644 --- a/dbms/src/Interpreters/InterpreterSelectQuery.cpp +++ b/dbms/src/Interpreters/InterpreterSelectQuery.cpp @@ -324,7 +324,7 @@ InterpreterSelectQuery::InterpreterSelectQuery( table_id = storage->getStorageID(); } - auto analyze = [&] () + auto analyze = [&] (bool try_move_to_prewhere = true) { syntax_analyzer_result = SyntaxAnalyzer(*context, options).analyze( query_ptr, source_header.getNamesAndTypesList(), required_result_column_names, storage, NamesAndTypesList()); @@ -397,7 +397,7 @@ InterpreterSelectQuery::InterpreterSelectQuery( throw Exception("PREWHERE is not supported if the table is filtered by row-level security expression", ErrorCodes::ILLEGAL_PREWHERE); /// Calculate structure of the result. - result_header = getSampleBlockImpl(); + result_header = getSampleBlockImpl(try_move_to_prewhere); }; analyze(); @@ -425,8 +425,13 @@ InterpreterSelectQuery::InterpreterSelectQuery( query.setExpression(ASTSelectQuery::Expression::WHERE, makeASTFunction("and", query.prewhere()->clone(), query.where()->clone())); need_analyze_again = true; } + if (need_analyze_again) - analyze(); + { + /// Do not try move conditions to PREWHERE for the second time. + /// Otherwise, we won't be able to fallback from inefficient PREWHERE to WHERE later. + analyze(/* try_move_to_prewhere = */ false); + } /// If there is no WHERE, filter blocks as usual if (query.prewhere() && !query.where()) @@ -509,7 +514,7 @@ QueryPipeline InterpreterSelectQuery::executeWithProcessors() } -Block InterpreterSelectQuery::getSampleBlockImpl() +Block InterpreterSelectQuery::getSampleBlockImpl(bool try_move_to_prewhere) { auto & query = getSelectQuery(); const Settings & settings = context->getSettingsRef(); @@ -533,7 +538,7 @@ Block InterpreterSelectQuery::getSampleBlockImpl() current_info.sets = query_analyzer->getPreparedSets(); /// Try transferring some condition from WHERE to PREWHERE if enabled and viable - if (settings.optimize_move_to_prewhere && query.where() && !query.prewhere() && !query.final()) + if (settings.optimize_move_to_prewhere && try_move_to_prewhere && query.where() && !query.prewhere() && !query.final()) MergeTreeWhereOptimizer{current_info, *context, merge_tree, syntax_analyzer_result->requiredSourceColumns(), log}; }; diff --git a/dbms/src/Interpreters/InterpreterSelectQuery.h b/dbms/src/Interpreters/InterpreterSelectQuery.h index 56ab2aaa8f55baa0b4e15794e90167e5c12f638b..77a6f1ca3acc0b35334dde685732f455831bea8f 100644 --- a/dbms/src/Interpreters/InterpreterSelectQuery.h +++ b/dbms/src/Interpreters/InterpreterSelectQuery.h @@ -104,7 +104,7 @@ private: ASTSelectQuery & getSelectQuery() { return query_ptr->as(); } - Block getSampleBlockImpl(); + Block getSampleBlockImpl(bool try_move_to_prewhere); struct Pipeline { diff --git a/dbms/src/Storages/MergeTree/MergeTreeRangeReader.cpp b/dbms/src/Storages/MergeTree/MergeTreeRangeReader.cpp index 517d6a1475640b35eebee211db52898d44ac5348..a0bd2567fe508b38f6b058f0ccf362a4e3d49624 100644 --- a/dbms/src/Storages/MergeTree/MergeTreeRangeReader.cpp +++ b/dbms/src/Storages/MergeTree/MergeTreeRangeReader.cpp @@ -431,9 +431,11 @@ void MergeTreeRangeReader::ReadResult::setFilter(const ColumnPtr & new_filter) } ConstantFilterDescription const_description(*new_filter); - if (const_description.always_false) + if (const_description.always_true) + setFilterConstTrue(); + else if (const_description.always_false) clear(); - else if (!const_description.always_true) + else { FilterDescription filter_description(*new_filter); filter_holder = filter_description.data_holder ? filter_description.data_holder : new_filter; diff --git a/dbms/tests/queries/0_stateless/01076_range_reader_segfault.reference b/dbms/tests/queries/0_stateless/01076_range_reader_segfault.reference new file mode 100644 index 0000000000000000000000000000000000000000..97ebc7c1a0f89de2d528a171e05148c9a506552d --- /dev/null +++ b/dbms/tests/queries/0_stateless/01076_range_reader_segfault.reference @@ -0,0 +1,2 @@ +99 +4950 diff --git a/dbms/tests/queries/0_stateless/01076_range_reader_segfault.sql b/dbms/tests/queries/0_stateless/01076_range_reader_segfault.sql new file mode 100644 index 0000000000000000000000000000000000000000..86a568ff617e7c0879ac42ece1b9e6e4505801ff --- /dev/null +++ b/dbms/tests/queries/0_stateless/01076_range_reader_segfault.sql @@ -0,0 +1,9 @@ +DROP TABLE IF EXISTS t; + +CREATE TABLE t (a Int, b Int, c Int) ENGINE = MergeTree ORDER BY tuple(); +INSERT INTO t SELECT number, number * 2, number * 3 FROM numbers(100); + +SELECT count() FROM t PREWHERE NOT ignore(a) WHERE b > 0; +SELECT sum(a) FROM t PREWHERE isNotNull(a) WHERE isNotNull(b) AND c > 0; + +DROP TABLE t;