diff options
author | Marko Mäkelä <marko.makela@mariadb.com> | 2023-01-13 10:45:41 +0200 |
---|---|---|
committer | Marko Mäkelä <marko.makela@mariadb.com> | 2023-01-13 10:45:41 +0200 |
commit | 3386b309756adba6b9633ad18c4e0575c7304cfe (patch) | |
tree | 094ff72f23d15731b16b2606494f69342052b194 /sql | |
parent | 5aa58a0d39e802d8dc0fda2a974713ee69961596 (diff) | |
parent | 73ecab3d26c055928673a2629f4513aa7008dbf0 (diff) | |
download | mariadb-git-3386b309756adba6b9633ad18c4e0575c7304cfe.tar.gz |
Merge 10.5 into 10.6
Diffstat (limited to 'sql')
-rw-r--r-- | sql/field.cc | 2 | ||||
-rw-r--r-- | sql/field.h | 2 | ||||
-rw-r--r-- | sql/item.cc | 104 | ||||
-rw-r--r-- | sql/item.h | 111 | ||||
-rw-r--r-- | sql/item_cmpfunc.cc | 62 | ||||
-rw-r--r-- | sql/item_cmpfunc.h | 25 | ||||
-rw-r--r-- | sql/item_create.cc | 1 | ||||
-rw-r--r-- | sql/item_jsonfunc.cc | 33 | ||||
-rw-r--r-- | sql/log_event_client.cc | 17 | ||||
-rw-r--r-- | sql/mysqld.cc | 25 | ||||
-rw-r--r-- | sql/opt_range.cc | 2 | ||||
-rw-r--r-- | sql/opt_range.h | 8 | ||||
-rw-r--r-- | sql/signal_handler.cc | 4 | ||||
-rw-r--r-- | sql/sp_head.cc | 4 | ||||
-rw-r--r-- | sql/sql_cache.h | 2 | ||||
-rw-r--r-- | sql/sql_class.h | 17 | ||||
-rw-r--r-- | sql/sql_insert.cc | 13 | ||||
-rw-r--r-- | sql/sql_join_cache.cc | 35 | ||||
-rw-r--r-- | sql/sql_select.cc | 25 | ||||
-rw-r--r-- | sql/sql_select.h | 9 | ||||
-rw-r--r-- | sql/sql_tvc.cc | 5 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 2 | ||||
-rw-r--r-- | sql/sys_vars.cc | 2 | ||||
-rw-r--r-- | sql/table.cc | 5 |
24 files changed, 364 insertions, 151 deletions
diff --git a/sql/field.cc b/sql/field.cc index 301f6deb403..d721bdefe52 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -10971,7 +10971,7 @@ Create_field *Create_field::clone(MEM_ROOT *mem_root) const } /** - Return true if default is an expression that must be saved explicitely + Return true if default is an expression that must be saved explicitly This is: - Not basic constants diff --git a/sql/field.h b/sql/field.h index 25c880c5aba..62dbdc00176 100644 --- a/sql/field.h +++ b/sql/field.h @@ -5431,7 +5431,7 @@ public: Record_addr addr(true); return make_field(share, mem_root, &addr, field_name_arg); } - /* Return true if default is an expression that must be saved explicitely */ + /* Return true if default is an expression that must be saved explicitly */ bool has_default_expression(); bool has_default_now_unireg_check() const diff --git a/sql/item.cc b/sql/item.cc index fdeafddc860..4f5b207c9e5 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -41,6 +41,7 @@ // find_item_in_list, // RESOLVED_AGAINST_ALIAS, ... #include "sql_expression_cache.h" +#include "sql_lex.h" // empty_clex_str const String my_null_string("NULL", 4, default_charset_info); const String my_default_string("DEFAULT", 7, default_charset_info); @@ -1315,12 +1316,11 @@ Item *Item_cache::safe_charset_converter(THD *thd, CHARSET_INFO *tocs) Item *conv= example->safe_charset_converter(thd, tocs); if (conv == example) return this; - Item_cache *cache; - if (!conv || conv->fix_fields(thd, (Item **) NULL) || - unlikely(!(cache= new (thd->mem_root) Item_cache_str(thd, conv)))) - return NULL; // Safe conversion is not possible, or OEM - cache->setup(thd, conv); - return cache; + if (!conv || conv->fix_fields(thd, (Item **) NULL)) + return NULL; // Safe conversion is not possible, or OOM + setup(thd, conv); + thd->change_item_tree(&example, conv); + return this; } @@ -1509,17 +1509,11 @@ int Item::save_in_field_no_warnings(Field *field, bool no_conversions) TABLE *table= field->table; THD *thd= table->in_use; enum_check_fields org_count_cuted_fields= thd->count_cuted_fields; - sql_mode_t org_sql_mode= thd->variables.sql_mode; MY_BITMAP *old_map= dbug_tmp_use_all_columns(table, &table->write_set); - - thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); - thd->variables.sql_mode|= MODE_INVALID_DATES; - thd->count_cuted_fields= CHECK_FIELD_IGNORE; - + Use_relaxed_field_copy urfc(table->in_use); res= save_in_field(field, no_conversions); thd->count_cuted_fields= org_count_cuted_fields; - thd->variables.sql_mode= org_sql_mode; dbug_tmp_restore_column_map(&table->write_set, old_map); return res; } @@ -2330,7 +2324,8 @@ void Item::split_sum_func2(THD *thd, Ref_ptr_array ref_pointer_array, if (unlikely((!(used_tables() & ~PARAM_TABLE_BIT) || (type() == REF_ITEM && - ((Item_ref*)this)->ref_type() != Item_ref::VIEW_REF)))) + ((Item_ref*)this)->ref_type() != Item_ref::VIEW_REF && + ((Item_ref*)this)->ref_type() != Item_ref::DIRECT_REF)))) return; } @@ -2647,7 +2642,6 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, safe_args[1]= args[item_sep]; } - bool res= FALSE; uint i; DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); @@ -2667,19 +2661,31 @@ bool Type_std_attributes::agg_item_set_converter(const DTCollation &coll, args[item_sep]= safe_args[1]; } my_coll_agg_error(args, nargs, fname.str, item_sep); - res= TRUE; - break; // we cannot return here, we need to restore "arena". + return TRUE; } - thd->change_item_tree(arg, conv); - if (conv->fix_fields_if_needed(thd, arg)) + return TRUE; + + Query_arena *arena, backup; + arena= thd->activate_stmt_arena_if_needed(&backup); + if (arena) { - res= TRUE; - break; // we cannot return here, we need to restore "arena". + Item_direct_ref_to_item *ref= + new (thd->mem_root) Item_direct_ref_to_item(thd, *arg); + if ((ref == NULL) || ref->fix_fields(thd, (Item **)&ref)) + { + thd->restore_active_arena(arena, &backup); + return TRUE; + } + *arg= ref; + thd->restore_active_arena(arena, &backup); + ref->change_item(thd, conv); } + else + thd->change_item_tree(arg, conv); } - return res; + return FALSE; } @@ -7336,7 +7342,7 @@ bool Item_null::send(Protocol *protocol, st_value *buffer) bool Item::cache_const_expr_analyzer(uchar **arg) { - bool *cache_flag= (bool*)*arg; + uchar *cache_flag= *arg; if (!*cache_flag) { Item *item= real_item(); @@ -7375,9 +7381,9 @@ bool Item::cache_const_expr_analyzer(uchar **arg) Item* Item::cache_const_expr_transformer(THD *thd, uchar *arg) { - if (*(bool*)arg) + if (*arg) { - *((bool*)arg)= FALSE; + *arg= FALSE; Item_cache *cache= get_cache(thd); if (!cache) return NULL; @@ -10319,8 +10325,8 @@ bool Item_cache_timestamp::cache_value() if (!example) return false; value_cached= true; - null_value= example->val_native_with_conversion_result(current_thd, &m_native, - type_handler()); + null_value_inside= null_value= + example->val_native_with_conversion_result(current_thd, &m_native, type_handler()); return true; } @@ -10878,8 +10884,6 @@ const char *dbug_print(SELECT_LEX_UNIT *x) { return dbug_print_unit(x); } #endif /*DBUG_OFF*/ - - void Item::register_in(THD *thd) { next= thd->free_list; @@ -10887,6 +10891,48 @@ void Item::register_in(THD *thd) } +Item_direct_ref_to_item::Item_direct_ref_to_item(THD *thd, Item *item) + : Item_direct_ref(thd, NULL, NULL, empty_clex_str, empty_clex_str) +{ + m_item= item; + ref= (Item**)&m_item; +} + +bool Item_direct_ref_to_item::fix_fields(THD *thd, Item **) +{ + DBUG_ASSERT(m_item != NULL); + if (m_item->fix_fields_if_needed_for_scalar(thd, ref)) + return TRUE; + set_properties(); + return FALSE; +} + +void Item_direct_ref_to_item::print(String *str, enum_query_type query_type) +{ + m_item->print(str, query_type); +} + +Item *Item_direct_ref_to_item::safe_charset_converter(THD *thd, + CHARSET_INFO *tocs) +{ + Item *conv= m_item->safe_charset_converter(thd, tocs); + if (conv != m_item) + { + if (conv== NULL || conv->fix_fields(thd, &conv)) + return NULL; + change_item(thd, conv); + } + return this; +} + +void Item_direct_ref_to_item::change_item(THD *thd, Item *i) +{ + DBUG_ASSERT(i->fixed()); + thd->change_item_tree(ref, i); + set_properties(); +} + + bool Item::cleanup_excluding_immutables_processor (void *arg) { if (!(get_extraction_flag() == MARKER_IMMUTABLE)) diff --git a/sql/item.h b/sql/item.h index 87b0f93e7be..18a3c1340c0 100644 --- a/sql/item.h +++ b/sql/item.h @@ -2141,6 +2141,11 @@ public: return ((this->*transformer) (thd, arg_t)); return 0; } + virtual Item* top_level_compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t) + { + return compile(thd, analyzer, arg_p, transformer, arg_t); + } virtual void traverse_cond(Cond_traverser traverser, void *arg, traverse_order order) @@ -6174,6 +6179,14 @@ public: Item_direct_ref::save_in_result_field(no_conversions); } + int save_in_field(Field *field, bool no_conversions) override + { + if (check_null_ref()) + return set_field_to_null_with_conversions(field, no_conversions); + + return Item_direct_ref::save_in_field(field, no_conversions); + } + void cleanup() override { null_ref_table= NULL; @@ -7764,6 +7777,104 @@ inline void Virtual_column_info::print(String* str) expr->print_for_table_def(str); } +class Item_direct_ref_to_item : public Item_direct_ref +{ + Item *m_item; +public: + Item_direct_ref_to_item(THD *thd, Item *item); + + void change_item(THD *thd, Item *); + + bool fix_fields(THD *thd, Item **it); + + void print(String *str, enum_query_type query_type); + + Item *safe_charset_converter(THD *thd, CHARSET_INFO *tocs); + Item *get_tmp_table_item(THD *thd) + { return m_item->get_tmp_table_item(thd); } + Item *get_copy(THD *thd) + { return m_item->get_copy(thd); } + COND *build_equal_items(THD *thd, COND_EQUAL *inherited, + bool link_item_fields, + COND_EQUAL **cond_equal_ref) + { + return m_item->build_equal_items(thd, inherited, link_item_fields, + cond_equal_ref); + } + const char *full_name() const { return m_item->full_name(); } + void make_send_field(THD *thd, Send_field *field) + { m_item->make_send_field(thd, field); } + bool eq(const Item *item, bool binary_cmp) const + { + Item *it= ((Item *) item)->real_item(); + return m_item->eq(it, binary_cmp); + } + void fix_after_pullout(st_select_lex *new_parent, Item **refptr, bool merge) + { m_item->fix_after_pullout(new_parent, &m_item, merge); } + void save_val(Field *to) + { return m_item->save_val(to); } + void save_result(Field *to) + { return m_item->save_result(to); } + int save_in_field(Field *to, bool no_conversions) + { return m_item->save_in_field(to, no_conversions); } + const Type_handler *type_handler() const { return m_item->type_handler(); } + table_map used_tables() const { return m_item->used_tables(); } + void update_used_tables() + { m_item->update_used_tables(); } + bool const_item() const { return m_item->const_item(); } + table_map not_null_tables() const { return m_item->not_null_tables(); } + bool walk(Item_processor processor, bool walk_subquery, void *arg) + { + return m_item->walk(processor, walk_subquery, arg) || + (this->*processor)(arg); + } + bool enumerate_field_refs_processor(void *arg) + { return m_item->enumerate_field_refs_processor(arg); } + Item_field *field_for_view_update() + { return m_item->field_for_view_update(); } + + /* Row emulation: forwarding of ROW-related calls to orig_item */ + uint cols() const + { return m_item->cols(); } + Item* element_index(uint i) + { return this; } + Item** addr(uint i) + { return &m_item; } + bool check_cols(uint c) + { return Item::check_cols(c); } + bool null_inside() + { return m_item->null_inside(); } + void bring_value() + {} + + Item_equal *get_item_equal() { return m_item->get_item_equal(); } + void set_item_equal(Item_equal *item_eq) { m_item->set_item_equal(item_eq); } + Item_equal *find_item_equal(COND_EQUAL *cond_equal) + { return m_item->find_item_equal(cond_equal); } + Item *propagate_equal_fields(THD *thd, const Context &ctx, COND_EQUAL *cond) + { return m_item->propagate_equal_fields(thd, ctx, cond); } + Item *replace_equal_field(THD *thd, uchar *arg) + { return m_item->replace_equal_field(thd, arg); } + + bool excl_dep_on_table(table_map tab_map) + { return m_item->excl_dep_on_table(tab_map); } + bool excl_dep_on_grouping_fields(st_select_lex *sel) + { return m_item->excl_dep_on_grouping_fields(sel); } + bool is_expensive() { return m_item->is_expensive(); } + Item* build_clone(THD *thd) { return get_copy(thd); } + + void split_sum_func(THD *thd, Ref_ptr_array ref_pointer_array, + List<Item> &fields, uint flags) + { + m_item->split_sum_func(thd, ref_pointer_array, fields, flags); + } + /* + This processor states that this is safe for virtual columns + (because this Item transparency) + */ + bool check_vcol_func_processor(void *arg) { return FALSE;} +}; + inline bool TABLE::mark_column_with_deps(Field *field) { bool res; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 74d63629fe9..3e1f6d96803 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -418,18 +418,9 @@ bool Item_func::setup_args_and_comparator(THD *thd, Arg_comparator *cmp) if (args[0]->cmp_type() == STRING_RESULT && args[1]->cmp_type() == STRING_RESULT) { - Query_arena *arena, backup; - arena= thd->activate_stmt_arena_if_needed(&backup); - DTCollation tmp; - bool ret= agg_arg_charsets_for_comparison(tmp, args, 2); - - if (arena) - thd->restore_active_arena(arena, &backup); - - if (ret) - return ret; - + if (agg_arg_charsets_for_comparison(tmp, args, 2)) + return true; cmp->m_compare_collation= tmp.collation; } // Convert constants when compared to int/year field @@ -5201,7 +5192,8 @@ bool Item_cond::walk(Item_processor processor, bool walk_subquery, void *arg) Item returned as the result of transformation of the root node */ -Item *Item_cond::transform(THD *thd, Item_transformer transformer, uchar *arg) +Item *Item_cond::do_transform(THD *thd, Item_transformer transformer, uchar *arg, + bool toplevel) { DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); @@ -5209,7 +5201,8 @@ Item *Item_cond::transform(THD *thd, Item_transformer transformer, uchar *arg) Item *item; while ((item= li++)) { - Item *new_item= item->transform(thd, transformer, arg); + Item *new_item= toplevel ? item->top_level_transform(thd, transformer, arg) + : item->transform(thd, transformer, arg); if (!new_item) return 0; @@ -5219,7 +5212,9 @@ Item *Item_cond::transform(THD *thd, Item_transformer transformer, uchar *arg) Otherwise we'll be allocating a lot of unnecessary memory for change records at each execution. */ - if (new_item != item) + if (toplevel) + *li.ref()= new_item; + else if (new_item != item) thd->change_item_tree(li.ref(), new_item); } return Item_func::transform(thd, transformer, arg); @@ -5227,35 +5222,6 @@ Item *Item_cond::transform(THD *thd, Item_transformer transformer, uchar *arg) /** - Transform an Item_cond object with a transformer callback function. - - This is like transform() but doesn't use change_item_tree(), - because top-level expression is stored in prep_where/prep_on anyway and - is restored from there, there is no need to use change_item_tree(). - - Furthermore, it can be actually harmful to use it, if build_equal_items() - had replaced Item_eq with Item_equal and deleted list_node with a pointer - to Item_eq. In this case rollback_item_tree_changes() would modify the - deleted list_node. -*/ -Item *Item_cond::top_level_transform(THD *thd, Item_transformer transformer, uchar *arg) -{ - DBUG_ASSERT(!thd->stmt_arena->is_stmt_prepare()); - - List_iterator<Item> li(list); - Item *item; - while ((item= li++)) - { - Item *new_item= item->top_level_transform(thd, transformer, arg); - if (!new_item) - return 0; - *li.ref()= new_item; - } - return Item_func::transform(thd, transformer, arg); -} - - -/** Compile Item_cond object with a processor and a transformer callback functions. @@ -5279,8 +5245,8 @@ Item *Item_cond::top_level_transform(THD *thd, Item_transformer transformer, uch Item returned as the result of transformation of the root node */ -Item *Item_cond::compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, - Item_transformer transformer, uchar *arg_t) +Item *Item_cond::do_compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t, bool toplevel) { if (!(this->*analyzer)(arg_p)) return 0; @@ -5295,7 +5261,11 @@ Item *Item_cond::compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, */ uchar *arg_v= *arg_p; Item *new_item= item->compile(thd, analyzer, &arg_v, transformer, arg_t); - if (new_item && new_item != item) + if (!new_item || new_item == item) + continue; + if (toplevel) + *li.ref()= new_item; + else thd->change_item_tree(li.ref(), new_item); } return Item_func::transform(thd, transformer, arg_t); diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 0e8cb90f096..e12a527d8af 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -3194,13 +3194,32 @@ public: 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; - Item *top_level_transform(THD *thd, Item_transformer transformer, uchar *arg) override; + Item *do_transform(THD *thd, Item_transformer transformer, uchar *arg, + bool toplevel); + Item *transform(THD *thd, Item_transformer transformer, uchar *arg) override + { + return do_transform(thd, transformer, arg, 0); + } + Item *top_level_transform(THD *thd, Item_transformer transformer, uchar *arg) + override + { + return do_transform(thd, transformer, arg, 1); + } void traverse_cond(Cond_traverser, void *arg, traverse_order order) override; void neg_arguments(THD *thd); Item* propagate_equal_fields(THD *, const Context &, COND_EQUAL *) override; + Item *do_compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t, bool toplevel); Item *compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, - Item_transformer transformer, uchar *arg_t) override; + Item_transformer transformer, uchar *arg_t) override + { + return do_compile(thd, analyzer, arg_p, transformer, arg_t, 0); + } + Item* top_level_compile(THD *thd, Item_analyzer analyzer, uchar **arg_p, + Item_transformer transformer, uchar *arg_t) override + { + return do_compile(thd, analyzer, arg_p, transformer, arg_t, 1); + } bool eval_not_null_tables(void *opt_arg) override; bool find_not_null_fields(table_map allowed) override; Item *build_clone(THD *thd) override; diff --git a/sql/item_create.cc b/sql/item_create.cc index 1562cab61ed..73e3befc9d6 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -5613,6 +5613,7 @@ Native_func_registry func_array[] = { { STRING_WITH_LEN("JSON_CONTAINS_PATH") }, BUILDER(Create_func_json_contains_path)}, { { STRING_WITH_LEN("JSON_DEPTH") }, BUILDER(Create_func_json_depth)}, { { STRING_WITH_LEN("JSON_DETAILED") }, BUILDER(Create_func_json_detailed)}, + { { STRING_WITH_LEN("JSON_PRETTY") }, BUILDER(Create_func_json_detailed)}, { { STRING_WITH_LEN("JSON_EXISTS") }, BUILDER(Create_func_json_exists)}, { { STRING_WITH_LEN("JSON_EXTRACT") }, BUILDER(Create_func_json_extract)}, { { STRING_WITH_LEN("JSON_INSERT") }, BUILDER(Create_func_json_insert)}, diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc index 1dc511e8da9..bbfd5f012eb 100644 --- a/sql/item_jsonfunc.cc +++ b/sql/item_jsonfunc.cc @@ -260,6 +260,10 @@ static int json_nice(json_engine_t *je, String *nice_js, static const char *comma= ", ", *colon= "\": "; uint comma_len, colon_len; int first_value= 1; + int value_size = 0; + int curr_state= -1; + int64_t value_len= 0; + String curr_str{}; nice_js->length(0); nice_js->set_charset(je->s.cs); @@ -286,6 +290,7 @@ static int json_nice(json_engine_t *je, String *nice_js, do { + curr_state= je->state; switch (je->state) { case JST_KEY: @@ -333,17 +338,23 @@ handle_value: if (append_simple(nice_js, je->value_begin, je->value_end - je->value_begin)) goto error; - + + curr_str.copy((const char *)je->value_begin, + je->value_end - je->value_begin, je->s.cs); + value_len= je->value_end - je->value_begin; first_value= 0; + if (value_size != -1) + value_size++; } else { if (mode == Item_func_json_format::DETAILED && - depth > 0 && + depth > 0 && !(curr_state != JST_KEY) && append_tab(nice_js, depth, tab_size)) goto error; nice_js->append((je->value_type == JSON_VALUE_OBJECT) ? "{" : "[", 1); first_value= 1; + value_size= (je->value_type == JSON_VALUE_OBJECT) ? -1: 0; depth++; } @@ -352,11 +363,27 @@ handle_value: case JST_OBJ_END: case JST_ARRAY_END: depth--; - if (mode == Item_func_json_format::DETAILED && + if (mode == Item_func_json_format::DETAILED && (value_size > 1 || value_size == -1) && append_tab(nice_js, depth, tab_size)) goto error; + + if (mode == Item_func_json_format::DETAILED && + value_size == 1 && je->state != JST_OBJ_END) + { + for (auto i = 0; i < value_len; i++) + { + nice_js->chop(); + } + for (auto i = 0; i < (depth + 1) * tab_size + 1; i++) + { + nice_js->chop(); + } + nice_js->append(curr_str); + } + nice_js->append((je->state == JST_OBJ_END) ? "}": "]", 1); first_value= 0; + value_size= -1; break; default: diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc index f63761ffa3f..621fd7ceaa1 100644 --- a/sql/log_event_client.cc +++ b/sql/log_event_client.cc @@ -839,10 +839,12 @@ log_event_print_value(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info, my_b_write_bit(file, ptr , (meta & 0xFF) * 8); return meta & 0xFF; + case MYSQL_TYPE_BLOB_COMPRESSED: case MYSQL_TYPE_BLOB: switch (meta) { case 1: - strmake(typestr, "TINYBLOB/TINYTEXT", typestr_length); + my_snprintf(typestr, typestr_length, "TINYBLOB/TINYTEXT%s", + type == MYSQL_TYPE_BLOB_COMPRESSED ? " COMPRESSED" : ""); if (!ptr) goto return_null; @@ -850,7 +852,8 @@ log_event_print_value(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info, my_b_write_quoted(file, ptr + 1, length); return length + 1; case 2: - strmake(typestr, "BLOB/TEXT", typestr_length); + my_snprintf(typestr, typestr_length, "BLOB/TEXT%s", + type == MYSQL_TYPE_BLOB_COMPRESSED ? " COMPRESSED" : ""); if (!ptr) goto return_null; @@ -858,7 +861,8 @@ log_event_print_value(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info, my_b_write_quoted(file, ptr + 2, length); return length + 2; case 3: - strmake(typestr, "MEDIUMBLOB/MEDIUMTEXT", typestr_length); + my_snprintf(typestr, typestr_length, "MEDIUMBLOB/MEDIUMTEXT%s", + type == MYSQL_TYPE_BLOB_COMPRESSED ? " COMPRESSED" : ""); if (!ptr) goto return_null; @@ -866,7 +870,8 @@ log_event_print_value(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info, my_b_write_quoted(file, ptr + 3, length); return length + 3; case 4: - strmake(typestr, "LONGBLOB/LONGTEXT", typestr_length); + my_snprintf(typestr, typestr_length, "LONGBLOB/LONGTEXT%s", + type == MYSQL_TYPE_BLOB_COMPRESSED ? " COMPRESSED" : ""); if (!ptr) goto return_null; @@ -878,10 +883,12 @@ log_event_print_value(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info, return 0; } + case MYSQL_TYPE_VARCHAR_COMPRESSED: case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_VAR_STRING: length= meta; - my_snprintf(typestr, typestr_length, "VARSTRING(%d)", length); + my_snprintf(typestr, typestr_length, "VARSTRING(%d)%s", length, + type == MYSQL_TYPE_VARCHAR_COMPRESSED ? " COMPRESSED" : ""); if (!ptr) goto return_null; diff --git a/sql/mysqld.cc b/sql/mysqld.cc index ecf2530b51c..f4da993673d 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -132,6 +132,8 @@ #include <my_service_manager.h> +#include <source_revision.h> + #define mysqld_charset &my_charset_latin1 @@ -4012,21 +4014,6 @@ static int init_common_variables() mysql_real_data_home_len= uint(strlen(mysql_real_data_home)); - if (!opt_abort) - { - if (IS_SYSVAR_AUTOSIZE(&server_version_ptr)) - sql_print_information("%s (server %s) starting as process %lu ...", - my_progname, server_version, (ulong) getpid()); - else - { - char real_server_version[SERVER_VERSION_LENGTH]; - set_server_version(real_server_version, sizeof(real_server_version)); - sql_print_information("%s (server %s as %s) starting as process %lu ...", - my_progname, real_server_version, server_version, - (ulong) getpid()); - } - } - sf_leaking_memory= 0; // no memory leaks from now on #ifndef EMBEDDED_LIBRARY @@ -4879,6 +4866,14 @@ static int init_server_components() error_handler_hook= my_message_sql; proc_info_hook= set_thd_stage_info; + /* + Print source revision hash, as one of the first lines, if not the + first in error log, for troubleshooting and debugging purposes + */ + if (!opt_help) + sql_print_information("Starting MariaDB %s source revision %s as process %lu", + server_version, SOURCE_REVISION, (ulong) getpid()); + #ifdef WITH_PERFSCHEMA_STORAGE_ENGINE /* Parsing the performance schema command line option may have reported diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 06334263220..e3c80a300a1 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -10621,7 +10621,7 @@ key_or(RANGE_OPT_PARAM *param, SEL_ARG *key1,SEL_ARG *key2) tmp: [---------] */ key2->copy_max_to_min(tmp); - key2= key2_next; + key2->next= key2_next; // In case of key2_shared } continue; } diff --git a/sql/opt_range.h b/sql/opt_range.h index 5594397e709..50c0ee921c9 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -779,7 +779,7 @@ class QUICK_RANGE :public Sql_alloc { } /** - Initalizes a key_range object for communication with storage engine. + Initializes a key_range object for communication with storage engine. This function facilitates communication with the Storage Engine API by translating the minimum endpoint of the interval represented by this @@ -800,7 +800,7 @@ class QUICK_RANGE :public Sql_alloc { } /** - Initalizes a key_range object for communication with storage engine. + Initializes a key_range object for communication with storage engine. This function facilitates communication with the Storage Engine API by translating the minimum endpoint of the interval represented by this @@ -817,7 +817,7 @@ class QUICK_RANGE :public Sql_alloc { } /** - Initalizes a key_range object for communication with storage engine. + Initializes a key_range object for communication with storage engine. This function facilitates communication with the Storage Engine API by translating the maximum endpoint of the interval represented by this @@ -838,7 +838,7 @@ class QUICK_RANGE :public Sql_alloc { } /** - Initalizes a key_range object for communication with storage engine. + Initializes a key_range object for communication with storage engine. This function facilitates communication with the Storage Engine API by translating the maximum endpoint of the interval represented by this diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc index aafbca66eda..4ca3c855066 100644 --- a/sql/signal_handler.cc +++ b/sql/signal_handler.cc @@ -23,6 +23,7 @@ #include "mysqld.h" #include "sql_class.h" #include "my_stacktrace.h" +#include <source_revision.h> #ifdef _WIN32 #include <crtdbg.h> @@ -181,7 +182,8 @@ extern "C" sig_handler handle_fatal_signal(int sig) "something is definitely wrong and this may fail.\n\n"); set_server_version(server_version, sizeof(server_version)); - my_safe_printf_stderr("Server version: %s\n", server_version); + my_safe_printf_stderr("Server version: %s source revision: %s\n", + server_version, SOURCE_REVISION); if (dflt_key_cache) my_safe_printf_stderr("key_buffer_size=%zu\n", diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 0fec4c9f3d7..1f1bf07f78d 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2413,7 +2413,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) Disable slow log if: - Slow logging is enabled (no change needed) - This is a normal SP (not event log) - - If we have not explicitely disabled logging of SP + - If we have not explicitly disabled logging of SP */ if (save_enable_slow_log && ((!(m_flags & LOG_SLOW_STATEMENTS) && @@ -2427,7 +2427,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args) Disable general log if: - If general log is enabled (no change needed) - This is a normal SP (not event log) - - If we have not explicitely disabled logging of SP + - If we have not explicitly disabled logging of SP */ if (!(thd->variables.option_bits & OPTION_LOG_OFF) && (!(m_flags & LOG_GENERAL_LOG) && diff --git a/sql/sql_cache.h b/sql/sql_cache.h index 3c561b3bd15..126693b9964 100644 --- a/sql/sql_cache.h +++ b/sql/sql_cache.h @@ -32,7 +32,7 @@ typedef struct st_changed_table_list CHANGED_TABLE_LIST; Can't create new free memory block if unused memory in block less then QUERY_CACHE_MIN_ALLOCATION_UNIT. if QUERY_CACHE_MIN_ALLOCATION_UNIT == 0 then - QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automaticaly + QUERY_CACHE_MIN_ALLOCATION_UNIT choosed automatically */ #define QUERY_CACHE_MIN_ALLOCATION_UNIT 512 diff --git a/sql/sql_class.h b/sql/sql_class.h index 626a4bd814a..1147e5c21a0 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -6125,7 +6125,7 @@ class select_insert :public select_result_interceptor { int prepare(List<Item> &list, SELECT_LEX_UNIT *u); virtual int prepare2(JOIN *join); virtual int send_data(List<Item> &items); - virtual bool store_values(List<Item> &values, bool ignore_errors); + virtual bool store_values(List<Item> &values); virtual bool can_rollback_data() { return 0; } bool prepare_eof(); bool send_ok_packet(); @@ -6171,7 +6171,7 @@ public: int prepare(List<Item> &list, SELECT_LEX_UNIT *u); int binlog_show_create_table(TABLE **tables, uint count); - bool store_values(List<Item> &values, bool ignore_errors); + bool store_values(List<Item> &values); bool send_eof(); virtual void abort_result_set(); virtual bool can_rollback_data() { return 1; } @@ -7606,6 +7606,19 @@ public: }; +class Use_relaxed_field_copy: public Sql_mode_save, + public Check_level_instant_set +{ +public: + Use_relaxed_field_copy(THD *thd) : + Sql_mode_save(thd), Check_level_instant_set(thd, CHECK_FIELD_IGNORE) + { + thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); + thd->variables.sql_mode|= MODE_INVALID_DATES; + } +}; + + /** This class resembles the SQL Standard schema qualified object name: <schema qualified name> ::= [ <schema name> <period> ] <qualified identifier> diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 5ad968f19a0..4b58514a7a3 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -4094,7 +4094,7 @@ int select_insert::send_data(List<Item> &values) bool error=0; thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields - if (store_values(values, info.ignore)) + if (store_values(values)) DBUG_RETURN(1); thd->count_cuted_fields= CHECK_FIELD_ERROR_FOR_NULL; if (unlikely(thd->is_error())) @@ -4152,17 +4152,17 @@ int select_insert::send_data(List<Item> &values) } -bool select_insert::store_values(List<Item> &values, bool ignore_errors) +bool select_insert::store_values(List<Item> &values) { DBUG_ENTER("select_insert::store_values"); bool error; if (fields->elements) error= fill_record_n_invoke_before_triggers(thd, table, *fields, values, - ignore_errors, TRG_EVENT_INSERT); + true, TRG_EVENT_INSERT); else error= fill_record_n_invoke_before_triggers(thd, table, table->field_to_fill(), - values, ignore_errors, TRG_EVENT_INSERT); + values, true, TRG_EVENT_INSERT); DBUG_RETURN(error); } @@ -4583,6 +4583,7 @@ TABLE *select_create::create_table_from_items(THD *thd, List<Item> *items, */ DBUG_ASSERT(0); } + create_table->table->pos_in_table_list= create_table; } } else @@ -4966,10 +4967,10 @@ bool binlog_drop_table(THD *thd, TABLE *table) } -bool select_create::store_values(List<Item> &values, bool ignore_errors) +bool select_create::store_values(List<Item> &values) { return fill_record_n_invoke_before_triggers(thd, table, field, values, - ignore_errors, TRG_EVENT_INSERT); + true, TRG_EVENT_INSERT); } diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc index 620c52a3f40..c7b6a0bf6e4 100644 --- a/sql/sql_join_cache.cc +++ b/sql/sql_join_cache.cc @@ -2293,11 +2293,7 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last) int error; enum_nested_loop_state rc= NESTED_LOOP_OK; join_tab->table->null_row= 0; - bool check_only_first_match= - join_tab->check_only_first_match() && - (!join_tab->first_inner || // semi-join case - join_tab->first_inner == join_tab->first_unmatched); // outer join case - bool outer_join_first_inner= join_tab->is_first_inner_for_outer_join(); + bool check_only_first_match= join_tab->check_only_first_match(); DBUG_ENTER("JOIN_CACHE::join_matching_records"); /* Return at once if there are no records in the join buffer */ @@ -2363,7 +2359,34 @@ enum_nested_loop_state JOIN_CACHE::join_matching_records(bool skip_last) Also those records that must be null complemented are not considered as candidates for matches. */ - if ((!check_only_first_match && !outer_join_first_inner) || + + bool not_exists_opt_is_applicable= true; + if (check_only_first_match && join_tab->first_inner) + { + /* + This is the case with not_exists optimization for nested outer join + when join_tab is the last inner table for one or more embedding outer + joins. To safely use 'not_exists' optimization in this case we have + to check that the match flags for all these embedding outer joins are + in the 'on' state. + (See also a similar check in evaluate_join_record() for the case when + join buffer are not used.) + */ + for (JOIN_TAB *tab= join_tab->first_inner; + tab && tab->first_inner && tab->last_inner == join_tab; + tab= tab->first_inner->first_upper) + { + if (get_match_flag_by_pos_from_join_buffer(rec_ptr, tab) != + MATCH_FOUND) + { + not_exists_opt_is_applicable= false; + break; + } + } + } + + if (!check_only_first_match || + (join_tab->first_inner && !not_exists_opt_is_applicable) || !skip_next_candidate_for_match(rec_ptr)) { read_next_candidate_for_match(rec_ptr); diff --git a/sql/sql_select.cc b/sql/sql_select.cc index d8073d320f8..3c2be0b1c8b 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -18696,7 +18696,8 @@ Field *Item_field::create_tmp_field_ex(MEM_ROOT *root, TABLE *table, src->set_field(field); if (!(result= create_tmp_field_from_item_field(root, table, NULL, param))) return NULL; - if (field->eq_def(result)) + if (!(field->flags & NO_DEFAULT_VALUE_FLAG) && + field->eq_def(result)) src->set_default_field(field); return result; } @@ -19577,8 +19578,10 @@ bool Create_tmp_table::finalize(THD *thd, { /* Copy default value. We have to use field_conv() for copy, instead of - memcpy(), because bit_fields may be stored differently + memcpy(), because bit_fields may be stored differently. + But otherwise we copy as is, in particular, ignore NO_ZERO_DATE, etc */ + Use_relaxed_field_copy urfc(thd); my_ptrdiff_t ptr_diff= (orig_field->table->s->default_values - orig_field->table->record[0]); field->set_notnull(); @@ -28955,20 +28958,20 @@ JOIN::reoptimize(Item *added_where, table_map join_tables, void JOIN::cache_const_exprs() { - bool cache_flag= FALSE; - bool *analyzer_arg= &cache_flag; + uchar cache_flag= FALSE; + uchar *analyzer_arg= &cache_flag; /* No need in cache if all tables are constant. */ if (const_tables == table_count) return; if (conds) - conds->compile(thd, &Item::cache_const_expr_analyzer, (uchar **)&analyzer_arg, - &Item::cache_const_expr_transformer, (uchar *)&cache_flag); + conds->top_level_compile(thd, &Item::cache_const_expr_analyzer, &analyzer_arg, + &Item::cache_const_expr_transformer, &cache_flag); cache_flag= FALSE; if (having) - having->compile(thd, &Item::cache_const_expr_analyzer, (uchar **)&analyzer_arg, - &Item::cache_const_expr_transformer, (uchar *)&cache_flag); + having->top_level_compile(thd, &Item::cache_const_expr_analyzer, + &analyzer_arg, &Item::cache_const_expr_transformer, &cache_flag); for (JOIN_TAB *tab= first_depth_first_tab(this); tab; tab= next_depth_first_tab(this, tab)) @@ -28976,10 +28979,8 @@ void JOIN::cache_const_exprs() if (*tab->on_expr_ref) { cache_flag= FALSE; - (*tab->on_expr_ref)->compile(thd, &Item::cache_const_expr_analyzer, - (uchar **)&analyzer_arg, - &Item::cache_const_expr_transformer, - (uchar *)&cache_flag); + (*tab->on_expr_ref)->top_level_compile(thd, &Item::cache_const_expr_analyzer, + &analyzer_arg, &Item::cache_const_expr_transformer, &cache_flag); } } } diff --git a/sql/sql_select.h b/sql/sql_select.h index 3332bc78b6c..ba38cdade55 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -1866,15 +1866,10 @@ public: */ enum store_key_result copy(THD *thd) { - enum store_key_result result; enum_check_fields org_count_cuted_fields= thd->count_cuted_fields; - sql_mode_t org_sql_mode= thd->variables.sql_mode; - thd->variables.sql_mode&= ~(MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE); - thd->variables.sql_mode|= MODE_INVALID_DATES; - thd->count_cuted_fields= CHECK_FIELD_IGNORE; - result= copy_inner(); + Use_relaxed_field_copy urfc(to_field->table->in_use); + store_key_result result= copy_inner(); thd->count_cuted_fields= org_count_cuted_fields; - thd->variables.sql_mode= org_sql_mode; return result; } diff --git a/sql/sql_tvc.cc b/sql/sql_tvc.cc index e7372a13a2d..2a7802f077e 100644 --- a/sql/sql_tvc.cc +++ b/sql/sql_tvc.cc @@ -573,7 +573,7 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd, if (is_list_of_rows) { - Item_row *row_list= (Item_row *)(args[i]->build_clone(thd)); + Item_row *row_list= (Item_row *)(args[i]); if (!row_list) return true; @@ -598,8 +598,7 @@ bool Item_func_in::create_value_list_for_tvc(THD *thd, sprintf(col_name, "_col_%i", 1); args[i]->set_name(thd, col_name, strlen(col_name), thd->charset()); } - Item *arg_clone= args[i]->build_clone(thd); - if (!arg_clone || tvc_value->push_back(arg_clone)) + if (tvc_value->push_back(args[i])) return true; } diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 3361fa0df0b..691fe7d9189 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1244,7 +1244,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, size_t *yystacksize); TRANSACTION can be a non-empty history unit, or can be an identifier in bit_expr. - In the grammar below we use %prec to explicitely tell Bison to go + In the grammar below we use %prec to explicitly tell Bison to go through the empty branch in the optional rule only when the lookahead token does not belong to a small set of selected tokens. diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc index 720b7bcc2df..f844c8c6912 100644 --- a/sql/sys_vars.cc +++ b/sql/sys_vars.cc @@ -5847,7 +5847,7 @@ static bool update_wsrep_auto_increment_control (sys_var *self, THD *thd, enum_v { /* The variables that control auto increment shall be calculated - automaticaly based on the size of the cluster. This usually done + automatically based on the size of the cluster. This usually done within the wsrep_view_handler_cb callback. However, if the user manually sets the value of wsrep_auto_increment_control to 'ON', then we should to re-calculate these variables again (because diff --git a/sql/table.cc b/sql/table.cc index 5aa635259c3..345b51646d8 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -3656,7 +3656,7 @@ class Vcol_expr_context bool inited; THD *thd; TABLE *table; - Query_arena backup_arena; + Query_arena backup_arena, *stmt_arena; table_map old_map; Security_context *save_security_ctx; sql_mode_t save_sql_mode; @@ -3666,6 +3666,7 @@ public: inited(false), thd(_thd), table(_table), + stmt_arena(thd->stmt_arena), old_map(table->map), save_security_ctx(thd->security_ctx), save_sql_mode(thd->variables.sql_mode) {} @@ -3686,6 +3687,7 @@ bool Vcol_expr_context::init() thd->security_ctx= tl->security_ctx; thd->set_n_backup_active_arena(table->expr_arena, &backup_arena); + thd->stmt_arena= thd; inited= true; return false; @@ -3699,6 +3701,7 @@ Vcol_expr_context::~Vcol_expr_context() thd->security_ctx= save_security_ctx; thd->restore_active_arena(table->expr_arena, &backup_arena); thd->variables.sql_mode= save_sql_mode; + thd->stmt_arena= stmt_arena; } |