@@ -536,30 +536,38 @@ bool TryScanIndex(ART &art, const ColumnList &column_list, TableFunctionInitInpu
536536 }
537537 }
538538
539- // If found, update the bound column refs within all index_exprs
540- if (found_index_column_in_input) {
541- for (auto &index_expr : index_exprs) {
542- ExpressionIterator::EnumerateExpression (index_expr, [&](Expression &expr) {
543- if (expr.GetExpressionClass () != ExpressionClass::BOUND_COLUMN_REF) {
544- return ;
545- }
539+ if (!found_index_column_in_input) {
540+ return false ;
541+ }
546542
547- auto &bound_column_ref_expr = expr.Cast <BoundColumnRefExpression>();
543+ for (auto col : index_column_to_proj_pos) {
544+ if (col == std::numeric_limits<idx_t >::max ()) {
545+ return false ;
546+ }
547+ }
548548
549- // If the bound column references an indexed column, update it
550- for (idx_t i = 0 ; i < indexed_columns.size (); ++i) {
551- if (bound_column_ref_expr.binding .column_index == indexed_columns[i]) {
552- bound_column_ref_expr.binding .column_index = index_column_to_proj_pos[i];
553- break ;
554- }
549+ // Update the bound column refs within all index_exprs
550+ for (auto &index_expr : index_exprs) {
551+ ExpressionIterator::EnumerateExpression (index_expr, [&](Expression &expr) {
552+ if (expr.GetExpressionClass () != ExpressionClass::BOUND_COLUMN_REF) {
553+ return ;
554+ }
555+
556+ auto &bound_column_ref_expr = expr.Cast <BoundColumnRefExpression>();
557+
558+ // If the bound column references an indexed column, update it
559+ for (idx_t i = 0 ; i < indexed_columns.size (); ++i) {
560+ if (bound_column_ref_expr.binding .column_index == indexed_columns[i]) {
561+ bound_column_ref_expr.binding .column_index = index_column_to_proj_pos[i];
562+ break ;
555563 }
556- });
557- }
564+ }
565+ });
558566 }
559567
560568 // The indexes of the filters match input.column_indexes, which are: i -> column_index.
561569 // Reuse the index <-> projection mappings from index expr rebinding
562- vector<vector<unique_ptr<Expression>>> filters ;
570+ vector<vector<unique_ptr<Expression>>> index_filters ;
563571
564572 for (idx_t i = 0 ; i < index_column_to_proj_pos.size (); ++i) {
565573 auto column_def = &column_list.GetColumn (LogicalIndex (indexed_columns[i]));
@@ -568,18 +576,21 @@ bool TryScanIndex(ART &art, const ColumnList &column_list, TableFunctionInitInpu
568576 auto filter = &maybe_filter->second ;
569577 auto filter_expressions = ExtractFilterExpressions (*column_def, *filter, index_column_to_proj_pos[i]);
570578
571- filters .push_back (std::move (filter_expressions));
579+ index_filters .push_back (std::move (filter_expressions));
572580 }
573581 }
574582
575- // Filters must match ART columns 1:1
576- if (filters.size () != indexed_columns.size () || filters.empty ()) {
583+ // Index filters must:
584+ // - Match ART column count 1:1
585+ // - Match filter expression set 1:1 (there may be filters on non-indexed columns, bail out if so)
586+ if (index_filters.size () != indexed_columns.size () || filter_set.filters .size () != index_filters.size () ||
587+ index_filters.empty ()) {
577588 return false ;
578589 }
579590
580591 // Do a compound scan if we have filter exprs bound for several columns
581- if (filters .size () > 1 ) {
582- auto scan_state = art.TryInitializeCompoundKeyScan (index_exprs, filters );
592+ if (index_filters .size () > 1 ) {
593+ auto scan_state = art.TryInitializeCompoundKeyScan (index_exprs, index_filters );
583594 if (!scan_state) {
584595 return false ;
585596 }
@@ -591,7 +602,7 @@ bool TryScanIndex(ART &art, const ColumnList &column_list, TableFunctionInitInpu
591602 }
592603 // Original single column index scan
593604 else {
594- for (const auto &filter_expr : filters [0 ]) {
605+ for (const auto &filter_expr : index_filters [0 ]) {
595606 auto scan_state = art.TryInitializeScan (*index_exprs[0 ], *filter_expr);
596607 if (!scan_state) {
597608 return false ;
0 commit comments