summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2011-06-06 16:17:58 +0300
committerGeorgi Kodinov <Georgi.Kodinov@Oracle.com>2011-06-06 16:17:58 +0300
commit455c676792b9e86746afd9567cfef2b8abcff0fb (patch)
treee7595cefaa0afdcedf56e8168738706d0b83f841 /sql
parent8ae2bb6eaaa5e2bf99390e498e5efe3090eb1d46 (diff)
parentaf78e87de36f0c10ce009b2bd9c856642ef1ab99 (diff)
downloadmariadb-git-455c676792b9e86746afd9567cfef2b8abcff0fb.tar.gz
merged mysql-5.5->mysql-5.5-security
Diffstat (limited to 'sql')
-rw-r--r--sql/debug_sync.cc32
-rw-r--r--sql/debug_sync.h2
-rw-r--r--sql/derror.cc21
-rw-r--r--sql/event_db_repository.cc20
-rw-r--r--sql/event_db_repository.h3
-rw-r--r--sql/events.cc57
-rw-r--r--sql/field.cc19
-rw-r--r--sql/ha_ndbcluster.cc7
-rw-r--r--sql/ha_ndbcluster_binlog.cc15
-rw-r--r--sql/ha_partition.cc55
-rw-r--r--sql/ha_partition.h4
-rw-r--r--sql/handler.cc9
-rw-r--r--sql/handler.h51
-rw-r--r--sql/item.cc58
-rw-r--r--sql/item_create.cc18
-rw-r--r--sql/item_func.cc16
-rw-r--r--sql/item_strfunc.cc8
-rw-r--r--sql/item_timefunc.cc9
-rw-r--r--sql/log.cc34
-rw-r--r--sql/log.h12
-rw-r--r--sql/log_event.cc1
-rw-r--r--sql/mdl.cc6
-rw-r--r--sql/my_decimal.cc11
-rw-r--r--sql/my_decimal.h3
-rw-r--r--sql/mysqld.cc88
-rw-r--r--sql/mysqld.h8
-rw-r--r--sql/password.c32
-rw-r--r--sql/rpl_rli.cc14
-rw-r--r--sql/scheduler.cc27
-rw-r--r--sql/scheduler.h15
-rw-r--r--sql/set_var.cc7
-rw-r--r--sql/share/errmsg-utf8.txt3
-rw-r--r--sql/sp_head.cc18
-rw-r--r--sql/sp_head.h2
-rw-r--r--sql/sql_acl.cc144
-rw-r--r--sql/sql_audit.cc32
-rw-r--r--sql/sql_base.cc4
-rw-r--r--sql/sql_binlog.cc4
-rw-r--r--sql/sql_class.cc278
-rw-r--r--sql/sql_class.h19
-rw-r--r--sql/sql_connect.cc48
-rw-r--r--sql/sql_connect.h2
-rw-r--r--sql/sql_cursor.h2
-rw-r--r--sql/sql_insert.cc7
-rw-r--r--sql/sql_load.cc5
-rw-r--r--sql/sql_parse.cc90
-rw-r--r--sql/sql_partition.cc2
-rw-r--r--sql/sql_plugin.cc13
-rw-r--r--sql/sql_prepare.cc32
-rw-r--r--sql/sql_reload.cc2
-rw-r--r--sql/sql_repl.cc2
-rw-r--r--sql/sql_show.cc346
-rw-r--r--sql/sql_table.cc67
-rw-r--r--sql/sql_yacc.yy20
-rw-r--r--sql/sys_vars.cc10
-rw-r--r--sql/table.cc18
-rw-r--r--sql/unireg.cc18
57 files changed, 1330 insertions, 520 deletions
diff --git a/sql/debug_sync.cc b/sql/debug_sync.cc
index 4f353597d6d..7f69ae54037 100644
--- a/sql/debug_sync.cc
+++ b/sql/debug_sync.cc
@@ -1745,11 +1745,20 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
We don't use enter_cond()/exit_cond(). They do not save old
mutex and cond. This would prohibit the use of DEBUG_SYNC
between other places of enter_cond() and exit_cond().
+
+ We need to check for existence of thd->mysys_var to also make
+ it possible to use DEBUG_SYNC framework in scheduler when this
+ variable has been set to NULL.
*/
- old_mutex= thd->mysys_var->current_mutex;
- old_cond= thd->mysys_var->current_cond;
- thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex;
- thd->mysys_var->current_cond= &debug_sync_global.ds_cond;
+ if (thd->mysys_var)
+ {
+ old_mutex= thd->mysys_var->current_mutex;
+ old_cond= thd->mysys_var->current_cond;
+ thd->mysys_var->current_mutex= &debug_sync_global.ds_mutex;
+ thd->mysys_var->current_cond= &debug_sync_global.ds_cond;
+ }
+ else
+ old_mutex= NULL;
set_timespec(abstime, action->timeout);
DBUG_EXECUTE("debug_sync_exec", {
@@ -1804,11 +1813,16 @@ static void debug_sync_execute(THD *thd, st_debug_sync_action *action)
is locked. (See comment in THD::exit_cond().)
*/
mysql_mutex_unlock(&debug_sync_global.ds_mutex);
- mysql_mutex_lock(&thd->mysys_var->mutex);
- thd->mysys_var->current_mutex= old_mutex;
- thd->mysys_var->current_cond= old_cond;
- thd_proc_info(thd, old_proc_info);
- mysql_mutex_unlock(&thd->mysys_var->mutex);
+ if (old_mutex)
+ {
+ mysql_mutex_lock(&thd->mysys_var->mutex);
+ thd->mysys_var->current_mutex= old_mutex;
+ thd->mysys_var->current_cond= old_cond;
+ thd_proc_info(thd, old_proc_info);
+ mysql_mutex_unlock(&thd->mysys_var->mutex);
+ }
+ else
+ thd_proc_info(thd, old_proc_info);
}
else
{
diff --git a/sql/debug_sync.h b/sql/debug_sync.h
index 9ac7da39d4d..ba3739e8ad5 100644
--- a/sql/debug_sync.h
+++ b/sql/debug_sync.h
@@ -39,7 +39,7 @@ class THD;
} while (0)
/* Command line option --debug-sync-timeout. See mysqld.cc. */
-extern uint opt_debug_sync_timeout;
+extern MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout;
/* Default WAIT_FOR timeout if command line option is given without argument. */
#define DEBUG_SYNC_DEFAULT_WAIT_TIMEOUT 300
diff --git a/sql/derror.cc b/sql/derror.cc
index db9cd3c0c58..2b4cc13073e 100644
--- a/sql/derror.cc
+++ b/sql/derror.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2005 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
@@ -108,7 +107,6 @@ bool read_texts(const char *file_name, const char *language,
char lang_path[FN_REFLEN];
uchar *buff;
uchar head[32],*pos;
- const char *errmsg;
DBUG_ENTER("read_texts");
LINT_INIT(buff);
@@ -185,18 +183,9 @@ Check that the above file is the right version for this program!",
DBUG_RETURN(0);
err:
- switch (funktpos) {
- case 2:
- errmsg= "Not enough memory for messagefile '%s'";
- break;
- case 1:
- errmsg= "Can't read from messagefile '%s'";
- break;
- default:
- errmsg= "Can't find messagefile '%s'";
- break;
- }
- sql_print_error(errmsg, name);
+ sql_print_error((funktpos == 2) ? "Not enough memory for messagefile '%s'" :
+ ((funktpos == 1) ? "Can't read from messagefile '%s'" :
+ "Can't find messagefile '%s'"), name);
if (file != FERR)
(void) mysql_file_close(file, MYF(MY_WME));
DBUG_RETURN(1);
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index 75d1c8ef8e8..9d52627fa83 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -620,18 +620,21 @@ Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
only creates a record on disk.
@pre The thread handle has no open tables.
- @param[in,out] thd THD
- @param[in] parse_data Parsed event definition
- @param[in] create_if_not TRUE if IF NOT EXISTS clause was provided
- to CREATE EVENT statement
-
+ @param[in,out] thd THD
+ @param[in] parse_data Parsed event definition
+ @param[in] create_if_not TRUE if IF NOT EXISTS clause was provided
+ to CREATE EVENT statement
+ @param[out] event_already_exists When method is completed successfully
+ set to true if event already exists else
+ set to false
@retval FALSE success
@retval TRUE error
*/
bool
Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
- my_bool create_if_not)
+ bool create_if_not,
+ bool *event_already_exists)
{
int ret= 1;
TABLE *table= NULL;
@@ -663,6 +666,7 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
{
if (create_if_not)
{
+ *event_already_exists= true;
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
parse_data->name.str);
@@ -670,8 +674,10 @@ Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
}
else
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);
+
goto end;
- }
+ } else
+ *event_already_exists= false;
DBUG_PRINT("info", ("non-existent, go forward"));
diff --git a/sql/event_db_repository.h b/sql/event_db_repository.h
index 58484d17f06..162ec5d1243 100644
--- a/sql/event_db_repository.h
+++ b/sql/event_db_repository.h
@@ -73,7 +73,8 @@ public:
Event_db_repository(){}
bool
- create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not);
+ create_event(THD *thd, Event_parse_data *parse_data, bool create_if_not,
+ bool *event_already_exists);
bool
update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname,
diff --git a/sql/events.cc b/sql/events.cc
index 23a0dc9eb52..819eca63e5c 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -284,6 +284,7 @@ create_query_string(THD *thd, String *buf)
return 0;
}
+
/**
Create a new event.
@@ -304,8 +305,8 @@ bool
Events::create_event(THD *thd, Event_parse_data *parse_data,
bool if_not_exists)
{
- int ret;
- bool save_binlog_row_based;
+ bool ret;
+ bool save_binlog_row_based, event_already_exists;
DBUG_ENTER("Events::create_event");
if (check_if_system_tables_error())
@@ -345,28 +346,32 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
DBUG_RETURN(TRUE);
/* On error conditions my_error() is called so no need to handle here */
- if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists)))
+ if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists,
+ &event_already_exists)))
{
Event_queue_element *new_element;
bool dropped= 0;
- if (!(new_element= new Event_queue_element()))
- ret= TRUE; // OOM
- else if ((ret= db_repository->load_named_event(thd, parse_data->dbname,
- parse_data->name,
- new_element)))
+ if (!event_already_exists)
{
- if (!db_repository->drop_event(thd, parse_data->dbname, parse_data->name,
- TRUE))
- dropped= 1;
- delete new_element;
- }
- else
- {
- /* TODO: do not ignore the out parameter and a possible OOM error! */
- bool created;
- if (event_queue)
- event_queue->create_event(thd, new_element, &created);
+ if (!(new_element= new Event_queue_element()))
+ ret= TRUE; // OOM
+ else if ((ret= db_repository->load_named_event(thd, parse_data->dbname,
+ parse_data->name,
+ new_element)))
+ {
+ if (!db_repository->drop_event(thd, parse_data->dbname, parse_data->name,
+ TRUE))
+ dropped= 1;
+ delete new_element;
+ }
+ else
+ {
+ /* TODO: do not ignore the out parameter and a possible OOM error! */
+ bool created;
+ if (event_queue)
+ event_queue->create_event(thd, new_element, &created);
+ }
}
/*
binlog the create event unless it's been successfully dropped
@@ -380,14 +385,14 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
{
sql_print_error("Event Error: An error occurred while creating query string, "
"before writing it into binary log.");
- ret= TRUE;
+ ret= true;
}
else
- {
- /* If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER
- will be written into the binary log as the definer for the SQL thread. */
+ /*
+ If the definer is not set or set to CURRENT_USER, the value of CURRENT_USER
+ will be written into the binary log as the definer for the SQL thread.
+ */
ret= write_bin_log(thd, TRUE, log_query.c_ptr(), log_query.length());
- }
}
}
/* Restore the state of binlog format */
@@ -445,7 +450,7 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
!sortcmp_lex_string(parse_data->name, *new_name,
system_charset_info))
{
- my_error(ER_EVENT_SAME_NAME, MYF(0), parse_data->name.str);
+ my_error(ER_EVENT_SAME_NAME, MYF(0));
DBUG_RETURN(TRUE);
}
diff --git a/sql/field.cc b/sql/field.cc
index 7ffc399718c..76fd6dc191c 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
@@ -2608,7 +2607,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
DBUG_ENTER("Field_new_decimal::store_value");
#ifndef DBUG_OFF
{
- char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+2];
DBUG_PRINT("enter", ("value: %s", dbug_decimal_as_string(dbug_buff, decimal_value)));
}
#endif
@@ -2623,7 +2622,7 @@ bool Field_new_decimal::store_value(const my_decimal *decimal_value)
}
#ifndef DBUG_OFF
{
- char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+2];
DBUG_PRINT("info", ("saving with precision %d scale: %d value %s",
(int)precision, (int)dec,
dbug_decimal_as_string(dbug_buff, decimal_value)));
@@ -2692,7 +2691,7 @@ int Field_new_decimal::store(const char *from, uint length,
}
#ifndef DBUG_OFF
- char dbug_buff[DECIMAL_MAX_STR_LENGTH+1];
+ char dbug_buff[DECIMAL_MAX_STR_LENGTH+2];
DBUG_PRINT("enter", ("value: %s",
dbug_decimal_as_string(dbug_buff, &decimal_value)));
#endif
@@ -9268,7 +9267,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
if (decimals >= NOT_FIXED_DEC)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), decimals, fld_name,
- NOT_FIXED_DEC-1);
+ static_cast<ulong>(NOT_FIXED_DEC - 1));
DBUG_RETURN(TRUE);
}
@@ -9338,8 +9337,8 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
my_decimal_trim(&length, &decimals);
if (length > DECIMAL_MAX_PRECISION)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), length, fld_name,
- DECIMAL_MAX_PRECISION);
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), static_cast<int>(length),
+ fld_name, static_cast<ulong>(DECIMAL_MAX_PRECISION));
DBUG_RETURN(TRUE);
}
if (length < decimals)
@@ -9563,7 +9562,7 @@ bool Create_field::init(THD *thd, char *fld_name, enum_field_types fld_type,
if (length > MAX_BIT_FIELD_LENGTH)
{
my_error(ER_TOO_BIG_DISPLAYWIDTH, MYF(0), fld_name,
- MAX_BIT_FIELD_LENGTH);
+ static_cast<ulong>(MAX_BIT_FIELD_LENGTH));
DBUG_RETURN(TRUE);
}
pack_length= (length + 7) / 8;
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 20745db9ce9..3c825ff3b4e 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
@@ -8699,7 +8698,7 @@ NDB_SHARE *ndbcluster_get_share(const char *key, TABLE *table,
DBUG_PRINT("error", ("get_share: failed to alloc share"));
if (!have_lock)
mysql_mutex_unlock(&ndbcluster_mutex);
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(*share));
+ my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(sizeof(*share)));
DBUG_RETURN(0);
}
}
diff --git a/sql/ha_ndbcluster_binlog.cc b/sql/ha_ndbcluster_binlog.cc
index e46b6b25f9c..c4b71bf32cf 100644
--- a/sql/ha_ndbcluster_binlog.cc
+++ b/sql/ha_ndbcluster_binlog.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2003 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-*/
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "sql_priv.h"
#include "unireg.h" // REQUIRED: for other includes
@@ -1225,12 +1224,14 @@ ndbcluster_update_slock(THD *thd,
}
if (ndb_error)
+ {
+ char buf[1024];
+ my_snprintf(buf, sizeof(buf), "Could not release lock on '%s.%s'",
+ db, table_name);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
- ndb_error->code,
- ndb_error->message,
- "Could not release lock on '%s.%s'",
- db, table_name);
+ ndb_error->code, ndb_error->message, buf);
+ }
if (trans)
ndb->closeTransaction(trans);
ndb->setDatabaseName(save_db);
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index 754d5dc99cf..785d118a5f4 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
This handler was developed by Mikael Ronstrom for version 5.1 of MySQL.
@@ -1069,6 +1069,10 @@ static int handle_opt_part(THD *thd, HA_CHECK_OPT *check_opt,
static bool print_admin_msg(THD* thd, const char* msg_type,
const char* db_name, const char* table_name,
const char* op_name, const char *fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 6, 7);
+static bool print_admin_msg(THD* thd, const char* msg_type,
+ const char* db_name, const char* table_name,
+ const char* op_name, const char *fmt, ...)
{
va_list args;
Protocol *protocol= thd->protocol;
@@ -6652,22 +6656,29 @@ bool ha_partition::check_if_incompatible_data(HA_CREATE_INFO *create_info,
/**
- Support of fast or online add/drop index
+ Support of in-place add/drop index
*/
-int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
+int ha_partition::add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
+ handler_add_index **add)
{
handler **file;
int ret= 0;
DBUG_ENTER("ha_partition::add_index");
+ *add= new handler_add_index(table, key_info, num_of_keys);
/*
There has already been a check in fix_partition_func in mysql_alter_table
before this call, which checks for unique/primary key violations of the
partitioning function. So no need for extra check here.
*/
for (file= m_file; *file; file++)
- if ((ret= (*file)->add_index(table_arg, key_info, num_of_keys)))
+ {
+ handler_add_index *add_index;
+ if ((ret= (*file)->add_index(table_arg, key_info, num_of_keys, &add_index)))
goto err;
+ if ((ret= (*file)->final_add_index(add_index, true)))
+ goto err;
+ }
DBUG_RETURN(ret);
err:
if (file > m_file)
@@ -6692,6 +6703,42 @@ err:
}
+/**
+ Second phase of in-place add index.
+
+ @note If commit is false, index changes are rolled back by dropping the
+ added indexes. If commit is true, nothing is done as the indexes
+ were already made active in ::add_index()
+ */
+
+int ha_partition::final_add_index(handler_add_index *add, bool commit)
+{
+ DBUG_ENTER("ha_partition::final_add_index");
+ // Rollback by dropping indexes.
+ if (!commit)
+ {
+ TABLE *table_arg= add->table;
+ uint num_of_keys= add->num_of_keys;
+ handler **file;
+ uint *key_numbers= (uint*) ha_thd()->alloc(sizeof(uint) * num_of_keys);
+ uint old_num_of_keys= table_arg->s->keys;
+ uint i;
+ /* The newly created keys have the last id's */
+ for (i= 0; i < num_of_keys; i++)
+ key_numbers[i]= i + old_num_of_keys;
+ if (!table_arg->key_info)
+ table_arg->key_info= add->key_info;
+ for (file= m_file; *file; file++)
+ {
+ (void) (*file)->prepare_drop_index(table_arg, key_numbers, num_of_keys);
+ (void) (*file)->final_drop_index(table_arg);
+ }
+ if (table_arg->key_info == add->key_info)
+ table_arg->key_info= NULL;
+ }
+ DBUG_RETURN(0);
+}
+
int ha_partition::prepare_drop_index(TABLE *table_arg, uint *key_num,
uint num_of_keys)
{
diff --git a/sql/ha_partition.h b/sql/ha_partition.h
index b0b11da823f..091efcfa727 100644
--- a/sql/ha_partition.h
+++ b/sql/ha_partition.h
@@ -1055,7 +1055,9 @@ public:
They are used for on-line/fast alter table add/drop index:
-------------------------------------------------------------------------
*/
- virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys);
+ virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
+ handler_add_index **add);
+ virtual int final_add_index(handler_add_index *add, bool commit);
virtual int prepare_drop_index(TABLE *table_arg, uint *key_num,
uint num_of_keys);
virtual int final_drop_index(TABLE *table_arg);
diff --git a/sql/handler.cc b/sql/handler.cc
index 445e1ec5a3c..580677242bd 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -278,7 +278,7 @@ handler *get_ha_partition(partition_info *part_info)
}
else
{
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(ha_partition));
+ my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(sizeof(ha_partition)));
}
DBUG_RETURN(((handler*) partition));
}
@@ -357,6 +357,7 @@ int ha_init_errors(void)
SETMSG(HA_ERR_AUTOINC_READ_FAILED, ER_DEFAULT(ER_AUTOINC_READ_FAILED));
SETMSG(HA_ERR_AUTOINC_ERANGE, ER_DEFAULT(ER_WARN_DATA_OUT_OF_RANGE));
SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER_DEFAULT(ER_TOO_MANY_CONCURRENT_TRXS));
+ SETMSG(HA_ERR_INDEX_COL_TOO_LONG, ER_DEFAULT(ER_INDEX_COLUMN_TOO_LONG));
/* Register the error messages for use with my_error(). */
return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
@@ -1638,7 +1639,8 @@ int ha_recover(HASH *commit_list)
}
if (!info.list)
{
- sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
+ sql_print_error(ER(ER_OUTOFMEMORY),
+ static_cast<int>(info.len*sizeof(XID)));
DBUG_RETURN(1);
}
@@ -2860,6 +2862,9 @@ void handler::print_error(int error, myf errflag)
case HA_ERR_TOO_MANY_CONCURRENT_TRXS:
textno= ER_TOO_MANY_CONCURRENT_TRXS;
break;
+ case HA_ERR_INDEX_COL_TOO_LONG:
+ textno= ER_INDEX_COLUMN_TOO_LONG;
+ break;
default:
{
/* The error was "unknown" to this function.
diff --git a/sql/handler.h b/sql/handler.h
index fbc52170297..893d8f015f5 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -1159,6 +1159,27 @@ uint calculate_key_len(TABLE *, uint, const uchar *, key_part_map);
*/
#define make_prev_keypart_map(N) (((key_part_map)1 << (N)) - 1)
+
+/**
+ Index creation context.
+ Created by handler::add_index() and freed by handler::final_add_index().
+*/
+
+class handler_add_index
+{
+public:
+ /* Table where the indexes are added */
+ TABLE* const table;
+ /* Indexes being created */
+ KEY* const key_info;
+ /* Size of key_info[] */
+ const uint num_of_keys;
+ handler_add_index(TABLE *table_arg, KEY *key_info_arg, uint num_of_keys_arg)
+ : table (table_arg), key_info (key_info_arg), num_of_keys (num_of_keys_arg)
+ {}
+ virtual ~handler_add_index() {}
+};
+
/**
The handler class is the interface for dynamically loadable
storage engines. Do not add ifdefs and take care when adding or
@@ -1717,8 +1738,36 @@ public:
virtual ulong index_flags(uint idx, uint part, bool all_parts) const =0;
- virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys)
+/**
+ First phase of in-place add index.
+ Handlers are supposed to create new indexes here but not make them
+ visible.
+
+ @param table_arg Table to add index to
+ @param key_info Information about new indexes
+ @param num_of_key Number of new indexes
+ @param add[out] Context of handler specific information needed
+ for final_add_index().
+
+ @note This function can be called with less than exclusive metadata
+ lock depending on which flags are listed in alter_table_flags.
+*/
+ virtual int add_index(TABLE *table_arg, KEY *key_info, uint num_of_keys,
+ handler_add_index **add)
{ return (HA_ERR_WRONG_COMMAND); }
+
+/**
+ Second and last phase of in-place add index.
+ Commit or rollback pending new indexes.
+
+ @param add Context of handler specific information from add_index().
+ @param commit If true, commit. If false, rollback index changes.
+
+ @note This function is called with exclusive metadata lock.
+*/
+ virtual int final_add_index(handler_add_index *add, bool commit)
+ { return (HA_ERR_WRONG_COMMAND); }
+
virtual int prepare_drop_index(TABLE *table_arg, uint *key_num,
uint num_of_keys)
{ return (HA_ERR_WRONG_COMMAND); }
diff --git a/sql/item.cc b/sql/item.cc
index 0aac941740f..fee6381a25f 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -2011,6 +2011,61 @@ Item_field::Item_field(THD *thd, Item_field *item)
collation.set(DERIVATION_IMPLICIT);
}
+
+/**
+ Calculate the max column length not taking into account the
+ limitations over integer types.
+
+ When storing data into fields the server currently just ignores the
+ limits specified on integer types, e.g. 1234 can safely be stored in
+ an int(2) and will not cause an error.
+ Thus when creating temporary tables and doing transformations
+ we must adjust the maximum field length to reflect this fact.
+ We take the un-restricted maximum length and adjust it similarly to
+ how the declared length is adjusted wrt unsignedness etc.
+ TODO: this all needs to go when we disable storing 1234 in int(2).
+
+ @param field_par Original field the use to calculate the lengths
+ @param max_length Item's calculated explicit max length
+ @return The adjusted max length
+*/
+
+inline static uint32
+adjust_max_effective_column_length(Field *field_par, uint32 max_length)
+{
+ uint32 new_max_length= field_par->max_display_length();
+ uint32 sign_length= (field_par->flags & UNSIGNED_FLAG) ? 0 : 1;
+
+ switch (field_par->type())
+ {
+ case MYSQL_TYPE_INT24:
+ /*
+ Compensate for MAX_MEDIUMINT_WIDTH being 1 too long (8)
+ compared to the actual number of digits that can fit into
+ the column.
+ */
+ new_max_length+= 1;
+ /* fall through */
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_TINY:
+ case MYSQL_TYPE_SHORT:
+
+ /* Take out the sign and add a conditional sign */
+ new_max_length= new_max_length - 1 + sign_length;
+ break;
+
+ /* BINGINT is always 20 no matter the sign */
+ case MYSQL_TYPE_LONGLONG:
+ /* make gcc happy */
+ default:
+ break;
+ }
+
+ /* Adjust only if the actual precision based one is bigger than specified */
+ return new_max_length > max_length ? new_max_length : max_length;
+}
+
+
void Item_field::set_field(Field *field_par)
{
field=result_field=field_par; // for easy coding with fields
@@ -2024,6 +2079,9 @@ void Item_field::set_field(Field *field_par)
collation.set(field_par->charset(), field_par->derivation(),
field_par->repertoire());
fix_char_length(field_par->char_length());
+
+ max_length= adjust_max_effective_column_length(field_par, max_length);
+
fixed= 1;
if (field->table->s->tmp_table == SYSTEM_TMP_TABLE)
any_privileges= 0;
diff --git a/sql/item_create.cc b/sql/item_create.cc
index 1ae65926013..28cc5beaf25 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
@@ -5215,8 +5215,8 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
decoded_size= strtoul(c_len, NULL, 10);
if (errno != 0)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), c_len, a->name,
- DECIMAL_MAX_PRECISION);
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), INT_MAX, a->name,
+ static_cast<ulong>(DECIMAL_MAX_PRECISION));
return NULL;
}
len= decoded_size;
@@ -5229,8 +5229,8 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
decoded_size= strtoul(c_dec, NULL, 10);
if ((errno != 0) || (decoded_size > UINT_MAX))
{
- my_error(ER_TOO_BIG_SCALE, MYF(0), c_dec, a->name,
- DECIMAL_MAX_SCALE);
+ my_error(ER_TOO_BIG_SCALE, MYF(0), INT_MAX, a->name,
+ static_cast<ulong>(DECIMAL_MAX_SCALE));
return NULL;
}
dec= decoded_size;
@@ -5243,14 +5243,14 @@ create_func_cast(THD *thd, Item *a, Cast_target cast_type,
}
if (len > DECIMAL_MAX_PRECISION)
{
- my_error(ER_TOO_BIG_PRECISION, MYF(0), len, a->name,
- DECIMAL_MAX_PRECISION);
+ my_error(ER_TOO_BIG_PRECISION, MYF(0), static_cast<int>(len), a->name,
+ static_cast<ulong>(DECIMAL_MAX_PRECISION));
return 0;
}
if (dec > DECIMAL_MAX_SCALE)
{
my_error(ER_TOO_BIG_SCALE, MYF(0), dec, a->name,
- DECIMAL_MAX_SCALE);
+ static_cast<ulong>(DECIMAL_MAX_SCALE));
return 0;
}
res= new (thd->mem_root) Item_decimal_typecast(a, len, dec);
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 24d0d94c6c5..754eae6d55b 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
@@ -52,6 +51,8 @@
#include "sp.h"
#include "set_var.h"
#include "debug_sync.h"
+#include <mysql/plugin.h>
+#include <mysql/service_thd_wait.h>
#ifdef NO_EMBEDDED_ACCESS_CHECKS
#define sp_restore_security_context(A,B) while (0) {}
@@ -1094,7 +1095,7 @@ err:
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_OUT_OF_RANGE,
ER(ER_WARN_DATA_OUT_OF_RANGE),
- name, 1);
+ name, 1L);
return dec;
}
@@ -2258,6 +2259,9 @@ void Item_func_round::fix_length_and_dec()
}
val1= args[1]->val_int();
+ if ((null_value= args[1]->is_null()))
+ return;
+
val1_unsigned= args[1]->unsigned_flag;
if (val1 < 0)
decimals_to_set= val1_unsigned ? INT_MAX : 0;
@@ -3152,7 +3156,7 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
if (!tmp_udf)
{
- my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str, errno);
+ my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str);
DBUG_RETURN(TRUE);
}
u_d=tmp_udf;
@@ -3890,6 +3894,7 @@ longlong Item_func_get_lock::val_int()
timed_cond.set_timeout(timeout * ULL(1000000000));
error= 0;
+ thd_wait_begin(thd, THD_WAIT_USER_LOCK);
while (ull->locked && !thd->killed)
{
DBUG_PRINT("info", ("waiting on lock"));
@@ -3901,6 +3906,7 @@ longlong Item_func_get_lock::val_int()
}
error= 0;
}
+ thd_wait_end(thd);
if (ull->locked)
{
@@ -4118,6 +4124,7 @@ longlong Item_func_sleep::val_int()
thd->mysys_var->current_cond= &cond;
error= 0;
+ thd_wait_begin(thd, THD_WAIT_SLEEP);
while (!thd->killed)
{
error= timed_cond.wait(&cond, &LOCK_user_locks);
@@ -4125,6 +4132,7 @@ longlong Item_func_sleep::val_int()
break;
error= 0;
}
+ thd_wait_end(thd);
thd_proc_info(thd, 0);
mysql_mutex_unlock(&LOCK_user_locks);
mysql_mutex_lock(&thd->mysys_var->mutex);
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index e1a4fcc8def..5a5284ca388 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
@@ -3702,7 +3701,8 @@ String *Item_func_uncompress::val_str(String *str)
push_warning_printf(current_thd,MYSQL_ERROR::WARN_LEVEL_WARN,
ER_TOO_BIG_FOR_UNCOMPRESS,
ER(ER_TOO_BIG_FOR_UNCOMPRESS),
- current_thd->variables.max_allowed_packet);
+ static_cast<int>(current_thd->variables.
+ max_allowed_packet));
goto err;
}
if (buffer.realloc((uint32)new_size))
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 5f30787f015..b642e38d8c6 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -1591,6 +1591,11 @@ bool Item_func_from_days::get_date(MYSQL_TIME *ltime, uint fuzzy_date)
return 1;
bzero(ltime, sizeof(MYSQL_TIME));
get_date_from_daynr((long) value, &ltime->year, &ltime->month, &ltime->day);
+
+ if ((null_value= (fuzzy_date & TIME_NO_ZERO_DATE) &&
+ (ltime->year == 0 || ltime->month == 0 || ltime->day == 0)))
+ return TRUE;
+
ltime->time_type= MYSQL_TIMESTAMP_DATE;
return 0;
}
@@ -2779,7 +2784,7 @@ String *Item_func_makedate::val_str(String *str)
long days;
if (args[0]->null_value || args[1]->null_value ||
- year < 0 || daynr <= 0)
+ year < 0 || year > 9999 || daynr <= 0)
goto err;
if (year < 100)
@@ -2822,7 +2827,7 @@ longlong Item_func_makedate::val_int()
long days;
if (args[0]->null_value || args[1]->null_value ||
- year < 0 || daynr <= 0)
+ year < 0 || year > 9999 || daynr <= 0)
goto err;
if (year < 100)
diff --git a/sql/log.cc b/sql/log.cc
index fe782c5d621..9080dcd7fa2 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -3372,12 +3372,6 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
DBUG_ENTER("reset_logs");
ha_reset_logs(thd);
- /*
- We need to get both locks to be sure that no one is trying to
- write to the index log file.
- */
- mysql_mutex_lock(&LOCK_log);
- mysql_mutex_lock(&LOCK_index);
/*
The following mutex is needed to ensure that no threads call
@@ -3387,6 +3381,13 @@ bool MYSQL_BIN_LOG::reset_logs(THD* thd)
*/
mysql_mutex_lock(&LOCK_thread_count);
+ /*
+ We need to get both locks to be sure that no one is trying to
+ write to the index log file.
+ */
+ mysql_mutex_lock(&LOCK_log);
+ mysql_mutex_lock(&LOCK_index);
+
/* Save variables so that we can reopen the log */
save_name=name;
name=0; // Protect against free
@@ -5993,7 +5994,7 @@ int TC_LOG_MMAP::open(const char *opt_name)
{
pg->next=pg+1;
pg->waiters=0;
- pg->state=POOL;
+ pg->state=PS_POOL;
mysql_mutex_init(key_PAGE_lock, &pg->lock, MY_MUTEX_INIT_FAST);
mysql_cond_init(key_PAGE_cond, &pg->cond, 0);
pg->start=(my_xid *)(data + i*tc_log_page_size);
@@ -6167,7 +6168,7 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
cookie= (ulong)((uchar *)p->ptr - data); // can never be zero
*p->ptr++= xid;
p->free--;
- p->state= DIRTY;
+ p->state= PS_DIRTY;
/* to sync or not to sync - this is the question */
mysql_mutex_unlock(&LOCK_active);
@@ -6179,13 +6180,13 @@ int TC_LOG_MMAP::log_xid(THD *thd, my_xid xid)
p->waiters++;
/*
note - it must be while (), not do ... while () here
- as p->state may be not DIRTY when we come here
+ as p->state may be not PS_DIRTY when we come here
*/
- while (p->state == DIRTY && syncing)
+ while (p->state == PS_DIRTY && syncing)
mysql_cond_wait(&p->cond, &LOCK_sync);
p->waiters--;
- err= p->state == ERROR;
- if (p->state != DIRTY) // page was synced
+ err= p->state == PS_ERROR;
+ if (p->state != PS_DIRTY) // page was synced
{
if (p->waiters == 0)
mysql_cond_signal(&COND_pool); // in case somebody's waiting
@@ -6223,7 +6224,7 @@ int TC_LOG_MMAP::sync()
pool_last->next=syncing;
pool_last=syncing;
syncing->next=0;
- syncing->state= err ? ERROR : POOL;
+ syncing->state= err ? PS_ERROR : PS_POOL;
mysql_cond_broadcast(&syncing->cond); // signal "sync done"
mysql_cond_signal(&COND_pool); // in case somebody's waiting
mysql_mutex_unlock(&LOCK_pool);
@@ -6506,8 +6507,11 @@ int TC_LOG_BINLOG::unlog(ulong cookie, my_xid xid)
{
DBUG_ENTER("TC_LOG_BINLOG::unlog");
mysql_mutex_lock(&LOCK_prep_xids);
- DBUG_ASSERT(prepared_xids > 0);
- if (--prepared_xids == 0) {
+ // prepared_xids can be 0 if the transaction had ignorable errors.
+ DBUG_ASSERT(prepared_xids >= 0);
+ if (prepared_xids > 0)
+ prepared_xids--;
+ if (prepared_xids == 0) {
DBUG_PRINT("info", ("prepared_xids=%lu", prepared_xids));
mysql_cond_signal(&COND_prep_xids);
}
diff --git a/sql/log.h b/sql/log.h
index 7f7d1a1cf3a..0f0f81dd402 100644
--- a/sql/log.h
+++ b/sql/log.h
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#ifndef LOG_H
#define LOG_H
@@ -63,9 +63,9 @@ class TC_LOG_MMAP: public TC_LOG
{
public: // only to keep Sun Forte on sol9x86 happy
typedef enum {
- POOL, // page is in pool
- ERROR, // last sync failed
- DIRTY // new xids added since last sync
+ PS_POOL, // page is in pool
+ PS_ERROR, // last sync failed
+ PS_DIRTY // new xids added since last sync
} PAGE_STATE;
private:
@@ -687,7 +687,7 @@ void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
void sql_print_information(const char *format, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
typedef void (*sql_print_message_func)(const char *format, ...)
- ATTRIBUTE_FORMAT(printf, 1, 2);
+ ATTRIBUTE_FORMAT_FPTR(printf, 1, 2);
extern sql_print_message_func sql_print_message_handlers[];
int error_log_print(enum loglevel level, const char *format,
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 39b4791ff3d..763bbf81a81 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -8441,6 +8441,7 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
m_field_metadata, m_field_metadata_size,
m_null_bits, m_flags);
table_list->m_tabledef_valid= TRUE;
+ table_list->m_conv_table= NULL;
table_list->open_type= OT_BASE_ONLY;
/*
diff --git a/sql/mdl.cc b/sql/mdl.cc
index 3aed54ce12d..21410db2d22 100644
--- a/sql/mdl.cc
+++ b/sql/mdl.cc
@@ -18,6 +18,8 @@
#include "debug_sync.h"
#include <hash.h>
#include <mysqld_error.h>
+#include <mysql/plugin.h>
+#include <mysql/service_thd_wait.h>
#ifdef HAVE_PSI_INTERFACE
static PSI_mutex_key key_MDL_map_mutex;
@@ -973,10 +975,14 @@ MDL_wait::timed_wait(THD *thd, struct timespec *abs_timeout,
old_msg= thd_enter_cond(thd, &m_COND_wait_status, &m_LOCK_wait_status,
wait_state_name);
+ thd_wait_begin(thd, THD_WAIT_META_DATA_LOCK);
while (!m_wait_status && !thd_killed(thd) &&
wait_result != ETIMEDOUT && wait_result != ETIME)
+ {
wait_result= mysql_cond_timedwait(&m_COND_wait_status, &m_LOCK_wait_status,
abs_timeout);
+ }
+ thd_wait_end(thd);
if (m_wait_status == EMPTY)
{
diff --git a/sql/my_decimal.cc b/sql/my_decimal.cc
index a5b60739b26..3b5fa81eab9 100644
--- a/sql/my_decimal.cc
+++ b/sql/my_decimal.cc
@@ -99,10 +99,11 @@ int my_decimal2string(uint mask, const my_decimal *d,
UNSIGNED. Hence the buffer for a ZEROFILLed value is the length
the user requested, plus one for a possible decimal point, plus
one if the user only wanted decimal places, but we force a leading
- zero on them. Because the type is implicitly UNSIGNED, we do not
- need to reserve a character for the sign. For all other cases,
- fixed_prec will be 0, and my_decimal_string_length() will be called
- instead to calculate the required size of the buffer.
+ zero on them, plus one for the '\0' terminator. Because the type
+ is implicitly UNSIGNED, we do not need to reserve a character for
+ the sign. For all other cases, fixed_prec will be 0, and
+ my_decimal_string_length() will be called instead to calculate the
+ required size of the buffer.
*/
int length= (fixed_prec
? (fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
@@ -332,7 +333,7 @@ print_decimal_buff(const my_decimal *dec, const uchar* ptr, int length)
const char *dbug_decimal_as_string(char *buff, const my_decimal *val)
{
- int length= DECIMAL_MAX_STR_LENGTH;
+ int length= DECIMAL_MAX_STR_LENGTH + 1; /* minimum size for buff */
if (!val)
return "NULL";
(void)decimal2string((decimal_t*) val, buff, &length, 0,0,0);
diff --git a/sql/my_decimal.h b/sql/my_decimal.h
index f3fd39f5721..6ac9d25b87d 100644
--- a/sql/my_decimal.h
+++ b/sql/my_decimal.h
@@ -62,7 +62,7 @@ typedef struct st_mysql_time MYSQL_TIME;
/**
maximum length of string representation (number of maximum decimal
- digits + 1 position for sign + 1 position for decimal point)
+ digits + 1 position for sign + 1 position for decimal point, no terminator)
*/
#define DECIMAL_MAX_STR_LENGTH (DECIMAL_MAX_POSSIBLE_PRECISION + 2)
@@ -243,6 +243,7 @@ inline uint32 my_decimal_precision_to_length(uint precision, uint8 scale,
inline
int my_decimal_string_length(const my_decimal *d)
{
+ /* length of string representation including terminating '\0' */
return decimal_string_size(d);
}
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index b349c5f91b1..6b00a6b3009 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -163,12 +163,12 @@ extern int memcntl(caddr_t, size_t, int, caddr_t, int, int);
int initgroups(const char *,unsigned int);
#endif
-#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
+#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
#include <ieeefp.h>
#ifdef HAVE_FP_EXCEPT // Fix type conflict
typedef fp_except fp_except_t;
#endif
-#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
+#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
#ifdef HAVE_SYS_FPU_H
/* for IRIX to use set_fpc_csr() */
#include <sys/fpu.h>
@@ -194,19 +194,24 @@ extern "C" my_bool reopen_fstreams(const char *filename,
inline void setup_fpu()
{
-#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
+#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H) && !defined(HAVE_FEDISABLEEXCEPT)
/* We can't handle floating point exceptions with threads, so disable
this on freebsd
- Don't fall for overflow, underflow,divide-by-zero or loss of precision
+ Don't fall for overflow, underflow,divide-by-zero or loss of precision.
+ fpsetmask() is deprecated in favor of fedisableexcept() in C99.
*/
-#if defined(__i386__)
+#if defined(FP_X_DNML)
fpsetmask(~(FP_X_INV | FP_X_DNML | FP_X_OFL | FP_X_UFL | FP_X_DZ |
FP_X_IMP));
#else
fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ |
FP_X_IMP));
-#endif /* __i386__ */
-#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
+#endif /* FP_X_DNML */
+#endif /* __FreeBSD__ && HAVE_IEEEFP_H && !HAVE_FEDISABLEEXCEPT */
+
+#ifdef HAVE_FEDISABLEEXCEPT
+ fedisableexcept(FE_ALL_EXCEPT);
+#endif
#ifdef HAVE_FESETROUND
/* Set FPU rounding mode to "round-to-nearest" */
@@ -422,7 +427,7 @@ my_bool opt_super_large_pages= 0;
my_bool opt_myisam_use_mmap= 0;
uint opt_large_page_size= 0;
#if defined(ENABLED_DEBUG_SYNC)
-uint opt_debug_sync_timeout= 0;
+MYSQL_PLUGIN_IMPORT uint opt_debug_sync_timeout= 0;
#endif /* defined(ENABLED_DEBUG_SYNC) */
my_bool opt_old_style_user_limits= 0, trust_function_creators= 0;
/*
@@ -2009,6 +2014,49 @@ extern "C" sig_handler end_thread_signal(int sig __attribute__((unused)))
/*
+ Cleanup THD object
+
+ SYNOPSIS
+ thd_cleanup()
+ thd Thread handler
+*/
+
+void thd_cleanup(THD *thd)
+{
+ thd->cleanup();
+}
+
+/*
+ Decrease number of connections
+
+ SYNOPSIS
+ dec_connection_count()
+*/
+
+void dec_connection_count()
+{
+ mysql_mutex_lock(&LOCK_connection_count);
+ --connection_count;
+ mysql_mutex_unlock(&LOCK_connection_count);
+}
+
+
+/*
+ Delete the THD object and decrease number of threads
+
+ SYNOPSIS
+ delete_thd()
+ thd Thread handler
+*/
+
+void delete_thd(THD *thd)
+{
+ thread_count--;
+ delete thd;
+}
+
+
+/*
Unlink thd from global list of available connections and free thd
SYNOPSIS
@@ -2023,15 +2071,17 @@ void unlink_thd(THD *thd)
{
DBUG_ENTER("unlink_thd");
DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
- thd->cleanup();
-
- mysql_mutex_lock(&LOCK_connection_count);
- --connection_count;
- mysql_mutex_unlock(&LOCK_connection_count);
+ thd_cleanup(thd);
+ dec_connection_count();
mysql_mutex_lock(&LOCK_thread_count);
- thread_count--;
- delete thd;
+ /*
+ Used by binlog_reset_master. It would be cleaner to use
+ DEBUG_SYNC here, but that's not possible because the THD's debug
+ sync feature has been shut down at this point.
+ */
+ DBUG_EXECUTE_IF("sleep_after_lock_thread_count_before_delete_thd", sleep(5););
+ delete_thd(thd);
DBUG_VOID_RETURN;
}
@@ -4923,6 +4973,14 @@ static bool read_init_file(char *file_name)
}
+/**
+ Increment number of created threads
+*/
+void inc_thread_created(void)
+{
+ thread_created++;
+}
+
#ifndef EMBEDDED_LIBRARY
/*
diff --git a/sql/mysqld.h b/sql/mysqld.h
index 303ee5bec0f..d2366224b3f 100644
--- a/sql/mysqld.h
+++ b/sql/mysqld.h
@@ -216,6 +216,10 @@ extern char err_shared_dir[];
extern TYPELIB thread_handling_typelib;
extern my_decimal decimal_zero;
+/*
+ THR_MALLOC is a key which will be used to set/get MEM_ROOT** for a thread,
+ using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
+*/
extern pthread_key(MEM_ROOT**,THR_MALLOC);
#ifdef HAVE_PSI_INTERFACE
@@ -503,6 +507,10 @@ get_thread_running()
extern "C" THD *_current_thd_noinline();
#define _current_thd() _current_thd_noinline()
#else
+/*
+ THR_THD is a key which will be used to set/get THD* for a thread,
+ using my_pthread_setspecific_ptr()/my_thread_getspecific_ptr().
+*/
extern pthread_key(THD*, THR_THD);
inline THD *_current_thd(void)
{
diff --git a/sql/password.c b/sql/password.c
index 3b69705cc87..236e7bde0d5 100644
--- a/sql/password.c
+++ b/sql/password.c
@@ -205,21 +205,16 @@ void scramble_323(char *to, const char *message, const char *password)
}
-/*
- Check scrambled message
- Used in pre 4.1 password handling
- SYNOPSIS
- check_scramble_323()
- scrambled scrambled message to check.
- message original random message which was used for scrambling; must
- be exactly SCRAMBLED_LENGTH_323 bytes long and
- NULL-terminated.
- hash_pass password which should be used for scrambling
- All params are IN.
+/**
+ Check scrambled message. Used in pre 4.1 password handling.
- RETURN VALUE
- 0 - password correct
- !0 - password invalid
+ @param scrambled Scrambled message to check.
+ @param message Original random message which was used for scrambling.
+ @param hash_pass Password which should be used for scrambling.
+
+ @remark scrambled and message must be SCRAMBLED_LENGTH_323 bytes long.
+
+ @return FALSE if password is correct, TRUE otherwise.
*/
my_bool
@@ -228,9 +223,16 @@ check_scramble_323(const unsigned char *scrambled, const char *message,
{
struct rand_struct rand_st;
ulong hash_message[2];
- uchar buff[16],*to,extra; /* Big enough for check */
+ /* Big enough for checks. */
+ uchar buff[16], scrambled_buff[SCRAMBLE_LENGTH_323 + 1];
+ uchar *to, extra;
const uchar *pos;
+ /* Ensure that the scrambled message is null-terminated. */
+ memcpy(scrambled_buff, scrambled, SCRAMBLE_LENGTH_323);
+ scrambled_buff[SCRAMBLE_LENGTH_323]= '\0';
+ scrambled= scrambled_buff;
+
hash_password(hash_message, message, SCRAMBLE_LENGTH_323);
randominit(&rand_st,hash_pass[0] ^ hash_message[0],
hash_pass[1] ^ hash_message[1]);
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index f2653894ea7..e72c813f09f 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -26,6 +26,8 @@
#include "rpl_utility.h"
#include "transaction.h"
#include "sql_parse.h" // end_trans, ROLLBACK
+#include <mysql/plugin.h>
+#include <mysql/service_thd_wait.h>
static int count_relay_log_space(Relay_log_info* rli);
@@ -799,6 +801,7 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name,
We are going to mysql_cond_(timed)wait(); if the SQL thread stops it
will wake us up.
*/
+ thd_wait_begin(thd, THD_WAIT_BINLOG);
if (timeout > 0)
{
/*
@@ -816,6 +819,7 @@ int Relay_log_info::wait_for_pos(THD* thd, String* log_name,
}
else
mysql_cond_wait(&data_cond, &data_lock);
+ thd_wait_end(thd);
DBUG_PRINT("info",("Got signal of master update or timed out"));
if (error == ETIMEDOUT || error == ETIME)
{
@@ -1254,6 +1258,16 @@ void Relay_log_info::clear_tables_to_lock()
tables_to_lock->m_tabledef.table_def::~table_def();
tables_to_lock->m_tabledef_valid= FALSE;
}
+
+ /*
+ If blob fields were used during conversion of field values
+ from the master table into the slave table, then we need to
+ free the memory used temporarily to store their values before
+ copying into the slave's table.
+ */
+ if (tables_to_lock->m_conv_table)
+ free_blobs(tables_to_lock->m_conv_table);
+
tables_to_lock=
static_cast<RPL_TABLE_LIST*>(tables_to_lock->next_global);
tables_to_lock_count--;
diff --git a/sql/scheduler.cc b/sql/scheduler.cc
index d61a452b99e..a3848e20be5 100644
--- a/sql/scheduler.cc
+++ b/sql/scheduler.cc
@@ -80,14 +80,26 @@ scheduler_functions *thread_scheduler= NULL;
*/
/**@{*/
-static void scheduler_wait_begin(void) {
+extern "C"
+{
+static void scheduler_wait_lock_begin(void) {
+ MYSQL_CALLBACK(thread_scheduler,
+ thd_wait_begin, (current_thd, THD_WAIT_TABLE_LOCK));
+}
+
+static void scheduler_wait_lock_end(void) {
+ MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd));
+}
+
+static void scheduler_wait_sync_begin(void) {
MYSQL_CALLBACK(thread_scheduler,
- thd_wait_begin, (current_thd, THD_WAIT_ROW_TABLE_LOCK));
+ thd_wait_begin, (current_thd, THD_WAIT_TABLE_LOCK));
}
-static void scheduler_wait_end(void) {
+static void scheduler_wait_sync_end(void) {
MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (current_thd));
}
+};
/**@}*/
/**
@@ -98,7 +110,10 @@ static void scheduler_wait_end(void) {
mysqld.cc, so this init function will always be called.
*/
static void scheduler_init() {
- thr_set_lock_wait_callback(scheduler_wait_begin, scheduler_wait_end);
+ thr_set_lock_wait_callback(scheduler_wait_lock_begin,
+ scheduler_wait_lock_end);
+ thr_set_sync_wait_callback(scheduler_wait_sync_begin,
+ scheduler_wait_sync_end);
}
/*
@@ -137,10 +152,6 @@ void one_thread_scheduler()
thd_scheduler::thd_scheduler()
: m_psi(NULL), data(NULL)
{
-#ifndef DBUG_OFF
- dbug_explain[0]= '\0';
- set_explain= FALSE;
-#endif
}
diff --git a/sql/scheduler.h b/sql/scheduler.h
index b5a175434b6..7cf54dec004 100644
--- a/sql/scheduler.h
+++ b/sql/scheduler.h
@@ -72,11 +72,6 @@ enum scheduler_types
void one_thread_per_connection_scheduler();
void one_thread_scheduler();
-enum pool_command_op
-{
- NOT_IN_USE_OP= 0, NORMAL_OP= 1, CONNECT_OP, KILL_OP, DIE_OP
-};
-
/*
To be used for pool-of-threads (implemeneted differently on various OSs)
*/
@@ -97,15 +92,15 @@ public:
void *data; /* scheduler-specific data structure */
-# ifndef DBUG_OFF
- char dbug_explain[512];
- bool set_explain;
-# endif
-
thd_scheduler();
~thd_scheduler();
};
+void *thd_get_scheduler_data(THD *thd);
+void thd_set_scheduler_data(THD *thd, void *data);
+PSI_thread* thd_get_psi(THD *thd);
+void thd_set_psi(THD *thd, PSI_thread *psi);
+
extern scheduler_functions *thread_scheduler;
#endif
diff --git a/sql/set_var.cc b/sql/set_var.cc
index f31fe6a351d..8e48e0213f0 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -117,7 +117,8 @@ void sys_var_end()
sys_var constructor
@param chain variables are linked into chain for mysql_add_sys_var_chain()
- @param name_arg the name of the variable. @sa my_option::name
+ @param name_arg the name of the variable. Must be 0-terminated and exist
+ for the liftime of the sys_var object. @sa my_option::name
@param comment shown in mysqld --help, @sa my_option::comment
@param flags_arg or'ed flag_enum values
@param off offset of the global variable value from the
@@ -164,8 +165,8 @@ sys_var::sys_var(sys_var_chain *chain, const char *name_arg,
*/
DBUG_ASSERT(parse_flag == PARSE_NORMAL || getopt_id <= 0 || getopt_id >= 255);
- name.str= name_arg;
- name.length= strlen(name_arg);
+ name.str= name_arg; // ER_NO_DEFAULT relies on 0-termination of name_arg
+ name.length= strlen(name_arg); // and so does this.
DBUG_ASSERT(name.length <= NAME_CHAR_LEN);
bzero(&option, sizeof(option));
diff --git a/sql/share/errmsg-utf8.txt b/sql/share/errmsg-utf8.txt
index 6898028df70..09620f2d260 100644
--- a/sql/share/errmsg-utf8.txt
+++ b/sql/share/errmsg-utf8.txt
@@ -6405,3 +6405,6 @@ ER_TABLE_NEEDS_REBUILD
WARN_OPTION_BELOW_LIMIT
eng "The value of '%s' should be no less than the value of '%s'"
+
+ER_INDEX_COLUMN_TOO_LONG
+ eng "Index column size too large. The maximum column size is %lu bytes."
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index c8368be953b..7b175cb0256 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
#include "sql_priv.h"
@@ -550,7 +550,7 @@ sp_head::operator delete(void *ptr, size_t size) throw()
sp_head::sp_head()
- :Query_arena(&main_mem_root, INITIALIZED_FOR_SP),
+ :Query_arena(&main_mem_root, STMT_INITIALIZED_FOR_SP),
m_flags(0),
m_sp_cache_version(0),
unsafe_flags(0),
@@ -1066,7 +1066,7 @@ void sp_head::recursion_level_error(THD *thd)
if (m_type == TYPE_ENUM_PROCEDURE)
{
my_error(ER_SP_RECURSION_LIMIT, MYF(0),
- thd->variables.max_sp_recursion_depth,
+ static_cast<int>(thd->variables.max_sp_recursion_depth),
m_name.str);
}
else
@@ -1208,7 +1208,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
Query_arena *old_arena;
/* per-instruction arena */
MEM_ROOT execute_mem_root;
- Query_arena execute_arena(&execute_mem_root, INITIALIZED_FOR_SP),
+ Query_arena execute_arena(&execute_mem_root, STMT_INITIALIZED_FOR_SP),
backup_arena;
query_id_t old_query_id;
TABLE *old_derived_tables;
@@ -1489,7 +1489,7 @@ sp_head::execute(THD *thd, bool merge_da_on_success)
thd->m_reprepare_observer= save_reprepare_observer;
thd->stmt_arena= old_arena;
- state= EXECUTED;
+ state= STMT_EXECUTED;
/*
Restore the caller's original warning information area:
@@ -1647,7 +1647,7 @@ sp_head::execute_trigger(THD *thd,
sp_rcontext *nctx = NULL;
bool err_status= FALSE;
MEM_ROOT call_mem_root;
- Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP);
+ Query_arena call_arena(&call_mem_root, Query_arena::STMT_INITIALIZED_FOR_SP);
Query_arena backup_arena;
DBUG_ENTER("sp_head::execute_trigger");
@@ -1788,7 +1788,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
String binlog_buf(buf, sizeof(buf), &my_charset_bin);
bool err_status= FALSE;
MEM_ROOT call_mem_root;
- Query_arena call_arena(&call_mem_root, Query_arena::INITIALIZED_FOR_SP);
+ Query_arena call_arena(&call_mem_root, Query_arena::STMT_INITIALIZED_FOR_SP);
Query_arena backup_arena;
DBUG_ENTER("sp_head::execute_function");
DBUG_PRINT("info", ("function %s", m_name.str));
@@ -2545,7 +2545,7 @@ sp_head::restore_thd_mem_root(THD *thd)
DBUG_ENTER("sp_head::restore_thd_mem_root");
Item *flist= free_list; // The old list
set_query_arena(thd); // Get new free_list and mem_root
- state= INITIALIZED_FOR_SP;
+ state= STMT_INITIALIZED_FOR_SP;
DBUG_PRINT("info", ("mem_root 0x%lx returned from thd mem root 0x%lx",
(ulong) &mem_root, (ulong) &thd->mem_root));
@@ -3010,7 +3010,7 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp,
(thd->stmt_da->sql_errno() != ER_CANT_REOPEN_TABLE &&
thd->stmt_da->sql_errno() != ER_NO_SUCH_TABLE &&
thd->stmt_da->sql_errno() != ER_UPDATE_TABLE_USED))
- thd->stmt_arena->state= Query_arena::EXECUTED;
+ thd->stmt_arena->state= Query_arena::STMT_EXECUTED;
/*
Merge here with the saved parent's values
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 5efd48fc7c6..4d5e2dd95ab 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -560,7 +560,7 @@ public:
/// Should give each a name or type code for debugging purposes?
sp_instr(uint ip, sp_pcontext *ctx)
- :Query_arena(0, INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
+ :Query_arena(0, STMT_INITIALIZED_FOR_SP), marked(0), m_ip(ip), m_ctx(ctx)
{}
virtual ~sp_instr()
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index 7d7595899d7..a065d8f9219 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -2273,13 +2273,12 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
*/
else if (!password_len && !combo.plugin.length && no_auto_create)
{
- my_error(ER_PASSWORD_NO_MATCH, MYF(0), combo.user.str, combo.host.str);
+ my_error(ER_PASSWORD_NO_MATCH, MYF(0));
goto end;
}
else if (!can_create_user)
{
- my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0),
- thd->security_ctx->user, thd->security_ctx->host_or_ip);
+ my_error(ER_CANT_CREATE_USER_WITH_GRANT, MYF(0));
goto end;
}
else if (combo.plugin.str[0])
@@ -2307,8 +2306,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
/* what == 'N' means revoke */
if (combo.plugin.length && what != 'N')
{
- my_error(ER_GRANT_PLUGIN_USER_EXISTS, MYF(0), combo.user.length,
- combo.user.str);
+ my_error(ER_GRANT_PLUGIN_USER_EXISTS, MYF(0),
+ static_cast<int>(combo.user.length), combo.user.str);
goto end;
}
if (combo.password.str) // If password given
@@ -3642,6 +3641,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
{ // Should never happen
/* Restore the state of binlog format */
DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
+ thd->lex->restore_backup_query_tables_list(&backup);
if (save_binlog_row_based)
thd->set_current_stmt_binlog_format_row();
DBUG_RETURN(TRUE); /* purecov: deadcode */
@@ -8398,14 +8398,21 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
}
#ifndef EMBEDDED_LIBRARY
+
+/** Get a string according to the protocol of the underlying buffer. */
+typedef char * (*get_proto_string_func_t) (char **, size_t *, size_t *);
+
/**
- Get a null character terminated string from a user-supplied buffer.
+ Get a string formatted according to the 4.1 version of the MySQL protocol.
- @param buffer[in, out] Pointer to the buffer to be scanned.
+ @param buffer[in, out] Pointer to the user-supplied buffer to be scanned.
@param max_bytes_available[in, out] Limit the bytes to scan.
@param string_length[out] The number of characters scanned not including
the null character.
+ @remark Strings are always null character terminated in this version of the
+ protocol.
+
@remark The string_length does not include the terminating null character.
However, after the call, the buffer is increased by string_length+1
bytes, beyond the null character if there still available bytes to
@@ -8416,9 +8423,9 @@ static bool parse_com_change_user_packet(MPVIO_EXT *mpvio, uint packet_length)
*/
static
-char *get_null_terminated_string(char **buffer,
- size_t *max_bytes_available,
- size_t *string_length)
+char *get_41_protocol_string(char **buffer,
+ size_t *max_bytes_available,
+ size_t *string_length)
{
char *str= (char *)memchr(*buffer, '\0', *max_bytes_available);
@@ -8428,7 +8435,60 @@ char *get_null_terminated_string(char **buffer,
*string_length= (size_t)(str - *buffer);
*max_bytes_available-= *string_length + 1;
str= *buffer;
- *buffer += *string_length + 1;
+ *buffer += *string_length + 1;
+
+ return str;
+}
+
+
+/**
+ Get a string formatted according to the 4.0 version of the MySQL protocol.
+
+ @param buffer[in, out] Pointer to the user-supplied buffer to be scanned.
+ @param max_bytes_available[in, out] Limit the bytes to scan.
+ @param string_length[out] The number of characters scanned not including
+ the null character.
+
+ @remark If there are not enough bytes left after the current position of
+ the buffer to satisfy the current string, the string is considered
+ to be empty and a pointer to empty_c_string is returned.
+
+ @remark A string at the end of the packet is not null terminated.
+
+ @return Pointer to beginning of the string scanned, or a pointer to a empty
+ string.
+*/
+static
+char *get_40_protocol_string(char **buffer,
+ size_t *max_bytes_available,
+ size_t *string_length)
+{
+ char *str;
+ size_t len;
+
+ /* No bytes to scan left, treat string as empty. */
+ if ((*max_bytes_available) == 0)
+ {
+ *string_length= 0;
+ return empty_c_string;
+ }
+
+ str= (char *) memchr(*buffer, '\0', *max_bytes_available);
+
+ /*
+ If the string was not null terminated by the client,
+ the remainder of the packet is the string. Otherwise,
+ advance the buffer past the end of the null terminated
+ string.
+ */
+ if (str == NULL)
+ len= *string_length= *max_bytes_available;
+ else
+ len= (*string_length= (size_t)(str - *buffer)) + 1;
+
+ str= *buffer;
+ *buffer+= len;
+ *max_bytes_available-= len;
return str;
}
@@ -8439,7 +8499,7 @@ char *get_null_terminated_string(char **buffer,
@param buffer[in, out] The buffer to scan; updates position after scan.
@param max_bytes_available[in, out] Limit the number of bytes to scan
@param string_length[out] Number of characters scanned
-
+
@remark In case the length is zero, then the total size of the string is
considered to be 1 byte; the size byte.
@@ -8525,14 +8585,14 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
DBUG_PRINT("info", ("client capabilities: %lu", mpvio->client_capabilities));
if (mpvio->client_capabilities & CLIENT_SSL)
{
- char error_string[1024] __attribute__((unused));
+ unsigned long errptr;
/* Do the SSL layering. */
if (!ssl_acceptor_fd)
return packet_error;
DBUG_PRINT("info", ("IO layer change in progress..."));
- if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout))
+ if (sslaccept(ssl_acceptor_fd, net->vio, net->read_timeout, &errptr))
{
DBUG_PRINT("error", ("Failed to accept new SSL connection"));
return packet_error;
@@ -8555,7 +8615,20 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
if ((mpvio->client_capabilities & CLIENT_TRANSACTIONS) &&
opt_using_transactions)
net->return_status= mpvio->server_status;
-
+
+ /*
+ The 4.0 and 4.1 versions of the protocol differ on how strings
+ are terminated. In the 4.0 version, if a string is at the end
+ of the packet, the string is not null terminated. Do not assume
+ that the returned string is always null terminated.
+ */
+ get_proto_string_func_t get_string;
+
+ if (mpvio->client_capabilities & CLIENT_PROTOCOL_41)
+ get_string= get_41_protocol_string;
+ else
+ get_string= get_40_protocol_string;
+
/*
In order to safely scan a head for '\0' string terminators
we must keep track of how many bytes remain in the allocated
@@ -8564,8 +8637,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
size_t bytes_remaining_in_packet= pkt_len - (end - (char *)net->read_pos);
size_t user_len;
- char *user= get_null_terminated_string(&end, &bytes_remaining_in_packet,
- &user_len);
+ char *user= get_string(&end, &bytes_remaining_in_packet, &user_len);
if (user == NULL)
return packet_error;
@@ -8590,8 +8662,7 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
/*
Old passwords are zero terminated strings.
*/
- passwd= get_null_terminated_string(&end, &bytes_remaining_in_packet,
- &passwd_len);
+ passwd= get_string(&end, &bytes_remaining_in_packet, &passwd_len);
}
if (passwd == NULL)
@@ -8602,40 +8673,43 @@ static ulong parse_client_handshake_packet(MPVIO_EXT *mpvio,
if (mpvio->client_capabilities & CLIENT_CONNECT_WITH_DB)
{
- db= get_null_terminated_string(&end, &bytes_remaining_in_packet,
- &db_len);
+ db= get_string(&end, &bytes_remaining_in_packet, &db_len);
if (db == NULL)
return packet_error;
}
size_t client_plugin_len= 0;
- char *client_plugin= get_null_terminated_string(&end,
- &bytes_remaining_in_packet,
- &client_plugin_len);
+ char *client_plugin= get_string(&end, &bytes_remaining_in_packet,
+ &client_plugin_len);
if (client_plugin == NULL)
client_plugin= &empty_c_string[0];
-
+
char db_buff[NAME_LEN + 1]; // buffer to store db in utf8
char user_buff[USERNAME_LENGTH + 1]; // buffer to store user in utf8
uint dummy_errors;
-
- /* Since 4.1 all database names are stored in utf8 */
+
+ /*
+ Copy and convert the user and database names to the character set used
+ by the server. Since 4.1 all database names are stored in UTF-8. Also,
+ ensure that the names are properly null-terminated as this is relied
+ upon later.
+ */
if (db)
{
db_len= copy_and_convert(db_buff, sizeof(db_buff) - 1, system_charset_info,
db, db_len, mpvio->charset_adapter->charset(),
&dummy_errors);
+ db_buff[db_len]= '\0';
db= db_buff;
- db_buff[db_len]= 0;
}
user_len= copy_and_convert(user_buff, sizeof(user_buff) - 1,
- system_charset_info, user, user_len,
- mpvio->charset_adapter->charset(),
- &dummy_errors);
+ system_charset_info, user, user_len,
+ mpvio->charset_adapter->charset(),
+ &dummy_errors);
+ user_buff[user_len]= '\0';
user= user_buff;
- user_buff[user_len]= 0;
/* If username starts and ends in "'", chop them off */
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
@@ -8898,7 +8972,7 @@ err:
if (mpvio->status == MPVIO_EXT::FAILURE)
{
inc_host_errors(mpvio->ip);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0));
}
DBUG_RETURN(-1);
}
@@ -9484,7 +9558,7 @@ static int native_password_authenticate(MYSQL_PLUGIN_VIO *vio,
}
inc_host_errors(mpvio->ip);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0));
DBUG_RETURN(CR_ERROR);
}
@@ -9538,7 +9612,7 @@ static int old_password_authenticate(MYSQL_PLUGIN_VIO *vio,
}
inc_host_errors(mpvio->ip);
- my_error(ER_HANDSHAKE_ERROR, MYF(0), mpvio->auth_info.host_or_ip);
+ my_error(ER_HANDSHAKE_ERROR, MYF(0));
return CR_ERROR;
}
diff --git a/sql/sql_audit.cc b/sql/sql_audit.cc
index 74e9e603ebe..ba2c72b7266 100644
--- a/sql/sql_audit.cc
+++ b/sql/sql_audit.cc
@@ -21,11 +21,18 @@ extern int finalize_audit_plugin(st_plugin_int *plugin);
#ifndef EMBEDDED_LIBRARY
+struct st_mysql_event_generic
+{
+ unsigned int event_class;
+ const void *event;
+};
+
unsigned long mysql_global_audit_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
static mysql_mutex_t LOCK_audit_mask;
-static void event_class_dispatch(THD *thd, const struct mysql_event *event);
+static void event_class_dispatch(THD *thd, unsigned int event_class,
+ const void *event);
static inline
@@ -64,7 +71,6 @@ typedef void (*audit_handler_t)(THD *thd, uint event_subtype, va_list ap);
static void general_class_handler(THD *thd, uint event_subtype, va_list ap)
{
mysql_event_general event;
- event.event_class= MYSQL_AUDIT_GENERAL_CLASS;
event.event_subclass= event_subtype;
event.general_error_code= va_arg(ap, int);
event.general_thread_id= thd ? thd->thread_id : 0;
@@ -77,14 +83,13 @@ static void general_class_handler(THD *thd, uint event_subtype, va_list ap)
event.general_query_length= va_arg(ap, unsigned int);
event.general_charset= va_arg(ap, struct charset_info_st *);
event.general_rows= (unsigned long long) va_arg(ap, ha_rows);
- event_class_dispatch(thd, (const mysql_event*) &event);
+ event_class_dispatch(thd, MYSQL_AUDIT_GENERAL_CLASS, &event);
}
static void connection_class_handler(THD *thd, uint event_subclass, va_list ap)
{
mysql_event_connection event;
- event.event_class= MYSQL_AUDIT_CONNECTION_CLASS;
event.event_subclass= event_subclass;
event.status= va_arg(ap, int);
event.thread_id= va_arg(ap, unsigned long);
@@ -102,7 +107,7 @@ static void connection_class_handler(THD *thd, uint event_subclass, va_list ap)
event.ip_length= va_arg(ap, unsigned int);
event.database= va_arg(ap, const char *);
event.database_length= va_arg(ap, unsigned int);
- event_class_dispatch(thd, (const mysql_event *) &event);
+ event_class_dispatch(thd, MYSQL_AUDIT_CONNECTION_CLASS, &event);
}
@@ -433,18 +438,19 @@ int finalize_audit_plugin(st_plugin_int *plugin)
static my_bool plugins_dispatch(THD *thd, plugin_ref plugin, void *arg)
{
- const struct mysql_event *event= (const struct mysql_event *) arg;
+ const struct st_mysql_event_generic *event_generic=
+ (const struct st_mysql_event_generic *) arg;
unsigned long event_class_mask[MYSQL_AUDIT_CLASS_MASK_SIZE];
st_mysql_audit *data= plugin_data(plugin, struct st_mysql_audit *);
- set_audit_mask(event_class_mask, event->event_class);
+ set_audit_mask(event_class_mask, event_generic->event_class);
/* Check to see if the plugin is interested in this event */
if (check_audit_mask(data->class_mask, event_class_mask))
return 0;
/* Actually notify the plugin */
- data->event_notify(thd, event);
+ data->event_notify(thd, event_generic->event_class, event_generic->event);
return 0;
}
@@ -457,15 +463,19 @@ static my_bool plugins_dispatch(THD *thd, plugin_ref plugin, void *arg)
@param[in] event
*/
-static void event_class_dispatch(THD *thd, const struct mysql_event *event)
+static void event_class_dispatch(THD *thd, unsigned int event_class,
+ const void *event)
{
+ struct st_mysql_event_generic event_generic;
+ event_generic.event_class= event_class;
+ event_generic.event= event;
/*
Check if we are doing a slow global dispatch. This event occurs when
thd == NULL as it is not associated with any particular thread.
*/
if (unlikely(!thd))
{
- plugin_foreach(thd, plugins_dispatch, MYSQL_AUDIT_PLUGIN, (void*) event);
+ plugin_foreach(thd, plugins_dispatch, MYSQL_AUDIT_PLUGIN, &event_generic);
}
else
{
@@ -476,7 +486,7 @@ static void event_class_dispatch(THD *thd, const struct mysql_event *event)
plugins_last= plugins + thd->audit_class_plugins.elements;
for (; plugins < plugins_last; plugins++)
- plugins_dispatch(thd, *plugins, (void*) event);
+ plugins_dispatch(thd, *plugins, &event_generic);
}
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index f9d85b1e024..43ad400ce64 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -3854,7 +3854,7 @@ static bool auto_repair_table(THD *thd, TABLE_LIST *table_list)
{
/* Give right error message */
thd->clear_error();
- my_error(ER_NOT_KEYFILE, MYF(0), share->table_name.str, my_errno);
+ my_error(ER_NOT_KEYFILE, MYF(0), share->table_name.str);
sql_print_error("Couldn't repair table: %s.%s", share->db.str,
share->table_name.str);
if (entry->file)
@@ -7921,7 +7921,7 @@ bool setup_tables(THD *thd, Name_resolution_context *context,
}
if (tablenr > MAX_TABLES)
{
- my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
+ my_error(ER_TOO_MANY_TABLES,MYF(0), static_cast<int>(MAX_TABLES));
DBUG_RETURN(1);
}
for (table_list= tables;
diff --git a/sql/sql_binlog.cc b/sql/sql_binlog.cc
index 503d830a10e..3b91a68c341 100644
--- a/sql/sql_binlog.cc
+++ b/sql/sql_binlog.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005-2006 MySQL AB
+/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -242,7 +242,7 @@ void mysql_client_binlog_statement(THD* thd)
TODO: Maybe a better error message since the BINLOG statement
now contains several events.
*/
- my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement");
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
goto end;
}
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 4af038bb4e0..7c2ed133f70 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -11,7 +11,8 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
+
/*****************************************************************************
**
@@ -216,6 +217,252 @@ bool foreign_key_prefix(Key *a, Key *b)
** Thread specific functions
****************************************************************************/
+/**
+ 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;
+}
+
+/**
+ 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
+
+ @param thd THD object
+*/
+void thd_set_killed(THD *thd)
+{
+ thd->killed= THD::KILL_CONNECTION;
+}
+
+/**
+ Clear errors from the previous THD
+
+ @param thd THD object
+*/
+void thd_clear_errors(THD *thd)
+{
+ my_errno= 0;
+ thd->mysys_var->abort= 0;
+}
+
+/**
+ Set thread stack in THD object
+
+ @param thd Thread object
+ @param stack_start Start of stack to set in THD object
+*/
+void thd_set_thread_stack(THD *thd, char *stack_start)
+{
+ thd->thread_stack= stack_start;
+}
+
+/**
+ Lock connection data for the set of connections this connection
+ belongs to
+
+ @param thd THD object
+*/
+void thd_lock_thread_count(THD *)
+{
+ mysql_mutex_lock(&LOCK_thread_count);
+}
+
+/**
+ Lock connection data for the set of connections this connection
+ belongs to
+
+ @param thd THD object
+*/
+void thd_unlock_thread_count(THD *)
+{
+ mysql_cond_broadcast(&COND_thread_count);
+ mysql_mutex_unlock(&LOCK_thread_count);
+}
+
+/**
+ Close the socket used by this connection
+
+ @param thd THD object
+*/
+void thd_close_connection(THD *thd)
+{
+ if (thd->net.vio)
+ vio_close(thd->net.vio);
+}
+
+/**
+ Get current THD object from thread local data
+
+ @retval The THD object for the thread, NULL if not connection thread
+*/
+THD *thd_get_current_thd()
+{
+ return current_thd;
+}
+
+/**
+ Set up various THD data for a new connection
+
+ thd_new_connection_setup
+
+ @param thd THD object
+ @param stack_start Start of stack for connection
+*/
+void thd_new_connection_setup(THD *thd, char *stack_start)
+{
+#ifdef HAVE_PSI_INTERFACE
+ if (PSI_server)
+ thd_set_psi(thd,
+ PSI_server->new_thread(key_thread_one_connection,
+ thd,
+ thd_get_thread_id((MYSQL_THD)thd)));
+#endif
+ thd->set_time();
+ thd->prior_thr_create_utime= thd->thr_create_utime= thd->start_utime=
+ my_micro_time();
+ threads.append(thd);
+ thd_unlock_thread_count(thd);
+ DBUG_PRINT("info", ("init new connection. thd: 0x%lx fd: %d",
+ (ulong)thd, thd->net.vio->sd));
+ thd_set_thread_stack(thd, stack_start);
+}
+
+/**
+ Lock data that needs protection in THD object
+
+ @param thd THD object
+*/
+void thd_lock_data(THD *thd)
+{
+ mysql_mutex_lock(&thd->LOCK_thd_data);
+}
+
+/**
+ Unlock data that needs protection in THD object
+
+ @param thd THD object
+*/
+void thd_unlock_data(THD *thd)
+{
+ mysql_mutex_unlock(&thd->LOCK_thd_data);
+}
+
+/**
+ Support method to check if connection has already started transcaction
+
+ @param client_cntx Low level client context
+
+ @retval TRUE if connection already started transaction
+*/
+bool thd_is_transaction_active(THD *thd)
+{
+ return thd->transaction.is_active();
+}
+
+/**
+ Check if there is buffered data on the socket representing the connection
+
+ @param thd THD object
+*/
+int thd_connection_has_data(THD *thd)
+{
+ Vio *vio= thd->net.vio;
+ return vio->has_data(vio);
+}
+
+/**
+ Set reading/writing on socket, used by SHOW PROCESSLIST
+
+ @param thd THD object
+ @param val Value to set it to (0 or 1)
+*/
+void thd_set_net_read_write(THD *thd, uint val)
+{
+ thd->net.reading_or_writing= val;
+}
+
+/**
+ Set reference to mysys variable in THD object
+
+ @param thd THD object
+ @param mysys_var Reference to set
+*/
+void thd_set_mysys_var(THD *thd, st_my_thread_var *mysys_var)
+{
+ thd->set_mysys_var(mysys_var);
+}
+
+/**
+ Get socket file descriptor for this connection
+
+ @param thd THD object
+
+ @retval Socket of the connection
+*/
+my_socket thd_get_fd(THD *thd)
+{
+ return thd->net.vio->sd;
+}
+
+/**
+ Get thread attributes for connection threads
+
+ @retval Reference to thread attribute for connection threads
+*/
+pthread_attr_t *get_connection_attrib(void)
+{
+ return &connection_attrib;
+}
+
+/**
+ Get max number of connections
+
+ @retval Max number of connections for MySQL Server
+*/
+ulong get_max_connections(void)
+{
+ return max_connections;
+}
+
/*
The following functions form part of the C plugin API
*/
@@ -493,7 +740,7 @@ bool Drop_table_error_handler::handle_condition(THD *thd,
THD::THD()
- :Statement(&main_lex, &main_mem_root, CONVENTIONAL_EXECUTION,
+ :Statement(&main_lex, &main_mem_root, STMT_CONVENTIONAL_EXECUTION,
/* statement id */ 0),
rli_fake(0),
user_time(0), in_sub_stmt(0),
@@ -1354,6 +1601,25 @@ bool THD::store_globals()
return 0;
}
+/*
+ Remove the thread specific info (THD and mem_root pointer) stored during
+ store_global call for this thread.
+*/
+bool THD::restore_globals()
+{
+ /*
+ Assert that thread_stack is initialized: it's necessary to be able
+ to track stack overrun.
+ */
+ DBUG_ASSERT(thread_stack);
+
+ /* Undocking the thread specific data. */
+ my_pthread_setspecific_ptr(THR_THD, NULL);
+ my_pthread_setspecific_ptr(THR_MALLOC, NULL);
+
+ return 0;
+}
+
/*
Cleanup after query.
@@ -2191,7 +2457,7 @@ bool select_export::send_data(List<Item> &items)
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
"string", printable_buff,
- item->name, row_count);
+ item->name, static_cast<long>(row_count));
}
else if (from_end_pos < res->ptr() + res->length())
{
@@ -2200,7 +2466,7 @@ bool select_export::send_data(List<Item> &items)
*/
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
WARN_DATA_TRUNCATED, ER(WARN_DATA_TRUNCATED),
- item->full_name(), row_count);
+ item->full_name(), static_cast<long>(row_count));
}
cvt_str.length(bytes);
res= &cvt_str;
@@ -3297,7 +3563,7 @@ extern "C" void thd_pool_wait_end(MYSQL_THD thd);
thd_wait_end MUST be called immediately after waking up again.
*/
-extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type)
+extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
{
MYSQL_CALLBACK(thread_scheduler, thd_wait_begin, (thd, wait_type));
}
@@ -3313,7 +3579,7 @@ extern "C" void thd_wait_end(MYSQL_THD thd)
MYSQL_CALLBACK(thread_scheduler, thd_wait_end, (thd));
}
#else
-extern "C" void thd_wait_begin(MYSQL_THD thd, thd_wait_type wait_type)
+extern "C" void thd_wait_begin(MYSQL_THD thd, int wait_type)
{
/* do NOTHING for the embedded library */
return;
diff --git a/sql/sql_class.h b/sql/sql_class.h
index 56d85e7cb6d..a2c622b2326 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -624,14 +624,14 @@ public:
/*
The states relfects three diffrent life cycles for three
different types of statements:
- Prepared statement: INITIALIZED -> PREPARED -> EXECUTED.
- Stored procedure: INITIALIZED_FOR_SP -> EXECUTED.
- Other statements: CONVENTIONAL_EXECUTION never changes.
+ Prepared statement: STMT_INITIALIZED -> STMT_PREPARED -> STMT_EXECUTED.
+ Stored procedure: STMT_INITIALIZED_FOR_SP -> STMT_EXECUTED.
+ Other statements: STMT_CONVENTIONAL_EXECUTION never changes.
*/
enum enum_state
{
- INITIALIZED= 0, INITIALIZED_FOR_SP= 1, PREPARED= 2,
- CONVENTIONAL_EXECUTION= 3, EXECUTED= 4, ERROR= -1
+ STMT_INITIALIZED= 0, STMT_INITIALIZED_FOR_SP= 1, STMT_PREPARED= 2,
+ STMT_CONVENTIONAL_EXECUTION= 3, STMT_EXECUTED= 4, STMT_ERROR= -1
};
enum_state state;
@@ -654,13 +654,13 @@ public:
virtual Type type() const;
virtual ~Query_arena() {};
- inline bool is_stmt_prepare() const { return state == INITIALIZED; }
+ inline bool is_stmt_prepare() const { return state == STMT_INITIALIZED; }
inline bool is_stmt_prepare_or_first_sp_execute() const
- { return (int)state < (int)PREPARED; }
+ { return (int)state < (int)STMT_PREPARED; }
inline bool is_stmt_prepare_or_first_stmt_execute() const
- { return (int)state <= (int)PREPARED; }
+ { return (int)state <= (int)STMT_PREPARED; }
inline bool is_conventional() const
- { return state == CONVENTIONAL_EXECUTION; }
+ { return state == STMT_CONVENTIONAL_EXECUTION; }
inline void* alloc(size_t size) { return alloc_root(mem_root,size); }
inline void* calloc(size_t size)
@@ -2199,6 +2199,7 @@ public:
void cleanup(void);
void cleanup_after_query();
bool store_globals();
+ bool restore_globals();
#ifdef SIGNAL_WITH_VIO_CLOSE
inline void set_active_vio(Vio* vio)
{
diff --git a/sql/sql_connect.cc b/sql/sql_connect.cc
index 9d7e20c1d6e..c3b978d7659 100644
--- a/sql/sql_connect.cc
+++ b/sql/sql_connect.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2007 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2007, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
Functions to autenticate and handle reqests for a connection
@@ -466,7 +465,7 @@ static int check_connection(THD *thd)
if (vio_peer_addr(net->vio, ip, &thd->peer_port, NI_MAXHOST))
{
- my_error(ER_BAD_HOST_ERROR, MYF(0), thd->main_security_ctx.host_or_ip);
+ my_error(ER_BAD_HOST_ERROR, MYF(0));
return 1;
}
if (!(thd->main_security_ctx.ip= my_strdup(ip,MYF(MY_WME))))
@@ -477,7 +476,7 @@ static int check_connection(THD *thd)
if (ip_to_hostname(&net->vio->remote, thd->main_security_ctx.ip,
&thd->main_security_ctx.host, &connect_errors))
{
- my_error(ER_BAD_HOST_ERROR, MYF(0), ip);
+ my_error(ER_BAD_HOST_ERROR, MYF(0));
return 1;
}
@@ -708,6 +707,32 @@ pthread_handler_t handle_one_connection(void *arg)
return 0;
}
+bool thd_prepare_connection(THD *thd)
+{
+ bool rc;
+ lex_start(thd);
+ rc= login_connection(thd);
+ MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd);
+ if (rc)
+ return rc;
+
+ MYSQL_CONNECTION_START(thd->thread_id, &thd->security_ctx->priv_user[0],
+ (char *) thd->security_ctx->host_or_ip);
+
+ prepare_new_connection_state(thd);
+ return FALSE;
+}
+
+bool thd_is_connection_alive(THD *thd)
+{
+ NET *net= &thd->net;
+ if (!net->error &&
+ net->vio != 0 &&
+ !(thd->killed == THD::KILL_CONNECTION))
+ return TRUE;
+ return FALSE;
+}
+
void do_handle_one_connection(THD *thd_arg)
{
THD *thd= thd_arg;
@@ -750,22 +775,13 @@ void do_handle_one_connection(THD *thd_arg)
for (;;)
{
- NET *net= &thd->net;
bool rc;
- lex_start(thd);
- rc= login_connection(thd);
- MYSQL_AUDIT_NOTIFY_CONNECTION_CONNECT(thd);
+ rc= thd_prepare_connection(thd);
if (rc)
goto end_thread;
- MYSQL_CONNECTION_START(thd->thread_id, &thd->security_ctx->priv_user[0],
- (char *) thd->security_ctx->host_or_ip);
-
- prepare_new_connection_state(thd);
-
- while (!net->error && net->vio != 0 &&
- !(thd->killed == THD::KILL_CONNECTION))
+ while (thd_is_connection_alive(thd))
{
mysql_audit_release(thd);
if (do_command(thd))
diff --git a/sql/sql_connect.h b/sql/sql_connect.h
index ff5a20dfbc2..1b71d95323d 100644
--- a/sql/sql_connect.h
+++ b/sql/sql_connect.h
@@ -35,6 +35,8 @@ void time_out_user_resource_limits(THD *thd, USER_CONN *uc);
void decrease_user_connections(USER_CONN *uc);
bool thd_init_client_charset(THD *thd, uint cs_number);
bool setup_connection_thread_globals(THD *thd);
+bool thd_prepare_connection(THD *thd);
+bool thd_is_connection_alive(THD *thd);
int check_user(THD *thd, enum enum_server_command command,
const char *passwd, uint passwd_len, const char *db,
diff --git a/sql/sql_cursor.h b/sql/sql_cursor.h
index ed7bfac821a..d19d14fa167 100644
--- a/sql/sql_cursor.h
+++ b/sql/sql_cursor.h
@@ -46,7 +46,7 @@ protected:
select_result *result;
public:
Server_side_cursor(MEM_ROOT *mem_root_arg, select_result *result_arg)
- :Query_arena(mem_root_arg, INITIALIZED), result(result_arg)
+ :Query_arena(mem_root_arg, STMT_INITIALIZED), result(result_arg)
{}
virtual bool is_open() const= 0;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 4475e087163..10afb8962a7 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -1,4 +1,4 @@
-/* Copyright 2000-2008 MySQL AB, 2008-2009 Sun Microsystems, Inc.
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/* Insert of records */
@@ -3889,7 +3888,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (table->s->fields < values.elements)
{
- my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1L);
DBUG_RETURN(-1);
}
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index f82e0948b54..96382400c2c 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. All rights reserved.
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
@@ -743,8 +743,7 @@ static bool write_execute_load_query_log_event(THD *thd, sql_exchange* ex,
pfields.append("`");
pfields.append(item->name);
pfields.append("`");
- pfields.append("=");
- val->print(&pfields, QT_ORDINARY);
+ pfields.append(val->name);
}
}
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 24f7fdb8e61..44a9243d8f5 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#define MYSQL_LEX 1
#include "my_global.h"
@@ -1749,6 +1749,67 @@ bool sp_process_definer(THD *thd)
/**
+ Auxiliary call that opens and locks tables for LOCK TABLES statement
+ and initializes the list of locked tables.
+
+ @param thd Thread context.
+ @param tables List of tables to be locked.
+
+ @return FALSE in case of success, TRUE in case of error.
+*/
+
+static bool lock_tables_open_and_lock_tables(THD *thd, TABLE_LIST *tables)
+{
+ Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
+ uint counter;
+ TABLE_LIST *table;
+
+ thd->in_lock_tables= 1;
+
+ if (open_tables(thd, &tables, &counter, 0, &lock_tables_prelocking_strategy))
+ goto err;
+
+ /*
+ We allow to change temporary tables even if they were locked for read
+ by LOCK TABLES. To avoid a discrepancy between lock acquired at LOCK
+ TABLES time and by the statement which is later executed under LOCK TABLES
+ we ensure that for temporary tables we always request a write lock (such
+ discrepancy can cause problems for the storage engine).
+ We don't set TABLE_LIST::lock_type in this case as this might result in
+ extra warnings from THD::decide_logging_format() even though binary logging
+ is totally irrelevant for LOCK TABLES.
+ */
+ for (table= tables; table; table= table->next_global)
+ if (!table->placeholder() && table->table->s->tmp_table)
+ table->table->reginfo.lock_type= TL_WRITE;
+
+ if (lock_tables(thd, tables, counter, 0) ||
+ thd->locked_tables_list.init_locked_tables(thd))
+ goto err;
+
+ thd->in_lock_tables= 0;
+
+ return FALSE;
+
+err:
+ thd->in_lock_tables= 0;
+
+ trans_rollback_stmt(thd);
+ /*
+ Need to end the current transaction, so the storage engine (InnoDB)
+ can free its locks if LOCK TABLES locked some tables before finding
+ that it can't lock a table in its list
+ */
+ trans_commit_implicit(thd);
+ /* Close tables and release metadata locks. */
+ close_thread_tables(thd);
+ DBUG_ASSERT(!thd->locked_tables_mode);
+ thd->mdl_context.release_transactional_locks();
+ return TRUE;
+}
+
+
+/**
Execute command saved in thd and lex->sql_command.
@param thd Thread handle
@@ -3093,31 +3154,11 @@ end_with_restore_list:
goto error;
thd->variables.option_bits|= OPTION_TABLE_LOCK;
- thd->in_lock_tables=1;
- {
- Lock_tables_prelocking_strategy lock_tables_prelocking_strategy;
-
- res= (open_and_lock_tables(thd, all_tables, FALSE, 0,
- &lock_tables_prelocking_strategy) ||
- thd->locked_tables_list.init_locked_tables(thd));
- }
-
- thd->in_lock_tables= 0;
+ res= lock_tables_open_and_lock_tables(thd, all_tables);
if (res)
{
- trans_rollback_stmt(thd);
- /*
- Need to end the current transaction, so the storage engine (InnoDB)
- can free its locks if LOCK TABLES locked some tables before finding
- that it can't lock a table in its list
- */
- trans_commit_implicit(thd);
- /* Close tables and release metadata locks. */
- close_thread_tables(thd);
- DBUG_ASSERT(!thd->locked_tables_mode);
- thd->mdl_context.release_transactional_locks();
thd->variables.option_bits&= ~(OPTION_TABLE_LOCK);
}
else
@@ -3412,8 +3453,7 @@ end_with_restore_list:
hostname_requires_resolving(user->host.str))
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_HOSTNAME_WONT_WORK,
- ER(ER_WARN_HOSTNAME_WONT_WORK),
- user->host.str);
+ ER(ER_WARN_HOSTNAME_WONT_WORK));
// Are we trying to change a password of another user
DBUG_ASSERT(user->host.str != 0);
@@ -5305,7 +5345,7 @@ mysql_new_select(LEX *lex, bool move_down)
lex->nest_level++;
if (lex->nest_level > (int) MAX_SELECT_NESTING)
{
- my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT,MYF(0),MAX_SELECT_NESTING);
+ my_error(ER_TOO_HIGH_LEVEL_OF_NESTING_FOR_SELECT, MYF(0));
DBUG_RETURN(1);
}
select_lex->nest_level= lex->nest_level;
diff --git a/sql/sql_partition.cc b/sql/sql_partition.cc
index 52d6757b03a..354548cbda4 100644
--- a/sql/sql_partition.cc
+++ b/sql/sql_partition.cc
@@ -7025,7 +7025,7 @@ void set_key_field_ptr(KEY *key_info, const uchar *new_buf,
void mem_alloc_error(size_t size)
{
- my_error(ER_OUTOFMEMORY, MYF(0), size);
+ my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(size));
}
#ifdef WITH_PARTITION_STORAGE_ENGINE
diff --git a/sql/sql_plugin.cc b/sql/sql_plugin.cc
index dc5b7b5a37b..5e092f3ef79 100644
--- a/sql/sql_plugin.cc
+++ b/sql/sql_plugin.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2005 MySQL AB, 2009 Sun Microsystems, Inc.
+/* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
#include "sql_priv.h" // SHOW_MY_BOOL
#include "unireg.h"
@@ -548,7 +548,8 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
if (!cur)
{
free_plugin_mem(&plugin_dl);
- report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
+ report_error(report, ER_OUTOFMEMORY,
+ static_cast<int>(plugin_dl.dl.length));
DBUG_RETURN(0);
}
/*
@@ -570,7 +571,8 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
if (! (plugin_dl.dl.str= (char*) my_malloc(plugin_dl.dl.length, MYF(0))))
{
free_plugin_mem(&plugin_dl);
- report_error(report, ER_OUTOFMEMORY, plugin_dl.dl.length);
+ report_error(report, ER_OUTOFMEMORY,
+ static_cast<int>(plugin_dl.dl.length));
DBUG_RETURN(0);
}
plugin_dl.dl.length= copy_and_convert(plugin_dl.dl.str, plugin_dl.dl.length,
@@ -581,7 +583,8 @@ static st_plugin_dl *plugin_dl_add(const LEX_STRING *dl, int report)
if (! (tmp= plugin_dl_insert_or_reuse(&plugin_dl)))
{
free_plugin_mem(&plugin_dl);
- report_error(report, ER_OUTOFMEMORY, sizeof(struct st_plugin_dl));
+ report_error(report, ER_OUTOFMEMORY,
+ static_cast<int>(sizeof(struct st_plugin_dl)));
DBUG_RETURN(0);
}
DBUG_RETURN(tmp);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index 779569b10fb..7f2ab1aeb8e 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -11,7 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/**
@file
@@ -1467,7 +1467,7 @@ static int mysql_test_select(Prepared_statement *stmt,
if (!lex->result && !(lex->result= new (stmt->mem_root) select_send))
{
- my_error(ER_OUTOFMEMORY, MYF(0), sizeof(select_send));
+ my_error(ER_OUTOFMEMORY, MYF(0), static_cast<int>(sizeof(select_send)));
goto error;
}
@@ -2543,7 +2543,7 @@ void mysqld_stmt_execute(THD *thd, char *packet_arg, uint packet_length)
if (!(stmt= find_prepared_statement(thd, stmt_id)))
{
char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), static_cast<int>(sizeof(llbuf)),
llstr(stmt_id, llbuf), "mysqld_stmt_execute");
DBUG_VOID_RETURN;
}
@@ -2597,7 +2597,7 @@ void mysql_sql_stmt_execute(THD *thd)
if (!(stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
{
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
- name->length, name->str, "EXECUTE");
+ static_cast<int>(name->length), name->str, "EXECUTE");
DBUG_VOID_RETURN;
}
@@ -2639,7 +2639,7 @@ void mysqld_stmt_fetch(THD *thd, char *packet, uint packet_length)
if (!(stmt= find_prepared_statement(thd, stmt_id)))
{
char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), static_cast<int>(sizeof(llbuf)),
llstr(stmt_id, llbuf), "mysqld_stmt_fetch");
DBUG_VOID_RETURN;
}
@@ -2699,7 +2699,7 @@ void mysqld_stmt_reset(THD *thd, char *packet)
if (!(stmt= find_prepared_statement(thd, stmt_id)))
{
char llbuf[22];
- my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), sizeof(llbuf),
+ my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), static_cast<int>(sizeof(llbuf)),
llstr(stmt_id, llbuf), "mysqld_stmt_reset");
DBUG_VOID_RETURN;
}
@@ -2712,7 +2712,7 @@ void mysqld_stmt_reset(THD *thd, char *packet)
*/
reset_stmt_params(stmt);
- stmt->state= Query_arena::PREPARED;
+ stmt->state= Query_arena::STMT_PREPARED;
general_log_print(thd, thd->command, NullS);
@@ -2774,7 +2774,7 @@ void mysql_sql_stmt_close(THD *thd)
if (! (stmt= (Prepared_statement*) thd->stmt_map.find_by_name(name)))
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
- name->length, name->str, "DEALLOCATE PREPARE");
+ static_cast<int>(name->length), name->str, "DEALLOCATE PREPARE");
else if (stmt->is_in_use())
my_error(ER_PS_NO_RECURSION, MYF(0));
else
@@ -2831,7 +2831,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
if (param_number >= stmt->param_count)
{
/* Error will be sent in execute call */
- stmt->state= Query_arena::ERROR;
+ stmt->state= Query_arena::STMT_ERROR;
stmt->last_errno= ER_WRONG_ARGUMENTS;
sprintf(stmt->last_error, ER(ER_WRONG_ARGUMENTS),
"mysqld_stmt_send_long_data");
@@ -2855,7 +2855,7 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
#endif
if (thd->stmt_da->is_error())
{
- stmt->state= Query_arena::ERROR;
+ stmt->state= Query_arena::STMT_ERROR;
stmt->last_errno= thd->stmt_da->sql_errno();
strncpy(stmt->last_error, thd->stmt_da->message(), MYSQL_ERRMSG_SIZE);
}
@@ -3010,7 +3010,7 @@ end:
Prepared_statement::Prepared_statement(THD *thd_arg)
:Statement(NULL, &main_mem_root,
- INITIALIZED, ++thd_arg->statement_id_counter),
+ STMT_INITIALIZED, ++thd_arg->statement_id_counter),
thd(thd_arg),
result(thd_arg),
param_array(0),
@@ -3283,7 +3283,7 @@ bool Prepared_statement::prepare(const char *packet, uint packet_len)
{
setup_set_params();
lex->context_analysis_only&= ~CONTEXT_ANALYSIS_ONLY_PREPARE;
- state= Query_arena::PREPARED;
+ state= Query_arena::STMT_PREPARED;
flags&= ~ (uint) IS_IN_USE;
/*
@@ -3401,7 +3401,7 @@ Prepared_statement::execute_loop(String *expanded_query,
int reprepare_attempt= 0;
/* Check if we got an error when sending long data */
- if (state == Query_arena::ERROR)
+ if (state == Query_arena::STMT_ERROR)
{
my_message(last_errno, last_error, MYF(0));
return TRUE;
@@ -3464,7 +3464,7 @@ Prepared_statement::execute_server_runnable(Server_runnable *server_runnable)
Item_change_list save_change_list;
thd->change_list.move_elements_to(&save_change_list);
- state= CONVENTIONAL_EXECUTION;
+ state= STMT_CONVENTIONAL_EXECUTION;
if (!(lex= new (mem_root) st_lex_local))
return TRUE;
@@ -3799,8 +3799,8 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
thd->set_statement(&stmt_backup);
thd->stmt_arena= old_stmt_arena;
- if (state == Query_arena::PREPARED)
- state= Query_arena::EXECUTED;
+ if (state == Query_arena::STMT_PREPARED)
+ state= Query_arena::STMT_EXECUTED;
if (error == 0 && this->lex->sql_command == SQLCOM_CALL)
{
diff --git a/sql/sql_reload.cc b/sql/sql_reload.cc
index a09aa5511bd..b567e3a1f85 100644
--- a/sql/sql_reload.cc
+++ b/sql/sql_reload.cc
@@ -86,7 +86,7 @@ bool reload_acl_and_cache(THD *thd, unsigned long options,
When an error is returned, my_message may have not been called and
the client will hang waiting for a response.
*/
- my_error(ER_UNKNOWN_ERROR, MYF(0), "FLUSH PRIVILEGES failed");
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
}
}
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 9783917aaf0..717356a1b8c 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -1490,7 +1490,7 @@ bool change_master(THD* thd, Master_info* mi)
get_dynamic(&lex_mi->repl_ignore_server_ids, (uchar*) &s_id, i);
if (s_id == ::server_id && replicate_same_server_id)
{
- my_error(ER_SLAVE_IGNORE_SERVER_IDS, MYF(0), s_id);
+ my_error(ER_SLAVE_IGNORE_SERVER_IDS, MYF(0), static_cast<int>(s_id));
ret= TRUE;
goto err;
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 9e9de5e3524..fb5ed62ecdf 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -2407,12 +2407,11 @@ bool schema_table_store_record(THD *thd, TABLE *table)
}
-int make_table_list(THD *thd, SELECT_LEX *sel,
- LEX_STRING *db_name, LEX_STRING *table_name)
+static int make_table_list(THD *thd, SELECT_LEX *sel,
+ LEX_STRING *db_name, LEX_STRING *table_name)
{
Table_ident *table_ident;
table_ident= new Table_ident(thd, *db_name, *table_name, 1);
- sel->init_query();
if (!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ, MDL_SHARED_READ))
return 1;
return 0;
@@ -2982,91 +2981,190 @@ make_table_name_list(THD *thd, List<LEX_STRING> *table_names, LEX *lex,
/**
- @brief Fill I_S table for SHOW COLUMNS|INDEX commands
+ Fill I_S table with data obtained by performing full-blown table open.
+
+ @param thd Thread handler.
+ @param is_show_fields_or_keys Indicates whether it is a legacy SHOW
+ COLUMNS or SHOW KEYS statement.
+ @param table TABLE object for I_S table to be filled.
+ @param schema_table I_S table description structure.
+ @param orig_db_name Database name.
+ @param orig_table_name Table name.
+ @param open_tables_state_backup Open_tables_state object which is used
+ to save/restore original status of
+ variables related to open tables state.
+ @param can_deadlock Indicates that deadlocks are possible
+ due to metadata locks, so to avoid
+ them we should not wait in case if
+ conflicting lock is present.
+
+ @retval FALSE - Success.
+ @retval TRUE - Failure.
+*/
+static bool
+fill_schema_table_by_open(THD *thd, bool is_show_fields_or_keys,
+ TABLE *table, ST_SCHEMA_TABLE *schema_table,
+ LEX_STRING *orig_db_name,
+ LEX_STRING *orig_table_name,
+ Open_tables_backup *open_tables_state_backup,
+ bool can_deadlock)
+{
+ Query_arena i_s_arena(thd->mem_root,
+ Query_arena::STMT_CONVENTIONAL_EXECUTION),
+ backup_arena, *old_arena;
+ LEX *old_lex= thd->lex, temp_lex, *lex;
+ LEX_STRING db_name, table_name;
+ TABLE_LIST *table_list;
+ bool result= true;
+
+ DBUG_ENTER("fill_schema_table_by_open");
+ /*
+ When a view is opened its structures are allocated on a permanent
+ statement arena and linked into the LEX tree for the current statement
+ (this happens even in cases when view is handled through TEMPTABLE
+ algorithm).
- @param[in] thd thread handler
- @param[in] tables TABLE_LIST for I_S table
- @param[in] schema_table pointer to I_S structure
- @param[in] can_deadlock Indicates that deadlocks are possible
- due to metadata locks, so to avoid
- them we should not wait in case if
- conflicting lock is present.
- @param[in] open_tables_state_backup pointer to Open_tables_backup object
- which is used to save|restore original
- status of variables related to
- open tables state
+ To prevent this process from unnecessary hogging of memory in the permanent
+ arena of our I_S query and to avoid damaging its LEX we use temporary
+ arena and LEX for table/view opening.
- @return Operation status
- @retval 0 success
- @retval 1 error
-*/
+ Use temporary arena instead of statement permanent arena. Also make
+ it active arena and save original one for successive restoring.
+ */
+ old_arena= thd->stmt_arena;
+ thd->stmt_arena= &i_s_arena;
+ thd->set_n_backup_active_arena(&i_s_arena, &backup_arena);
-static int
-fill_schema_show_cols_or_idxs(THD *thd, TABLE_LIST *tables,
- ST_SCHEMA_TABLE *schema_table,
- bool can_deadlock,
- Open_tables_backup *open_tables_state_backup)
-{
- LEX *lex= thd->lex;
- bool res;
- LEX_STRING tmp_lex_string, tmp_lex_string1, *db_name, *table_name;
- enum_sql_command save_sql_command= lex->sql_command;
- TABLE_LIST *show_table_list= tables->schema_select_lex->table_list.first;
- TABLE *table= tables->table;
- int error= 1;
- DBUG_ENTER("fill_schema_show");
+ /* Prepare temporary LEX. */
+ thd->lex= lex= &temp_lex;
+ lex_start(thd);
+
+ /* Disable constant subquery evaluation as we won't be locking tables. */
+ lex->context_analysis_only= CONTEXT_ANALYSIS_ONLY_VIEW;
- lex->all_selects_list= tables->schema_select_lex;
/*
- Restore thd->temporary_tables to be able to process
- temporary tables(only for 'show index' & 'show columns').
- This should be changed when processing of temporary tables for
- I_S tables will be done.
+ Some of process_table() functions rely on wildcard being passed from
+ old LEX (or at least being initialized).
*/
- thd->temporary_tables= open_tables_state_backup->temporary_tables;
+ lex->wild= old_lex->wild;
+
+ /*
+ Since make_table_list() might change database and table name passed
+ to it we create copies of orig_db_name and orig_table_name here.
+ These copies are used for make_table_list() while unaltered values
+ are passed to process_table() functions.
+ */
+ if (!thd->make_lex_string(&db_name, orig_db_name->str,
+ orig_db_name->length, FALSE) ||
+ !thd->make_lex_string(&table_name, orig_table_name->str,
+ orig_table_name->length, FALSE))
+ goto end;
+
+ /*
+ Create table list element for table to be open. Link it with the
+ temporary LEX. The latter is required to correctly open views and
+ produce table describing their structure.
+ */
+ if (make_table_list(thd, &lex->select_lex, &db_name, &table_name))
+ goto end;
+
+ table_list= lex->select_lex.table_list.first;
+
+ if (is_show_fields_or_keys)
+ {
+ /*
+ Restore thd->temporary_tables to be able to process
+ temporary tables (only for 'show index' & 'show columns').
+ This should be changed when processing of temporary tables for
+ I_S tables will be done.
+ */
+ thd->temporary_tables= open_tables_state_backup->temporary_tables;
+ }
+ else
+ {
+ /*
+ Apply optimization flags for table opening which are relevant for
+ this I_S table. We can't do this for SHOW COLUMNS/KEYS because of
+ backward compatibility.
+ */
+ table_list->i_s_requested_object= schema_table->i_s_requested_object;
+ }
+
/*
Let us set fake sql_command so views won't try to merge
themselves into main statement. If we don't do this,
SELECT * from information_schema.xxxx will cause problems.
- SQLCOM_SHOW_FIELDS is used because it satisfies 'only_view_structure()'
+ SQLCOM_SHOW_FIELDS is used because it satisfies
+ 'only_view_structure()'.
*/
lex->sql_command= SQLCOM_SHOW_FIELDS;
- res= open_normal_and_derived_tables(thd, show_table_list,
- (MYSQL_OPEN_IGNORE_FLUSH |
- MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
- (can_deadlock ?
- MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)));
- lex->sql_command= save_sql_command;
+ result= open_normal_and_derived_tables(thd, table_list,
+ (MYSQL_OPEN_IGNORE_FLUSH |
+ MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
+ (can_deadlock ?
+ MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)));
+ /*
+ Restore old value of sql_command back as it is being looked at in
+ process_table() function.
+ */
+ lex->sql_command= old_lex->sql_command;
DEBUG_SYNC(thd, "after_open_table_ignore_flush");
/*
- get_all_tables() returns 1 on failure and 0 on success thus
- return only these and not the result code of ::process_table()
-
- We should use show_table_list->alias instead of
- show_table_list->table_name because table_name
- could be changed during opening of I_S tables. It's safe
- to use alias because alias contains original table name
- in this case(this part of code is used only for
- 'show columns' & 'show statistics' commands).
+ XXX: show_table_list has a flag i_is_requested,
+ and when it's set, open_normal_and_derived_tables()
+ can return an error without setting an error message
+ in THD, which is a hack. This is why we have to
+ check for res, then for thd->is_error() and only then
+ for thd->main_da.sql_errno().
+
+ Again we don't do this for SHOW COLUMNS/KEYS because
+ of backward compatibility.
*/
- table_name= thd->make_lex_string(&tmp_lex_string1, show_table_list->alias,
- strlen(show_table_list->alias), FALSE);
- if (!show_table_list->view)
- db_name= thd->make_lex_string(&tmp_lex_string, show_table_list->db,
- show_table_list->db_length, FALSE);
- else
- db_name= &show_table_list->view_db;
-
-
- error= test(schema_table->process_table(thd, show_table_list,
- table, res, db_name,
- table_name));
- thd->temporary_tables= 0;
- close_tables_for_reopen(thd, &show_table_list,
- open_tables_state_backup->mdl_system_tables_svp);
- DBUG_RETURN(error);
+ if (!is_show_fields_or_keys && result && thd->is_error() &&
+ thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE)
+ {
+ /*
+ Hide error for a non-existing table.
+ For example, this error can occur when we use a where condition
+ with a db name and table, but the table does not exist.
+ */
+ result= false;
+ thd->clear_error();
+ }
+ else
+ {
+ result= schema_table->process_table(thd, table_list,
+ table, result,
+ orig_db_name,
+ orig_table_name);
+ }
+
+
+end:
+ lex->unit.cleanup();
+
+ /* Restore original LEX value, statement's arena and THD arena values. */
+ lex_end(thd->lex);
+
+ if (i_s_arena.free_list)
+ i_s_arena.free_items();
+
+ /*
+ For safety reset list of open temporary tables before closing
+ all tables open within this Open_tables_state.
+ */
+ thd->temporary_tables= NULL;
+ close_thread_tables(thd);
+ thd->mdl_context.rollback_to_savepoint(open_tables_state_backup->mdl_system_tables_svp);
+
+ thd->lex= old_lex;
+
+ thd->stmt_arena= old_arena;
+ thd->restore_active_arena(&i_s_arena, &backup_arena);
+
+ DBUG_RETURN(result);
}
@@ -3477,10 +3575,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
LEX *lex= thd->lex;
TABLE *table= tables->table;
- SELECT_LEX *old_all_select_lex= lex->all_selects_list;
SELECT_LEX *lsel= tables->schema_select_lex;
ST_SCHEMA_TABLE *schema_table= tables->schema_table;
- SELECT_LEX sel;
LOOKUP_FIELD_VALUES lookup_field_vals;
LEX_STRING *db_name, *table_name;
bool with_i_schema;
@@ -3488,11 +3584,8 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
List<LEX_STRING> db_names;
List_iterator_fast<LEX_STRING> it(db_names);
COND *partial_cond= 0;
- uint derived_tables= lex->derived_tables;
int error= 1;
Open_tables_backup open_tables_state_backup;
- uint8 save_context_analysis_only= lex->context_analysis_only;
- Query_tables_list query_tables_list_backup;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
Security_context *sctx= thd->security_ctx;
#endif
@@ -3511,15 +3604,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
*/
can_deadlock= thd->mdl_context.has_locks();
- lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
- lex->reset_n_backup_query_tables_list(&query_tables_list_backup);
- /*
- Restore Query_tables_list::sql_command value, which was reset
- above, as ST_SCHEMA_TABLE::process_table() functions often rely
- that this value reflects which SHOW statement is executed.
- */
- lex->sql_command= query_tables_list_backup.sql_command;
-
/*
We should not introduce deadlocks even if we already have some
tables open and locked, since we won't lock tables which we will
@@ -3539,9 +3623,19 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
*/
if (lsel && lsel->table_list.first)
{
- error= fill_schema_show_cols_or_idxs(thd, tables, schema_table,
- can_deadlock,
- &open_tables_state_backup);
+ LEX_STRING db_name, table_name;
+
+ db_name.str= lsel->table_list.first->db;
+ db_name.length= lsel->table_list.first->db_length;
+
+ table_name.str= lsel->table_list.first->table_name;
+ table_name.length= lsel->table_list.first->table_name_length;
+
+ error= fill_schema_table_by_open(thd, TRUE,
+ table, schema_table,
+ &db_name, &table_name,
+ &open_tables_state_backup,
+ can_deadlock);
goto err;
}
@@ -3595,12 +3689,6 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
it.rewind(); /* To get access to new elements in basis list */
while ((db_name= it++))
{
- LEX_STRING orig_db_name;
-
- /* db_name can be changed in make_table_list() func */
- if (!thd->make_lex_string(&orig_db_name, db_name->str,
- db_name->length, FALSE))
- goto err;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (!(check_access(thd, SELECT_ACL, db_name->str,
&thd->col_access, NULL, 0, 1) ||
@@ -3678,66 +3766,13 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
continue;
}
- int res;
- LEX_STRING tmp_lex_string;
- /*
- Set the parent lex of 'sel' because it is needed by
- sel.init_query() which is called inside make_table_list.
- */
- sel.parent_lex= lex;
- if (make_table_list(thd, &sel, db_name, table_name))
- goto err;
- TABLE_LIST *show_table_list= sel.table_list.first;
- lex->all_selects_list= &sel;
- lex->derived_tables= 0;
- lex->sql_command= SQLCOM_SHOW_FIELDS;
- show_table_list->i_s_requested_object=
- schema_table->i_s_requested_object;
DEBUG_SYNC(thd, "before_open_in_get_all_tables");
- res= open_normal_and_derived_tables(thd, show_table_list,
- (MYSQL_OPEN_IGNORE_FLUSH |
- MYSQL_OPEN_FORCE_SHARED_HIGH_PRIO_MDL |
- (can_deadlock ? MYSQL_OPEN_FAIL_ON_MDL_CONFLICT : 0)));
- lex->sql_command= query_tables_list_backup.sql_command;
- /*
- XXX: show_table_list has a flag i_is_requested,
- and when it's set, open_normal_and_derived_tables()
- can return an error without setting an error message
- in THD, which is a hack. This is why we have to
- check for res, then for thd->is_error() only then
- for thd->stmt_da->sql_errno().
- */
- if (res && thd->is_error() &&
- thd->stmt_da->sql_errno() == ER_NO_SUCH_TABLE)
- {
- /*
- Hide error for not existing table.
- This error can occur for example when we use
- where condition with db name and table name and this
- table does not exist.
- */
- res= 0;
- thd->clear_error();
- }
- else
- {
- /*
- We should use show_table_list->alias instead of
- show_table_list->table_name because table_name
- could be changed during opening of I_S tables. It's safe
- to use alias because alias contains original table name
- in this case.
- */
- thd->make_lex_string(&tmp_lex_string, show_table_list->alias,
- strlen(show_table_list->alias), FALSE);
- res= schema_table->process_table(thd, show_table_list, table,
- res, &orig_db_name,
- &tmp_lex_string);
- close_tables_for_reopen(thd, &show_table_list,
- open_tables_state_backup.mdl_system_tables_svp);
- }
- DBUG_ASSERT(!lex->query_tables_own_last);
- if (res)
+
+ if (fill_schema_table_by_open(thd, FALSE,
+ table, schema_table,
+ db_name, table_name,
+ &open_tables_state_backup,
+ can_deadlock))
goto err;
}
}
@@ -3753,10 +3788,7 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
error= 0;
err:
thd->restore_backup_open_tables_state(&open_tables_state_backup);
- lex->restore_backup_query_tables_list(&query_tables_list_backup);
- lex->derived_tables= derived_tables;
- lex->all_selects_list= old_all_select_lex;
- lex->context_analysis_only= save_context_analysis_only;
+
DBUG_RETURN(error);
}
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index f98ac676525..a5cc386d740 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -2618,7 +2618,8 @@ int prepare_create_field(Create_field *sql_field,
MAX_FIELD_CHARLENGTH)
{
my_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
- MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
+ MYF(0), sql_field->field_name,
+ static_cast<ulong>(MAX_FIELD_CHARLENGTH));
DBUG_RETURN(1);
}
}
@@ -3614,12 +3615,12 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
my_error(ER_TOO_LONG_INDEX_COMMENT, MYF(0),
- key_info->name, (uint) INDEX_COMMENT_MAXLEN);
+ key_info->name, static_cast<ulong>(INDEX_COMMENT_MAXLEN));
DBUG_RETURN(-1);
}
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_INDEX_COMMENT),
- key_info->name, (uint) INDEX_COMMENT_MAXLEN);
+ key_info->name, static_cast<ulong>(INDEX_COMMENT_MAXLEN));
/* do not push duplicate warnings */
if (!check_duplicate_warning(thd, warn_buff, strlen(warn_buff)))
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -3747,7 +3748,8 @@ static bool prepare_blob_field(THD *thd, Create_field *sql_field)
MODE_STRICT_ALL_TABLES)))
{
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
- MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
+ static_cast<ulong>(MAX_FIELD_VARCHARLENGTH /
+ sql_field->charset->mbmaxlen));
DBUG_RETURN(1);
}
sql_field->sql_type= MYSQL_TYPE_BLOB;
@@ -5678,6 +5680,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
uint index_drop_count= 0;
uint *index_drop_buffer= NULL;
uint index_add_count= 0;
+ handler_add_index *add= NULL;
+ bool pending_inplace_add_index= false;
uint *index_add_buffer= NULL;
uint candidate_key_count= 0;
bool no_pk;
@@ -6432,6 +6436,9 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+ if (error)
+ goto err_new_table_cleanup;
+
/* If we did not need to copy, we might still need to add/drop indexes. */
if (! new_table)
{
@@ -6463,7 +6470,8 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
key_part->field= table->field[key_part->fieldnr];
}
/* Add the indexes. */
- if ((error= table->file->add_index(table, key_info, index_add_count)))
+ if ((error= table->file->add_index(table, key_info, index_add_count,
+ &add)))
{
/*
Exchange the key_info for the error message. If we exchange
@@ -6475,11 +6483,27 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
table->key_info= save_key_info;
goto err_new_table_cleanup;
}
+ pending_inplace_add_index= true;
}
/*end of if (index_add_count)*/
if (index_drop_count)
{
+ /* Currently we must finalize add index if we also drop indexes */
+ if (pending_inplace_add_index)
+ {
+ /* Committing index changes needs exclusive metadata lock. */
+ DBUG_ASSERT(thd->mdl_context.is_lock_owner(MDL_key::TABLE,
+ table_list->db,
+ table_list->table_name,
+ MDL_EXCLUSIVE));
+ if ((error= table->file->final_add_index(add, true)))
+ {
+ table->file->print_error(error, MYF(0));
+ goto err_new_table_cleanup;
+ }
+ pending_inplace_add_index= false;
+ }
/* The prepare_drop_index() method takes an array of key numbers. */
key_numbers= (uint*) thd->alloc(sizeof(uint) * index_drop_count);
keyno_p= key_numbers;
@@ -6520,11 +6544,14 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
/*end of if (! new_table) for add/drop index*/
- if (error)
- goto err_new_table_cleanup;
-
if (table->s->tmp_table != NO_TMP_TABLE)
{
+ /*
+ In-place operations are not supported for temporary tables, so
+ we don't have to call final_add_index() in this case. The assert
+ verifies that in-place add index has not been done.
+ */
+ DBUG_ASSERT(!pending_inplace_add_index);
/* Close lock if this is a transactional table */
if (thd->lock)
{
@@ -6591,8 +6618,30 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
my_casedn_str(files_charset_info, old_name);
if (wait_while_table_is_used(thd, table, HA_EXTRA_PREPARE_FOR_RENAME))
+ {
+ if (pending_inplace_add_index)
+ {
+ pending_inplace_add_index= false;
+ table->file->final_add_index(add, false);
+ }
+ // Mark this TABLE instance as stale to avoid out-of-sync index information.
+ table->m_needs_reopen= true;
goto err_new_table_cleanup;
-
+ }
+ if (pending_inplace_add_index)
+ {
+ pending_inplace_add_index= false;
+ DBUG_EXECUTE_IF("alter_table_rollback_new_index", {
+ table->file->final_add_index(add, false);
+ my_error(ER_UNKNOWN_ERROR, MYF(0));
+ goto err_new_table_cleanup;
+ });
+ if ((error= table->file->final_add_index(add, true)))
+ {
+ table->file->print_error(error, MYF(0));
+ goto err_new_table_cleanup;
+ }
+ }
close_all_tables_for_name(thd, table->s,
new_name != table_name || new_db != db);
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 13a1b8029f2..5ab1a648d09 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -1,4 +1,4 @@
-/* Copyright (c) 2000, 2010 Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2011 Oracle and/or its affiliates. All rights reserved.
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
@@ -11574,7 +11574,23 @@ field_or_var:
opt_load_data_set_spec:
/* empty */ {}
- | SET insert_update_list {}
+ | SET load_data_set_list {}
+ ;
+
+load_data_set_list:
+ load_data_set_list ',' load_data_set_elem
+ | load_data_set_elem
+ ;
+
+load_data_set_elem:
+ simple_ident_nospvar equal remember_name expr_or_default remember_end
+ {
+ LEX *lex= Lex;
+ if (lex->update_list.push_back($1) ||
+ lex->value_list.push_back($4))
+ MYSQL_YYABORT;
+ $4->set_name($3, (uint) ($5 - $3), YYTHD->charset());
+ }
;
/* Common definitions */
diff --git a/sql/sys_vars.cc b/sql/sys_vars.cc
index ad7bf3fef2a..6c6ccc5209e 100644
--- a/sql/sys_vars.cc
+++ b/sql/sys_vars.cc
@@ -695,7 +695,7 @@ static bool event_scheduler_update(sys_var *self, THD *thd, enum_var_type type)
: Events::stop();
mysql_mutex_lock(&LOCK_global_system_variables);
if (ret)
- my_error(ER_EVENT_SET_VAR_ERROR, MYF(0));
+ my_error(ER_EVENT_SET_VAR_ERROR, MYF(0), 0);
return ret;
}
@@ -2504,7 +2504,7 @@ static bool update_last_insert_id(THD *thd, set_var *var)
{
if (!var->value)
{
- my_error(ER_NO_DEFAULT, MYF(0), var->var->name);
+ my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
return true;
}
thd->first_successful_insert_id_in_prev_stmt=
@@ -2553,7 +2553,7 @@ static bool update_insert_id(THD *thd, set_var *var)
{
if (!var->value)
{
- my_error(ER_NO_DEFAULT, MYF(0), var->var->name);
+ my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
return true;
}
thd->force_one_auto_inc_interval(var->save_result.ulonglong_value);
@@ -2576,7 +2576,7 @@ static bool update_rand_seed1(THD *thd, set_var *var)
{
if (!var->value)
{
- my_error(ER_NO_DEFAULT, MYF(0), var->var->name);
+ my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
return true;
}
thd->rand.seed1= (ulong) var->save_result.ulonglong_value;
@@ -2598,7 +2598,7 @@ static bool update_rand_seed2(THD *thd, set_var *var)
{
if (!var->value)
{
- my_error(ER_NO_DEFAULT, MYF(0), var->var->name);
+ my_error(ER_NO_DEFAULT, MYF(0), var->var->name.str);
return true;
}
thd->rand.seed2= (ulong) var->save_result.ulonglong_value;
diff --git a/sql/table.cc b/sql/table.cc
index 68e2566ffc1..c62d84743bc 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -1992,7 +1992,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
Query_arena *backup_stmt_arena_ptr= thd->stmt_arena;
Query_arena backup_arena;
- Query_arena part_func_arena(&outparam->mem_root, Query_arena::INITIALIZED);
+ Query_arena part_func_arena(&outparam->mem_root,
+ Query_arena::STMT_INITIALIZED);
thd->set_n_backup_active_arena(&part_func_arena, &backup_arena);
thd->stmt_arena= &part_func_arena;
bool tmp;
@@ -2188,7 +2189,15 @@ void free_blobs(register TABLE *table)
for (ptr= table->s->blob_field, end=ptr + table->s->blob_fields ;
ptr != end ;
ptr++)
- ((Field_blob*) table->field[*ptr])->free();
+ {
+ /*
+ Reduced TABLE objects which are used by row-based replication for
+ type conversion might have some fields missing. Skip freeing BLOB
+ buffers for such missing fields.
+ */
+ if (table->field[*ptr])
+ ((Field_blob*) table->field[*ptr])->free();
+ }
}
@@ -2422,7 +2431,7 @@ void open_table_error(TABLE_SHARE *share, int error, int db_errno, int errarg)
default: /* Better wrong error than none */
case 4:
strxmov(buff, share->normalized_path.str, reg_ext, NullS);
- my_error(ER_NOT_FORM_FILE, errortype, buff, 0);
+ my_error(ER_NOT_FORM_FILE, errortype, buff);
break;
}
DBUG_VOID_RETURN;
@@ -3009,7 +3018,8 @@ Table_check_intact::check(TABLE *table, const TABLE_FIELD_DEF *table_def)
report_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE,
ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
table->alias, table_def->count, table->s->fields,
- table->s->mysql_version, MYSQL_VERSION_ID);
+ static_cast<int>(table->s->mysql_version),
+ MYSQL_VERSION_ID);
DBUG_RETURN(TRUE);
}
else if (MYSQL_VERSION_ID == table->s->mysql_version)
diff --git a/sql/unireg.cc b/sql/unireg.cc
index 5a44c5e68f5..ae49a0da35c 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000-2006 MySQL AB, 2008-2009 Sun Microsystems, Inc
+/* Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
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
@@ -11,8 +11,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
/*
Functions to create a unireg form-file from a FIELD and a fieldname-fieldinfo
@@ -230,13 +229,13 @@ bool mysql_create_frm(THD *thd, const char *file_name,
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
my_error(ER_TOO_LONG_TABLE_COMMENT, MYF(0),
- real_table_name, (uint) TABLE_COMMENT_MAXLEN);
+ real_table_name, static_cast<ulong>(TABLE_COMMENT_MAXLEN));
my_free(screen_buff);
DBUG_RETURN(1);
}
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_TABLE_COMMENT),
- real_table_name, (uint) TABLE_COMMENT_MAXLEN);
+ real_table_name, static_cast<ulong>(TABLE_COMMENT_MAXLEN));
/* do not push duplicate warnings */
if (!check_duplicate_warning(current_thd, warn_buff, strlen(warn_buff)))
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -737,13 +736,14 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
if ((current_thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
- my_error(ER_TOO_LONG_FIELD_COMMENT, MYF(0),
- field->field_name, (uint) COLUMN_COMMENT_MAXLEN);
+ my_error(ER_TOO_LONG_FIELD_COMMENT, MYF(0), field->field_name,
+ static_cast<ulong>(COLUMN_COMMENT_MAXLEN));
DBUG_RETURN(1);
}
char warn_buff[MYSQL_ERRMSG_SIZE];
my_snprintf(warn_buff, sizeof(warn_buff), ER(ER_TOO_LONG_FIELD_COMMENT),
- field->field_name, (uint) COLUMN_COMMENT_MAXLEN);
+ field->field_name,
+ static_cast<ulong>(COLUMN_COMMENT_MAXLEN));
/* do not push duplicate warnings */
if (!check_duplicate_warning(current_thd, warn_buff, strlen(warn_buff)))
push_warning(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
@@ -831,7 +831,7 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
if (reclength > (ulong) file->max_record_length())
{
- my_error(ER_TOO_BIG_ROWSIZE, MYF(0), (uint) file->max_record_length());
+ my_error(ER_TOO_BIG_ROWSIZE, MYF(0), static_cast<long>(file->max_record_length()));
DBUG_RETURN(1);
}
/* Hack to avoid bugs with small static rows in MySQL */