summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/opt_subselect.cc4
-rw-r--r--sql/sql_partition.cc40
-rw-r--r--sql/sql_plugin.cc20
-rw-r--r--sql/sql_priv.h2
-rw-r--r--sql/sql_select.cc75
-rw-r--r--sql/sql_select.h8
6 files changed, 111 insertions, 38 deletions
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 03204a627ed..cc63efa7d8c 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -3433,6 +3433,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
table_map remaining_tables= 0;
table_map handled_tabs= 0;
join->sjm_lookup_tables= 0;
+ join->sjm_scan_tables= 0;
for (tablenr= table_count - 1 ; tablenr != join->const_tables - 1; tablenr--)
{
POSITION *pos= join->best_positions + tablenr;
@@ -3491,6 +3492,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
for (i= tablenr; i != (first + sjm->tables - 1); i--)
rem_tables |= join->best_positions[i].table->table->map;
+ for (i= first; i < first+ sjm->tables; i++)
+ join->sjm_scan_tables |= join->best_positions[i].table->table->map;
+
POSITION dummy;
join->cur_sj_inner_tables= 0;
for (i= first + sjm->tables; i <= tablenr; i++)
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index be7824aae9e..5446db41a72 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -1870,6 +1870,22 @@ static int add_subpartition_by(File fptr)
return err + add_partition_by(fptr);
}
+static int add_name_string(File fptr, const char *name)
+{
+ int err;
+ String name_string("", 0, system_charset_info);
+ THD *thd= current_thd;
+ ulonglong save_sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode&= ~MODE_ANSI_QUOTES;
+ ulonglong save_options= thd->variables.option_bits;
+ thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE;
+ append_identifier(thd, &name_string, name, strlen(name));
+ thd->variables.sql_mode= save_sql_mode;
+ thd->variables.option_bits= save_options;
+ err= add_string_object(fptr, &name_string);
+ return err;
+}
+
static int add_part_field_list(File fptr, List<char> field_list)
{
uint i, num_fields;
@@ -1881,15 +1897,7 @@ static int add_part_field_list(File fptr, List<char> field_list)
err+= add_begin_parenthesis(fptr);
while (i < num_fields)
{
- const char *field_str= part_it++;
- String field_string("", 0, system_charset_info);
- THD *thd= current_thd;
- ulonglong save_options= thd->variables.option_bits;
- thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE;
- append_identifier(thd, &field_string, field_str,
- strlen(field_str));
- thd->variables.option_bits= save_options;
- err+= add_string_object(fptr, &field_string);
+ err+= add_name_string(fptr, part_it++);
if (i != (num_fields-1))
err+= add_comma(fptr);
i++;
@@ -1898,20 +1906,6 @@ static int add_part_field_list(File fptr, List<char> field_list)
return err;
}
-static int add_name_string(File fptr, const char *name)
-{
- int err;
- String name_string("", 0, system_charset_info);
- THD *thd= current_thd;
- ulonglong save_options= thd->variables.option_bits;
- thd->variables.option_bits&= ~OPTION_QUOTE_SHOW_CREATE;
- append_identifier(thd, &name_string, name,
- strlen(name));
- thd->variables.option_bits= save_options;
- err= add_string_object(fptr, &name_string);
- return err;
-}
-
static int add_int(File fptr, longlong number)
{
char buff[32];
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index 63c3933db93..e34409b3532 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -306,6 +306,12 @@ static plugin_ref intern_plugin_lock(LEX *lex, plugin_ref plugin);
static void intern_plugin_unlock(LEX *lex, plugin_ref plugin);
static void reap_plugins(void);
+bool plugin_is_forced(struct st_plugin_int *p)
+{
+ return p->load_option == PLUGIN_FORCE ||
+ p->load_option == PLUGIN_FORCE_PLUS_PERMANENT;
+}
+
static void report_error(int where_to, uint error, ...)
{
va_list args;
@@ -1360,7 +1366,7 @@ static int plugin_initialize(MEM_ROOT *tmp_root, struct st_plugin_int *plugin,
if (options_only || state == PLUGIN_IS_DISABLED)
{
- ret= 0;
+ ret= !options_only && plugin_is_forced(plugin);
goto err;
}
@@ -1671,8 +1677,7 @@ int plugin_init(int *argc, char **argv, int flags)
while ((plugin_ptr= *(--reap)))
{
mysql_mutex_unlock(&LOCK_plugin);
- if (plugin_ptr->load_option == PLUGIN_FORCE ||
- plugin_ptr->load_option == PLUGIN_FORCE_PLUS_PERMANENT)
+ if (plugin_is_forced(plugin_ptr))
reaped_mandatory_plugin= TRUE;
plugin_deinitialize(plugin_ptr, true);
mysql_mutex_lock(&LOCK_plugin);
@@ -3536,8 +3541,7 @@ static int construct_options(MEM_ROOT *mem_root, struct st_plugin_int *tmp,
plugin_dash.length + 1);
strxmov(plugin_name_with_prefix_ptr, plugin_dash.str, plugin_name_ptr, NullS);
- if (tmp->load_option != PLUGIN_FORCE &&
- tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT)
+ if (!plugin_is_forced(tmp))
{
/* support --skip-plugin-foo syntax */
options[0].name= plugin_name_ptr;
@@ -3855,8 +3859,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
We adjust the default value to account for the hardcoded exceptions
we have set for the federated and ndbcluster storage engines.
*/
- if (tmp->load_option != PLUGIN_FORCE &&
- tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT)
+ if (!plugin_is_forced(tmp))
opts[0].def_value= opts[1].def_value= plugin_load_option;
error= handle_options(argc, &argv, opts, NULL);
@@ -3872,8 +3875,7 @@ static int test_plugin_options(MEM_ROOT *tmp_root, struct st_plugin_int *tmp,
Set plugin loading policy from option value. First element in the option
list is always the <plugin name> option value.
*/
- if (tmp->load_option != PLUGIN_FORCE &&
- tmp->load_option != PLUGIN_FORCE_PLUS_PERMANENT)
+ if (!plugin_is_forced(tmp))
plugin_load_option= (enum_plugin_load_option) *(ulong*) opts[0].value;
}
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 09a22ba0444..2c9a22d4bd9 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -121,7 +121,7 @@
#define OPTION_AUTOCOMMIT (1ULL << 8) // THD, user
#define OPTION_BIG_SELECTS (1ULL << 9) // THD, user
#define OPTION_LOG_OFF (1ULL << 10) // THD, user
-#define OPTION_QUOTE_SHOW_CREATE (1ULL << 11) // THD, user, unused
+#define OPTION_QUOTE_SHOW_CREATE (1ULL << 11) // THD, user
#define TMP_TABLE_ALL_COLUMNS (1ULL << 12) // SELECT, intern
#define OPTION_WARNINGS (1ULL << 13) // THD, user
#define OPTION_AUTO_IS_NULL (1ULL << 14) // THD, user, binlog
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 6a281a4583e..7be9bfb7838 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1305,6 +1305,7 @@ TODO: make view to decide if it is possible to write to WHERE directly or make S
DBUG_PRINT("info",("Select tables optimized away"));
zero_result_cause= "Select tables optimized away";
tables_list= 0; // All tables resolved
+ select_lex->min_max_opt_list.empty();
const_tables= top_join_tab_count= table_count;
/*
Extract all table-independent conditions and replace the WHERE
@@ -2942,8 +2943,11 @@ void JOIN::exec_inner()
if (sort_table_cond)
{
if (!curr_table->select)
+ {
if (!(curr_table->select= new SQL_SELECT))
DBUG_VOID_RETURN;
+ curr_table->select->head= curr_table->table;
+ }
if (!curr_table->select->cond)
curr_table->select->cond= sort_table_cond;
else
@@ -8076,6 +8080,63 @@ bool JOIN_TAB::hash_join_is_possible()
}
+/**
+ @brief
+ Check whether a KEYUSE can be really used for access this join table
+
+ @param join Join structure with the best join order
+ for which the check is performed
+ @param keyuse Evaluated KEYUSE structure
+
+ @details
+ This function is supposed to be used after the best execution plan have been
+ already chosen and the JOIN_TAB array for the best join order been already set.
+ For a given KEYUSE to access this JOIN_TAB in the best execution plan the
+ function checks whether it really can be used. The function first performs
+ the check with access_from_tables_is_allowed(). If it succeeds it checks
+ whether the keyuse->val does not use some fields of a materialized semijoin
+ nest that cannot be used to build keys to access outer tables.
+ Such KEYUSEs exists for the query like this:
+ select * from ot
+ where ot.c in (select it1.c from it1, it2 where it1.c=f(it2.c))
+ Here we have two KEYUSEs to access table ot: with val=it1.c and val=f(it2.c).
+ However if the subquery was materialized the second KEYUSE cannot be employed
+ to access ot.
+
+ @retval true the given keyuse can be used for ref access of this JOIN_TAB
+ @retval false otherwise
+*/
+
+bool JOIN_TAB::keyuse_is_valid_for_access_in_chosen_plan(JOIN *join,
+ KEYUSE *keyuse)
+{
+ if (!access_from_tables_is_allowed(keyuse->used_tables,
+ join->sjm_lookup_tables))
+ return false;
+ if (join->sjm_scan_tables & table->map)
+ return true;
+ table_map keyuse_sjm_scan_tables= keyuse->used_tables &
+ join->sjm_scan_tables;
+ if (!keyuse_sjm_scan_tables)
+ return true;
+ uint sjm_tab_nr= 0;
+ while (!(keyuse_sjm_scan_tables & table_map(1) << sjm_tab_nr))
+ sjm_tab_nr++;
+ JOIN_TAB *sjm_tab= join->map2table[sjm_tab_nr];
+ TABLE_LIST *emb_sj_nest= sjm_tab->emb_sj_nest;
+ if (!(emb_sj_nest->sj_mat_info && emb_sj_nest->sj_mat_info->is_used &&
+ emb_sj_nest->sj_mat_info->is_sj_scan))
+ return true;
+ st_select_lex *sjm_sel= emb_sj_nest->sj_subq_pred->unit->first_select();
+ for (uint i= 0; i < sjm_sel->item_list.elements; i++)
+ {
+ if (sjm_sel->ref_pointer_array[i] == keyuse->val)
+ return true;
+ }
+ return false;
+}
+
+
static uint
cache_record_length(JOIN *join,uint idx)
{
@@ -8623,6 +8684,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
do
{
if (!(~used_tables & keyuse->used_tables) &&
+ join_tab->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse) &&
are_tables_local(join_tab, keyuse->used_tables))
{
if (first_keyuse)
@@ -8637,6 +8699,8 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
{
if (curr->keypart == keyuse->keypart &&
!(~used_tables & curr->used_tables) &&
+ join_tab->keyuse_is_valid_for_access_in_chosen_plan(join,
+ keyuse) &&
are_tables_local(join_tab, curr->used_tables))
break;
}
@@ -8671,6 +8735,7 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
do
{
if (!(~used_tables & keyuse->used_tables) &&
+ join_tab->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse) &&
are_tables_local(join_tab, keyuse->used_tables))
{
bool add_key_part= TRUE;
@@ -8680,7 +8745,9 @@ static bool create_hj_key_for_table(JOIN *join, JOIN_TAB *join_tab,
{
if (curr->keypart == keyuse->keypart &&
!(~used_tables & curr->used_tables) &&
- are_tables_local(join_tab, curr->used_tables))
+ join_tab->keyuse_is_valid_for_access_in_chosen_plan(join,
+ curr) &&
+ are_tables_local(join_tab, curr->used_tables))
{
keyuse->keypart= NO_KEYPART;
add_key_part= FALSE;
@@ -8782,8 +8849,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
do
{
if (!(~used_tables & keyuse->used_tables) &&
- j->access_from_tables_is_allowed(keyuse->used_tables,
- join->sjm_lookup_tables))
+ j->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse))
{
if (are_tables_local(j, keyuse->val->used_tables()))
{
@@ -8853,8 +8919,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j,
for (i=0 ; i < keyparts ; keyuse++,i++)
{
while (((~used_tables) & keyuse->used_tables) ||
- !j->access_from_tables_is_allowed(keyuse->used_tables,
- join->sjm_lookup_tables) ||
+ !j->keyuse_is_valid_for_access_in_chosen_plan(join, keyuse) ||
keyuse->keypart == NO_KEYPART ||
(keyuse->keypart !=
(is_hash_join_key_no(key) ?
diff --git a/sql/sql_select.h b/sql/sql_select.h
index d51bca785a5..4f1b7bd7e05 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -534,6 +534,8 @@ typedef struct st_join_table {
!(used_sjm_lookup_tables & ~emb_sj_nest->sj_inner_tables));
}
+ bool keyuse_is_valid_for_access_in_chosen_plan(JOIN *join, KEYUSE *keyuse);
+
void remove_redundant_bnl_scan_conds();
} JOIN_TAB;
@@ -1000,6 +1002,11 @@ public:
to materialize and access by lookups
*/
table_map sjm_lookup_tables;
+ /**
+ Bitmap of semijoin tables that the chosen plan decided
+ to materialize to scan the results of materialization
+ */
+ table_map sjm_scan_tables;
/*
Constant tables for which we have found a row (as opposed to those for
which we didn't).
@@ -1341,6 +1348,7 @@ public:
pre_sort_join_tab= NULL;
emb_sjm_nest= NULL;
sjm_lookup_tables= 0;
+ sjm_scan_tables= 0;
exec_saved_explain= false;
/*