summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorMarko Mäkelä <marko.makela@mariadb.com>2023-01-13 11:22:29 +0200
committerMarko Mäkelä <marko.makela@mariadb.com>2023-01-13 11:22:29 +0200
commit5d5735c181f1300c7b208f865806268b16eec5c6 (patch)
treee18b411c66ad0128689a37af272046d7df8d18a0 /sql
parent820ebcec8651d2478ece554f059a5513f0b2bedf (diff)
parent88c35781cc9f5f3c63de98a8b6e7eb3378d4fae5 (diff)
downloadmariadb-git-5d5735c181f1300c7b208f865806268b16eec5c6.tar.gz
Merge 10.8 into 10.9
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc2
-rw-r--r--sql/field.h2
-rw-r--r--sql/item.cc104
-rw-r--r--sql/item.h111
-rw-r--r--sql/item_cmpfunc.cc62
-rw-r--r--sql/item_cmpfunc.h25
-rw-r--r--sql/item_create.cc1
-rw-r--r--sql/item_jsonfunc.cc33
-rw-r--r--sql/log_event_client.cc17
-rw-r--r--sql/mysqld.cc25
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/opt_range.h8
-rw-r--r--sql/signal_handler.cc4
-rw-r--r--sql/sp_head.cc4
-rw-r--r--sql/sql_cache.h2
-rw-r--r--sql/sql_class.h17
-rw-r--r--sql/sql_insert.cc13
-rw-r--r--sql/sql_join_cache.cc35
-rw-r--r--sql/sql_select.cc25
-rw-r--r--sql/sql_select.h9
-rw-r--r--sql/sql_tvc.cc5
-rw-r--r--sql/sql_yacc.yy2
-rw-r--r--sql/sys_vars.cc2
-rw-r--r--sql/table.cc5
24 files changed, 364 insertions, 151 deletions
diff --git a/sql/field.cc b/sql/field.cc
index c1ba05f5fad..fd8ffe3333c 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -11019,7 +11019,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 3d9c8406df1..05feb7a4275 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -5448,7 +5448,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 10a8127d06f..59be33cb77f 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;
}
@@ -7364,7 +7370,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();
@@ -7403,9 +7409,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;
@@ -10357,8 +10363,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;
}
@@ -10916,8 +10922,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;
@@ -10925,6 +10929,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 a0641ef4c76..7c440e76be1 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -2151,6 +2151,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)
@@ -6177,6 +6182,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;
@@ -7775,6 +7788,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 4f18d849461..8a1e6d9ffc3 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
@@ -5196,7 +5187,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());
@@ -5204,7 +5196,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;
@@ -5214,7 +5207,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);
@@ -5222,35 +5217,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.
@@ -5274,8 +5240,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;
@@ -5290,7 +5256,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 b5a09664cda..1422afb0fd0 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -3181,13 +3181,32 @@ public:
COND **conds);
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 7caa0123faf..1538bd6d0f2 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -5739,6 +5739,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_EQUALS") }, BUILDER(Create_func_json_equals)},
{ { STRING_WITH_LEN("JSON_EXISTS") }, BUILDER(Create_func_json_exists)},
{ { STRING_WITH_LEN("JSON_EXTRACT") }, BUILDER(Create_func_json_extract)},
diff --git a/sql/item_jsonfunc.cc b/sql/item_jsonfunc.cc
index aaee8a99294..2efb8e39439 100644
--- a/sql/item_jsonfunc.cc
+++ b/sql/item_jsonfunc.cc
@@ -285,6 +285,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);
@@ -311,6 +315,7 @@ static int json_nice(json_engine_t *je, String *nice_js,
do
{
+ curr_state= je->state;
switch (je->state)
{
case JST_KEY:
@@ -358,17 +363,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++;
}
@@ -377,11 +388,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 6d308ac6cd6..92adb98d8c7 100644
--- a/sql/log_event_client.cc
+++ b/sql/log_event_client.cc
@@ -840,10 +840,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;
@@ -851,7 +853,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;
@@ -859,7 +862,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;
@@ -867,7 +871,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;
@@ -879,10 +884,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 5f5b54a9163..2644ac3c896 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -133,6 +133,8 @@
#include <my_service_manager.h>
+#include <source_revision.h>
+
#define mysqld_charset &my_charset_latin1
@@ -4049,21 +4051,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
@@ -4917,6 +4904,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 9652e839862..05443ea78bf 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -10628,7 +10628,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 1f4d3f1cd1f..7a067b49295 100644
--- a/sql/opt_range.h
+++ b/sql/opt_range.h
@@ -955,7 +955,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
@@ -976,7 +976,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
@@ -993,7 +993,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
@@ -1014,7 +1014,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 a42cff49855..9991f261202 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 7e5ea9e6a96..b1a89998467 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -2407,7 +2407,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) &&
@@ -2421,7 +2421,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 422216133b0..97c4d36f505 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -6142,7 +6142,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();
@@ -6189,7 +6189,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; }
@@ -7624,6 +7624,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 a7fc7afb19f..379bc31a814 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -4148,7 +4148,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()))
@@ -4206,17 +4206,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);
}
@@ -4642,6 +4642,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
@@ -5025,10 +5026,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 caf9e429af5..aa5b5ea8e9d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -18718,7 +18718,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;
}
@@ -19599,8 +19600,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();
@@ -28985,20 +28988,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))
@@ -29006,10 +29009,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 e0fb0960b60..6d04fb89a6c 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 6e6d446ce16..d1c32e7d9d3 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 fc4b84553c3..a6cbf581c1a 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1241,7 +1241,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 5fb7ab4b26b..9149efc08c1 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -5893,7 +5893,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 d0b3d99c373..0bc06d47a71 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -3671,7 +3671,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;
@@ -3681,6 +3681,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) {}
@@ -3701,6 +3702,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;
@@ -3714,6 +3716,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;
}