|
61 | 61 | #include "sql/enum_query_type.h"
|
62 | 62 | #include "sql/error_handler.h" // Functional_index_error_handler
|
63 | 63 | #include "sql/handler.h"
|
| 64 | +#include "sql/item.h" |
64 | 65 | #include "sql/item_cmpfunc.h"
|
65 | 66 | #include "sql/item_func.h"
|
66 | 67 | #include "sql/item_row.h"
|
@@ -3556,6 +3557,11 @@ static bool check_simple_equality(THD *thd, Item *left_item, Item *right_item,
|
3556 | 3557 | const_item = left_item;
|
3557 | 3558 | }
|
3558 | 3559 |
|
| 3560 | + // Don't evaluate subqueries if they are disabled during optimization. |
| 3561 | + if (const_item != nullptr && |
| 3562 | + !evaluate_during_optimization(const_item, thd->lex->current_select())) |
| 3563 | + return false; |
| 3564 | + |
3559 | 3565 | /*
|
3560 | 3566 | If the constant expression contains a reference to the field
|
3561 | 3567 | (for example, a = (a IS NULL)), we don't want to replace the
|
@@ -3650,7 +3656,7 @@ static bool check_row_equality(THD *thd, Item *left_row, Item_row *right_row,
|
3650 | 3656 | return true;
|
3651 | 3657 | if (!is_converted) thd->lex->current_select()->cond_count++;
|
3652 | 3658 | } else {
|
3653 |
| - if (check_simple_equality(thd, left_item, right_item, 0, cond_equal, |
| 3659 | + if (check_simple_equality(thd, left_item, right_item, nullptr, cond_equal, |
3654 | 3660 | &is_converted))
|
3655 | 3661 | return true;
|
3656 | 3662 | thd->lex->current_select()->cond_count++;
|
@@ -9108,7 +9114,8 @@ static bool make_join_select(JOIN *join, Item *cond) {
|
9108 | 9114 | }
|
9109 | 9115 | DBUG_EXECUTE("where",
|
9110 | 9116 | print_where(thd, const_cond, "constants", QT_ORDINARY););
|
9111 |
| - if (const_cond != NULL) { |
| 9117 | + if (const_cond != nullptr && |
| 9118 | + evaluate_during_optimization(const_cond, join->select_lex)) { |
9112 | 9119 | const bool const_cond_result = const_cond->val_int() != 0;
|
9113 | 9120 | if (thd->is_error()) return true;
|
9114 | 9121 |
|
@@ -9695,7 +9702,8 @@ ORDER *JOIN::remove_const(ORDER *first_order, Item *cond, bool change_list,
|
9695 | 9702 | (primary_tables > 1 && rollup.state == ROLLUP::STATE_INITED &&
|
9696 | 9703 | select_lex->outer_join))
|
9697 | 9704 | *simple_order = 0; // Must do a temp table to sort
|
9698 |
| - else if (!(order_tables & not_const_tables)) { |
| 9705 | + else if ((order_tables & not_const_tables) == 0 && |
| 9706 | + evaluate_during_optimization(order->item[0], select_lex)) { |
9699 | 9707 | if (order->item[0]->has_subquery()) {
|
9700 | 9708 | if (!thd->lex->is_explain()) {
|
9701 | 9709 | Opt_trace_array trace_subselect(trace, "subselect_evaluation");
|
@@ -9863,15 +9871,26 @@ bool optimize_cond(THD *thd, Item **cond, COND_EQUAL **cond_equal,
|
9863 | 9871 | return false;
|
9864 | 9872 | }
|
9865 | 9873 |
|
| 9874 | +/** |
| 9875 | + Checks if a condition can be evaluated during constant folding. It can be |
| 9876 | + evaluated if it is constant during execution and not expensive to evaluate. If |
| 9877 | + it contains a subquery, it should not be evaluated if the option |
| 9878 | + OPTION_NO_SUBQUERY_DURING_OPTIMIZATION is active. |
| 9879 | +*/ |
| 9880 | +static bool can_evaluate_condition(THD *thd, Item *condition) { |
| 9881 | + return condition->const_for_execution() && !condition->is_expensive() && |
| 9882 | + evaluate_during_optimization(condition, thd->lex->current_select()); |
| 9883 | +} |
| 9884 | + |
9866 | 9885 | /**
|
9867 | 9886 | Calls fold_condition. If that made the condition constant for execution,
|
9868 | 9887 | simplify and fold again. @see fold_condition() for arguments.
|
9869 | 9888 | */
|
9870 | 9889 | static bool fold_condition_exec(THD *thd, Item *cond, Item **retcond,
|
9871 | 9890 | Item::cond_result *cond_value) {
|
9872 | 9891 | if (fold_condition(thd, cond, retcond, cond_value)) return true;
|
9873 |
| - if (*retcond != nullptr && (*retcond)->const_for_execution() && |
9874 |
| - !(*retcond)->is_expensive()) // simplify further maybe |
| 9892 | + if (*retcond != nullptr && |
| 9893 | + can_evaluate_condition(thd, *retcond)) // simplify further maybe |
9875 | 9894 | return remove_eq_conds(thd, *retcond, retcond, cond_value);
|
9876 | 9895 | return false;
|
9877 | 9896 | }
|
@@ -9974,13 +9993,13 @@ bool remove_eq_conds(THD *thd, Item *cond, Item **retcond,
|
9974 | 9993 | *retcond = item;
|
9975 | 9994 | return false;
|
9976 | 9995 | }
|
9977 |
| - } else if (cond->const_for_execution() && !cond->is_expensive()) { |
| 9996 | + } else if (can_evaluate_condition(thd, cond)) { |
9978 | 9997 | bool value;
|
9979 | 9998 | if (eval_const_cond(thd, cond, &value)) return true;
|
9980 | 9999 | *cond_value = value ? Item::COND_TRUE : Item::COND_FALSE;
|
9981 | 10000 | *retcond = NULL;
|
9982 | 10001 | return false;
|
9983 |
| - } else { // boolan compare function |
| 10002 | + } else { // Boolean compare function |
9984 | 10003 | *cond_value = cond->eq_cmp_result();
|
9985 | 10004 | if (*cond_value == Item::COND_OK) {
|
9986 | 10005 | return fold_condition_exec(thd, cond, retcond, cond_value);
|
@@ -10877,3 +10896,19 @@ static uint32 get_key_length_tmp_table(Item *item) {
|
10877 | 10896 |
|
10878 | 10897 | return len;
|
10879 | 10898 | }
|
| 10899 | + |
| 10900 | +bool evaluate_during_optimization(const Item *item, const SELECT_LEX *select) { |
| 10901 | + /* |
| 10902 | + Should only be called on items that are const_for_execution(), as those |
| 10903 | + items are the only ones that are allowed to be evaluated during optimization |
| 10904 | + in the first place. |
| 10905 | + |
| 10906 | + Additionally, allow items that only access tables in JOIN::const_table_map. |
| 10907 | + This should not be necessary, but the const_for_execution() property is not |
| 10908 | + always updated correctly by update_used_tables() for certain subqueries. |
| 10909 | + */ |
| 10910 | + DBUG_ASSERT(item->const_for_execution() || |
| 10911 | + (item->used_tables() & ~select->join->const_table_map) == 0); |
| 10912 | + return !item->has_subquery() || (select->active_options() & |
| 10913 | + OPTION_NO_SUBQUERY_DURING_OPTIMIZATION) == 0; |
| 10914 | +} |
0 commit comments