From aee84453ab6befef296afdf8e66a8e295b624c72 Mon Sep 17 00:00:00 2001 From: Monty Date: Tue, 14 Jul 2020 18:36:05 +0300 Subject: [PATCH] MDEV-23001 Precreate static Item_bool() to simplify code The following changes where done: - Create global Item: Item_false and Item_true - Replace all creation if 'FALSE' and 'TRUE' top level items used for WHERE/HAVING/ON clauses to use Item_false and Item_true. The benefit are: - Less and faster code - No test needed if we where able to create the new item. - Fixed possible errors if 'new' would have failed for the Item_bool's fixup! 470277728d2e27fe057cf33a437a9e40e1a04b61 --- sql/item.cc | 19 +++++++++++- sql/item.h | 33 ++++++++++++++++++-- sql/item_xmlfunc.cc | 4 +-- sql/opt_index_cond_pushdown.cc | 6 ++-- sql/sql_base.cc | 2 +- sql/sql_select.cc | 55 ++++++++++++++-------------------- 6 files changed, 77 insertions(+), 42 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 74c2c85d4863e..1833fa4f3570c 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -55,7 +55,8 @@ const char *item_empty_name=""; const char *item_used_name= "\0"; static int save_field_in_field(Field *, bool *, Field *, bool); - +const Item_bool_static Item_false("FALSE", 0); +const Item_bool_static Item_true("TRUE", 1); /** Compare two Items for List::add_unique() @@ -438,6 +439,21 @@ Item::Item(THD *thd): } } +/* + This is only used for static const items +*/ + +Item::Item(): + is_expensive_cache(-1), name(null_clex_str), orig_name(0) +{ + DBUG_ASSERT(my_progname == NULL); // before main() + marker= 0; + maybe_null= null_value= with_window_func= with_field= false; + in_rollup= 0; + with_param= 0; + join_tab_idx= MAX_TABLES; +} + const TABLE_SHARE *Item::field_table_or_null() { @@ -3630,6 +3646,7 @@ String *Item_int::val_str(String *str) return str; } + void Item_int::print(String *str, enum_query_type query_type) { StringBuffer buf; diff --git a/sql/item.h b/sql/item.h index 1efd1ae8065c9..061cc9f2e9085 100644 --- a/sql/item.h +++ b/sql/item.h @@ -963,6 +963,7 @@ class Item: public Value_source, optimisation changes in prepared statements */ Item(THD *thd, Item *item); + Item(); /* For const item */ virtual ~Item() { #ifdef EXTRA_DEBUG @@ -1986,7 +1987,7 @@ class Item: public Value_source, virtual bool limit_index_condition_pushdown_processor(void *arg) { return 0; } virtual bool exists2in_processor(void *arg) { return 0; } virtual bool find_selective_predicates_list_processor(void *arg) { return 0; } - bool cleanup_is_expensive_cache_processor(void *arg) + virtual bool cleanup_is_expensive_cache_processor(void *arg) { is_expensive_cache= (int8)(-1); return 0; @@ -2837,6 +2838,7 @@ class Item_basic_value :public Item, fix_charset_and_length(str.charset(), dv, Metadata(&str)); } Item_basic_value(THD *thd): Item(thd) {} + Item_basic_value(): Item() {} public: Field *create_tmp_field_ex(MEM_ROOT *root, TABLE *table, Tmp_field_src *src, @@ -2866,6 +2868,7 @@ class Item_basic_constant :public Item_basic_value { public: Item_basic_constant(THD *thd): Item_basic_value(thd) {}; + Item_basic_constant(): Item_basic_value() {}; bool check_vcol_func_processor(void *arg) { return false; } const Item_const *get_item_const() const { return this; } virtual Item_basic_constant *make_string_literal_concat(THD *thd, @@ -3247,10 +3250,14 @@ class Item_literal: public Item_basic_constant public: Item_literal(THD *thd): Item_basic_constant(thd) { } + Item_literal(): Item_basic_constant() + {} Type type() const override { return CONST_ITEM; } - bool check_partition_func_processor(void *) override { return false;} + bool check_partition_func_processor(void *int_arg) override { return false;} bool const_item() const override { return true; } bool basic_const_item() const override { return true; } + bool is_expensive() override { return false; } + bool cleanup_is_expensive_cache_processor(void *arg) override { return 0; } }; @@ -3258,6 +3265,7 @@ class Item_num: public Item_literal { public: Item_num(THD *thd): Item_literal(thd) { collation= DTCollation_numeric(); } + Item_num(): Item_literal() { collation= DTCollation_numeric(); } Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs) override; bool get_date(THD *thd, MYSQL_TIME *ltime, date_mode_t fuzzydate) override { @@ -4236,6 +4244,13 @@ class Item_int :public Item_num name.str= str_arg; name.length= safe_strlen(name.str); unsigned_flag= flag; } + Item_int(const char *str_arg,longlong i,size_t length): + Item_num(), value(i) + { + max_length=(uint32)length; + name.str= str_arg; name.length= safe_strlen(name.str); + unsigned_flag= 1; + } Item_int(THD *thd, const char *str_arg, size_t length=64); const Type_handler *type_handler() const override { return type_handler_long_or_longlong(); } @@ -4270,6 +4285,8 @@ class Item_bool :public Item_int Item_bool(THD *thd, const char *str_arg, longlong i): Item_int(thd, str_arg, i, 1) {} Item_bool(THD *thd, bool i) :Item_int(thd, (longlong) i, 1) { } + Item_bool(const char *str_arg, longlong i): + Item_int(str_arg, i, 1) {} bool is_bool_literal() const override { return true; } Item *neg_transformer(THD *thd) override; const Type_handler *type_handler() const override @@ -4286,6 +4303,18 @@ class Item_bool :public Item_int }; +class Item_bool_static :public Item_bool +{ +public: + Item_bool_static(const char *str_arg, longlong i): + Item_bool(str_arg, i) {}; + + void set_join_tab_idx(uint join_tab_idx_arg) override + { DBUG_ASSERT(0); } +}; + +extern const Item_bool_static Item_false, Item_true; + class Item_uint :public Item_int { public: diff --git a/sql/item_xmlfunc.cc b/sql/item_xmlfunc.cc index 6e863b1ffef2b..f0c1f0f5075ff 100644 --- a/sql/item_xmlfunc.cc +++ b/sql/item_xmlfunc.cc @@ -1176,13 +1176,13 @@ my_xpath_keyword(MY_XPATH *x, static Item *create_func_true(MY_XPATH *xpath, Item **args, uint nargs) { - return new (xpath->thd->mem_root) Item_bool(xpath->thd, "xpath_bool", 1); + return (Item*) &Item_true; } static Item *create_func_false(MY_XPATH *xpath, Item **args, uint nargs) { - return new (xpath->thd->mem_root) Item_bool(xpath->thd, "xpath_bool", 0); + return (Item*) &Item_false; } diff --git a/sql/opt_index_cond_pushdown.cc b/sql/opt_index_cond_pushdown.cc index 15bc2074e1f8c..e950ad1b7ca1e 100644 --- a/sql/opt_index_cond_pushdown.cc +++ b/sql/opt_index_cond_pushdown.cc @@ -185,8 +185,8 @@ bool uses_index_fields_only(Item *item, TABLE *tbl, uint keyno, static Item *make_cond_for_index(THD *thd, Item *cond, TABLE *table, uint keyno, bool other_tbls_ok) { - if (!cond) - return NULL; + if (!cond || cond->basic_const_item()) + return cond; if (cond->type() == Item::COND_ITEM) { uint n_marked= 0; @@ -218,7 +218,7 @@ static Item *make_cond_for_index(THD *thd, Item *cond, TABLE *table, uint keyno, case 0: return (COND*) 0; case 1: - new_cond->used_tables_cache= used_tables; + /* remove AND level if there is only one argument */ return new_cond->argument_list()->head(); default: new_cond->quick_fix_field(); diff --git a/sql/sql_base.cc b/sql/sql_base.cc index 894e2fb1d84d1..7b61f75035978 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -7428,7 +7428,7 @@ store_top_level_join_columns(THD *thd, TABLE_LIST *table_ref, /* Add a TRUE condition to outer joins that have no common columns. */ if (table_ref_2->outer_join && !table_ref_1->on_expr && !table_ref_2->on_expr) - table_ref_2->on_expr= new (thd->mem_root) Item_int(thd, (longlong) 1, 1); // Always true. + table_ref_2->on_expr= (Item*) &Item_true; /* Change this table reference to become a leaf for name resolution. */ if (left_neighbor) diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 4b03bd056f396..549bd24eb6919 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -2444,7 +2444,7 @@ int JOIN::optimize_stage2() if (!conds && outer_join) { /* Handle the case where we have an OUTER JOIN without a WHERE */ - conds= new (thd->mem_root) Item_bool(thd, true); // Always true + conds= (Item*) &Item_true; } if (impossible_where) @@ -2615,7 +2615,7 @@ int JOIN::optimize_stage2() if (conds && const_table_map != found_const_table_map && (select_options & SELECT_DESCRIBE)) { - conds=new (thd->mem_root) Item_bool(thd, false); // Always false + conds= (Item*) &Item_false; } /* Cache constant expressions in WHERE, HAVING, ON clauses. */ @@ -2933,7 +2933,7 @@ int JOIN::optimize_stage2() having= having->remove_eq_conds(thd, &select_lex->having_value, true); if (select_lex->having_value == Item::COND_FALSE) { - having= new (thd->mem_root) Item_bool(thd, false); + having= (Item*) &Item_false; zero_result_cause= "Impossible HAVING noticed after reading const tables"; error= 0; select_lex->mark_const_derived(zero_result_cause); @@ -5513,7 +5513,7 @@ make_join_statistics(JOIN *join, List &tables_list, if (join->cond_value == Item::COND_FALSE) { join->impossible_where= true; - conds= new (join->thd->mem_root) Item_bool(join->thd, false); + conds= (Item*) &Item_false; } join->cond_equal= NULL; @@ -11758,7 +11758,7 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond) below to check if we should use 'quick' instead. */ DBUG_PRINT("info", ("Item_int")); - tmp= new (thd->mem_root) Item_bool(thd, true); // Always true + tmp= (Item*) &Item_true; } } @@ -15318,7 +15318,7 @@ COND *Item_cond_and::build_equal_items(THD *thd, if (!cond_args->elements && !cond_equal.current_level.elements && !eq_list.elements) - return new (thd->mem_root) Item_bool(thd, true); + return (Item*) &Item_true; List_iterator_fast it(cond_equal.current_level); while ((item_equal= it++)) @@ -15425,7 +15425,7 @@ COND *Item_func_eq::build_equal_items(THD *thd, Item_equal *item_equal; int n= cond_equal.current_level.elements + eq_list.elements; if (n == 0) - return new (thd->mem_root) Item_bool(thd, true); + return (Item*) &Item_true; else if (n == 1) { if ((item_equal= cond_equal.current_level.pop())) @@ -15829,7 +15829,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, List eq_list; Item_func_eq *eq_item= 0; if (((Item *) item_equal)->const_item() && !item_equal->val_int()) - return new (thd->mem_root) Item_bool(thd, false); + return (Item*) &Item_false; Item *item_const= item_equal->get_const(); Item_equal_fields_iterator it(*item_equal); Item *head; @@ -15974,7 +15974,7 @@ Item *eliminate_item_equal(THD *thd, COND *cond, COND_EQUAL *upper_levels, switch (eq_list.elements) { case 0: - res= cond ? cond : new (thd->mem_root) Item_bool(thd, true); + res= cond ? cond : (Item*) &Item_true; break; case 1: if (!cond || cond->is_bool_literal()) @@ -17812,7 +17812,7 @@ Item_func_isnull::remove_eq_conds(THD *thd, Item::cond_result *cond_value, */ - Item *item0= new(thd->mem_root) Item_bool(thd, false); + Item *item0= (Item*) &Item_false; Item *eq_cond= new(thd->mem_root) Item_func_eq(thd, args[0], item0); if (!eq_cond) return this; @@ -22855,6 +22855,8 @@ make_cond_for_table_from_pred(THD *thd, Item *root_cond, Item *cond, return new_cond; } } + else if (cond->basic_const_item()) + return cond; if (is_top_and_level && used_table == rand_table_bit && (cond->used_tables() & ~OUTER_REF_TABLE_BIT) != rand_table_bit) @@ -29432,17 +29434,13 @@ void JOIN::make_notnull_conds_for_range_scans() if (conds && build_notnull_conds_for_range_scans(this, conds, conds->used_tables())) { - Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1); - if (false_cond) - { - /* - Found a IS NULL conjunctive predicate for a null-rejected field - in the WHERE clause - */ - conds= false_cond; - cond_equal= 0; - impossible_where= true; - } + /* + Found a IS NULL conjunctive predicate for a null-rejected field + in the WHERE clause + */ + conds= (Item*) &Item_false; + cond_equal= 0; + impossible_where= true; DBUG_VOID_RETURN; } @@ -29463,9 +29461,7 @@ void JOIN::make_notnull_conds_for_range_scans() Found a IS NULL conjunctive predicate for a null-rejected field of the inner table of an outer join with ON expression tbl->on_expr */ - Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1); - if (false_cond) - tbl->on_expr= false_cond; + tbl->on_expr= (Item*) &Item_false; } } } @@ -29606,7 +29602,6 @@ void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join, { TABLE_LIST *tbl; table_map used_tables= 0; - THD *thd= join->thd; List_iterator li(nest_tbl->nested_join->join_list); while ((tbl= li++)) @@ -29617,9 +29612,7 @@ void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join, if (used_tables && build_notnull_conds_for_range_scans(join, nest_tbl->on_expr, used_tables)) { - Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1); - if (false_cond) - nest_tbl->on_expr= false_cond; + nest_tbl->on_expr= (Item*) &Item_false; } li.rewind(); @@ -29633,11 +29626,7 @@ void build_notnull_conds_for_inner_nest_of_outer_join(JOIN *join, } else if (build_notnull_conds_for_range_scans(join, tbl->on_expr, tbl->table->map)) - { - Item *false_cond= new (thd->mem_root) Item_int(thd, (longlong) 0, 1); - if (false_cond) - tbl->on_expr= false_cond; - } + tbl->on_expr= (Item*) &Item_false; } } }