summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2012-02-21 20:51:56 +0100
committerSergei Golubchik <sergii@pisem.net>2012-02-21 20:51:56 +0100
commitedab37cd680ebcca999d989c34251f6be1115c54 (patch)
tree9a960e6324916997d8efa87ce8d48d099d78cab8 /sql
parent5bf311e1e853457c31dbadd3d130b2569a867d80 (diff)
parent446554a15bd84f39ec4a8163e9f4456fa9be8fb2 (diff)
downloadmariadb-git-edab37cd680ebcca999d989c34251f6be1115c54.tar.gz
5.3 merge
Diffstat (limited to 'sql')
-rw-r--r--sql/handler.cc21
-rw-r--r--sql/handler.h4
-rw-r--r--sql/log.cc1
-rw-r--r--sql/mysqld.cc8
-rw-r--r--sql/mysqld.h3
-rw-r--r--sql/opt_index_cond_pushdown.cc14
-rw-r--r--sql/opt_range.cc16
-rw-r--r--sql/signal_handler.cc72
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_join_cache.cc22
-rw-r--r--sql/sql_join_cache.h2
-rw-r--r--sql/sql_list.h7
-rw-r--r--sql/sql_select.cc40
13 files changed, 158 insertions, 54 deletions
diff --git a/sql/handler.cc b/sql/handler.cc
index 8c2756977cf..5f8a64e486c 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4617,6 +4617,27 @@ int handler::compare_key2(key_range *range)
}
+/**
+ ICP callback - to be called by an engine to check the pushed condition
+*/
+extern "C" enum icp_result handler_index_cond_check(void* h_arg)
+{
+ handler *h= (handler*)h_arg;
+ THD *thd= h->table->in_use;
+ enum icp_result res;
+
+ if (thd_killed(thd))
+ return ICP_ABORTED_BY_USER;
+
+ if (h->end_range && h->compare_key2(h->end_range) > 0)
+ return ICP_OUT_OF_RANGE;
+ h->increment_statistics(&SSV::ha_pushed_index_cond_checks);
+ if ((res= h->pushed_idx_cond->val_int()? ICP_MATCH : ICP_NO_MATCH) ==
+ ICP_NO_MATCH)
+ h->increment_statistics(&SSV::ha_pushed_index_cond_filtered);
+ return res;
+}
+
int handler::index_read_idx_map(uchar * buf, uint index, const uchar * key,
key_part_map keypart_map,
enum ha_rkey_function find_flag)
diff --git a/sql/handler.h b/sql/handler.h
index b52ee6a7279..0ff1a8db01d 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1638,6 +1638,8 @@ public:
{}
};
+extern "C" enum icp_result handler_index_cond_check(void* h_arg);
+
uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map);
/*
bitmap with first N+1 bits set
@@ -2857,6 +2859,8 @@ public:
{ return ht; }
inline int ha_write_tmp_row(uchar *buf);
inline int ha_update_tmp_row(const uchar * old_data, uchar * new_data);
+
+ friend enum icp_result handler_index_cond_check(void* h_arg);
};
#include "multi_range_read.h"
diff --git a/sql/log.cc b/sql/log.cc
index 9e9716dde67..577297fa1a4 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -2230,7 +2230,6 @@ static int find_uniq_filename(char *name)
char *start, *end;
int error= 0;
DBUG_ENTER("find_uniq_filename");
- LINT_INIT(number);
length= dirname_part(buff, name, &buf_length);
start= name + length;
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index bea3d1ef4a4..e5b9a6e6312 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -340,7 +340,7 @@ static volatile bool ready_to_exit;
static my_bool opt_debugging= 0, opt_external_locking= 0, opt_console= 0;
static my_bool opt_short_log_format= 0;
static uint kill_cached_threads, wake_thread;
- ulong max_used_connections;
+ulong max_used_connections;
static volatile ulong cached_thread_count= 0;
static char *mysqld_user, *mysqld_chroot;
static char *default_character_set_name;
@@ -680,6 +680,7 @@ char *opt_logname, *opt_slow_logname, *opt_bin_logname;
my_bool opt_stack_trace;
static volatile sig_atomic_t kill_in_progress;
+my_bool opt_expect_abort= 0;
static my_bool opt_bootstrap, opt_myisam_log;
static int cleanup_done;
static ulong opt_specialflag;
@@ -1240,7 +1241,6 @@ static int mysql_init_variables(void);
static int get_options(int *argc_ptr, char ***argv_ptr);
static bool add_terminator(DYNAMIC_ARRAY *options);
extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
-static void set_server_version(void);
static int init_thread_environment();
static char *get_relative_path(const char *path);
static int fix_paths(void);
@@ -6876,6 +6876,8 @@ SHOW_VAR status_vars[]= {
{"Handler_mrr_init", (char*) offsetof(STATUS_VAR, ha_multi_range_read_init_count), SHOW_LONG_STATUS},
#endif
{"Handler_prepare", (char*) offsetof(STATUS_VAR, ha_prepare_count), SHOW_LONG_STATUS},
+ {"Handler_pushed_index_cond_checks",(char*) offsetof(STATUS_VAR, ha_pushed_index_cond_checks), SHOW_LONG_STATUS},
+ {"Handler_pushed_index_cond_filtered",(char*) offsetof(STATUS_VAR, ha_pushed_index_cond_filtered), SHOW_LONG_STATUS},
{"Handler_read_first", (char*) offsetof(STATUS_VAR, ha_read_first_count), SHOW_LONG_STATUS},
{"Handler_read_key", (char*) offsetof(STATUS_VAR, ha_read_key_count), SHOW_LONG_STATUS},
{"Handler_read_last", (char*) offsetof(STATUS_VAR, ha_read_last_count), SHOW_LONG_STATUS},
@@ -7905,7 +7907,7 @@ static int get_options(int *argc_ptr, char ***argv_ptr)
(MYSQL_SERVER_SUFFIX is set by the compilation environment)
*/
-static void set_server_version(void)
+void set_server_version(void)
{
char *end= strxmov(server_version, MYSQL_SERVER_VERSION,
MYSQL_SERVER_SUFFIX_STR, NullS);
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 9246ea90fa1..296b747b1ce 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -501,6 +501,8 @@ get_thread_running()
return num_thread_running;
}
+void set_server_version(void);
+
#if defined(MYSQL_DYNAMIC_PLUGIN) && defined(_WIN32)
extern "C" THD *_current_thd_noinline();
#define _current_thd() _current_thd_noinline()
@@ -534,6 +536,7 @@ extern scheduler_functions *thread_scheduler, *extra_thread_scheduler;
extern char *opt_log_basename;
extern my_bool opt_master_verify_checksum;
extern my_bool opt_stack_trace;
+extern my_bool opt_expect_abort;
extern my_bool opt_slave_sql_verify_checksum;
extern ulong binlog_checksum_options;
extern bool max_user_connections_checking;
diff --git a/sql/opt_index_cond_pushdown.cc b/sql/opt_index_cond_pushdown.cc
index ba6aece7377..df9dae8e442 100644
--- a/sql/opt_index_cond_pushdown.cc
+++ b/sql/opt_index_cond_pushdown.cc
@@ -345,13 +345,23 @@ void push_index_cond(JOIN_TAB *tab, uint keyno)
{
DBUG_ENTER("push_index_cond");
Item *idx_cond;
-
+
+ /*
+ Backported the following from MySQL 5.6:
+ 6. The index is not a clustered index. The performance improvement
+ of pushing an index condition on a clustered key is much lower
+ than on a non-clustered key. This restriction should be
+ re-evaluated when WL#6061 is implemented.
+ */
if ((tab->table->file->index_flags(keyno, 0, 1) &
HA_DO_INDEX_COND_PUSHDOWN) &&
optimizer_flag(tab->join->thd, OPTIMIZER_SWITCH_INDEX_COND_PUSHDOWN) &&
tab->join->thd->lex->sql_command != SQLCOM_UPDATE_MULTI &&
tab->join->thd->lex->sql_command != SQLCOM_DELETE_MULTI &&
- tab->type != JT_CONST && tab->type != JT_SYSTEM)
+ tab->type != JT_CONST && tab->type != JT_SYSTEM &&
+ !(keyno == tab->table->s->primary_key && // (6)
+ tab->table->file->primary_key_is_clustered())) // (6)
+
{
DBUG_EXECUTE("where",
print_where(tab->select_cond, "full cond", QT_ORDINARY););
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9fb29512b83..a004e7700c7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -578,6 +578,14 @@ public:
increment_use_count(1);
use_count++;
}
+ void incr_refs_all()
+ {
+ for (SEL_ARG *pos=first(); pos ; pos=pos->next)
+ {
+ pos->increment_use_count(1);
+ }
+ use_count++;
+ }
void free_tree()
{
for (SEL_ARG *pos=first(); pos ; pos=pos->next)
@@ -1117,9 +1125,11 @@ int SEL_IMERGE::and_sel_tree(RANGE_OPT_PARAM *param, SEL_TREE *tree,
for (SEL_TREE** or_tree= trees; or_tree != trees_next; or_tree++)
{
SEL_TREE *res_or_tree= 0;
- if (!(res_or_tree= new SEL_TREE()))
+ SEL_TREE *and_tree= 0;
+ if (!(res_or_tree= new SEL_TREE()) ||
+ !(and_tree= new SEL_TREE(tree, TRUE, param)))
return (-1);
- if (!and_range_trees(param, *or_tree, tree, res_or_tree))
+ if (!and_range_trees(param, *or_tree, and_tree, res_or_tree))
{
if (new_imerge->or_sel_tree(param, res_or_tree))
return (-1);
@@ -1332,7 +1342,7 @@ SEL_TREE::SEL_TREE(SEL_TREE *arg, bool without_merges,
for (uint idx= 0; idx < param->keys; idx++)
{
if ((keys[idx]= arg->keys[idx]))
- keys[idx]->incr_refs();
+ keys[idx]->incr_refs_all();
}
if (without_merges)
diff --git a/sql/signal_handler.cc b/sql/signal_handler.cc
index fe75b209ab1..dd50854d818 100644
--- a/sql/signal_handler.cc
+++ b/sql/signal_handler.cc
@@ -1,4 +1,5 @@
-/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2011, Oracle and/or its affiliates.
+ Copyright (c) 2011, Monty Program Ab.
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
@@ -30,7 +31,7 @@
#endif
/*
- We are handling signals in this file.
+ We are handling signals/exceptions in this file.
Any global variables we read should be 'volatile sig_atomic_t'
to guarantee that we read some consistent value.
*/
@@ -44,23 +45,27 @@ extern volatile sig_atomic_t ld_assume_kernel_is_set;
extern const char *optimizer_switch_names[];
/**
- * Handler for fatal signals
+ * Handler for fatal signals on POSIX, exception handler on Windows.
*
* Fatal events (seg.fault, bus error etc.) will trigger
* this signal handler. The handler will try to dump relevant
* debugging information to stderr and dump a core image.
*
- * Signal handlers can only use a set of 'safe' system calls
- * and library functions. A list of safe calls in POSIX systems
+ * POSIX : Signal handlers should, if possible, only use a set of 'safe' system
+ * calls and library functions. A list of safe calls in POSIX systems
* are available at:
* http://pubs.opengroup.org/onlinepubs/009695399/functions/xsh_chap02_04.html
- * For MS Windows, guidelines are available at:
- * http://msdn.microsoft.com/en-us/library/xdkz3x12(v=vs.71).aspx
*
- * @param sig Signal number
+ * @param sig Signal number /Exception code
*/
extern "C" sig_handler handle_fatal_signal(int sig)
{
+ time_t curr_time;
+ struct tm tm;
+#ifdef HAVE_STACKTRACE
+ THD *thd;
+#endif
+
if (segfaulted)
{
my_safe_printf_stderr("Fatal " SIGNAL_FMT " while backtracing\n", sig);
@@ -69,43 +74,40 @@ extern "C" sig_handler handle_fatal_signal(int sig)
segfaulted = 1;
-#ifdef __WIN__
- SYSTEMTIME utc_time;
- GetSystemTime(&utc_time);
- const long hrs= utc_time.wHour;
- const long mins= utc_time.wMinute;
- const long secs= utc_time.wSecond;
+ curr_time= my_time(0);
+ localtime_r(&curr_time, &tm);
+
+ my_safe_printf_stderr("%02d%02d%02d %2d:%02d:%02d ",
+ tm.tm_year % 100, tm.tm_mon+1, tm.tm_mday,
+ tm.tm_hour, tm.tm_min, tm.tm_sec);
+ if (opt_expect_abort
+#ifdef _WIN32
+ && sig == EXCEPTION_BREAKPOINT /* __debugbreak in my_sigabrt_hander() */
#else
- /* Using time() instead of my_time() to avoid looping */
- const time_t curr_time= time(NULL);
- /* Calculate time of day */
- const long tmins = curr_time / 60;
- const long thrs = tmins / 60;
- const long hrs = thrs % 24;
- const long mins = tmins % 60;
- const long secs = curr_time % 60;
+ && sig == SIGABRT
#endif
+ )
+ {
+ fprintf(stderr,"[Note] mysqld did an expected abort\n");
+ goto end;
+ }
- char hrs_buf[3]= "00";
- char mins_buf[3]= "00";
- char secs_buf[3]= "00";
- my_safe_itoa(10, hrs, &hrs_buf[2]);
- my_safe_itoa(10, mins, &mins_buf[2]);
- my_safe_itoa(10, secs, &secs_buf[2]);
-
- my_safe_printf_stderr("%s:%s:%s UTC - mysqld got " SIGNAL_FMT " ;\n",
- hrs_buf, mins_buf, secs_buf, sig);
+ my_safe_printf_stderr("[ERROR] mysqld got " SIGNAL_FMT " ;\n",sig);
my_safe_printf_stderr("%s",
"This could be because you hit a bug. It is also possible that this binary\n"
"or one of the libraries it was linked against is corrupt, improperly built,\n"
- "or misconfigured. This error can also be caused by malfunctioning hardware.\n");
+ "or misconfigured. This error can also be caused by malfunctioning hardware.\n\n");
+
+ my_safe_printf_stderr("%s",
+ "To report this bug, see http://kb.askmonty.org/en/reporting-bugs\n\n");
my_safe_printf_stderr("%s",
"We will try our best to scrape up some info that will hopefully help\n"
"diagnose the problem, but since we have already crashed, \n"
"something is definitely wrong and this may fail.\n\n");
+ set_server_version();
my_safe_printf_stderr("Server version: %s\n", server_version);
my_safe_printf_stderr("key_buffer_size=%lu\n",
@@ -153,7 +155,7 @@ extern "C" sig_handler handle_fatal_signal(int sig)
#endif /* HAVE_LINUXTHREADS */
#ifdef HAVE_STACKTRACE
- THD *thd=current_thd;
+ thd= current_thd;
if (opt_stack_trace)
{
@@ -268,15 +270,19 @@ extern "C" sig_handler handle_fatal_signal(int sig)
if (test_flags & TEST_CORE_ON_SIGNAL)
{
my_safe_printf_stderr("%s", "Writing a core file\n");
+ fflush(stderr);
my_write_core(sig);
}
#endif
+end:
#ifndef __WIN__
/*
Quit, without running destructors (etc.)
On Windows, do not terminate, but pass control to exception filter.
*/
_exit(1); // Using _exit(), since exit() is not async signal safe
+#else
+ return;
#endif
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 581e35aa137..980189ae9e0 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -602,6 +602,8 @@ typedef struct system_status_var
ulong ha_tmp_update_count;
ulong ha_tmp_write_count;
ulong ha_prepare_count;
+ ulong ha_pushed_index_cond_checks;
+ ulong ha_pushed_index_cond_filtered;
ulong ha_discover_count;
ulong ha_savepoint_count;
ulong ha_savepoint_rollback_count;
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index f0362585e39..f4fe8790bf7 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -2577,6 +2577,15 @@ void JOIN_CACHE::print_explain_comment(String *str)
str->append(STRING_WITH_LEN(")"));
}
+/**
+ get thread handle.
+*/
+
+THD *JOIN_CACHE::thd()
+{
+ return join->thd;
+}
+
static void add_mrr_explain_info(String *str, uint mrr_mode, handler *file)
{
@@ -4016,7 +4025,11 @@ bool bka_skip_index_tuple(range_seq_t rseq, range_id_t range_info)
{
DBUG_ENTER("bka_skip_index_tuple");
JOIN_CACHE_BKA *cache= (JOIN_CACHE_BKA *) rseq;
- bool res= cache->skip_index_tuple(range_info);
+ THD *thd= cache->thd();
+ bool res;
+ status_var_increment(thd->status_var.ha_pushed_index_cond_checks);
+ if ((res= cache->skip_index_tuple(range_info)))
+ status_var_increment(thd->status_var.ha_pushed_index_cond_filtered);
DBUG_RETURN(res);
}
@@ -4491,7 +4504,12 @@ bool bkah_skip_index_tuple(range_seq_t rseq, range_id_t range_info)
{
DBUG_ENTER("bka_unique_skip_index_tuple");
JOIN_CACHE_BKAH *cache= (JOIN_CACHE_BKAH *) rseq;
- DBUG_RETURN(cache->skip_index_tuple(range_info));
+ THD *thd= cache->thd();
+ bool res;
+ status_var_increment(thd->status_var.ha_pushed_index_cond_checks);
+ if ((res= cache->skip_index_tuple(range_info)))
+ status_var_increment(thd->status_var.ha_pushed_index_cond_filtered);
+ DBUG_RETURN(res);
}
diff --git a/sql/sql_join_cache.h b/sql/sql_join_cache.h
index 84c9d52c558..6953f6881ee 100644
--- a/sql/sql_join_cache.h
+++ b/sql/sql_join_cache.h
@@ -659,6 +659,8 @@ public:
/* Add a comment on the join algorithm employed by the join cache */
virtual void print_explain_comment(String *str);
+ THD *thd();
+
virtual ~JOIN_CACHE() {}
void reset_join(JOIN *j) { join= j; }
void free()
diff --git a/sql/sql_list.h b/sql/sql_list.h
index 7bd72cba359..6cc05ff1f62 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -260,7 +260,12 @@ public:
last= &first;
return tmp->info;
}
- inline void disjoin(base_list *list)
+ /*
+ Remove from this list elements that are contained in the passed list.
+ We assume that the passed list is a tail of this list (that is, the whole
+ list_node* elements are shared).
+ */
+ inline void disjoin(const base_list *list)
{
list_node **prev= &first;
list_node *node= first;
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 9a085ec6314..4c02f19926f 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -1295,9 +1295,20 @@ JOIN::optimize()
Item *ref_item= *ref_item_ptr;
if (!ref_item->used_tables() && !(select_options & SELECT_DESCRIBE))
continue;
- COND_EQUAL *equals= tab->first_inner ? tab->first_inner->cond_equal :
- cond_equal;
- ref_item= substitute_for_best_equal_field(tab, ref_item, equals, map2table);
+ COND_EQUAL *equals= cond_equal;
+ JOIN_TAB *first_inner= tab->first_inner;
+ while (equals)
+ {
+ ref_item= substitute_for_best_equal_field(tab, ref_item,
+ equals, map2table);
+ if (first_inner)
+ {
+ equals= first_inner->cond_equal;
+ first_inner= first_inner->first_upper;
+ }
+ else
+ equals= 0;
+ }
ref_item->update_used_tables();
if (*ref_item_ptr != ref_item)
{
@@ -9311,7 +9322,7 @@ uint check_join_cache_usage(JOIN_TAB *tab,
Check whether table tab and the previous one belong to the same nest of
inner tables and if so do not use join buffer when joining table tab.
*/
- if (tab->first_inner)
+ if (tab->first_inner && tab != tab->first_inner)
{
for (JOIN_TAB *first_inner= tab[-1].first_inner;
first_inner;
@@ -9321,7 +9332,7 @@ uint check_join_cache_usage(JOIN_TAB *tab,
goto no_join_cache;
}
}
- else if (tab->first_sj_inner_tab &&
+ else if (tab->first_sj_inner_tab && tab != tab->first_sj_inner_tab &&
tab->first_sj_inner_tab == tab[-1].first_sj_inner_tab)
goto no_join_cache;
}
@@ -10569,10 +10580,22 @@ return_zero_rows(JOIN *join, select_result *result, List<TABLE_LIST> &tables,
if (send_row)
{
+ /*
+ Set all tables to have NULL row. This is needed as we will be evaluating
+ HAVING condition.
+ */
List_iterator<TABLE_LIST> ti(tables);
TABLE_LIST *table;
while ((table= ti++))
- mark_as_null_row(table->table); // All fields are NULL
+ {
+ /*
+ Don't touch semi-join materialization tables, as the above join_free()
+ call has freed them (and HAVING clause can't have references to them
+ anyway).
+ */
+ if (!table->is_jtbm())
+ mark_as_null_row(table->table); // All fields are NULL
+ }
if (having &&
!having->walk(&Item::clear_sum_processor, FALSE, NULL) &&
having->val_int() == 0)
@@ -12819,9 +12842,8 @@ optimize_cond(JOIN *join, COND *conds, List<TABLE_LIST> *join_list,
multiple equality contains a constant.
*/
DBUG_EXECUTE("where", print_where(conds, "original", QT_ORDINARY););
- conds= build_equal_items(join->thd, conds, NULL, join_list,
- &join->cond_equal);
- DBUG_EXECUTE("where",print_where(conds,"after equal_items", QT_ORDINARY););
+ conds= build_equal_items(join->thd, conds, NULL, join_list, cond_equal);
+ DBUG_EXECUTE("where",print_where(conds,"after equal_items", QT_ORDINARY););
/* change field = field to field = const for each found field = const */
propagate_cond_constants(thd, (I_List<COND_CMP> *) 0, conds, conds);