summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/field.cc16
-rw-r--r--sql/field.h1
-rw-r--r--sql/opt_range.cc24
-rw-r--r--sql/opt_subselect.cc26
-rw-r--r--sql/opt_subselect.h8
-rw-r--r--sql/sql_parse.cc1
-rw-r--r--sql/sql_select.cc52
-rw-r--r--sql/sql_select.h8
-rw-r--r--sql/sql_statistics.cc9
-rw-r--r--sql/sql_yacc.yy2
-rw-r--r--sql/sql_yacc_ora.yy2
11 files changed, 96 insertions, 53 deletions
diff --git a/sql/field.cc b/sql/field.cc
index 14d78433503..99cda09f2bb 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1,6 +1,6 @@
/*
Copyright (c) 2000, 2017, Oracle and/or its affiliates.
- Copyright (c) 2008, 2017, MariaDB
+ Copyright (c) 2008, 2019, 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
@@ -2405,29 +2405,19 @@ Field *Field::clone(MEM_ROOT *root, TABLE *new_table)
}
-
Field *Field::clone(MEM_ROOT *root, TABLE *new_table, my_ptrdiff_t diff)
{
Field *tmp;
if ((tmp= (Field*) memdup_root(root,(char*) this,size_of())))
{
- tmp->init(new_table);
+ if (new_table)
+ tmp->init(new_table);
tmp->move_field_offset(diff);
}
return tmp;
}
-Field *Field::clone(MEM_ROOT *root, my_ptrdiff_t diff)
-{
- Field *tmp;
- if ((tmp= (Field*) memdup_root(root,(char*) this,size_of())))
- {
- tmp->move_field_offset(diff);
- }
- return tmp;
-}
-
int Field::set_default()
{
if (default_value)
diff --git a/sql/field.h b/sql/field.h
index 053236133d0..35f531ac4ab 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -1254,7 +1254,6 @@ public:
uchar *new_null_ptr, uint new_null_bit);
Field *clone(MEM_ROOT *mem_root, TABLE *new_table);
Field *clone(MEM_ROOT *mem_root, TABLE *new_table, my_ptrdiff_t diff);
- Field *clone(MEM_ROOT *mem_root, my_ptrdiff_t diff);
inline void move_field(uchar *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 57bd244e738..32e6a767f15 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -2414,12 +2414,16 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
records= head->stat_records();
if (!records)
records++; /* purecov: inspected */
- scan_time= (double) records / TIME_FOR_COMPARE + 1;
- read_time= (double) head->file->scan_time() + scan_time + 1.1;
- if (head->force_index)
+
+ if (head->force_index || force_quick_range)
scan_time= read_time= DBL_MAX;
- if (limit < records)
- read_time= (double) records + scan_time + 1; // Force to use index
+ else
+ {
+ scan_time= (double) records / TIME_FOR_COMPARE + 1;
+ read_time= (double) head->file->scan_time() + scan_time + 1.1;
+ if (limit < records)
+ read_time= (double) records + scan_time + 1; // Force to use index
+ }
possible_keys.clear_all();
@@ -10413,6 +10417,16 @@ ha_rows check_quick_select(PARAM *param, uint idx, bool index_only,
bufsize, mrr_flags, cost);
if (rows != HA_POS_ERROR)
{
+ ha_rows table_records= param->table->stat_records();
+ if (rows > table_records)
+ {
+ /*
+ For any index the total number of records within all ranges
+ cannot be be bigger than the number of records in the table
+ */
+ rows= table_records;
+ set_if_bigger(rows, 1);
+ }
param->quick_rows[keynr]= rows;
param->possible_keys.set_bit(keynr);
if (update_tbl_stats)
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 6dd7de63612..7eeba821a47 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -452,11 +452,6 @@ bool find_eq_ref_candidate(TABLE *table, table_map sj_inner_tables);
static SJ_MATERIALIZATION_INFO *
at_sjmat_pos(const JOIN *join, table_map remaining_tables, const JOIN_TAB *tab,
uint idx, bool *loose_scan);
-void best_access_path(JOIN *join, JOIN_TAB *s,
- table_map remaining_tables, uint idx,
- bool disable_jbuf, double record_count,
- POSITION *pos, POSITION *loose_scan_pos);
-
static Item *create_subq_in_equalities(THD *thd, SJ_MATERIALIZATION_INFO *sjm,
Item_in_subselect *subq_pred);
static bool remove_sj_conds(THD *thd, Item **tree);
@@ -2718,6 +2713,13 @@ void advance_sj_state(JOIN *join, table_map remaining_tables, uint idx,
NULL,
};
+#ifdef HAVE_valgrind
+ new (&pos->firstmatch_picker) Firstmatch_picker;
+ new (&pos->loosescan_picker) LooseScan_picker;
+ new (&pos->sjmat_picker) Sj_materialization_picker;
+ new (&pos->dups_weedout_picker) Duplicate_weedout_picker;
+#endif
+
if (join->emb_sjm_nest)
{
/*
@@ -3007,7 +3009,8 @@ bool Sj_materialization_picker::check_qep(JOIN *join,
bool disable_jbuf= (join->thd->variables.join_cache_level == 0);
for (i= first_tab + mat_info->tables; i <= idx; i++)
{
- best_access_path(join, join->positions[i].table, rem_tables, i,
+ best_access_path(join, join->positions[i].table, rem_tables,
+ join->positions, i,
disable_jbuf, prefix_rec_count, &curpos, &dummy);
prefix_rec_count= COST_MULT(prefix_rec_count, curpos.records_read);
prefix_cost= COST_ADD(prefix_cost, curpos.read_time);
@@ -3626,7 +3629,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
join->cur_sj_inner_tables= 0;
for (i= first + sjm->tables; i <= tablenr; i++)
{
- best_access_path(join, join->best_positions[i].table, rem_tables, i,
+ best_access_path(join, join->best_positions[i].table, rem_tables,
+ join->best_positions, i,
FALSE, prefix_rec_count,
join->best_positions + i, &dummy);
prefix_rec_count *= join->best_positions[i].records_read;
@@ -3658,8 +3662,9 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
{
if (join->best_positions[idx].use_join_buffer)
{
- best_access_path(join, join->best_positions[idx].table,
- rem_tables, idx, TRUE /* no jbuf */,
+ best_access_path(join, join->best_positions[idx].table,
+ rem_tables, join->best_positions, idx,
+ TRUE /* no jbuf */,
record_count, join->best_positions + idx, &dummy);
}
record_count *= join->best_positions[idx].records_read;
@@ -3689,7 +3694,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
if (join->best_positions[idx].use_join_buffer || (idx == first))
{
best_access_path(join, join->best_positions[idx].table,
- rem_tables, idx, TRUE /* no jbuf */,
+ rem_tables, join->best_positions, idx,
+ TRUE /* no jbuf */,
record_count, join->best_positions + idx,
&loose_scan_pos);
if (idx==first)
diff --git a/sql/opt_subselect.h b/sql/opt_subselect.h
index 2b9031b1b81..395ceb86b2e 100644
--- a/sql/opt_subselect.h
+++ b/sql/opt_subselect.h
@@ -88,6 +88,7 @@ class Loose_scan_opt
KEYUSE *best_loose_scan_start_key;
uint best_max_loose_keypart;
+ table_map best_ref_depend_map;
public:
Loose_scan_opt():
@@ -249,13 +250,14 @@ public:
best_loose_scan_records= records;
best_max_loose_keypart= max_loose_keypart;
best_loose_scan_start_key= start_key;
+ best_ref_depend_map= 0;
}
}
}
}
void check_ref_access_part2(uint key, KEYUSE *start_key, double records,
- double read_time)
+ double read_time, table_map ref_depend_map_arg)
{
if (part1_conds_met && read_time < best_loose_scan_cost)
{
@@ -265,6 +267,7 @@ public:
best_loose_scan_records= records;
best_max_loose_keypart= max_loose_keypart;
best_loose_scan_start_key= start_key;
+ best_ref_depend_map= ref_depend_map_arg;
}
}
@@ -280,6 +283,7 @@ public:
best_loose_scan_records= rows2double(quick->records);
best_max_loose_keypart= quick_max_loose_keypart;
best_loose_scan_start_key= NULL;
+ best_ref_depend_map= 0;
}
}
@@ -295,7 +299,7 @@ public:
pos->loosescan_picker.loosescan_parts= best_max_loose_keypart + 1;
pos->use_join_buffer= FALSE;
pos->table= tab;
- // todo need ref_depend_map ?
+ pos->ref_depend_map= best_ref_depend_map;
DBUG_PRINT("info", ("Produced a LooseScan plan, key %s, %s",
tab->table->key_info[best_loose_scan_key].name.str,
best_loose_scan_start_key? "(ref access)":
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 86def348125..0e17370e93c 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -522,7 +522,6 @@ void init_update_queries(void)
server_command_flags[COM_STMT_SEND_LONG_DATA]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_REGISTER_SLAVE]= CF_SKIP_WSREP_CHECK;
server_command_flags[COM_MULTI]= CF_SKIP_WSREP_CHECK | CF_NO_COM_MULTI;
- server_command_flags[CF_NO_COM_MULTI]= CF_NO_COM_MULTI;
/* Initialize the sql command flags array. */
memset(sql_command_flags, 0, sizeof(sql_command_flags));
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 0cbb480e245..460c7346cdd 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -100,10 +100,6 @@ static int sort_keyuse(KEYUSE *a,KEYUSE *b);
static bool are_tables_local(JOIN_TAB *jtab, table_map used_tables);
static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
bool allow_full_scan, table_map used_tables);
-void best_access_path(JOIN *join, JOIN_TAB *s,
- table_map remaining_tables, uint idx,
- bool disable_jbuf, double record_count,
- POSITION *pos, POSITION *loose_scan_pos);
static void optimize_straight_join(JOIN *join, table_map join_tables);
static bool greedy_search(JOIN *join, table_map remaining_tables,
uint depth, uint prune_level,
@@ -5088,6 +5084,13 @@ make_join_statistics(JOIN *join, List<TABLE_LIST> &tables_list,
{
if (choose_plan(join, all_table_map & ~join->const_table_map))
goto error;
+
+#ifdef HAVE_valgrind
+ // JOIN::positions holds the current query plan. We've already
+ // made the plan choice, so we should only use JOIN::best_positions
+ for (uint k=join->const_tables; k < join->table_count; k++)
+ MEM_UNDEFINED(&join->positions[k], sizeof(join->positions[k]));
+#endif
}
else
{
@@ -6785,6 +6788,7 @@ void
best_access_path(JOIN *join,
JOIN_TAB *s,
table_map remaining_tables,
+ const POSITION *join_positions,
uint idx,
bool disable_jbuf,
double record_count,
@@ -6897,7 +6901,7 @@ best_access_path(JOIN *join,
if (!keyuse->val->maybe_null || keyuse->null_rejecting)
notnull_part|=keyuse->keypart_map;
- double tmp2= prev_record_reads(join->positions, idx,
+ double tmp2= prev_record_reads(join_positions, idx,
(found_ref | keyuse->used_tables));
if (tmp2 < best_prev_record_reads)
{
@@ -6938,7 +6942,7 @@ best_access_path(JOIN *join,
Really, there should be records=0.0 (yes!)
but 1.0 would be probably safer
*/
- tmp= prev_record_reads(join->positions, idx, found_ref);
+ tmp= prev_record_reads(join_positions, idx, found_ref);
records= 1.0;
}
else
@@ -6961,7 +6965,7 @@ best_access_path(JOIN *join,
(!(key_flags & HA_NULL_PART_KEY) || // (2)
all_key_parts == notnull_part)) // (3)
{
- tmp = prev_record_reads(join->positions, idx, found_ref);
+ tmp = prev_record_reads(join_positions, idx, found_ref);
records=1.0;
}
else
@@ -7205,7 +7209,8 @@ best_access_path(JOIN *join,
}
tmp= COST_ADD(tmp, s->startup_cost);
- loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp);
+ loose_scan_opt.check_ref_access_part2(key, start_key, records, tmp,
+ found_ref);
} /* not ft_key */
if (tmp + 0.0001 < best_time - records/(double) TIME_FOR_COMPARE)
@@ -7890,7 +7895,8 @@ optimize_straight_join(JOIN *join, table_map join_tables)
for (JOIN_TAB **pos= join->best_ref + idx ; (s= *pos) ; pos++)
{
/* Find the best access method from 's' to the current partial plan */
- best_access_path(join, s, join_tables, idx, disable_jbuf, record_count,
+ best_access_path(join, s, join_tables, join->positions, idx,
+ disable_jbuf, record_count,
join->positions + idx, &loose_scan_pos);
/* compute the cost of the new plan extended with 's' */
@@ -8510,7 +8516,19 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
}
keyparts++;
}
+ /*
+ Here we discount selectivity of the constant range CR. To calculate
+ this selectivity we use elements from the quick_rows[] array.
+ If we have indexes i1,...,ik with the same prefix compatible
+ with CR any of the estimate quick_rows[i1], ... quick_rows[ik] could
+ be used for this calculation but here we don't know which one was
+ actually used. So sel could be greater than 1 and we have to cap it.
+ However if sel becomes greater than 2 then with high probability
+ something went wrong.
+ */
sel /= (double)table->quick_rows[key] / (double) table->stat_records();
+ DBUG_ASSERT(0 < sel && sel <= 2.0);
+ set_if_smaller(sel, 1.0);
used_range_selectivity= true;
}
}
@@ -8558,6 +8576,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
if (table->field[fldno]->cond_selectivity > 0)
{
sel /= table->field[fldno]->cond_selectivity;
+ DBUG_ASSERT(0 < sel && sel <= 2.0);
set_if_smaller(sel, 1.0);
}
/*
@@ -8615,6 +8634,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
if (field->cond_selectivity > 0)
{
sel/= field->cond_selectivity;
+ DBUG_ASSERT(0 < sel && sel <= 2.0);
set_if_smaller(sel, 1.0);
}
break;
@@ -8626,6 +8646,7 @@ double table_cond_selectivity(JOIN *join, uint idx, JOIN_TAB *s,
sel*= table_multi_eq_cond_selectivity(join, idx, s, rem_tables,
keyparts, ref_keyuse_steps);
+ DBUG_ASSERT(0.0 < sel && sel <= 1.0);
return sel;
}
@@ -8809,8 +8830,8 @@ best_extension_by_limited_search(JOIN *join,
/* Find the best access method from 's' to the current partial plan */
POSITION loose_scan_pos;
- best_access_path(join, s, remaining_tables, idx, disable_jbuf,
- record_count, position, &loose_scan_pos);
+ best_access_path(join, s, remaining_tables, join->positions, idx,
+ disable_jbuf, record_count, position, &loose_scan_pos);
/* Compute the cost of extending the plan with 's' */
current_record_count= COST_MULT(record_count, position->records_read);
@@ -9196,11 +9217,11 @@ cache_record_length(JOIN *join,uint idx)
*/
double
-prev_record_reads(POSITION *positions, uint idx, table_map found_ref)
+prev_record_reads(const POSITION *positions, uint idx, table_map found_ref)
{
double found=1.0;
- POSITION *pos_end= positions - 1;
- for (POSITION *pos= positions + idx - 1; pos != pos_end; pos--)
+ const POSITION *pos_end= positions - 1;
+ for (const POSITION *pos= positions + idx - 1; pos != pos_end; pos--)
{
if (pos->table->table->map & found_ref)
{
@@ -15963,7 +15984,8 @@ void optimize_wo_join_buffering(JOIN *join, uint first_tab, uint last_tab,
if ((i == first_tab && first_alt) || join->positions[i].use_join_buffer)
{
/* Find the best access method that would not use join buffering */
- best_access_path(join, rs, reopt_remaining_tables, i,
+ best_access_path(join, rs, reopt_remaining_tables,
+ join->positions, i,
TRUE, rec_count,
&pos, &loose_scan_pos);
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index efb0c474c89..a63ce24bf3b 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -838,6 +838,7 @@ public:
friend void best_access_path(JOIN *join,
JOIN_TAB *s,
table_map remaining_tables,
+ const struct st_position *join_positions,
uint idx,
bool disable_jbuf,
double record_count,
@@ -2043,6 +2044,11 @@ protected:
}
};
+void best_access_path(JOIN *join, JOIN_TAB *s,
+ table_map remaining_tables,
+ const POSITION *join_positions, uint idx,
+ bool disable_jbuf, double record_count,
+ POSITION *pos, POSITION *loose_scan_pos);
bool cp_buffer_from_ref(THD *thd, TABLE *table, TABLE_REF *ref);
bool error_if_full_join(JOIN *join);
int report_error(TABLE *table, int error);
@@ -2413,7 +2419,7 @@ bool instantiate_tmp_table(TABLE *table, KEY *keyinfo,
ulonglong options);
bool open_tmp_table(TABLE *table);
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps);
-double prev_record_reads(POSITION *positions, uint idx, table_map found_ref);
+double prev_record_reads(const POSITION *positions, uint idx, table_map found_ref);
void fix_list_after_tbl_changes(SELECT_LEX *new_parent, List<TABLE_LIST> *tlist);
double get_tmp_table_lookup_cost(THD *thd, double row_count, uint row_size);
double get_tmp_table_write_cost(THD *thd, double row_count, uint row_size);
diff --git a/sql/sql_statistics.cc b/sql/sql_statistics.cc
index 5e0275fa65d..59ae111f716 100644
--- a/sql/sql_statistics.cc
+++ b/sql/sql_statistics.cc
@@ -1,4 +1,5 @@
/* Copyright (C) 2009 MySQL AB
+ Copyright (c) 2019, 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
@@ -1154,12 +1155,18 @@ public:
case COLUMN_STAT_MIN_VALUE:
table_field->read_stats->min_value->set_notnull();
stat_field->val_str(&val);
+#if 0 /* MDEV-20589 FIXME: This fails! */
+ DBUG_ASSERT(table_field->read_stats->min_value->is_stat_field);
+#endif
table_field->read_stats->min_value->store(val.ptr(), val.length(),
&my_charset_bin);
break;
case COLUMN_STAT_MAX_VALUE:
table_field->read_stats->max_value->set_notnull();
stat_field->val_str(&val);
+#if 0 /* MDEV-20589 FIXME: This fails! */
+ DBUG_ASSERT(table_field->read_stats->min_value->is_stat_field);
+#endif
table_field->read_stats->max_value->store(val.ptr(), val.length(),
&my_charset_bin);
break;
@@ -2043,7 +2050,7 @@ void create_min_max_statistical_fields_for_table_share(THD *thd,
Field *fld;
Field *table_field= *field_ptr;
my_ptrdiff_t diff= record - table_share->default_values;
- if (!(fld= table_field->clone(&stats_cb->mem_root, diff)))
+ if (!(fld= table_field->clone(&stats_cb->mem_root, NULL, diff)))
continue;
if (i == 0)
table_field->read_stats->min_value= fld;
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 5977404e9c3..00ab03cba26 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -3082,8 +3082,6 @@ server_option:
{
MYSQL_YYABORT_UNLESS(Lex->server_options.host.str == 0);
Lex->server_options.host= $2;
- my_casedn_str(system_charset_info,
- (char*) Lex->server_options.host.str);
}
| DATABASE TEXT_STRING_sys
{
diff --git a/sql/sql_yacc_ora.yy b/sql/sql_yacc_ora.yy
index 5dc3e82edce..f33ef8cfc68 100644
--- a/sql/sql_yacc_ora.yy
+++ b/sql/sql_yacc_ora.yy
@@ -2715,8 +2715,6 @@ server_option:
{
MYSQL_YYABORT_UNLESS(Lex->server_options.host.str == 0);
Lex->server_options.host= $2;
- my_casedn_str(system_charset_info,
- (char*) Lex->server_options.host.str);
}
| DATABASE TEXT_STRING_sys
{