summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2012-05-21 20:54:41 +0200
committerSergei Golubchik <sergii@pisem.net>2012-05-21 20:54:41 +0200
commit1185420da0964b2f06d9fd91bd02d067b0a359de (patch)
tree0b4162e316a18fa6ce3f56ee447454b4c73d1805 /sql
parent431e042b5d76ed5fd219c39db798c9e7478731c8 (diff)
parent7f6f53a8df10c76f93848c8d06bc5af71051c525 (diff)
downloadmariadb-git-1185420da0964b2f06d9fd91bd02d067b0a359de.tar.gz
5.3 merge
Diffstat (limited to 'sql')
-rw-r--r--sql/item_cmpfunc.h2
-rw-r--r--sql/opt_range.cc2
-rw-r--r--sql/opt_subselect.cc22
-rw-r--r--sql/opt_sum.cc4
-rw-r--r--sql/slave.cc5
-rw-r--r--sql/sql_base.cc2
-rw-r--r--sql/sql_reload.cc5
-rw-r--r--sql/sql_select.cc70
-rw-r--r--sql/sql_select.h14
9 files changed, 109 insertions, 17 deletions
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index b9740c7af03..de62bc49930 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -252,6 +252,7 @@ public:
{ with_subselect= true; }
bool fix_fields(THD *, Item **);
bool fix_left(THD *thd, Item **ref);
+ table_map not_null_tables() const { return 0; }
bool is_null();
longlong val_int();
void cleanup();
@@ -503,6 +504,7 @@ public:
{}
virtual void top_level_item() { abort_on_null= 1; }
bool is_top_level_item() { return abort_on_null; }
+ table_map not_null_tables() const { return 0; }
longlong val_int();
enum Functype functype() const { return NOT_ALL_FUNC; }
const char *func_name() const { return "<not>"; }
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index c6ee117213d..965250170a5 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -13271,7 +13271,7 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min()
if (min_max_arg_part && min_max_arg_part->field->is_null())
{
/* Find the first subsequent record without NULL in the MIN/MAX field. */
- key_copy(tmp_record, record, index_info, 0);
+ key_copy(tmp_record, record, index_info, max_used_key_length);
result= file->ha_index_read_map(record, tmp_record,
make_keypart_map(real_key_parts),
HA_READ_AFTER_KEY);
diff --git a/sql/opt_subselect.cc b/sql/opt_subselect.cc
index 9bf1aaf4039..bab061a2ac7 100644
--- a/sql/opt_subselect.cc
+++ b/sql/opt_subselect.cc
@@ -3176,6 +3176,25 @@ at_sjmat_pos(const JOIN *join, table_map remaining_tables, const JOIN_TAB *tab,
}
+/*
+ Re-calculate values of join->best_positions[start..end].prefix_record_count
+*/
+
+static void recalculate_prefix_record_count(JOIN *join, uint start, uint end)
+{
+ for (uint j= start; j < end ;j++)
+ {
+ double prefix_count;
+ if (j == join->const_tables)
+ prefix_count= 1.0;
+ else
+ prefix_count= join->best_positions[j-1].prefix_record_count *
+ join->best_positions[j-1].records_read;
+
+ join->best_positions[j].prefix_record_count= prefix_count;
+ }
+}
+
/*
Fix semi-join strategies for the picked join order
@@ -3245,6 +3264,8 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
sjm->is_sj_scan= FALSE;
memcpy(pos - sjm->tables + 1, sjm->positions,
sizeof(POSITION) * sjm->tables);
+ recalculate_prefix_record_count(join, tablenr - sjm->tables + 1,
+ tablenr);
first= tablenr - sjm->tables + 1;
join->best_positions[first].n_sj_tables= sjm->tables;
join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE;
@@ -3258,6 +3279,7 @@ void fix_semijoin_strategies_for_picked_join_order(JOIN *join)
first= pos->sjmat_picker.sjm_scan_last_inner - sjm->tables + 1;
memcpy(join->best_positions + first,
sjm->positions, sizeof(POSITION) * sjm->tables);
+ recalculate_prefix_record_count(join, first, first + sjm->tables);
join->best_positions[first].sj_strategy= SJ_OPT_MATERIALIZE_SCAN;
join->best_positions[first].n_sj_tables= sjm->tables;
/*
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 430c201d3e6..cbec039b3e4 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -415,7 +415,7 @@ int opt_sum_query(THD *thd,
}
removed_tables|= table->map;
}
- else if (!expr->const_item() || !is_exact_count)
+ else if (!expr->const_item() || !is_exact_count || conds)
{
/*
The optimization is not applicable in both cases:
@@ -425,6 +425,8 @@ int opt_sum_query(THD *thd,
NULL if the query does not return any rows. Thus, if we are not
able to determine if the query returns any rows, we can't apply
the optimization and replace MIN/MAX with a constant.
+ (c) there is a WHERE clause. The WHERE conditions may result in
+ an empty result, but the clause cannot be taken into account here.
*/
const_result= 0;
break;
diff --git a/sql/slave.cc b/sql/slave.cc
index 94af12472c1..5292595d157 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -1829,7 +1829,9 @@ Waiting for the slave SQL thread to free enough relay log space");
#endif
if (rli->sql_force_rotate_relay)
{
+ mysql_mutex_lock(&active_mi->data_lock);
rotate_relay_log(rli->mi);
+ mysql_mutex_unlock(&active_mi->data_lock);
rli->sql_force_rotate_relay= false;
}
@@ -5396,7 +5398,10 @@ int rotate_relay_log(Master_info* mi)
output in SHOW SLAVE STATUS meanwhile. So we harvest now.
If the log is closed, then this will just harvest the last writes, probably
0 as they probably have been harvested.
+
+ Note that it needs to be protected by mi->data_lock.
*/
+ mysql_mutex_assert_owner(&mi->data_lock);
rli->relay_log.harvest_bytes_written(&rli->log_space_total);
end:
DBUG_RETURN(error);
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 51b84f309c7..688108555d6 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1987,8 +1987,8 @@ next:
("convert merged to materialization to resolve the conflict"));
derived->change_refs_to_fields();
derived->set_materialized_derived();
+ goto retry;
}
- goto retry;
}
DBUG_RETURN(res);
}
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index 1f3b1effff3..914b9026014 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -24,6 +24,7 @@
#include "sql_db.h" // my_dbopt_cleanup
#include "hostname.h" // hostname_cache_refresh
#include "sql_repl.h" // reset_master, reset_slave
+#include "rpl_mi.h" // Master_info::data_lock
#include "debug_sync.h"
static void disable_checkpoints(THD *thd);
@@ -156,10 +157,10 @@ bool reload_acl_and_cache(THD *thd, unsigned long options,
if (options & REFRESH_RELAY_LOG)
{
#ifdef HAVE_REPLICATION
- mysql_mutex_lock(&LOCK_active_mi);
+ mysql_mutex_lock(&active_mi->data_lock);
if (rotate_relay_log(active_mi))
*write_to_binlog= -1;
- mysql_mutex_unlock(&LOCK_active_mi);
+ mysql_mutex_unlock(&active_mi->data_lock);
#endif
}
#ifdef HAVE_QUERY_CACHE
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 515a21505d9..f88a14c3312 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -114,7 +114,8 @@ static store_key *get_store_key(THD *thd,
uint maybe_null);
static bool make_outerjoin_info(JOIN *join);
static Item*
-make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables, table_map sjm_tables);
+make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables,
+ table_map sjm_tables, bool inside_or_clause);
static bool make_join_select(JOIN *join,SQL_SELECT *select,COND *item);
static void revise_cache_usage(JOIN_TAB *join_tab);
static bool make_join_readinfo(JOIN *join, ulonglong options, uint no_jbuf_after);
@@ -1333,8 +1334,19 @@ JOIN::optimize()
store_key *key_copy= tab->ref.key_copy[key_copy_index];
if (key_copy->type() == store_key::FIELD_STORE_KEY)
{
- store_key_field *field_copy= ((store_key_field *)key_copy);
- field_copy->change_source_field((Item_field *) item);
+ if (item->basic_const_item())
+ {
+ /* It is constant propagated here */
+ tab->ref.key_copy[key_copy_index]=
+ new store_key_const_item(*tab->ref.key_copy[key_copy_index],
+ item);
+ }
+ else
+ {
+ store_key_field *field_copy= ((store_key_field *)key_copy);
+ DBUG_ASSERT(item->type() == Item::FIELD_ITEM);
+ field_copy->change_source_field((Item_field *) item);
+ }
}
}
key_copy_index++;
@@ -1523,7 +1535,6 @@ JOIN::optimize()
simple_order=1;
select_distinct= 0; // No need in distinct for 1 row
group_optimized_away= 1;
- implicit_grouping= TRUE;
}
calc_group_buffer(this, group_list);
@@ -8009,7 +8020,31 @@ JOIN::make_simple_join(JOIN *parent, TABLE *temp_table)
tmp_table_param.copy_field= tmp_table_param.copy_field_end=0;
first_record= sort_and_group=0;
send_records= (ha_rows) 0;
- group= 0;
+
+ if (group_optimized_away && !tmp_table_param.precomputed_group_by)
+ {
+ /*
+ If grouping has been optimized away, a temporary table is
+ normally not needed unless we're explicitly requested to create
+ one (e.g. due to a SQL_BUFFER_RESULT hint or INSERT ... SELECT).
+
+ In this case (grouping was optimized away), temp_table was
+ created without a grouping expression and JOIN::exec() will not
+ perform the necessary grouping (by the use of end_send_group()
+ or end_write_group()) if JOIN::group is set to false.
+
+ There is one exception: if the loose index scan access method is
+ used to read into the temporary table, grouping and aggregate
+ functions are handled.
+ */
+ // the temporary table was explicitly requested
+ DBUG_ASSERT(test(select_options & OPTION_BUFFER_RESULT));
+ // the temporary table does not have a grouping expression
+ DBUG_ASSERT(!temp_table->group);
+ }
+ else
+ group= false;
+
row_limit= unit->select_limit_cnt;
do_send_rows= row_limit ? 1 : 0;
@@ -8138,6 +8173,16 @@ static void add_not_null_conds(JOIN *join)
Item *item= tab->ref.items[keypart];
Item *notnull;
Item *real= item->real_item();
+ if (real->basic_const_item())
+ {
+ /*
+ It could be constant instead of field after constant
+ propagation.
+ */
+ DBUG_ASSERT(real->is_expensive() || // prevent early expensive eval
+ !real->is_null()); // NULLs are not propagated
+ continue;
+ }
DBUG_ASSERT(real->type() == Item::FIELD_ITEM);
Item_field *not_null_item= (Item_field*)real;
JOIN_TAB *referred_tab= not_null_item->field->table->reginfo.join_tab;
@@ -8519,7 +8564,8 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
if (tab->bush_children)
{
// Reached the materialization tab
- tmp= make_cond_after_sjm(cond, cond, save_used_tables, used_tables);
+ tmp= make_cond_after_sjm(cond, cond, save_used_tables, used_tables,
+ /*inside_or_clause=*/FALSE);
used_tables= save_used_tables | used_tables;
save_used_tables= 0;
}
@@ -17732,13 +17778,14 @@ make_cond_for_table_from_pred(THD *thd, Item *root_cond, Item *cond,
*/
static COND *
make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables,
- table_map sjm_tables)
+ table_map sjm_tables, bool inside_or_clause)
{
/*
We assume that conditions that refer to only join prefix tables or
sjm_tables have already been checked.
*/
- if ((!(cond->used_tables() & ~tables) ||
+ if (!inside_or_clause &&
+ (!(cond->used_tables() & ~tables) ||
!(cond->used_tables() & ~sjm_tables)))
return (COND*) 0; // Already checked
@@ -17755,7 +17802,8 @@ make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables,
Item *item;
while ((item=li++))
{
- Item *fix=make_cond_after_sjm(root_cond, item, tables, sjm_tables);
+ Item *fix=make_cond_after_sjm(root_cond, item, tables, sjm_tables,
+ inside_or_clause);
if (fix)
new_cond->argument_list()->push_back(fix);
}
@@ -17785,7 +17833,8 @@ make_cond_after_sjm(Item *root_cond, Item *cond, table_map tables,
Item *item;
while ((item=li++))
{
- Item *fix= make_cond_after_sjm(root_cond, item, tables, 0L);
+ Item *fix= make_cond_after_sjm(root_cond, item, tables, sjm_tables,
+ /*inside_or_clause= */TRUE);
if (!fix)
return (COND*) 0; // Always true
new_cond->argument_list()->push_back(fix);
@@ -18373,7 +18422,6 @@ test_if_skip_sort_order(JOIN_TAB *tab,ORDER *order,ha_rows select_limit,
KEYUSE *keyuse= tab->keyuse;
while (keyuse->key != new_ref_key && keyuse->table == tab->table)
keyuse++;
-
if (create_ref_for_key(tab->join, tab, keyuse, FALSE,
(tab->join->const_table_map |
OUTER_REF_TABLE_BIT)))
diff --git a/sql/sql_select.h b/sql/sql_select.h
index 08ddc27e204..c4553148cc6 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -1465,6 +1465,11 @@ public:
to_field=field_arg->new_key_field(thd->mem_root, field_arg->table,
ptr, null, 1);
}
+ store_key(store_key &arg)
+ :Sql_alloc(), null_key(arg.null_key), to_field(arg.to_field),
+ null_ptr(arg.null_ptr), err(arg.err)
+
+ {}
virtual ~store_key() {} /** Not actually needed */
virtual enum Type type() const=0;
virtual const char *name() const=0;
@@ -1569,6 +1574,10 @@ public:
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : (uchar*) 0, length), item(item_arg), use_value(val)
{}
+ store_key_item(store_key &arg, Item *new_item, bool val)
+ :store_key(arg), item(new_item), use_value(val)
+ {}
+
enum Type type() const { return ITEM_STORE_KEY; }
const char *name() const { return "func"; }
@@ -1614,11 +1623,14 @@ public:
store_key_const_item(THD *thd, Field *to_field_arg, uchar *ptr,
uchar *null_ptr_arg, uint length,
Item *item_arg)
- :store_key_item(thd, to_field_arg,ptr,
+ :store_key_item(thd, to_field_arg, ptr,
null_ptr_arg ? null_ptr_arg : item_arg->maybe_null ?
&err : (uchar*) 0, length, item_arg, FALSE), inited(0)
{
}
+ store_key_const_item(store_key &arg, Item *new_item)
+ :store_key_item(arg, new_item, FALSE), inited(0)
+ {}
enum Type type() const { return CONST_ITEM_STORE_KEY; }
const char *name() const { return "const"; }