summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Petrunia <psergey@askmonty.org>2021-06-30 18:13:08 +0300
committerSergei Petrunia <psergey@askmonty.org>2021-06-30 18:41:46 +0300
commiteebe2090c848b5cedc5235473d80dbd2c25d2943 (patch)
treebd12d7d9809997b892437ef3b7341d330ee46147 /sql
parenta1e2ca057dda4dc434f057ce9391aa7afd9b5583 (diff)
parent4a6e2d343745c11086c05f0041a8267591bb073c (diff)
downloadmariadb-git-eebe2090c848b5cedc5235473d80dbd2c25d2943.tar.gz
Merge 10.3 -> 10.4
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.h2
-rw-r--r--sql/item_create.cc5
-rw-r--r--sql/lex.h7
-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.cc83
8 files changed, 174 insertions, 10 deletions
diff --git a/sql/handler.h b/sql/handler.h
index a179e084605..99aaac12402 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1008,6 +1008,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,
@@ -1024,6 +1025,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 ffc90e16b8f..d92aba03a4a 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -7147,7 +7147,6 @@ Create_func_year_week::create_native(THD *thd, LEX_CSTRING *name,
return func;
}
-
#define BUILDER(F) & F::s_singleton
#ifdef HAVE_SPATIAL
@@ -7167,7 +7166,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)},
@@ -7526,6 +7525,8 @@ static Native_func_registry func_array[] =
{ {0, 0}, NULL}
};
+size_t func_array_length= sizeof(func_array) / sizeof(Native_func_registry) - 1;
+
static HASH native_functions_hash;
extern "C" uchar*
diff --git a/sql/lex.h b/sql/lex.h
index 92ce01a1094..e35e109a3bf 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -45,7 +45,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
lists
*/
-static SYMBOL symbols[] = {
+SYMBOL symbols[] = {
{ "&&", SYM(AND_AND_SYM)},
{ "<=", SYM(LE)},
{ "<>", SYM(NE)},
@@ -731,7 +731,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)},
@@ -782,4 +782,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/spatial.cc b/sql/spatial.cc
index bda64c6d420..53e8c4c8bdd 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -539,7 +539,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)
@@ -556,6 +560,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 fc01dcdc750..a4e0fd6b683 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"
@@ -1359,6 +1359,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 93a4fcbe277..1ec5d0b0550 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"
@@ -9744,8 +9745,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(
@@ -9770,9 +9770,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 7b5b2c8bf89..1f8278528cf 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -66,6 +66,19 @@
#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 func_array[];
+extern size_t func_array_length;
+
enum enum_i_s_events_fields
{
ISE_EVENT_CATALOG= 0,
@@ -7941,6 +7954,60 @@ 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");
+
+ uint 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++){
+ const char *name= sql_functions[i].name;
+ if (add_symbol_to_table(name, table))
+ DBUG_RETURN(1);
+ }
+
+ for (uint i= 0; i < func_array_length; i++){
+ const char *name= func_array[i].name.str;
+ if (add_symbol_to_table(name, table))
+ DBUG_RETURN(1);
+ }
+
+ DBUG_RETURN(0);
+}
+
int fill_status(THD *thd, TABLE_LIST *tables, COND *cond)
{
@@ -9235,6 +9302,18 @@ ST_FIELD_INFO enabled_roles_fields_info[]=
{0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
};
+ST_FIELD_INFO keywords_field_info[]=
+{
+ {"WORD", KEYWORD_SIZE, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, SKIP_OPEN_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
+};
+
+ST_FIELD_INFO sql_functions_field_info[]=
+{
+ {"FUNCTION", KEYWORD_SIZE, MYSQL_TYPE_STRING, 0, MY_I_S_MAYBE_NULL, 0, SKIP_OPEN_TABLE},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0, SKIP_OPEN_TABLE}
+};
+
ST_FIELD_INFO engines_fields_info[]=
{
@@ -9942,6 +10021,8 @@ ST_SCHEMA_TABLE schema_tables[]=
fill_status, make_old_format, 0, 0, -1, 0, 0},
{"GLOBAL_VARIABLES", variables_fields_info, 0,
fill_variables, make_old_format, 0, 0, -1, 0, 0},
+ {"KEYWORDS", keywords_field_info, 0,
+ fill_i_s_keywords, 0, 0, -1, -1, 0, 0},
{"KEY_CACHES", keycache_fields_info, 0,
fill_key_cache_tables, 0, 0, -1,-1, 0, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, 0,
@@ -9979,6 +10060,8 @@ ST_SCHEMA_TABLE schema_tables[]=
{"STATISTICS", 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", sql_functions_field_info, 0,
+ fill_i_s_sql_functions, 0, 0, -1, -1, 0, 0},
{"SYSTEM_VARIABLES", sysvars_fields_info, 0,
fill_sysvars, make_old_format, 0, 0, -1, 0, 0},
{"TABLES", tables_fields_info, 0,