From cb6a084076d4688c11936bfa91b03a83570f69e0 Mon Sep 17 00:00:00 2001 From: "jimw@rama.(none)" <> Date: Thu, 17 Aug 2006 12:25:40 -0700 Subject: [PATCH 01/19] Bug #2717: include/my_global.h mis-defines __attribute__ Fix when __attribute__() is stubbed out, add ATTRIBUTE_FORMAT() for specifying __attribute__((format(...))) safely, make more use of the format attribute, and fix some of the warnings that this turns up (plus a bonus unrelated one). --- include/m_ctype.h | 5 +++-- include/m_string.h | 3 ++- include/my_global.h | 22 +++++++++++++++++++++- include/my_sys.h | 4 ++-- sql/item_subselect.cc | 2 +- sql/item_timefunc.cc | 4 ++-- sql/mysql_priv.h | 11 ++++++----- sql/mysqld.cc | 21 +++++++++++---------- sql/opt_range.cc | 7 ++++--- sql/set_var.cc | 12 ++++++------ sql/slave.cc | 2 +- sql/slave.h | 3 ++- sql/sql_acl.cc | 4 ++-- sql/sql_class.h | 2 +- 14 files changed, 64 insertions(+), 38 deletions(-) diff --git a/include/m_ctype.h b/include/m_ctype.h index cd1dac9dde8..b2bf8d3e30f 100644 --- a/include/m_ctype.h +++ b/include/m_ctype.h @@ -175,7 +175,7 @@ typedef struct my_charset_handler_st /* Charset dependant snprintf() */ int (*snprintf)(struct charset_info_st *, char *to, uint n, const char *fmt, - ...); + ...) ATTRIBUTE_FORMAT(printf, 4, 5); int (*long10_to_str)(struct charset_info_st *, char *to, uint n, int radix, long int val); int (*longlong10_to_str)(struct charset_info_st *, char *to, uint n, @@ -300,7 +300,8 @@ int my_wc_mb_8bit(CHARSET_INFO *cs,my_wc_t wc, uchar *s, uchar *e); ulong my_scan_8bit(CHARSET_INFO *cs, const char *b, const char *e, int sq); int my_snprintf_8bit(struct charset_info_st *, char *to, uint n, - const char *fmt, ...); + const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 4, 5); long my_strntol_8bit(CHARSET_INFO *, const char *s, uint l, int base, char **e, int *err); diff --git a/include/m_string.h b/include/m_string.h index d7edff4f626..08408c372b5 100644 --- a/include/m_string.h +++ b/include/m_string.h @@ -247,7 +247,8 @@ extern ulonglong strtoull(const char *str, char **ptr, int base); extern int my_vsnprintf( char *str, size_t n, const char *format, va_list ap ); -extern int my_snprintf(char* to, size_t n, const char* fmt, ...); +extern int my_snprintf(char *to, size_t n, const char *fmt, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); #if defined(__cplusplus) && !defined(OS2) } diff --git a/include/my_global.h b/include/my_global.h index 6baa4558d50..2fbb1db4b77 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -414,14 +414,34 @@ typedef unsigned short ushort; #define function_volatile volatile #define my_reinterpret_cast(A) reinterpret_cast #define my_const_cast(A) const_cast +# ifndef GCC_VERSION +# define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__) +# endif #elif !defined(my_reinterpret_cast) #define my_reinterpret_cast(A) (A) #define my_const_cast(A) (A) #endif -#if !defined(__attribute__) && (defined(__cplusplus) || !defined(__GNUC__) || __GNUC__ == 2 && __GNUC_MINOR__ < 8) + +/* + Disable __attribute__() on GCC < 2.7 and non-GCC compilers +*/ +#if !defined(__attribute__) && (!defined(__GNUC__) || GCC_VERSION < 2007) #define __attribute__(A) #endif +/* + __attribute__((format(...))) is only supported in gcc >= 2.8 and g++ >= 3.4 +*/ +#ifndef ATTRIBUTE_FORMAT +# if defined(__GNUC__) && \ + ((!defined(__cplusplus__) && GCC_VERSION >= 2008) || \ + GCC_VERSION >= 3004) +# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) +# else +# define ATTRIBUTE_FORMAT(style, m, n) +# endif +#endif + /* From old s-system.h */ /* diff --git a/include/my_sys.h b/include/my_sys.h index 02ea188a18e..46e09e8ddf4 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -588,8 +588,8 @@ extern int my_chsize(File fd,my_off_t newlength, int filler, myf MyFlags); extern int my_sync(File fd, myf my_flags); extern int my_error _VARARGS((int nr,myf MyFlags, ...)); extern int my_printf_error _VARARGS((uint my_err, const char *format, - myf MyFlags, ...) - __attribute__ ((format (printf, 2, 4)))); + myf MyFlags, ...)) + ATTRIBUTE_FORMAT(printf, 2, 4); extern int my_message(uint my_err, const char *str,myf MyFlags); extern int my_message_no_curses(uint my_err, const char *str,myf MyFlags); extern int my_message_curses(uint my_err, const char *str,myf MyFlags); diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index c95a91de13e..006153cc51f 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -545,7 +545,7 @@ Item_allany_subselect::Item_allany_subselect(Item * left_exp, chooser_compare_func_creator fc, st_select_lex *select_lex, bool all_arg) - :Item_in_subselect(), all(all_arg), func_creator(fc) + :Item_in_subselect(), func_creator(fc), all(all_arg) { DBUG_ENTER("Item_in_subselect::Item_in_subselect"); left_expr= left_exp; diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc index 44d9b422263..21e27d6c7b4 100644 --- a/sql/item_timefunc.cc +++ b/sql/item_timefunc.cc @@ -65,7 +65,7 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, ltime->hour, ltime->minute, ltime->second); break; case TIME_MICROSECOND: - length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06d", + length= cs->cset->snprintf(cs, buff, length, "%s%02d:%02d:%02d.%06ld", ltime->neg ? "-" : "", ltime->hour, ltime->minute, ltime->second, ltime->second_part); @@ -82,7 +82,7 @@ static bool make_datetime(date_time_format_types format, TIME *ltime, break; case DATE_TIME_MICROSECOND: length= cs->cset->snprintf(cs, buff, length, - "%04d-%02d-%02d %02d:%02d:%02d.%06d", + "%04d-%02d-%02d %02d:%02d:%02d.%06ld", ltime->year, ltime->month, ltime->day, ltime->hour, ltime->minute, ltime->second, ltime->second_part); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 9c5bcc2d53f..76627eaf3ec 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -712,7 +712,8 @@ void mysql_stmt_get_longdata(THD *thd, char *pos, ulong packet_length); MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint code, const char *msg); void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, - uint code, const char *format, ...); + uint code, const char *format, ...) + ATTRIBUTE_FORMAT(printf,4,5); void mysql_reset_errors(THD *thd); my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show); @@ -847,10 +848,10 @@ bool init_errmessage(void); void sql_perror(const char *message); void vprint_msg_to_log(enum loglevel level, const char *format, va_list args); -void sql_print_error(const char *format, ...); -void sql_print_warning(const char *format, ...); -void sql_print_information(const char *format, ...); - +void sql_print_error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); +void sql_print_warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); +void sql_print_information(const char *format, ...) + ATTRIBUTE_FORMAT(printf, 1, 2); bool fn_format_relative_to_data_home(my_string to, const char *name, diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 74c7b1a4e4c..ba0a7d134fa 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -952,8 +952,8 @@ extern "C" sig_handler print_signal_warning(int sig) if (!DBUG_IN_USE) { if (global_system_variables.log_warnings) - sql_print_warning("Got signal %d from thread %d", - sig,my_thread_id()); + sql_print_warning("Got signal %d from thread %ld", + sig, my_thread_id()); } #ifdef DONT_REMEMBER_SIGNAL my_sigset(sig,print_signal_warning); /* int. thread system calls */ @@ -1443,8 +1443,8 @@ static void server_init(void) if (strlen(mysqld_unix_port) > (sizeof(UNIXaddr.sun_path) - 1)) { - sql_print_error("The socket file path is too long (> %d): %s", - sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); + sql_print_error("The socket file path is too long (> %lu): %s", + sizeof(UNIXaddr.sun_path) - 1, mysqld_unix_port); unireg_abort(1); } if ((unix_sock= socket(AF_UNIX, SOCK_STREAM, 0)) < 0) @@ -2786,9 +2786,9 @@ static void openssl_lock(int mode, openssl_lock_t *lock, const char *file, sql_print_error("Fatal: OpenSSL interface problem (mode=0x%x)", mode); abort(); } - if (err) + if (err) { - sql_print_error("Fatal: can't %s OpenSSL %s lock", what); + sql_print_error("Fatal: can't %s OpenSSL lock", what); abort(); } } @@ -6549,14 +6549,15 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), exit(1); } switch (method-1) { - case 0: - method_conv= MI_STATS_METHOD_NULLS_EQUAL; + case 2: + method_conv= MI_STATS_METHOD_IGNORE_NULLS; break; case 1: method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; break; - case 2: - method_conv= MI_STATS_METHOD_IGNORE_NULLS; + case 0: + default: + method_conv= MI_STATS_METHOD_NULLS_EQUAL; break; } global_system_variables.myisam_stats_method= method_conv; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 57903ffe7b9..f5e8a799c4c 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -2513,8 +2513,9 @@ void SEL_ARG::test_use_count(SEL_ARG *root) ulong count=count_key_part_usage(root,pos->next_key_part); if (count > pos->next_key_part->use_count) { - sql_print_information("Use_count: Wrong count for key at %lx, %lu should be %lu", - pos,pos->next_key_part->use_count,count); + sql_print_information("Use_count: Wrong count for key at %lx, %lu " + "should be %lu", (long unsigned int)pos, + pos->next_key_part->use_count, count); return; } pos->next_key_part->test_use_count(root); @@ -2522,7 +2523,7 @@ void SEL_ARG::test_use_count(SEL_ARG *root) } if (e_count != elements) sql_print_warning("Wrong use count: %u (should be %u) for tree at %lx", - e_count, elements, (gptr) this); + e_count, elements, (long unsigned int) this); } #endif diff --git a/sql/set_var.cc b/sql/set_var.cc index 1d994f1c98f..8d6db6bf688 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1150,14 +1150,14 @@ static void fix_net_retry_count(THD *thd, enum_var_type type) thd->net.retry_count=thd->variables.net_retry_count; } #else /* HAVE_REPLICATION */ -static void fix_net_read_timeout(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_read_timeout(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} -static void fix_net_write_timeout(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_write_timeout(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} -static void fix_net_retry_count(THD *thd __attribute__(unused), - enum_var_type type __attribute__(unused)) +static void fix_net_retry_count(THD *thd __attribute__((unused)), + enum_var_type type __attribute__((unused))) {} #endif /* HAVE_REPLICATION */ diff --git a/sql/slave.cc b/sql/slave.cc index b2862a437bb..ff1da2541d4 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -4073,7 +4073,7 @@ static int connect_to_master(THD* thd, MYSQL* mysql, MASTER_INFO* mi, suppress_warnings= 0; sql_print_error("Slave I/O thread: error %s to master \ '%s@%s:%d': \ -Error: '%s' errno: %d retry-time: %d retries: %d", +Error: '%s' errno: %d retry-time: %d retries: %lu", (reconnect ? "reconnecting" : "connecting"), mi->user,mi->host,mi->port, mysql_error(mysql), last_errno, diff --git a/sql/slave.h b/sql/slave.h index f780b7c8473..dccfcf01a8f 100644 --- a/sql/slave.h +++ b/sql/slave.h @@ -551,7 +551,8 @@ const char *rewrite_db(const char* db, uint32 *new_db_len); const char *print_slave_db_safe(const char *db); int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code); void skip_load_data_infile(NET* net); -void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...); +void slave_print_error(RELAY_LOG_INFO *rli, int err_code, const char *msg, ...) + ATTRIBUTE_FORMAT(printf, 3, 4); void end_slave(); /* clean up */ void init_master_info_with_options(MASTER_INFO* mi); diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 734bccb6b46..affab490656 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -426,7 +426,7 @@ static my_bool acl_load(THD *thd, TABLE_LIST *tables) "case that has been forced to lowercase because " "lower_case_table_names is set. It will not be " "possible to remove this privilege using REVOKE.", - db.db, db.user, db.host.hostname, db.host.hostname); + db.db, db.user, db.host.hostname); } } db.sort=get_sort(3,db.host.hostname,db.db,db.user); @@ -2778,7 +2778,7 @@ static my_bool grant_load(TABLE_LIST *tables) sql_print_warning("'tables_priv' entry '%s %s@%s' " "ignored in --skip-name-resolve mode.", mem_check->tname, mem_check->user, - mem_check->host); + mem_check->host.hostname); continue; } } diff --git a/sql/sql_class.h b/sql/sql_class.h index e8fe175cd7c..fe5ceb4c754 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -145,7 +145,7 @@ public: bool no_auto_events_arg, ulong max_size); void new_file(bool need_lock= 1); bool write(THD *thd, enum enum_server_command command, - const char *format,...); + const char *format, ...) ATTRIBUTE_FORMAT(printf, 4, 5); bool write(THD *thd, const char *query, uint query_length, time_t query_start=0); bool write(Log_event* event_info); // binary log write From f25b8f20d21e15be7ca7eb71f3bbbed539924fc1 Mon Sep 17 00:00:00 2001 From: "ramil/ram@mysql.com/myoffice.izhnet.ru" <> Date: Tue, 29 Aug 2006 14:38:02 +0500 Subject: [PATCH 02/19] Fix for bug #21142: Malformed insert causes a segmentation fault. - possible stack overflow fixed. --- client/mysql.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index 09818ae27b3..1a967ed8364 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -2615,7 +2615,7 @@ com_connect(String *buffer, char *line) bzero(buff, sizeof(buff)); if (buffer) { - strmov(buff, line); + strmake(buff, line, sizeof(buff) - 1); tmp= get_arg(buff, 0); if (tmp && *tmp) { @@ -2729,7 +2729,7 @@ com_use(String *buffer __attribute__((unused)), char *line) char *tmp, buff[FN_REFLEN + 1]; bzero(buff, sizeof(buff)); - strmov(buff, line); + strmake(buff, line, sizeof(buff) - 1); tmp= get_arg(buff, 0); if (!tmp || !*tmp) { From 13200c3f9616cc10d1d077799f4d9945693350bc Mon Sep 17 00:00:00 2001 From: "tnurnberg@salvation.intern.azundris.com" <> Date: Mon, 4 Sep 2006 09:13:40 +0200 Subject: [PATCH 03/19] Bug#21913: DATE_FORMAT() Crashes mysql server if I use it through mysql-connector-j driver. Variable character_set_results can legally be NULL (for "no conversion.") This could result in a NULL deref that crashed the server. Fixed. (Although ran some additional precursory tests to see whether I could break anything else, but no breakage so far.) --- mysql-test/r/func_time.result | 12 ++++++++++++ mysql-test/t/func_time.test | 18 ++++++++++++++++++ sql/sql_string.cc | 7 ++++++- 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result index fab0bf01f58..07a46f92469 100644 --- a/mysql-test/r/func_time.result +++ b/mysql-test/r/func_time.result @@ -688,3 +688,15 @@ t1 CREATE TABLE `t1` ( `from_unixtime(1) + 0` double(23,6) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; +SET NAMES latin1; +SET character_set_results = NULL; +SHOW VARIABLES LIKE 'character_set_results'; +Variable_name Value +character_set_results +CREATE TABLE testBug8868 (field1 DATE, field2 VARCHAR(32) CHARACTER SET BINARY); +INSERT INTO testBug8868 VALUES ('2006-09-04', 'abcd'); +SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; +fmtddate field2 +Sep-4 12:00AM abcd +DROP TABLE testBug8868; +SET NAMES DEFAULT; diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test index b232fb14e1e..8a7f8792081 100644 --- a/mysql-test/t/func_time.test +++ b/mysql-test/t/func_time.test @@ -358,4 +358,22 @@ create table t1 select now() - now(), curtime() - curtime(), show create table t1; drop table t1; +# +# 21913: DATE_FORMAT() Crashes mysql server if I use it through +# mysql-connector-j driver. +# + +SET NAMES latin1; +SET character_set_results = NULL; +SHOW VARIABLES LIKE 'character_set_results'; + +CREATE TABLE testBug8868 (field1 DATE, field2 VARCHAR(32) CHARACTER SET BINARY); +INSERT INTO testBug8868 VALUES ('2006-09-04', 'abcd'); + +SELECT DATE_FORMAT(field1,'%b-%e %l:%i%p') as fmtddate, field2 FROM testBug8868; + +DROP TABLE testBug8868; + +SET NAMES DEFAULT; + # End of 4.1 tests diff --git a/sql/sql_string.cc b/sql/sql_string.cc index 939ffe8d9d2..aaa85b0d96c 100644 --- a/sql/sql_string.cc +++ b/sql/sql_string.cc @@ -248,6 +248,10 @@ bool String::copy(const char *str,uint32 arg_length, CHARSET_INFO *cs) 0 No conversion needed 1 Either character set conversion or adding leading zeros (e.g. for UCS-2) must be done + + NOTE + to_cs may be NULL for "no conversion" if the system variable + character_set_results is NULL. */ bool String::needs_conversion(uint32 arg_length, @@ -256,7 +260,8 @@ bool String::needs_conversion(uint32 arg_length, uint32 *offset) { *offset= 0; - if ((to_cs == &my_charset_bin) || + if (!to_cs || + (to_cs == &my_charset_bin) || (to_cs == from_cs) || my_charset_same(from_cs, to_cs) || ((from_cs == &my_charset_bin) && From f4265f7a5741517799b17b493cebffb6bbb86571 Mon Sep 17 00:00:00 2001 From: "tsmith@maint1.mysql.com" <> Date: Thu, 7 Sep 2006 00:01:00 +0200 Subject: [PATCH 04/19] Bug #21250: esolve stack traces on AMD64 (backport to mysql-4.1) --- sql/stacktrace.c | 55 +++++++++++++++++++++++++++++++++++------------- sql/stacktrace.h | 8 +++++-- 2 files changed, 46 insertions(+), 17 deletions(-) diff --git a/sql/stacktrace.c b/sql/stacktrace.c index 838f547dc02..43f35c452f7 100644 --- a/sql/stacktrace.c +++ b/sql/stacktrace.c @@ -21,6 +21,7 @@ #ifdef HAVE_STACKTRACE #include +#include #define PTR_SANE(p) ((p) && (char*)(p) >= heap_start && (char*)(p) <= heap_end) @@ -44,7 +45,29 @@ void safe_print_str(const char* name, const char* val, int max_len) } #ifdef TARGET_OS_LINUX -#define SIGRETURN_FRAME_COUNT 2 + +#ifdef __i386__ +#define SIGRETURN_FRAME_OFFSET 17 +#endif + +#ifdef __x86_64__ +#define SIGRETURN_FRAME_OFFSET 23 +#endif + +static my_bool is_nptl; + +/* Check if we are using NPTL or LinuxThreads on Linux */ +void check_thread_lib(void) +{ + char buf[5]; + +#ifdef _CS_GNU_LIBPTHREAD_VERSION + confstr(_CS_GNU_LIBPTHREAD_VERSION, buf, sizeof(buf)); + is_nptl = !strncasecmp(buf, "NPTL", sizeof(buf)); +#else + is_nptl = 0; +#endif +} #if defined(__alpha__) && defined(__GNUC__) /* @@ -90,7 +113,7 @@ inline uint32* find_prev_pc(uint32* pc, uchar** fp) void print_stacktrace(gptr stack_bottom, ulong thread_stack) { uchar** fp; - uint frame_count = 0; + uint frame_count = 0, sigreturn_frame_count; #if defined(__alpha__) && defined(__GNUC__) uint32* pc; #endif @@ -100,28 +123,27 @@ void print_stacktrace(gptr stack_bottom, ulong thread_stack) Attempting backtrace. You can use the following information to find out\n\ where mysqld died. If you see no messages after this, something went\n\ terribly wrong...\n"); -#ifdef __i386__ +#ifdef __i386__ __asm __volatile__ ("movl %%ebp,%0" :"=r"(fp) :"r"(fp)); - if (!fp) - { - fprintf(stderr, "frame pointer (ebp) is NULL, did you compile with\n\ --fomit-frame-pointer? Aborting backtrace!\n"); - return; - } +#endif +#ifdef __x86_64__ + __asm __volatile__ ("movq %%rbp,%0" + :"=r"(fp) + :"r"(fp)); #endif #if defined(__alpha__) && defined(__GNUC__) __asm __volatile__ ("mov $30,%0" :"=r"(fp) :"r"(fp)); +#endif if (!fp) { - fprintf(stderr, "frame pointer (fp) is NULL, did you compile with\n\ + fprintf(stderr, "frame pointer is NULL, did you compile with\n\ -fomit-frame-pointer? Aborting backtrace!\n"); return; } -#endif /* __alpha__ */ if (!stack_bottom || (gptr) stack_bottom > (gptr) &fp) { @@ -151,13 +173,16 @@ terribly wrong...\n"); :"r"(pc)); #endif /* __alpha__ */ + /* We are 1 frame above signal frame with NPTL and 2 frames above with LT */ + sigreturn_frame_count = is_nptl ? 1 : 2; + while (fp < (uchar**) stack_bottom) { -#ifdef __i386__ +#if defined(__i386__) || defined(__x86_64__) uchar** new_fp = (uchar**)*fp; - fprintf(stderr, "%p\n", frame_count == SIGRETURN_FRAME_COUNT ? - *(fp+17) : *(fp+1)); -#endif /* __386__ */ + fprintf(stderr, "%p\n", frame_count == sigreturn_frame_count ? + *(fp + SIGRETURN_FRAME_OFFSET) : *(fp + 1)); +#endif /* defined(__386__) || defined(__x86_64__) */ #if defined(__alpha__) && defined(__GNUC__) uchar** new_fp = find_prev_fp(pc, fp); diff --git a/sql/stacktrace.h b/sql/stacktrace.h index d5d1e05ef0e..527d10d70a2 100644 --- a/sql/stacktrace.h +++ b/sql/stacktrace.h @@ -19,16 +19,20 @@ extern "C" { #endif #ifdef TARGET_OS_LINUX -#if defined(HAVE_STACKTRACE) || (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) +#if defined(HAVE_STACKTRACE) || (defined (__x86_64__) || defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) #undef HAVE_STACKTRACE #define HAVE_STACKTRACE extern char* __bss_start; extern char* heap_start; -#define init_stacktrace() { heap_start = (char*) &__bss_start; } +#define init_stacktrace() do { \ + heap_start = (char*) &__bss_start; \ + check_thread_lib(); \ + } while(0); void print_stacktrace(gptr stack_bottom, ulong thread_stack); void safe_print_str(const char* name, const char* val, int max_len); +void check_thread_lib(void); #endif /* (defined (__i386__) || (defined(__alpha__) && defined(__GNUC__))) */ #endif /* TARGET_OS_LINUX */ From b6cd727ed1f722ae37f9302196f6f20121bbbb4d Mon Sep 17 00:00:00 2001 From: "tsmith@maint1.mysql.com" <> Date: Thu, 7 Sep 2006 00:11:43 +0200 Subject: [PATCH 05/19] Bug #21054: myisam_stats_method ignored in my.cnf and cmdline Fix OPT_MYISAM_STATS_METHOD case, where the NULLS_EQUAL and NULLS_NOT_EQUAL methods were mixed up --- sql/mysqld.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sql/mysqld.cc b/sql/mysqld.cc index fc3ca5085cf..71a0e35925e 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -6537,10 +6537,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), } switch (method-1) { case 0: - method_conv= MI_STATS_METHOD_NULLS_EQUAL; + method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; break; case 1: - method_conv= MI_STATS_METHOD_NULLS_NOT_EQUAL; + method_conv= MI_STATS_METHOD_NULLS_EQUAL; break; case 2: method_conv= MI_STATS_METHOD_IGNORE_NULLS; From 268c7a352280cf2e2bc334296866b46867777c64 Mon Sep 17 00:00:00 2001 From: "kaa@polly.local" <> Date: Fri, 8 Sep 2006 14:08:29 +0400 Subject: [PATCH 06/19] Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various functions - Honor unsigned_flag in the corresponding functions - Use compare_int_signed_unsigned()/compare_int_unsigned_signed() instead of explicit comparison in GREATEST() and LEAST() --- mysql-test/r/case.result | 6 ++++++ mysql-test/r/func_if.result | 6 ++++++ mysql-test/r/func_test.result | 6 ++++++ mysql-test/r/user_var.result | 4 ++++ mysql-test/t/case.test | 6 ++++++ mysql-test/t/func_if.test | 10 ++++++++++ mysql-test/t/func_test.test | 6 ++++++ mysql-test/t/user_var.test | 6 ++++++ sql/item_cmpfunc.cc | 21 +++++++++----------- sql/item_cmpfunc.h | 14 +++++++++++++ sql/item_func.cc | 37 ++++++++++++++++++++++++++++------- sql/item_func.h | 2 +- sql/sql_class.h | 1 + 13 files changed, 105 insertions(+), 20 deletions(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index a5495d0fc3e..ccac701bfc1 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -177,3 +177,9 @@ from t1 where b=3 group by b; min(a) min(case when 1=1 then a else NULL end) min(case when 1!=1 then NULL else a end) 2 2 2 drop table t1; +SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; +CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END +18446744073709551615 +SELECT COALESCE(18446744073709551615); +COALESCE(18446744073709551615) +18446744073709551615 diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index 2c8f19f1754..e9aa195d175 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -99,3 +99,9 @@ a NULLIF(a,'') NULL NULL NULL DROP TABLE t1; +SELECT IF(1 != 0, 18446744073709551615, 1); +IF(1 != 0, 18446744073709551615, 1) +18446744073709551615 +SELECT IFNULL(NULL, 18446744073709551615); +IFNULL(NULL, 18446744073709551615) +18446744073709551615 diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index 8a28312b348..cc27865cc4c 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -183,3 +183,9 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; 5 mod 3 5 mod -3 -5 mod 3 -5 mod -3 2 2 -2 -2 +SELECT GREATEST(1, 18446744073709551615); +GREATEST(1, 18446744073709551615) +18446744073709551615 +SELECT LEAST(1, 18446744073709551615); +LEAST(1, 18446744073709551615) +1 diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 58b785d1432..dce852e84ae 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -203,3 +203,7 @@ select @@global.version; select @@session.VERSION; @@session.VERSION # +set @a=18446744073709551615; +select @a; +@a +18446744073709551615 diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index fd1b6e5247f..b868ae12b69 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -130,4 +130,10 @@ select min(a), min(case when 1=1 then a else NULL end), from t1 where b=3 group by b; drop table t1; +# +# Bug #20924: UNSIGNED values in CASE and COALESCE are treated as SIGNED +# +SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; +SELECT COALESCE(18446744073709551615); + # End of 4.1 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 5756793c673..17117b07437 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -73,4 +73,14 @@ SELECT a, NULLIF(a,'') FROM t1 WHERE NULLIF(a,'') IS NULL; DROP TABLE t1; +# +# Bug #20924: UNSIGNED values in IF() are treated as SIGNED +# +SELECT IF(1 != 0, 18446744073709551615, 1); + +# +# Bug #20924: UNSIGNED values in IFNULL() are treated as SIGNED +# +SELECT IFNULL(NULL, 18446744073709551615); + # End of 4.1 tests diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index 2ad64b6c5a6..631639c7a74 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -108,4 +108,10 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; +# +# Bug #20924: UNSIGNED values in GREATEST() and LEAST() are treated as SIGNED +# +SELECT GREATEST(1, 18446744073709551615); +SELECT LEAST(1, 18446744073709551615); + # End of 4.1 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 7691a574a2a..810d5e96da5 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -141,4 +141,10 @@ select @@global.version; --replace_column 1 # select @@session.VERSION; +# +# Bug #20924 SET on a user variable saves UNSIGNED as SIGNED +# +set @a=18446744073709551615; +select @a; + # End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index f14efc7187b..cf8d0c39d58 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -619,11 +619,7 @@ int Arg_comparator::compare_int_signed_unsigned() if (!(*b)->null_value) { owner->null_value= 0; - if (sval1 < 0 || (ulonglong)sval1 < uval2) - return -1; - if ((ulonglong)sval1 == uval2) - return 0; - return 1; + return ::compare_int_signed_unsigned(sval1, uval2); } } owner->null_value= 1; @@ -644,13 +640,7 @@ int Arg_comparator::compare_int_unsigned_signed() if (!(*b)->null_value) { owner->null_value= 0; - if (sval2 < 0) - return 1; - if (uval1 < (ulonglong)sval2) - return -1; - if (uval1 == (ulonglong)sval2) - return 0; - return 1; + return ::compare_int_unsigned_signed(uval1, sval2); } } owner->null_value= 1; @@ -1162,11 +1152,13 @@ Item_func_ifnull::val_int() if (!args[0]->null_value) { null_value=0; + unsigned_flag= args[0]->unsigned_flag; return value; } value=args[1]->val_int(); if ((null_value=args[1]->null_value)) return 0; + unsigned_flag= args[1]->unsigned_flag; return value; } @@ -1286,6 +1278,7 @@ Item_func_if::val_int() Item *arg= args[0]->val_int() ? args[1] : args[2]; longlong value=arg->val_int(); null_value=arg->null_value; + unsigned_flag= arg->unsigned_flag; return value; } @@ -1492,6 +1485,7 @@ longlong Item_func_case::val_int() } res=item->val_int(); null_value=item->null_value; + unsigned_flag= item->unsigned_flag; return res; } @@ -1623,7 +1617,10 @@ longlong Item_func_coalesce::val_int() { longlong res=args[i]->val_int(); if (!args[i]->null_value) + { + unsigned_flag= args[i]->unsigned_flag; return res; + } } null_value=1; return 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 73abe208d9e..513260205c2 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1077,3 +1077,17 @@ inline Item *and_conds(Item *a, Item *b) } Item *and_expressions(Item *a, Item *b, Item **org_item); + +inline int compare_int_signed_unsigned(longlong sval, ulonglong uval) +{ + if (sval < 0 || (ulonglong)sval < uval) + return -1; + if ((ulonglong)sval == uval) + return 0; + return 1; +} + +inline int compare_int_unsigned_signed(ulonglong uval, longlong sval) +{ + return -compare_int_signed_unsigned(sval, uval); +} diff --git a/sql/item_func.cc b/sql/item_func.cc index 91ccef6511f..85865ad6fb6 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1235,19 +1235,35 @@ longlong Item_func_min_max::val_int() { DBUG_ASSERT(fixed == 1); longlong value=0; + my_bool arg_unsigned_flag; + my_bool cmp; null_value=1; for (uint i=0; i < arg_count ; i++) { + longlong tmp= args[i]->val_int(); + arg_unsigned_flag= args[i]->unsigned_flag; if (null_value) { - value=args[i]->val_int(); + value= tmp; null_value=args[i]->null_value; + unsigned_flag= arg_unsigned_flag; } else { - longlong tmp=args[i]->val_int(); - if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0) - value=tmp; + if (args[i]->null_value) + continue; + if (unsigned_flag && arg_unsigned_flag || + (!unsigned_flag && !arg_unsigned_flag)) + cmp= tmp < value; + else if (unsigned_flag) + cmp= compare_int_signed_unsigned(tmp, value) < 0; + else + cmp= compare_int_unsigned_signed(tmp, value) < 0; + if ((cmp ? cmp_sign : -cmp_sign) > 0) + { + value= tmp; + unsigned_flag= arg_unsigned_flag; + } } } return value; @@ -2313,6 +2329,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, entry->length=0; entry->update_query_id=0; entry->collation.set(NULL, DERIVATION_IMPLICIT); + entry->unsigned_flag= 0; /* If we are here, we were called from a SET or a query which sets a variable. Imagine it is this: @@ -2390,7 +2407,7 @@ Item_func_set_user_var::fix_length_and_dec() bool Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type, CHARSET_INFO *cs, - Derivation dv) + Derivation dv, bool unsigned_arg) { if ((null_value=args[0]->null_value)) { @@ -2437,6 +2454,7 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length, entry->length= length; entry->type=type; entry->collation.set(cs, dv); + entry->unsigned_flag= unsigned_arg; } return 0; @@ -2507,7 +2525,10 @@ String *user_var_entry::val_str(my_bool *null_value, String *str, str->set(*(double*) value, decimals, &my_charset_bin); break; case INT_RESULT: - str->set(*(longlong*) value, &my_charset_bin); + if (!unsigned_flag) + str->set(*(longlong*) value, &my_charset_bin); + else + str->set(*(ulonglong*) value, &my_charset_bin); break; case STRING_RESULT: if (str->copy(value, length, collation.collation)) @@ -2548,6 +2569,7 @@ Item_func_set_user_var::check() case INT_RESULT: { save_result.vint= args[0]->val_int(); + unsigned_flag= args[0]->unsigned_flag; break; } case STRING_RESULT: @@ -2598,7 +2620,8 @@ Item_func_set_user_var::update() case INT_RESULT: { res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), - INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); + INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, + unsigned_flag); break; } case STRING_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index f4a1258a02c..d9e1396fde6 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -962,7 +962,7 @@ public: longlong val_int(); String *val_str(String *str); bool update_hash(void *ptr, uint length, enum Item_result type, - CHARSET_INFO *cs, Derivation dv); + CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0); bool check(); bool update(); enum Item_result result_type () const { return cached_result_type; } diff --git a/sql/sql_class.h b/sql/sql_class.h index f1cf9c7b3e2..2db0077c0b4 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1460,6 +1460,7 @@ class user_var_entry char *value; ulong length, update_query_id, used_query_id; Item_result type; + bool unsigned_flag; double val(my_bool *null_value); longlong val_int(my_bool *null_value); From c5d70b1a931d06ed143e6067e749885fe9a46618 Mon Sep 17 00:00:00 2001 From: "knielsen@ymer.(none)" <> Date: Mon, 11 Sep 2006 16:49:44 +0200 Subject: [PATCH 07/19] BUG#16282 Build gcc.o as a small library, instead of passing .cpp sources to the linker command (causes problems with parallel make on Solaris). This fix is for 4.1. In 5.0 and up a different fix is used. --- ndb/config/common.mk.am | 2 +- ndb/config/type_ndbapitools.mk.am | 2 +- ndb/src/common/portlib/Makefile.am | 3 ++- ndb/src/kernel/Makefile.am | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) diff --git a/ndb/config/common.mk.am b/ndb/config/common.mk.am index 869e2fae91d..4df1b0e289a 100644 --- a/ndb/config/common.mk.am +++ b/ndb/config/common.mk.am @@ -7,6 +7,6 @@ ndbapiincludedir = "$(pkgincludedir)/ndb/ndbapi" mgmapiincludedir = "$(pkgincludedir)/ndb/mgmapi" INCLUDES = $(INCLUDES_LOC) -LDADD = $(top_srcdir)/ndb/src/common/portlib/gcc.cpp $(LDADD_LOC) +LDADD = $(LDADD_LOC) -L$(top_srcdir)/ndb/src/common/portlib -lmygcc DEFS = @DEFS@ @NDB_DEFS@ $(DEFS_LOC) $(NDB_EXTRA_FLAGS) NDB_CXXFLAGS=@ndb_cxxflags_fix@ $(NDB_CXXFLAGS_LOC) diff --git a/ndb/config/type_ndbapitools.mk.am b/ndb/config/type_ndbapitools.mk.am index d4eb090112d..679dac09f47 100644 --- a/ndb/config/type_ndbapitools.mk.am +++ b/ndb/config/type_ndbapitools.mk.am @@ -3,7 +3,7 @@ LDADD += \ $(top_builddir)/ndb/src/libndbclient.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ - $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ + $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -lmygcc INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \ -I$(top_srcdir)/ndb/include \ diff --git a/ndb/src/common/portlib/Makefile.am b/ndb/src/common/portlib/Makefile.am index 99138a7414e..67b5dbc3001 100644 --- a/ndb/src/common/portlib/Makefile.am +++ b/ndb/src/common/portlib/Makefile.am @@ -1,4 +1,5 @@ -noinst_HEADERS = gcc.cpp +noinst_LIBRARIES = libmygcc.a +libmygcc_a_SOURCES = gcc.cpp noinst_LTLIBRARIES = libportlib.la diff --git a/ndb/src/kernel/Makefile.am b/ndb/src/kernel/Makefile.am index 389cb85c1d8..5b55238c262 100644 --- a/ndb/src/kernel/Makefile.am +++ b/ndb/src/kernel/Makefile.am @@ -53,7 +53,8 @@ LDADD += \ $(top_builddir)/ndb/src/common/util/libgeneral.la \ $(top_builddir)/dbug/libdbug.a \ $(top_builddir)/mysys/libmysys.a \ - $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ + $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@ -lmygcc + # Don't update the files from bitkeeper %::SCCS/s.% From 5df7611caa310a88666f7fd2a7f14bd23ca8e24a Mon Sep 17 00:00:00 2001 From: "kaa@polly.local" <> Date: Tue, 12 Sep 2006 16:25:40 +0400 Subject: [PATCH 08/19] Post-review fixes for bug #20924 --- mysql-test/r/case.result | 1 + mysql-test/r/func_if.result | 1 + mysql-test/r/func_test.result | 1 + mysql-test/r/user_var.result | 1 + mysql-test/t/case.test | 6 ++++-- mysql-test/t/func_if.test | 10 +++++++--- mysql-test/t/func_test.test | 6 ++++-- mysql-test/t/user_var.test | 6 ++++-- sql/item_func.cc | 13 ++++++------- sql/item_func.h | 2 +- sql/log_event.cc | 2 +- 11 files changed, 31 insertions(+), 18 deletions(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index ccac701bfc1..db56fd82f72 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -183,3 +183,4 @@ CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END SELECT COALESCE(18446744073709551615); COALESCE(18446744073709551615) 18446744073709551615 +End of 4.1 tests diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index e9aa195d175..72275039ba7 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -105,3 +105,4 @@ IF(1 != 0, 18446744073709551615, 1) SELECT IFNULL(NULL, 18446744073709551615); IFNULL(NULL, 18446744073709551615) 18446744073709551615 +End of 4.1 tests diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index cc27865cc4c..7c9827a5005 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -189,3 +189,4 @@ GREATEST(1, 18446744073709551615) SELECT LEAST(1, 18446744073709551615); LEAST(1, 18446744073709551615) 1 +End of 4.1 tests diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index dce852e84ae..6797fb0799d 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -207,3 +207,4 @@ set @a=18446744073709551615; select @a; @a 18446744073709551615 +End of 4.1 tests diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index b868ae12b69..d0d503a8821 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -131,9 +131,11 @@ from t1 where b=3 group by b; drop table t1; # -# Bug #20924: UNSIGNED values in CASE and COALESCE are treated as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - UNSIGNED values in CASE and COALESCE are treated as SIGNED # SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; SELECT COALESCE(18446744073709551615); -# End of 4.1 tests +--echo End of 4.1 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 17117b07437..69cfcf7860b 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -74,13 +74,17 @@ SELECT a, NULLIF(a,'') FROM t1 WHERE NULLIF(a,'') IS NULL; DROP TABLE t1; # -# Bug #20924: UNSIGNED values in IF() are treated as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - UNSIGNED values in IF() are treated as SIGNED # SELECT IF(1 != 0, 18446744073709551615, 1); # -# Bug #20924: UNSIGNED values in IFNULL() are treated as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - UNSIGNED values in IFNULL() are treated as SIGNED # SELECT IFNULL(NULL, 18446744073709551615); -# End of 4.1 tests +--echo End of 4.1 tests diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index 631639c7a74..549b0e60246 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -109,9 +109,11 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; # -# Bug #20924: UNSIGNED values in GREATEST() and LEAST() are treated as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - UNSIGNED values in GREATEST() and LEAST() are treated as SIGNED # SELECT GREATEST(1, 18446744073709551615); SELECT LEAST(1, 18446744073709551615); -# End of 4.1 tests +--echo End of 4.1 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index 810d5e96da5..b7c8f962637 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -142,9 +142,11 @@ select @@global.version; select @@session.VERSION; # -# Bug #20924 SET on a user variable saves UNSIGNED as SIGNED +# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various +# functions +# - SET on a user variable saves UNSIGNED as SIGNED # set @a=18446744073709551615; select @a; -# End of 4.1 tests +--echo End of 4.1 tests diff --git a/sql/item_func.cc b/sql/item_func.cc index 85865ad6fb6..d43dadfa4a4 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1252,8 +1252,7 @@ longlong Item_func_min_max::val_int() { if (args[i]->null_value) continue; - if (unsigned_flag && arg_unsigned_flag || - (!unsigned_flag && !arg_unsigned_flag)) + if (unsigned_flag == arg_unsigned_flag) cmp= tmp < value; else if (unsigned_flag) cmp= compare_int_signed_unsigned(tmp, value) < 0; @@ -2614,26 +2613,26 @@ Item_func_set_user_var::update() case REAL_RESULT: { res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), - REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); + REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0); break; } case INT_RESULT: { res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), - INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, - unsigned_flag); + INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, + unsigned_flag); break; } case STRING_RESULT: { if (!save_result.vstr) // Null value res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); else res= update_hash((void*) save_result.vstr->ptr(), save_result.vstr->length(), STRING_RESULT, save_result.vstr->charset(), - DERIVATION_IMPLICIT); + DERIVATION_IMPLICIT, 0); break; } case ROW_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index d9e1396fde6..3a29b9d6f15 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -962,7 +962,7 @@ public: longlong val_int(); String *val_str(String *str); bool update_hash(void *ptr, uint length, enum Item_result type, - CHARSET_INFO *cs, Derivation dv, bool unsigned_arg= 0); + CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); bool check(); bool update(); enum Item_result result_type () const { return cached_result_type; } diff --git a/sql/log_event.cc b/sql/log_event.cc index 19c32b2d28e..ef375a30441 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2607,7 +2607,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) a single record and with a single column. Thus, like a column value, it could always have IMPLICIT derivation. */ - e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT); + e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0); free_root(thd->mem_root,0); rli->inc_event_relay_log_pos(get_event_len()); From 397f0df9ad2df62698d4c1824c965c4b884b990c Mon Sep 17 00:00:00 2001 From: "kaa@polly.local" <> Date: Wed, 13 Sep 2006 14:41:28 +0400 Subject: [PATCH 09/19] Cset exclude: kaa@polly.local|ChangeSet|20060912122540|09861 Cset exclude: kaa@polly.local|ChangeSet|20060908100829|09983 --- mysql-test/r/case.result | 7 ------ mysql-test/r/func_if.result | 7 ------ mysql-test/r/func_test.result | 7 ------ mysql-test/r/user_var.result | 5 ----- mysql-test/t/case.test | 10 +-------- mysql-test/t/func_if.test | 16 +------------ mysql-test/t/func_test.test | 10 +-------- mysql-test/t/user_var.test | 10 +-------- sql/item_cmpfunc.cc | 21 ++++++++++-------- sql/item_cmpfunc.h | 14 ------------ sql/item_func.cc | 42 +++++++++-------------------------- sql/item_func.h | 2 +- sql/log_event.cc | 2 +- sql/sql_class.h | 1 - 14 files changed, 28 insertions(+), 126 deletions(-) diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result index db56fd82f72..a5495d0fc3e 100644 --- a/mysql-test/r/case.result +++ b/mysql-test/r/case.result @@ -177,10 +177,3 @@ from t1 where b=3 group by b; min(a) min(case when 1=1 then a else NULL end) min(case when 1!=1 then NULL else a end) 2 2 2 drop table t1; -SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; -CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END -18446744073709551615 -SELECT COALESCE(18446744073709551615); -COALESCE(18446744073709551615) -18446744073709551615 -End of 4.1 tests diff --git a/mysql-test/r/func_if.result b/mysql-test/r/func_if.result index 72275039ba7..2c8f19f1754 100644 --- a/mysql-test/r/func_if.result +++ b/mysql-test/r/func_if.result @@ -99,10 +99,3 @@ a NULLIF(a,'') NULL NULL NULL DROP TABLE t1; -SELECT IF(1 != 0, 18446744073709551615, 1); -IF(1 != 0, 18446744073709551615, 1) -18446744073709551615 -SELECT IFNULL(NULL, 18446744073709551615); -IFNULL(NULL, 18446744073709551615) -18446744073709551615 -End of 4.1 tests diff --git a/mysql-test/r/func_test.result b/mysql-test/r/func_test.result index 7c9827a5005..8a28312b348 100644 --- a/mysql-test/r/func_test.result +++ b/mysql-test/r/func_test.result @@ -183,10 +183,3 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; 5 mod 3 5 mod -3 -5 mod 3 -5 mod -3 2 2 -2 -2 -SELECT GREATEST(1, 18446744073709551615); -GREATEST(1, 18446744073709551615) -18446744073709551615 -SELECT LEAST(1, 18446744073709551615); -LEAST(1, 18446744073709551615) -1 -End of 4.1 tests diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result index 6797fb0799d..58b785d1432 100644 --- a/mysql-test/r/user_var.result +++ b/mysql-test/r/user_var.result @@ -203,8 +203,3 @@ select @@global.version; select @@session.VERSION; @@session.VERSION # -set @a=18446744073709551615; -select @a; -@a -18446744073709551615 -End of 4.1 tests diff --git a/mysql-test/t/case.test b/mysql-test/t/case.test index d0d503a8821..fd1b6e5247f 100644 --- a/mysql-test/t/case.test +++ b/mysql-test/t/case.test @@ -130,12 +130,4 @@ select min(a), min(case when 1=1 then a else NULL end), from t1 where b=3 group by b; drop table t1; -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - UNSIGNED values in CASE and COALESCE are treated as SIGNED -# -SELECT CASE 1 WHEN 1 THEN 18446744073709551615 ELSE 1 END; -SELECT COALESCE(18446744073709551615); - ---echo End of 4.1 tests +# End of 4.1 tests diff --git a/mysql-test/t/func_if.test b/mysql-test/t/func_if.test index 69cfcf7860b..5756793c673 100644 --- a/mysql-test/t/func_if.test +++ b/mysql-test/t/func_if.test @@ -73,18 +73,4 @@ SELECT a, NULLIF(a,'') FROM t1 WHERE NULLIF(a,'') IS NULL; DROP TABLE t1; -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - UNSIGNED values in IF() are treated as SIGNED -# -SELECT IF(1 != 0, 18446744073709551615, 1); - -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - UNSIGNED values in IFNULL() are treated as SIGNED -# -SELECT IFNULL(NULL, 18446744073709551615); - ---echo End of 4.1 tests +# End of 4.1 tests diff --git a/mysql-test/t/func_test.test b/mysql-test/t/func_test.test index 549b0e60246..2ad64b6c5a6 100644 --- a/mysql-test/t/func_test.test +++ b/mysql-test/t/func_test.test @@ -108,12 +108,4 @@ select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3; select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3; -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - UNSIGNED values in GREATEST() and LEAST() are treated as SIGNED -# -SELECT GREATEST(1, 18446744073709551615); -SELECT LEAST(1, 18446744073709551615); - ---echo End of 4.1 tests +# End of 4.1 tests diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test index b7c8f962637..7691a574a2a 100644 --- a/mysql-test/t/user_var.test +++ b/mysql-test/t/user_var.test @@ -141,12 +141,4 @@ select @@global.version; --replace_column 1 # select @@session.VERSION; -# -# Bug #20924: CAST(expr as UNSIGNED) returns SIGNED value when used in various -# functions -# - SET on a user variable saves UNSIGNED as SIGNED -# -set @a=18446744073709551615; -select @a; - ---echo End of 4.1 tests +# End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index cf8d0c39d58..f14efc7187b 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -619,7 +619,11 @@ int Arg_comparator::compare_int_signed_unsigned() if (!(*b)->null_value) { owner->null_value= 0; - return ::compare_int_signed_unsigned(sval1, uval2); + if (sval1 < 0 || (ulonglong)sval1 < uval2) + return -1; + if ((ulonglong)sval1 == uval2) + return 0; + return 1; } } owner->null_value= 1; @@ -640,7 +644,13 @@ int Arg_comparator::compare_int_unsigned_signed() if (!(*b)->null_value) { owner->null_value= 0; - return ::compare_int_unsigned_signed(uval1, sval2); + if (sval2 < 0) + return 1; + if (uval1 < (ulonglong)sval2) + return -1; + if (uval1 == (ulonglong)sval2) + return 0; + return 1; } } owner->null_value= 1; @@ -1152,13 +1162,11 @@ Item_func_ifnull::val_int() if (!args[0]->null_value) { null_value=0; - unsigned_flag= args[0]->unsigned_flag; return value; } value=args[1]->val_int(); if ((null_value=args[1]->null_value)) return 0; - unsigned_flag= args[1]->unsigned_flag; return value; } @@ -1278,7 +1286,6 @@ Item_func_if::val_int() Item *arg= args[0]->val_int() ? args[1] : args[2]; longlong value=arg->val_int(); null_value=arg->null_value; - unsigned_flag= arg->unsigned_flag; return value; } @@ -1485,7 +1492,6 @@ longlong Item_func_case::val_int() } res=item->val_int(); null_value=item->null_value; - unsigned_flag= item->unsigned_flag; return res; } @@ -1617,10 +1623,7 @@ longlong Item_func_coalesce::val_int() { longlong res=args[i]->val_int(); if (!args[i]->null_value) - { - unsigned_flag= args[i]->unsigned_flag; return res; - } } null_value=1; return 0; diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h index 513260205c2..73abe208d9e 100644 --- a/sql/item_cmpfunc.h +++ b/sql/item_cmpfunc.h @@ -1077,17 +1077,3 @@ inline Item *and_conds(Item *a, Item *b) } Item *and_expressions(Item *a, Item *b, Item **org_item); - -inline int compare_int_signed_unsigned(longlong sval, ulonglong uval) -{ - if (sval < 0 || (ulonglong)sval < uval) - return -1; - if ((ulonglong)sval == uval) - return 0; - return 1; -} - -inline int compare_int_unsigned_signed(ulonglong uval, longlong sval) -{ - return -compare_int_signed_unsigned(sval, uval); -} diff --git a/sql/item_func.cc b/sql/item_func.cc index d43dadfa4a4..91ccef6511f 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -1235,34 +1235,19 @@ longlong Item_func_min_max::val_int() { DBUG_ASSERT(fixed == 1); longlong value=0; - my_bool arg_unsigned_flag; - my_bool cmp; null_value=1; for (uint i=0; i < arg_count ; i++) { - longlong tmp= args[i]->val_int(); - arg_unsigned_flag= args[i]->unsigned_flag; if (null_value) { - value= tmp; + value=args[i]->val_int(); null_value=args[i]->null_value; - unsigned_flag= arg_unsigned_flag; } else { - if (args[i]->null_value) - continue; - if (unsigned_flag == arg_unsigned_flag) - cmp= tmp < value; - else if (unsigned_flag) - cmp= compare_int_signed_unsigned(tmp, value) < 0; - else - cmp= compare_int_unsigned_signed(tmp, value) < 0; - if ((cmp ? cmp_sign : -cmp_sign) > 0) - { - value= tmp; - unsigned_flag= arg_unsigned_flag; - } + longlong tmp=args[i]->val_int(); + if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0) + value=tmp; } } return value; @@ -2328,7 +2313,6 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name, entry->length=0; entry->update_query_id=0; entry->collation.set(NULL, DERIVATION_IMPLICIT); - entry->unsigned_flag= 0; /* If we are here, we were called from a SET or a query which sets a variable. Imagine it is this: @@ -2406,7 +2390,7 @@ Item_func_set_user_var::fix_length_and_dec() bool Item_func_set_user_var::update_hash(void *ptr, uint length, Item_result type, CHARSET_INFO *cs, - Derivation dv, bool unsigned_arg) + Derivation dv) { if ((null_value=args[0]->null_value)) { @@ -2453,7 +2437,6 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length, entry->length= length; entry->type=type; entry->collation.set(cs, dv); - entry->unsigned_flag= unsigned_arg; } return 0; @@ -2524,10 +2507,7 @@ String *user_var_entry::val_str(my_bool *null_value, String *str, str->set(*(double*) value, decimals, &my_charset_bin); break; case INT_RESULT: - if (!unsigned_flag) - str->set(*(longlong*) value, &my_charset_bin); - else - str->set(*(ulonglong*) value, &my_charset_bin); + str->set(*(longlong*) value, &my_charset_bin); break; case STRING_RESULT: if (str->copy(value, length, collation.collation)) @@ -2568,7 +2548,6 @@ Item_func_set_user_var::check() case INT_RESULT: { save_result.vint= args[0]->val_int(); - unsigned_flag= args[0]->unsigned_flag; break; } case STRING_RESULT: @@ -2613,26 +2592,25 @@ Item_func_set_user_var::update() case REAL_RESULT: { res= update_hash((void*) &save_result.vreal,sizeof(save_result.vreal), - REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, 0); + REAL_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); break; } case INT_RESULT: { res= update_hash((void*) &save_result.vint, sizeof(save_result.vint), - INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT, - unsigned_flag); + INT_RESULT, &my_charset_bin, DERIVATION_IMPLICIT); break; } case STRING_RESULT: { if (!save_result.vstr) // Null value res= update_hash((void*) 0, 0, STRING_RESULT, &my_charset_bin, - DERIVATION_IMPLICIT, 0); + DERIVATION_IMPLICIT); else res= update_hash((void*) save_result.vstr->ptr(), save_result.vstr->length(), STRING_RESULT, save_result.vstr->charset(), - DERIVATION_IMPLICIT, 0); + DERIVATION_IMPLICIT); break; } case ROW_RESULT: diff --git a/sql/item_func.h b/sql/item_func.h index 3a29b9d6f15..f4a1258a02c 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -962,7 +962,7 @@ public: longlong val_int(); String *val_str(String *str); bool update_hash(void *ptr, uint length, enum Item_result type, - CHARSET_INFO *cs, Derivation dv, bool unsigned_arg); + CHARSET_INFO *cs, Derivation dv); bool check(); bool update(); enum Item_result result_type () const { return cached_result_type; } diff --git a/sql/log_event.cc b/sql/log_event.cc index ef375a30441..19c32b2d28e 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2607,7 +2607,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli) a single record and with a single column. Thus, like a column value, it could always have IMPLICIT derivation. */ - e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0); + e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT); free_root(thd->mem_root,0); rli->inc_event_relay_log_pos(get_event_len()); diff --git a/sql/sql_class.h b/sql/sql_class.h index 2db0077c0b4..f1cf9c7b3e2 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1460,7 +1460,6 @@ class user_var_entry char *value; ulong length, update_query_id, used_query_id; Item_result type; - bool unsigned_flag; double val(my_bool *null_value); longlong val_int(my_bool *null_value); From 66fa757e1f6a3d9373119ac5437e490ead191411 Mon Sep 17 00:00:00 2001 From: "thek@kpdesk.mysql.com" <> Date: Tue, 19 Sep 2006 12:40:31 +0200 Subject: [PATCH 10/19] Bug#21139 Handling of database differs in "embedded" , test lowercase_fs_off fails - Access checks are omitted when compliled without --with-embedded-privilege-control - Patch: skip this test --- mysql-test/t/lowercase_fs_off.test | 1 + 1 file changed, 1 insertion(+) diff --git a/mysql-test/t/lowercase_fs_off.test b/mysql-test/t/lowercase_fs_off.test index 7f7b573e7ee..883315994fe 100644 --- a/mysql-test/t/lowercase_fs_off.test +++ b/mysql-test/t/lowercase_fs_off.test @@ -3,6 +3,7 @@ # i.e. lower_case_filesystem=OFF # -- source include/have_case_sensitive_file_system.inc +-- source include/not_embedded.inc connect (master,localhost,root,,); connection master; From d3f503a0bd4160dc62998777c6d9013cad5e7efe Mon Sep 17 00:00:00 2001 From: "ramil/ram@mysql.com/myoffice.izhnet.ru" <> Date: Thu, 21 Sep 2006 16:05:01 +0500 Subject: [PATCH 11/19] Fix for bug #20204: "order by" changes the results returned Item_substr's results are improperly stored in a temporary table due to wrongly calculated max_length value for multi-byte charsets if two arguments specified. --- mysql-test/r/ctype_utf8.result | 13 +++++++++++++ mysql-test/t/ctype_utf8.test | 12 ++++++++++++ sql/item_strfunc.cc | 3 ++- 3 files changed, 27 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 941b834a733..22b6de80a35 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1352,3 +1352,16 @@ select database(); database() имя_базы_в_кодировке_утф8_длиной_больше_чем_45 drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use test; +create table t1(a char(10)) default charset utf8; +insert into t1 values ('123'), ('456'); +explain +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE Y ALL NULL NULL NULL NULL 2 Using temporary; Using filesort +1 SIMPLE Z ALL NULL NULL NULL NULL 2 Using where +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +substr(Z.a,-1) a +3 123 +6 456 +drop table t1; diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 7272cb79089..90d7ec1b3a0 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1087,5 +1087,17 @@ create database имя_базы_в_кодировке_утф8_длиной_бо use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; select database(); drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; +use test; + +# +# Bug #20204: "order by" changes the results returned +# + +create table t1(a char(10)) default charset utf8; +insert into t1 values ('123'), ('456'); +explain + select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +select substr(Z.a,-1), Z.a from t1 as Y join t1 as Z on Y.a=Z.a order by 1; +drop table t1; # End of 4.1 tests diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1ef11945bd5..98888226e58 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -1109,12 +1109,13 @@ void Item_func_substr::fix_length_and_dec() } if (arg_count == 3 && args[2]->const_item()) { - int32 length= (int32) args[2]->val_int() * collation.collation->mbmaxlen; + int32 length= (int32) args[2]->val_int(); if (length <= 0) max_length=0; /* purecov: inspected */ else set_if_smaller(max_length,(uint) length); } + max_length*= collation.collation->mbmaxlen; } From 1530b51d8f3b976b18c94e6d04195350c32b39f7 Mon Sep 17 00:00:00 2001 From: "kaa@polly.local" <> Date: Fri, 22 Sep 2006 19:23:58 +0400 Subject: [PATCH 12/19] Fixed bug #22129: A small double precision number becomes zero Better checks for underflow/overflow --- mysql-test/r/type_float.result | 7 ++++ mysql-test/t/type_float.test | 11 +++++- strings/strtod.c | 69 ++++++++++++++++++++++------------ 3 files changed, 61 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result index e8daeb08526..95050163787 100644 --- a/mysql-test/r/type_float.result +++ b/mysql-test/r/type_float.result @@ -272,3 +272,10 @@ desc t3; Field Type Null Key Default Extra a double 0 drop table t1,t2,t3; +select 1e-308, 1.00000001e-300, 100000000e-300; +1e-308 1.00000001e-300 100000000e-300 +0 1.00000001e-300 1e-292 +select 10e307; +10e307 +1e+308 +End of 4.1 tests diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test index 75723d2a0ff..8a484f7bcd0 100644 --- a/mysql-test/t/type_float.test +++ b/mysql-test/t/type_float.test @@ -179,4 +179,13 @@ show warnings; desc t3; drop table t1,t2,t3; -# End of 4.1 tests +# +# Bug #22129: A small double precision number becomes zero +# +# check if underflows are detected correctly +select 1e-308, 1.00000001e-300, 100000000e-300; + +# check if overflows are detected correctly +select 10e307; + +--echo End of 4.1 tests diff --git a/strings/strtod.c b/strings/strtod.c index da1b4f4baa6..3f9a1ac8c52 100644 --- a/strings/strtod.c +++ b/strings/strtod.c @@ -30,7 +30,8 @@ #include #define MAX_DBL_EXP 308 -#define MAX_RESULT_FOR_MAX_EXP 1.79769313486232 +#define MAX_RESULT_FOR_MAX_EXP 1.7976931348623157 +#define MIN_RESULT_FOR_MIN_EXP 2.225073858507202 static double scaler10[] = { 1.0, 1e10, 1e20, 1e30, 1e40, 1e50, 1e60, 1e70, 1e80, 1e90 }; @@ -57,10 +58,11 @@ double my_strtod(const char *str, char **end_ptr, int *error) { double result= 0.0; uint negative= 0, ndigits, dec_digits= 0, neg_exp= 0; - int exp= 0, digits_after_dec_point= 0; + int exp= 0, digits_after_dec_point= 0, tmp_exp; const char *old_str, *end= *end_ptr, *start_of_number; char next_char; my_bool overflow=0; + double scaler= 1.0; *error= 0; if (str >= end) @@ -91,6 +93,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) while ((next_char= *str) >= '0' && next_char <= '9') { result= result*10.0 + (next_char - '0'); + scaler= scaler*10.0; if (++str == end) { next_char= 0; /* Found end of string */ @@ -114,6 +117,7 @@ double my_strtod(const char *str, char **end_ptr, int *error) { result= result*10.0 + (next_char - '0'); digits_after_dec_point++; + scaler= scaler*10.0; if (++str == end) { next_char= 0; @@ -144,39 +148,54 @@ double my_strtod(const char *str, char **end_ptr, int *error) } while (str < end && my_isdigit(&my_charset_latin1, *str)); } } - if ((exp= (neg_exp ? exp + digits_after_dec_point : - exp - digits_after_dec_point))) + tmp_exp= neg_exp ? exp + digits_after_dec_point : exp - digits_after_dec_point; + if (tmp_exp) { - double scaler; + int order; + /* + Check for underflow/overflow. + order is such an integer number that f = C * 10 ^ order, + where f is the resulting floating point number and 1 <= C < 10. + Here we compute the modulus + */ + order= exp + (neg_exp ? -1 : 1) * (ndigits - 1); + if (order < 0) + order= -order; + if (order >= MAX_DBL_EXP && result) + { + double c; + /* Compute modulus of C (see comment above) */ + c= result / scaler * 10.0; + if (neg_exp) + { + if (order > MAX_DBL_EXP || c < MIN_RESULT_FOR_MIN_EXP) + { + result= 0.0; + goto done; + } + } + else + { + if (order > MAX_DBL_EXP || c > MAX_RESULT_FOR_MAX_EXP) + { + overflow= 1; + goto done; + } + } + } + + exp= tmp_exp; if (exp < 0) { exp= -exp; neg_exp= 1; /* neg_exp was 0 before */ } - if (exp + ndigits >= MAX_DBL_EXP + 1 && result) - { - /* - This is not 100 % as we actually will give an owerflow for - 17E307 but not for 1.7E308 but lets cut some corners to make life - simpler - */ - if (exp + ndigits > MAX_DBL_EXP + 1 || - result >= MAX_RESULT_FOR_MAX_EXP) - { - if (neg_exp) - result= 0.0; - else - overflow= 1; - goto done; - } - } - scaler= 1.0; while (exp >= 100) { - scaler*= 1.0e100; + result= neg_exp ? result/1.0e100 : result*1.0e100; exp-= 100; } - scaler*= scaler10[exp/10]*scaler1[exp%10]; + scaler= scaler10[exp/10]*scaler1[exp%10]; if (neg_exp) result/= scaler; else From 5edd58b14c9c7217bfd397f6479202c147c6682c Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Mon, 25 Sep 2006 20:01:39 +0200 Subject: [PATCH 13/19] Bug#18888 Trying to overwrite sql/lex_hash.h during build -Backport fix for bug19738 to 4.1 --- sql/Makefile.am | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sql/Makefile.am b/sql/Makefile.am index 9e512c362a9..43a7617df52 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -26,7 +26,7 @@ INCLUDES = @MT_INCLUDES@ @ZLIB_INCLUDES@ \ WRAPLIBS= @WRAPLIBS@ SUBDIRS = share libexec_PROGRAMS = mysqld -noinst_PROGRAMS = gen_lex_hash +EXTRA_PROGRAMS = gen_lex_hash bin_PROGRAMS = mysql_tzinfo_to_sql gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@ LDADD = @isam_libs@ \ @@ -137,7 +137,11 @@ sql_yacc.o: sql_yacc.cc sql_yacc.h $(HEADERS) @echo "If it fails, re-run configure with --with-low-memory" $(CXXCOMPILE) $(LM_CFLAGS) -c $< -lex_hash.h: gen_lex_hash$(EXEEXT) +# This generates lex_hash.h +# NOTE Built sources should depend on their sources not the tool +# this avoid the rebuild of the built files in a source dist +lex_hash.h: gen_lex_hash.cc lex.h + $(MAKE) $(AM_MAKEFLAGS) gen_lex_hash$(EXEEXT) ./gen_lex_hash$(EXEEXT) > $@ # For testing of udf_example.so; Works on platforms with gcc From f063bee3b264cd6e1f61f190196f1a01780fe410 Mon Sep 17 00:00:00 2001 From: "iggy@rolltop.ignatz42.dyndns.org" <> Date: Thu, 28 Sep 2006 14:30:20 -0400 Subject: [PATCH 14/19] Bug#20305: PROCEDURE ANALYSE() returns wrong M for FLOAT(M, D) and DOUBLE(M, D) --- mysql-test/r/analyse.result | 13 +++++++++++++ mysql-test/t/analyse.test | 14 +++++++++++++- sql/sql_analyse.cc | 8 ++++---- 3 files changed, 30 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result index f8737d8082b..fd1b0a1bb86 100644 --- a/mysql-test/r/analyse.result +++ b/mysql-test/r/analyse.result @@ -134,3 +134,16 @@ test.t1.product Computer TV 2 8 0 0 4.2500 NULL ENUM('Computer','Phone','TV') NO sum(profit) 10 6900 2 4 0 0 1946 2868 ENUM('10','275','600','6900') NOT NULL avg(profit) 10.0000 1380.0000 7 9 0 0 394.6875 570.2003 ENUM('10.0000','68.7500','120.0000','1380.0000') NOT NULL drop table t1,t2; +create table t1 (f1 double(10,5), f2 char(10), f3 double(10,5)); +insert into t1 values (5.999, "5.9999", 5.99999), (9.555, "9.5555", 9.55555); +select f1 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f1 5.99900 9.55500 7 7 0 0 7.77700 1.77800 FLOAT(4,3) NOT NULL +select f2 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f2 5.9999 9.5555 6 6 0 0 6.0000 NULL FLOAT(5,4) UNSIGNED NOT NULL +select f3 from t1 procedure analyse(1, 1); +Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype +test.t1.f3 5.99999 9.55555 7 7 0 0 7.77777 1.77778 FLOAT(6,5) NOT NULL +drop table t1; +End of 4.1 tests diff --git a/mysql-test/t/analyse.test b/mysql-test/t/analyse.test index dfca8f575a4..88fe8dc55e7 100644 --- a/mysql-test/t/analyse.test +++ b/mysql-test/t/analyse.test @@ -82,4 +82,16 @@ create table t2 (country_id int primary key, country char(20) not null); insert into t2 values (1, 'USA'),(2,'India'), (3,'Finland'); select product, sum(profit),avg(profit) from t1 group by product with rollup procedure analyse(); drop table t1,t2; -# End of 4.1 tests + +# +# Bug #20305 PROCEDURE ANALYSE() returns wrong M for FLOAT(M, D) and DOUBLE(M, D) +# + +create table t1 (f1 double(10,5), f2 char(10), f3 double(10,5)); +insert into t1 values (5.999, "5.9999", 5.99999), (9.555, "9.5555", 9.55555); +select f1 from t1 procedure analyse(1, 1); +select f2 from t1 procedure analyse(1, 1); +select f3 from t1 procedure analyse(1, 1); +drop table t1; + +--echo End of 4.1 tests diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc index d2237c24139..3420368a026 100644 --- a/sql/sql_analyse.cc +++ b/sql/sql_analyse.cc @@ -709,9 +709,9 @@ void field_str::get_opt_type(String *answer, ha_rows total_rows) else if (num_info.decimals) // DOUBLE(%d,%d) sometime { if (num_info.dval > -FLT_MAX && num_info.dval < FLT_MAX) - sprintf(buff, "FLOAT(%d,%d)", num_info.integers, num_info.decimals); + sprintf(buff, "FLOAT(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); else - sprintf(buff, "DOUBLE(%d,%d)", num_info.integers, num_info.decimals); + sprintf(buff, "DOUBLE(%d,%d)", (num_info.integers + num_info.decimals), num_info.decimals); } else if (ev_num_info.llval >= -128 && ev_num_info.ullval <= @@ -818,10 +818,10 @@ void field_real::get_opt_type(String *answer, else { if (min_arg >= -FLT_MAX && max_arg <= FLT_MAX) - sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1), + sprintf(buff, "FLOAT(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, max_notzero_dec_len); else - sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1), + sprintf(buff, "DOUBLE(%d,%d)", (int) max_length - (item->decimals + 1) + max_notzero_dec_len, max_notzero_dec_len); answer->append(buff, (uint) strlen(buff)); } From 52d22ad827e298a6dc6c581cc266022eefd475d8 Mon Sep 17 00:00:00 2001 From: "jimw@rama.(none)" <> Date: Fri, 29 Sep 2006 19:28:16 -0700 Subject: [PATCH 15/19] Disable __attribute__ entirely on g++ < 3.4. (Bug #2717) --- include/my_global.h | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) diff --git a/include/my_global.h b/include/my_global.h index 2fbb1db4b77..173f054b306 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -423,23 +423,28 @@ typedef unsigned short ushort; #endif /* - Disable __attribute__() on GCC < 2.7 and non-GCC compilers + Disable __attribute__() on gcc < 2.7, g++ < 3.4, and non-gcc compilers. + Some forms of __attribute__ are actually supported in earlier versions of + g++, but we just disable them all because we only use them to generate + compilation warnings. */ -#if !defined(__attribute__) && (!defined(__GNUC__) || GCC_VERSION < 2007) -#define __attribute__(A) +#ifndef __attribute__ +# if !defined(__GNUC__) +# define __attribute__(A) +# elif GCC_VERSION < 2008 +# define __attribute__(A) +# elif defined(__cplusplus__) && GCC_VERSION < 3004 +# define __attribute__(A) +# endif #endif /* __attribute__((format(...))) is only supported in gcc >= 2.8 and g++ >= 3.4 + But that's already covered by the __attribute__ tests above, so this is + just a convenience macro. */ #ifndef ATTRIBUTE_FORMAT -# if defined(__GNUC__) && \ - ((!defined(__cplusplus__) && GCC_VERSION >= 2008) || \ - GCC_VERSION >= 3004) -# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) -# else -# define ATTRIBUTE_FORMAT(style, m, n) -# endif +# define ATTRIBUTE_FORMAT(style, m, n) __attribute__((format(style, m, n))) #endif /* From old s-system.h */ From 1517d370486b84ba3d3f536c201c2cbb7f5a5b89 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Mon, 2 Oct 2006 13:46:40 +0200 Subject: [PATCH 16/19] Fix __attribute__(A) macro (it formerly used bogus __cplusplus__ symbol) --- include/my_global.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/my_global.h b/include/my_global.h index 173f054b306..a150bb42928 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -433,7 +433,7 @@ typedef unsigned short ushort; # define __attribute__(A) # elif GCC_VERSION < 2008 # define __attribute__(A) -# elif defined(__cplusplus__) && GCC_VERSION < 3004 +# elif defined(__cplusplus) && GCC_VERSION < 3004 # define __attribute__(A) # endif #endif From c3a1980e1683c83ae26e77727a6ba525d71dd2e4 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Mon, 2 Oct 2006 13:47:18 +0200 Subject: [PATCH 17/19] Remove faulty merge causing ctype_utf8 failure --- mysql-test/r/ctype_utf8.result | 12 ------------ mysql-test/t/ctype_utf8.test | 17 ----------------- 2 files changed, 29 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 22b6de80a35..a6eeabb83ef 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,18 +1340,6 @@ select a from t1 group by a; a e drop table t1; -set names utf8; -grant select on test.* to юзер_юзер@localhost; -user() -юзер_юзер@localhost -revoke all on test.* from юзер_юзер@localhost; -drop user юзер_юзер@localhost; -create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -database() -имя_базы_в_кодировке_утф8_длиной_больше_чем_45 -drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; use test; create table t1(a char(10)) default charset utf8; insert into t1 values ('123'), ('456'); diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index cb34d51e3cb..4e2bb6a7d66 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -1073,23 +1073,6 @@ select a from t1 group by a; drop table t1; -# -# Bug#20393: User name truncation in mysql client -# Bug#21432: Database/Table name limited to 64 bytes, not chars, problems with multi-byte -# -set names utf8; -#create user юзер_юзер@localhost; -grant select on test.* to юзер_юзер@localhost; ---exec $MYSQL --default-character-set=utf8 --user=юзер_юзер -e "select user()" -revoke all on test.* from юзер_юзер@localhost; -drop user юзер_юзер@localhost; - -create database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -select database(); -drop database имя_базы_в_кодировке_утф8_длиной_больше_чем_45; -use test; - # # Bug #20204: "order by" changes the results returned # From cb0a874c11a2959e3f88f5a1cbcd1c0fe6807c9b Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Mon, 2 Oct 2006 13:53:10 +0200 Subject: [PATCH 18/19] When compiling with qcc on QNC the define __GNUC__will be set although it doesn't support full GNU syntax - disable __attribute__ when using qcc --- include/my_global.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/include/my_global.h b/include/my_global.h index a150bb42928..d92df6fa743 100644 --- a/include/my_global.h +++ b/include/my_global.h @@ -431,6 +431,9 @@ typedef unsigned short ushort; #ifndef __attribute__ # if !defined(__GNUC__) # define __attribute__(A) +# elif defined (__QNXNTO__) + /* qcc defines GNUC */ +# define __attribute__(A) # elif GCC_VERSION < 2008 # define __attribute__(A) # elif defined(__cplusplus) && GCC_VERSION < 3004 From d5ad8ff4a2e523ad8f9e45bd98a329f33f542266 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Mon, 2 Oct 2006 14:05:36 +0200 Subject: [PATCH 19/19] Remove faulty merge --- mysql-test/r/ctype_utf8.result | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index a6eeabb83ef..2862d6ad650 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1340,7 +1340,6 @@ select a from t1 group by a; a e drop table t1; -use test; create table t1(a char(10)) default charset utf8; insert into t1 values ('123'), ('456'); explain