diff --git a/sql/range_optimizer/index_range_scan_plan.cc b/sql/range_optimizer/index_range_scan_plan.cc index 4822303b995..81a7c233873 100644 --- a/sql/range_optimizer/index_range_scan_plan.cc +++ b/sql/range_optimizer/index_range_scan_plan.cc @@ -871,6 +871,11 @@ AccessPath *get_key_scans_params(THD *thd, RANGE_OPT_PARAM *param, thd, param, idx, read_index_only, key, update_tbl_stats, order_direction, skip_records_in_range, &mrr_flags, &buf_size, &cost, &is_ror_scan, &is_imerge_scan); + if (param->error_handler.has_memory_error()) { + trace_idx.add("chosen", false) + .add_alnum("cause", "range_optimizer_max_mem_size_exceeded"); + return nullptr; + } if (found_records != HA_POS_ERROR && ror_only && !is_ror_scan) { trace_idx.add("chosen", false).add_alnum("cause", "not_rowid_ordered"); continue; @@ -959,6 +964,15 @@ AccessPath *get_key_scans_params(THD *thd, RANGE_OPT_PARAM *param, return nullptr; } + const ulonglong max_range_mem = thd->variables.range_optimizer_max_mem_size; + const uint best_keynr = param->real_keynr[best_idx]; + if (max_range_mem > 0 && + param->table->quick_n_ranges[best_keynr] > + max_range_mem / sizeof(QUICK_RANGE)) { + param->error_handler.report_memory_error(thd); + return nullptr; + } + Quick_ranges ranges(param->return_mem_root); unsigned used_key_parts, num_exact_key_parts; if (get_ranges_from_tree(param->return_mem_root, param->table, diff --git a/sql/range_optimizer/internal.h b/sql/range_optimizer/internal.h index fb48e1a66b3..74e3d1a65ca 100644 --- a/sql/range_optimizer/internal.h +++ b/sql/range_optimizer/internal.h @@ -85,15 +85,8 @@ class Range_optimizer_error_handler : public Internal_error_handler { /* Out of memory error is reported only once. Return as handled */ if (m_is_mem_error && sql_errno == EE_CAPACITY_EXCEEDED) return true; if (sql_errno == EE_CAPACITY_EXCEEDED) { - m_is_mem_error = true; - /* Convert the error into a warning. */ + report_memory_error(thd); *level = Sql_condition::SL_WARNING; - push_warning_printf( - thd, Sql_condition::SL_WARNING, ER_CAPACITY_EXCEEDED, - ER_THD(thd, ER_CAPACITY_EXCEEDED), - (ulonglong)thd->variables.range_optimizer_max_mem_size, - "range_optimizer_max_mem_size", - ER_THD(thd, ER_CAPACITY_EXCEEDED_IN_RANGE_OPTIMIZER)); return true; } } @@ -101,6 +94,18 @@ class Range_optimizer_error_handler : public Internal_error_handler { } bool has_errors() const { return m_has_errors; } + bool has_memory_error() const { return m_is_mem_error; } + void report_memory_error(THD *thd) { + m_has_errors = true; + if (m_is_mem_error) return; + m_is_mem_error = true; + push_warning_printf( + thd, Sql_condition::SL_WARNING, ER_CAPACITY_EXCEEDED, + ER_THD(thd, ER_CAPACITY_EXCEEDED), + (ulonglong)thd->variables.range_optimizer_max_mem_size, + "range_optimizer_max_mem_size", + ER_THD(thd, ER_CAPACITY_EXCEEDED_IN_RANGE_OPTIMIZER)); + } private: bool m_has_errors;