mirror of
https://github.com/MariaDB/server.git
synced 2025-08-08 11:22:35 +03:00
Make marking/testing of top level item uniform
There where several different implementations of is_top_level_item(), with different variable names and tests. In some cases the code used 'is_top_level_item()' as a test, in other cases it accessed the variable directrly. This patch makes all usage of 'top_level_item' uniform. The new implementation stores the 'is_tol_level_item()' flag as part of base_flags. This saves 7 bytes in all items that previously stored the flag in it's own bool. I had to keep 'top_level_item()' virtual to ensure that Item_bool_const item's will not be updated. 'is_top_level_item()' is not virtual anymore.
This commit is contained in:
44
sql/item.h
44
sql/item.h
@@ -769,8 +769,8 @@ enum class item_base_t : item_flags_t
|
||||
FIXED= (1<<2), // Was fixed with fix_fields().
|
||||
IS_EXPLICIT_NAME= (1<<3), // The name of this Item was set by the user
|
||||
// (or was auto generated otherwise)
|
||||
IS_IN_WITH_CYCLE= (1<<4) // This item is in CYCLE clause
|
||||
// of WITH.
|
||||
IS_IN_WITH_CYCLE= (1<<4), // This item is in CYCLE clause of WITH.
|
||||
AT_TOP_LEVEL= (1<<5) // At top (AND) level of item tree
|
||||
};
|
||||
|
||||
|
||||
@@ -1319,6 +1319,25 @@ public:
|
||||
{
|
||||
set_maybe_null(maybe_null_arg);
|
||||
}
|
||||
/*
|
||||
Mark the item that it is a top level item, or part of a top level AND item,
|
||||
for WHERE and ON clauses:
|
||||
Example: ... WHERE a=5 AND b=6; Both a=5 and b=6 are top level items
|
||||
|
||||
This is used to indicate that there is no distinction between if the
|
||||
value of the item is FALSE or NULL..
|
||||
This enables Item_cond_and and subquery related items to do special
|
||||
"top level" optimizations.
|
||||
*/
|
||||
virtual void top_level_item()
|
||||
{
|
||||
base_flags|= item_base_t::AT_TOP_LEVEL;
|
||||
}
|
||||
/*
|
||||
Return TRUE if this item of top WHERE level (AND/OR)
|
||||
*/
|
||||
bool is_top_level_item() const
|
||||
{ return (bool) (base_flags & item_base_t::AT_TOP_LEVEL); }
|
||||
|
||||
void set_typelib(const TYPELIB *typelib) override
|
||||
{
|
||||
@@ -2027,25 +2046,6 @@ public:
|
||||
{
|
||||
return type_handler()->Item_update_null_value(this);
|
||||
}
|
||||
|
||||
/*
|
||||
Inform the item that there will be no distinction between its result
|
||||
being FALSE or NULL.
|
||||
|
||||
NOTE
|
||||
This function will be called for eg. Items that are top-level AND-parts
|
||||
of the WHERE clause. Items implementing this function (currently
|
||||
Item_cond_and and subquery-related item) enable special optimizations
|
||||
when they are "top level".
|
||||
*/
|
||||
virtual void top_level_item() {}
|
||||
/*
|
||||
Return TRUE if it is item of top WHERE level (AND/OR) and it is
|
||||
important, return FALSE if it not important (we can not use to simplify
|
||||
calculations) or not top level
|
||||
*/
|
||||
virtual bool is_top_level_item() const
|
||||
{ return FALSE; /* not important */}
|
||||
/*
|
||||
return IN/ALL/ANY subquery or NULL
|
||||
*/
|
||||
@@ -4420,6 +4420,8 @@ public:
|
||||
Item_bool_static(const char *str_arg, longlong i):
|
||||
Item_bool(str_arg, i) {};
|
||||
|
||||
/* Don't mark static items as top level item */
|
||||
virtual void top_level_item() override {}
|
||||
void set_join_tab_idx(uint8 join_tab_idx_arg) override
|
||||
{ DBUG_ASSERT(0); }
|
||||
};
|
||||
|
@@ -1065,14 +1065,14 @@ int Arg_comparator::compare_row()
|
||||
// NULL was compared
|
||||
switch (((Item_func*)owner)->functype()) {
|
||||
case Item_func::NE_FUNC:
|
||||
break; // NE never aborts on NULL even if abort_on_null is set
|
||||
break; // NE never aborts on NULL
|
||||
case Item_func::LT_FUNC:
|
||||
case Item_func::LE_FUNC:
|
||||
case Item_func::GT_FUNC:
|
||||
case Item_func::GE_FUNC:
|
||||
return -1; // <, <=, > and >= always fail on NULL
|
||||
case Item_func::EQ_FUNC:
|
||||
if (((Item_func_eq*)owner)->abort_on_null)
|
||||
if (owner->is_top_level_item())
|
||||
return -1; // We do not need correct NULL returning
|
||||
break;
|
||||
default:
|
||||
@@ -1189,12 +1189,6 @@ longlong Item_func_truth::val_int()
|
||||
}
|
||||
|
||||
|
||||
bool Item_in_optimizer::is_top_level_item() const
|
||||
{
|
||||
return args[1]->is_top_level_item();
|
||||
}
|
||||
|
||||
|
||||
void Item_in_optimizer::fix_after_pullout(st_select_lex *new_parent,
|
||||
Item **ref, bool merge)
|
||||
{
|
||||
@@ -1379,7 +1373,8 @@ bool Item_in_optimizer::fix_fields(THD *thd, Item **ref)
|
||||
}
|
||||
|
||||
base_flags|= (item_base_t::FIXED |
|
||||
(args[1]->base_flags & item_base_t::MAYBE_NULL));
|
||||
(args[1]->base_flags & (item_base_t::MAYBE_NULL |
|
||||
item_base_t::AT_TOP_LEVEL)));
|
||||
with_flags|= (item_with_t::SUBQUERY |
|
||||
args[1]->with_flags |
|
||||
(args[0]->with_flags &
|
||||
@@ -2065,7 +2060,7 @@ bool Item_func_between::eval_not_null_tables(void *opt_arg)
|
||||
return 1;
|
||||
|
||||
/* not_null_tables_cache == union(T1(e),T1(e1),T1(e2)) */
|
||||
if (pred_level && !negated)
|
||||
if (is_top_level_item() && !negated)
|
||||
return 0;
|
||||
|
||||
/* not_null_tables_cache == union(T1(e), intersection(T1(e1),T1(e2))) */
|
||||
@@ -2467,6 +2462,10 @@ bool
|
||||
Item_func_if::fix_fields(THD *thd, Item **ref)
|
||||
{
|
||||
DBUG_ASSERT(fixed() == 0);
|
||||
/*
|
||||
Mark that we don't care if args[0] is NULL or FALSE, we regard both cases as
|
||||
false.
|
||||
*/
|
||||
args[0]->top_level_item();
|
||||
|
||||
if (Item_func::fix_fields(thd, ref))
|
||||
@@ -4342,7 +4341,7 @@ Item_func_in::eval_not_null_tables(void *opt_arg)
|
||||
return 1;
|
||||
|
||||
/* not_null_tables_cache == union(T1(e),union(T1(ei))) */
|
||||
if (pred_level && negated)
|
||||
if (is_top_level_item() && negated)
|
||||
return 0;
|
||||
|
||||
/* not_null_tables_cache = union(T1(e),intersection(T1(ei))) */
|
||||
@@ -4796,9 +4795,10 @@ bool Item_func_bit_and::fix_length_and_dec()
|
||||
|
||||
Item_cond::Item_cond(THD *thd, Item_cond *item)
|
||||
:Item_bool_func(thd, item),
|
||||
abort_on_null(item->abort_on_null),
|
||||
and_tables_cache(item->and_tables_cache)
|
||||
{
|
||||
base_flags|= (item->base_flags & item_base_t::AT_TOP_LEVEL);
|
||||
|
||||
/*
|
||||
item->list will be copied by copy_andor_arguments() call
|
||||
*/
|
||||
@@ -4806,7 +4806,7 @@ Item_cond::Item_cond(THD *thd, Item_cond *item)
|
||||
|
||||
|
||||
Item_cond::Item_cond(THD *thd, Item *i1, Item *i2):
|
||||
Item_bool_func(thd), abort_on_null(0)
|
||||
Item_bool_func(thd)
|
||||
{
|
||||
list.push_back(i1, thd->mem_root);
|
||||
list.push_back(i2, thd->mem_root);
|
||||
@@ -4874,7 +4874,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
|
||||
((Item_cond*) item)->list.empty();
|
||||
item= *li.ref(); // new current item
|
||||
}
|
||||
if (abort_on_null)
|
||||
if (is_top_level_item())
|
||||
item->top_level_item();
|
||||
|
||||
/*
|
||||
@@ -4901,7 +4901,7 @@ Item_cond::fix_fields(THD *thd, Item **ref)
|
||||
if (item->can_eval_in_optimize() && !item->with_sp_var() &&
|
||||
!cond_has_datetime_is_null(item))
|
||||
{
|
||||
if (item->eval_const_cond() == is_and_cond && top_level())
|
||||
if (item->eval_const_cond() == is_and_cond && is_top_level_item())
|
||||
{
|
||||
/*
|
||||
a. This is "... AND true_cond AND ..."
|
||||
@@ -4958,7 +4958,7 @@ Item_cond::eval_not_null_tables(void *opt_arg)
|
||||
if (item->can_eval_in_optimize() && !item->with_sp_var() &&
|
||||
!cond_has_datetime_is_null(item))
|
||||
{
|
||||
if (item->eval_const_cond() == is_and_cond && top_level())
|
||||
if (item->eval_const_cond() == is_and_cond && is_top_level_item())
|
||||
{
|
||||
/*
|
||||
a. This is "... AND true_cond AND ..."
|
||||
@@ -5393,17 +5393,18 @@ void Item_cond_and::mark_as_condition_AND_part(TABLE_LIST *embedding)
|
||||
Evaluation of AND(expr, expr, expr ...).
|
||||
|
||||
@note
|
||||
abort_if_null is set for AND expressions for which we don't care if the
|
||||
result is NULL or 0. This is set for:
|
||||
There are AND expressions for which we don't care if the
|
||||
result is NULL or 0. This is the case for:
|
||||
- WHERE clause
|
||||
- HAVING clause
|
||||
- IF(expression)
|
||||
For these we mark them as "top_level_items"
|
||||
|
||||
@retval
|
||||
1 If all expressions are true
|
||||
@retval
|
||||
0 If all expressions are false or if we find a NULL expression and
|
||||
'abort_on_null' is set.
|
||||
0 If any of the expressions are false or if we find a NULL expression and
|
||||
this is a top_level_item.
|
||||
@retval
|
||||
NULL if all expression are either 1 or NULL
|
||||
*/
|
||||
@@ -5419,8 +5420,8 @@ longlong Item_cond_and::val_int()
|
||||
{
|
||||
if (!item->val_bool())
|
||||
{
|
||||
if (abort_on_null || !(null_value= item->null_value))
|
||||
return 0; // return FALSE
|
||||
if (is_top_level_item() || !(null_value= item->null_value))
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return null_value ? 0 : 1;
|
||||
|
@@ -411,7 +411,6 @@ public:
|
||||
void set_join_tab_idx(uint8 join_tab_idx_arg) override
|
||||
{ args[1]->set_join_tab_idx(join_tab_idx_arg); }
|
||||
void get_cache_parameters(List<Item> ¶meters) override;
|
||||
bool is_top_level_item() const override;
|
||||
bool eval_not_null_tables(void *opt_arg) override;
|
||||
bool find_not_null_fields(table_map allowed) override;
|
||||
void fix_after_pullout(st_select_lex *new_parent, Item **ref,
|
||||
@@ -631,12 +630,8 @@ public:
|
||||
|
||||
class Item_func_not :public Item_bool_func
|
||||
{
|
||||
bool abort_on_null;
|
||||
public:
|
||||
Item_func_not(THD *thd, Item *a):
|
||||
Item_bool_func(thd, a), abort_on_null(FALSE) {}
|
||||
void top_level_item() override { abort_on_null= 1; }
|
||||
bool is_top_level_item() const override { return abort_on_null; }
|
||||
Item_func_not(THD *thd, Item *a): Item_bool_func(thd, a) {}
|
||||
longlong val_int() override;
|
||||
enum Functype functype() const override { return NOT_FUNC; }
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
@@ -755,11 +750,10 @@ public:
|
||||
|
||||
class Item_func_eq :public Item_bool_rowready_func2
|
||||
{
|
||||
bool abort_on_null;
|
||||
public:
|
||||
Item_func_eq(THD *thd, Item *a, Item *b):
|
||||
Item_bool_rowready_func2(thd, a, b),
|
||||
abort_on_null(false), in_equality_no(UINT_MAX)
|
||||
in_equality_no(UINT_MAX)
|
||||
{}
|
||||
longlong val_int() override;
|
||||
enum Functype functype() const override { return EQ_FUNC; }
|
||||
@@ -770,7 +764,6 @@ public:
|
||||
static LEX_CSTRING name= {STRING_WITH_LEN("=") };
|
||||
return name;
|
||||
}
|
||||
void top_level_item() override { abort_on_null= true; }
|
||||
Item *negated_item(THD *thd) override;
|
||||
COND *build_equal_items(THD *thd, COND_EQUAL *inherited,
|
||||
bool link_item_fields,
|
||||
@@ -956,15 +949,12 @@ protected:
|
||||
DTCollation cmp_collation;
|
||||
public:
|
||||
bool negated; /* <=> the item represents NOT <func> */
|
||||
bool pred_level; /* <=> [NOT] <func> is used on a predicate level */
|
||||
public:
|
||||
Item_func_opt_neg(THD *thd, Item *a, Item *b, Item *c):
|
||||
Item_bool_func(thd, a, b, c), negated(0), pred_level(0) {}
|
||||
Item_bool_func(thd, a, b, c), negated(0) {}
|
||||
Item_func_opt_neg(THD *thd, List<Item> &list):
|
||||
Item_bool_func(thd, list), negated(0), pred_level(0) {}
|
||||
Item_bool_func(thd, list), negated(0) {}
|
||||
public:
|
||||
void top_level_item() override { pred_level= 1; }
|
||||
bool is_top_level_item() const override { return pred_level; }
|
||||
Item *neg_transformer(THD *thd) override
|
||||
{
|
||||
negated= !negated;
|
||||
@@ -2800,11 +2790,9 @@ public:
|
||||
|
||||
class Item_func_isnotnull :public Item_func_null_predicate
|
||||
{
|
||||
bool abort_on_null;
|
||||
public:
|
||||
Item_func_isnotnull(THD *thd, Item *a):
|
||||
Item_func_null_predicate(thd, a), abort_on_null(0)
|
||||
{ }
|
||||
Item_func_null_predicate(thd, a) {}
|
||||
longlong val_int() override;
|
||||
enum Functype functype() const override { return ISNOTNULL_FUNC; }
|
||||
LEX_CSTRING func_name_cstring() const override
|
||||
@@ -2814,10 +2802,9 @@ public:
|
||||
}
|
||||
enum precedence precedence() const override { return CMP_PRECEDENCE; }
|
||||
table_map not_null_tables() const override
|
||||
{ return abort_on_null ? not_null_tables_cache : 0; }
|
||||
{ return is_top_level_item() ? not_null_tables_cache : 0; }
|
||||
Item *neg_transformer(THD *thd) override;
|
||||
void print(String *str, enum_query_type query_type) override;
|
||||
void top_level_item() override { abort_on_null=1; }
|
||||
Item *get_copy(THD *thd) override
|
||||
{ return get_item_copy<Item_func_isnotnull>(thd, this); }
|
||||
};
|
||||
@@ -3128,17 +3115,19 @@ class Item_cond :public Item_bool_func
|
||||
{
|
||||
protected:
|
||||
List<Item> list;
|
||||
bool abort_on_null;
|
||||
table_map and_tables_cache;
|
||||
|
||||
public:
|
||||
/* Item_cond() is only used to create top level items */
|
||||
Item_cond(THD *thd): Item_bool_func(thd), abort_on_null(1)
|
||||
{ const_item_cache=0; }
|
||||
Item_cond(THD *thd): Item_bool_func(thd)
|
||||
{
|
||||
/* Item_cond() is only used to create top level items */
|
||||
top_level_item();
|
||||
const_item_cache=0;
|
||||
}
|
||||
Item_cond(THD *thd, Item *i1, Item *i2);
|
||||
Item_cond(THD *thd, Item_cond *item);
|
||||
Item_cond(THD *thd, List<Item> &nlist):
|
||||
Item_bool_func(thd), list(nlist), abort_on_null(0) {}
|
||||
Item_bool_func(thd), list(nlist) {}
|
||||
bool add(Item *item, MEM_ROOT *root)
|
||||
{
|
||||
DBUG_ASSERT(item);
|
||||
@@ -3185,8 +3174,6 @@ public:
|
||||
List<Item> &fields, uint flags) override;
|
||||
friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
|
||||
COND **conds);
|
||||
void top_level_item() override { abort_on_null=1; }
|
||||
bool top_level() { return abort_on_null; }
|
||||
void copy_andor_arguments(THD *thd, Item_cond *item);
|
||||
bool walk(Item_processor processor, bool walk_subquery, void *arg) override;
|
||||
Item *transform(THD *thd, Item_transformer transformer, uchar *arg) override;
|
||||
@@ -3542,7 +3529,7 @@ public:
|
||||
}
|
||||
enum precedence precedence() const override { return AND_PRECEDENCE; }
|
||||
table_map not_null_tables() const override
|
||||
{ return abort_on_null ? not_null_tables_cache: and_tables_cache; }
|
||||
{ return is_top_level_item() ? not_null_tables_cache: and_tables_cache; }
|
||||
Item *copy_andor_structure(THD *thd) override;
|
||||
Item *neg_transformer(THD *thd) override;
|
||||
void mark_as_condition_AND_part(TABLE_LIST *embedding) override;
|
||||
|
@@ -1587,7 +1587,7 @@ bool Item_singlerow_subselect::get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t
|
||||
|
||||
Item_exists_subselect::Item_exists_subselect(THD *thd,
|
||||
st_select_lex *select_lex):
|
||||
Item_subselect(thd), upper_not(NULL), abort_on_null(0),
|
||||
Item_subselect(thd), upper_not(NULL),
|
||||
emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0)
|
||||
{
|
||||
DBUG_ENTER("Item_exists_subselect::Item_exists_subselect");
|
||||
@@ -1672,7 +1672,6 @@ Item_allany_subselect::Item_allany_subselect(THD *thd, Item * left_exp,
|
||||
func= func_creator(all_arg);
|
||||
init(select_lex, new (thd->mem_root) select_exists_subselect(thd, this));
|
||||
max_columns= 1;
|
||||
abort_on_null= 0;
|
||||
reset();
|
||||
//if test_limit will fail then error will be reported to client
|
||||
test_limit(select_lex->master_unit());
|
||||
@@ -2247,8 +2246,11 @@ bool Item_allany_subselect::is_maxmin_applicable(JOIN *join)
|
||||
Check if max/min optimization applicable: It is top item of
|
||||
WHERE condition.
|
||||
*/
|
||||
return (abort_on_null || (upper_item && upper_item->is_top_level_item())) &&
|
||||
!(join->select_lex->master_unit()->uncacheable & ~UNCACHEABLE_EXPLAIN) && !func->eqne_op();
|
||||
return ((is_top_level_item() ||
|
||||
(upper_item && upper_item->is_top_level_item())) &&
|
||||
!(join->select_lex->master_unit()->uncacheable &
|
||||
~UNCACHEABLE_EXPLAIN) &&
|
||||
!func->eqne_op());
|
||||
}
|
||||
|
||||
|
||||
@@ -2318,7 +2320,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
|
||||
ref_pointer_array[0],
|
||||
{STRING_WITH_LEN("<ref>")},
|
||||
field_name));
|
||||
if (!abort_on_null && left_expr->maybe_null())
|
||||
if (!is_top_level_item() && left_expr->maybe_null())
|
||||
{
|
||||
/*
|
||||
We can encounter "NULL IN (SELECT ...)". Wrap the added condition
|
||||
@@ -2351,7 +2353,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
|
||||
Item *orig_item= item;
|
||||
|
||||
item= func->create(thd, expr, item);
|
||||
if (!abort_on_null && orig_item->maybe_null())
|
||||
if (!is_top_level_item() && orig_item->maybe_null())
|
||||
{
|
||||
having= new (thd->mem_root) Item_is_not_null_test(thd, this, having);
|
||||
if (left_expr->maybe_null())
|
||||
@@ -2373,7 +2375,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
|
||||
If we may encounter NULL IN (SELECT ...) and care whether subquery
|
||||
result is NULL or FALSE, wrap condition in a trig_cond.
|
||||
*/
|
||||
if (!abort_on_null && left_expr->maybe_null())
|
||||
if (!is_top_level_item() && left_expr->maybe_null())
|
||||
{
|
||||
disable_cond_guard_for_const_null_left_expr(0);
|
||||
if (!(item= new (thd->mem_root) Item_func_trig_cond(thd, item,
|
||||
@@ -2403,7 +2405,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN *join,
|
||||
&select_lex->ref_pointer_array[0],
|
||||
no_matter_name,
|
||||
field_name));
|
||||
if (!abort_on_null && left_expr->maybe_null())
|
||||
if (!is_top_level_item() && left_expr->maybe_null())
|
||||
{
|
||||
disable_cond_guard_for_const_null_left_expr(0);
|
||||
if (!(new_having= new (thd->mem_root)
|
||||
@@ -2602,7 +2604,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
|
||||
list_ref));
|
||||
Item *col_item= new (thd->mem_root)
|
||||
Item_cond_or(thd, item_eq, item_isnull);
|
||||
if (!abort_on_null && left_expr->element_index(i)->maybe_null() &&
|
||||
if (!is_top_level_item() && left_expr->element_index(i)->maybe_null() &&
|
||||
get_cond_guard(i))
|
||||
{
|
||||
disable_cond_guard_for_const_null_left_expr(i);
|
||||
@@ -2621,7 +2623,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
|
||||
ref_pointer_array[i],
|
||||
no_matter_name,
|
||||
list_ref));
|
||||
if (!abort_on_null && left_expr->element_index(i)->maybe_null() &&
|
||||
if (!is_top_level_item() && left_expr->element_index(i)->maybe_null() &&
|
||||
get_cond_guard(i) )
|
||||
{
|
||||
disable_cond_guard_for_const_null_left_expr(i);
|
||||
@@ -2662,7 +2664,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
|
||||
ref_pointer_array[i],
|
||||
no_matter_name,
|
||||
list_ref));
|
||||
if (!abort_on_null && select_lex->ref_pointer_array[i]->maybe_null())
|
||||
if (!is_top_level_item() && select_lex->ref_pointer_array[i]->maybe_null())
|
||||
{
|
||||
Item *having_col_item=
|
||||
new (thd->mem_root)
|
||||
@@ -2694,7 +2696,7 @@ Item_in_subselect::create_row_in_to_exists_cond(JOIN * join,
|
||||
}
|
||||
*having_item= and_items(thd, *having_item, having_col_item);
|
||||
}
|
||||
if (!abort_on_null && left_expr->element_index(i)->maybe_null() &&
|
||||
if (!is_top_level_item() && left_expr->element_index(i)->maybe_null() &&
|
||||
get_cond_guard(i))
|
||||
{
|
||||
if (!(item= new (thd->mem_root)
|
||||
@@ -3663,7 +3665,7 @@ bool Item_in_subselect::init_cond_guards()
|
||||
{
|
||||
DBUG_ASSERT(thd);
|
||||
uint cols_num= left_expr->cols();
|
||||
if (!abort_on_null && !pushed_cond_guards &&
|
||||
if (!is_top_level_item() && !pushed_cond_guards &&
|
||||
(left_expr->maybe_null() || cols_num > 1))
|
||||
{
|
||||
if (!(pushed_cond_guards= (bool*)thd->alloc(sizeof(bool) * cols_num)))
|
||||
@@ -4245,9 +4247,9 @@ bool subselect_uniquesubquery_engine::copy_ref_key(bool skip_constants)
|
||||
- NULL if select produces empty row set
|
||||
- FALSE otherwise.
|
||||
|
||||
In some cases (IN subselect is a top level item, i.e. abort_on_null==TRUE)
|
||||
the caller doesn't distinguish between NULL and FALSE result and we just
|
||||
return FALSE.
|
||||
In some cases (IN subselect is a top level item, i.e.
|
||||
is_top_level_item() == TRUE, the caller doesn't distinguish between NULL and
|
||||
FALSE result and we just return FALSE.
|
||||
Otherwise we make a full table scan to see if there is at least one
|
||||
matching row.
|
||||
|
||||
|
@@ -373,7 +373,6 @@ class Item_exists_subselect :public Item_subselect
|
||||
protected:
|
||||
Item_func_not *upper_not;
|
||||
bool value; /* value of this item (boolean: exists/not-exists) */
|
||||
bool abort_on_null;
|
||||
|
||||
void init_length_and_dec();
|
||||
bool select_prepare_to_be_in();
|
||||
@@ -397,7 +396,7 @@ public:
|
||||
|
||||
Item_exists_subselect(THD *thd_arg, st_select_lex *select_lex);
|
||||
Item_exists_subselect(THD *thd_arg):
|
||||
Item_subselect(thd_arg), upper_not(NULL), abort_on_null(0),
|
||||
Item_subselect(thd_arg), upper_not(NULL),
|
||||
emb_on_expr_nest(NULL), optimizer(0), exists_transformed(0)
|
||||
{}
|
||||
|
||||
@@ -424,8 +423,6 @@ public:
|
||||
bool fix_length_and_dec() override;
|
||||
void print(String *str, enum_query_type query_type) override;
|
||||
bool select_transformer(JOIN *join) override;
|
||||
void top_level_item() override { abort_on_null=1; }
|
||||
bool is_top_level_item() const override { return abort_on_null; }
|
||||
bool exists2in_processor(void *opt_arg) override;
|
||||
|
||||
Item* expr_cache_insert_transformer(THD *thd, uchar *unused) override;
|
||||
|
@@ -16362,9 +16362,9 @@ static void update_const_equal_items(THD *thd, COND *cond, JOIN_TAB *tab,
|
||||
Item *item;
|
||||
while ((item= li++))
|
||||
update_const_equal_items(thd, item, tab,
|
||||
(((Item_cond*) cond)->top_level() &&
|
||||
((Item_cond*) cond)->functype() ==
|
||||
Item_func::COND_AND_FUNC));
|
||||
cond->is_top_level_item() &&
|
||||
((Item_cond*) cond)->functype() ==
|
||||
Item_func::COND_AND_FUNC);
|
||||
}
|
||||
else if (cond->type() == Item::FUNC_ITEM &&
|
||||
((Item_func*) cond)->functype() == Item_func::MULT_EQUAL_FUNC)
|
||||
|
Reference in New Issue
Block a user