diff options
Diffstat (limited to 'sql')
-rw-r--r-- | sql/handler.h | 2 | ||||
-rw-r--r-- | sql/item_create.cc | 3 | ||||
-rw-r--r-- | sql/lex.h | 7 | ||||
-rw-r--r-- | sql/mysqld.cc | 1 | ||||
-rw-r--r-- | sql/spatial.cc | 6 | ||||
-rw-r--r-- | sql/sql_derived.cc | 63 | ||||
-rw-r--r-- | sql/sql_derived.h | 5 | ||||
-rw-r--r-- | sql/sql_lex.cc | 13 | ||||
-rw-r--r-- | sql/sql_show.cc | 82 | ||||
-rw-r--r-- | sql/sql_table.cc | 10 | ||||
-rw-r--r-- | sql/transaction.cc | 39 | ||||
-rw-r--r-- | sql/wsrep_sst.cc | 5 |
12 files changed, 193 insertions, 43 deletions
diff --git a/sql/handler.h b/sql/handler.h index 4e98560a869..38c78e1961f 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -1037,6 +1037,7 @@ enum enum_schema_tables SCH_FILES, SCH_GLOBAL_STATUS, SCH_GLOBAL_VARIABLES, + SCH_KEYWORDS, SCH_KEY_CACHES, SCH_KEY_COLUMN_USAGE, SCH_OPEN_TABLES, @@ -1053,6 +1054,7 @@ enum enum_schema_tables SCH_SESSION_STATUS, SCH_SESSION_VARIABLES, SCH_STATISTICS, + SCH_SQL_FUNCTIONS, SCH_SYSTEM_VARIABLES, SCH_TABLES, SCH_TABLESPACES, diff --git a/sql/item_create.cc b/sql/item_create.cc index 6ac08813be8..8850688f33b 100644 --- a/sql/item_create.cc +++ b/sql/item_create.cc @@ -5390,7 +5390,6 @@ Create_func_year_week::create_native(THD *thd, LEX_CSTRING *name, return func; } - #define BUILDER(F) & F::s_singleton /* @@ -5404,7 +5403,7 @@ Create_func_year_week::create_native(THD *thd, LEX_CSTRING *name, - keep 1 line per entry, it makes grep | sort easier */ -static Native_func_registry func_array[] = +Native_func_registry func_array[] = { { { STRING_WITH_LEN("ABS") }, BUILDER(Create_func_abs)}, { { STRING_WITH_LEN("ACOS") }, BUILDER(Create_func_acos)}, diff --git a/sql/lex.h b/sql/lex.h index 542356c0e43..e344b32ae83 100644 --- a/sql/lex.h +++ b/sql/lex.h @@ -48,7 +48,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"}; the perfschema.start_server_low_digest_sql_length test! */ -static SYMBOL symbols[] = { +SYMBOL symbols[] = { { "&&", SYM(AND_AND_SYM)}, { "<=", SYM(LE)}, { "<>", SYM(NE)}, @@ -735,7 +735,7 @@ static SYMBOL symbols[] = { }; -static SYMBOL sql_functions[] = { +SYMBOL sql_functions[] = { { "ADDDATE", SYM(ADDDATE_SYM)}, { "BIT_AND", SYM(BIT_AND)}, { "BIT_OR", SYM(BIT_OR)}, @@ -788,4 +788,7 @@ static SYMBOL sql_functions[] = { { "VAR_SAMP", SYM(VAR_SAMP_SYM)}, }; +size_t symbols_length= sizeof(symbols) / sizeof(SYMBOL); +size_t sql_functions_length= sizeof(sql_functions) / sizeof(SYMBOL); + #endif /* LEX_INCLUDED */ diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 3a164d68574..cb87cb737c3 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1889,6 +1889,7 @@ static void mysqld_exit(int exit_code) wait_for_signal_thread_to_end(); #ifdef WITH_WSREP wsrep_deinit_server(); + wsrep_sst_auth_free(); #endif /* WITH_WSREP */ mysql_audit_finalize(); clean_up_mutexes(); diff --git a/sql/spatial.cc b/sql/spatial.cc index 13fff34df21..a06c7652267 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -565,7 +565,11 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, goto handle_geometry_key; feature_type_found= 1; } + else /* can't understand the type. */ + break; } + else /* The "type" value can only be string. */ + break; } else if (key_len == coord_keyname_len && memcmp(key_buf, coord_keyname, coord_keyname_len) == 0) @@ -582,6 +586,8 @@ Geometry *Geometry::create_from_json(Geometry_buffer *buffer, coord_start= je->value_begin; if (ci && ci != &geometrycollection_class) goto create_geom; + if (json_skip_level(je)) + goto err_return; } } else if (key_len == geometries_keyname_len && diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc index ed3743b029b..f8ee3475af8 100644 --- a/sql/sql_derived.cc +++ b/sql/sql_derived.cc @@ -25,13 +25,13 @@ #include "mariadb.h" /* NO_EMBEDDED_ACCESS_CHECKS */ #include "sql_priv.h" #include "unireg.h" -#include "sql_derived.h" #include "sql_select.h" #include "derived_handler.h" #include "sql_base.h" #include "sql_view.h" // check_duplicate_names #include "sql_acl.h" // SELECT_ACL #include "sql_class.h" +#include "sql_derived.h" #include "sql_cte.h" #include "my_json_writer.h" #include "opt_trace.h" @@ -1358,6 +1358,67 @@ bool mysql_derived_reinit(THD *thd, LEX *lex, TABLE_LIST *derived) } +/* + @brief + Given condition cond and transformer+argument, try transforming as many + conjuncts as possible. + + @detail + The motivation of this function is to convert the condition that's being + pushed into a WHERE clause with derived_field_transformer_for_where or + with derived_grouping_field_transformer_for_where. + The transformer may fail for some sub-condition, in this case we want to + convert the most restrictive part of the condition that can be pushed. + + This function only does it for top-level AND: conjuncts that could not be + converted are dropped. + + @return + Converted condition, or NULL if nothing could be converted +*/ + +Item *transform_condition_or_part(THD *thd, + Item *cond, + Item_transformer transformer, + uchar *arg) +{ + if (cond->type() != Item::COND_ITEM || + ((Item_cond*) cond)->functype() != Item_func::COND_AND_FUNC) + { + Item *new_item= cond->transform(thd, transformer, arg); + // Indicate that the condition is not pushable + if (!new_item) + cond->clear_extraction_flag(); + return new_item; + } + + List_iterator<Item> li(*((Item_cond*) cond)->argument_list()); + Item *item; + while ((item=li++)) + { + Item *new_item= item->transform(thd, transformer, arg); + if (!new_item) + { + // Indicate that the condition is not pushable + item->clear_extraction_flag(); + li.remove(); + } + else + li.replace(new_item); + } + + switch (((Item_cond*) cond)->argument_list()->elements) + { + case 0: + return NULL; + case 1: + return ((Item_cond*) cond)->argument_list()->head(); + default: + return cond; + } +} + + /** @brief Extract condition that can be pushed into a derived table/view diff --git a/sql/sql_derived.h b/sql/sql_derived.h index 403277d65c9..6100b4b4d7e 100644 --- a/sql/sql_derived.h +++ b/sql/sql_derived.h @@ -23,6 +23,11 @@ struct LEX; bool mysql_handle_derived(LEX *lex, uint phases); bool mysql_handle_single_derived(LEX *lex, TABLE_LIST *derived, uint phases); +Item *transform_condition_or_part(THD *thd, + Item *cond, + Item_transformer transformer, + uchar *arg); + bool pushdown_cond_for_derived(THD *thd, Item *cond, TABLE_LIST *derived); #endif /* SQL_DERIVED_INCLUDED */ diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 27088df3417..5784c10a29c 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -31,6 +31,7 @@ #include "sql_select.h" #include "sql_cte.h" #include "sql_signal.h" +#include "sql_derived.h" #include "sql_truncate.h" // Sql_cmd_truncate_table #include "sql_admin.h" // Sql_cmd_analyze/Check..._table #include "sql_partition.h" @@ -10437,8 +10438,7 @@ void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond, if (!join->group_list && !with_sum_func) { - cond= - cond->transform(thd, transformer, arg); + cond= transform_condition_or_part(thd, cond, transformer, arg); if (cond) { cond->walk( @@ -10463,9 +10463,12 @@ void st_select_lex::pushdown_cond_into_where_clause(THD *thd, Item *cond, into WHERE so it can be pushed. */ if (cond_over_grouping_fields) - cond_over_grouping_fields= cond_over_grouping_fields->transform(thd, - &Item::grouping_field_transformer_for_where, - (uchar*) this); + { + cond_over_grouping_fields= + transform_condition_or_part(thd, cond_over_grouping_fields, + &Item::grouping_field_transformer_for_where, + (uchar*) this); + } if (cond_over_grouping_fields) { diff --git a/sql/sql_show.cc b/sql/sql_show.cc index ab62a56b166..f9546b79e6f 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2015, Oracle and/or its affiliates. - Copyright (c) 2009, 2020, MariaDB + Copyright (c) 2009, 2021, MariaDB This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -66,6 +66,18 @@ #include "opt_trace.h" #include "my_cpu.h" + +#include "lex_symbol.h" +#define KEYWORD_SIZE 64 + +extern SYMBOL symbols[]; +extern size_t symbols_length; + +extern SYMBOL sql_functions[]; +extern size_t sql_functions_length; + +extern Native_func_registry_array native_func_registry_array; + enum enum_i_s_events_fields { ISE_EVENT_CATALOG= 0, @@ -7837,6 +7849,58 @@ int fill_variables(THD *thd, TABLE_LIST *tables, COND *cond) DBUG_RETURN(res); } +int add_symbol_to_table(const char* name, TABLE* table){ + DBUG_ENTER("add_symbol_to_table"); + + size_t length= strlen(name); + + // If you've added a new SQL keyword longer than KEYWORD_SIZE, + // please increase the defined max length + DBUG_ASSERT(length < KEYWORD_SIZE); + + restore_record(table, s->default_values); + table->field[0]->set_notnull(); + table->field[0]->store(name, length, + system_charset_info); + if (schema_table_store_record(table->in_use, table)) + DBUG_RETURN(1); + + DBUG_RETURN(0); +} + +int fill_i_s_keywords(THD *thd, TABLE_LIST *tables, COND *cond) +{ + DBUG_ENTER("fill_i_s_keywords"); + + TABLE *table= tables->table; + + for (uint i= 0; i < symbols_length; i++){ + const char *name= symbols[i].name; + if (add_symbol_to_table(name, table)) + DBUG_RETURN(1); + } + + DBUG_RETURN(0); +} + +int fill_i_s_sql_functions(THD *thd, TABLE_LIST *tables, COND *cond) +{ + DBUG_ENTER("fill_i_s_sql_functions"); + + TABLE *table= tables->table; + + for (uint i= 0; i < sql_functions_length; i++) + if (add_symbol_to_table(sql_functions[i].name, table)) + DBUG_RETURN(1); + + for (uint i= 0; i < native_func_registry_array.count(); i++) + if (add_symbol_to_table(native_func_registry_array.element(i).name.str, + table)) + DBUG_RETURN(1); + + DBUG_RETURN(0); +} + int fill_status(THD *thd, TABLE_LIST *tables, COND *cond) { @@ -8988,6 +9052,18 @@ ST_FIELD_INFO enabled_roles_fields_info[]= CEnd() }; +ST_FIELD_INFO keywords_field_info[]= +{ + Column("WORD", Varchar(KEYWORD_SIZE), NULLABLE), + CEnd() +}; + +ST_FIELD_INFO sql_functions_field_info[]= +{ + Column("FUNCTION", Varchar(KEYWORD_SIZE), NULLABLE), + CEnd() +}; + ST_FIELD_INFO engines_fields_info[]= { @@ -9566,6 +9642,8 @@ ST_SCHEMA_TABLE schema_tables[]= fill_status, make_old_format, 0, 0, -1, 0, 0}, {"GLOBAL_VARIABLES", Show::variables_fields_info, 0, fill_variables, make_old_format, 0, 0, -1, 0, 0}, + {"KEYWORDS", Show::keywords_field_info, 0, + fill_i_s_keywords, 0, 0, -1, -1, 0, 0}, {"KEY_CACHES", Show::keycache_fields_info, 0, fill_key_cache_tables, 0, 0, -1,-1, 0, 0}, {"KEY_COLUMN_USAGE", Show::key_column_usage_fields_info, 0, @@ -9603,6 +9681,8 @@ ST_SCHEMA_TABLE schema_tables[]= {"STATISTICS", Show::stat_fields_info, 0, get_all_tables, make_old_format, get_schema_stat_record, 1, 2, 0, OPEN_TABLE_ONLY|OPTIMIZE_I_S_TABLE}, + {"SQL_FUNCTIONS", Show::sql_functions_field_info, 0, + fill_i_s_sql_functions, 0, 0, -1, -1, 0, 0}, {"SYSTEM_VARIABLES", Show::sysvars_fields_info, 0, fill_sysvars, make_old_format, 0, 0, -1, 0, 0}, {"TABLES", Show::tables_fields_info, 0, diff --git a/sql/sql_table.cc b/sql/sql_table.cc index f58ce8f997d..b182401e3db 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -10681,9 +10681,13 @@ do_continue:; if (alter_info->requested_lock == Alter_info::ALTER_TABLE_LOCK_NONE) ha_alter_info.online= true; // Ask storage engine whether to use copy or in-place - ha_alter_info.inplace_supported= - table->file->check_if_supported_inplace_alter(&altered_table, - &ha_alter_info); + { + Check_level_instant_set check_level_save(thd, CHECK_FIELD_WARN); + ha_alter_info.inplace_supported= + table->file->check_if_supported_inplace_alter(&altered_table, + &ha_alter_info); + } + if (ha_alter_info.inplace_supported != HA_ALTER_INPLACE_NOT_SUPPORTED) { List_iterator<Key> it(alter_info->key_list); diff --git a/sql/transaction.cc b/sql/transaction.cc index 8bd58419ec9..958abebfc47 100644 --- a/sql/transaction.cc +++ b/sql/transaction.cc @@ -1,5 +1,5 @@ /* Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. - Copyright (c) 2009, 2020, MariaDB Corporation. + Copyright (c) 2009, 2021, MariaDB Corporation. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -667,33 +667,6 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name) if (thd->transaction->xid_state.check_has_uncommitted_xa()) DBUG_RETURN(TRUE); - /** - Checking whether it is safe to release metadata locks acquired after - savepoint, if rollback to savepoint is successful. - - Whether it is safe to release MDL after rollback to savepoint depends - on storage engines participating in transaction: - - - InnoDB doesn't release any row-locks on rollback to savepoint so it - is probably a bad idea to release MDL as well. - - Binary log implementation in some cases (e.g when non-transactional - tables involved) may choose not to remove events added after savepoint - from transactional cache, but instead will write them to binary - log accompanied with ROLLBACK TO SAVEPOINT statement. Since the real - write happens at the end of transaction releasing MDL on tables - mentioned in these events (i.e. acquired after savepoint and before - rollback ot it) can break replication, as concurrent DROP TABLES - statements will be able to drop these tables before events will get - into binary log, - - For backward-compatibility reasons we always release MDL if binary - logging is off. - */ - bool mdl_can_safely_rollback_to_savepoint= - (!((WSREP_EMULATE_BINLOG_NNULL(thd) || mysql_bin_log.is_open()) - && thd->variables.sql_log_bin) || - ha_rollback_to_savepoint_can_release_mdl(thd)); - if (ha_rollback_to_savepoint(thd, sv)) res= TRUE; else if (((thd->variables.option_bits & OPTION_KEEP_LOG) || @@ -705,7 +678,15 @@ bool trans_rollback_to_savepoint(THD *thd, LEX_CSTRING name) thd->transaction->savepoints= sv; - if (!res && mdl_can_safely_rollback_to_savepoint) + if (res) + /* An error occurred during rollback; we cannot release any MDL */; + else if (thd->variables.sql_log_bin && + (WSREP_EMULATE_BINLOG_NNULL(thd) || mysql_bin_log.is_open())) + /* In some cases (such as with non-transactional tables) we may + choose to preserve events that were added after the SAVEPOINT, + delimiting them by SAVEPOINT and ROLLBACK TO SAVEPOINT statements. + Prematurely releasing MDL on such objects would break replication. */; + else if (ha_rollback_to_savepoint_can_release_mdl(thd)) thd->mdl_context.rollback_to_savepoint(sv->mdl_savepoint); DBUG_RETURN(MY_TEST(res)); diff --git a/sql/wsrep_sst.cc b/sql/wsrep_sst.cc index 32ea506f5ea..862a446c70f 100644 --- a/sql/wsrep_sst.cc +++ b/sql/wsrep_sst.cc @@ -1055,6 +1055,8 @@ static ssize_t sst_prepare_other (const char* method, { WSREP_ERROR("sst_prepare_other(): generate_binlog_index_opt_val() failed %d", ret); + if (binlog_opt_val) my_free(binlog_opt_val); + return ret; } make_wsrep_defaults_file(); @@ -1072,6 +1074,7 @@ static ssize_t sst_prepare_other (const char* method, wsrep_defaults_file, (int)getpid(), binlog_opt_val, binlog_index_opt_val); + my_free(binlog_opt_val); my_free(binlog_index_opt_val); @@ -1798,6 +1801,8 @@ static int sst_donate_other (const char* method, { WSREP_ERROR("sst_prepare_other(): generate_binlog_index_opt_val() failed %d", ret); + if (binlog_opt_val) my_free(binlog_opt_val); + return ret; } make_wsrep_defaults_file(); |