summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorSergei Golubchik <sergii@pisem.net>2012-11-03 12:28:51 +0100
committerSergei Golubchik <sergii@pisem.net>2012-11-03 12:28:51 +0100
commit40e94a3734b1daa254810c4be64e17b84dbbc2a2 (patch)
tree5e14dfc106276445caf85dc76c8034c8b0df11b4 /sql
parent247e654fa7e04dd0c5181c2241470f56749d2a99 (diff)
parent4ffc9c3b01459a2904a7154a6c750d128864fc7b (diff)
downloadmariadb-git-40e94a3734b1daa254810c4be64e17b84dbbc2a2.tar.gz
merge with 5.5
Diffstat (limited to 'sql')
-rw-r--r--sql/create_options.cc7
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/gen_lex_hash.cc25
-rw-r--r--sql/ha_partition.cc151
-rw-r--r--sql/ha_partition.h12
-rw-r--r--sql/handler.cc30
-rw-r--r--sql/item.cc6
-rw-r--r--sql/item_strfunc.cc51
-rw-r--r--sql/item_subselect.cc27
-rw-r--r--sql/item_subselect.h5
-rw-r--r--sql/log.cc8
-rw-r--r--sql/mdl.cc120
-rw-r--r--sql/mdl.h6
-rw-r--r--sql/mysqld.cc62
-rw-r--r--sql/mysqld.h16
-rw-r--r--sql/opt_range.cc40
-rw-r--r--sql/scheduler.cc24
-rw-r--r--sql/scheduler.h2
-rw-r--r--sql/set_var.cc36
-rw-r--r--sql/set_var.h4
-rw-r--r--sql/share/charsets/Index.xml2
-rw-r--r--sql/share/errmsg-utf8.txt4
-rw-r--r--sql/spatial.cc7
-rw-r--r--sql/spatial.h8
-rw-r--r--sql/sql_base.cc23
-rw-r--r--sql/sql_class.cc70
-rw-r--r--sql/sql_join_cache.cc29
-rw-r--r--sql/sql_list.h4
-rw-r--r--sql/sql_plugin.cc5
-rw-r--r--sql/sql_prepare.cc8
-rw-r--r--sql/sql_priv.h2
-rw-r--r--sql/sql_select.cc26
-rw-r--r--sql/sql_show.cc278
-rw-r--r--sql/sql_show.h8
-rw-r--r--sql/sql_string.h11
-rw-r--r--sql/sys_vars.cc26
-rw-r--r--sql/sys_vars.h88
-rw-r--r--sql/table.cc12
-rw-r--r--sql/table.h1
-rw-r--r--sql/threadpool_common.cc2
-rw-r--r--sql/threadpool_unix.cc18
-rw-r--r--sql/threadpool_win.cc16
42 files changed, 955 insertions, 329 deletions
diff --git a/sql/create_options.cc b/sql/create_options.cc
index e4881388688..5cedfa03a63 100644
--- a/sql/create_options.cc
+++ b/sql/create_options.cc
@@ -137,11 +137,8 @@ static bool set_one_value(ha_create_table_option *opt,
my_option optp=
{ opt->name, 1, 0, (uchar **)val, 0, 0, GET_ULL,
- REQUIRED_ARG,
- (longlong) opt->def_value,
- (longlong) opt->min_value,
- opt->max_value,
- 0, (long) opt->block_size, 0};
+ REQUIRED_ARG, (longlong)opt->def_value, (longlong)opt->min_value,
+ opt->max_value, 0, (long) opt->block_size, 0};
ulonglong orig_val= strtoull(value->str, NULL, 10);
my_bool unused;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 103d3600559..ac67fb56395 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -1,5 +1,5 @@
-/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2012, 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
diff --git a/sql/gen_lex_hash.cc b/sql/gen_lex_hash.cc
index 7b50b26c6ca..c37f4f145cf 100644
--- a/sql/gen_lex_hash.cc
+++ b/sql/gen_lex_hash.cc
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
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
@@ -85,6 +85,7 @@ So, we can read full search-structure as 32-bit word
#include <stdio.h>
#include <string.h>
+#include <welcome_copyright_notice.h> /* ORACLE_WELCOME_COPYRIGHT_NOTICE */
struct hash_lex_struct
{
@@ -376,25 +377,9 @@ int main(int argc,char **argv)
/* Broken up to indicate that it's not advice to you, gentle reader. */
printf("/*\n\n Do " "not " "edit " "this " "file " "directly!\n\n*/\n");
- printf("\
-/* Copyright (C) 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.\n\
- Copyright (C) 2008-2011 Oracle\n\
-\n\
- This program is free software; you can redistribute it and/or modify\n\
- it under the terms of the GNU General Public License as published by\n\
- the Free Software Foundation; version 2 of the License.\n\
-\n\
- This program is distributed in the hope that it will be useful,\n\
- but WITHOUT ANY WARRANTY; without even the implied warranty of\n\
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n\
- GNU General Public License for more details.\n\
-\n\
- You should have received a copy of the GNU General Public License\n\
- along with this program; see the file COPYING. If not, write to the\n\
- Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston\n\
- MA 02110-1301 USA. */\n\
-\n\
-");
+ puts("/*");
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
+ puts("*/");
/* Broken up to indicate that it's not advice to you, gentle reader. */
printf("/* Do " "not " "edit " "this " "file! This is generated by "
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 4bc2b2439b4..2804da8e7ae 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -324,8 +324,7 @@ ha_partition::~ha_partition()
for (i= 0; i < m_tot_parts; i++)
delete m_file[i];
}
- my_free(m_ordered_rec_buffer);
- m_ordered_rec_buffer= NULL;
+ destroy_record_priority_queue();
my_free(m_part_ids_sorted_by_num_of_records);
clear_handler_file();
@@ -2826,7 +2825,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
{
char *name_buffer_ptr;
int error= HA_ERR_INITIALIZATION;
- uint alloc_len;
handler **file;
char name_buff[FN_REFLEN];
bool is_not_tmp_table= (table_share->tmp_table == NO_TMP_TABLE);
@@ -2844,32 +2842,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
m_start_key.length= 0;
m_rec0= table->record[0];
m_rec_length= table_share->stored_rec_length;
- alloc_len= m_tot_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
- alloc_len+= table_share->max_key_length;
- if (!m_ordered_rec_buffer)
- {
- if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME))))
- {
- DBUG_RETURN(error);
- }
- {
- /*
- We set-up one record per partition and each record has 2 bytes in
- front where the partition id is written. This is used by ordered
- index_read.
- We also set-up a reference to the first record for temporary use in
- setting up the scan.
- */
- char *ptr= (char*)m_ordered_rec_buffer;
- uint i= 0;
- do
- {
- int2store(ptr, i);
- ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
- } while (++i < m_tot_parts);
- m_start_key.key= (const uchar*)ptr;
- }
- }
if (!m_part_ids_sorted_by_num_of_records)
{
if (!(m_part_ids_sorted_by_num_of_records=
@@ -2899,7 +2871,7 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
if (m_is_clone_of)
{
- uint i;
+ uint i, alloc_len;
DBUG_ASSERT(m_clone_mem_root);
/* Allocate an array of handler pointers for the partitions handlers. */
alloc_len= (m_tot_parts + 1) * sizeof(handler*);
@@ -2977,12 +2949,6 @@ int ha_partition::open(const char *name, int mode, uint test_if_locked)
being opened once.
*/
clear_handler_file();
- /*
- Initialize priority queue, initialized to reading forward.
- */
- if ((error= init_queue(&m_queue, m_tot_parts, (uint) PARTITION_BYTES_IN_POS,
- 0, key_rec_cmp, (void*)this, 0, 0)))
- goto err_handler;
/*
Use table_share->ha_part_data to share auto_increment_value among
@@ -3136,7 +3102,7 @@ int ha_partition::close(void)
DBUG_ENTER("ha_partition::close");
DBUG_ASSERT(table->s == table_share);
- delete_queue(&m_queue);
+ destroy_record_priority_queue();
bitmap_free(&m_bulk_insert_started);
if (!m_is_clone_of)
bitmap_free(&(m_part_info->used_partitions));
@@ -4436,6 +4402,78 @@ int ha_partition::rnd_pos_by_record(uchar *record)
subset of the partitions are used, then only use those partitions.
*/
+
+/**
+ Setup the ordered record buffer and the priority queue.
+*/
+
+bool ha_partition::init_record_priority_queue()
+{
+ DBUG_ENTER("ha_partition::init_record_priority_queue");
+ DBUG_ASSERT(!m_ordered_rec_buffer);
+ /*
+ Initialize the ordered record buffer.
+ */
+ if (!m_ordered_rec_buffer)
+ {
+ uint alloc_len;
+ uint used_parts= bitmap_bits_set(&m_part_info->used_partitions);
+ /* Allocate record buffer for each used partition. */
+ alloc_len= used_parts * (m_rec_length + PARTITION_BYTES_IN_POS);
+ /* Allocate a key for temporary use when setting up the scan. */
+ alloc_len+= table_share->max_key_length;
+
+ if (!(m_ordered_rec_buffer= (uchar*)my_malloc(alloc_len, MYF(MY_WME))))
+ DBUG_RETURN(true);
+
+ /*
+ We set-up one record per partition and each record has 2 bytes in
+ front where the partition id is written. This is used by ordered
+ index_read.
+ We also set-up a reference to the first record for temporary use in
+ setting up the scan.
+ */
+ char *ptr= (char*) m_ordered_rec_buffer;
+ uint16 i= 0;
+ do
+ {
+ if (bitmap_is_set(&m_part_info->used_partitions, i))
+ {
+ int2store(ptr, i);
+ ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
+ }
+ } while (++i < m_tot_parts);
+ m_start_key.key= (const uchar*)ptr;
+ /* Initialize priority queue, initialized to reading forward. */
+ if (init_queue(&m_queue, used_parts, (uint) PARTITION_BYTES_IN_POS,
+ 0, key_rec_cmp, (void*)m_curr_key_info, 0, 0))
+ {
+ my_free(m_ordered_rec_buffer);
+ m_ordered_rec_buffer= NULL;
+ DBUG_RETURN(true);
+ }
+ }
+ DBUG_RETURN(false);
+}
+
+
+/**
+ Destroy the ordered record buffer and the priority queue.
+*/
+
+void ha_partition::destroy_record_priority_queue()
+{
+ DBUG_ENTER("ha_partition::destroy_record_priority_queue");
+ if (m_ordered_rec_buffer)
+ {
+ delete_queue(&m_queue);
+ my_free(m_ordered_rec_buffer);
+ m_ordered_rec_buffer= NULL;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
/*
Initialize handler before start of index scan
@@ -4478,6 +4516,10 @@ int ha_partition::index_init(uint inx, bool sorted)
}
else
m_curr_key_info[1]= NULL;
+
+ if (init_record_priority_queue())
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM);
+
/*
Some handlers only read fields as specified by the bitmap for the
read set. For partitioned handlers we always require that the
@@ -4552,11 +4594,11 @@ int ha_partition::index_end()
do
{
int tmp;
- /* TODO RONM: Change to index_end() when code is stable */
if (bitmap_is_set(&(m_part_info->used_partitions), (file - m_file)))
if ((tmp= (*file)->ha_index_end()))
error= tmp;
} while (*(++file));
+ destroy_record_priority_queue();
DBUG_RETURN(error);
}
@@ -5268,6 +5310,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
uint i;
uint j= queue_first_element(&m_queue);
bool found= FALSE;
+ uchar *part_rec_buf_ptr= m_ordered_rec_buffer;
DBUG_ENTER("ha_partition::handle_ordered_index_scan");
m_top_entry= NO_CURRENT_PART_ID;
@@ -5278,7 +5321,7 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
{
if (!(bitmap_is_set(&(m_part_info->used_partitions), i)))
continue;
- uchar *rec_buf_ptr= rec_buf(i);
+ uchar *rec_buf_ptr= part_rec_buf_ptr + PARTITION_BYTES_IN_POS;
int error;
handler *file= m_file[i];
@@ -5325,12 +5368,13 @@ int ha_partition::handle_ordered_index_scan(uchar *buf, bool reverse_order)
/*
Initialize queue without order first, simply insert
*/
- queue_element(&m_queue, j++)= (uchar*)queue_buf(i);
+ queue_element(&m_queue, j++)= part_rec_buf_ptr;
}
else if (error != HA_ERR_KEY_NOT_FOUND && error != HA_ERR_END_OF_FILE)
{
DBUG_RETURN(error);
}
+ part_rec_buf_ptr+= m_rec_length + PARTITION_BYTES_IN_POS;
}
if (found)
{
@@ -5393,18 +5437,19 @@ int ha_partition::handle_ordered_next(uchar *buf, bool is_next_same)
{
int error;
uint part_id= m_top_entry;
+ uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS;
handler *file= m_file[part_id];
DBUG_ENTER("ha_partition::handle_ordered_next");
if (m_index_scan_type == partition_read_range)
{
error= file->read_range_next();
- memcpy(rec_buf(part_id), table->record[0], m_rec_length);
+ memcpy(rec_buf, table->record[0], m_rec_length);
}
else if (!is_next_same)
- error= file->ha_index_next(rec_buf(part_id));
+ error= file->ha_index_next(rec_buf);
else
- error= file->ha_index_next_same(rec_buf(part_id), m_start_key.key,
+ error= file->ha_index_next_same(rec_buf, m_start_key.key,
m_start_key.length);
if (error)
{
@@ -5447,10 +5492,11 @@ int ha_partition::handle_ordered_prev(uchar *buf)
{
int error;
uint part_id= m_top_entry;
+ uchar *rec_buf= queue_top(&m_queue) + PARTITION_BYTES_IN_POS;
handler *file= m_file[part_id];
DBUG_ENTER("ha_partition::handle_ordered_prev");
- if ((error= file->ha_index_prev(rec_buf(part_id))))
+ if ((error= file->ha_index_prev(rec_buf)))
{
if (error == HA_ERR_END_OF_FILE)
{
@@ -7570,23 +7616,6 @@ int ha_partition::indexes_are_disabled(void)
struct st_mysql_storage_engine partition_storage_engine=
{ MYSQL_HANDLERTON_INTERFACE_VERSION };
-mysql_declare_plugin(partition)
-{
- MYSQL_STORAGE_ENGINE_PLUGIN,
- &partition_storage_engine,
- "partition",
- "Mikael Ronstrom, MySQL AB",
- "Partition Storage Engine Helper",
- PLUGIN_LICENSE_GPL,
- partition_initialize, /* Plugin Init */
- NULL, /* Plugin Deinit */
- 0x0100, /* 1.0 */
- NULL, /* status variables */
- NULL, /* system variables */
- NULL, /* config options */
- 0, /* flags */
-}
-mysql_declare_plugin_end;
maria_declare_plugin(partition)
{
MYSQL_STORAGE_ENGINE_PLUGIN,
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index ee2bd0e39b9..3a0a35fdfc0 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -510,21 +510,13 @@ public:
virtual int read_range_next();
private:
+ bool init_record_priority_queue();
+ void destroy_record_priority_queue();
int common_index_read(uchar * buf, bool have_start_key);
int common_first_last(uchar * buf);
int partition_scan_set_up(uchar * buf, bool idx_read_flag);
int handle_unordered_next(uchar * buf, bool next_same);
int handle_unordered_scan_next_partition(uchar * buf);
- uchar *queue_buf(uint part_id)
- {
- return (m_ordered_rec_buffer +
- (part_id * (m_rec_length + PARTITION_BYTES_IN_POS)));
- }
- uchar *rec_buf(uint part_id)
- {
- return (queue_buf(part_id) +
- PARTITION_BYTES_IN_POS);
- }
int handle_ordered_index_scan(uchar * buf, bool reverse_order);
int handle_ordered_next(uchar * buf, bool next_same);
int handle_ordered_prev(uchar * buf);
diff --git a/sql/handler.cc b/sql/handler.cc
index 8041e457d03..ed671a921bb 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -4811,7 +4811,20 @@ int handler::read_range_first(const key_range *start_key,
DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND)
? HA_ERR_END_OF_FILE
: result);
- DBUG_RETURN (compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
+
+ if (compare_key(end_range) <= 0)
+ {
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ /*
+ The last read row does not fall in the range. So request
+ storage engine to release row lock if possible.
+ */
+ unlock_row();
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
}
@@ -4843,7 +4856,20 @@ int handler::read_range_next()
result= ha_index_next(table->record[0]);
if (result)
DBUG_RETURN(result);
- DBUG_RETURN(compare_key(end_range) <= 0 ? 0 : HA_ERR_END_OF_FILE);
+
+ if (compare_key(end_range) <= 0)
+ {
+ DBUG_RETURN(0);
+ }
+ else
+ {
+ /*
+ The last read row does not fall in the range. So request
+ storage engine to release row lock if possible.
+ */
+ unlock_row();
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
+ }
}
diff --git a/sql/item.cc b/sql/item.cc
index 13a4524f131..216ef628271 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -6837,7 +6837,7 @@ bool Item_ref::fix_fields(THD *thd, Item **reference)
if (from_field != not_found_field)
{
Item_field* fld;
- if (!(fld= new Item_field(thd, last_checked_context, from_field)))
+ if (!(fld= new Item_field(from_field)))
goto error;
thd->change_item_tree(reference, fld);
mark_as_dependent(thd, last_checked_context->select_lex,
@@ -9607,7 +9607,7 @@ table_map Item_direct_view_ref::used_tables() const
{
return get_depended_from() ?
OUTER_REF_TABLE_BIT :
- ((view->merged || !view->table) ?
+ ((view->is_merged_derived() || view->merged || !view->table) ?
(*ref)->used_tables() :
view->table->map);
}
@@ -9616,7 +9616,7 @@ table_map Item_direct_view_ref::not_null_tables() const
{
return get_depended_from() ?
0 :
- ((view->merged || !view->table) ?
+ ((view->is_merged_derived() || view->merged || !view->table) ?
(*ref)->not_null_tables() :
view->table->map);
}
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 4c0c81aa8c6..c2a7edb735a 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -3300,23 +3300,21 @@ err:
String* Item_func_export_set::val_str(String* str)
{
DBUG_ASSERT(fixed == 1);
- ulonglong the_set = (ulonglong) args[0]->val_int();
- String yes_buf, *yes;
- yes = args[1]->val_str(&yes_buf);
- String no_buf, *no;
- no = args[2]->val_str(&no_buf);
- String *sep = NULL, sep_buf ;
+ String yes_buf, no_buf, sep_buf;
+ const ulonglong the_set = (ulonglong) args[0]->val_int();
+ const String *yes= args[1]->val_str(&yes_buf);
+ const String *no= args[2]->val_str(&no_buf);
+ const String *sep= NULL;
uint num_set_values = 64;
- ulonglong mask = 0x1;
str->length(0);
str->set_charset(collation.collation);
/* Check if some argument is a NULL value */
if (args[0]->null_value || args[1]->null_value || args[2]->null_value)
{
- null_value=1;
- return 0;
+ null_value= true;
+ return NULL;
}
/*
Arg count can only be 3, 4 or 5 here. This is guaranteed from the
@@ -3329,37 +3327,56 @@ String* Item_func_export_set::val_str(String* str)
num_set_values=64;
if (args[4]->null_value)
{
- null_value=1;
- return 0;
+ null_value= true;
+ return NULL;
}
/* Fall through */
case 4:
if (!(sep = args[3]->val_str(&sep_buf))) // Only true if NULL
{
- null_value=1;
- return 0;
+ null_value= true;
+ return NULL;
}
break;
case 3:
{
/* errors is not checked - assume "," can always be converted */
uint errors;
- sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin, collation.collation, &errors);
+ sep_buf.copy(STRING_WITH_LEN(","), &my_charset_bin,
+ collation.collation, &errors);
sep = &sep_buf;
}
break;
default:
DBUG_ASSERT(0); // cannot happen
}
- null_value=0;
+ null_value= false;
+
+ const ulong max_allowed_packet= current_thd->variables.max_allowed_packet;
+ const uint num_separators= num_set_values > 0 ? num_set_values - 1 : 0;
+ const ulonglong max_total_length=
+ num_set_values * max(yes->length(), no->length()) +
+ num_separators * sep->length();
+
+ if (unlikely(max_total_length > max_allowed_packet))
+ {
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARN_ALLOWED_PACKET_OVERFLOWED,
+ ER(ER_WARN_ALLOWED_PACKET_OVERFLOWED),
+ func_name(), max_allowed_packet);
+ null_value= true;
+ return NULL;
+ }
- for (uint i = 0; i < num_set_values; i++, mask = (mask << 1))
+ uint ix;
+ ulonglong mask;
+ for (ix= 0, mask=0x1; ix < num_set_values; ++ix, mask = (mask << 1))
{
if (the_set & mask)
str->append(*yes);
else
str->append(*no);
- if (i != num_set_values - 1)
+ if (ix != num_separators)
str->append(*sep);
}
return str;
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index 83c7e3e1529..ab77bb0e59c 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -49,7 +49,7 @@ Item_subselect::Item_subselect():
used_tables_cache(0), have_to_be_excluded(0), const_item_cache(1),
inside_first_fix_fields(0), done_first_fix_fields(FALSE),
expr_cache(0), forced_const(FALSE), substitution(0), engine(0), eliminated(FALSE),
- engine_changed(0), changed(0), is_correlated(FALSE)
+ changed(0), is_correlated(FALSE)
{
DBUG_ENTER("Item_subselect::Item_subselect");
DBUG_PRINT("enter", ("this: 0x%lx", (ulong) this));
@@ -623,6 +623,8 @@ bool Item_subselect::walk(Item_processor processor, bool walk_subquery,
bool Item_subselect::exec()
{
+ subselect_engine *org_engine= engine;
+
DBUG_ENTER("Item_subselect::exec");
/*
@@ -644,11 +646,14 @@ bool Item_subselect::exec()
#ifndef DBUG_OFF
++exec_counter;
#endif
- if (engine_changed)
+ if (engine != org_engine)
{
- engine_changed= 0;
- res= exec();
- DBUG_RETURN(res);
+ /*
+ If the subquery engine changed during execution due to lazy subquery
+ optimization, or because the original engine found a more efficient other
+ engine, re-execute the subquery with the new engine.
+ */
+ DBUG_RETURN(exec());
}
DBUG_RETURN(res);
}
@@ -1063,11 +1068,9 @@ Item_singlerow_subselect::select_transformer(JOIN *join)
}
substitution= select_lex->item_list.head();
/*
- as far as we moved content to upper level, field which depend of
- 'upper' select is not really dependent => we remove this dependence
+ as far as we moved content to upper level we have to fix dependences & Co
*/
- substitution->walk(&Item::remove_dependence_processor, 0,
- (uchar *) select_lex->outer_select());
+ substitution->fix_after_pullout(select_lex->outer_select(), &substitution);
}
DBUG_RETURN(false);
}
@@ -2003,7 +2006,7 @@ Item_in_subselect::create_single_in_to_exists_cond(JOIN * join,
}
else
{
- Item *item= (Item*) select_lex->item_list.head();
+ Item *item= (Item*) select_lex->item_list.head()->real_item();
if (select_lex->table_list.elements)
{
@@ -3143,10 +3146,8 @@ int subselect_single_select_engine::exec()
DBUG_RETURN(1); /* purecov: inspected */
}
}
- if (item->engine_changed)
- {
+ if (item->engine_changed(this))
DBUG_RETURN(1);
- }
}
if (select_lex->uncacheable &&
select_lex->uncacheable != UNCACHEABLE_EXPLAIN
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 2a64c63a1be..1da129380e7 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -122,8 +122,6 @@ public:
*/
bool eliminated;
- /* changed engine indicator */
- bool engine_changed;
/* subquery is transformed */
bool changed;
@@ -200,9 +198,9 @@ public:
{
old_engine= engine;
engine= eng;
- engine_changed= 1;
return eng == 0;
}
+ bool engine_changed(subselect_engine *eng) { return engine != eng; }
/*
True if this subquery has been already evaluated. Implemented only for
single select and union subqueries only.
@@ -260,7 +258,6 @@ public:
st_select_lex*, st_select_lex*,
Field*, Item*, Item_ident*);
friend bool convert_join_subqueries_to_semijoins(JOIN *join);
-
};
/* single value subselect */
diff --git a/sql/log.cc b/sql/log.cc
index 5c21fa21f97..69ff68d335f 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -305,7 +305,7 @@ public:
before_stmt_pos= MY_OFF_T_UNDEF;
}
- void set_binlog_cache_info(ulong param_max_binlog_cache_size,
+ void set_binlog_cache_info(my_off_t param_max_binlog_cache_size,
ulong *param_ptr_binlog_cache_use,
ulong *param_ptr_binlog_cache_disk_use)
{
@@ -382,7 +382,7 @@ private:
is configured. This corresponds to either
. max_binlog_cache_size or max_binlog_stmt_cache_size.
*/
- ulong saved_max_binlog_cache_size;
+ my_off_t saved_max_binlog_cache_size;
/*
Stores a pointer to the status variable that keeps track of the in-memory
@@ -420,8 +420,8 @@ private:
class binlog_cache_mngr {
public:
- binlog_cache_mngr(ulong param_max_binlog_stmt_cache_size,
- ulong param_max_binlog_cache_size,
+ binlog_cache_mngr(my_off_t param_max_binlog_stmt_cache_size,
+ my_off_t param_max_binlog_cache_size,
ulong *param_ptr_binlog_stmt_cache_use,
ulong *param_ptr_binlog_stmt_cache_disk_use,
ulong *param_ptr_binlog_cache_use,
diff --git a/sql/mdl.cc b/sql/mdl.cc
index 0e30e44c19a..ce37f10128b 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -395,7 +395,8 @@ public:
bool has_pending_conflicting_lock(enum_mdl_type type);
- bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx) const;
+ bool can_grant_lock(enum_mdl_type type, MDL_context *requstor_ctx,
+ bool ignore_lock_priority) const;
inline static MDL_lock *create(const MDL_key *key);
@@ -409,14 +410,24 @@ public:
virtual bool needs_notification(const MDL_ticket *ticket) const = 0;
virtual void notify_conflicting_locks(MDL_context *ctx) = 0;
+ virtual bitmap_t hog_lock_types_bitmap() const = 0;
+
/** List of granted tickets for this lock. */
Ticket_list m_granted;
/** Tickets for contexts waiting to acquire a lock. */
Ticket_list m_waiting;
+
+ /**
+ Number of times high priority lock requests have been granted while
+ low priority lock requests were waiting.
+ */
+ ulong m_hog_lock_count;
+
public:
MDL_lock(const MDL_key *key_arg)
: key(key_arg),
+ m_hog_lock_count(0),
m_ref_usage(0),
m_ref_release(0),
m_is_destroyed(FALSE),
@@ -501,6 +512,15 @@ public:
}
virtual void notify_conflicting_locks(MDL_context *ctx);
+ /*
+ In scoped locks, only IX lock request would starve because of X/S. But that
+ is practically very rare case. So just return 0 from this function.
+ */
+ virtual bitmap_t hog_lock_types_bitmap() const
+ {
+ return 0;
+ }
+
private:
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
@@ -553,6 +573,18 @@ public:
}
virtual void notify_conflicting_locks(MDL_context *ctx);
+ /*
+ To prevent starvation, these lock types that are only granted
+ max_write_lock_count times in a row while other lock types are
+ waiting.
+ */
+ virtual bitmap_t hog_lock_types_bitmap() const
+ {
+ return (MDL_BIT(MDL_SHARED_NO_WRITE) |
+ MDL_BIT(MDL_SHARED_NO_READ_WRITE) |
+ MDL_BIT(MDL_EXCLUSIVE));
+ }
+
private:
static const bitmap_t m_granted_incompatible[MDL_TYPE_END];
static const bitmap_t m_waiting_incompatible[MDL_TYPE_END];
@@ -1285,6 +1317,41 @@ void MDL_lock::reschedule_waiters()
{
MDL_lock::Ticket_iterator it(m_waiting);
MDL_ticket *ticket;
+ bool skip_high_priority= false;
+ bitmap_t hog_lock_types= hog_lock_types_bitmap();
+
+ if (m_hog_lock_count >= max_write_lock_count)
+ {
+ /*
+ If number of successively granted high-prio, strong locks has exceeded
+ max_write_lock_count give a way to low-prio, weak locks to avoid their
+ starvation.
+ */
+
+ if ((m_waiting.bitmap() & ~hog_lock_types) != 0)
+ {
+ /*
+ Even though normally when m_hog_lock_count is non-0 there is
+ some pending low-prio lock, we still can encounter situation
+ when m_hog_lock_count is non-0 and there are no pending low-prio
+ locks. This, for example, can happen when a ticket for pending
+ low-prio lock was removed from waiters list due to timeout,
+ and reschedule_waiters() is called after that to update the
+ waiters queue. m_hog_lock_count will be reset to 0 at the
+ end of this call in such case.
+
+ Note that it is not an issue if we fail to wake up any pending
+ waiters for weak locks in the loop below. This would mean that
+ all of them are either killed, timed out or chosen as a victim
+ by deadlock resolver, but have not managed to remove ticket
+ from the waiters list yet. After tickets will be removed from
+ the waiters queue there will be another call to
+ reschedule_waiters() with pending bitmap updated to reflect new
+ state of waiters queue.
+ */
+ skip_high_priority= true;
+ }
+ }
/*
Find the first (and hence the oldest) waiting request which
@@ -1306,7 +1373,16 @@ void MDL_lock::reschedule_waiters()
*/
while ((ticket= it++))
{
- if (can_grant_lock(ticket->get_type(), ticket->get_ctx()))
+ /*
+ Skip high-prio, strong locks if earlier we have decided to give way to
+ low-prio, weaker locks.
+ */
+ if (skip_high_priority &&
+ ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0))
+ continue;
+
+ if (can_grant_lock(ticket->get_type(), ticket->get_ctx(),
+ skip_high_priority))
{
if (! ticket->get_ctx()->m_wait.set_status(MDL_wait::GRANTED))
{
@@ -1320,6 +1396,13 @@ void MDL_lock::reschedule_waiters()
*/
m_waiting.remove_ticket(ticket);
m_granted.add_ticket(ticket);
+
+ /*
+ Increase counter of successively granted high-priority strong locks,
+ if we have granted one.
+ */
+ if ((MDL_BIT(ticket->get_type()) & hog_lock_types) != 0)
+ m_hog_lock_count++;
}
/*
If we could not update the wait slot of the waiter,
@@ -1331,6 +1414,24 @@ void MDL_lock::reschedule_waiters()
*/
}
}
+
+ if ((m_waiting.bitmap() & ~hog_lock_types) == 0)
+ {
+ /*
+ Reset number of successively granted high-prio, strong locks
+ if there are no pending low-prio, weak locks.
+ This ensures:
+ - That m_hog_lock_count is correctly reset after strong lock
+ is released and weak locks are granted (or there are no
+ other lock requests).
+ - That situation when SNW lock is granted along with some SR
+ locks, but SW locks are still blocked are handled correctly.
+ - That m_hog_lock_count is zero in most cases when there are no pending
+ weak locks (see comment at the start of this method for example of
+ exception). This allows to save on checks at the start of this method.
+ */
+ m_hog_lock_count= 0;
+ }
}
@@ -1485,8 +1586,9 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] =
Check if request for the metadata lock can be satisfied given its
current state.
- @param type_arg The requested lock type.
- @param requestor_ctx The MDL context of the requestor.
+ @param type_arg The requested lock type.
+ @param requestor_ctx The MDL context of the requestor.
+ @param ignore_lock_priority Ignore lock priority.
@retval TRUE Lock request can be satisfied
@retval FALSE There is some conflicting lock.
@@ -1498,19 +1600,21 @@ MDL_object_lock::m_waiting_incompatible[MDL_TYPE_END] =
bool
MDL_lock::can_grant_lock(enum_mdl_type type_arg,
- MDL_context *requestor_ctx) const
+ MDL_context *requestor_ctx,
+ bool ignore_lock_priority) const
{
bool can_grant= FALSE;
bitmap_t waiting_incompat_map= incompatible_waiting_types_bitmap()[type_arg];
bitmap_t granted_incompat_map= incompatible_granted_types_bitmap()[type_arg];
+
/*
New lock request can be satisfied iff:
- There are no incompatible types of satisfied requests
in other contexts
- There are no waiting requests which have higher priority
- than this request.
+ than this request when priority was not ignored.
*/
- if (! (m_waiting.bitmap() & waiting_incompat_map))
+ if (ignore_lock_priority || !(m_waiting.bitmap() & waiting_incompat_map))
{
if (! (m_granted.bitmap() & granted_incompat_map))
can_grant= TRUE;
@@ -1806,7 +1910,7 @@ MDL_context::try_acquire_lock_impl(MDL_request *mdl_request,
ticket->m_lock= lock;
- if (lock->can_grant_lock(mdl_request->type, this))
+ if (lock->can_grant_lock(mdl_request->type, this, false))
{
lock->m_granted.add_ticket(ticket);
diff --git a/sql/mdl.h b/sql/mdl.h
index f816d160f7b..477f4df7807 100644
--- a/sql/mdl.h
+++ b/sql/mdl.h
@@ -876,4 +876,10 @@ extern mysql_mutex_t LOCK_open;
extern ulong mdl_locks_cache_size;
static const ulong MDL_LOCKS_CACHE_SIZE_DEFAULT = 1024;
+/*
+ Metadata locking subsystem tries not to grant more than
+ max_write_lock_count high-prio, strong locks successively,
+ to avoid starving out weak, low-prio locks.
+*/
+extern "C" ulong max_write_lock_count;
#endif
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 28eb0b7d756..d02d9194f3f 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -278,6 +278,8 @@ extern "C" sig_handler handle_fatal_signal(int sig);
/* Constants */
+#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
+
const char *show_comp_option_name[]= {"YES", "NO", "DISABLED"};
static const char *tc_heuristic_recover_names[]=
@@ -624,6 +626,21 @@ I_List<THD> threads;
Rpl_filter* rpl_filter;
Rpl_filter* binlog_filter;
+THD *first_global_thread()
+{
+ if (threads.is_empty())
+ return NULL;
+ return threads.head();
+}
+
+THD *next_global_thread(THD *thd)
+{
+ if (threads.is_last(thd))
+ return NULL;
+ struct ilink *next= thd->next;
+ return static_cast<THD*>(next);
+}
+
struct system_variables global_system_variables;
struct system_variables max_system_variables;
struct system_status_var global_status_var;
@@ -1809,6 +1826,7 @@ void clean_up(bool print_message)
my_tz_free();
my_dboptions_cache_free();
+ ignore_db_dirs_free();
#ifndef NO_EMBEDDED_ACCESS_CHECKS
servers_free(1);
acl_free(1);
@@ -3519,6 +3537,9 @@ static int init_common_variables()
mysql_init_variables())
return 1;
+ if (ignore_db_dirs_init())
+ return 1;
+
#ifdef HAVE_TZNAME
struct tm tm_tmp;
localtime_r(&server_start_time,&tm_tmp);
@@ -3952,6 +3973,12 @@ You should consider changing lower_case_table_names to 1 or 2",
files_charset_info :
&my_charset_bin);
+ if (ignore_db_dirs_process_additions())
+ {
+ sql_print_error("An error occurred while storing ignore_db_dirs to a hash.");
+ return 1;
+ }
+
return 0;
}
@@ -6420,7 +6447,7 @@ struct my_option my_long_options[]=
#ifdef HAVE_MMAP
{"log-tc-size", 0, "Size of transaction coordinator log.",
&opt_tc_log_size, &opt_tc_log_size, 0, GET_ULONG,
- REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (longlong) ULONG_MAX, 0,
+ REQUIRED_ARG, TC_LOG_MIN_SIZE, TC_LOG_MIN_SIZE, (ulonglong) ULONG_MAX, 0,
TC_LOG_PAGE_SIZE, 0},
#endif
{"master-info-file", 0,
@@ -7157,6 +7184,7 @@ SHOW_VAR status_vars[]= {
{"Aborted_clients", (char*) &aborted_threads, SHOW_LONG},
{"Aborted_connects", (char*) &aborted_connects, SHOW_LONG},
{"Access_denied_errors", (char*) offsetof(STATUS_VAR, access_denied_errors), SHOW_LONG_STATUS},
+ {"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
{"Binlog_cache_disk_use", (char*) &binlog_cache_disk_use, SHOW_LONG},
{"Binlog_cache_use", (char*) &binlog_cache_use, SHOW_LONG},
{"Binlog_stmt_cache_disk_use",(char*) &binlog_stmt_cache_disk_use, SHOW_LONG},
@@ -7164,7 +7192,6 @@ SHOW_VAR status_vars[]= {
{"Busy_time", (char*) offsetof(STATUS_VAR, busy_time), SHOW_DOUBLE_STATUS},
{"Bytes_received", (char*) offsetof(STATUS_VAR, bytes_received), SHOW_LONGLONG_STATUS},
{"Bytes_sent", (char*) offsetof(STATUS_VAR, bytes_sent), SHOW_LONGLONG_STATUS},
- {"Binlog_bytes_written", (char*) offsetof(STATUS_VAR, binlog_bytes_written), SHOW_LONGLONG_STATUS},
{"Com", (char*) com_status_vars, SHOW_ARRAY},
{"Compression", (char*) &show_net_compression, SHOW_SIMPLE_FUNC},
{"Connections", (char*) &thread_id, SHOW_LONG_NOFLUSH},
@@ -7193,11 +7220,9 @@ SHOW_VAR status_vars[]= {
{"Handler_external_lock", (char*) offsetof(STATUS_VAR, ha_external_lock_count), SHOW_LONGLONG_STATUS},
{"Handler_icp_attempts", (char*) offsetof(STATUS_VAR, ha_icp_attempts), SHOW_LONG_STATUS},
{"Handler_icp_match", (char*) offsetof(STATUS_VAR, ha_icp_match), SHOW_LONG_STATUS},
-
{"Handler_mrr_init", (char*) offsetof(STATUS_VAR, ha_mrr_init_count), SHOW_LONG_STATUS},
{"Handler_mrr_key_refills", (char*) offsetof(STATUS_VAR, ha_mrr_key_refills_count), SHOW_LONG_STATUS},
{"Handler_mrr_rowid_refills", (char*) offsetof(STATUS_VAR, ha_mrr_rowid_refills_count), SHOW_LONG_STATUS},
-
{"Handler_prepare", (char*) offsetof(STATUS_VAR, ha_prepare_count), 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},
@@ -7227,8 +7252,8 @@ SHOW_VAR status_vars[]= {
{"Opened_tables", (char*) offsetof(STATUS_VAR, opened_tables), SHOW_LONG_STATUS},
{"Opened_views", (char*) offsetof(STATUS_VAR, opened_views), SHOW_LONG_STATUS},
{"Prepared_stmt_count", (char*) &show_prepared_stmt_count, SHOW_SIMPLE_FUNC},
- {"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
{"Rows_read", (char*) offsetof(STATUS_VAR, rows_read), SHOW_LONGLONG_STATUS},
+ {"Rows_sent", (char*) offsetof(STATUS_VAR, rows_sent), SHOW_LONGLONG_STATUS},
{"Rows_tmp_read", (char*) offsetof(STATUS_VAR, rows_tmp_read), SHOW_LONGLONG_STATUS},
#ifdef HAVE_QUERY_CACHE
{"Qcache_free_blocks", (char*) &query_cache.free_memory_blocks, SHOW_LONG_NOFLUSH},
@@ -7252,9 +7277,9 @@ SHOW_VAR status_vars[]= {
{"Select_scan", (char*) offsetof(STATUS_VAR, select_scan_count_), SHOW_LONG_STATUS},
{"Slave_open_temp_tables", (char*) &slave_open_temp_tables, SHOW_LONG},
#ifdef HAVE_REPLICATION
- {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG},
{"Slave_heartbeat_period", (char*) &show_heartbeat_period, SHOW_SIMPLE_FUNC},
{"Slave_received_heartbeats",(char*) &show_slave_received_heartbeats, SHOW_SIMPLE_FUNC},
+ {"Slave_retried_transactions",(char*)&slave_retried_transactions, SHOW_LONG},
{"Slave_running", (char*) &show_slave_running, SHOW_SIMPLE_FUNC},
#endif
{"Slow_launch_threads", (char*) &slow_launch_threads, SHOW_LONG},
@@ -7389,14 +7414,8 @@ static void usage(void)
if (!default_collation_name)
default_collation_name= (char*) default_charset_info->name;
print_version();
- puts("\
-Copyright (C) 2000-2008 MySQL AB, by Monty and others.\n\
-Copyright (C) 2000, 2011 Oracle.\n\
-Copyright (C) 2009-2011 Monty Program Ab.\n\
-This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
-and you are welcome to modify and redistribute it under the GPL license\n\n\
-Starts the MariaDB database server.\n");
-
+ puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
+ puts("Starts the MariaDB database server.\n");
printf("Usage: %s [OPTIONS]\n", my_progname);
if (!opt_verbose)
puts("\nFor more help options (several pages), use mysqld --verbose --help.");
@@ -7956,6 +7975,20 @@ mysqld_get_one_option(int optid,
if (argument == NULL) /* no argument */
log_error_file_ptr= const_cast<char*>("");
break;
+ case OPT_IGNORE_DB_DIRECTORY:
+ if (*argument == 0)
+ ignore_db_dirs_reset();
+ else
+ {
+ if (push_ignored_db_dir(argument))
+ {
+ sql_print_error("Can't start server: "
+ "cannot process --ignore-db-dir=%.*s",
+ FN_REFLEN, argument);
+ return 1;
+ }
+ }
+ break;
case OPT_MAX_LONG_DATA_SIZE:
max_long_data_size_used= true;
break;
@@ -8024,7 +8057,6 @@ mysqld_get_one_option(int optid,
"'%s'", argument);
return 0;
}
-
#endif
break;
}
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 67fa44fe7d9..eaf22954cc4 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -497,20 +497,25 @@ enum options_mysqld
OPT_BINLOG_FORMAT,
OPT_BINLOG_IGNORE_DB,
OPT_BIN_LOG,
- OPT_LOG_BASENAME,
OPT_BOOTSTRAP,
OPT_CONSOLE,
OPT_DEBUG_SYNC_TIMEOUT,
OPT_DELAY_KEY_WRITE_ALL,
OPT_DEPRECATED_OPTION,
+ OPT_ENGINE_CONDITION_PUSHDOWN,
+ OPT_IGNORE_DB_DIRECTORY,
OPT_ISAM_LOG,
OPT_KEY_BUFFER_SIZE,
OPT_KEY_CACHE_AGE_THRESHOLD,
OPT_KEY_CACHE_BLOCK_SIZE,
OPT_KEY_CACHE_DIVISION_LIMIT,
OPT_KEY_CACHE_PARTITIONS,
+ OPT_LOG_BASENAME,
+ OPT_LOG_ERROR,
OPT_LOWER_CASE_TABLE_NAMES,
+ OPT_MAX_LONG_DATA_SIZE,
OPT_ONE_THREAD,
+ OPT_PFS_INSTRUMENT,
OPT_POOL_OF_THREADS,
OPT_REPLICATE_DO_DB,
OPT_REPLICATE_DO_TABLE,
@@ -532,15 +537,12 @@ enum options_mysqld
OPT_SSL_CAPATH,
OPT_SSL_CERT,
OPT_SSL_CIPHER,
+ OPT_SSL_CRL,
+ OPT_SSL_CRLPATH,
OPT_SSL_KEY,
OPT_UPDATE_LOG,
OPT_WANT_CORE,
- OPT_ENGINE_CONDITION_PUSHDOWN,
- OPT_LOG_ERROR,
- OPT_MAX_LONG_DATA_SIZE,
- OPT_SSL_CRL,
- OPT_SSL_CRLPATH,
- OPT_PFS_INSTRUMENT
+ OPT_which_is_always_the_last
};
#endif
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 994b3f75989..5cf3a29a4b7 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -3853,27 +3853,28 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
ppar->cur_subpart_fields+= ppar->is_subpart_keypart[key_tree_part];
*(ppar->arg_stack_end++)= key_tree;
+ if (ignore_part_fields)
+ {
+ /*
+ We come here when a condition on the first partitioning
+ fields led to evaluating the partitioning condition
+ (due to finding a condition of the type a < const or
+ b > const). Thus we must ignore the rest of the
+ partitioning fields but we still want to analyse the
+ subpartitioning fields.
+ */
+ if (key_tree->next_key_part)
+ res= find_used_partitions(ppar, key_tree->next_key_part);
+ else
+ res= -1;
+ goto pop_and_go_right;
+ }
+
if (key_tree->type == SEL_ARG::KEY_RANGE)
{
if (ppar->part_info->get_part_iter_for_interval &&
key_tree->part <= ppar->last_part_partno)
{
- if (ignore_part_fields)
- {
- /*
- We come here when a condition on the first partitioning
- fields led to evaluating the partitioning condition
- (due to finding a condition of the type a < const or
- b > const). Thus we must ignore the rest of the
- partitioning fields but we still want to analyse the
- subpartitioning fields.
- */
- if (key_tree->next_key_part)
- res= find_used_partitions(ppar, key_tree->next_key_part);
- else
- res= -1;
- goto pop_and_go_right;
- }
/* Collect left and right bound, their lengths and flags */
uchar *min_key= ppar->cur_min_key;
uchar *max_key= ppar->cur_max_key;
@@ -4114,6 +4115,13 @@ int find_used_partitions(PART_PRUNE_PARAM *ppar, SEL_ARG *key_tree)
res= -1;
goto pop_and_go_right;
}
+ /*
+ No meaning in continuing with rest of partitioning key parts.
+ Will try to continue with subpartitioning key parts.
+ */
+ ppar->ignore_part_fields= true;
+ did_set_ignore_part_fields= true;
+ goto process_next_key_part;
}
}
diff --git a/sql/scheduler.cc b/sql/scheduler.cc
index 78a1a2a32bb..0ae4121ef4c 100644
--- a/sql/scheduler.cc
+++ b/sql/scheduler.cc
@@ -79,11 +79,34 @@ void scheduler_init() {
scheduler_wait_sync_end);
}
+
+/**
+ Kill notification callback, used by one-thread-per-connection
+ and threadpool scheduler.
+
+ Wakes up a thread that is stuck in read/poll/epoll/event-poll
+ routines used by threadpool, such that subsequent attempt to
+ read from client connection will result in IO error.
+*/
+
+void post_kill_notification(THD *thd)
+{
+ DBUG_ENTER("post_kill_notification");
+ if (current_thd == thd || thd->system_thread)
+ DBUG_VOID_RETURN;
+
+ if (thd->net.vio)
+ vio_shutdown(thd->net.vio, SHUT_RD);
+ DBUG_VOID_RETURN;
+}
+
/*
Initialize scheduler for --thread-handling=one-thread-per-connection
*/
#ifndef EMBEDDED_LIBRARY
+
+
void one_thread_per_connection_scheduler(scheduler_functions *func,
ulong *arg_max_connections,
uint *arg_connection_count)
@@ -95,6 +118,7 @@ void one_thread_per_connection_scheduler(scheduler_functions *func,
func->init_new_connection_thread= init_new_connection_handler_thread;
func->add_connection= create_thread_to_handle_connection;
func->end_thread= one_thread_per_connection_end;
+ func->post_kill_notification= post_kill_notification;
}
#endif
diff --git a/sql/scheduler.h b/sql/scheduler.h
index 82bba5abe65..4e200e86d74 100644
--- a/sql/scheduler.h
+++ b/sql/scheduler.h
@@ -78,7 +78,7 @@ void one_thread_per_connection_scheduler(scheduler_functions *func,
void one_thread_scheduler(scheduler_functions *func);
extern void scheduler_init();
-
+extern void post_kill_notification(THD *);
/*
To be used for pool-of-threads (implemeneted differently on various OSs)
*/
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 1276dd28e22..bf18ca49b37 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -130,9 +130,9 @@ void sys_var_end()
put your additional checks here
@param on_update_func a function to be called at the end of sys_var::update,
any post-update activity should happen here
- @param deprecated_version if not 0 - when this variable will go away
- @param substitute if not 0 - what one should use instead when this
- deprecated variable
+ @param substitute If non-NULL, this variable is deprecated and the
+ string describes what one should use instead. If an empty string,
+ the variable is deprecated but no replacement is offered.
*/
sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
const char *comment, int flags_arg, ptrdiff_t off,
@@ -141,11 +141,12 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
PolyLock *lock, enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func,
on_update_function on_update_func,
- uint deprecated_version, const char *substitute) :
+ const char *substitute) :
next(0),
binlog_status(binlog_status_arg),
flags(flags_arg), show_val_type(show_val_type_arg),
guard(lock), offset(off), on_check(on_check_func), on_update(on_update_func),
+ deprecation_substitute(substitute),
is_os_charset(FALSE)
{
/*
@@ -171,12 +172,6 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
option.value= (uchar **)global_var_ptr();
option.def_value= def_val;
- deprecated.version= deprecated_version;
- deprecated.substitute= substitute;
- DBUG_ASSERT((deprecated_version != 0) || (substitute == 0));
- DBUG_ASSERT(deprecated_version % 100 == 0);
- DBUG_ASSERT(!deprecated_version || MYSQL_VERSION_ID < deprecated_version);
-
if (chain->last)
chain->last->next= this;
else
@@ -271,21 +266,24 @@ bool sys_var::set_default(THD *thd, enum_var_type type)
void sys_var::do_deprecated_warning(THD *thd)
{
- if (deprecated.version)
+ if (deprecation_substitute != NULL)
{
- char buf1[NAME_CHAR_LEN + 3], buf2[10];
+ char buf1[NAME_CHAR_LEN + 3];
strxnmov(buf1, sizeof(buf1)-1, "@@", name.str, 0);
- my_snprintf(buf2, sizeof(buf2), "%d.%d", deprecated.version/100/100,
- deprecated.version/100%100);
- uint errmsg= deprecated.substitute
- ? ER_WARN_DEPRECATED_SYNTAX_WITH_VER
- : ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT;
+
+ /*
+ if deprecation_substitute is an empty string,
+ there is no replacement for the syntax
+ */
+ uint errmsg= deprecation_substitute[0] == '\0'
+ ? ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT
+ : ER_WARN_DEPRECATED_SYNTAX;
if (thd)
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DEPRECATED_SYNTAX, ER(errmsg),
- buf1, buf2, deprecated.substitute);
+ buf1, deprecation_substitute);
else
- sql_print_warning(ER_DEFAULT(errmsg), buf1, buf2, deprecated.substitute);
+ sql_print_warning(ER_DEFAULT(errmsg), buf1, deprecation_substitute);
}
}
diff --git a/sql/set_var.h b/sql/set_var.h
index dcb60ba0bdf..52c68a4031e 100644
--- a/sql/set_var.h
+++ b/sql/set_var.h
@@ -81,7 +81,7 @@ protected:
ptrdiff_t offset; ///< offset to the value from global_system_variables
on_check_function on_check;
on_update_function on_update;
- struct { uint version; const char *substitute; } deprecated;
+ const char *const deprecation_substitute;
bool is_os_charset; ///< true if the value is in character_set_filesystem
public:
@@ -90,7 +90,7 @@ public:
enum get_opt_arg_type getopt_arg_type, SHOW_TYPE show_val_type_arg,
longlong def_val, PolyLock *lock, enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func, on_update_function on_update_func,
- uint deprecated_version, const char *substitute);
+ const char *substitute);
virtual ~sys_var() {}
diff --git a/sql/share/charsets/Index.xml b/sql/share/charsets/Index.xml
index 80b844e2f19..f32d8bf6127 100644
--- a/sql/share/charsets/Index.xml
+++ b/sql/share/charsets/Index.xml
@@ -3,7 +3,7 @@
<charsets max-id="99">
<copyright>
- Copyright (C) 2003 MySQL AB
+ Copyright (c) 2003, 2012, Oracle and/or its affiliates.
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
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 5a298b4d25c..49f35719a77 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6343,8 +6343,8 @@ ER_INSIDE_TRANSACTION_PREVENTS_SWITCH_BINLOG_FORMAT
ER_PATH_LENGTH
eng "The path specified for %.64s is too long."
ER_WARN_DEPRECATED_SYNTAX_NO_REPLACEMENT
- eng "The syntax '%s' is deprecated and will be removed in MariaDB %s."
- ger "Die Syntax '%s' ist veraltet und wird in MariaDB %s entfernt."
+ eng "'%s' is deprecated and will be removed in a future release."
+ ger "'%s' ist veraltet und wird in einer zukünftigen Version entfernt werden."
ER_WRONG_NATIVE_TABLE_STRUCTURE
eng "Native table '%-.64s'.'%-.64s' has the wrong structure"
diff --git a/sql/spatial.cc b/sql/spatial.cc
index e82eec26fdb..de0b563eaf4 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -601,7 +601,8 @@ uint Gis_line_string::init_from_wkb(const char *wkb, uint len,
Gis_point p;
if (len < 4 ||
- (n_points= wkb_get_uint(wkb, bo))<1)
+ (n_points= wkb_get_uint(wkb, bo)) < 1 ||
+ n_points > max_n_points)
return 0;
proper_length= 4 + n_points * POINT_DATA_SIZE;
@@ -1334,9 +1335,9 @@ uint Gis_multi_point::init_from_wkb(const char *wkb, uint len, wkbByteOrder bo,
Gis_point p;
const char *wkb_end;
- if (len < 4)
+ if (len < 4 ||
+ (n_points= wkb_get_uint(wkb, bo)) > max_n_points)
return 0;
- n_points= wkb_get_uint(wkb, bo);
proper_size= 4 + n_points * (WKB_HEADER_SIZE + POINT_DATA_SIZE);
if (len < proper_size || res->reserve(proper_size))
diff --git a/sql/spatial.h b/sql/spatial.h
index 07675d59040..1277e7bc01c 100644
--- a/sql/spatial.h
+++ b/sql/spatial.h
@@ -391,6 +391,10 @@ public:
class Gis_line_string: public Geometry
{
+ // Maximum number of points in LineString that can fit into String
+ static const uint32 max_n_points=
+ (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
+ POINT_DATA_SIZE;
public:
Gis_line_string() {} /* Remove gcc warning */
virtual ~Gis_line_string() {} /* Remove gcc warning */
@@ -451,6 +455,10 @@ public:
class Gis_multi_point: public Geometry
{
+ // Maximum number of points in MultiPoint that can fit into String
+ static const uint32 max_n_points=
+ (uint32) (UINT_MAX32 - WKB_HEADER_SIZE - 4 /* n_points */) /
+ (WKB_HEADER_SIZE + POINT_DATA_SIZE);
public:
Gis_multi_point() {} /* Remove gcc warning */
virtual ~Gis_multi_point() {} /* Remove gcc warning */
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index feb4e43eb51..db926061406 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -5059,8 +5059,6 @@ restart:
*/
if (thd->locked_tables_mode <= LTM_LOCK_TABLES)
{
- bool need_prelocking= FALSE;
- TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
/*
Process elements of the prelocking set which are present there
since parsing stage or were added to it by invocations of
@@ -5073,10 +5071,19 @@ restart:
for (Sroutine_hash_entry *rt= *sroutine_to_open; rt;
sroutine_to_open= &rt->next, rt= rt->next)
{
+ bool need_prelocking= false;
+ TABLE_LIST **save_query_tables_last= thd->lex->query_tables_last;
+
error= open_and_process_routine(thd, thd->lex, rt, prelocking_strategy,
has_prelocking_list, &ot_ctx,
&need_prelocking);
+ if (need_prelocking && ! thd->lex->requires_prelocking())
+ thd->lex->mark_as_requiring_prelocking(save_query_tables_last);
+
+ if (need_prelocking && ! *start)
+ *start= thd->lex->query_tables;
+
if (error)
{
if (ot_ctx.can_recover_from_failed_open())
@@ -5097,12 +5104,6 @@ restart:
goto err;
}
}
-
- if (need_prelocking && ! thd->lex->requires_prelocking())
- thd->lex->mark_as_requiring_prelocking(save_query_tables_last);
-
- if (need_prelocking && ! *start)
- *start= thd->lex->query_tables;
}
}
@@ -5375,6 +5376,12 @@ static bool check_lock_and_start_stmt(THD *thd,
DBUG_ENTER("check_lock_and_start_stmt");
/*
+ Prelocking placeholder is not set for TABLE_LIST that
+ are directly used by TOP level statement.
+ */
+ DBUG_ASSERT(table_list->prelocking_placeholder == false);
+
+ /*
TL_WRITE_DEFAULT and TL_READ_DEFAULT are supposed to be parser only
types of locks so they should be converted to appropriate other types
to be passed to storage engine. The exact lock type passed to the
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index ba1d46ec3cc..fc5653750f3 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -275,6 +275,64 @@ bool Foreign_key::validate(List<Create_field> &table_fields)
/****************************************************************************
** Thread specific functions
****************************************************************************/
+#ifdef ONLY_FOR_MYSQL_CLOSED_SOURCE_SCHEDULED
+/**
+ Get reference to scheduler data object
+
+ @param thd THD object
+
+ @retval Scheduler data object on THD
+*/
+void *thd_get_scheduler_data(THD *thd)
+{
+ return thd->scheduler.data;
+}
+
+/**
+ Set reference to Scheduler data object for THD object
+
+ @param thd THD object
+ @param psi Scheduler data object to set on THD
+*/
+void thd_set_scheduler_data(THD *thd, void *data)
+{
+ thd->scheduler.data= data;
+}
+
+/**
+ Get reference to Performance Schema object for THD object
+
+ @param thd THD object
+
+ @retval Performance schema object for thread on THD
+*/
+PSI_thread *thd_get_psi(THD *thd)
+{
+ return thd->scheduler.m_psi;
+}
+
+/**
+ Get net_wait_timeout for THD object
+
+ @param thd THD object
+
+ @retval net_wait_timeout value for thread on THD
+*/
+ulong thd_get_net_wait_timeout(THD* thd)
+{
+ return thd->variables.net_wait_timeout;
+}
+
+/**
+ Set reference to Performance Schema object for THD object
+
+ @param thd THD object
+ @param psi Performance schema object for thread
+*/
+void thd_set_psi(THD *thd, PSI_thread *psi)
+{
+ thd->scheduler.m_psi= psi;
+}
/**
Set the state on connection to killed
@@ -407,6 +465,17 @@ void thd_set_net_read_write(THD *thd, uint val)
}
/**
+ Get reading/writing on socket from THD object
+ @param thd THD object
+
+ @retval net.reading_or_writing value for thread on THD.
+*/
+uint thd_get_net_read_write(THD *thd)
+{
+ return thd->net.reading_or_writing;
+}
+
+/**
Set reference to mysys variable in THD object
@param thd THD object
@@ -428,6 +497,7 @@ my_socket thd_get_fd(THD *thd)
{
return mysql_socket_getfd(thd->net.vio->mysql_socket);
}
+#endif
/**
Get thread attributes for connection threads
diff --git a/sql/sql_join_cache.cc b/sql/sql_join_cache.cc
index 4148842a826..1f375bf1a03 100644
--- a/sql/sql_join_cache.cc
+++ b/sql/sql_join_cache.cc
@@ -681,7 +681,23 @@ void JOIN_CACHE::set_constants()
uint len= length + fields*sizeof(uint)+blobs*sizeof(uchar *) +
(prev_cache ? prev_cache->get_size_of_rec_offset() : 0) +
sizeof(ulong);
- buff_size= max(join->thd->variables.join_buff_size, 2*len);
+ /*
+ The values of size_of_rec_ofs, size_of_rec_len, size_of_fld_ofs,
+ base_prefix_length, pack_length, pack_length_with_blob_ptrs
+ will be recalculated later in this function when we get the estimate
+ for the actual value of the join buffer size.
+ */
+ size_of_rec_ofs= size_of_rec_len= size_of_fld_ofs= 4;
+ base_prefix_length= (with_length ? size_of_rec_len : 0) +
+ (prev_cache ? prev_cache->get_size_of_rec_offset() : 0);
+ pack_length= (with_length ? size_of_rec_len : 0) +
+ (prev_cache ? prev_cache->get_size_of_rec_offset() : 0) +
+ length + fields*sizeof(uint);
+ pack_length_with_blob_ptrs= pack_length + blobs*sizeof(uchar *);
+ min_buff_size= 0;
+ min_records= 1;
+ buff_size= max(join->thd->variables.join_buff_size,
+ get_min_join_buffer_size());
size_of_rec_ofs= offset_size(buff_size);
size_of_rec_len= blobs ? size_of_rec_ofs : offset_size(len);
size_of_fld_ofs= size_of_rec_len;
@@ -754,19 +770,24 @@ ulong JOIN_CACHE::get_min_join_buffer_size()
if (!min_buff_size)
{
size_t len= 0;
+ size_t len_last= 0;
for (JOIN_TAB *tab= start_tab; tab != join_tab;
tab= next_linear_tab(join, tab, WITHOUT_BUSH_ROOTS))
{
len+= tab->get_max_used_fieldlength();
+ len_last=+ tab->get_used_fieldlength();
}
- len+= get_record_max_affix_length() + get_max_key_addon_space_per_record();
- size_t min_sz= len*min_records;
+ size_t len_addon= get_record_max_affix_length() +
+ get_max_key_addon_space_per_record();
+ len+= len_addon;
+ len_last+= len_addon;
+ size_t min_sz= len*(min_records-1) + len_last;
+ min_sz+= pack_length_with_blob_ptrs;
size_t add_sz= 0;
for (uint i=0; i < min_records; i++)
add_sz+= join_tab_scan->aux_buffer_incr(i+1);
avg_aux_buffer_incr= add_sz/min_records;
min_sz+= add_sz;
- min_sz+= pack_length_with_blob_ptrs;
set_if_bigger(min_sz, 1);
min_buff_size= min_sz;
}
diff --git a/sql/sql_list.h b/sql/sql_list.h
index e3a04c36071..2b2d9e59771 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -667,6 +667,9 @@ public:
inline void empty() { first= &last; last.prev= &first; }
base_ilist() { empty(); }
inline bool is_empty() { return first == &last; }
+ // Returns true if p is the last "real" object in the list,
+ // i.e. p->next points to the sentinel.
+ inline bool is_last(ilink *p) { return p->next == NULL || p->next == &last; }
inline void append(ilink *a)
{
first->prev= &a->next;
@@ -742,6 +745,7 @@ class I_List :private base_ilist
{
public:
I_List() :base_ilist() {}
+ inline bool is_last(T *p) { return base_ilist::is_last(p); }
inline void empty() { base_ilist::empty(); }
inline bool is_empty() { return base_ilist::is_empty(); }
inline void append(T* a) { base_ilist::append(a); }
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index f19b8ca26ef..e15f6339847 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -274,7 +274,7 @@ public:
(plugin_var_arg->flags & PLUGIN_VAR_THDLOCAL ? SESSION : GLOBAL) |
(plugin_var_arg->flags & PLUGIN_VAR_READONLY ? READONLY : 0),
0, -1, NO_ARG, pluginvar_show_type(plugin_var_arg), 0, 0,
- VARIABLE_NOT_IN_BINLOG, 0, 0, 0, 0),
+ VARIABLE_NOT_IN_BINLOG, NULL, NULL, NULL),
plugin_var(plugin_var_arg), orig_pluginvar_name(plugin_var_arg->name)
{ plugin_var->name= name_arg; }
sys_var_pluginvar *cast_pluginvar() { return this; }
@@ -2159,7 +2159,8 @@ static bool do_uninstall(THD *thd, TABLE *table, const LEX_STRING *name)
struct st_plugin_int *plugin;
mysql_mutex_assert_owner(&LOCK_plugin);
- if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)))
+ if (!(plugin= plugin_find_internal(name, MYSQL_ANY_PLUGIN)) ||
+ plugin->state & (PLUGIN_IS_UNINITIALIZED | PLUGIN_IS_DYING))
{
my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PLUGIN", name->str);
return 1;
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 75611a054f0..969e6ee4574 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -878,6 +878,14 @@ static bool insert_params_with_log(Prepared_statement *stmt, uchar *null_array,
param->set_param_func(param, &read_pos, (uint) (data_end - read_pos));
if (param->state == Item_param::NO_VALUE)
DBUG_RETURN(1);
+
+ if (param->limit_clause_param && param->item_type != Item::INT_ITEM)
+ {
+ param->set_int(param->val_int(), MY_INT64_NUM_DECIMAL_DIGITS);
+ param->item_type= Item::INT_ITEM;
+ if (!param->unsigned_flag && param->value.integer < 0)
+ DBUG_RETURN(1);
+ }
}
}
/*
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index a1c0b2d8729..762a7769acf 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -365,6 +365,8 @@ inline int hexchar_to_int(char c)
#define IS_TABLESPACES_NODEGROUP_ID 7
#define IS_TABLESPACES_TABLESPACE_COMMENT 8
+bool db_name_is_in_ignore_db_dirs_list(const char *dbase);
+
#endif /* MYSQL_SERVER */
#endif /* MYSQL_CLIENT */
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index ba44aba33b9..89d6e993b1d 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -764,8 +764,6 @@ JOIN::prepare(Item ***rref_pointer_array,
if (having)
{
- Query_arena backup, *arena;
- arena= thd->activate_stmt_arena_if_needed(&backup);
nesting_map save_allow_sum_func= thd->lex->allow_sum_func;
thd->where="having clause";
thd->lex->allow_sum_func|= 1 << select_lex_arg->nest_level;
@@ -781,9 +779,6 @@ JOIN::prepare(Item ***rref_pointer_array,
(having->fix_fields(thd, &having) ||
having->check_cols(1)));
select_lex->having_fix_field= 0;
- select_lex->having= having;
- if (arena)
- thd->restore_active_arena(arena, &backup);
if (having_fix_rc || thd->is_error())
DBUG_RETURN(-1); /* purecov: inspected */
@@ -1738,12 +1733,19 @@ JOIN::optimize_inner()
DBUG_RETURN(1);
}
}
-
+ /*
+ Calculate a possible 'limit' of table rows for 'GROUP BY': 'need_tmp'
+ implies that there will be more postprocessing so the specified
+ 'limit' should not be enforced yet in the call to
+ 'test_if_skip_sort_order'.
+ */
+ const ha_rows limit = need_tmp ? HA_POS_ERROR : unit->select_limit_cnt;
+
if (!(select_options & SELECT_BIG_RESULT) &&
((group_list &&
(!simple_group ||
!test_if_skip_sort_order(&join_tab[const_tables], group_list,
- unit->select_limit_cnt, 0,
+ limit, 0,
&join_tab[const_tables].table->
keys_in_use_for_group_by))) ||
select_distinct) &&
@@ -4016,8 +4018,10 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
new_fields->null_rejecting);
}
else if (old->eq_func && new_fields->eq_func &&
- ((old->val->const_item() && old->val->is_null()) ||
- new_fields->val->is_null()))
+ ((old->val->const_item() && !old->val->is_expensive() &&
+ old->val->is_null()) ||
+ (!new_fields->val->is_expensive() &&
+ new_fields->val->is_null())))
{
/* field = expression OR field IS NULL */
old->level= and_level;
@@ -4031,7 +4035,8 @@ merge_key_fields(KEY_FIELD *start,KEY_FIELD *new_fields,KEY_FIELD *end,
Remember the NOT NULL value unless the value does not depend
on other tables.
*/
- if (!old->val->used_tables() && old->val->is_null())
+ if (!old->val->used_tables() && !old->val->is_expensive() &&
+ old->val->is_null())
old->val= new_fields->val;
}
else
@@ -8163,6 +8168,7 @@ get_store_key(THD *thd, KEYUSE *keyuse, table_map used_tables,
key_part->length,
((Item_field*) keyuse->val->real_item())->field,
keyuse->val->real_item()->full_name());
+
return new store_key_item(thd,
key_part->field,
key_buff + maybe_null,
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 2a82ae115a0..73d441a2d9d 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -414,6 +414,281 @@ bool mysqld_show_privileges(THD *thd)
}
+/** Hash of LEX_STRINGs used to search for ignored db directories. */
+static HASH ignore_db_dirs_hash;
+
+/**
+ An array of LEX_STRING pointers to collect the options at
+ option parsing time.
+*/
+static DYNAMIC_ARRAY ignore_db_dirs_array;
+
+/**
+ A value for the read only system variable to show a list of
+ ignored directories.
+*/
+char *opt_ignore_db_dirs= NULL;
+
+/**
+ This flag is ON if:
+ - the list of ignored directories is not empty
+
+ - and some of the ignored directory names
+ need no tablename-to-filename conversion.
+ Otherwise, if the name of the directory contains
+ unconditional characters like '+' or '.', they
+ never can match the database directory name. So the
+ db_name_is_in_ignore_db_dirs_list() can just return at once.
+*/
+static bool skip_ignored_dir_check= TRUE;
+
+/**
+ Sets up the data structures for collection of directories at option
+ processing time.
+ We need to collect the directories in an array first, because
+ we need the character sets initialized before setting up the hash.
+
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+bool
+ignore_db_dirs_init()
+{
+ return my_init_dynamic_array(&ignore_db_dirs_array, sizeof(LEX_STRING *),
+ 0, 0);
+}
+
+
+/**
+ Retrieves the key (the string itself) from the LEX_STRING hash members.
+
+ Needed by hash_init().
+
+ @param data the data element from the hash
+ @param out len_ret Placeholder to return the length of the key
+ @param unused
+ @return a pointer to the key
+*/
+
+static uchar *
+db_dirs_hash_get_key(const uchar *data, size_t *len_ret,
+ my_bool __attribute__((unused)))
+{
+ LEX_STRING *e= (LEX_STRING *) data;
+
+ *len_ret= e->length;
+ return (uchar *) e->str;
+}
+
+
+/**
+ Wrap a directory name into a LEX_STRING and push it to the array.
+
+ Called at option processing time for each --ignore-db-dir option.
+
+ @param path the name of the directory to push
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+bool
+push_ignored_db_dir(char *path)
+{
+ LEX_STRING *new_elt;
+ char *new_elt_buffer;
+ size_t path_len= strlen(path);
+
+ if (!path_len || path_len >= FN_REFLEN)
+ return true;
+
+ // No need to normalize, it's only a directory name, not a path.
+ if (!my_multi_malloc(0,
+ &new_elt, sizeof(LEX_STRING),
+ &new_elt_buffer, path_len + 1,
+ NullS))
+ return true;
+ new_elt->str= new_elt_buffer;
+ memcpy(new_elt_buffer, path, path_len);
+ new_elt_buffer[path_len]= 0;
+ new_elt->length= path_len;
+ return insert_dynamic(&ignore_db_dirs_array, (uchar*) &new_elt);
+}
+
+
+/**
+ Clean up the directory ignore options accumulated so far.
+
+ Called at option processing time for each --ignore-db-dir option
+ with an empty argument.
+*/
+
+void
+ignore_db_dirs_reset()
+{
+ LEX_STRING **elt;
+ while (NULL!= (elt= (LEX_STRING **) pop_dynamic(&ignore_db_dirs_array)))
+ if (elt && *elt)
+ my_free(*elt);
+}
+
+
+/**
+ Free the directory ignore option variables.
+
+ Called at server shutdown.
+*/
+
+void
+ignore_db_dirs_free()
+{
+ if (opt_ignore_db_dirs)
+ {
+ my_free(opt_ignore_db_dirs);
+ opt_ignore_db_dirs= NULL;
+ }
+ ignore_db_dirs_reset();
+ delete_dynamic(&ignore_db_dirs_array);
+ my_hash_free(&ignore_db_dirs_hash);
+}
+
+
+/**
+ Initialize the ignore db directories hash and status variable from
+ the options collected in the array.
+
+ Called when option processing is over and the server's in-memory
+ structures are fully initialized.
+
+ @return state
+ @retval TRUE failed
+ @retval FALSE success
+*/
+
+static void dispose_db_dir(void *ptr)
+{
+ my_free(ptr);
+}
+
+
+bool
+ignore_db_dirs_process_additions()
+{
+ ulong i;
+ size_t len;
+ char *ptr;
+ LEX_STRING *dir;
+
+
+ skip_ignored_dir_check= TRUE;
+
+ if (my_hash_init(&ignore_db_dirs_hash,
+ lower_case_table_names ?
+ character_set_filesystem : &my_charset_bin,
+ 0, 0, 0, db_dirs_hash_get_key,
+ dispose_db_dir,
+ HASH_UNIQUE))
+ return true;
+
+ /* len starts from 1 because of the terminating zero. */
+ len= 1;
+ for (i= 0; i < ignore_db_dirs_array.elements; i++)
+ {
+ get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ len+= dir->length + 1; // +1 for the comma
+ if (skip_ignored_dir_check)
+ {
+ char buff[FN_REFLEN];
+ (void) tablename_to_filename(dir->str, buff, sizeof(buff));
+ skip_ignored_dir_check= strcmp(dir->str, buff) != 0;
+ }
+ }
+
+ /* No delimiter for the last directory. */
+ if (len > 1)
+ len--;
+
+ /* +1 the terminating zero */
+ ptr= opt_ignore_db_dirs= (char *) my_malloc(len + 1, MYF(0));
+ if (!ptr)
+ return true;
+
+ /* Make sure we have an empty string to start with. */
+ *ptr= 0;
+
+ for (i= 0; i < ignore_db_dirs_array.elements; i++)
+ {
+ get_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ if (my_hash_insert(&ignore_db_dirs_hash, (uchar *) dir))
+ return true;
+ ptr= strnmov(ptr, dir->str, dir->length);
+ if (i + 1 < ignore_db_dirs_array.elements)
+ ptr= strmov(ptr, ",");
+
+ /*
+ Set the transferred array element to NULL to avoid double free
+ in case of error.
+ */
+ dir= NULL;
+ set_dynamic(&ignore_db_dirs_array, (uchar *) &dir, i);
+ }
+
+ /* make sure the string is terminated */
+ DBUG_ASSERT(ptr - opt_ignore_db_dirs <= (ptrdiff_t) len);
+ *ptr= 0;
+
+ /*
+ It's OK to empty the array here as the allocated elements are
+ referenced through the hash now.
+ */
+ reset_dynamic(&ignore_db_dirs_array);
+
+ return false;
+}
+
+
+/**
+ Check if a directory name is in the hash of ignored directories.
+
+ @return search result
+ @retval TRUE found
+ @retval FALSE not found
+*/
+
+static inline bool
+is_in_ignore_db_dirs_list(const char *directory)
+{
+ return ignore_db_dirs_hash.records &&
+ NULL != my_hash_search(&ignore_db_dirs_hash, (const uchar *) directory,
+ strlen(directory));
+}
+
+
+/**
+ Check if a database name is in the hash of ignored directories.
+
+ @return search result
+ @retval TRUE found
+ @retval FALSE not found
+*/
+
+bool
+db_name_is_in_ignore_db_dirs_list(const char *directory)
+{
+ char buff[FN_REFLEN];
+ uint buff_len;
+
+ if (skip_ignored_dir_check)
+ return 0;
+
+ buff_len= tablename_to_filename(directory, buff, sizeof(buff));
+
+ return my_hash_search(&ignore_db_dirs_hash, (uchar *) buff, buff_len)!=NULL;
+}
+
+
/*
find_files() - find files in a given directory.
@@ -499,6 +774,9 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
if (!MY_S_ISDIR(file->mystat->st_mode))
continue;
+ if (is_in_ignore_db_dirs_list(file->name))
+ continue;
+
file_name_len= filename_to_tablename(file->name, uname, sizeof(uname));
if (wild)
{
diff --git a/sql/sql_show.h b/sql/sql_show.h
index 7541ed58e48..03d8af3aabd 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -158,4 +158,12 @@ public:
void call_in_target_thread();
};
+/* Handle the ignored database directories list for SHOW/I_S. */
+bool ignore_db_dirs_init();
+void ignore_db_dirs_free();
+void ignore_db_dirs_reset();
+bool ignore_db_dirs_process_additions();
+bool push_ignored_db_dir(char *path);
+extern char *opt_ignore_db_dirs;
+
#endif /* SQL_SHOW_H */
diff --git a/sql/sql_string.h b/sql/sql_string.h
index 2f0cd9103dc..8b09d449c2b 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -2,8 +2,8 @@
#define SQL_STRING_INCLUDED
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
- Copyright (c) 2008-2011 Monty Program Ab
+ Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2008, 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
@@ -279,8 +279,11 @@ public:
}
return realloc_with_extra(arg_length);
}
- inline void shrink(uint32 arg_length) // Shrink buffer
+ // Shrink the buffer, but only if it is allocated on the heap.
+ inline void shrink(uint32 arg_length)
{
+ if (!is_alloced())
+ return;
if (ALIGN_SIZE(arg_length+1) < Alloced_length)
{
char *new_ptr;
@@ -296,7 +299,7 @@ public:
}
}
}
- bool is_alloced() { return alloced; }
+ bool is_alloced() const { return alloced; }
inline String& operator = (const String &s)
{
if (&s != this)
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index 02f7fc0601c..193447156c0 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -51,6 +51,7 @@
#include <myisam.h>
#include "log_slow.h"
#include "debug_sync.h" // DEBUG_SYNC
+#include "sql_show.h"
#include "log_event.h"
#ifdef WITH_PERFSCHEMA_STORAGE_ENGINE
@@ -771,14 +772,14 @@ static Sys_var_ulong Sys_connect_timeout(
static Sys_var_charptr Sys_datadir(
"datadir", "Path to the database root directory",
READ_ONLY GLOBAL_VAR(mysql_real_data_home_ptr),
- CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(0));
+ CMD_LINE(REQUIRED_ARG, 'h'), IN_FS_CHARSET, DEFAULT(mysql_real_data_home));
#ifndef DBUG_OFF
static Sys_var_dbug Sys_dbug(
"debug", "Built-in DBUG debugger", sys_var::SESSION,
CMD_LINE(OPT_ARG, '#'), DEFAULT(""), NO_MUTEX_GUARD, NOT_IN_BINLOG,
ON_CHECK(check_has_super), ON_UPDATE(0),
- DEPRECATED(100100, "'@@debug_dbug'"));
+ DEPRECATED("'@@debug_dbug'"));
static Sys_var_dbug Sys_debug_dbug(
"debug_dbug", "Built-in DBUG debugger", sys_var::SESSION,
@@ -1438,7 +1439,7 @@ static Sys_var_harows Sys_sql_max_join_size(
SESSION_VAR(max_join_size), NO_CMD_LINE,
VALID_RANGE(1, HA_POS_ERROR), DEFAULT(HA_POS_ERROR), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(fix_max_join_size), DEPRECATED(100100, "'@@max_join_size'"));
+ ON_UPDATE(fix_max_join_size), DEPRECATED("'@@max_join_size'"));
static Sys_var_ulong Sys_max_long_data_size(
"max_long_data_size",
@@ -1881,7 +1882,7 @@ static Sys_var_ulong Sys_rpl_recovery_rank(
GLOBAL_VAR(rpl_recovery_rank), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(0, ULONG_MAX), DEFAULT(0), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0),
- DEPRECATED(100100, 0));
+ DEPRECATED(""));
static Sys_var_ulong Sys_range_alloc_block_size(
"range_alloc_block_size",
@@ -1895,7 +1896,7 @@ static Sys_var_ulong Sys_multi_range_count(
SESSION_VAR(multi_range_count), CMD_LINE(REQUIRED_ARG),
VALID_RANGE(1, ULONG_MAX), DEFAULT(256), BLOCK_SIZE(1),
NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0), ON_UPDATE(0),
- DEPRECATED(100100, "'@@mrr_buffer_size'"));
+ DEPRECATED("'@@mrr_buffer_size'"));
static bool fix_thd_mem_root(sys_var *self, THD *thd, enum_var_type type)
{
@@ -2679,7 +2680,7 @@ static Sys_var_mybool Sys_engine_condition_pushdown(
CMD_LINE(OPT_ARG, OPT_ENGINE_CONDITION_PUSHDOWN),
DEFAULT(TRUE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(NULL),
ON_UPDATE(fix_engine_condition_pushdown),
- DEPRECATED(100100, "'@@optimizer_switch'"));
+ DEPRECATED("'@@optimizer_switch'"));
static Sys_var_plugin Sys_default_storage_engine(
"default_storage_engine", "The default storage engine for new tables",
@@ -3361,7 +3362,7 @@ static Sys_var_mybool Sys_log(
"log", "Alias for --general-log. Deprecated",
GLOBAL_VAR(opt_log), NO_CMD_LINE,
DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(fix_log_state), DEPRECATED(100100, "'@@general_log'"));
+ ON_UPDATE(fix_log_state), DEPRECATED("'@@general_log'"));
static Sys_var_mybool Sys_slow_query_log(
"slow_query_log",
@@ -3378,7 +3379,7 @@ static Sys_var_mybool Sys_log_slow(
"Alias for --slow-query-log. Deprecated",
GLOBAL_VAR(opt_slow_log), NO_CMD_LINE,
DEFAULT(FALSE), NO_MUTEX_GUARD, NOT_IN_BINLOG, ON_CHECK(0),
- ON_UPDATE(fix_log_state), DEPRECATED(100100, "'@@slow_query_log'"));
+ ON_UPDATE(fix_log_state), DEPRECATED("'@@slow_query_log'"));
static bool fix_log_state(sys_var *self, THD *thd, enum_var_type type)
{
@@ -3816,6 +3817,15 @@ static Sys_var_tz Sys_time_zone(
SESSION_VAR(time_zone), NO_CMD_LINE,
DEFAULT(&default_tz), NO_MUTEX_GUARD, IN_BINLOG);
+static Sys_var_charptr Sys_ignore_db_dirs(
+ "ignore_db_dirs",
+ "Specifies a directory to add to the ignore list when collecting "
+ "database names from the datadir. Put a blank argument to reset "
+ "the list accumulated so far.",
+ READ_ONLY GLOBAL_VAR(opt_ignore_db_dirs),
+ CMD_LINE(REQUIRED_ARG, OPT_IGNORE_DB_DIRECTORY),
+ IN_FS_CHARSET, DEFAULT(0));
+
static Sys_var_ulong Sys_sp_cache_size(
"stored_program_cache",
"The soft upper limit for number of cached stored routines for "
diff --git a/sql/sys_vars.h b/sql/sys_vars.h
index 54ae4025a65..98a2b4c17fb 100644
--- a/sql/sys_vars.h
+++ b/sql/sys_vars.h
@@ -61,7 +61,7 @@
@@foreign_key_checks <-> OPTION_NO_FOREIGN_KEY_CHECKS
*/
#define REVERSE(X) ~(X)
-#define DEPRECATED(X, Y) X, Y
+#define DEPRECATED(X) X
#define session_var(THD, TYPE) (*(TYPE*)session_var_ptr(THD))
#define global_var(TYPE) (*(TYPE*)global_var_ptr())
@@ -128,10 +128,10 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOWT, def_val, lock, binlog_status_arg,
- on_check_func, on_update_func, deprecated_version, substitute)
+ on_check_func, on_update_func, substitute)
{
option.var_type= ARGT;
option.min_value= min_val;
@@ -240,11 +240,11 @@ public:
ulonglong def_val, PolyLock *lock,
enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func, on_update_function on_update_func,
- uint deprecated_version, const char *substitute)
+ const char *substitute)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, show_val_type_arg, def_val, lock,
binlog_status_arg, on_check_func,
- on_update_func, deprecated_version, substitute)
+ on_update_func, substitute)
{
for (typelib.count= 0; values[typelib.count]; typelib.count++) /*no-op */;
typelib.name="";
@@ -307,11 +307,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_CHAR, values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_ENUM;
global_var(ulong)= def_val;
@@ -354,11 +354,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_MY_BOOL, bool_values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_BOOL;
global_var(my_bool)= def_val;
@@ -409,11 +409,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR_PTR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
/*
@@ -504,7 +504,7 @@ public:
: sys_var(&all_sys_vars, name_arg, comment,
sys_var::READONLY+sys_var::ONLY_SESSION, 0, -1,
NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
- NULL, NULL, 0, NULL)
+ NULL, NULL, NULL)
{
is_os_charset= is_os_charset_arg == IN_FS_CHARSET;
option.var_type= GET_STR;
@@ -563,7 +563,7 @@ public:
Sys_var_rpl_filter(const char *name, int getopt_id, const char *comment)
: sys_var(&all_sys_vars, name, comment, sys_var::GLOBAL, 0, -1,
NO_ARG, SHOW_CHAR, 0, NULL, VARIABLE_NOT_IN_BINLOG,
- NULL, NULL, 0, NULL), opt_id(getopt_id)
+ NULL, NULL, NULL), opt_id(getopt_id)
{
option.var_type= GET_STR;
}
@@ -617,10 +617,10 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_charptr(name_arg, comment, flag_args, off, sizeof(char*),
getopt, is_os_charset_arg, def_val, lock, binlog_status_arg,
- on_check_func, on_update_func, deprecated_version, substitute)
+ on_check_func, on_update_func, substitute)
{
global_var(LEX_STRING).length= strlen(def_val);
SYSVAR_ASSERT(size == sizeof(LEX_STRING));
@@ -655,7 +655,7 @@ public:
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
0, VARIABLE_NOT_IN_BINLOG, on_check_func, on_update_func,
- 0, 0),max_length(max_length_arg)
+ 0),max_length(max_length_arg)
{
option.var_type= GET_NO_ARG;
SYSVAR_ASSERT(scope() == ONLY_SESSION)
@@ -744,11 +744,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{ option.var_type= GET_NO_ARG; }
bool do_check(THD *thd, set_var *var)
{
@@ -828,11 +828,11 @@ public:
enum binlog_status_enum binlog_status_arg,
on_check_function on_check_func,
keycache_update_function on_update_func,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_ulonglong(name_arg, comment, flag_args, off, size,
getopt, min_val, max_val, def_val,
block_size, lock, binlog_status_arg, on_check_func, 0,
- deprecated_version, substitute),
+ substitute),
keycache_update(on_update_func)
{
option.var_type|= GET_ASK_ADDR;
@@ -989,11 +989,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_DOUBLE, (longlong) double2ulonglong(def_val),
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_DOUBLE;
option.min_value= (longlong) double2ulonglong(min_val);
@@ -1053,11 +1053,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_int(name_arg, comment, SESSION, off, size, getopt,
min_val, max_val, def_val, block_size,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{ }
uchar *session_value_ptr(THD *thd, LEX_STRING *base)
{
@@ -1094,11 +1094,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_CHAR, values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_FLAGSET;
global_var(ulonglong)= def_val;
@@ -1205,11 +1205,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_CHAR, values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_SET;
global_var(ulonglong)= def_val;
@@ -1311,11 +1311,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute),
+ substitute),
plugin_type(plugin_type_arg)
{
option.var_type= GET_STR;
@@ -1424,11 +1424,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, 0, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
SYSVAR_ASSERT(scope() == ONLY_SESSION);
option.var_type= GET_NO_ARG;
@@ -1517,11 +1517,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_typelib(name_arg, comment, flag_args, off, getopt,
SHOW_MY_BOOL, bool_values, def_val, lock,
binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
option.var_type= GET_BOOL;
reverse_semantics= my_count_bits(bitmask_arg) > 1;
@@ -1590,11 +1590,11 @@ public:
on_check_function on_check_func,
session_special_update_function update_func_arg,
session_special_read_function read_func_arg,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_ulonglong(name_arg, comment, flag_args, 0,
sizeof(ulonglong), getopt, min_val,
max_val, 0, block_size, lock, binlog_status_arg, on_check_func, 0,
- deprecated_version, substitute),
+ substitute),
read_func(read_func_arg), update_func(update_func_arg)
{
SYSVAR_ASSERT(scope() == ONLY_SESSION);
@@ -1640,11 +1640,11 @@ public:
on_check_function on_check_func,
session_special_update_function update_func_arg,
session_special_read_function read_func_arg,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: Sys_var_double(name_arg, comment, flag_args, 0,
sizeof(double), getopt, min_val,
max_val, 0, lock, binlog_status_arg, on_check_func, 0,
- deprecated_version, substitute),
+ substitute),
read_func(read_func_arg), update_func(update_func_arg)
{
SYSVAR_ASSERT(scope() == ONLY_SESSION);
@@ -1694,11 +1694,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, 0,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
SYSVAR_ASSERT(scope() == GLOBAL);
SYSVAR_ASSERT(getopt.id == -1);
@@ -1762,11 +1762,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute),
+ substitute),
name_offset(name_off)
{
option.var_type= GET_STR;
@@ -1834,11 +1834,11 @@ public:
enum binlog_status_enum binlog_status_arg=VARIABLE_NOT_IN_BINLOG,
on_check_function on_check_func=0,
on_update_function on_update_func=0,
- uint deprecated_version=0, const char *substitute=0)
+ const char *substitute=0)
: sys_var(&all_sys_vars, name_arg, comment, flag_args, off, getopt.id,
getopt.arg_type, SHOW_CHAR, (intptr)def_val,
lock, binlog_status_arg, on_check_func, on_update_func,
- deprecated_version, substitute)
+ substitute)
{
SYSVAR_ASSERT(getopt.id == -1);
SYSVAR_ASSERT(size == sizeof(Time_zone *));
diff --git a/sql/table.cc b/sql/table.cc
index f033c08553a..18aaed6d81f 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -3444,6 +3444,9 @@ bool check_db_name(LEX_STRING *org_name)
if (lower_case_table_names && name != any_db)
my_casedn_str(files_charset_info, name);
+ if (db_name_is_in_ignore_db_dirs_list(name))
+ return 1;
+
return check_table_name(name, name_length, check_for_path_chars);
}
@@ -4968,7 +4971,16 @@ TABLE *TABLE_LIST::get_real_join_table()
tbl= (tbl->view != NULL ?
tbl->view->select_lex.get_table_list() :
tbl->derived->first_select()->get_table_list());
+
+ /* find left table in outer join on this level */
+ while(tbl->outer_join & JOIN_TYPE_RIGHT)
+ {
+ DBUG_ASSERT(tbl->next_local);
+ tbl= tbl->next_local;
+ }
+
}
+
return tbl->table;
}
diff --git a/sql/table.h b/sql/table.h
index 458d661ceb5..1f546693fb3 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -1900,6 +1900,7 @@ struct TABLE_LIST
/* TRUE <=> derived table should be filled right after optimization. */
bool fill_me;
/* TRUE <=> view/DT is merged. */
+ /* TODO: replace with derived_type */
bool merged;
bool merged_for_insert;
/* TRUE <=> don't prepare this derived table/view as it should be merged.*/
diff --git a/sql/threadpool_common.cc b/sql/threadpool_common.cc
index 7e5bbd11c69..6b956768287 100644
--- a/sql/threadpool_common.cc
+++ b/sql/threadpool_common.cc
@@ -257,7 +257,7 @@ static scheduler_functions tp_scheduler_functions=
tp_add_connection, // add_connection
tp_wait_begin, // thd_wait_begin
tp_wait_end, // thd_wait_end
- tp_post_kill_notification, // post_kill_notification
+ post_kill_notification, // post_kill_notification
NULL, // end_thread
tp_end // end
};
diff --git a/sql/threadpool_unix.cc b/sql/threadpool_unix.cc
index 60c3ad69c65..13deb167d9b 100644
--- a/sql/threadpool_unix.cc
+++ b/sql/threadpool_unix.cc
@@ -173,7 +173,6 @@ static int create_worker(thread_group_t *thread_group);
static void *worker_main(void *param);
static void check_stall(thread_group_t *thread_group);
static void connection_abort(connection_t *connection);
-void tp_post_kill_notification(THD *thd);
static void set_wait_timeout(connection_t *connection);
static void set_next_timeout_check(ulonglong abstime);
static void print_pool_blocked_message(bool);
@@ -444,7 +443,7 @@ static void timeout_check(pool_timer_t *timer)
/* Wait timeout exceeded, kill connection. */
mysql_mutex_lock(&thd->LOCK_thd_data);
thd->killed = KILL_CONNECTION;
- tp_post_kill_notification(thd);
+ post_kill_notification(thd);
mysql_mutex_unlock(&thd->LOCK_thd_data);
}
else
@@ -1259,21 +1258,6 @@ static void connection_abort(connection_t *connection)
/**
- MySQL scheduler callback : kill connection
-*/
-
-void tp_post_kill_notification(THD *thd)
-{
- DBUG_ENTER("tp_post_kill_notification");
- if (current_thd == thd || thd->system_thread)
- DBUG_VOID_RETURN;
-
- if (thd->net.vio)
- vio_shutdown(thd->net.vio, SHUT_RD);
- DBUG_VOID_RETURN;
-}
-
-/**
MySQL scheduler callback: wait begin
*/
diff --git a/sql/threadpool_win.cc b/sql/threadpool_win.cc
index 7bf4d98d16d..9cef1af272c 100644
--- a/sql/threadpool_win.cc
+++ b/sql/threadpool_win.cc
@@ -544,22 +544,6 @@ void tp_end(void)
}
}
-/**
- Notify pool about connection being killed.
-*/
-void tp_post_kill_notification(THD *thd)
-{
- if (current_thd == thd)
- return; /* There is nothing to do.*/
-
- if (thd->system_thread)
- return; /* Will crash if we attempt to kill system thread. */
-
- Vio *vio= thd->net.vio;
-
- vio_shutdown(vio, SD_BOTH);
-
-}
/*
Handle read completion/notification.