summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/ha_partition.cc5
-rw-r--r--sql/handler.cc37
-rw-r--r--sql/item.cc83
-rw-r--r--sql/item.h2
-rw-r--r--sql/item_cmpfunc.cc13
-rw-r--r--sql/item_func.cc15
-rw-r--r--sql/item_strfunc.cc5
-rw-r--r--sql/item_sum.cc3
-rw-r--r--sql/log.cc7
-rw-r--r--sql/log_event.cc6
-rw-r--r--sql/log_event.h2
-rw-r--r--sql/mysql_priv.h19
-rw-r--r--sql/mysqld.cc234
-rw-r--r--sql/opt_range.cc57
-rw-r--r--sql/protocol.cc23
-rw-r--r--sql/rpl_record.cc34
-rw-r--r--sql/rpl_rli.cc5
-rw-r--r--sql/rpl_rli.h7
-rw-r--r--sql/set_var.cc236
-rw-r--r--sql/share/errmsg.txt39
-rw-r--r--sql/sp.cc4
-rw-r--r--sql/sql_base.cc3
-rw-r--r--sql/sql_cache.cc50
-rw-r--r--sql/sql_class.cc9
-rw-r--r--sql/sql_class.h2
-rw-r--r--sql/sql_handler.cc19
-rw-r--r--sql/sql_insert.cc14
-rw-r--r--sql/sql_lex.cc1
-rw-r--r--sql/sql_lex.h9
-rw-r--r--sql/sql_load.cc29
-rw-r--r--sql/sql_parse.cc24
-rw-r--r--sql/sql_select.cc35
-rw-r--r--sql/sql_show.cc49
-rw-r--r--sql/sql_string.cc19
-rw-r--r--sql/sql_table.cc15
-rw-r--r--sql/sql_view.cc52
-rw-r--r--sql/sql_yacc.yy36
-rw-r--r--sql/table.cc5
-rw-r--r--sql/unireg.cc17
39 files changed, 805 insertions, 419 deletions
diff --git a/sql/ha_partition.cc b/sql/ha_partition.cc
index e0bd3e6fb7e..4f24ce3f591 100644
--- a/sql/ha_partition.cc
+++ b/sql/ha_partition.cc
@@ -4929,10 +4929,11 @@ int ha_partition::info(uint flag)
This flag is used to get index number of the unique index that
reported duplicate key
We will report the errkey on the last handler used and ignore the rest
+ Note: all engines does not support HA_STATUS_ERRKEY, so set errkey.
*/
+ file->errkey= errkey;
file->info(HA_STATUS_ERRKEY);
- if (file->errkey != (uint) -1)
- errkey= file->errkey;
+ errkey= file->errkey;
}
if (flag & HA_STATUS_TIME)
{
diff --git a/sql/handler.cc b/sql/handler.cc
index ca04398aa35..1804eb5fbd3 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -429,14 +429,11 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
MYF(MY_WME | MY_ZEROFILL));
/* Historical Requirement */
plugin->data= hton; // shortcut for the future
- if (plugin->plugin->init)
+ if (plugin->plugin->init && plugin->plugin->init(hton))
{
- if (plugin->plugin->init(hton))
- {
- sql_print_error("Plugin '%s' init function returned error.",
- plugin->name.str);
- goto err;
- }
+ sql_print_error("Plugin '%s' init function returned error.",
+ plugin->name.str);
+ goto err;
}
/*
@@ -463,17 +460,13 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
if (idx == (int) DB_TYPE_DEFAULT)
{
sql_print_warning("Too many storage engines!");
- DBUG_RETURN(1);
+ goto err_deinit;
}
if (hton->db_type != DB_TYPE_UNKNOWN)
sql_print_warning("Storage engine '%s' has conflicting typecode. "
"Assigning value %d.", plugin->plugin->name, idx);
hton->db_type= (enum legacy_db_type) idx;
}
- installed_htons[hton->db_type]= hton;
- tmp= hton->savepoint_offset;
- hton->savepoint_offset= savepoint_alloc_size;
- savepoint_alloc_size+= tmp;
/*
In case a plugin is uninstalled and re-installed later, it should
@@ -494,11 +487,14 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
{
sql_print_error("Too many plugins loaded. Limit is %lu. "
"Failed on '%s'", (ulong) MAX_HA, plugin->name.str);
- goto err;
+ goto err_deinit;
}
hton->slot= total_ha++;
}
-
+ installed_htons[hton->db_type]= hton;
+ tmp= hton->savepoint_offset;
+ hton->savepoint_offset= savepoint_alloc_size;
+ savepoint_alloc_size+= tmp;
hton2plugin[hton->slot]=plugin;
if (hton->prepare)
total_ha_2pc++;
@@ -530,7 +526,18 @@ int ha_initialize_handlerton(st_plugin_int *plugin)
};
DBUG_RETURN(0);
+
+err_deinit:
+ /*
+ Let plugin do its inner deinitialization as plugin->init()
+ was successfully called before.
+ */
+ if (plugin->plugin->deinit)
+ (void) plugin->plugin->deinit(NULL);
+
err:
+ my_free((uchar*) hton, MYF(0));
+ plugin->data= NULL;
DBUG_RETURN(1);
}
@@ -2928,7 +2935,7 @@ uint handler::get_dup_key(int error)
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
error == HA_ERR_FOUND_DUPP_UNIQUE || error == HA_ERR_NULL_IN_SPATIAL ||
error == HA_ERR_DROP_INDEX_FK)
- info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
+ table->file->info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
DBUG_RETURN(table->file->errkey);
}
diff --git a/sql/item.cc b/sql/item.cc
index 1ecbecf8615..35a88d10fe0 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -1637,48 +1637,11 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
}
-/**
- Collect arguments' character sets together.
-
- We allow to apply automatic character set conversion in some cases.
- The conditions when conversion is possible are:
- - arguments A and B have different charsets
- - A wins according to coercibility rules
- (i.e. a column is stronger than a string constant,
- an explicit COLLATE clause is stronger than a column)
- - character set of A is either superset for character set of B,
- or B is a string constant which can be converted into the
- character set of A without data loss.
-
- If all of the above is true, then it's possible to convert
- B into the character set of A, and then compare according
- to the collation of A.
-
- For functions with more than two arguments:
- @code
- collect(A,B,C) ::= collect(collect(A,B),C)
- @endcode
- Since this function calls THD::change_item_tree() on the passed Item **
- pointers, it is necessary to pass the original Item **'s, not copies.
- Otherwise their values will not be properly restored (see BUG#20769).
- If the items are not consecutive (eg. args[2] and args[5]), use the
- item_sep argument, ie.
- @code
- agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
- @endcode
-*/
-
-bool agg_item_charsets(DTCollation &coll, const char *fname,
- Item **args, uint nargs, uint flags, int item_sep)
+bool agg_item_set_converter(DTCollation &coll, const char *fname,
+ Item **args, uint nargs, uint flags, int item_sep)
{
Item **arg, *safe_args[2];
- LINT_INIT(safe_args[0]);
- LINT_INIT(safe_args[1]);
-
- if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
- return TRUE;
-
/*
For better error reporting: save the first and the second argument.
We need this only if the the number of args is 3 or 2:
@@ -1758,6 +1721,46 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
}
+/*
+ Collect arguments' character sets together.
+ We allow to apply automatic character set conversion in some cases.
+ The conditions when conversion is possible are:
+ - arguments A and B have different charsets
+ - A wins according to coercibility rules
+ (i.e. a column is stronger than a string constant,
+ an explicit COLLATE clause is stronger than a column)
+ - character set of A is either superset for character set of B,
+ or B is a string constant which can be converted into the
+ character set of A without data loss.
+
+ If all of the above is true, then it's possible to convert
+ B into the character set of A, and then compare according
+ to the collation of A.
+
+ For functions with more than two arguments:
+
+ collect(A,B,C) ::= collect(collect(A,B),C)
+
+ Since this function calls THD::change_item_tree() on the passed Item **
+ pointers, it is necessary to pass the original Item **'s, not copies.
+ Otherwise their values will not be properly restored (see BUG#20769).
+ If the items are not consecutive (eg. args[2] and args[5]), use the
+ item_sep argument, ie.
+
+ agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
+
+*/
+
+bool agg_item_charsets(DTCollation &coll, const char *fname,
+ Item **args, uint nargs, uint flags, int item_sep)
+{
+ if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
+ return TRUE;
+
+ return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep);
+}
+
+
void Item_ident_for_show::make_field(Send_field *tmp_field)
{
tmp_field->table_name= tmp_field->org_table_name= table_name;
@@ -3097,7 +3100,7 @@ bool Item_param::convert_str_value(THD *thd)
str_value.set_charset(value.cs_info.final_character_set_of_str_value);
/* Here str_value is guaranteed to be in final_character_set_of_str_value */
- max_length= str_value.length();
+ max_length= str_value.numchars() * str_value.charset()->mbmaxlen;
decimals= 0;
/*
str_value_ptr is returned from val_str(). It must be not alloced
diff --git a/sql/item.h b/sql/item.h
index e90cdbbc8f8..eb1b28b4004 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -1304,6 +1304,8 @@ bool agg_item_collations(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags, int item_sep);
bool agg_item_collations_for_comparison(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags);
+bool agg_item_set_converter(DTCollation &coll, const char *fname,
+ Item **args, uint nargs, uint flags, int item_sep);
bool agg_item_charsets(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags, int item_sep);
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index cad3bb29961..a30aa56cdb5 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -549,7 +549,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
return 1;
}
- comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i));
+ if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)))
+ return 1;
}
break;
}
@@ -893,6 +894,16 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
get_value_func= &get_time_value;
return 0;
}
+ else if (type == STRING_RESULT &&
+ (*a)->result_type() == STRING_RESULT &&
+ (*b)->result_type() == STRING_RESULT)
+ {
+ DTCollation coll;
+ coll.set((*a)->collation.collation);
+ if (agg_item_set_converter(coll, owner_arg->func_name(),
+ b, 1, MY_COLL_CMP_CONV, 1))
+ return 1;
+ }
return set_compare_func(owner_arg, type);
}
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 55ed5604301..beafa142501 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -4840,7 +4840,9 @@ bool Item_func_get_system_var::is_written_to_binlog()
void Item_func_get_system_var::fix_length_and_dec()
{
+ char *cptr;
maybe_null=0;
+ max_length= 0;
if (var->check_type(var_type))
{
@@ -4870,8 +4872,14 @@ void Item_func_get_system_var::fix_length_and_dec()
break;
case SHOW_CHAR:
case SHOW_CHAR_PTR:
+ pthread_mutex_lock(&LOCK_global_system_variables);
+ cptr= var->show_type() == SHOW_CHAR_PTR ?
+ *(char**) var->value_ptr(current_thd, var_type, &component) :
+ (char*) var->value_ptr(current_thd, var_type, &component);
+ if (cptr)
+ max_length= strlen(cptr) * system_charset_info->mbmaxlen;
+ pthread_mutex_unlock(&LOCK_global_system_variables);
collation.set(system_charset_info, DERIVATION_SYSCONST);
- max_length= MAX_BLOB_WIDTH;
decimals=NOT_FIXED_DEC;
break;
case SHOW_BOOL:
@@ -5374,7 +5382,10 @@ bool Item_func_match::fix_fields(THD *thd, Item **ref)
if (item->type() == Item::REF_ITEM)
args[i]= item= *((Item_ref *)item)->ref;
if (item->type() != Item::FIELD_ITEM)
- key=NO_SUCH_KEY;
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "AGAINST");
+ return TRUE;
+ }
}
/*
Check that all columns come from the same table.
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index 669d160d322..67743b9324c 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -105,13 +105,10 @@ String *Item_func_md5::val_str(String *str)
str->set_charset(&my_charset_bin);
if (sptr)
{
- my_MD5_CTX context;
uchar digest[16];
null_value=0;
- my_MD5Init (&context);
- my_MD5Update (&context,(uchar *) sptr->ptr(), sptr->length());
- my_MD5Final (digest, &context);
+ MY_MD5_HASH(digest,(uchar *) sptr->ptr(), sptr->length());
if (str->alloc(32)) // Ensure that memory is free
{
null_value=1;
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 1821136cc9d..a6d8bb8a52d 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -439,7 +439,8 @@ void Item_sum::make_field(Send_field *tmp_field)
void Item_sum::print(String *str, enum_query_type query_type)
{
- Item **pargs= orig_args;
+ /* orig_args is not filled with valid values until fix_fields() */
+ Item **pargs= fixed ? orig_args : args;
str->append(func_name());
for (uint i=0 ; i < arg_count ; i++)
{
diff --git a/sql/log.cc b/sql/log.cc
index d0ba1ec90c3..0f6cc0b5c1e 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -4662,10 +4662,14 @@ bool flush_error_log()
uchar buf[IO_SIZE];
freopen(err_temp,"a+",stderr);
+ setbuf(stderr, NULL);
(void) my_delete(err_renamed, MYF(0));
my_rename(log_error_file,err_renamed,MYF(0));
if (freopen(log_error_file,"a+",stdout))
+ {
freopen(log_error_file,"a+",stderr);
+ setbuf(stderr, NULL);
+ }
if ((fd = my_open(err_temp, O_RDONLY, MYF(0))) >= 0)
{
@@ -4681,7 +4685,10 @@ bool flush_error_log()
#else
my_rename(log_error_file,err_renamed,MYF(0));
if (freopen(log_error_file,"a+",stdout))
+ {
freopen(log_error_file,"a+",stderr);
+ setbuf(stderr, NULL);
+ }
else
result= 1;
#endif
diff --git a/sql/log_event.cc b/sql/log_event.cc
index 139c9ee8dd3..dd0185acc0d 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -354,7 +354,7 @@ static char *slave_load_file_stem(char *buf, uint file_id,
int event_server_id, const char *ext)
{
char *res;
- fn_format(buf,"SQL_LOAD-",slave_load_tmpdir, "", MY_UNPACK_FILENAME);
+ fn_format(buf,PREFIX_SQL_LOAD,slave_load_tmpdir, "", MY_UNPACK_FILENAME);
to_unix_path(buf);
buf = strend(buf);
@@ -393,7 +393,7 @@ static void cleanup_load_tmpdir()
we cannot meet Start_log event in the middle of events from one
LOAD DATA.
*/
- p= strmake(prefbuf, STRING_WITH_LEN("SQL_LOAD-"));
+ p= strmake(prefbuf, STRING_WITH_LEN(PREFIX_SQL_LOAD));
p= int10_to_str(::server_id, p, 10);
*(p++)= '-';
*p= 0;
@@ -1258,7 +1258,7 @@ void Log_event::print_header(IO_CACHE* file,
my_b_printf(file, "#");
print_timestamp(file);
- my_b_printf(file, " server id %d end_log_pos %s ", server_id,
+ my_b_printf(file, " server id %lu end_log_pos %s ", (ulong) server_id,
llstr(log_pos,llbuff));
/* mysqlbinlog --hexdump */
diff --git a/sql/log_event.h b/sql/log_event.h
index 1d11d7e2d5f..82fc8d771e1 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -47,6 +47,8 @@
#include "rpl_reporting.h"
#endif
+#define PREFIX_SQL_LOAD "SQL_LOAD-"
+
/**
Either assert or return an error.
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index e90e2e4c027..2ca037ade9c 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -282,16 +282,12 @@ protected:
*/
#define TABLE_DEF_CACHE_MIN 256
-/*
- Value of 9236 discovered through binary search 2006-09-26 on Ubuntu Dapper
- Drake, libc6 2.3.6-0ubuntu2, Linux kernel 2.6.15-27-686, on x86. (Added
- 100 bytes as reasonable buffer against growth and other environments'
- requirements.)
-
- Feel free to raise this by the smallest amount you can to get the
- "execution_constants" test to pass.
- */
-#define STACK_MIN_SIZE 12000 ///< Abort if less stack during eval.
+/*
+ Stack reservation.
+ Feel free to raise this by the smallest amount you can to get the
+ "execution_constants" test to pass.
+*/
+#define STACK_MIN_SIZE 16000 // Abort if less stack during eval.
#define STACK_MIN_SIZE_FOR_OPEN 1024*80
#define STACK_BUFF_ALLOC 352 ///< For stack overrun checks
@@ -2421,7 +2417,8 @@ extern "C" void unireg_abort(int exit_code) __attribute__((noreturn));
void kill_delayed_threads(void);
bool check_stack_overrun(THD *thd, long margin, uchar *dummy);
#else
-#define unireg_abort(exit_code) DBUG_RETURN(exit_code)
+extern "C" void unireg_clear(int exit_code);
+#define unireg_abort(exit_code) do { unireg_clear(exit_code); DBUG_RETURN(exit_code); } while(0)
inline void kill_delayed_threads(void) {}
#define check_stack_overrun(A, B, C) 0
#endif
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 2b996301a73..bd09f49cc31 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -178,39 +178,41 @@ int initgroups(const char *,unsigned int);
#ifdef HAVE_FP_EXCEPT // Fix type conflict
typedef fp_except fp_except_t;
#endif
+#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
+#ifdef HAVE_SYS_FPU_H
+/* for IRIX to use set_fpc_csr() */
+#include <sys/fpu.h>
+#endif
-/**
- We can't handle floating point exceptions with threads, so disable
- this on freebsd.
-*/
-inline void set_proper_floating_point_mode()
+inline void setup_fpu()
{
- /* Don't fall for overflow, underflow,divide-by-zero or loss of precision */
+#if defined(__FreeBSD__) && defined(HAVE_IEEEFP_H)
+ /* 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
+ */
#if defined(__i386__)
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
-}
-#elif defined(__sgi)
-/* for IRIX to use set_fpc_csr() */
-#include <sys/fpu.h>
+ fpsetmask(~(FP_X_INV | FP_X_OFL | FP_X_UFL | FP_X_DZ |
+ FP_X_IMP));
+#endif /* __i386__ */
+#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
-inline void set_proper_floating_point_mode()
-{
+#ifdef HAVE_FESETROUND
+ /* Set FPU rounding mode to "round-to-nearest" */
+ fesetround(FE_TONEAREST);
+#endif /* HAVE_FESETROUND */
+
+#if defined(__sgi) && defined(HAVE_SYS_FPU_H)
/* Enable denormalized DOUBLE values support for IRIX */
- {
- union fpc_csr n;
- n.fc_word = get_fpc_csr();
- n.fc_struct.flush = 0;
- set_fpc_csr(n.fc_word);
- }
+ union fpc_csr n;
+ n.fc_word = get_fpc_csr();
+ n.fc_struct.flush = 0;
+ set_fpc_csr(n.fc_word);
+#endif
}
-#else
-#define set_proper_floating_point_mode()
-#endif /* __FreeBSD__ && HAVE_IEEEFP_H */
} /* cplusplus */
@@ -689,6 +691,8 @@ bool mysqld_embedded=0;
bool mysqld_embedded=1;
#endif
+static my_bool plugins_are_initialized= FALSE;
+
#ifndef DBUG_OFF
static const char* default_dbug_option;
#endif
@@ -741,12 +745,12 @@ uint connection_count= 0;
pthread_handler_t signal_hand(void *arg);
static int mysql_init_variables(void);
-static void get_options(int *argc,char **argv);
+static int get_options(int *argc,char **argv);
extern "C" my_bool mysqld_get_one_option(int, const struct my_option *, char *);
static void set_server_version(void);
static int init_thread_environment();
static char *get_relative_path(const char *path);
-static void fix_paths(void);
+static int fix_paths(void);
pthread_handler_t handle_connections_sockets(void *arg);
pthread_handler_t kill_server_thread(void *arg);
static void bootstrap(FILE *file);
@@ -760,7 +764,7 @@ pthread_handler_t handle_connections_shared_memory(void *arg);
pthread_handler_t handle_slave(void *arg);
static ulong find_bit_type(const char *x, TYPELIB *bit_lib);
static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib,
- const char *option);
+ const char *option, int *error);
static void clean_up(bool print_message);
static int test_if_case_insensitive(const char *dir_name);
static void register_mutex_order();
@@ -1184,10 +1188,10 @@ extern "C" void unireg_abort(int exit_code)
{
DBUG_ENTER("unireg_abort");
+ if (opt_help)
+ usage();
if (exit_code)
sql_print_error("Aborting\n");
- else if (opt_help)
- usage();
clean_up(!opt_help && (exit_code || !opt_bootstrap)); /* purecov: inspected */
DBUG_PRINT("quit",("done with cleanup in unireg_abort"));
wait_for_signal_thread_to_end();
@@ -1195,7 +1199,8 @@ extern "C" void unireg_abort(int exit_code)
my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
exit(exit_code); /* purecov: inspected */
}
-#endif
+
+#endif /*EMBEDDED_LIBRARY*/
void clean_up(bool print_message)
@@ -3283,7 +3288,8 @@ static int init_common_variables(const char *conf_file_name, int argc,
load_defaults(conf_file_name, groups, &argc, &argv);
defaults_argv=argv;
defaults_argc=argc;
- get_options(&defaults_argc, defaults_argv);
+ if (get_options(&defaults_argc, defaults_argv))
+ return 1;
set_server_version();
DBUG_PRINT("info",("%s Ver %s for %s on %s\n",my_progname,
@@ -3734,7 +3740,7 @@ static int init_server_components()
query_cache_init();
query_cache_resize(query_cache_size);
my_rnd_init(&sql_rand,(ulong) server_start_time,(ulong) server_start_time/2);
- set_proper_floating_point_mode();
+ setup_fpu();
init_thr_lock();
my_uuid_init((ulong) (my_rnd(&sql_rand))*12345,12345);
#ifdef HAVE_REPLICATION
@@ -3764,7 +3770,10 @@ static int init_server_components()
#ifndef EMBEDDED_LIBRARY
if (freopen(log_error_file, "a+", stdout))
#endif
+ {
freopen(log_error_file, "a+", stderr);
+ setbuf(stderr, NULL);
+ }
}
}
@@ -3916,12 +3925,15 @@ server.");
if (ha_init_errors())
DBUG_RETURN(1);
- if (plugin_init(&defaults_argc, defaults_argv,
- (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
- (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
- {
- sql_print_error("Failed to initialize plugins.");
- unireg_abort(1);
+ {
+ if (plugin_init(&defaults_argc, defaults_argv,
+ (opt_noacl ? PLUGIN_INIT_SKIP_PLUGIN_TABLE : 0) |
+ (opt_help ? PLUGIN_INIT_SKIP_INITIALIZATION : 0)))
+ {
+ sql_print_error("Failed to initialize plugins.");
+ unireg_abort(1);
+ }
+ plugins_are_initialized= TRUE; /* Don't separate from init function */
}
if (opt_help)
@@ -4395,6 +4407,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
{
freopen(log_error_file,"a+",stdout);
freopen(log_error_file,"a+",stderr);
+ setbuf(stderr, NULL);
FreeConsole(); // Remove window
}
#endif
@@ -6349,7 +6362,7 @@ Can't be set to 1 if --log-slave-updates is used.",
GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"server-id", OPT_SERVER_ID,
"Uniquely identifies the server instance in the community of replication partners.",
- (uchar**) &server_id, (uchar**) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, 0,
+ (uchar**) &server_id, (uchar**) &server_id, 0, GET_ULONG, REQUIRED_ARG, 0, 0, UINT_MAX32,
0, 0, 0},
{"set-variable", 'O',
"Change the value of a variable. Please note that this option is deprecated;you can set variables directly with --variable-name=value.",
@@ -7535,7 +7548,8 @@ static void usage(void)
default_collation_name= (char*) default_charset_info->name;
print_version();
puts("\
-Copyright (C) 2000-2008 MySQL AB, Monty and others, 2008-2009 Sun Microsystems, Inc.\n\
+Copyright (C) 2000-2008 MySQL AB, by Monty and others\n\
+Copyright (C) 2008 Sun Microsystems, Inc.\n\
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
and you are welcome to modify and redistribute it under the GPL license\n\n\
Starts the MySQL database server\n");
@@ -7565,6 +7579,13 @@ Starts the MySQL database server\n");
/* Print out all the options including plugin supplied options */
my_print_help_inc_plugins(my_long_options, sizeof(my_long_options)/sizeof(my_option));
+ if (! plugins_are_initialized)
+ {
+ puts("\n\
+Plugins have parameters that are not reflected in this list\n\
+because execution stopped before plugins were initialized.");
+ }
+
puts("\n\
To see what values a running MySQL server is using, type\n\
'mysqladmin variables' instead of 'mysqld --verbose --help'.");
@@ -7591,6 +7612,7 @@ To see what values a running MySQL server is using, type\n\
static int mysql_init_variables(void)
{
+ int error;
/* Things reset to zero */
opt_skip_slave_start= opt_reckless_slave = 0;
mysql_home[0]= pidfile_name[0]= log_error_file[0]= 0;
@@ -7651,7 +7673,10 @@ static int mysql_init_variables(void)
delay_key_write_options= (uint) DELAY_KEY_WRITE_ON;
slave_exec_mode_options= 0;
slave_exec_mode_options= (uint)
- find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL);
+ find_bit_type_or_exit(slave_exec_mode_str, &slave_exec_mode_typelib, NULL,
+ &error);
+ if (error)
+ return 1;
opt_specialflag= SPECIAL_ENGLISH;
unix_sock= ip_sock= INVALID_SOCKET;
mysql_home_ptr= mysql_home;
@@ -7830,6 +7855,8 @@ mysqld_get_one_option(int optid,
const struct my_option *opt __attribute__((unused)),
char *argument)
{
+ int error;
+
switch(optid) {
#ifndef DBUG_OFF
case '#':
@@ -7883,7 +7910,9 @@ mysqld_get_one_option(int optid,
break;
case OPT_SLAVE_EXEC_MODE:
slave_exec_mode_options= (uint)
- find_bit_type_or_exit(argument, &slave_exec_mode_typelib, "");
+ find_bit_type_or_exit(argument, &slave_exec_mode_typelib, "", &error);
+ if (error)
+ return 1;
break;
#endif
case OPT_SAFEMALLOC_MEM_LIMIT:
@@ -7951,18 +7980,16 @@ mysqld_get_one_option(int optid,
if (!(p= strstr(argument, "->")))
{
- fprintf(stderr,
- "Bad syntax in replicate-rewrite-db - missing '->'!\n");
- exit(1);
+ sql_print_error("Bad syntax in replicate-rewrite-db - missing '->'!\n");
+ return 1;
}
val= p--;
while (my_isspace(mysqld_charset, *p) && p > argument)
*p-- = 0;
if (p == argument)
{
- fprintf(stderr,
- "Bad syntax in replicate-rewrite-db - empty FROM db!\n");
- exit(1);
+ sql_print_error("Bad syntax in replicate-rewrite-db - empty FROM db!\n");
+ return 1;
}
*val= 0;
val+= 2;
@@ -7970,9 +7997,8 @@ mysqld_get_one_option(int optid,
*val++;
if (!*val)
{
- fprintf(stderr,
- "Bad syntax in replicate-rewrite-db - empty TO db!\n");
- exit(1);
+ sql_print_error("Bad syntax in replicate-rewrite-db - empty TO db!\n");
+ return 1;
}
rpl_filter->add_db_rewrite(key, val);
@@ -8000,8 +8026,8 @@ mysqld_get_one_option(int optid,
{
if (rpl_filter->add_do_table(argument))
{
- fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
- exit(1);
+ sql_print_error("Could not add do table rule '%s'!\n", argument);
+ return 1;
}
break;
}
@@ -8009,8 +8035,8 @@ mysqld_get_one_option(int optid,
{
if (rpl_filter->add_wild_do_table(argument))
{
- fprintf(stderr, "Could not add do table rule '%s'!\n", argument);
- exit(1);
+ sql_print_error("Could not add do table rule '%s'!\n", argument);
+ return 1;
}
break;
}
@@ -8018,8 +8044,8 @@ mysqld_get_one_option(int optid,
{
if (rpl_filter->add_wild_ignore_table(argument))
{
- fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
- exit(1);
+ sql_print_error("Could not add ignore table rule '%s'!\n", argument);
+ return 1;
}
break;
}
@@ -8027,8 +8053,8 @@ mysqld_get_one_option(int optid,
{
if (rpl_filter->add_ignore_table(argument))
{
- fprintf(stderr, "Could not add ignore table rule '%s'!\n", argument);
- exit(1);
+ sql_print_error("Could not add ignore table rule '%s'!\n", argument);
+ return 1;
}
break;
}
@@ -8049,7 +8075,9 @@ mysqld_get_one_option(int optid,
{
log_output_str= argument;
log_output_options=
- find_bit_type_or_exit(argument, &log_output_typelib, opt->name);
+ find_bit_type_or_exit(argument, &log_output_typelib, opt->name, &error);
+ if (error)
+ return 1;
}
break;
}
@@ -8059,7 +8087,7 @@ mysqld_get_one_option(int optid,
sql_perror("Event scheduler is not supported in embedded build.");
#else
if (Events::set_opt_event_scheduler(argument))
- exit(1);
+ return 1;
#endif
break;
case (int) OPT_SKIP_NEW:
@@ -8098,7 +8126,7 @@ mysqld_get_one_option(int optid,
case (int) OPT_SKIP_NETWORKING:
#if defined(__NETWARE__)
sql_perror("Can't start server: skip-networking option is currently not supported on NetWare");
- exit(1);
+ return 1;
#endif
opt_disable_networking=1;
mysqld_port=0;
@@ -8165,8 +8193,8 @@ mysqld_get_one_option(int optid,
case OPT_MASTER_SSL_CA:
if (!slave_warning_issued) //only show the warning once
{
- slave_warning_issued = true;
- WARN_DEPRECATED(NULL, "5.2", "for replication startup options",
+ slave_warning_issued = true;
+ WARN_DEPRECATED(NULL, "6.0", "for replication startup options",
"'CHANGE MASTER'");
}
break;
@@ -8269,7 +8297,10 @@ mysqld_get_one_option(int optid,
{
myisam_recover_options_str=argument;
myisam_recover_options=
- find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name);
+ find_bit_type_or_exit(argument, &myisam_recover_typelib, opt->name,
+ &error);
+ if (error)
+ return 1;
}
ha_open_options|=HA_OPEN_ABORT_IF_CRASHED;
break;
@@ -8314,7 +8345,9 @@ mysqld_get_one_option(int optid,
{
sql_mode_str= argument;
global_system_variables.sql_mode=
- find_bit_type_or_exit(argument, &sql_mode_typelib, opt->name);
+ find_bit_type_or_exit(argument, &sql_mode_typelib, opt->name, &error);
+ if (error)
+ return 1;
global_system_variables.sql_mode= fix_sql_mode(global_system_variables.
sql_mode);
break;
@@ -8353,13 +8386,17 @@ mysqld_get_one_option(int optid,
/** Handle arguments for multiple key caches. */
-extern "C" uchar **mysql_getopt_value(const char *keyname, uint key_length,
- const struct my_option *option);
+extern "C" int mysql_getopt_value(uchar **value,
+ const char *keyname, uint key_length,
+ const struct my_option *option,
+ int *error);
-uchar* *
+static uchar* *
mysql_getopt_value(const char *keyname, uint key_length,
- const struct my_option *option)
+ const struct my_option *option, int *error)
{
+ if (error)
+ *error= 0;
switch (option->id) {
case OPT_KEY_BUFFER_SIZE:
case OPT_KEY_CACHE_BLOCK_SIZE:
@@ -8368,7 +8405,11 @@ mysql_getopt_value(const char *keyname, uint key_length,
{
KEY_CACHE *key_cache;
if (!(key_cache= get_or_create_key_cache(keyname, key_length)))
- exit(1);
+ {
+ if (error)
+ *error= EXIT_OUT_OF_MEMORY;
+ return 0;
+ }
switch (option->id) {
case OPT_KEY_BUFFER_SIZE:
return (uchar**) &key_cache->param_buff_size;
@@ -8406,7 +8447,7 @@ void option_error_reporter(enum loglevel level, const char *format, ...)
@todo
- FIXME add EXIT_TOO_MANY_ARGUMENTS to "mysys_err.h" and return that code?
*/
-static void get_options(int *argc,char **argv)
+static int get_options(int *argc,char **argv)
{
int ho_error;
@@ -8420,7 +8461,7 @@ static void get_options(int *argc,char **argv)
if ((ho_error= handle_options(argc, &argv, my_long_options,
mysqld_get_one_option)))
- exit(ho_error);
+ return ho_error;
(*argc)++; /* add back one for the progname handle_options removes */
/* no need to do this for argv as we are discarding it. */
@@ -8459,7 +8500,8 @@ static void get_options(int *argc,char **argv)
max_allowed_packet= global_system_variables.max_allowed_packet;
net_buffer_length= global_system_variables.net_buffer_length;
#endif
- fix_paths();
+ if (fix_paths())
+ return 1;
/*
Set some global variables from the global_system_variables
@@ -8487,7 +8529,7 @@ static void get_options(int *argc,char **argv)
&global_system_variables.time_format) ||
init_global_datetime_format(MYSQL_TIMESTAMP_DATETIME,
&global_system_variables.datetime_format))
- exit(1);
+ return 1;
#ifdef EMBEDDED_LIBRARY
one_thread_scheduler(&thread_scheduler);
@@ -8500,6 +8542,7 @@ static void get_options(int *argc,char **argv)
else
pool_of_threads_scheduler(&thread_scheduler); /* purecov: tested */
#endif
+ return 0;
}
@@ -8563,7 +8606,7 @@ fn_format_relative_to_data_home(char * to, const char *name,
}
-static void fix_paths(void)
+static int fix_paths(void)
{
char buff[FN_REFLEN],*pos;
convert_dirname(mysql_home,mysql_home,NullS);
@@ -8610,12 +8653,12 @@ static void fix_paths(void)
charsets_dir=mysql_charsets_dir;
if (init_tmpdir(&mysql_tmpdir_list, opt_mysql_tmpdir))
- exit(1);
+ return 1;
#ifdef HAVE_REPLICATION
if (!slave_load_tmpdir)
{
if (!(slave_load_tmpdir = (char*) my_strdup(mysql_tmpdir, MYF(MY_FAE))))
- exit(1);
+ return 1;
}
#endif /* HAVE_REPLICATION */
/*
@@ -8628,30 +8671,37 @@ static void fix_paths(void)
my_free(opt_secure_file_priv, MYF(0));
opt_secure_file_priv= my_strdup(buff, MYF(MY_FAE));
}
+ return 0;
}
static ulong find_bit_type_or_exit(const char *x, TYPELIB *bit_lib,
- const char *option)
+ const char *option, int *error)
{
- ulong res;
-
+ ulong result;
const char **ptr;
-
- if ((res= find_bit_type(x, bit_lib)) == ~(ulong) 0)
+
+ *error= 0;
+ if ((result= find_bit_type(x, bit_lib)) == ~(ulong) 0)
{
+ char *buff= (char *) my_alloca(2048);
+ char *cbuf;
ptr= bit_lib->type_names;
- if (!*x)
- fprintf(stderr, "No option given to %s\n", option);
- else
- fprintf(stderr, "Wrong option to %s. Option(s) given: %s\n", option, x);
- fprintf(stderr, "Alternatives are: '%s'", *ptr);
+ cbuf= buff + ((!*x) ?
+ my_snprintf(buff, 2048, "No option given to %s\n", option) :
+ my_snprintf(buff, 2048, "Wrong option to %s. Option(s) given: %s\n",
+ option, x));
+ cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), "Alternatives are: '%s'", *ptr);
while (*++ptr)
- fprintf(stderr, ",'%s'", *ptr);
- fprintf(stderr, "\n");
- exit(1);
+ cbuf+= my_snprintf(cbuf, 2048 - (cbuf-buff), ",'%s'", *ptr);
+ my_snprintf(cbuf, 2048 - (cbuf-buff), "\n");
+ sql_perror(buff);
+ *error= 1;
+ my_afree(buff);
+ return 0;
}
- return res;
+
+ return result;
}
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 9f8f17eb4ba..31cb829fd93 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -9239,32 +9239,37 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
KEY *cur_index_info= table->key_info;
KEY *cur_index_info_end= cur_index_info + table->s->keys;
- KEY_PART_INFO *cur_part= NULL;
- KEY_PART_INFO *end_part; /* Last part for loops. */
- /* Last index part. */
- KEY_PART_INFO *last_part= NULL;
- KEY_PART_INFO *first_non_group_part= NULL;
- KEY_PART_INFO *first_non_infix_part= NULL;
- uint key_infix_parts= 0;
- uint cur_group_key_parts= 0;
- uint cur_group_prefix_len= 0;
/* Cost-related variables for the best index so far. */
double best_read_cost= DBL_MAX;
ha_rows best_records= 0;
SEL_ARG *best_index_tree= NULL;
ha_rows best_quick_prefix_records= 0;
uint best_param_idx= 0;
- double cur_read_cost= DBL_MAX;
- ha_rows cur_records;
+
+ const uint pk= param->table->s->primary_key;
SEL_ARG *cur_index_tree= NULL;
ha_rows cur_quick_prefix_records= 0;
uint cur_param_idx=MAX_KEY;
- key_map cur_used_key_parts;
- uint pk= param->table->s->primary_key;
for (uint cur_index= 0 ; cur_index_info != cur_index_info_end ;
cur_index_info++, cur_index++)
{
+ KEY_PART_INFO *cur_part;
+ KEY_PART_INFO *end_part; /* Last part for loops. */
+ /* Last index part. */
+ KEY_PART_INFO *last_part;
+ KEY_PART_INFO *first_non_group_part;
+ KEY_PART_INFO *first_non_infix_part;
+ uint key_infix_parts;
+ uint cur_group_key_parts= 0;
+ uint cur_group_prefix_len= 0;
+ double cur_read_cost;
+ ha_rows cur_records;
+ key_map used_key_parts_map;
+ uint cur_key_infix_len= 0;
+ uchar cur_key_infix[MAX_KEY_LENGTH];
+ uint cur_used_key_parts;
+
/* Check (B1) - if current index is covering. */
if (!table->covering_keys.is_set(cur_index))
goto next_index;
@@ -9334,7 +9339,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
else if (join->select_distinct)
{
select_items_it.rewind();
- cur_used_key_parts.clear_all();
+ used_key_parts_map.clear_all();
uint max_key_part= 0;
while ((item= select_items_it++))
{
@@ -9345,13 +9350,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
Check if this attribute was already present in the select list.
If it was present, then its corresponding key part was alredy used.
*/
- if (cur_used_key_parts.is_set(key_part_nr))
+ if (used_key_parts_map.is_set(key_part_nr))
continue;
if (key_part_nr < 1 || key_part_nr > join->fields_list.elements)
goto next_index;
cur_part= cur_index_info->key_part + key_part_nr - 1;
cur_group_prefix_len+= cur_part->store_length;
- cur_used_key_parts.set_bit(key_part_nr);
+ used_key_parts_map.set_bit(key_part_nr);
++cur_group_key_parts;
max_key_part= max(max_key_part,key_part_nr);
}
@@ -9363,7 +9368,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
ulonglong all_parts, cur_parts;
all_parts= (1<<max_key_part) - 1;
- cur_parts= cur_used_key_parts.to_ulonglong() >> 1;
+ cur_parts= used_key_parts_map.to_ulonglong() >> 1;
if (all_parts != cur_parts)
goto next_index;
}
@@ -9413,7 +9418,8 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
&dummy);
if (!get_constant_key_infix(cur_index_info, index_range_tree,
first_non_group_part, min_max_arg_part,
- last_part, thd, key_infix, &key_infix_len,
+ last_part, thd, cur_key_infix,
+ &cur_key_infix_len,
&first_non_infix_part))
goto next_index;
}
@@ -9467,9 +9473,9 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
}
/* If we got to this point, cur_index_info passes the test. */
- key_infix_parts= key_infix_len ?
+ key_infix_parts= cur_key_infix_len ?
(first_non_infix_part - first_non_group_part) : 0;
- used_key_parts= cur_group_key_parts + key_infix_parts;
+ cur_used_key_parts= cur_group_key_parts + key_infix_parts;
/* Compute the cost of using this index. */
if (tree)
@@ -9481,7 +9487,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
cur_quick_prefix_records= check_quick_select(param, cur_param_idx,
cur_index_tree, TRUE);
}
- cost_group_min_max(table, cur_index_info, used_key_parts,
+ cost_group_min_max(table, cur_index_info, cur_used_key_parts,
cur_group_key_parts, tree, cur_index_tree,
cur_quick_prefix_records, have_min, have_max,
&cur_read_cost, &cur_records);
@@ -9492,7 +9498,6 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
*/
if (cur_read_cost < best_read_cost - (DBL_EPSILON * cur_read_cost))
{
- DBUG_ASSERT(tree != 0 || cur_param_idx == MAX_KEY);
index_info= cur_index_info;
index= cur_index;
best_read_cost= cur_read_cost;
@@ -9502,11 +9507,13 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree)
best_param_idx= cur_param_idx;
group_key_parts= cur_group_key_parts;
group_prefix_len= cur_group_prefix_len;
+ key_infix_len= cur_key_infix_len;
+ if (key_infix_len)
+ memcpy (key_infix, cur_key_infix, sizeof (key_infix));
+ used_key_parts= cur_used_key_parts;
}
- next_index:
- cur_group_key_parts= 0;
- cur_group_prefix_len= 0;
+ next_index:;
}
if (!index_info) /* No usable index found. */
DBUG_RETURN(NULL);
diff --git a/sql/protocol.cc b/sql/protocol.cc
index e608420f21a..a99259ffbcf 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -576,7 +576,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
else
{
/* With conversion */
- uint max_char_len;
+ ulonglong max_length;
+ uint32 field_length;
int2store(pos, thd_charset->number);
/*
For TEXT/BLOB columns, field_length describes the maximum data
@@ -587,12 +588,22 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
char_count * mbmaxlen, where character count is taken from the
definition of the column. In other words, the maximum number
of characters here is limited by the column definition.
+
+ When one has a LONG TEXT column with a single-byte
+ character set, and the connection character set is multi-byte, the
+ client may get fields longer than UINT_MAX32, due to
+ <character set column> -> <character set connection> conversion.
+ In that case column max length does not fit into the 4 bytes
+ reserved for it in the protocol.
*/
- max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
- field.type <= (int) MYSQL_TYPE_BLOB) ?
- field.length / item->collation.collation->mbminlen :
- field.length / item->collation.collation->mbmaxlen;
- int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
+ max_length= (field.type >= MYSQL_TYPE_TINY_BLOB &&
+ field.type <= MYSQL_TYPE_BLOB) ?
+ field.length / item->collation.collation->mbminlen :
+ field.length / item->collation.collation->mbmaxlen;
+ max_length*= thd_charset->mbmaxlen;
+ field_length= (max_length > UINT_MAX32) ?
+ UINT_MAX32 : (uint32) max_length;
+ int4store(pos + 2, field_length);
}
pos[6]= field.type;
int2store(pos+7,field.flags);
diff --git a/sql/rpl_record.cc b/sql/rpl_record.cc
index 7c74dcba5a0..14a80cbb4b6 100644
--- a/sql/rpl_record.cc
+++ b/sql/rpl_record.cc
@@ -297,21 +297,16 @@ unpack_row(Relay_log_info const *rli,
/**
Fills @c table->record[0] with default values.
- First @c empty_record() is called and then, additionally, fields are
- initialized explicitly with a call to @c set_default().
-
- For optimization reasons, the explicit initialization can be skipped for
- first @c skip fields. This is useful if later we are going to fill these
- fields from other source (e.g. from a Rows replication event).
-
- If @c check is true, fields are explicitly initialized only if they have
- default value or can be NULL. Otherwise error is reported.
+ First @c restore_record() is called to restore the default values for
+ record concerning the given table. Then, if @c check is true,
+ a check is performed to see if fields are have default value or can
+ be NULL. Otherwise error is reported.
@param table Table whose record[0] buffer is prepared.
- @param skip Number of columns for which default value initialization
+ @param skip Number of columns for which default/nullable check
should be skipped.
- @param check Indicates if errors should be checked when setting default
- values.
+ @param check Indicates if errors should be raised when checking
+ default/nullable field properties.
@returns 0 on success or a handler level error code
*/
@@ -321,25 +316,28 @@ int prepare_record(TABLE *const table,
DBUG_ENTER("prepare_record");
int error= 0;
- empty_record(table);
+ restore_record(table, s->default_values);
- if (skip >= table->s->fields) // nothing to do
+ /*
+ This skip should be revisited in 6.0, because in 6.0 RBR one
+ can have holes in the row (as the grain of the writeset is
+ the column and not the entire row).
+ */
+ if (skip >= table->s->fields || !check)
DBUG_RETURN(0);
- /* Explicit initialization of fields */
+ /* Checking if exists default/nullable fields in the default values. */
for (Field **field_ptr= table->field+skip ; *field_ptr ; ++field_ptr)
{
uint32 const mask= NOT_NULL_FLAG | NO_DEFAULT_VALUE_FLAG;
Field *const f= *field_ptr;
- if (check && ((f->flags & mask) == mask))
+ if (((f->flags & mask) == mask))
{
my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), f->field_name);
error = HA_ERR_ROWS_EVENT_APPLY;
}
- else
- f->set_default();
}
DBUG_RETURN(error);
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index fe8e17dc1c7..03ea244c4e5 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -104,6 +104,11 @@ int init_relay_log_info(Relay_log_info* rli,
rli->tables_to_lock= 0;
rli->tables_to_lock_count= 0;
+ fn_format(rli->slave_patternload_file, PREFIX_SQL_LOAD, slave_load_tmpdir, "",
+ MY_PACK_FILENAME | MY_UNPACK_FILENAME |
+ MY_RETURN_REAL_PATH);
+ rli->slave_patternload_file_size= strlen(rli->slave_patternload_file);
+
/*
The relay log will now be opened, as a SEQ_READ_APPEND IO_CACHE.
Note that the I/O thread flushes it to disk after writing every
diff --git a/sql/rpl_rli.h b/sql/rpl_rli.h
index e13ea93842c..171778d9675 100644
--- a/sql/rpl_rli.h
+++ b/sql/rpl_rli.h
@@ -260,6 +260,13 @@ public:
char ign_master_log_name_end[FN_REFLEN];
ulonglong ign_master_log_pos_end;
+ /*
+ Indentifies where the SQL Thread should create temporary files for the
+ LOAD DATA INFILE. This is used for security reasons.
+ */
+ char slave_patternload_file[FN_REFLEN];
+ size_t slave_patternload_file_size;
+
Relay_log_info();
~Relay_log_info();
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 66d4db2d9b2..6fa15dd3c7c 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -110,6 +110,7 @@ static void sys_default_init_connect(THD*, enum_var_type type);
static bool sys_update_init_slave(THD*, set_var*);
static void sys_default_init_slave(THD*, enum_var_type type);
static bool set_option_bit(THD *thd, set_var *var);
+static bool set_option_log_bin_bit(THD *thd, set_var *var);
static bool set_option_autocommit(THD *thd, set_var *var);
static int check_log_update(THD *thd, set_var *var);
static bool set_log_update(THD *thd, set_var *var);
@@ -134,8 +135,6 @@ static int check_max_delayed_threads(THD *thd, set_var *var);
static void fix_thd_mem_root(THD *thd, enum_var_type type);
static void fix_trans_mem_root(THD *thd, enum_var_type type);
static void fix_server_id(THD *thd, enum_var_type type);
-static ulonglong fix_unsigned(THD *, ulonglong, const struct my_option *);
-static bool get_unsigned(THD *thd, set_var *var);
bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
const char *name, longlong val);
static KEY_CACHE *create_key_cache(const char *name, uint length);
@@ -744,7 +743,7 @@ static sys_var_thd_bit sys_log_update(&vars, "sql_log_update",
OPTION_BIN_LOG);
static sys_var_thd_bit sys_log_binlog(&vars, "sql_log_bin",
check_log_update,
- set_option_bit,
+ set_option_log_bin_bit,
OPTION_BIN_LOG);
static sys_var_thd_bit sys_sql_warnings(&vars, "sql_warnings", 0,
set_option_bit,
@@ -1384,6 +1383,19 @@ static void fix_server_id(THD *thd, enum_var_type type)
}
+/**
+ Throw warning (error in STRICT mode) if value for variable needed bounding.
+ Only call from check(), not update(), because an error in update() would be
+ bad mojo. Plug-in interface also uses this.
+
+ @param thd thread handle
+ @param fixed did we have to correct the value? (throw warn/err if so)
+ @param unsignd is value's type unsigned?
+ @param name variable's name
+ @param val variable's value
+
+ @retval TRUE on error, FALSE otherwise (warning or OK)
+ */
bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
const char *name, longlong val)
{
@@ -1409,26 +1421,128 @@ bool throw_bounds_warning(THD *thd, bool fixed, bool unsignd,
return FALSE;
}
-static ulonglong fix_unsigned(THD *thd, ulonglong num,
+
+/**
+ check an unsigned user-supplied value for a systemvariable against bounds.
+
+ TODO: This is a wrapper function to call clipping from within an update()
+ function. Calling bounds from within update() is fair game in theory,
+ but we can only send warnings from in there, not errors, and besides,
+ it violates our model of separating check from update phase.
+ To avoid breaking out of the server with an ASSERT() in strict mode,
+ we pretend we're not in strict mode when we go through here. Bug#43233
+ was opened to remind us to replace this kludge with The Right Thing,
+ which of course is to do the check in the actual check phase, and then
+ throw an error or warning accordingly.
+
+ @param thd thread handle
+ @param num the value to limit
+ @param option_limits the bounds-record, or NULL if none
+ */
+static void bound_unsigned(THD *thd, ulonglong *num,
const struct my_option *option_limits)
{
- my_bool fixed= FALSE;
- ulonglong out= getopt_ull_limit_value(num, option_limits, &fixed);
+ if (option_limits)
+ {
+ my_bool fixed = FALSE;
+ ulonglong unadjusted= *num;
+
+ *num= getopt_ull_limit_value(unadjusted, option_limits, &fixed);
- throw_bounds_warning(thd, fixed, TRUE, option_limits->name, (longlong) num);
- return out;
+ if (fixed)
+ {
+ ulong ssm= thd->variables.sql_mode;
+ thd->variables.sql_mode&= ~MODE_STRICT_ALL_TABLES;
+ throw_bounds_warning(thd, fixed, TRUE, option_limits->name, unadjusted);
+ thd->variables.sql_mode= ssm;
+ }
+ }
}
-static bool get_unsigned(THD *thd, set_var *var)
-{
+
+/**
+ Get unsigned system-variable.
+ Negative value does not wrap around, but becomes zero.
+ Check user-supplied value for a systemvariable against bounds.
+ If we needed to adjust the value, throw a warning or error depending
+ on SQL-mode.
+
+ @param thd thread handle
+ @param var the system-variable to get
+ @param user_max a limit given with --maximum-variable-name=... or 0
+ @param var_type function will bound on systems where necessary.
+
+ @retval TRUE on error, FALSE otherwise (warning or OK)
+ */
+static bool get_unsigned(THD *thd, set_var *var, ulonglong user_max,
+ ulong var_type)
+{
+ int warnings= 0;
+ ulonglong unadjusted;
+ const struct my_option *limits= var->var->option_limits;
+ struct my_option fallback;
+
+ /* get_unsigned() */
if (var->value->unsigned_flag)
var->save_result.ulonglong_value= (ulonglong) var->value->val_int();
else
{
longlong v= var->value->val_int();
var->save_result.ulonglong_value= (ulonglong) ((v < 0) ? 0 : v);
+ if (v < 0)
+ {
+ warnings++;
+ if (throw_bounds_warning(thd, TRUE, FALSE, var->var->name, v))
+ return TRUE; /* warning was promoted to error, give up */
+ }
}
- return 0;
+
+ unadjusted= var->save_result.ulonglong_value;
+
+ /* max, if any */
+
+ if ((user_max > 0) && (unadjusted > user_max))
+ {
+ var->save_result.ulonglong_value= user_max;
+
+ if ((warnings == 0) && throw_bounds_warning(thd, TRUE, TRUE,
+ var->var->name,
+ (longlong) unadjusted))
+ return TRUE;
+
+ warnings++;
+ }
+
+ /*
+ if the sysvar doesn't have a proper bounds record but the check
+ function would like bounding to ULONG where its size differs from
+ that of ULONGLONG, we make up a bogus limits record here and let
+ the usual suspects handle the actual limiting.
+ */
+
+ if (!limits && var_type != GET_ULL)
+ {
+ bzero(&fallback, sizeof(fallback));
+ fallback.var_type= var_type;
+ limits= &fallback;
+ }
+
+ /* fix_unsigned() */
+ if (limits)
+ {
+ my_bool fixed;
+
+ var->save_result.ulonglong_value= getopt_ull_limit_value(var->save_result.
+ ulonglong_value,
+ limits, &fixed);
+
+ if ((warnings == 0) && throw_bounds_warning(thd, fixed, TRUE,
+ var->var->name,
+ (longlong) unadjusted))
+ return TRUE;
+ }
+
+ return FALSE;
}
@@ -1442,29 +1556,13 @@ sys_var_long_ptr(sys_var_chain *chain, const char *name_arg, ulong *value_ptr_ar
bool sys_var_long_ptr_global::check(THD *thd, set_var *var)
{
- return get_unsigned(thd, var);
+ return get_unsigned(thd, var, 0, GET_ULONG);
}
bool sys_var_long_ptr_global::update(THD *thd, set_var *var)
{
- ulonglong tmp= var->save_result.ulonglong_value;
pthread_mutex_lock(guard);
- if (option_limits)
- *value= (ulong) fix_unsigned(thd, tmp, option_limits);
- else
- {
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
- /* Avoid overflows on 32 bit systems */
- if (tmp > ULONG_MAX)
- {
- tmp= ULONG_MAX;
- throw_bounds_warning(thd, TRUE, TRUE, name,
- (longlong) var->save_result.ulonglong_value);
- }
-#endif
- *value= (ulong) tmp;
- }
-
+ *value= (ulong) var->save_result.ulonglong_value;
pthread_mutex_unlock(guard);
return 0;
}
@@ -1484,10 +1582,8 @@ bool sys_var_ulonglong_ptr::update(THD *thd, set_var *var)
{
ulonglong tmp= var->save_result.ulonglong_value;
pthread_mutex_lock(&LOCK_global_system_variables);
- if (option_limits)
- *value= (ulonglong) fix_unsigned(thd, tmp, option_limits);
- else
- *value= (ulonglong) tmp;
+ bound_unsigned(thd, &tmp, option_limits);
+ *value= (ulonglong) tmp;
pthread_mutex_unlock(&LOCK_global_system_variables);
return 0;
}
@@ -1536,36 +1632,18 @@ uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type,
bool sys_var_thd_ulong::check(THD *thd, set_var *var)
{
- return (get_unsigned(thd, var) ||
- (check_func && (*check_func)(thd, var)));
+ if (get_unsigned(thd, var, max_system_variables.*offset, GET_ULONG))
+ return TRUE;
+ DBUG_ASSERT(var->save_result.ulonglong_value <= ULONG_MAX);
+ return ((check_func && (*check_func)(thd, var)));
}
bool sys_var_thd_ulong::update(THD *thd, set_var *var)
{
- ulonglong tmp= var->save_result.ulonglong_value;
-
- /* Don't use bigger value than given with --maximum-variable-name=.. */
- if (tmp > max_system_variables.*offset)
- {
- throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) tmp);
- tmp= max_system_variables.*offset;
- }
-
- if (option_limits)
- tmp= fix_unsigned(thd, tmp, option_limits);
-#if SIZEOF_LONG < SIZEOF_LONG_LONG
- else if (tmp > ULONG_MAX)
- {
- tmp= ULONG_MAX;
- throw_bounds_warning(thd, TRUE, TRUE, name, (longlong) var->save_result.ulonglong_value);
- }
-#endif
-
- DBUG_ASSERT(tmp <= ULONG_MAX);
if (var->type == OPT_GLOBAL)
- global_system_variables.*offset= (ulong) tmp;
+ global_system_variables.*offset= (ulong) var->save_result.ulonglong_value;
else
- thd->variables.*offset= (ulong) tmp;
+ thd->variables.*offset= (ulong) var->save_result.ulonglong_value;
return 0;
}
@@ -1603,8 +1681,8 @@ bool sys_var_thd_ha_rows::update(THD *thd, set_var *var)
if ((ha_rows) tmp > max_system_variables.*offset)
tmp= max_system_variables.*offset;
- if (option_limits)
- tmp= (ha_rows) fix_unsigned(thd, tmp, option_limits);
+ bound_unsigned(thd, &tmp, option_limits);
+
if (var->type == OPT_GLOBAL)
{
/* Lock is needed to make things safe on 32 bit systems */
@@ -1645,27 +1723,21 @@ uchar *sys_var_thd_ha_rows::value_ptr(THD *thd, enum_var_type type,
bool sys_var_thd_ulonglong::check(THD *thd, set_var *var)
{
- return get_unsigned(thd, var);
+ return get_unsigned(thd, var, max_system_variables.*offset, GET_ULL);
}
bool sys_var_thd_ulonglong::update(THD *thd, set_var *var)
{
- ulonglong tmp= var->save_result.ulonglong_value;
-
- if (tmp > max_system_variables.*offset)
- tmp= max_system_variables.*offset;
-
- if (option_limits)
- tmp= fix_unsigned(thd, tmp, option_limits);
if (var->type == OPT_GLOBAL)
{
/* Lock is needed to make things safe on 32 bit systems */
pthread_mutex_lock(&LOCK_global_system_variables);
- global_system_variables.*offset= (ulonglong) tmp;
+ global_system_variables.*offset= (ulonglong)
+ var->save_result.ulonglong_value;
pthread_mutex_unlock(&LOCK_global_system_variables);
}
else
- thd->variables.*offset= (ulonglong) tmp;
+ thd->variables.*offset= (ulonglong) var->save_result.ulonglong_value;
return 0;
}
@@ -2296,10 +2368,10 @@ bool sys_var_key_buffer_size::update(THD *thd, set_var *var)
goto end;
}
- key_cache->param_buff_size=
- (ulonglong) fix_unsigned(thd, tmp, option_limits);
+ bound_unsigned(thd, &tmp, option_limits);
+ key_cache->param_buff_size= (ulonglong) tmp;
- /* If key cache didn't existed initialize it, else resize it */
+ /* If key cache didn't exist initialize it, else resize it */
key_cache->in_init= 1;
pthread_mutex_unlock(&LOCK_global_system_variables);
@@ -2325,7 +2397,7 @@ end:
*/
bool sys_var_key_cache_long::update(THD *thd, set_var *var)
{
- ulong tmp= (ulong) var->value->val_int();
+ ulonglong tmp= var->value->val_int();
LEX_STRING *base_name= &var->base;
bool error= 0;
@@ -2350,8 +2422,8 @@ bool sys_var_key_cache_long::update(THD *thd, set_var *var)
if (key_cache->in_init)
goto end;
- *((ulong*) (((char*) key_cache) + offset))=
- (ulong) fix_unsigned(thd, tmp, option_limits);
+ bound_unsigned(thd, &tmp, option_limits);
+ *((ulong*) (((char*) key_cache) + offset))= (ulong) tmp;
/*
Don't create a new key cache if it didn't exist
@@ -2968,6 +3040,16 @@ static bool set_option_bit(THD *thd, set_var *var)
return 0;
}
+/*
+ Functions to be only used to update thd->options OPTION_BIN_LOG bit
+*/
+static bool set_option_log_bin_bit(THD *thd, set_var *var)
+{
+ set_option_bit(thd, var);
+ if (!thd->in_sub_stmt)
+ thd->sql_log_bin_toplevel= thd->options & OPTION_BIN_LOG;
+ return 0;
+}
static bool set_option_autocommit(THD *thd, set_var *var)
{
@@ -3687,7 +3769,7 @@ bool sys_var_thd_storage_engine::update(THD *thd, set_var *var)
void sys_var_thd_table_type::warn_deprecated(THD *thd)
{
- WARN_DEPRECATED(thd, "5.2", "@@table_type", "'@@storage_engine'");
+ WARN_DEPRECATED(thd, "6.0", "@@table_type", "'@@storage_engine'");
}
void sys_var_thd_table_type::set_default(THD *thd, enum_var_type type)
@@ -3949,7 +4031,7 @@ bool process_key_caches(process_key_cache_t func)
void sys_var_trust_routine_creators::warn_deprecated(THD *thd)
{
- WARN_DEPRECATED(thd, "5.2", "@@log_bin_trust_routine_creators",
+ WARN_DEPRECATED(thd, "6.0", "@@log_bin_trust_routine_creators",
"'@@log_bin_trust_function_creators'");
}
diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt
index befd064e3e3..aa1521acab6 100644
--- a/sql/share/errmsg.txt
+++ b/sql/share/errmsg.txt
@@ -5775,9 +5775,9 @@ ER_PARTITION_MGMT_ON_NONPARTITIONED
ger "Partitionsverwaltung einer nicht partitionierten Tabelle ist nicht möglich"
swe "Partitioneringskommando på en opartitionerad tabell är inte möjligt"
ER_FOREIGN_KEY_ON_PARTITIONED
- eng "Foreign key condition is not yet supported in conjunction with partitioning"
+ eng "Foreign key clause is not yet supported in conjunction with partitioning"
ger "Fremdschlüssel-Beschränkungen sind im Zusammenhang mit Partitionierung nicht zulässig"
- swe "Foreign key villkor är inte ännu implementerad i kombination med partitionering"
+ swe "Foreign key klausul är inte ännu implementerad i kombination med partitionering"
ER_DROP_PARTITION_NON_EXISTENT
eng "Error in list of partitions to %-.64s"
ger "Fehler in der Partitionsliste bei %-.64s"
@@ -5791,13 +5791,13 @@ ER_COALESCE_ONLY_ON_HASH_PARTITION
ger "COALESCE PARTITION kann nur auf HASH- oder KEY-Partitionen benutzt werden"
swe "COALESCE PARTITION kan bara användas på HASH/KEY partitioner"
ER_REORG_HASH_ONLY_ON_SAME_NO
- eng "REORGANISE PARTITION can only be used to reorganise partitions not to change their numbers"
+ eng "REORGANIZE PARTITION can only be used to reorganize partitions not to change their numbers"
ger "REORGANIZE PARTITION kann nur zur Reorganisation von Partitionen verwendet werden, nicht, um ihre Nummern zu ändern"
- swe "REORGANISE PARTITION kan bara användas för att omorganisera partitioner, inte för att ändra deras antal"
+ swe "REORGANIZE PARTITION kan bara användas för att omorganisera partitioner, inte för att ändra deras antal"
ER_REORG_NO_PARAM_ERROR
- eng "REORGANISE PARTITION without parameters can only be used on auto-partitioned tables using HASH PARTITIONs"
+ eng "REORGANIZE PARTITION without parameters can only be used on auto-partitioned tables using HASH PARTITIONs"
ger "REORGANIZE PARTITION ohne Parameter kann nur für auto-partitionierte Tabellen verwendet werden, die HASH-Partitionierung benutzen"
- swe "REORGANISE PARTITION utan parametrar kan bara användas på auto-partitionerade tabeller som använder HASH partitionering"
+ swe "REORGANIZE PARTITION utan parametrar kan bara användas på auto-partitionerade tabeller som använder HASH partitionering"
ER_ONLY_ON_RANGE_LIST_PARTITION
eng "%-.64s PARTITION can only be used on RANGE/LIST partitions"
ger "%-.64s PARTITION kann nur für RANGE- oder LIST-Partitionen verwendet werden"
@@ -5815,7 +5815,7 @@ ER_COALESCE_PARTITION_NO_PARTITION
ger "Zumindest eine Partition muss mit COALESCE PARTITION zusammengefügt werden"
swe "Åtminstone en partition måste slås ihop vid COALESCE PARTITION"
ER_REORG_PARTITION_NOT_EXIST
- eng "More partitions to reorganise than there are partitions"
+ eng "More partitions to reorganize than there are partitions"
ger "Es wurde versucht, mehr Partitionen als vorhanden zu reorganisieren"
swe "Fler partitioner att reorganisera än det finns partitioner"
ER_SAME_NAME_PARTITION
@@ -5827,7 +5827,7 @@ ER_NO_BINLOG_ERROR
ger "Es es nicht erlaubt, bei diesem Befehl binlog abzuschalten"
swe "Det är inte tillåtet att stänga av binlog på detta kommando"
ER_CONSECUTIVE_REORG_PARTITIONS
- eng "When reorganising a set of partitions they must be in consecutive order"
+ eng "When reorganizing a set of partitions they must be in consecutive order"
ger "Bei der Reorganisation eines Satzes von Partitionen müssen diese in geordneter Reihenfolge vorliegen"
swe "När ett antal partitioner omorganiseras måste de vara i konsekutiv ordning"
ER_REORG_OUTSIDE_RANGE
@@ -6154,3 +6154,26 @@ WARN_PLUGIN_BUSY
ER_VARIABLE_IS_READONLY
eng "%s variable '%s' is read-only. Use SET %s to assign the value"
+
+ER_WARN_ENGINE_TRANSACTION_ROLLBACK
+ eng "Storage engine %s does not support rollback for this statement. Transaction rolled back and must be restarted"
+
+ER_SLAVE_HEARTBEAT_FAILURE
+ eng "Unexpected master's heartbeat data: %s"
+ER_SLAVE_HEARTBEAT_VALUE_OUT_OF_RANGE
+ eng "The requested value for the heartbeat period %s %s"
+
+ER_NDB_REPLICATION_SCHEMA_ERROR
+ eng "Bad schema for mysql.ndb_replication table. Message: %-.64s"
+ER_CONFLICT_FN_PARSE_ERROR
+ eng "Error in parsing conflict function. Message: %-.64s"
+ER_EXCEPTIONS_WRITE_ERROR
+ eng "Write to exceptions table failed. Message: %-.128s""
+
+ER_TOO_LONG_TABLE_COMMENT
+ eng "Comment for table '%-.64s' is too long (max = %lu)"
+ por "Comentário para a tabela '%-.64s' é longo demais (max = %lu)"
+
+ER_TOO_LONG_FIELD_COMMENT
+ eng "Comment for field '%-.64s' is too long (max = %lu)"
+ por "Comentário para o campo '%-.64s' é longo demais (max = %lu)"
diff --git a/sql/sp.cc b/sql/sp.cc
index cc545992857..b2c7c389136 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -936,10 +936,12 @@ sp_create_routine(THD *thd, int type, sp_head *sp)
ret= SP_INTERNAL_ERROR;
goto done;
}
-
+ /* restore sql_mode when binloging */
+ thd->variables.sql_mode= saved_mode;
/* Such a statement can always go directly to binlog, no trans cache */
thd->binlog_query(THD::MYSQL_QUERY_TYPE,
log_query.c_ptr(), log_query.length(), FALSE, FALSE);
+ thd->variables.sql_mode= 0;
}
}
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index 695bb2d07e5..9bc01511600 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -1440,7 +1440,8 @@ void close_temporary_tables(THD *thd)
if (!thd->temporary_tables)
return;
- if (!mysql_bin_log.is_open() || thd->current_stmt_binlog_row_based)
+ if (!mysql_bin_log.is_open() ||
+ (thd->current_stmt_binlog_row_based && thd->variables.binlog_format == BINLOG_FORMAT_ROW))
{
TABLE *tmp_next;
for (table= thd->temporary_tables; table; table= tmp_next)
diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc
index 63a5af5e666..5ff5e596f63 100644
--- a/sql/sql_cache.cc
+++ b/sql/sql_cache.cc
@@ -418,6 +418,43 @@ TYPELIB query_cache_type_typelib=
array_elements(query_cache_type_names)-1,"", query_cache_type_names, NULL
};
+
+/**
+ Helper function for determine if a SELECT statement has a SQL_NO_CACHE
+ directive.
+
+ @param sql A pointer to the first white space character after SELECT
+
+ @return
+ @retval TRUE The character string contains SQL_NO_CACHE
+ @retval FALSE No directive found.
+*/
+
+static bool has_no_cache_directive(char *sql)
+{
+ int i=0;
+ while (sql[i] == ' ')
+ ++i;
+
+ if (my_toupper(system_charset_info, sql[i]) == 'S' &&
+ my_toupper(system_charset_info, sql[i+1]) == 'Q' &&
+ my_toupper(system_charset_info, sql[i+2]) == 'L' &&
+ my_toupper(system_charset_info, sql[i+3]) == '_' &&
+ my_toupper(system_charset_info, sql[i+4]) == 'N' &&
+ my_toupper(system_charset_info, sql[i+5]) == 'O' &&
+ my_toupper(system_charset_info, sql[i+6]) == '_' &&
+ my_toupper(system_charset_info, sql[i+7]) == 'C' &&
+ my_toupper(system_charset_info, sql[i+8]) == 'A' &&
+ my_toupper(system_charset_info, sql[i+9]) == 'C' &&
+ my_toupper(system_charset_info, sql[i+10]) == 'H' &&
+ my_toupper(system_charset_info, sql[i+11]) == 'E' &&
+ my_toupper(system_charset_info, sql[i+12]) == ' ')
+ return TRUE;
+
+ return FALSE;
+}
+
+
/*****************************************************************************
Query_cache_block_table method(s)
*****************************************************************************/
@@ -1236,6 +1273,16 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length)
DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached"));
goto err;
}
+
+ if (query_length > 20 && has_no_cache_directive(&sql[i+6]))
+ {
+ /*
+ We do not increase 'refused' statistics here since it will be done
+ later when the query is parsed.
+ */
+ DBUG_PRINT("qcache", ("The statement has a SQL_NO_CACHE directive"));
+ goto err;
+ }
}
STRUCT_LOCK(&structure_guard_mutex);
@@ -1524,6 +1571,9 @@ void Query_cache::invalidate(THD *thd, TABLE_LIST *tables_used,
invalidate_table(thd, tables_used);
}
+ DBUG_EXECUTE_IF("wait_after_query_cache_invalidate",
+ debug_wait_for_kill("wait_after_query_cache_invalidate"););
+
DBUG_VOID_RETURN;
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index 125a4ceea2f..cbb1861fe71 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -543,6 +543,7 @@ THD::THD()
Open_tables_state(refresh_version), rli_fake(0),
lock_id(&main_lock_id),
user_time(0), in_sub_stmt(0),
+ sql_log_bin_toplevel(false),
binlog_table_maps(0), binlog_flags(0UL),
table_map_for_update(0),
arg_of_last_insert_id_function(FALSE),
@@ -796,6 +797,7 @@ void THD::init(void)
update_charset();
reset_current_stmt_binlog_row_based();
bzero((char *) &status_var, sizeof(status_var));
+ sql_log_bin_toplevel= options & OPTION_BIN_LOG;
}
@@ -1640,6 +1642,11 @@ bool select_send::send_data(List<Item> &items)
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
break;
}
+ /*
+ Reset buffer to its original state, as it may have been altered in
+ Item::send().
+ */
+ buffer.set(buff, sizeof(buff), &my_charset_bin);
}
thd->sent_row_count++;
if (thd->is_error())
@@ -3646,7 +3653,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, char const *query_arg,
If we are in statement mode and trying to log an unsafe statement,
we should print a warning.
*/
- if (lex->is_stmt_unsafe() &&
+ if (sql_log_bin_toplevel && lex->is_stmt_unsafe() &&
variables.binlog_format == BINLOG_FORMAT_STMT)
{
push_warning(this, MYSQL_ERROR::WARN_LEVEL_WARN,
diff --git a/sql/sql_class.h b/sql/sql_class.h
index c491f2d3348..a3bb79773ec 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -1356,6 +1356,8 @@ public:
/* <> 0 if we are inside of trigger or stored function. */
uint in_sub_stmt;
+ /* TRUE when the current top has SQL_LOG_BIN ON */
+ bool sql_log_bin_toplevel;
/* container for handler's private per-connection data */
Ha_data ha_data[MAX_HA];
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index 28a9fb5c78e..9c8bba6208c 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -160,6 +160,9 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables,
table->query_id= thd->query_id;
table->open_by_handler= 0;
}
+
+ /* Mark table as closed, ready for re-open if necessary. */
+ tables->table= NULL;
}
/*
@@ -177,8 +180,7 @@ static void mysql_ha_close_table(THD *thd, TABLE_LIST *tables,
'reopen' is set when a handler table is to be re-opened. In this case,
'tables' is the pointer to the hashed TABLE_LIST object which has been
saved on the original open.
- 'reopen' is also used to suppress the sending of an 'ok' message or
- error messages.
+ 'reopen' is also used to suppress the sending of an 'ok' message.
RETURN
FALSE OK
@@ -214,8 +216,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
strlen(tables->alias) + 1))
{
DBUG_PRINT("info",("duplicate '%s'", tables->alias));
- if (! reopen)
- my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
+ my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
goto err;
}
}
@@ -259,8 +260,7 @@ bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
/* There can be only one table in '*tables'. */
if (! (tables->table->file->ha_table_flags() & HA_CAN_SQL_HANDLER))
{
- if (! reopen)
- my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
+ my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
goto err;
}
@@ -479,8 +479,7 @@ retry:
if (need_reopen)
{
- mysql_ha_close_table(thd, tables, FALSE);
- hash_tables->table= NULL;
+ mysql_ha_close_table(thd, hash_tables, FALSE);
/*
The lock might have been aborted, we need to manually reset
thd->some_tables_deleted because handler's tables are closed
@@ -761,11 +760,7 @@ void mysql_ha_flush(THD *thd)
{
hash_tables= (TABLE_LIST*) hash_element(&thd->handler_tables_hash, i);
if (hash_tables->table && hash_tables->table->needs_reopen_or_name_lock())
- {
mysql_ha_close_table(thd, hash_tables, TRUE);
- /* Mark table as closed, ready for re-open. */
- hash_tables->table= NULL;
- }
}
DBUG_VOID_RETURN;
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 61b8490f9be..728dd1bcae6 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -928,20 +928,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
}
DBUG_ASSERT(transactional_table || !changed ||
thd->transaction.stmt.modified_non_trans_table);
-
- if (thd->lock)
- {
- /*
- Invalidate the table in the query cache if something changed
- after unlocking when changes become fisible.
- TODO: this is workaround. right way will be move invalidating in
- the unlock procedure.
- */
- if (lock_type == TL_WRITE_CONCURRENT_INSERT && changed)
- {
- query_cache_invalidate3(thd, table_list, 1);
- }
- }
}
thd_proc_info(thd, "end");
/*
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index 9619d26893c..19a19f2b6fb 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -1559,6 +1559,7 @@ void st_select_lex::init_query()
exclude_from_table_unique_test= no_wrap_view_item= FALSE;
nest_level= 0;
link_next= 0;
+ lock_option= TL_READ_DEFAULT;
}
void st_select_lex::init_select()
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index ed6b9e7d8df..a48b99d07c7 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -688,6 +688,15 @@ public:
int cur_pos_in_select_list;
List<udf_func> udf_list; /* udf function calls stack */
+
+ /**
+ Per sub-query locking strategy.
+ Note: This variable might interfer with the corresponding statement-level
+ variable Lex::lock_option because on how different parser rules depend
+ on eachother.
+ */
+ thr_lock_type lock_option;
+
/*
This is a copy of the original JOIN USING list that comes from
the parser. The parser :
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index cae8f682a09..9334d19fc1c 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -15,10 +15,10 @@
/* Copy data from a textfile to table */
-
#include "mysql_priv.h"
#include <my_dir.h>
#include <m_ctype.h>
+#include "rpl_mi.h"
#include "sql_repl.h"
#include "sp_head.h"
#include "sql_trigger.h"
@@ -310,8 +310,31 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
is_fifo = 1;
#endif
- if (opt_secure_file_priv &&
- strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv)))
+ if (thd->slave_thread)
+ {
+#if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
+ if (strncmp(active_mi->rli.slave_patternload_file, name,
+ active_mi->rli.slave_patternload_file_size))
+ {
+ /*
+ LOAD DATA INFILE in the slave SQL Thread can only read from
+ --slave-load-tmpdir". This should never happen. Please, report a bug.
+ */
+
+ sql_print_error("LOAD DATA INFILE in the slave SQL Thread can only read from --slave-load-tmpdir. " \
+ "Please, report a bug.");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--slave-load-tmpdir");
+ DBUG_RETURN(TRUE);
+ }
+#else
+ /*
+ This is impossible and should never happen.
+ */
+ DBUG_ASSERT(FALSE);
+#endif
+ }
+ else if (opt_secure_file_priv &&
+ strncmp(opt_secure_file_priv, name, strlen(opt_secure_file_priv)))
{
/* Read only allowed from within dir specified by secure_file_priv */
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--secure-file-priv");
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 8536f2308c9..1e76534e374 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -4449,6 +4449,7 @@ create_sp_error:
case SP_KEY_NOT_FOUND:
if (lex->drop_if_exists)
{
+ write_bin_log(thd, TRUE, thd->query, thd->query_length);
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
SP_COM_STRING(lex), lex->spname->m_name.str);
@@ -5601,6 +5602,14 @@ void mysql_reset_thd_for_next_command(THD *thd)
}
+/**
+ Resets the lex->current_select object.
+ @note It is assumed that lex->current_select != NULL
+
+ This function is a wrapper around select_lex->init_select() with an added
+ check for the special situation when using INTO OUTFILE and LOAD DATA.
+*/
+
void
mysql_init_select(LEX *lex)
{
@@ -5615,6 +5624,18 @@ mysql_init_select(LEX *lex)
}
+/**
+ Used to allocate a new SELECT_LEX object on the current thd mem_root and
+ link it into the relevant lists.
+
+ This function is always followed by mysql_init_select.
+
+ @see mysql_init_select
+
+ @retval TRUE An error occurred
+ @retval FALSE The new SELECT_LEX was successfully allocated.
+*/
+
bool
mysql_new_select(LEX *lex, bool move_down)
{
@@ -5988,7 +6009,7 @@ bool add_field_to_list(THD *thd, LEX_STRING *field_name, enum_field_types type,
*/
char buf[32];
my_snprintf(buf, sizeof(buf), "TIMESTAMP(%s)", length);
- WARN_DEPRECATED(thd, "5.2", buf, "'TIMESTAMP'");
+ WARN_DEPRECATED(thd, "6.0", buf, "'TIMESTAMP'");
}
if (!(new_field= new Create_field()) ||
@@ -6432,7 +6453,6 @@ void st_select_lex::set_lock_for_tables(thr_lock_type lock_type)
DBUG_ENTER("set_lock_for_tables");
DBUG_PRINT("enter", ("lock_type: %d for_update: %d", lock_type,
for_update));
-
for (TABLE_LIST *tables= (TABLE_LIST*) table_list.first;
tables;
tables= tables->next_local)
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 658064db899..401becf1450 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -2483,11 +2483,12 @@ typedef struct st_sargable_param
*/
static bool
-make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
+make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
DYNAMIC_ARRAY *keyuse_array)
{
int error;
TABLE *table;
+ TABLE_LIST *tables= tables_arg;
uint i,table_count,const_count,key;
table_map found_const_table_map, all_table_map, found_ref, refs;
key_map const_ref, eq_part;
@@ -2524,10 +2525,11 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
s->needed_reg.init();
table_vector[i]=s->table=table=tables->table;
table->pos_in_table_list= tables;
- if ((error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK)))
+ error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ if (error)
{
table->file->print_error(error, MYF(0));
- DBUG_RETURN(1);
+ goto error;
}
table->quick_keys.clear_all();
table->reginfo.join_tab=s;
@@ -2623,7 +2625,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
{
join->tables=0; // Don't use join->table
my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
- DBUG_RETURN(1);
+ goto error;
}
s->key_dependent= s->dependent;
}
@@ -2633,7 +2635,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
conds, join->cond_equal,
~outer_join, join->select_lex, &sargables))
- DBUG_RETURN(1);
+ goto error;
/* Read tables with 0 or 1 rows (system tables) */
join->const_table_map= 0;
@@ -2649,7 +2651,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if ((tmp=join_read_const_table(s, p_pos)))
{
if (tmp > 0)
- DBUG_RETURN(1); // Fatal error
+ goto error; // Fatal error
}
else
found_const_table_map|= s->table->map;
@@ -2721,7 +2723,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if ((tmp= join_read_const_table(s, join->positions+const_count-1)))
{
if (tmp > 0)
- DBUG_RETURN(1); // Fatal error
+ goto error; // Fatal error
}
else
found_const_table_map|= table->map;
@@ -2770,12 +2772,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
set_position(join,const_count++,s,start_keyuse);
if (create_ref_for_key(join, s, start_keyuse,
found_const_table_map))
- DBUG_RETURN(1);
+ goto error;
if ((tmp=join_read_const_table(s,
join->positions+const_count-1)))
{
if (tmp > 0)
- DBUG_RETURN(1); // Fatal error
+ goto error; // Fatal error
}
else
found_const_table_map|= table->map;
@@ -2852,7 +2854,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
*s->on_expr_ref ? *s->on_expr_ref : conds,
1, &error);
if (!select)
- DBUG_RETURN(1);
+ goto error;
records= get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit);
s->quick=select->quick;
@@ -2898,7 +2900,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
{
optimize_keyuse(join, keyuse_array);
if (choose_plan(join, all_table_map & ~join->const_table_map))
- DBUG_RETURN(TRUE);
+ goto error;
}
else
{
@@ -2908,6 +2910,17 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
}
/* Generate an execution plan from the found optimal join order. */
DBUG_RETURN(join->thd->killed || get_best_combination(join));
+
+error:
+ /*
+ Need to clean up join_tab from TABLEs in case of error.
+ They won't get cleaned up by JOIN::cleanup() because JOIN::join_tab
+ may not be assigned yet by this function (which is building join_tab).
+ Dangling TABLE::reginfo.join_tab may cause part_of_refkey to choke.
+ */
+ for (tables= tables_arg; tables; tables= tables->next_leaf)
+ tables->table->reginfo.join_tab= NULL;
+ DBUG_RETURN (1);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 8ae2787dc1a..21d97c7b50a 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -287,7 +287,7 @@ static struct show_privileges_st sys_privileges[]=
{"Alter", "Tables", "To alter the table"},
{"Alter routine", "Functions,Procedures", "To alter or drop stored functions/procedures"},
{"Create", "Databases,Tables,Indexes", "To create new databases and tables"},
- {"Create routine","Functions,Procedures","To use CREATE FUNCTION/PROCEDURE"},
+ {"Create routine","Databases","To use CREATE FUNCTION/PROCEDURE"},
{"Create temporary tables","Databases","To use CREATE TEMPORARY TABLE"},
{"Create view", "Tables", "To create new views"},
{"Create user", "Server Admin", "To create new users"},
@@ -468,11 +468,18 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint col_access=thd->col_access;
#endif
+ uint wild_length= 0;
TABLE_LIST table_list;
DBUG_ENTER("find_files");
- if (wild && !wild[0])
- wild=0;
+ if (wild)
+ {
+ if (!wild[0])
+ wild= 0;
+ else
+ wild_length= strlen(wild);
+ }
+
bzero((char*) &table_list,sizeof(table_list));
@@ -537,8 +544,11 @@ find_files(THD *thd, List<LEX_STRING> *files, const char *db,
{
if (lower_case_table_names)
{
- if (wild_case_compare(files_charset_info, uname, wild))
- continue;
+ if (my_wildcmp(files_charset_info,
+ uname, uname + file_name_len,
+ wild, wild + wild_length,
+ wild_prefix, wild_one,wild_many))
+ continue;
}
else if (wild_compare(uname, wild, 0))
continue;
@@ -1590,21 +1600,25 @@ void append_definer(THD *thd, String *buffer, const LEX_STRING *definer_user,
int
view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
{
+ my_bool compact_view_name= TRUE;
my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
MODE_ORACLE |
MODE_MSSQL |
MODE_DB2 |
MODE_MAXDB |
MODE_ANSI)) != 0;
- /*
- Compact output format for view can be used
- - if user has db of this view as current db
- - if this view only references table inside it's own db
- */
+
if (!thd->db || strcmp(thd->db, table->view_db.str))
- table->compact_view_format= FALSE;
+ /*
+ print compact view name if the view belongs to the current database
+ */
+ compact_view_name= table->compact_view_format= FALSE;
else
{
+ /*
+ Compact output format for view body can be used
+ if this view only references table inside it's own db
+ */
TABLE_LIST *tbl;
table->compact_view_format= TRUE;
for (tbl= thd->lex->query_tables;
@@ -1625,7 +1639,7 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
view_store_options(thd, table, buff);
}
buff->append(STRING_WITH_LEN("VIEW "));
- if (!table->compact_view_format)
+ if (!compact_view_name)
{
append_identifier(thd, buff, table->view_db.str, table->view_db.length);
buff->append('.');
@@ -3777,7 +3791,18 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
table->field[4]->store((longlong) count, TRUE);
field->sql_type(type);
table->field[14]->store(type.ptr(), type.length(), cs);
+ /*
+ MySQL column type has the following format:
+ base_type [(dimension)] [unsigned] [zerofill].
+ For DATA_TYPE column we extract only base type.
+ */
tmp_buff= strchr(type.ptr(), '(');
+ if (!tmp_buff)
+ /*
+ if there is no dimention part then check the presence of
+ [unsigned] [zerofill] attributes and cut them of if exist.
+ */
+ tmp_buff= strchr(type.ptr(), ' ');
table->field[7]->store(type.ptr(),
(tmp_buff ? tmp_buff - type.ptr() :
type.length()), cs);
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 34b310931d6..d661505d1a9 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -71,25 +71,22 @@ bool String::realloc(uint32 alloc_length)
char *new_ptr;
if (alloced)
{
- if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
- {
- Ptr=new_ptr;
- Alloced_length=len;
- }
- else
- return TRUE; // Signal error
+ if (!(new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
+ return TRUE; // Signal error
}
else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME))))
{
+ if (str_length > len - 1)
+ str_length= 0;
if (str_length) // Avoid bugs in memcpy on AIX
memcpy(new_ptr,Ptr,str_length);
new_ptr[str_length]=0;
- Ptr=new_ptr;
- Alloced_length=len;
alloced=1;
}
else
return TRUE; // Signal error
+ Ptr= new_ptr;
+ Alloced_length= len;
}
Ptr[alloc_length]=0; // This make other funcs shorter
return FALSE;
@@ -115,7 +112,7 @@ bool String::set_real(double num,uint decimals, CHARSET_INFO *cs)
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
- uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
+ uint32 len= my_sprintf(buff,(buff, "%.15g",num));// Enough for a DATETIME
return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
}
#ifdef HAVE_FCONVERT
@@ -667,7 +664,7 @@ void String::qs_append(const char *str, uint32 len)
void String::qs_append(double d)
{
char *buff = Ptr + str_length;
- str_length+= my_sprintf(buff, (buff, "%.14g", d));
+ str_length+= my_sprintf(buff, (buff, "%.15g", d));
}
void String::qs_append(double *d)
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index e17432e0689..27723f7d1ae 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -3322,7 +3322,7 @@ bool mysql_create_table_no_lock(THD *thd,
if (key->type == Key::FOREIGN_KEY &&
!part_info->is_auto_partitioned)
{
- my_error(ER_CANNOT_ADD_FOREIGN, MYF(0));
+ my_error(ER_FOREIGN_KEY_ON_PARTITIONED, MYF(0));
goto err;
}
}
@@ -4306,7 +4306,14 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
ER_VIEW_CHECKSUM, ER(ER_VIEW_CHECKSUM));
- result_code= HA_ADMIN_CORRUPT;
+ if (thd->main_da.is_error() &&
+ (thd->main_da.sql_errno() == ER_NO_SUCH_TABLE ||
+ thd->main_da.sql_errno() == ER_FILE_NOT_FOUND))
+ /* A missing table is just issued as a failed command */
+ result_code= HA_ADMIN_FAILED;
+ else
+ /* Default failure code is corrupt table */
+ result_code= HA_ADMIN_CORRUPT;
goto send_result;
}
@@ -4648,7 +4655,7 @@ err:
bool mysql_backup_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_backup_table");
- WARN_DEPRECATED(thd, "5.2", "BACKUP TABLE",
+ WARN_DEPRECATED(thd, "6.0", "BACKUP TABLE",
"MySQL Administrator (mysqldump, mysql)");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
"backup", TL_READ, 0, 0, 0, 0,
@@ -4659,7 +4666,7 @@ bool mysql_backup_table(THD* thd, TABLE_LIST* table_list)
bool mysql_restore_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_restore_table");
- WARN_DEPRECATED(thd, "5.2", "RESTORE TABLE",
+ WARN_DEPRECATED(thd, "6.0", "RESTORE TABLE",
"MySQL Administrator (mysqldump, mysql)");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
"restore", TL_WRITE, 1, 1, 0,
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index 816040aa323..58448f82d82 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -564,24 +564,36 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
fill_effective_table_privileges(thd, &view->grant, view->db,
view->table_name);
+ /*
+ Make sure that the current user does not have more column-level privileges
+ on the newly created view than he/she does on the underlying
+ tables. E.g. it must not be so that the user has UPDATE privileges on a
+ view column of he/she doesn't have it on the underlying table's
+ corresponding column. In that case, return an error for CREATE VIEW.
+ */
{
Item *report_item= NULL;
+ /*
+ This will hold the intersection of the priviliges on all columns in the
+ view.
+ */
uint final_priv= VIEW_ANY_ACL;
-
- for (sl= select_lex; sl; sl= sl->next_select())
- {
- DBUG_ASSERT(view->db); /* Must be set in the parser */
- List_iterator_fast<Item> it(sl->item_list);
- Item *item;
- while ((item= it++))
+
+ for (sl= select_lex; sl; sl= sl->next_select())
{
+ DBUG_ASSERT(view->db); /* Must be set in the parser */
+ List_iterator_fast<Item> it(sl->item_list);
+ Item *item;
+ while ((item= it++))
+ {
Item_field *fld= item->filed_for_view_update();
- uint priv= (get_column_grant(thd, &view->grant, view->db,
- view->table_name, item->name) &
- VIEW_ANY_ACL);
+ uint priv= (get_column_grant(thd, &view->grant, view->db,
+ view->table_name, item->name) &
+ VIEW_ANY_ACL);
if (fld && !fld->field->table->s->tmp_table)
- {
+ {
+
final_priv&= fld->have_privileges;
if (~fld->have_privileges & priv)
@@ -589,17 +601,15 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
}
}
}
-
- if (!final_priv)
- {
- DBUG_ASSERT(report_item);
-
- my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
- "create view", thd->security_ctx->priv_user,
+
+ if (!final_priv && report_item)
+ {
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ "create view", thd->security_ctx->priv_user,
thd->security_ctx->priv_host, report_item->name,
- view->table_name);
- res= TRUE;
- goto err;
+ view->table_name);
+ res= TRUE;
+ goto err;
}
}
#endif
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index 920fe7af9fb..ef68a954668 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -4392,7 +4392,7 @@ create_table_option:
| TYPE_SYM opt_equal storage_engines
{
Lex->create_info.db_type= $3;
- WARN_DEPRECATED(yythd, "5.2", "TYPE=storage_engine",
+ WARN_DEPRECATED(yythd, "6.0", "TYPE=storage_engine",
"'ENGINE=storage_engine'");
Lex->create_info.used_fields|= HA_CREATE_USED_ENGINE;
}
@@ -6489,7 +6489,8 @@ select_option:
{
if (check_simple_select())
MYSQL_YYABORT;
- Lex->lock_option= TL_READ_HIGH_PRIORITY;
+ Lex->lock_option= TL_READ_HIGH_PRIORITY;
+ Lex->current_select->lock_option= TL_READ_HIGH_PRIORITY;
}
| DISTINCT { Select->options|= SELECT_DISTINCT; }
| SQL_SMALL_RESULT { Select->options|= SELECT_SMALL_RESULT; }
@@ -6535,6 +6536,7 @@ select_lock_type:
{
LEX *lex=Lex;
lex->current_select->set_lock_for_tables(TL_WRITE);
+ lex->current_select->lock_option= TL_WRITE;
lex->safe_to_cache_query=0;
}
| LOCK_SYM IN_SYM SHARE_SYM MODE_SYM
@@ -6542,6 +6544,7 @@ select_lock_type:
LEX *lex=Lex;
lex->current_select->
set_lock_for_tables(TL_READ_WITH_SHARED_LOCKS);
+ lex->current_select->lock_option= TL_READ_WITH_SHARED_LOCKS;
lex->safe_to_cache_query=0;
}
;
@@ -9261,6 +9264,11 @@ drop:
THD *thd= YYTHD;
LEX *lex= thd->lex;
sp_name *spname;
+ if ($4.str && check_db_name(&$4))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), $4.str);
+ MYSQL_YYABORT;
+ }
if (lex->sphead)
{
my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
@@ -9869,7 +9877,7 @@ show_param:
| opt_full PLUGIN_SYM
{
LEX *lex= Lex;
- WARN_DEPRECATED(yythd, "5.2", "SHOW PLUGIN", "'SHOW PLUGINS'");
+ WARN_DEPRECATED(yythd, "6.0", "SHOW PLUGIN", "'SHOW PLUGINS'");
lex->sql_command= SQLCOM_SHOW_PLUGINS;
if (prepare_schema_table(YYTHD, lex, 0, SCH_PLUGINS))
MYSQL_YYABORT;
@@ -9938,7 +9946,7 @@ show_param:
{
LEX *lex=Lex;
lex->sql_command= SQLCOM_SHOW_STORAGE_ENGINES;
- WARN_DEPRECATED(yythd, "5.2", "SHOW TABLE TYPES", "'SHOW [STORAGE] ENGINES'");
+ WARN_DEPRECATED(yythd, "6.0", "SHOW TABLE TYPES", "'SHOW [STORAGE] ENGINES'");
if (prepare_schema_table(YYTHD, lex, 0, SCH_ENGINES))
MYSQL_YYABORT;
}
@@ -9999,7 +10007,7 @@ show_param:
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB");
MYSQL_YYABORT;
}
- WARN_DEPRECATED(yythd, "5.2", "SHOW INNODB STATUS", "'SHOW ENGINE INNODB STATUS'");
+ WARN_DEPRECATED(yythd, "6.0", "SHOW INNODB STATUS", "'SHOW ENGINE INNODB STATUS'");
}
| MUTEX_SYM STATUS_SYM
{
@@ -10011,7 +10019,7 @@ show_param:
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), "InnoDB");
MYSQL_YYABORT;
}
- WARN_DEPRECATED(yythd, "5.2", "SHOW MUTEX STATUS", "'SHOW ENGINE INNODB MUTEX'");
+ WARN_DEPRECATED(yythd, "6.0", "SHOW MUTEX STATUS", "'SHOW ENGINE INNODB MUTEX'");
}
| opt_full PROCESSLIST_SYM
{ Lex->sql_command= SQLCOM_SHOW_PROCESSLIST;}
@@ -10406,7 +10414,7 @@ load:
| LOAD TABLE_SYM table_ident FROM MASTER_SYM
{
LEX *lex=Lex;
- WARN_DEPRECATED(yythd, "5.2", "LOAD TABLE FROM MASTER",
+ WARN_DEPRECATED(yythd, "6.0", "LOAD TABLE FROM MASTER",
"MySQL Administrator (mysqldump, mysql)");
if (lex->sphead)
{
@@ -10453,7 +10461,7 @@ load_data:
| FROM MASTER_SYM
{
Lex->sql_command = SQLCOM_LOAD_MASTER_DATA;
- WARN_DEPRECATED(yythd, "5.2", "LOAD DATA FROM MASTER",
+ WARN_DEPRECATED(yythd, "6.0", "LOAD DATA FROM MASTER",
"mysqldump or future "
"BACKUP/RESTORE DATABASE facility");
}
@@ -12914,6 +12922,18 @@ subselect_start:
subselect_end:
{
LEX *lex=Lex;
+ /*
+ Set the required lock level for the tables associated with the
+ current sub-select. This will overwrite previous lock options set
+ using st_select_lex::add_table_to_list in any of the following
+ rules: single_multi, table_wild_one, load_data, table_alias_ref,
+ table_factor.
+ The default lock level is TL_READ_DEFAULT but it can be modified
+ with query options specific for a certain (sub-)SELECT.
+ */
+ lex->current_select->
+ set_lock_for_tables(lex->current_select->lock_option);
+
lex->pop_context();
SELECT_LEX *child= lex->current_select;
lex->current_select = lex->current_select->return_after_parsing();
diff --git a/sql/table.cc b/sql/table.cc
index 7437f601c7b..3bb3ff9328b 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -2983,11 +2983,8 @@ void st_table::reset_item_list(List<Item> *item_list) const
void TABLE_LIST::calc_md5(char *buffer)
{
- my_MD5_CTX context;
uchar digest[16];
- my_MD5Init(&context);
- my_MD5Update(&context,(uchar *) select_stmt.str, select_stmt.length);
- my_MD5Final(digest, &context);
+ MY_MD5_HASH(digest, (uchar *) select_stmt.str, select_stmt.length);
sprintf((char *) buffer,
"%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
digest[0], digest[1], digest[2], digest[3],
diff --git a/sql/unireg.cc b/sql/unireg.cc
index eedac2fd582..954f0bc3c7b 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -228,16 +228,16 @@ bool mysql_create_frm(THD *thd, const char *file_name,
create_info->comment.length, 60);
if (tmp_len < create_info->comment.length)
{
- (void) my_snprintf(buff, sizeof(buff), "Too long comment for table '%s'",
- table);
if ((thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
- my_message(ER_UNKNOWN_ERROR, buff, MYF(0));
+ my_error(ER_TOO_LONG_TABLE_COMMENT, MYF(0), table, tmp_len);
goto err;
}
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff);
+ ER_TOO_LONG_TABLE_COMMENT,
+ ER(ER_TOO_LONG_TABLE_COMMENT),
+ table, tmp_len);
create_info->comment.length= tmp_len;
}
@@ -612,17 +612,16 @@ static bool pack_header(uchar *forminfo, enum legacy_db_type table_type,
255);
if (tmp_len < field->comment.length)
{
- char buff[128];
- (void) my_snprintf(buff,sizeof(buff), "Too long comment for field '%s'",
- field->field_name);
if ((current_thd->variables.sql_mode &
(MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)))
{
- my_message(ER_UNKNOWN_ERROR, buff, MYF(0));
+ my_error(ER_TOO_LONG_FIELD_COMMENT, MYF(0), field->field_name, tmp_len);
DBUG_RETURN(1);
}
push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), buff);
+ ER_TOO_LONG_FIELD_COMMENT,
+ ER(ER_TOO_LONG_FIELD_COMMENT),
+ field->field_name, tmp_len);
field->comment.length= tmp_len;
}