summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.h2
-rw-r--r--sql/item_create.cc3
-rw-r--r--sql/lex.h7
-rw-r--r--sql/mysqld.cc1
-rw-r--r--sql/spatial.cc6
-rw-r--r--sql/sql_derived.cc63
-rw-r--r--sql/sql_derived.h5
-rw-r--r--sql/sql_lex.cc13
-rw-r--r--sql/sql_show.cc82
-rw-r--r--sql/sql_table.cc10
-rw-r--r--sql/transaction.cc39
-rw-r--r--sql/wsrep_sst.cc5
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();