From a247d3a3b7f0ec777a1b03b95f4a0971d1c8118b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 13 Oct 2005 12:28:43 -0700 Subject: [PATCH 01/69] Fix being able to set default TCP port for command-line utilities by using MYSQL_TCP_PORT variable. (Bug #5792) client/mysql.cc: Set default port to 0 so MYSQL_TCP_PORT is handled by mysql_server_init(). client/mysqladmin.cc: Set default port to 0 so MYSQL_TCP_PORT is handled by mysql_server_init(). client/mysqlbinlog.cc: Set default port to 0 so MYSQL_TCP_PORT is handled by mysql_server_init(). client/mysqlcheck.c: Set default port to 0 so MYSQL_TCP_PORT is handled by mysql_server_init(). client/mysqldump.c: Set default port to 0 so MYSQL_TCP_PORT is handled by mysql_server_init(). client/mysqlimport.c: Set default port to 0 so MYSQL_TCP_PORT is handled by mysql_server_init(). client/mysqlshow.c: Set default port to 0 so MYSQL_TCP_PORT is handled by mysql_server_init(). client/mysqltest.c: Set default port to 0 so MYSQL_TCP_PORT is handled by mysql_server_init(). --- client/mysql.cc | 2 +- client/mysqladmin.cc | 2 +- client/mysqlbinlog.cc | 4 ++-- client/mysqlcheck.c | 2 +- client/mysqldump.c | 2 +- client/mysqlimport.c | 2 +- client/mysqlshow.c | 2 +- client/mysqltest.c | 2 +- 8 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/mysql.cc b/client/mysql.cc index d82d29a9a54..6b1ea869f39 100644 --- a/client/mysql.cc +++ b/client/mysql.cc @@ -610,7 +610,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"prompt", OPT_PROMPT, "Set the mysql prompt to this value.", (gptr*) ¤t_prompt, (gptr*) ¤t_prompt, 0, GET_STR_ALLOC, diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc index da790bce375..dfd279b002f 100644 --- a/client/mysqladmin.cc +++ b/client/mysqladmin.cc @@ -161,7 +161,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &tcp_port, - (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, + (gptr*) &tcp_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"relative", 'r', diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index 802d5081ad6..09e648015a7 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -49,7 +49,7 @@ static const char* database= 0; static my_bool force_opt= 0, short_form= 0, remote_opt= 0; static ulonglong offset = 0; static const char* host = 0; -static int port = MYSQL_PORT; +static int port= 0; static const char* sock= 0; static const char* user = 0; static char* pass = 0; @@ -462,7 +462,7 @@ static struct my_option my_long_options[] = {"password", 'p', "Password to connect to remote server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Use port to connect to the remote server.", - (gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0, + (gptr*) &port, (gptr*) &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"position", 'j', "Deprecated. Use --start-position instead.", (gptr*) &start_position, (gptr*) &start_position, 0, GET_ULL, diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c index 2a2ae1311c9..ccca5aec85e 100644 --- a/client/mysqlcheck.c +++ b/client/mysqlcheck.c @@ -122,7 +122,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqldump.c b/client/mysqldump.c index 3458f74d8a2..ed1c0a7519b 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -322,7 +322,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqlimport.c b/client/mysqlimport.c index ca4acd82db6..a2e408b3982 100644 --- a/client/mysqlimport.c +++ b/client/mysqlimport.c @@ -121,7 +121,7 @@ static struct my_option my_long_options[] = NO_ARG, 0, 0, 0, 0, 0, 0}, #endif {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"protocol", OPT_MYSQL_PROTOCOL, "The protocol of connection (tcp,socket,pipe,memory).", 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, diff --git a/client/mysqlshow.c b/client/mysqlshow.c index 44fc9448782..bc304b2dc11 100644 --- a/client/mysqlshow.c +++ b/client/mysqlshow.c @@ -183,7 +183,7 @@ static struct my_option my_long_options[] = "Password to use when connecting to server. If password is not given it's asked from the tty.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port, - (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, + (gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, #ifdef __WIN__ {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG, diff --git a/client/mysqltest.c b/client/mysqltest.c index 35408368a73..bd8a0a4fe65 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2474,7 +2474,7 @@ static struct my_option my_long_options[] = {"password", 'p', "Password to use when connecting to server.", 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, {"port", 'P', "Port number to use for connection.", (gptr*) &port, - (gptr*) &port, 0, GET_INT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0, 0}, + (gptr*) &port, 0, GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"ps-protocol", OPT_PS_PROTOCOL, "Use prepared statements protocol for communication", (gptr*) &ps_protocol, (gptr*) &ps_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, From 42155a35d1baadf047d80eeb4594c2c15cc17cad Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 28 Oct 2005 18:12:57 -0700 Subject: [PATCH 02/69] Fix bug in handling of decimal fields in UNION statements that could cause a crash or write to an incorrect memory location. (Bug #14216) mysql-test/r/union.result: Update results mysql-test/t/union.test: Add regression test sql/item.cc: Set max_length for decimal fields correctly --- mysql-test/r/union.result | 26 ++++++++++++++++++++++++++ mysql-test/t/union.test | 18 ++++++++++++++++++ sql/item.cc | 7 +++++-- 3 files changed, 49 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 318bfa2cda8..a9b2345d834 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1253,3 +1253,29 @@ id 5 99 drop table t1; +create table t1 (f1 decimal(60,25), f2 decimal(60,25)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +f1 +0.0000000000000000000000000 +0.0000000000000000000000000 +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +description f1 +XXXXXXXXXXXXXXXXXXXX 0.0000000000000000000000000 +YYYYYYYYYYYYYYYYYYYY 0.0000000000000000000000000 +drop table t1; +create table t1 (f1 decimal(60,24), f2 decimal(60,24)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +f1 +0.000000000000000000000000 +0.000000000000000000000000 +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +description f1 +XXXXXXXXXXXXXXXXXXXX 0.000000000000000000000000 +YYYYYYYYYYYYYYYYYYYY 0.000000000000000000000000 +drop table t1; diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index 6a54909536a..1f6fc2c8d3b 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -756,4 +756,22 @@ select 99 union all select id from t1 order by 1; select id from t1 union all select 99 order by 1; drop table t1; +# +# Bug #14216: UNION + DECIMAL wrong values in result +# +create table t1 (f1 decimal(60,25), f2 decimal(60,25)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +drop table t1; +create table t1 (f1 decimal(60,24), f2 decimal(60,24)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +drop table t1; + # End of 4.1 tests diff --git a/sql/item.cc b/sql/item.cc index 642a0ccf1b4..56f0beeeb44 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -3274,8 +3274,11 @@ bool Item_type_holder::join_types(THD *thd, Item *item) { int delta1= max_length_orig - decimals_orig; int delta2= item->max_length - item->decimals; - max_length= min(max(delta1, delta2) + decimals, - (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7); + if (fld_type == MYSQL_TYPE_DECIMAL) + max_length= max(delta1, delta2) + decimals; + else + max_length= min(max(delta1, delta2) + decimals, + (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7); } else max_length= (fld_type == MYSQL_TYPE_FLOAT) ? FLT_DIG+6 : DBL_DIG+7; From 2c4c542ba2a82d42d3109f5257d0323e99bb321d Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 1 Nov 2005 14:58:52 +0100 Subject: [PATCH 03/69] Fixed BUG#14376: MySQL crash on scoped variable (re)initialization Added finer scope control for default clauses of local variable declarations. mysql-test/r/sp.result: New test case for BUG#14376. mysql-test/t/sp.test: New test case for BUG#14376. sql/sp_pcontext.cc: Added boundary variable for local parameters/variables, for better scope control of default values. sql/sp_pcontext.h: Added boundary variable for local parameters/variables, for better scope control of default values. sql/sql_yacc.yy: Make the variables of the current DECLARE "invisible" to its DEFAULT clause. --- mysql-test/r/sp.result | 29 +++++++++++++++++++++++++++ mysql-test/t/sp.test | 45 ++++++++++++++++++++++++++++++++++++++++++ sql/sp_pcontext.cc | 5 +++-- sql/sp_pcontext.h | 16 +++++++++++++++ sql/sql_yacc.yy | 8 +++++++- 5 files changed, 100 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 1f3f7dba7da..1e4d3de5dfa 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3575,4 +3575,33 @@ DROP VIEW bug13095_v1 DROP PROCEDURE IF EXISTS bug13095; DROP VIEW IF EXISTS bug13095_v1; DROP TABLE IF EXISTS bug13095_t1; +drop procedure if exists bug14376| +create procedure bug14376() +begin +declare x int default x; +end| +call bug14376()| +ERROR 42S22: Unknown column 'x' in 'field list' +drop procedure bug14376| +create procedure bug14376() +begin +declare x int default 42; +begin +declare x int default x; +select x; +end; +end| +call bug14376()| +x +42 +drop procedure bug14376| +create procedure bug14376(x int) +begin +declare x int default x; +select x; +end| +call bug14376(4711)| +x +4711 +drop procedure bug14376| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index ab57139bb77..f1b76686c4a 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4489,6 +4489,51 @@ DROP TABLE IF EXISTS bug13095_t1; delimiter |; +# +# BUG#14376: MySQL crash on scoped variable (re)initialization +# +--disable_warnings +drop procedure if exists bug14376| +--enable_warnings + +create procedure bug14376() +begin + declare x int default x; +end| + +# Not the error we want, but that's what we got for now... +--error ER_BAD_FIELD_ERROR +call bug14376()| +drop procedure bug14376| + +create procedure bug14376() +begin + declare x int default 42; + + begin + declare x int default x; + + select x; + end; +end| + +call bug14376()| + +drop procedure bug14376| + +create procedure bug14376(x int) +begin + declare x int default x; + + select x; +end| + +call bug14376(4711)| + +drop procedure bug14376| + + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index f873b676925..cca3e03d69c 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -52,7 +52,7 @@ sp_cond_check(LEX_STRING *sqlstate) sp_pcontext::sp_pcontext(sp_pcontext *prev) : Sql_alloc(), m_psubsize(0), m_csubsize(0), m_hsubsize(0), - m_handlers(0), m_parent(prev) + m_handlers(0), m_parent(prev), m_pboundary(0) { VOID(my_init_dynamic_array(&m_pvar, sizeof(sp_pvar_t *), 16, 8)); VOID(my_init_dynamic_array(&m_cond, sizeof(sp_cond_type_t *), 16, 8)); @@ -150,7 +150,7 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx) sp_pvar_t * sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped) { - uint i= m_pvar.elements; + uint i= m_pboundary; while (i--) { @@ -186,6 +186,7 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type, p->offset= current_pvars(); p->dflt= NULL; insert_dynamic(&m_pvar, (gptr)&p); + m_pboundary= m_pvar.elements; } } diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index bd2259cb6fb..fbeac37c058 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -164,6 +164,7 @@ class sp_pcontext : public Sql_alloc { while (num--) pop_dynamic(&m_pvar); + m_pboundary= m_pvar.elements; } // Find by name @@ -183,6 +184,14 @@ class sp_pcontext : public Sql_alloc return p; } + // Set the current scope boundary (for default values) + // The argument is the number of variables to skip. + inline void + declare_var_boundary(uint n) + { + m_pboundary= m_pvar.elements-n; + } + // // Labels // @@ -287,6 +296,13 @@ private: uint m_poffset; // Variable offset for this context uint m_coffset; // Cursor offset for this context + /* + Boundary for finding variables in this in this context. + This is normally the same as m_pvar.elements, but differs during + parsing of DECLARE ... DEFAULT, to get the scope right for DEFAULT + values. + */ + uint m_pboundary; DYNAMIC_ARRAY m_pvar; // Parameters/variables DYNAMIC_ARRAY m_cond; // Conditions diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 109dcd7e86a..c3c53b2f611 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1660,7 +1660,12 @@ sp_decls: sp_decl: DECLARE_SYM sp_decl_idents type - { Lex->sphead->reset_lex(YYTHD); } + { + LEX *lex= Lex; + + lex->sphead->reset_lex(YYTHD); + lex->spcont->declare_var_boundary($2); + } sp_opt_default { LEX *lex= Lex; @@ -1690,6 +1695,7 @@ sp_decl: lex->sphead->add_instr(in); ctx->set_default(i, it); } + ctx->declare_var_boundary(0); lex->sphead->restore_lex(YYTHD); $$.vars= $2; $$.conds= $$.hndlrs= $$.curs= 0; From 85cc43802bee44bcf02b459812ac8d77aa83a85f Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Nov 2005 12:34:19 +0400 Subject: [PATCH 04/69] Bug#14146 CHAR(...USING ...) and CONVERT(CHAR(...) USING...) produce different results ctype_utf8.result, ctype_utf8.test: Adding test case. item_strfunc.cc: item_strfunc.h: Moving the well formed checking code into a method, to reuse in several Item_func_xxx. Reusing the new method in Item_func_char and Item_func_charset_conv. sql/item_strfunc.h: Bug#14146 CHAR(...USING ...) and CONVERT(CHAR(...) USING...) produce different results Moving the well formed checking code into a method, to reuse in several Item_func_xxx. sql/item_strfunc.cc: Moving the well formed checking code into a method, to reuse in several Item_func_xxx. mysql-test/t/ctype_utf8.test: Adding test case. mysql-test/r/ctype_utf8.result: Adding test case. --- mysql-test/r/ctype_utf8.result | 10 ++++++ mysql-test/t/ctype_utf8.test | 6 +++- sql/item_strfunc.cc | 63 ++++++++++++++++++---------------- sql/item_strfunc.h | 1 + 4 files changed, 50 insertions(+), 30 deletions(-) diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result index 874983daff2..c57b06f4895 100644 --- a/mysql-test/r/ctype_utf8.result +++ b/mysql-test/r/ctype_utf8.result @@ -1095,6 +1095,11 @@ char(0xff,0x8f using utf8) Ъ▐ Warnings: Warning 1300 Invalid utf8 character string: 'FF8F' +select convert(char(0xff,0x8f) using utf8); +convert(char(0xff,0x8f) using utf8) +Ъ▐ +Warnings: +Warning 1300 Invalid utf8 character string: 'FF8F' set sql_mode=traditional; select char(0xff,0x8f using utf8); char(0xff,0x8f using utf8) @@ -1116,6 +1121,11 @@ char(2557 using utf8) NULL Warnings: Error 1300 Invalid utf8 character string: 'FD' +select convert(char(0xff,0x8f) using utf8); +convert(char(0xff,0x8f) using utf8) +NULL +Warnings: +Error 1300 Invalid utf8 character string: 'FF8F' select hex(convert(char(2557 using latin1) using utf8)); hex(convert(char(2557 using latin1) using utf8)) 09C3BD diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test index 5670e9efbf9..a96564f4e76 100644 --- a/mysql-test/t/ctype_utf8.test +++ b/mysql-test/t/ctype_utf8.test @@ -884,7 +884,9 @@ SELECT DISTINCT id FROM t1 ORDER BY id; DROP TABLE t1; # -# Bugs#10504: Character set does not support traditional mode +# Bug#10504: Character set does not support traditional mode +# Bug#14146: CHAR(...USING ...) and CONVERT(CHAR(...) USING...) +# produce different results # set names utf8; # correct value @@ -894,12 +896,14 @@ select char(0xd18f using utf8); select char(53647 using utf8); # incorrect value: return with warning select char(0xff,0x8f using utf8); +select convert(char(0xff,0x8f) using utf8); # incorrect value in strict mode: return NULL with "Error" level warning set sql_mode=traditional; select char(0xff,0x8f using utf8); select char(195 using utf8); select char(196 using utf8); select char(2557 using utf8); +select convert(char(0xff,0x8f) using utf8); # # Check convert + char + using diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 1e8fe2e695f..b4cdacd4bc0 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -48,6 +48,38 @@ static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, } +String *Item_str_func::check_well_formed_result(String *str) +{ + /* Check whether we got a well-formed string */ + CHARSET_INFO *cs= str->charset(); + int well_formed_error; + uint wlen= cs->cset->well_formed_len(cs, + str->ptr(), str->ptr() + str->length(), + str->length(), &well_formed_error); + if (wlen < str->length()) + { + THD *thd= current_thd; + char hexbuf[7]; + enum MYSQL_ERROR::enum_warning_level level; + uint diff= str->length() - wlen; + set_if_smaller(diff, 3); + octet2hex(hexbuf, str->ptr() + wlen, diff); + if (thd->variables.sql_mode & + (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) + { + level= MYSQL_ERROR::WARN_LEVEL_ERROR; + null_value= 1; + str= 0; + } + else + level= MYSQL_ERROR::WARN_LEVEL_WARN; + push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, + ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); + } + return str; +} + + double Item_str_func::val_real() { DBUG_ASSERT(fixed == 1); @@ -1984,34 +2016,7 @@ String *Item_func_char::val_str(String *str) } str->set_charset(collation.collation); str->realloc(str->length()); // Add end 0 (for Purify) - - /* Check whether we got a well-formed string */ - CHARSET_INFO *cs= collation.collation; - int well_formed_error; - uint wlen= cs->cset->well_formed_len(cs, - str->ptr(), str->ptr() + str->length(), - str->length(), &well_formed_error); - if (wlen < str->length()) - { - THD *thd= current_thd; - char hexbuf[7]; - enum MYSQL_ERROR::enum_warning_level level; - uint diff= str->length() - wlen; - set_if_smaller(diff, 3); - octet2hex(hexbuf, str->ptr() + wlen, diff); - if (thd->variables.sql_mode & - (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES)) - { - level= MYSQL_ERROR::WARN_LEVEL_ERROR; - null_value= 1; - str= 0; - } - else - level= MYSQL_ERROR::WARN_LEVEL_WARN; - push_warning_printf(thd, level, ER_INVALID_CHARACTER_STRING, - ER(ER_INVALID_CHARACTER_STRING), cs->csname, hexbuf); - } - return str; + return check_well_formed_result(str); } @@ -2320,7 +2325,7 @@ String *Item_func_conv_charset::val_str(String *str) } null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(), conv_charset, &dummy_errors); - return null_value ? 0 : &str_value; + return null_value ? 0 : check_well_formed_result(&str_value); } void Item_func_conv_charset::fix_length_and_dec() diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 5889821293d..d196fac87e8 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -35,6 +35,7 @@ public: double val_real(); enum Item_result result_type () const { return STRING_RESULT; } void left_right_max_length(); + String *check_well_formed_result(String *str); }; class Item_func_md5 :public Item_str_func From 73e4a7788679effd0908e1d27ad15c52f5cbaca3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 7 Nov 2005 14:59:52 -0800 Subject: [PATCH 05/69] Fix handling of comparisons done by IN() to be consistent with how they are done for the = operator, such as when doing a comparison with a large unsigned number that was quoted. (Bug #12612) mysql-test/r/func_equal.result: Add new results mysql-test/t/func_equal.test: Add new test sql/item_cmpfunc.cc: Handle FIELD_ITEM that can be compared as a longlong in agg_cmp_type() instead of in each of the places it is called. --- mysql-test/r/func_equal.result | 9 ++++++ mysql-test/t/func_equal.test | 9 ++++++ sql/item_cmpfunc.cc | 58 +++++++++++++++++++--------------- 3 files changed, 50 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/func_equal.result b/mysql-test/r/func_equal.result index 352b76f2744..98838c80861 100644 --- a/mysql-test/r/func_equal.result +++ b/mysql-test/r/func_equal.result @@ -27,3 +27,12 @@ id value select * from t1 where id <=> value or value<=>id; id value drop table t1,t2; +create table t1 (a bigint unsigned); +insert into t1 values (4828532208463511553); +select * from t1 where a = '4828532208463511553'; +a +4828532208463511553 +select * from t1 where a in ('4828532208463511553'); +a +4828532208463511553 +drop table t1; diff --git a/mysql-test/t/func_equal.test b/mysql-test/t/func_equal.test index 18d34e3ba16..382bde43647 100644 --- a/mysql-test/t/func_equal.test +++ b/mysql-test/t/func_equal.test @@ -32,4 +32,13 @@ select * from t1 where value <=> value; select * from t1 where id <=> value or value<=>id; drop table t1,t2; +# +# Bug #12612: quoted bigint unsigned value and the use of "in" in where clause +# +create table t1 (a bigint unsigned); +insert into t1 values (4828532208463511553); +select * from t1 where a = '4828532208463511553'; +select * from t1 where a in ('4828532208463511553'); +drop table t1; + # End of 4.1 tests diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2c76c7ec7b3..646de534348 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -25,6 +25,8 @@ #include #include "sql_select.h" +static bool convert_constant_item(THD *thd, Field *field, Item **item); + static Item_result item_store_type(Item_result a,Item_result b) { if (a == STRING_RESULT || b == STRING_RESULT) @@ -43,14 +45,37 @@ static void agg_result_type(Item_result *type, Item **items, uint nitems) type[0]= item_store_type(type[0], items[i]->result_type()); } -static void agg_cmp_type(Item_result *type, Item **items, uint nitems) + +static void agg_cmp_type(THD *thd, Item_result *type, Item **items, uint nitems) { uint i; + Field *field= NULL; + bool all_constant= TRUE; + + /* If the first argument is a FIELD_ITEM, pull out the field. */ + if (items[0]->type() == Item::FIELD_ITEM) + field=((Item_field *)items[0])->field; + /* But if it can't be compared as a longlong, we don't really care. */ + if (field && !field->can_be_compared_as_longlong()) + field= NULL; + type[0]= items[0]->result_type(); - for (i=1 ; i < nitems ; i++) + for (i= 1; i < nitems; i++) + { type[0]= item_cmp_type(type[0], items[i]->result_type()); + if (field && !convert_constant_item(thd, field, &items[i])) + all_constant= FALSE; + } + + /* + If we had a field that can be compared as a longlong, and all constant + items, then the aggregate result will be an INT_RESULT. + */ + if (field && all_constant) + type[0]= INT_RESULT; } + static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname) { @@ -881,31 +906,11 @@ void Item_func_between::fix_length_and_dec() */ if (!args[0] || !args[1] || !args[2]) return; - agg_cmp_type(&cmp_type, args, 3); + agg_cmp_type(thd, &cmp_type, args, 3); + if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV)) return; - - /* - Make a special case of compare with date/time and longlong fields. - They are compared as integers, so for const item this time-consuming - conversion can be done only once, not for every single comparison - */ - if (args[0]->type() == FIELD_ITEM) - { - Field *field=((Item_field*) args[0])->field; - if (field->can_be_compared_as_longlong()) - { - /* - The following can't be recoded with || as convert_constant_item - changes the argument - */ - if (convert_constant_item(thd, field,&args[1])) - cmp_type=INT_RESULT; // Works for all types. - if (convert_constant_item(thd, field,&args[2])) - cmp_type=INT_RESULT; // Works for all types. - } - } } @@ -1400,6 +1405,7 @@ void Item_func_case::fix_length_and_dec() { Item **agg; uint nagg; + THD *thd= current_thd; if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1)))) return; @@ -1429,7 +1435,7 @@ void Item_func_case::fix_length_and_dec() for (nagg= 0; nagg < ncases/2 ; nagg++) agg[nagg+1]= args[nagg*2]; nagg++; - agg_cmp_type(&cmp_type, agg, nagg); + agg_cmp_type(thd, &cmp_type, agg, nagg); if ((cmp_type == STRING_RESULT) && agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV)) return; @@ -1910,7 +1916,7 @@ void Item_func_in::fix_length_and_dec() uint const_itm= 1; THD *thd= current_thd; - agg_cmp_type(&cmp_type, args, arg_count); + agg_cmp_type(thd, &cmp_type, args, arg_count); if (cmp_type == STRING_RESULT && agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV)) From 850cfe786a39c6088be8647cc8d2b35c765841aa Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 8 Nov 2005 14:47:33 +0100 Subject: [PATCH 06/69] Fixed BUG#14643: Stored Procedure: Continuing after failed var. initialization crashes server. Make sure variables are initialized to something (like null) when the default initialization fails and a continue handler is in effect. mysql-test/r/sp.result: New test case for BUG#14643. mysql-test/t/sp.test: New test case for BUG#14643. sql/sp_head.cc: Make sure variables are initialized to something (like null) when the default initialization fails and a continue handler is in effect. If this also fails (out of memory), we have to abort without letting the handler catch. --- mysql-test/r/sp.result | 36 ++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 44 ++++++++++++++++++++++++++++++++++++++++++ sql/sp_head.cc | 20 +++++++++++++++++++ 3 files changed, 100 insertions(+) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index d50e6dd3751..ab80545590c 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3617,4 +3617,40 @@ count(*) drop table t3, t4| drop procedure bug14210| set @@session.max_heap_table_size=default| +drop procedure if exists bug14643_1| +drop procedure if exists bug14643_2| +create procedure bug14643_1() +begin +declare continue handler for sqlexception select 'boo' as 'Handler'; +begin +declare v int default x; +if v = 1 then +select 1; +else +select 2; +end if; +end; +end| +create procedure bug14643_2() +begin +declare continue handler for sqlexception select 'boo' as 'Handler'; +case x +when 1 then +select 1; +else +select 2; +end case; +end| +call bug14643_1()| +Handler +boo +2 +2 +call bug14643_2()| +Handler +boo +2 +2 +drop procedure bug14643_1| +drop procedure bug14643_2| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index eaf69c0ab03..edfa09c0e7c 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4541,6 +4541,50 @@ drop table t3, t4| drop procedure bug14210| set @@session.max_heap_table_size=default| + +# +# BUG#14643: Stored Procedure: Continuing after failed var. initialization +# crashes server. +# +--disable_warnings +drop procedure if exists bug14643_1| +drop procedure if exists bug14643_2| +--enable_warnings + +create procedure bug14643_1() +begin + declare continue handler for sqlexception select 'boo' as 'Handler'; + + begin + declare v int default x; + + if v = 1 then + select 1; + else + select 2; + end if; + end; +end| + +create procedure bug14643_2() +begin + declare continue handler for sqlexception select 'boo' as 'Handler'; + + case x + when 1 then + select 1; + else + select 2; + end case; +end| + +call bug14643_1()| +call bug14643_2()| + +drop procedure bug14643_1| +drop procedure bug14643_2| + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sp_head.cc b/sql/sp_head.cc index abc66ce0b21..8d6ce3336f2 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -2031,6 +2031,26 @@ sp_instr_set::exec_core(THD *thd, uint *nextp) { int res= thd->spcont->set_item_eval(thd, m_offset, &m_value, m_type); + if (res < 0 && + thd->spcont->get_item(m_offset) == NULL && + thd->spcont->found_handler_here()) + { + /* + Failed to evaluate the value, the variable is still not initialized, + and a handler has been found. Set to null so we can continue. + */ + Item *it= new Item_null(); + + if (!it || thd->spcont->set_item_eval(thd, m_offset, &it, m_type) < 0) + { /* If this also failed, we have to abort */ + sp_rcontext *spcont= thd->spcont; + + thd->spcont= 0; /* Avoid handlers */ + my_error(ER_OUT_OF_RESOURCES, MYF(0)); + spcont->clear_handler(); + thd->spcont= spcont; + } + } *nextp = m_ip+1; return res; } From 388dc4c3f8c89b817f612dff3ce0d52ecb9dd7b7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 10 Nov 2005 17:05:36 -0800 Subject: [PATCH 07/69] Don't try to mysqlhotcopy the INFORMATION_SCHEMA database. (Bug #14610) scripts/mysqlhotcopy.sh: Skip INFORMATION_SCHEMA when matching database names against regex. --- scripts/mysqlhotcopy.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/mysqlhotcopy.sh b/scripts/mysqlhotcopy.sh index 1c5cd6a4faf..bf53aa78e15 100644 --- a/scripts/mysqlhotcopy.sh +++ b/scripts/mysqlhotcopy.sh @@ -252,6 +252,7 @@ if ( defined $opt{regexp} ) { my $sth_dbs = $dbh->prepare("show databases"); $sth_dbs->execute; while ( my ($db_name) = $sth_dbs->fetchrow_array ) { + next if $db_name =~ m/^information_schema$/i; push @db_desc, { 'src' => $db_name, 't_regex' => $t_regex } if ( $db_name =~ m/$opt{regexp}/o ); } } From a2e5a9f9235b6cbb851c5cf357bb34113d25e030 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 14 Nov 2005 16:36:06 +0400 Subject: [PATCH 08/69] Bug#14406 GRANTS ON objects with non-ascii names borked after FLUSH PRIVILEGES ps_grant.result: Fixing result order. grant.result: Adding test case, fixing result order. grant.test: Adding test case. sql_acl.cc: Fixed that my_charset_latin1 was incorrectly used instead of system_charset_info. This problem was previously fixed by Ingo in 5.0. This patch is basically a backport of the same changes into 4.1. sql/sql_acl.cc: Bug#14406 GRANTS ON objects with non-ascii names borked after FLUSH PRIVILEGES Fixed that my_charset_latin1 was incorrectly used instead of system_charset_info. This problem was previously fixed by Ingo in 5.0. This patch is basically a backport of the same changes into 4.1. mysql-test/t/grant.test: Adding test case. mysql-test/r/grant.result: Adding test case, fixing result order. mysql-test/r/ps_grant.result: Fixing result order. --- mysql-test/r/grant.result | 27 ++++++++-- mysql-test/r/ps_grant.result | 6 +-- mysql-test/t/grant.test | 12 +++++ sql/sql_acl.cc | 95 ++++++++++++++++++------------------ 4 files changed, 87 insertions(+), 53 deletions(-) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index a50293752ec..0a406c1ffc2 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -351,10 +351,10 @@ GRANT USAGE ON *.* TO 'grant_user'@'localhost' GRANT INSERT (a, d, c, b) ON `test`.`t1` TO 'grant_user'@'localhost' select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv; Host Db User Table_name Column_name Column_priv -localhost test grant_user t1 c Insert localhost test grant_user t1 b Insert -localhost test grant_user t1 a Insert localhost test grant_user t1 d Insert +localhost test grant_user t1 a Insert +localhost test grant_user t1 c Insert revoke ALL PRIVILEGES on t1 from grant_user@localhost; show grants for grant_user@localhost; Grants for grant_user@localhost @@ -377,9 +377,9 @@ show grants for mysqltest_3@localhost; Grants for mysqltest_3@localhost GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost' GRANT SELECT (b) ON `mysqltest_1`.`t2` TO 'mysqltest_3'@'localhost' -GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost' GRANT UPDATE (a) ON `mysqltest_1`.`t1` TO 'mysqltest_3'@'localhost' GRANT UPDATE (d) ON `mysqltest_2`.`t2` TO 'mysqltest_3'@'localhost' +GRANT SELECT (c) ON `mysqltest_2`.`t1` TO 'mysqltest_3'@'localhost' update mysqltest_1.t1, mysqltest_1.t2 set q=10 where b=1; ERROR 42000: UPDATE command denied to user 'mysqltest_3'@'localhost' for column 'q' in table 't1' update mysqltest_1.t1, mysqltest_2.t2 set d=20 where d=1; @@ -443,3 +443,24 @@ flush privileges; set @user123="non-existent"; select * from mysql.db where user=@user123; Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv +set names koi8r; +create database бд; +grant select on бд.* to root@localhost; +select hex(Db) from mysql.db where Db='бд'; +hex(Db) +D0B1D0B4 +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT SELECT ON `бд`.* TO 'root'@'localhost' +flush privileges; +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT SELECT ON `бд`.* TO 'root'@'localhost' +drop database бд; +revoke all privileges on бд.* from root@localhost; +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +set names latin1; diff --git a/mysql-test/r/ps_grant.result b/mysql-test/r/ps_grant.result index f883bef8591..1d66bad7eb7 100644 --- a/mysql-test/r/ps_grant.result +++ b/mysql-test/r/ps_grant.result @@ -32,19 +32,19 @@ identified by 'looser' ; show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' drop table mysqltest.t9 ; show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' show grants for second_user@localhost ; Grants for second_user@localhost GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3' -GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost' +GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost' prepare s_t1 from 'select a as my_col from t1' ; execute s_t1 ; my_col diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test index b0de62e679c..039e41dcf34 100644 --- a/mysql-test/t/grant.test +++ b/mysql-test/t/grant.test @@ -409,4 +409,16 @@ flush privileges; set @user123="non-existent"; select * from mysql.db where user=@user123; +set names koi8r; +create database бд; +grant select on бд.* to root@localhost; +select hex(Db) from mysql.db where Db='бд'; +show grants for root@localhost; +flush privileges; +show grants for root@localhost; +drop database бд; +revoke all privileges on бд.* from root@localhost; +show grants for root@localhost; +set names latin1; + # End of 4.1 tests diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc index 47c6343bc3b..1ade6ce3064 100644 --- a/sql/sql_acl.cc +++ b/sql/sql_acl.cc @@ -903,7 +903,7 @@ static void acl_update_user(const char *user, const char *host, { if (!acl_user->host.hostname && !host[0] || acl_user->host.hostname && - !my_strcasecmp(&my_charset_latin1, host, acl_user->host.hostname)) + !my_strcasecmp(system_charset_info, host, acl_user->host.hostname)) { acl_user->access=privileges; if (mqh->bits & 1) @@ -982,7 +982,7 @@ static void acl_update_db(const char *user, const char *host, const char *db, { if (!acl_db->host.hostname && !host[0] || acl_db->host.hostname && - !my_strcasecmp(&my_charset_latin1, host, acl_db->host.hostname)) + !my_strcasecmp(system_charset_info, host, acl_db->host.hostname)) { if (!acl_db->db && !db[0] || acl_db->db && !strcmp(db,acl_db->db)) @@ -1128,7 +1128,7 @@ static void init_check_host(void) DBUG_ENTER("init_check_host"); VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip), acl_users.elements,1)); - VOID(hash_init(&acl_check_hosts,&my_charset_latin1,acl_users.elements,0,0, + VOID(hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0, (hash_get_key) check_get_key,0,0)); if (!allow_all_hosts) { @@ -1144,7 +1144,7 @@ static void init_check_host(void) { // Check if host already exists acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,j, acl_host_and_ip *); - if (!my_strcasecmp(&my_charset_latin1, + if (!my_strcasecmp(system_charset_info, acl_user->host.hostname, acl->hostname)) break; // already stored } @@ -1225,7 +1225,7 @@ bool check_change_password(THD *thd, const char *host, const char *user, } if (!thd->slave_thread && (strcmp(thd->user,user) || - my_strcasecmp(&my_charset_latin1, host, thd->priv_host))) + my_strcasecmp(system_charset_info, host, thd->priv_host))) { if (check_access(thd, UPDATE_ACL, "mysql",0,1,0)) return(1); @@ -1434,7 +1434,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname, return (tmp & host->ip_mask) == host->ip; } return (!host->hostname || - (hostname && !wild_case_compare(&my_charset_latin1, + (hostname && !wild_case_compare(system_charset_info, hostname,host->hostname)) || (ip && !wild_compare(ip,host->hostname,0))); } @@ -1447,7 +1447,7 @@ bool hostname_requires_resolving(const char *hostname) int namelen= strlen(hostname); int lhlen= strlen(my_localhost); if ((namelen == lhlen) && - !my_strnncoll(&my_charset_latin1, (const uchar *)hostname, namelen, + !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen, (const uchar *)my_localhost, strlen(my_localhost))) return FALSE; for (; (cur=*hostname); hostname++) @@ -1481,8 +1481,8 @@ static bool update_user_table(THD *thd, TABLE *table, DBUG_ENTER("update_user_table"); DBUG_PRINT("enter",("user: %s host: %s",user,host)); - table->field[0]->store(host,(uint) strlen(host), &my_charset_latin1); - table->field[1]->store(user,(uint) strlen(user), &my_charset_latin1); + table->field[0]->store(host,(uint) strlen(host), system_charset_info); + table->field[1]->store(user,(uint) strlen(user), system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, @@ -1494,7 +1494,7 @@ static bool update_user_table(THD *thd, TABLE *table, DBUG_RETURN(1); /* purecov: deadcode */ } store_record(table,record[1]); - table->field[2]->store(new_password, new_password_len, &my_charset_latin1); + table->field[2]->store(new_password, new_password_len, system_charset_info); if ((error=table->file->update_row(table->record[1],table->record[0]))) { table->file->print_error(error,MYF(0)); /* purecov: deadcode */ @@ -1559,8 +1559,8 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, password=combo.password.str; } - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(combo.user.str,combo.user.length, system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0], 0, (byte*) table->field[0]->ptr, @@ -1579,18 +1579,18 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, old_row_exists = 0; restore_record(table,default_values); // cp empty row from default_values table->field[0]->store(combo.host.str,combo.host.length, - &my_charset_latin1); + system_charset_info); table->field[1]->store(combo.user.str,combo.user.length, - &my_charset_latin1); + system_charset_info); table->field[2]->store(password, password_len, - &my_charset_latin1); + system_charset_info); } else { old_row_exists = 1; store_record(table,record[1]); // Save copy for update if (combo.password.str) // If password given - table->field[2]->store(password, password_len, &my_charset_latin1); + table->field[2]->store(password, password_len, system_charset_info); else if (!rights && !revoke_grant && thd->lex->ssl_type == SSL_TYPE_NOT_SPECIFIED && !thd->lex->mqh.bits) { @@ -1637,15 +1637,15 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo, if (thd->lex->ssl_cipher) table->field[next_field+1]->store(thd->lex->ssl_cipher, strlen(thd->lex->ssl_cipher), - &my_charset_latin1); + system_charset_info); if (thd->lex->x509_issuer) table->field[next_field+2]->store(thd->lex->x509_issuer, strlen(thd->lex->x509_issuer), - &my_charset_latin1); + system_charset_info); if (thd->lex->x509_subject) table->field[next_field+3]->store(thd->lex->x509_subject, strlen(thd->lex->x509_subject), - &my_charset_latin1); + system_charset_info); break; case SSL_TYPE_NOT_SPECIFIED: break; @@ -1750,9 +1750,9 @@ static int replace_db_table(TABLE *table, const char *db, DBUG_RETURN(-1); } - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, (byte*) table->field[0]->ptr, @@ -1766,9 +1766,9 @@ static int replace_db_table(TABLE *table, const char *db, } old_row_exists = 0; restore_record(table,default_values); // cp empty row from default_values - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); } else { @@ -1880,7 +1880,7 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u, key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3; hash_key = (char*) alloc_root(&memex,key_length); strmov(strmov(strmov(hash_key,user)+1,db)+1,tname); - (void) hash_init(&hash_columns,&my_charset_latin1, + (void) hash_init(&hash_columns,system_charset_info, 0,0,0, (hash_get_key) get_key_column,0,0); } @@ -1916,17 +1916,17 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs) privs = fix_rights_for_table(privs); cols = fix_rights_for_column(cols); - (void) hash_init(&hash_columns,&my_charset_latin1, + (void) hash_init(&hash_columns,system_charset_info, 0,0,0, (hash_get_key) get_key_column,0,0); if (cols) { int key_len; col_privs->field[0]->store(host.hostname, host.hostname ? (uint) strlen(host.hostname) : 0, - &my_charset_latin1); - col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1); - col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1); + system_charset_info); + col_privs->field[1]->store(db,(uint) strlen(db), system_charset_info); + col_privs->field[2]->store(user,(uint) strlen(user), system_charset_info); + col_privs->field[3]->store(tname,(uint) strlen(tname), system_charset_info); key_len=(col_privs->field[0]->pack_length()+ col_privs->field[1]->pack_length()+ col_privs->field[2]->pack_length()+ @@ -2032,10 +2032,10 @@ static int replace_column_table(GRANT_TABLE *g_t, byte key[MAX_KEY_LENGTH]; DBUG_ENTER("replace_column_table"); - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); - table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); + table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info); key_length=(table->field[0]->pack_length()+ table->field[1]->pack_length()+ table->field[2]->pack_length()+ table->field[3]->pack_length()); key_copy(key,table,0,key_length); @@ -2053,7 +2053,7 @@ static int replace_column_table(GRANT_TABLE *g_t, bool old_row_exists=0; key_restore(table,key,0,key_length); table->field[4]->store(xx->column.ptr(),xx->column.length(), - &my_charset_latin1); + system_charset_info); table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr, @@ -2071,7 +2071,7 @@ static int replace_column_table(GRANT_TABLE *g_t, restore_record(table,default_values); // Get empty record key_restore(table,key,0,key_length); table->field[4]->store(xx->column.ptr(),xx->column.length(), - &my_charset_latin1); + system_charset_info); } else { @@ -2143,7 +2143,8 @@ static int replace_column_table(GRANT_TABLE *g_t, { GRANT_COLUMN *grant_column = NULL; char colum_name_buf[HOSTNAME_LENGTH+1]; - String column_name(colum_name_buf,sizeof(colum_name_buf),&my_charset_latin1); + String column_name(colum_name_buf,sizeof(colum_name_buf), + system_charset_info); privileges&= ~rights; table->field[6]->store((longlong) @@ -2213,10 +2214,10 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } restore_record(table,default_values); // Get empty record - table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1); - table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1); - table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1); - table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1); + table->field[0]->store(combo.host.str,combo.host.length, system_charset_info); + table->field[1]->store(db,(uint) strlen(db), system_charset_info); + table->field[2]->store(combo.user.str,combo.user.length, system_charset_info); + table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info); store_record(table,record[1]); // store at pos 1 table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS); if (table->file->index_read_idx(table->record[0],0, @@ -2261,7 +2262,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table, } } - table->field[4]->store(grantor,(uint) strlen(grantor), &my_charset_latin1); + table->field[4]->store(grantor,(uint) strlen(grantor), system_charset_info); table->field[6]->store((longlong) store_table_rights); table->field[7]->store((longlong) store_col_rights); rights=fix_rights_for_table(store_table_rights); @@ -2727,7 +2728,7 @@ static my_bool grant_load(TABLE_LIST *tables) DBUG_ENTER("grant_load"); grant_option = FALSE; - (void) hash_init(&column_priv_hash,&my_charset_latin1, + (void) hash_init(&column_priv_hash,system_charset_info, 0,0,0, (hash_get_key) get_grant_table, (hash_free_key) free_grant_table,0); init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0); @@ -3206,7 +3207,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) if (!(host=acl_user->host.hostname)) host= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) break; } if (counter == acl_users.elements) @@ -3340,7 +3341,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) host= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host)) + !my_strcasecmp(system_charset_info, lex_user->host.str, host)) { want_access=acl_db->access; if (want_access) @@ -3400,7 +3401,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user) user= ""; if (!strcmp(lex_user->user.str,user) && - !my_strcasecmp(&my_charset_latin1, lex_user->host.str, + !my_strcasecmp(system_charset_info, lex_user->host.str, grant_table->host.hostname)) { ulong table_access= grant_table->privs; From f455634cba9c7b949583e64f08b40de6b16e85b3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Nov 2005 11:52:58 +0400 Subject: [PATCH 09/69] Fix for bug #15047: "server crash when compiling without transaction support". sql/sql_class.h: Fix for bug #15047: "server crash when compiling without transaction support". - set xid_state.xa_state to XA_NOTR in absence of transactional engines, as we check it in the end_trans() which is always called from the ha_enable_transaction(). --- sql/sql_class.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sql/sql_class.h b/sql/sql_class.h index ed6f5732ca8..9395252310b 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1229,14 +1229,16 @@ public: free_root(&mem_root,MYF(MY_KEEP_PREALLOC)); #endif } -#ifdef USING_TRANSACTIONS st_transactions() { +#ifdef USING_TRANSACTIONS bzero((char*)this, sizeof(*this)); xid_state.xid.null(); init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0); - } +#else + xid_state.xa_state= XA_NOTR; #endif + } } transaction; Field *dupp_field; #ifndef __WIN__ From 95b92b4369cd85c3c04d1910e30333e862f416fa Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Nov 2005 12:27:58 +0100 Subject: [PATCH 10/69] Bug #14514 Creating table with packed key fails silently - Backport from 5.0 include/my_base.h: Rename HA_CREATE_FROM_ENGINE to HA_OPTION_CREATE_FROM_ENGINE, ie. it's a bit in the table_options variable mysql-test/r/ndb_basic.result: Add test result mysql-test/t/ndb_basic.test: Add test case for bug14514 sql/ha_ndbcluster.cc: Use new bitmask for table_options to detect if create from engine sql/handler.cc: Use new bit for create from engine --- include/my_base.h | 2 +- mysql-test/r/ndb_basic.result | 4 ++++ mysql-test/t/ndb_basic.test | 8 ++++++++ sql/ha_ndbcluster.cc | 2 +- sql/handler.cc | 2 +- 5 files changed, 15 insertions(+), 3 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index d702ec45140..271e7cd23ba 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -231,6 +231,7 @@ enum ha_base_keytype { #define HA_OPTION_CHECKSUM 32 #define HA_OPTION_DELAY_KEY_WRITE 64 #define HA_OPTION_NO_PACK_KEYS 128 /* Reserved for MySQL */ +#define HA_OPTION_CREATE_FROM_ENGINE 256 #define HA_OPTION_TEMP_COMPRESS_RECORD ((uint) 16384) /* set by isamchk */ #define HA_OPTION_READ_ONLY_DATA ((uint) 32768) /* Set by isamchk */ @@ -241,7 +242,6 @@ enum ha_base_keytype { #define HA_CREATE_TMP_TABLE 4 #define HA_CREATE_CHECKSUM 8 #define HA_CREATE_DELAY_KEY_WRITE 64 -#define HA_CREATE_FROM_ENGINE 128 /* Bits in flag to _status */ diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index 3712fa2b5ca..42b5a39d3d8 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -667,3 +667,7 @@ counter datavalue 57 newval 58 newval drop table t1; +CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; +select * from t1; +b +drop table t1; diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test index 144e466d937..c8cf5823500 100644 --- a/mysql-test/t/ndb_basic.test +++ b/mysql-test/t/ndb_basic.test @@ -606,4 +606,12 @@ select * from t1 order by counter; drop table t1; +# +# BUG#14514 Creating table with packed key fails silently +# + +CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; +select * from t1; +drop table t1; + # End of 4.1 tests diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 608dc3eaa54..5391f0dedd0 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3711,7 +3711,7 @@ int ha_ndbcluster::create(const char *name, const void *data, *pack_data; const char **key_names= form->keynames.type_names; char name2[FN_HEADLEN]; - bool create_from_engine= (info->table_options & HA_CREATE_FROM_ENGINE); + bool create_from_engine= (info->table_options & HA_OPTION_CREATE_FROM_ENGINE); DBUG_ENTER("create"); DBUG_PRINT("enter", ("name: %s", name)); diff --git a/sql/handler.cc b/sql/handler.cc index e6bc1496a00..e166f9885fc 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -1382,7 +1382,7 @@ int ha_create_table_from_engine(THD* thd, DBUG_RETURN(3); update_create_info_from_table(&create_info, &table); - create_info.table_options|= HA_CREATE_FROM_ENGINE; + create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE; if (lower_case_table_names == 2 && !(table.file->table_flags() & HA_FILE_BASED)) From 31ea9f945d2acfa8e0dec18df8ae7094d7ca62b0 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Nov 2005 16:09:26 +0400 Subject: [PATCH 11/69] Fix for bug#14780 memory leak for mysql 4.1.14 with openssl enabled --- sql-common/client.c | 6 +++++- vio/vio.c | 2 +- vio/vio_priv.h | 1 - vio/viossl.c | 19 ------------------- 4 files changed, 6 insertions(+), 22 deletions(-) diff --git a/sql-common/client.c b/sql-common/client.c index 3979b9304f7..3a598832253 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -1487,11 +1487,15 @@ mysql_ssl_set(MYSQL *mysql __attribute__((unused)) , static void mysql_ssl_free(MYSQL *mysql __attribute__((unused))) { + struct st_VioSSLConnectorFd *st= + (struct st_VioSSLConnectorFd*) mysql->connector_fd; my_free(mysql->options.ssl_key, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_cert, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_ca, MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); - my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); + if (st) + SSL_CTX_free(st->ssl_context); my_free(mysql->connector_fd,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.ssl_key = 0; mysql->options.ssl_cert = 0; diff --git a/vio/vio.c b/vio/vio.c index 427c52e29d3..6174acd7024 100644 --- a/vio/vio.c +++ b/vio/vio.c @@ -83,7 +83,7 @@ void vio_reset(Vio* vio, enum enum_vio_type type, #ifdef HAVE_OPENSSL if (type == VIO_TYPE_SSL) { - vio->viodelete =vio_ssl_delete; + vio->viodelete =vio_delete; vio->vioerrno =vio_ssl_errno; vio->read =vio_ssl_read; vio->write =vio_ssl_write; diff --git a/vio/vio_priv.h b/vio/vio_priv.h index c1c78cc6efa..eb495025ddd 100644 --- a/vio/vio_priv.h +++ b/vio/vio_priv.h @@ -28,7 +28,6 @@ void vio_ignore_timeout(Vio *vio, uint which, uint timeout); #ifdef HAVE_OPENSSL #include "my_net.h" /* needed because of struct in_addr */ -void vio_ssl_delete(Vio* vio); int vio_ssl_read(Vio *vio,gptr buf, int size); int vio_ssl_write(Vio *vio,const gptr buf,int size); void vio_ssl_timeout(Vio *vio, uint which, uint timeout); diff --git a/vio/viossl.c b/vio/viossl.c index a3a2e7190bd..62145fe5006 100644 --- a/vio/viossl.c +++ b/vio/viossl.c @@ -69,25 +69,6 @@ report_errors() DBUG_VOID_RETURN; } -/* - Delete a vio object - - SYNPOSIS - vio_ssl_delete() - vio Vio object. May be 0. -*/ - - -void vio_ssl_delete(Vio * vio) -{ - if (vio) - { - if (vio->type != VIO_CLOSED) - vio_close(vio); - my_free((gptr) vio,MYF(0)); - } -} - int vio_ssl_errno(Vio *vio __attribute__((unused))) { From 72d19611d198164e1fcd2e16b270a11824d860bf Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 21 Nov 2005 17:26:31 +0400 Subject: [PATCH 12/69] Bug#10446 Illegal mix of collations: item_strfunc.h, item_strfunc.cc, item.cc: Try to convert a const item into destination character set. If conversion happens without data loss, then cache the converted value and return it during val_str(). Otherwise, if conversion loses data, return Illeral mix of collations error, as it happened previously. ctype_recoding.result, ctype_recoding.test: Fixing tests accordingly. sql/item.cc: Bug#10446 Illegal mix of collations Try to convert a const item into destination character set. If conversion happens without data loss, then cache the converted value and return it during val_str(). Otherwise, if conversion loses data, return Illeral mix of collations error, as it happened previously. sql/item_strfunc.cc: Return cached value when it's possible. mysql-test/t/ctype_recoding.test: Fixing tests accordingly. mysql-test/r/ctype_recoding.result: Fixing tests accordingly. --- mysql-test/r/ctype_recoding.result | 9 +++++++- mysql-test/t/ctype_recoding.test | 11 ++++++++-- sql/item.cc | 12 ++--------- sql/item_strfunc.cc | 2 ++ sql/item_strfunc.h | 34 ++++++++++++++++++++++++++++-- 5 files changed, 53 insertions(+), 15 deletions(-) diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result index 1c75988fd21..0b5c6f8974c 100644 --- a/mysql-test/r/ctype_recoding.result +++ b/mysql-test/r/ctype_recoding.result @@ -181,11 +181,18 @@ select * from t1 where a=_koi8r' a вася select * from t1 where a=concat(_koi8r'вася'); -ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation '=' +a +вася select * from t1 where a=_latin1'вася'; ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation '=' drop table t1; set names latin1; +create table t1 (a char(10) character set utf8 collate utf8_bin); +insert into t1 values (' xxx'); +select * from t1 where a=lpad('xxx',10,' '); +a + xxx +drop table t1; set names koi8r; create table t1 (c1 char(10) character set cp1251); insert into t1 values ('ъ'); diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test index 9949ef88da4..5648cea7fd3 100644 --- a/mysql-test/t/ctype_recoding.test +++ b/mysql-test/t/ctype_recoding.test @@ -144,8 +144,7 @@ create table t1 (a char(10) character set cp1251); insert into t1 values (_koi8r'вася'); # this is possible: select * from t1 where a=_koi8r'вася'; -# this is not possible, because we have a function, not just a constant: ---error 1267 +# this is possible, because we have a function with constant arguments: select * from t1 where a=concat(_koi8r'вася'); # this is not posible, cannot convert _latin1'вася' into cp1251: --error 1267 @@ -153,6 +152,14 @@ select * from t1 where a=_latin1' drop table t1; set names latin1; +# +# Bug#10446 Illegal mix of collations +# +create table t1 (a char(10) character set utf8 collate utf8_bin); +insert into t1 values (' xxx'); +select * from t1 where a=lpad('xxx',10,' '); +drop table t1; + # # Check more automatic conversion # diff --git a/sql/item.cc b/sql/item.cc index 642a0ccf1b4..5acde7c082d 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -211,16 +211,8 @@ bool Item::eq(const Item *item, bool binary_cmp) const Item *Item::safe_charset_converter(CHARSET_INFO *tocs) { - /* - Allow conversion from and to "binary". - Don't allow automatic conversion to non-Unicode charsets, - as it potentially loses data. - */ - if (collation.collation != &my_charset_bin && - tocs != &my_charset_bin && - !(tocs->state & MY_CS_UNICODE)) - return NULL; // safe conversion is not possible - return new Item_func_conv_charset(this, tocs); + Item_func_conv_charset *conv= new Item_func_conv_charset(this, tocs, 1); + return conv->safe ? conv : NULL; } diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc index 6ca6ce62c54..60cb3348590 100644 --- a/sql/item_strfunc.cc +++ b/sql/item_strfunc.cc @@ -2252,6 +2252,8 @@ String *Item_func_conv::val_str(String *str) String *Item_func_conv_charset::val_str(String *str) { DBUG_ASSERT(fixed == 1); + if (use_cached_value) + return null_value ? 0 : &str_value; String *arg= args[0]->val_str(str); uint dummy_errors; if (!arg) diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h index 87aee9ac25c..c4505fce248 100644 --- a/sql/item_strfunc.h +++ b/sql/item_strfunc.h @@ -614,10 +614,40 @@ public: class Item_func_conv_charset :public Item_str_func { + bool use_cached_value; public: + bool safe; CHARSET_INFO *conv_charset; // keep it public - Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a) - { conv_charset=cs; } + Item_func_conv_charset(Item *a, CHARSET_INFO *cs) :Item_str_func(a) + { conv_charset= cs; use_cached_value= 0; safe= 0; } + Item_func_conv_charset(Item *a, CHARSET_INFO *cs, bool cache_if_const) + :Item_str_func(a) + { + DBUG_ASSERT(args[0]->fixed); + conv_charset= cs; + if (cache_if_const && args[0]->const_item()) + { + uint errors= 0; + String tmp, *str= args[0]->val_str(&tmp); + if (!str || str_value.copy(str->ptr(), str->length(), + str->charset(), conv_charset, &errors)) + null_value= 1; + use_cached_value= 1; + safe= (errors == 0); + } + else + { + use_cached_value= 0; + /* + Conversion from and to "binary" is safe. + Conversion to Unicode is safe. + Other kind of conversions are potentially lossy. + */ + safe= (args[0]->collation.collation == &my_charset_bin || + cs == &my_charset_bin || + (cs->state & MY_CS_UNICODE)); + } + } String *val_str(String *); void fix_length_and_dec(); const char *func_name() const { return "convert"; } From b118282377a7b80b8d50b996d896bd5424d5d52e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Nov 2005 11:56:53 +0100 Subject: [PATCH 13/69] Fixed BUG#13729 Stored procedures: packet error after exception handled Don't set thd->is_fatal_error in sql_update for duplicate key errors. mysql-test/r/sp.result: New test case for BUG#13729. mysql-test/r/sp_trans.result: New test case for BUG#14840. mysql-test/t/sp.test: New test case for BUG#13729. mysql-test/t/sp_trans.test: New test case for BUG#14840. sql/sql_update.cc: Don't set thd->is_fatal_error if it's a duplicate key error. --- mysql-test/r/sp.result | 18 ++++++++++ mysql-test/r/sp_trans.result | 56 +++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 27 +++++++++++++++ mysql-test/t/sp_trans.test | 64 ++++++++++++++++++++++++++++++++++++ sql/sql_update.cc | 14 ++++++-- 5 files changed, 177 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 93332af21a9..5e1d21eaec6 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -3667,4 +3667,22 @@ call bug14845()| a 0 drop procedure bug14845| +drop procedure if exists bug13729| +drop table if exists t3| +create table t3 (s1 int, primary key (s1))| +insert into t3 values (1),(2)| +create procedure bug13729() +begin +declare continue handler for sqlexception select 55; +update t3 set s1 = 1; +end| +call bug13729()| +55 +55 +select * from t3| +s1 +1 +2 +drop procedure bug13729| +drop table t3| drop table t1,t2; diff --git a/mysql-test/r/sp_trans.result b/mysql-test/r/sp_trans.result index bb742d0d3d7..8f2bd9985fc 100644 --- a/mysql-test/r/sp_trans.result +++ b/mysql-test/r/sp_trans.result @@ -369,3 +369,59 @@ drop procedure bug13825_0| drop procedure bug13825_1| drop procedure bug13825_2| drop table t1, t2| +drop table if exists t3| +drop procedure if exists bug14840_1| +drop procedure if exists bug14840_2| +create table t3 +( +x int, +y int, +primary key (x) +) engine=InnoDB| +create procedure bug14840_1() +begin +declare err int default 0; +declare continue handler for sqlexception +set err = err + 1; +start transaction; +update t3 set x = 1, y = 42 where x = 2; +insert into t3 values (3, 4711); +if err > 0 then +rollback; +else +commit; +end if; +select * from t3; +end| +create procedure bug14840_2() +begin +declare err int default 0; +declare continue handler for sqlexception +begin +set err = err + 1; +select err as 'Ping'; +end; +update t3 set x = 1, y = 42 where x = 2; +update t3 set x = 1, y = 42 where x = 2; +insert into t3 values (3, 4711); +select * from t3; +end| +insert into t3 values (1, 3), (2, 5)| +call bug14840_1()| +x y +1 3 +2 5 +delete from t3| +insert into t3 values (1, 3), (2, 5)| +call bug14840_2()| +Ping +1 +Ping +2 +x y +1 3 +2 5 +3 4711 +drop procedure bug14840_1| +drop procedure bug14840_2| +drop table t3| diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 5ad2b9287aa..8fa3ae46de4 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4594,6 +4594,33 @@ end| call bug14845()| drop procedure bug14845| +# +# BUG#13729: Stored procedures: packet error after exception handled +# +--disable_warnings +drop procedure if exists bug13729| +drop table if exists t3| +--enable_warnings + +create table t3 (s1 int, primary key (s1))| + +insert into t3 values (1),(2)| + +create procedure bug13729() +begin + declare continue handler for sqlexception select 55; + + update t3 set s1 = 1; +end| + +call bug13729()| +# Used to cause Packets out of order +select * from t3| + +drop procedure bug13729| +drop table t3| + + # # BUG#NNNN: New bug synopsis # diff --git a/mysql-test/t/sp_trans.test b/mysql-test/t/sp_trans.test index d72eaf5dca0..308d4ad5c33 100644 --- a/mysql-test/t/sp_trans.test +++ b/mysql-test/t/sp_trans.test @@ -355,6 +355,70 @@ drop procedure bug13825_2| drop table t1, t2| +# +# BUG#14840: CONTINUE handler problem +# +--disable_warnings +drop table if exists t3| +drop procedure if exists bug14840_1| +drop procedure if exists bug14840_2| +--enable_warnings + +create table t3 +( + x int, + y int, + primary key (x) +) engine=InnoDB| + +# This used to hang the client since the insert returned with an +# error status (left over from the update) even though it succeeded, +# which caused the execution to end at that point. +create procedure bug14840_1() +begin + declare err int default 0; + declare continue handler for sqlexception + set err = err + 1; + + start transaction; + update t3 set x = 1, y = 42 where x = 2; + insert into t3 values (3, 4711); + if err > 0 then + rollback; + else + commit; + end if; + select * from t3; +end| + +# A simpler (non-transactional) case: insert at select should be done +create procedure bug14840_2() +begin + declare err int default 0; + declare continue handler for sqlexception + begin + set err = err + 1; + select err as 'Ping'; + end; + + update t3 set x = 1, y = 42 where x = 2; + update t3 set x = 1, y = 42 where x = 2; + insert into t3 values (3, 4711); + select * from t3; +end| + +insert into t3 values (1, 3), (2, 5)| +call bug14840_1()| + +delete from t3| +insert into t3 values (1, 3), (2, 5)| +call bug14840_2()| + +drop procedure bug14840_1| +drop procedure bug14840_2| +drop table t3| + + # # BUG#NNNN: New bug synopsis # diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 039aa0f71fa..50f8e35a9e9 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -465,7 +465,12 @@ int mysql_update(THD *thd, } else if (!ignore || error != HA_ERR_FOUND_DUPP_KEY) { - thd->fatal_error(); // Force error message + /* + If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to + do anything; otherwise... + */ + if (error != HA_ERR_FOUND_DUPP_KEY) + thd->fatal_error(); /* Other handler errors are fatal */ table->file->print_error(error,MYF(0)); error= 1; break; @@ -1259,7 +1264,12 @@ bool multi_update::send_data(List ¬_used_values) updated--; if (!ignore || error != HA_ERR_FOUND_DUPP_KEY) { - thd->fatal_error(); // Force error message + /* + If (ignore && error == HA_ERR_FOUND_DUPP_KEY) we don't have to + do anything; otherwise... + */ + if (error != HA_ERR_FOUND_DUPP_KEY) + thd->fatal_error(); /* Other handler errors are fatal */ table->file->print_error(error,MYF(0)); DBUG_RETURN(1); } From 147be17067dc699aec2f12e7a52992ffc329d8b1 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Nov 2005 18:18:41 +0300 Subject: [PATCH 14/69] Fixes bug #14902. When analysing a table with FT index that contains stopwords table statistics is not updated, so the next execution of analyze table will try to update statistics again. mysql-test/r/analyze.result: Updated result file for bug #14902 test. mysql-test/t/analyze.test: Test for bug #14902. --- myisam/mi_check.c | 3 ++- mysql-test/r/analyze.result | 9 +++++++++ mysql-test/t/analyze.test | 14 ++++++++++++++ 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/myisam/mi_check.c b/myisam/mi_check.c index 6296193d6b0..9ce1dff51af 100644 --- a/myisam/mi_check.c +++ b/myisam/mi_check.c @@ -402,7 +402,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) full_text_keys++; if (share->state.key_root[key] == HA_OFFSET_ERROR && (info->state->records == 0 || keyinfo->flag & HA_FULLTEXT)) - continue; + goto do_stat; if (!_mi_fetch_keypage(info,keyinfo,share->state.key_root[key], DFLT_INIT_HITS,info->buff,0)) { @@ -498,6 +498,7 @@ int chk_key(MI_CHECK *param, register MI_INFO *info) param->max_level); all_keydata+=param->keydata; all_totaldata+=param->totaldata; key_totlength+=length; +do_stat: if (param->testflag & T_STATISTICS) update_key_parts(keyinfo, rec_per_key_part, param->unique_count, param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? diff --git a/mysql-test/r/analyze.result b/mysql-test/r/analyze.result index 0b44a502b13..3ccc3566432 100644 --- a/mysql-test/r/analyze.result +++ b/mysql-test/r/analyze.result @@ -30,3 +30,12 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; +create table t1 (a mediumtext, fulltext key key1(a)) charset utf8 collate utf8_general_ci engine myisam; +insert into t1 values ('hello'); +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status OK +analyze table t1; +Table Op Msg_type Msg_text +test.t1 analyze status Table is already up to date +drop table t1; diff --git a/mysql-test/t/analyze.test b/mysql-test/t/analyze.test index 3c3b3933bc3..9d94f5da9d9 100644 --- a/mysql-test/t/analyze.test +++ b/mysql-test/t/analyze.test @@ -39,4 +39,18 @@ check table t1; drop table t1; +# Bug #14902 ANALYZE TABLE fails to recognize up-to-date tables +# minimal test case to get an error. +# The problem is happening when analysing table with FT index that +# contains stopwords only. The first execution of analyze table should +# mark index statistics as up to date so that next execution of this +# statement will end up with Table is up to date status. +create table t1 (a mediumtext, fulltext key key1(a)) charset utf8 collate utf8_general_ci engine myisam; +insert into t1 values ('hello'); + +analyze table t1; +analyze table t1; + +drop table t1; + # End of 4.1 tests From 0f64a6222edc0d0ded4e1b48fa428f8a7b44e67e Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Nov 2005 14:57:26 -0800 Subject: [PATCH 15/69] Fix result of ROW_COUNT() after 'EXECUTE prepstmt'. (Bug #14956) mysql-test/r/ps.result: Add new results mysql-test/t/ps.test: Add new test sql/sql_parse.cc: Don't reset row_count after processing EXECUTE statement. --- mysql-test/r/ps.result | 7 +++++++ mysql-test/t/ps.test | 12 ++++++++++++ sql/sql_parse.cc | 12 ++++++++---- 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f1c3672083d..2ce2b5db431 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -806,3 +806,10 @@ execute stmt; @@tx_isolation REPEATABLE-READ deallocate prepare stmt; +create table t1 (id int); +prepare ins_call from "insert into t1 (id) values (1)"; +execute ins_call; +select row_count(); +row_count() +1 +drop table t1; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index 94ee2b1ca39..cfc49bbfd41 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -843,3 +843,15 @@ execute stmt; deallocate prepare stmt; # End of 4.1 tests + +# +# Bug #14956: ROW_COUNT() returns incorrect result after EXECUTE of prepared +# statement +# +create table t1 (id int); +prepare ins_call from "insert into t1 (id) values (1)"; +execute ins_call; +select row_count(); +drop table t1; + +# End of 5.0 tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index c19d54feda5..4f45451ddc4 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -4822,11 +4822,15 @@ end_with_restore_list: /* - The return value for ROW_COUNT() is "implementation dependent" if - the statement is not DELETE, INSERT or UPDATE (or a CALL executing - such a statement), but -1 is what JDBC and ODBC wants. + The return value for ROW_COUNT() is "implementation dependent" if the + statement is not DELETE, INSERT or UPDATE, but -1 is what JDBC and ODBC + wants. + + We do not change the value for a CALL or EXECUTE statement, so the value + generated by the last called (or executed) statement is preserved. */ - if (lex->sql_command != SQLCOM_CALL && uc_update_queries[lex->sql_command]<2) + if (lex->sql_command != SQLCOM_CALL && lex->sql_command != SQLCOM_EXECUTE && + uc_update_queries[lex->sql_command]<2) thd->row_count_func= -1; goto cleanup; From 687b57be8d5e2ed0d69227f6285d4e0b804982dd Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Nov 2005 17:05:59 -0800 Subject: [PATCH 16/69] Fix handling of maximum value for MAX_ROWS on 64-bit platforms. (Bug #14155) mysql-test/r/create.result: Add new results mysql-test/t/create.test: Add regression test sql/table.cc: To cap a value at 2^32-1 on a 64-bit platform, use UINT_MAX32, not ~(ulong)0, since a ulong may be 64-bit itself. --- mysql-test/r/create.result | 19 +++++++++++++++++++ mysql-test/t/create.test | 14 ++++++++++++++ sql/table.cc | 8 ++++---- 3 files changed, 37 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 6edd4cbc48f..80a3c2ea82d 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -621,3 +621,22 @@ create table if not exists t1 (a int); Warnings: Note 1050 Table 't1' already exists drop table t1; +create table t1 (i int) engine=myisam max_rows=100000000000; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 MAX_ROWS=4294967295 +alter table t1 max_rows=100; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 MAX_ROWS=100 +alter table t1 max_rows=100000000000; +show create table t1; +Table Create Table +t1 CREATE TABLE `t1` ( + `i` int(11) default NULL +) ENGINE=MyISAM DEFAULT CHARSET=latin1 MAX_ROWS=4294967295 +drop table t1; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 73184853d1a..50a2e1a3cba 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -527,3 +527,17 @@ create table if not exists t1 (a int); drop table t1; # End of 4.1 tests + +# +# Bug #14155: Maximum value of MAX_ROWS handled incorrectly on 64-bit +# platforms +# +create table t1 (i int) engine=myisam max_rows=100000000000; +show create table t1; +alter table t1 max_rows=100; +show create table t1; +alter table t1 max_rows=100000000000; +show create table t1; +drop table t1; + +# End of 5.0 tests diff --git a/sql/table.cc b/sql/table.cc index 04d1a95cd9b..eb8cbf9b5e2 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1253,10 +1253,10 @@ File create_frm(register my_string name, const char *db, const char *table, #if SIZEOF_OFF_T > 4 /* Fix this when we have new .frm files; Current limit is 4G rows (QQ) */ - if (create_info->max_rows > ~(ulong) 0) - create_info->max_rows= ~(ulong) 0; - if (create_info->min_rows > ~(ulong) 0) - create_info->min_rows= ~(ulong) 0; + if (create_info->max_rows > UINT_MAX32) + create_info->max_rows= UINT_MAX32; + if (create_info->min_rows > UINT_MAX32) + create_info->min_rows= UINT_MAX32; #endif /* Ensure that raid_chunks can't be larger than 255, as this would cause From eb92d6a1e338f91447134b1ff85e5ad1c4900428 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 23 Nov 2005 17:31:44 -0800 Subject: [PATCH 17/69] Fix values printed by mysqldump for empty blob fields when --hex-blob is used. (Bug #13318) client/mysqldump.c: Don't use 0x... syntax for empty fields. mysql-test/r/mysqldump.result: Add new results mysql-test/t/mysqldump.test: Add new regression test --- client/mysqldump.c | 13 ++++---- mysql-test/r/mysqldump.result | 63 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqldump.test | 9 +++++ 3 files changed, 79 insertions(+), 6 deletions(-) diff --git a/client/mysqldump.c b/client/mysqldump.c index 3458f74d8a2..b6e1be2cddd 100644 --- a/client/mysqldump.c +++ b/client/mysqldump.c @@ -1768,6 +1768,8 @@ static void dumpTable(uint numFields, char *table) for (i = 0; i < mysql_num_fields(res); i++) { int is_blob; + ulong length= lengths[i]; + if (!(field = mysql_fetch_field(res))) { my_snprintf(query, QUERY_LENGTH, @@ -1777,7 +1779,7 @@ static void dumpTable(uint numFields, char *table) error= EX_CONSCHECK; goto err; } - + /* 63 is my_charset_bin. If charsetnr is not 63, we have not a BLOB but a TEXT column. @@ -1792,7 +1794,6 @@ static void dumpTable(uint numFields, char *table) field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0; if (extended_insert) { - ulong length = lengths[i]; if (i == 0) dynstr_set(&extended_row,"("); else @@ -1882,19 +1883,19 @@ static void dumpTable(uint numFields, char *table) { print_xml_tag1(md_result_file, "\t\t", "field name=", field->name, ""); - print_quoted_xml(md_result_file, row[i], lengths[i]); + print_quoted_xml(md_result_file, row[i], length); fputs("\n", md_result_file); } - else if (opt_hex_blob && is_blob) + else if (opt_hex_blob && is_blob && length) { /* sakaik got the idea to to provide blob's in hex notation. */ - char *ptr= row[i], *end= ptr+ lengths[i]; + char *ptr= row[i], *end= ptr + length; fputs("0x", md_result_file); for (; ptr < end ; ptr++) fprintf(md_result_file, "%02X", *((uchar *)ptr)); } else - unescape(md_result_file, row[i], lengths[i]); + unescape(md_result_file, row[i], length); } else { diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index cb2e8e5528a..1add3510770 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -1493,3 +1493,66 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir drop table t1, t2; +create table t1 (a binary(1), b blob); +insert into t1 values ('',''); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` binary(1) default NULL, + `b` blob +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES ('',''); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` binary(1) default NULL, + `b` blob +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES ('',''); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +drop table t1; diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test index 4978da0bd67..c97de0894c4 100644 --- a/mysql-test/t/mysqldump.test +++ b/mysql-test/t/mysqldump.test @@ -635,4 +635,13 @@ insert into t2 (a, b) values (NULL, NULL),(10, NULL),(NULL, "twenty"),(30, "thir --exec $MYSQL_DUMP --skip-comments --xml --no-create-info test drop table t1, t2; +# +# Bug #13318: Bad result with empty field and --hex-blob +# +create table t1 (a binary(1), b blob); +insert into t1 values ('',''); +--exec $MYSQL_DUMP --skip-comments --skip-extended-insert --hex-blob test t1 +--exec $MYSQL_DUMP --skip-comments --hex-blob test t1 +drop table t1; + # End of 4.1 tests From c2421d3f0dffe87a272483712a4c6a455b1b3ecd Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 17:30:25 +1100 Subject: [PATCH 18/69] BUG#15215 mysqld fails at start-up because of illegal reply from mgmd In the rare circumstance where a mysqld connects to a mgm server, then the mgm server goes away before a node id can be allocated, it was possible to get an Error in mgm protocol parser error message. ndb/src/common/mgmcommon/ConfigRetriever.cpp: When allocating node id, retry connecting to a management server if it goes away. ndb/src/mgmapi/mgmapi.cpp: Treat Eof and NoLine results from the parser as a sign that we should disconnect from this management server. It's up to the caller to work out if they want to try again. --- ndb/src/common/mgmcommon/ConfigRetriever.cpp | 6 ++++++ ndb/src/mgmapi/mgmapi.cpp | 8 +++++++- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index b3d0221fedb..278bf2b8ec7 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -341,9 +341,15 @@ ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds) { while (1) { + if(!ndb_mgm_is_connected(m_handle)) + if(!ndb_mgm_connect(m_handle, 0, 0, 0)) + goto next; + int res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type); if(res >= 0) return _ownNodeId= (Uint32)res; + + next: if (no_retries == 0) break; no_retries--; diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp index 9bb238ca90b..a69a61dcda7 100644 --- a/ndb/src/mgmapi/mgmapi.cpp +++ b/ndb/src/mgmapi/mgmapi.cpp @@ -336,10 +336,16 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow *command_reply, const Properties* p = parser.parse(ctx, session); if (p == NULL){ if(!ndb_mgm_is_connected(handle)) { - return NULL; + DBUG_RETURN(NULL); } else { + if(ctx.m_status==Parser_t::Eof + || ctx.m_status==Parser_t::NoLine) + { + ndb_mgm_disconnect(handle); + DBUG_RETURN(NULL); + } /** * Print some info about why the parser returns NULL */ From 2665fb75d6490dacbcee36ee3e3e7fe371da95c3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Nov 2005 00:04:53 +1100 Subject: [PATCH 19/69] small build fix for some compilers ndb/src/common/mgmcommon/ConfigRetriever.cpp: build fix for some compilers --- ndb/src/common/mgmcommon/ConfigRetriever.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp index 278bf2b8ec7..a44550da48b 100644 --- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp +++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp @@ -336,6 +336,7 @@ ConfigRetriever::setNodeId(Uint32 nodeid) Uint32 ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds) { + int res; _ownNodeId= 0; if(m_handle != 0) { @@ -345,7 +346,7 @@ ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds) if(!ndb_mgm_connect(m_handle, 0, 0, 0)) goto next; - int res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type); + res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type); if(res >= 0) return _ownNodeId= (Uint32)res; From d2ac9b5b6788f65eeb0b8ae38ad71c7ea7805a03 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 16:11:59 +0200 Subject: [PATCH 20/69] table t7 was not dropped at the end mysql-test/r/join_nested.result: drop t7 mysql-test/t/join_nested.test: drop t7 --- mysql-test/r/join_nested.result | 2 +- mysql-test/t/join_nested.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/join_nested.result b/mysql-test/r/join_nested.result index c4dd6cf9a86..b3ba5423421 100644 --- a/mysql-test/r/join_nested.result +++ b/mysql-test/r/join_nested.result @@ -1466,4 +1466,4 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 ref a a 5 test.t3.b X 1 SIMPLE t6 ref a a 5 test.t4.b X 1 SIMPLE t5 ref a a 5 test.t3.b X -drop table t0, t1, t2, t4, t5, t6; +drop table t0, t1, t2, t4, t5, t6, t7; diff --git a/mysql-test/t/join_nested.test b/mysql-test/t/join_nested.test index 9dbf153ec55..6e4e64bda9c 100644 --- a/mysql-test/t/join_nested.test +++ b/mysql-test/t/join_nested.test @@ -899,4 +899,4 @@ explain select * from t2 left join (t3 left join (t4 join t6 on t6.a=t4.b) on t4.a=t3.b join t5 on t5.a=t3.b) on t3.a=t2.b; -drop table t0, t1, t2, t4, t5, t6; +drop table t0, t1, t2, t4, t5, t6, t7; From 102c0281fa1a746d6d473fbb22237a5dac1b82ba Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 16:21:07 +0100 Subject: [PATCH 21/69] Moved check of wrong schema version earlier --- sql/ha_ndbcluster.cc | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc index 6760208488f..e06559dc593 100644 --- a/sql/ha_ndbcluster.cc +++ b/sql/ha_ndbcluster.cc @@ -3285,12 +3285,7 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) DBUG_PRINT("info", ("Table schema version: %d", tab->getObjectVersion())); } - if (m_table != (void *)tab) - { - m_table= (void *)tab; - m_table_version = tab->getObjectVersion(); - } - else if (m_table_version < tab->getObjectVersion()) + if (m_table_version < tab->getObjectVersion()) { /* The table has been altered, caller has to retry @@ -3298,6 +3293,13 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type) NdbError err= ndb->getNdbError(NDB_INVALID_SCHEMA_OBJECT); DBUG_RETURN(ndb_to_mysql_error(&err)); } + if (m_table != (void *)tab) + { + m_table= (void *)tab; + m_table_version = tab->getObjectVersion(); + if (!(my_errno= build_index_list(ndb, table, ILBP_OPEN))) + DBUG_RETURN(my_errno); + } m_table_info= tab_info; } no_uncommitted_rows_init(thd); From 54f9b2cc1b5dfaf5f465852a02ef7289a1ac2e7a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 18:27:14 +0300 Subject: [PATCH 22/69] Polishing: get rid of C++-style comments. mysys/my_open.c: Get rid of C++-style comments. --- mysys/my_open.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/mysys/my_open.c b/mysys/my_open.c index baca97450b7..6ed3cb5becf 100644 --- a/mysys/my_open.c +++ b/mysys/my_open.c @@ -267,7 +267,7 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode) */ switch (oflag & (_O_CREAT | _O_EXCL | _O_TRUNC)) { case 0: - case _O_EXCL: // ignore EXCL w/o CREAT + case _O_EXCL: /* ignore EXCL w/o CREAT */ filecreate= OPEN_EXISTING; break; @@ -281,7 +281,7 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode) break; case _O_TRUNC: - case _O_TRUNC | _O_EXCL: // ignore EXCL w/o CREAT + case _O_TRUNC | _O_EXCL: /* ignore EXCL w/o CREAT */ filecreate= TRUNCATE_EXISTING; break; @@ -290,7 +290,7 @@ File my_sopen(const char *path, int oflag, int shflag, int pmode) break; default: - // this can't happen ... all cases are covered + /* this can't happen ... all cases are covered */ errno= EINVAL; _doserrno= 0L; return -1; From e6d90f51de36fe91aa21746403200d3392306d57 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 18:42:39 +0300 Subject: [PATCH 23/69] Make it buildable with -ansi flag on some platforms. extra/innochecksum.c: Define _XOPEN_SOURCE in order to include getopt.h when needed. The problem is that some platforms (for instance, SuSE 9.1/gcc-3.3.3) do not include getopt.h unless _XOPEN_SOURCE is defined, so optarg is undefined and the compiler complains. --- extra/innochecksum.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/extra/innochecksum.c b/extra/innochecksum.c index 739953298af..bae5f3e8821 100644 --- a/extra/innochecksum.c +++ b/extra/innochecksum.c @@ -28,6 +28,8 @@ #define _LARGEFILE_SOURCE #define _LARGEFILE64_SOURCE +#define _XOPEN_SOURCE /* needed to include getopt.h on some platforms. */ + #include #include #include From 3190b21f95e58886e1507384bf792ed68a9f8397 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 19:16:51 +0300 Subject: [PATCH 24/69] Fix bug #14482 Wrongly applied optimization in resolve_const_item() caused crash resolve_const_item() substitutes item which will evaluate to constant with equvalent constant item, basing on the item's result type. In this case subselect was resolved as constant, and resolve_const_item() was substituting it's result's Item_caches to Item_null. Later Item_cache's function was called for Item_null object, which caused server crash. resolve_const_item() now substitutes constants for items with result_type == ROW_RESULT only for Item_rows. sql/item.cc: Fix bug #14482 Wrongly applied optimization in resolve_const_item() caused crash resolve_const_item() now applies optimization for items with result_type == ROW_RESULT only to Item_rows. mysql-test/t/select.test: Test case for bug #14482 Wrongly applied optimization in resolve_const_item() caused crash mysql-test/r/select.result: Test case for bug #14482 Wrongly applied optimization in resolve_const_item() caused crash --- mysql-test/r/select.result | 8 ++++++++ mysql-test/t/select.test | 11 +++++++++++ sql/item.cc | 15 ++++++++++++--- 3 files changed, 31 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 64c329ee104..b80ca2b195e 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2706,3 +2706,11 @@ select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; count(f2) >0 1 drop table t1,t2; +create table t1 (f1 int,f2 int); +insert into t1 values(1,1); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t2 values(1,1); +select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2)); +f1 f2 +1 1 +drop table t1,t2; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 39c7cdfa8a9..996d5854854 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2237,4 +2237,15 @@ insert into t1 values (1,1); insert into t2 values (1,1),(1,2); select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; drop table t1,t2; + +# +# Bug #14482 Server crash when subselecting from the same table +# +create table t1 (f1 int,f2 int); +insert into t1 values(1,1); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t2 values(1,1); +select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2)); +drop table t1,t2; + # End of 4.1 tests diff --git a/sql/item.cc b/sql/item.cc index 642a0ccf1b4..6ca2627dbff 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2863,7 +2863,7 @@ Item_result item_cmp_type(Item_result a,Item_result b) void resolve_const_item(THD *thd, Item **ref, Item *comp_item) { Item *item= *ref; - Item *new_item; + Item *new_item= NULL; if (item->basic_const_item()) return; // Can't be better Item_result res_type=item_cmp_type(comp_item->result_type(), @@ -2892,8 +2892,17 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) new_item= (null_value ? (Item*) new Item_null(name) : (Item*) new Item_int(name, result, length)); } - else if (res_type == ROW_RESULT) + else if (res_type == ROW_RESULT && item->type() == Item::ROW_ITEM && + comp_item->type() == Item::ROW_ITEM) { + /* + Substitute constants only in Item_rows. Don't affect other Items + with ROW_RESULT (eg Item_singlerow_subselect). + + For such Items more optimal is to detect if it is constant and replace + it with Item_row. This would optimize queries like this: + SELECT * FROM t1 WHERE (a,b) = (SELECT a,b FROM t2 LIMIT 1); + */ Item_row *item_row= (Item_row*) item; Item_row *comp_item_row= (Item_row*) comp_item; uint col; @@ -2910,7 +2919,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item) while (col-- > 0) resolve_const_item(thd, item_row->addr(col), comp_item_row->el(col)); } - else + else if (res_type == REAL_RESULT) { // It must REAL_RESULT double result=item->val(); uint length=item->max_length,decimals=item->decimals; From a101950d7b2adf1c08de95e581b4d1d5bd84e361 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 17:17:36 +0100 Subject: [PATCH 25/69] Bug #15168 yassl failure on amd64 - Use libtool to build libraries config/ac-macros/yassl.m4: If necessary, disable inlining for all files in libtaocrypt not only integer.cpp Remove ver yassl_libs_with_path, not used anymore extra/yassl/src/Makefile.am: Let libtool build libraries extra/yassl/taocrypt/src/Makefile.am: Let libtool build libraries Only build one lib libmysqld/Makefile.am: Dont include yassl libs in libmysqld libmysqld/examples/Makefile.am: Add yassl includes and libs when linking examples with libmysqld --- config/ac-macros/yassl.m4 | 10 ++++------ extra/yassl/src/Makefile.am | 4 ++-- extra/yassl/taocrypt/src/Makefile.am | 12 ++++-------- libmysqld/Makefile.am | 3 +-- libmysqld/examples/Makefile.am | 4 ++-- 5 files changed, 13 insertions(+), 20 deletions(-) diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index 9d9a4d55000..d1216554862 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -16,7 +16,6 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ AC_MSG_RESULT([using bundled yaSSL]) yassl_dir="extra/yassl" yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt" - yassl_libs_with_path="\$(top_srcdir)/extra/yassl/src/libyassl.a \$(top_srcdir)/extra/yassl/taocrypt/src/libtaocrypt.a" yassl_includes="-I\$(top_srcdir)/extra/yassl/include" AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) @@ -24,12 +23,12 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ yassl_integer_extra_cxxflags="" case $host_cpu--$CXX_VERSION in sparc*--*Sun*C++*5.6*) - # Disable inlining when compiling taocrypt/src/integer.cpp - yassl_integer_extra_cxxflags="+d" - AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/integer.cpp]) + # Disable inlining when compiling taocrypt/src/ + yassl_taocrypt_extra_cxxflags="+d" + AC_MSG_NOTICE([disabling inlining for yassl/taocrypt/src/]) ;; esac - AC_SUBST([yassl_integer_extra_cxxflags]) + AC_SUBST([yassl_taocrypt_extra_cxxflags]) else yassl_dir="" @@ -38,6 +37,5 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ AC_SUBST(yassl_libs) AC_SUBST(yassl_includes) AC_SUBST(yassl_dir) - AC_SUBST(yassl_libs_with_path) AM_CONDITIONAL([HAVE_YASSL], [ test "with_yassl" = "yes" ]) ]) diff --git a/extra/yassl/src/Makefile.am b/extra/yassl/src/Makefile.am index df96018e1cf..a852ca4019b 100644 --- a/extra/yassl/src/Makefile.am +++ b/extra/yassl/src/Makefile.am @@ -1,7 +1,7 @@ INCLUDES = -I../include -I../taocrypt/include -I../mySTL -noinst_LIBRARIES = libyassl.a -libyassl_a_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ +noinst_LTLIBRARIES = libyassl.la +libyassl_la_SOURCES = buffer.cpp cert_wrapper.cpp crypto_wrapper.cpp \ handshake.cpp lock.cpp log.cpp socket_wrapper.cpp ssl.cpp \ template_instnt.cpp timer.cpp yassl_imp.cpp yassl_error.cpp yassl_int.cpp EXTRA_DIST = $(wildcard ../include/*.hpp) $(wildcard ../include/openssl/*.h) diff --git a/extra/yassl/taocrypt/src/Makefile.am b/extra/yassl/taocrypt/src/Makefile.am index 0319fc6057b..d89fa95a940 100644 --- a/extra/yassl/taocrypt/src/Makefile.am +++ b/extra/yassl/taocrypt/src/Makefile.am @@ -1,15 +1,11 @@ INCLUDES = -I../include -I../../mySTL -noinst_LIBRARIES = libtaoint.a libtaocrypt.a +noinst_LTLIBRARIES = libtaocrypt.la -libtaoint_a_SOURCES = integer.cpp -libtaoint_a_CXXFLAGS = @yassl_integer_extra_cxxflags@ - -libtaocrypt_a_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \ +libtaocrypt_la_SOURCES = aes.cpp aestables.cpp algebra.cpp arc4.cpp asn.cpp \ coding.cpp dh.cpp des.cpp dsa.cpp file.cpp hash.cpp \ md2.cpp md5.cpp misc.cpp random.cpp ripemd.cpp rsa.cpp sha.cpp \ - template_instnt.cpp -libtaocrypt_a_LIBADD = libtaoint_a-integer.o + template_instnt.cpp integer.cpp +libtaocrypt_la_CXXFLAGS = @yassl_taocrypt_extra_cxxflags@ -DYASSL_PURE_C EXTRA_DIST = $(wildcard ../include/*.hpp) -AM_CXXFLAGS = -DYASSL_PURE_C diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index 8ddc8752f07..f07bbacba02 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -80,8 +80,7 @@ INC_LIB= $(top_builddir)/regex/libregex.a \ $(top_builddir)/mysys/libmysys.a \ $(top_builddir)/strings/libmystrings.a \ $(top_builddir)/dbug/libdbug.a \ - $(top_builddir)/vio/libvio.a \ - @yassl_libs_with_path@ + $(top_builddir)/vio/libvio.a # diff --git a/libmysqld/examples/Makefile.am b/libmysqld/examples/Makefile.am index 925a6573efe..414cf63b003 100644 --- a/libmysqld/examples/Makefile.am +++ b/libmysqld/examples/Makefile.am @@ -34,8 +34,8 @@ link_sources: DEFS = -DEMBEDDED_LIBRARY INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include -I$(srcdir) \ -I$(top_srcdir) -I$(top_srcdir)/client -I$(top_srcdir)/regex \ - $(openssl_includes) -LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ + $(openssl_includes) $(yassl_includes) +LIBS = @LIBS@ @WRAPLIBS@ @CLIENT_LIBS@ $(yassl_libs) LDADD = @CLIENT_EXTRA_LDFLAGS@ ../libmysqld.a @innodb_system_libs@ @LIBDL@ $(CXXLDFLAGS) mysqltest_embedded_LINK = $(CXXLINK) From ae2dc30930108eff19259b59182fbaf867af677b Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 20:24:45 +0400 Subject: [PATCH 26/69] Fix for bug #14693 (ALTER COLUMN SET DEFAULT has no effect) mysql-test/r/alter_table.result: test result mysql-test/t/alter_table.test: test case sql/sql_table.cc: we should set the flag with the ALTER requirements --- mysql-test/r/alter_table.result | 6 ++++++ mysql-test/t/alter_table.test | 9 +++++++++ sql/sql_table.cc | 5 ++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result index 9b60a187d0b..f224a10c9bd 100644 --- a/mysql-test/r/alter_table.result +++ b/mysql-test/r/alter_table.result @@ -556,3 +556,9 @@ ERROR 3D000: No database selected alter table test.t1 rename test.t1; use test; drop table t1; +create table t1 (mycol int(10) not null); +alter table t1 alter column mycol set default 0; +desc t1; +Field Type Null Key Default Extra +mycol int(10) NO 0 +drop table t1; diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test index bae94656125..3878b55da11 100644 --- a/mysql-test/t/alter_table.test +++ b/mysql-test/t/alter_table.test @@ -401,3 +401,12 @@ use test; drop table t1; # End of 4.1 tests + +# +# Bug #14693 (ALTER SET DEFAULT doesn't work) +# + +create table t1 (mycol int(10) not null); +alter table t1 alter column mycol set default 0; +desc t1; +drop table t1; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index e8ffdc23ec5..8c7b4e401a9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3379,7 +3379,10 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change); DBUG_RETURN(TRUE); } - def->def=alter->def; // Use new default + if ((def->def=alter->def)) // Use new default + def->flags&= ~NO_DEFAULT_VALUE_FLAG; + else + def->flags|= NO_DEFAULT_VALUE_FLAG; alter_it.remove(); } } From 591fabb390e2fbf7f54e7d54ccce38065e8b4507 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 19:54:02 +0300 Subject: [PATCH 27/69] Fix bug#13293 Wrongly used index results in endless loop. Loose index scan using only second part of multipart index was choosen, which results in creating wrong keys and endless loop. get_best_group_min_max() now allows loose index scan for distinct only if used keyparts forms a prefix of the index. mysql-test/t/group_min_max.test: Test case for bug #13293 Wrongly used index results in endless loop. mysql-test/r/group_min_max.result: Test case for bug #13293 Wrongly used index results in endless loop. sql/opt_range.cc: Fix bug #13293 Wrongly used index results in endless loop. get_best_group_min_max() now allows loose index scan for distinct only if used keyparts forms a prefix of the index. --- mysql-test/r/group_min_max.result | 10 ++++++++++ mysql-test/t/group_min_max.test | 10 ++++++++++ sql/opt_range.cc | 13 +++++++++++++ 3 files changed, 33 insertions(+) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 038d0c75f74..91f7eaeea2c 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2002,3 +2002,13 @@ a count(a) 1 1 NULL 1 drop table t1; +create table t1 (f1 int, f2 char(1), primary key(f1,f2)) engine=innodb; +insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d"); +alter table t1 drop primary key, add primary key (f2, f1); +explain select distinct f1 a, f1 b from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 index NULL PRIMARY 5 NULL 4 Using index; Using temporary +explain select distinct f1, f2 from t1; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 range NULL PRIMARY 5 NULL 3 Using index for group-by; Using temporary +drop table t1; diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 3d751f4a571..9738bbcca49 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -693,3 +693,13 @@ create table t1(a int, key(a)) engine=innodb; insert into t1 values(1); select a, count(a) from t1 group by a with rollup; drop table t1; + +# +# Bug #13293 Wrongly used index results in endless loop. +# +create table t1 (f1 int, f2 char(1), primary key(f1,f2)) engine=innodb; +insert into t1 values ( 1,"e"),(2,"a"),( 3,"c"),(4,"d"); +alter table t1 drop primary key, add primary key (f2, f1); +explain select distinct f1 a, f1 b from t1; +explain select distinct f1, f2 from t1; +drop table t1; diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 323e829f219..cddcec29ecc 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -7197,6 +7197,7 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) { select_items_it.rewind(); cur_used_key_parts.clear_all(); + uint max_key_part= 0; while ((item= select_items_it++)) { item_field= (Item_field*) item; /* (SA5) already checked above. */ @@ -7214,7 +7215,19 @@ get_best_group_min_max(PARAM *param, SEL_TREE *tree) cur_group_prefix_len+= cur_part->store_length; cur_used_key_parts.set_bit(key_part_nr); ++cur_group_key_parts; + max_key_part= max(max_key_part,key_part_nr); } + /* + Check that used key parts forms a prefix of the index. + To check this we compare bits in all_parts and cur_parts. + all_parts have all bits set from 0 to (max_key_part-1). + cur_parts have bits set for only used keyparts. + */ + ulonglong all_parts, cur_parts; + all_parts= (1<> 1; + if (all_parts != cur_parts) + goto next_index; } else DBUG_ASSERT(FALSE); From f8aae3e6049d1e2f1109b75cf56f415aa1dd2509 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 18:13:08 +0100 Subject: [PATCH 28/69] don't call handler::info() in SHOW CREATE TABLE --- sql/sql_show.cc | 1 - 1 file changed, 1 deletion(-) diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 9449224c01a..cb537a43053 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -898,7 +898,6 @@ store_create_info(THD *thd, TABLE_LIST *table_list, String *packet) } key_info= table->key_info; - file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME); bzero((char*) &create_info, sizeof(create_info)); file->update_create_info(&create_info); primary_key= share->primary_key; From 0b262a6213a85ce3512facb23950145d051dca46 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 19:13:13 +0100 Subject: [PATCH 29/69] Some post-merge cleaning, and made assert THD::store_globals() work at all times. mysql-test/t/sp.test: Tidying up after merge. sql/mysqld.cc: Make sure we have thd->thread_stack set before calling store_globals(). (And fixed compiler warning.) sql/sql_class.cc: Init THD::tread_stack in constructor. --- mysql-test/t/sp.test | 2 ++ sql/mysqld.cc | 5 ++++- sql/sql_class.cc | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 56b64532ab8..fba3cfcbfbc 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4773,6 +4773,8 @@ drop procedure bug10100pv| drop procedure bug10100pd| drop procedure bug10100pc| drop view v1| + +# # BUG#13729: Stored procedures: packet error after exception handled # --disable_warnings diff --git a/sql/mysqld.cc b/sql/mysqld.cc index b5b95e48889..8792d2560ae 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -1589,6 +1589,7 @@ void end_thread(THD *thd, bool put_in_cache) wake_thread--; thd=thread_cache.get(); thd->real_id=pthread_self(); + thd->thread_stack= (char *) &thd; (void) thd->store_globals(); thd->thr_create_time= time(NULL); threads.append(thd); @@ -6912,8 +6913,10 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), case OPT_MYISAM_STATS_METHOD: { ulong method_conv; - myisam_stats_method_str= argument; int method; + LINT_INIT(method_conv); + + myisam_stats_method_str= argument; if ((method=find_type(argument, &myisam_stats_method_typelib, 2)) <= 0) { fprintf(stderr, "Invalid value of myisam_stats_method: %s.\n", argument); diff --git a/sql/sql_class.cc b/sql/sql_class.cc index b65f353e492..70dfaca53d3 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -183,6 +183,7 @@ THD::THD() spcont(NULL) { stmt_arena= this; + thread_stack= 0; db= 0; catalog= (char*)"std"; // the only catalog we have for now main_security_ctx.init(); From dc8a5d54bd82659d81649176ece97878ba151214 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 24 Nov 2005 19:51:52 +0100 Subject: [PATCH 30/69] Remove t3 in join_nested.test mysql-test/r/join_nested.result: Remove t3 too. mysql-test/t/join_nested.test: Remove t3 too. --- mysql-test/r/join_nested.result | 2 +- mysql-test/t/join_nested.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/join_nested.result b/mysql-test/r/join_nested.result index b3ba5423421..6b7293d46bc 100644 --- a/mysql-test/r/join_nested.result +++ b/mysql-test/r/join_nested.result @@ -1466,4 +1466,4 @@ id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t4 ref a a 5 test.t3.b X 1 SIMPLE t6 ref a a 5 test.t4.b X 1 SIMPLE t5 ref a a 5 test.t3.b X -drop table t0, t1, t2, t4, t5, t6, t7; +drop table t0, t1, t2, t3, t4, t5, t6, t7; diff --git a/mysql-test/t/join_nested.test b/mysql-test/t/join_nested.test index 6e4e64bda9c..9f23e2d0e2f 100644 --- a/mysql-test/t/join_nested.test +++ b/mysql-test/t/join_nested.test @@ -899,4 +899,4 @@ explain select * from t2 left join (t3 left join (t4 join t6 on t6.a=t4.b) on t4.a=t3.b join t5 on t5.a=t3.b) on t3.a=t2.b; -drop table t0, t1, t2, t4, t5, t6, t7; +drop table t0, t1, t2, t3, t4, t5, t6, t7; From e1af5e5dfd302b03b12e897812ecbb7befb98c3d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Nov 2005 10:41:22 +0100 Subject: [PATCH 31/69] Updated expected error --- mysql-test/r/ndb_alter_table.result | 2 +- mysql-test/t/ndb_alter_table.test | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result index 62e8455ae9f..b5fceba7cee 100644 --- a/mysql-test/r/ndb_alter_table.result +++ b/mysql-test/r/ndb_alter_table.result @@ -179,7 +179,7 @@ a b c 2 two two alter table t1 drop index c; select * from t1 where b = 'two'; -ERROR HY000: Table definition has changed, please retry transaction +ERROR HY000: Can't lock file (errno: 241) select * from t1 where b = 'two'; a b c 2 two two diff --git a/mysql-test/t/ndb_alter_table.test b/mysql-test/t/ndb_alter_table.test index d89b81859e7..22383a82bca 100644 --- a/mysql-test/t/ndb_alter_table.test +++ b/mysql-test/t/ndb_alter_table.test @@ -149,7 +149,7 @@ connection server1; alter table t1 drop index c; connection server2; # This should fail since index information is not automatically refreshed ---error 1105 +--error 1015 select * from t1 where b = 'two'; select * from t1 where b = 'two'; connection server1; From 2a1ae3a5e3cbc7bb076c91ba0f8b5e6242319b28 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Nov 2005 13:25:31 +0300 Subject: [PATCH 32/69] A fix and a test case for Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP": make sure that 'typelib' object for ENUM values and 'Item_string' object for DEFAULT clause are created in the statement memory root. mysql-test/r/ps.result: Test results has been fixed (Bug#14410) mysql-test/t/ps.test: A test case for Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP" sql/mysql_priv.h: typelib() function declaration has been changed. sql/sql_table.cc: Supply the statement memory root to use in typelib() and safe_charset_converter() functions to ensure that objects created during the first execution of CREATE TABLE statement are allocated in persistent memory of the statement. sql/table.cc: Change typelib() function to require MEM_ROOT. --- mysql-test/r/ps.result | 19 +++++++++++++++++++ mysql-test/t/ps.test | 29 +++++++++++++++++++++++++++++ sql/mysql_priv.h | 2 +- sql/sql_table.cc | 29 +++++++++++++++++++++++++---- sql/table.cc | 6 +++--- 5 files changed, 77 insertions(+), 8 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f5bf3ffa96d..d46c2d5b3d5 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -699,3 +699,22 @@ execute stmt; @@tx_isolation REPEATABLE-READ deallocate prepare stmt; +prepare stmt from "create temporary table t1 (letter enum('','a','b','c') +not null)"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +set names latin1; +prepare stmt from "create table t1 (a enum('test') default 'test') + character set utf8"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +set names default; +deallocate prepare stmt; diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test index c4cb0056763..82dfc643801 100644 --- a/mysql-test/t/ps.test +++ b/mysql-test/t/ps.test @@ -718,4 +718,33 @@ set @@tx_isolation=default; execute stmt; deallocate prepare stmt; +# +# Bug#14410 "Crash in Enum or Set type in CREATE TABLE and PS/SP" +# +# Part I. Make sure the typelib for ENUM is created in the statement memory +# root. +prepare stmt from "create temporary table t1 (letter enum('','a','b','c') +not null)"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +# Part II. Make sure that when the default value is converted to UTF-8, +# the new item is # created in the statement memory root. +set names latin1; +prepare stmt from "create table t1 (a enum('test') default 'test') + character set utf8"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +# Cleanup +set names default; +deallocate prepare stmt; + # End of 4.1 tests + diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index a9057ae24f6..c128fac8d9e 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1119,7 +1119,7 @@ int calc_weekday(long daynr,bool sunday_first_day_of_week); uint calc_week(TIME *l_time, uint week_behaviour, uint *year); void find_date(char *pos,uint *vek,uint flag); TYPELIB *convert_strings_to_array_type(my_string *typelibs, my_string *end); -TYPELIB *typelib(List &strings); +TYPELIB *typelib(MEM_ROOT *mem_root, List &strings); ulong get_form_pos(File file, uchar *head, TYPELIB *save_names); ulong make_new_entry(File file,uchar *fileinfo,TYPELIB *formnames, const char *newname); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 0e0a05ea099..294c59af90f 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -524,7 +524,14 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, */ if (!interval) { - interval= sql_field->interval= typelib(sql_field->interval_list); + /* + Create the typelib in prepared statement memory if we're + executing one. + */ + MEM_ROOT *stmt_root= thd->current_arena->mem_root; + + interval= sql_field->interval= typelib(stmt_root, + sql_field->interval_list); List_iterator it(sql_field->interval_list); String conv, *tmp; for (uint i= 0; (tmp= it++); i++) @@ -534,7 +541,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, { uint cnv_errs; conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs); - char *buf= (char*) sql_alloc(conv.length()+1); + char *buf= (char*) alloc_root(stmt_root, conv.length()+1); memcpy(buf, conv.ptr(), conv.length()); buf[conv.length()]= '\0'; interval->type_names[i]= buf; @@ -556,8 +563,22 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, */ if (sql_field->def && cs != sql_field->def->collation.collation) { - if (!(sql_field->def= - sql_field->def->safe_charset_converter(cs))) + Item_arena backup_arena; + bool need_to_change_arena= + !thd->current_arena->is_conventional_execution(); + if (need_to_change_arena) + { + /* Asser that we don't do that at every PS execute */ + DBUG_ASSERT(thd->current_arena->is_first_stmt_execute()); + thd->set_n_backup_item_arena(thd->current_arena, &backup_arena); + } + + sql_field->def= sql_field->def->safe_charset_converter(cs); + + if (need_to_change_arena) + thd->restore_backup_item_arena(thd->current_arena, &backup_arena); + + if (! sql_field->def) { /* Could not convert */ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name); diff --git a/sql/table.cc b/sql/table.cc index 04d1a95cd9b..de539205ffd 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -1099,15 +1099,15 @@ fix_type_pointers(const char ***array, TYPELIB *point_to_type, uint types, } /* fix_type_pointers */ -TYPELIB *typelib(List &strings) +TYPELIB *typelib(MEM_ROOT *mem_root, List &strings) { - TYPELIB *result=(TYPELIB*) sql_alloc(sizeof(TYPELIB)); + TYPELIB *result= (TYPELIB*) alloc_root(mem_root, sizeof(TYPELIB)); if (!result) return 0; result->count=strings.elements; result->name=""; uint nbytes= (sizeof(char*) + sizeof(uint)) * (result->count + 1); - if (!(result->type_names= (const char**) sql_alloc(nbytes))) + if (!(result->type_names= (const char**) alloc_root(mem_root, nbytes))) return 0; result->type_lengths= (uint*) (result->type_names + result->count + 1); List_iterator it(strings); From 2e79201c727a593d93eae269e48e0240161525fd Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Nov 2005 18:53:55 +0300 Subject: [PATCH 33/69] Post-merge fixes. --- mysql-test/r/ndb_basic.result | 8 ++++---- mysql-test/r/ps.result | 19 +++++++++++++++++++ mysql-test/r/select.result | 8 ++++++++ sql/sql_table.cc | 15 +++++++-------- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result index e288592c390..55cbbd89b3c 100644 --- a/mysql-test/r/ndb_basic.result +++ b/mysql-test/r/ndb_basic.result @@ -667,13 +667,13 @@ counter datavalue 57 newval 58 newval drop table t1; +CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; +select * from t1; +b +drop table t1; create table atablewithareallylongandirritatingname (a int); insert into atablewithareallylongandirritatingname values (2); select * from atablewithareallylongandirritatingname; a 2 drop table atablewithareallylongandirritatingname; -CREATE TABLE t1 ( b INT ) PACK_KEYS = 0 ENGINE = ndb; -select * from t1; -b -drop table t1; diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f1c3672083d..742f68be445 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -806,3 +806,22 @@ execute stmt; @@tx_isolation REPEATABLE-READ deallocate prepare stmt; +prepare stmt from "create temporary table t1 (letter enum('','a','b','c') +not null)"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +set names latin1; +prepare stmt from "create table t1 (a enum('test') default 'test') + character set utf8"; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +execute stmt; +drop table t1; +set names default; +deallocate prepare stmt; diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index 8a126b7ddfb..e9348a6640f 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -2708,6 +2708,14 @@ select distinct count(f2) >0 from t1 left join t2 on f1=f3 group by f1; count(f2) >0 1 drop table t1,t2; +create table t1 (f1 int,f2 int); +insert into t1 values(1,1); +create table t2 (f3 int, f4 int, primary key(f3,f4)); +insert into t2 values(1,1); +select * from t1 where f1 in (select f3 from t2 where (f3,f4)= (select f3,f4 from t2)); +f1 f2 +1 1 +drop table t1,t2; CREATE TABLE t1 ( city char(30) ); INSERT INTO t1 VALUES ('London'); INSERT INTO t1 VALUES ('Paris'); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 03ed0fe4e66..949417dfa30 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -729,7 +729,7 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, Create the typelib in prepared statement memory if we're executing one. */ - MEM_ROOT *stmt_root= thd->current_arena->mem_root; + MEM_ROOT *stmt_root= thd->stmt_arena->mem_root; interval= sql_field->interval= typelib(stmt_root, sql_field->interval_list); @@ -763,21 +763,20 @@ static int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info, */ if (sql_field->def && cs != sql_field->def->collation.collation) { - Item_arena backup_arena; - bool need_to_change_arena= - !thd->current_arena->is_conventional_execution(); + Query_arena backup_arena; + bool need_to_change_arena= !thd->stmt_arena->is_conventional(); if (need_to_change_arena) { /* Asser that we don't do that at every PS execute */ - DBUG_ASSERT(thd->current_arena->is_first_stmt_execute() || - thd->current_arena->is_first_sp_execute()); - thd->set_n_backup_item_arena(thd->current_arena, &backup_arena); + DBUG_ASSERT(thd->stmt_arena->is_first_stmt_execute() || + thd->stmt_arena->is_first_sp_execute()); + thd->set_n_backup_active_arena(thd->stmt_arena, &backup_arena); } sql_field->def= sql_field->def->safe_charset_converter(cs); if (need_to_change_arena) - thd->restore_backup_item_arena(thd->current_arena, &backup_arena); + thd->restore_active_arena(thd->stmt_arena, &backup_arena); if (! sql_field->def) { From 08a4868bb66235db4d0011a26082067d1e368e92 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Nov 2005 20:47:22 +0300 Subject: [PATCH 34/69] BUG#15024: get_best_covering_ror_intersect() tries to build ROR-intersection by starting with an empty index set and adding indexes to it until it becomes covering. If the set becomes covering after adding the first index, return NULL and don't try constructing ROR-intersection of one index (which caused a crash) --- sql/opt_range.cc | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/opt_range.cc b/sql/opt_range.cc index 323e829f219..bf7eb370e42 100644 --- a/sql/opt_range.cc +++ b/sql/opt_range.cc @@ -3136,10 +3136,10 @@ TRP_ROR_INTERSECT *get_best_covering_ror_intersect(PARAM *param, /* F=F-covered by first(I) */ bitmap_union(&covered_fields, &(*ror_scan_mark)->covered_fields); all_covered= bitmap_is_subset(¶m->needed_fields, &covered_fields); - } while (!all_covered && (++ror_scan_mark < ror_scans_end)); - - if (!all_covered) - DBUG_RETURN(NULL); /* should not happen actually */ + } while ((++ror_scan_mark < ror_scans_end) && !all_covered); + + if (!all_covered || (ror_scan_mark - tree->ror_scans) == 1) + DBUG_RETURN(NULL); /* Ok, [tree->ror_scans .. ror_scan) holds covering index_intersection with From fd4fcd2f7ff58591f3e43a82d3d1dc50758bc8ab Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 25 Nov 2005 18:51:44 -0800 Subject: [PATCH 35/69] Fixed bug #15106. A typo bug caused loss of a predicate of the form field=const in some cases. mysql-test/r/select.result: Added a test case for bug #15106. mysql-test/t/select.test: Added a test case for bug #15106. --- mysql-test/r/select.result | 46 ++++++++++++++++++++++++++++++++++++++ mysql-test/t/select.test | 45 +++++++++++++++++++++++++++++++++++++ sql/item_cmpfunc.cc | 2 +- 3 files changed, 92 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result index e9348a6640f..598ea2b10d1 100644 --- a/mysql-test/r/select.result +++ b/mysql-test/r/select.result @@ -3291,3 +3291,49 @@ f1 f2 x1 30 1 30 drop table t1; drop view v1, v2, v3; +CREATE TABLE t1(key_a int4 NOT NULL, optimus varchar(32), PRIMARY KEY(key_a)); +CREATE TABLE t2(key_a int4 NOT NULL, prime varchar(32), PRIMARY KEY(key_a)); +CREATE table t3(key_a int4 NOT NULL, key_b int4 NOT NULL, foo varchar(32), +PRIMARY KEY(key_a,key_b)); +INSERT INTO t1 VALUES (0,''); +INSERT INTO t1 VALUES (1,'i'); +INSERT INTO t1 VALUES (2,'j'); +INSERT INTO t1 VALUES (3,'k'); +INSERT INTO t2 VALUES (1,'r'); +INSERT INTO t2 VALUES (2,'s'); +INSERT INTO t2 VALUES (3,'t'); +INSERT INTO t3 VALUES (1,5,'x'); +INSERT INTO t3 VALUES (1,6,'y'); +INSERT INTO t3 VALUES (2,5,'xx'); +INSERT INTO t3 VALUES (2,6,'yy'); +INSERT INTO t3 VALUES (2,7,'zz'); +INSERT INTO t3 VALUES (3,5,'xxx'); +SELECT t2.key_a,foo +FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a +INNER JOIN t3 ON t1.key_a = t3.key_a +WHERE t2.key_a=2 and key_b=5; +key_a foo +2 xx +EXPLAIN SELECT t2.key_a,foo +FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a +INNER JOIN t3 ON t1.key_a = t3.key_a +WHERE t2.key_a=2 and key_b=5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1 +SELECT t2.key_a,foo +FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a +INNER JOIN t3 ON t1.key_a = t3.key_a +WHERE t2.key_a=2 and key_b=5; +key_a foo +2 xx +EXPLAIN SELECT t2.key_a,foo +FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a +INNER JOIN t3 ON t1.key_a = t3.key_a +WHERE t2.key_a=2 and key_b=5; +id select_type table type possible_keys key key_len ref rows Extra +1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t2 const PRIMARY PRIMARY 4 const 1 Using index +1 SIMPLE t3 const PRIMARY PRIMARY 8 const,const 1 +DROP TABLE t1,t2,t3; diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test index 4eaa8eca052..a73d08f5f18 100644 --- a/mysql-test/t/select.test +++ b/mysql-test/t/select.test @@ -2760,3 +2760,48 @@ select f1, f2, v2.f1 as x1 from v2 order by v2.f1; select f1, f2, v3.f1 as x1 from v3 order by v3.f1; drop table t1; drop view v1, v2, v3; + +# +# Bug #15106: lost equality predicate of the form field=const in a join query +# + +CREATE TABLE t1(key_a int4 NOT NULL, optimus varchar(32), PRIMARY KEY(key_a)); +CREATE TABLE t2(key_a int4 NOT NULL, prime varchar(32), PRIMARY KEY(key_a)); +CREATE table t3(key_a int4 NOT NULL, key_b int4 NOT NULL, foo varchar(32), + PRIMARY KEY(key_a,key_b)); + +INSERT INTO t1 VALUES (0,''); +INSERT INTO t1 VALUES (1,'i'); +INSERT INTO t1 VALUES (2,'j'); +INSERT INTO t1 VALUES (3,'k'); + +INSERT INTO t2 VALUES (1,'r'); +INSERT INTO t2 VALUES (2,'s'); +INSERT INTO t2 VALUES (3,'t'); + +INSERT INTO t3 VALUES (1,5,'x'); +INSERT INTO t3 VALUES (1,6,'y'); +INSERT INTO t3 VALUES (2,5,'xx'); +INSERT INTO t3 VALUES (2,6,'yy'); +INSERT INTO t3 VALUES (2,7,'zz'); +INSERT INTO t3 VALUES (3,5,'xxx'); + +SELECT t2.key_a,foo + FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a + INNER JOIN t3 ON t1.key_a = t3.key_a + WHERE t2.key_a=2 and key_b=5; +EXPLAIN SELECT t2.key_a,foo + FROM t1 INNER JOIN t2 ON t1.key_a = t2.key_a + INNER JOIN t3 ON t1.key_a = t3.key_a + WHERE t2.key_a=2 and key_b=5; + +SELECT t2.key_a,foo + FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a + INNER JOIN t3 ON t1.key_a = t3.key_a + WHERE t2.key_a=2 and key_b=5; +EXPLAIN SELECT t2.key_a,foo + FROM t1 INNER JOIN t2 ON t2.key_a = t1.key_a + INNER JOIN t3 ON t1.key_a = t3.key_a + WHERE t2.key_a=2 and key_b=5; + +DROP TABLE t1,t2,t3; diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 2a7754c0217..ae8437674b2 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -3662,7 +3662,7 @@ void Item_equal::merge(Item_equal *item) the multiple equality already contains a constant and its value is not equal to the value of c. */ - add(const_item); + add(c); } cond_false|= item->cond_false; } From 94ab2caa6d1596c2be3a5d249622207f4d00579c Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Nov 2005 08:54:13 +0100 Subject: [PATCH 36/69] documenting HA_STATUS_xxx flags --- include/my_base.h | 49 +++++++++++++++++++++++++++++++------- sql/examples/ha_example.cc | 2 ++ sql/handler.h | 2 +- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/include/my_base.h b/include/my_base.h index ba3edfad0c8..a2d43304adf 100644 --- a/include/my_base.h +++ b/include/my_base.h @@ -260,15 +260,48 @@ enum ha_base_keytype { #define HA_CREATE_CHECKSUM 8 #define HA_CREATE_DELAY_KEY_WRITE 64 - /* Bits in flag to _status */ +/* + The following flags (OR-ed) are passed to handler::info() method. + The method copies misc handler information out of the storage engine + to data structures accessible from MySQL -#define HA_STATUS_POS 1 /* Return position */ -#define HA_STATUS_NO_LOCK 2 /* Don't use external lock */ -#define HA_STATUS_TIME 4 /* Return update time */ -#define HA_STATUS_CONST 8 /* Return constants values */ -#define HA_STATUS_VARIABLE 16 -#define HA_STATUS_ERRKEY 32 -#define HA_STATUS_AUTO 64 + Same flags are also passed down to mi_status, myrg_status, etc. +*/ + +/* this one is not used */ +#define HA_STATUS_POS 1 +/* + assuming the table keeps shared actual copy of the 'info' and + local, possibly outdated copy, the following flag means that + it should not try to get the actual data (locking the shared structure) + slightly outdated version will suffice +*/ +#define HA_STATUS_NO_LOCK 2 +/* update the time of the last modification (in handler::update_time) */ +#define HA_STATUS_TIME 4 +/* + update the 'constant' part of the info: + handler::max_data_file_length, max_index_file_length, create_time + sortkey, ref_length, block_size, data_file_name, index_file_name. + handler::table->s->keys_in_use, keys_for_keyread, rec_per_key +*/ +#define HA_STATUS_CONST 8 +/* + update the 'variable' part of the info: + handler::records, deleted, data_file_length, index_file_length, + delete_length, check_time, mean_rec_length +*/ +#define HA_STATUS_VARIABLE 16 +/* + get the information about the key that caused last duplicate value error + update handler::errkey and handler::dupp_ref + see handler::get_dup_key() +*/ +#define HA_STATUS_ERRKEY 32 +/* + update handler::auto_increment_value +*/ +#define HA_STATUS_AUTO 64 /* Errorcodes given by functions */ diff --git a/sql/examples/ha_example.cc b/sql/examples/ha_example.cc index d340b9289ec..471ece77490 100644 --- a/sql/examples/ha_example.cc +++ b/sql/examples/ha_example.cc @@ -480,6 +480,8 @@ int ha_example::rnd_pos(byte * buf, byte *pos) /* ::info() is used to return information to the optimizer. + see my_base.h for the complete description + Currently this table handler doesn't implement most of the fields really needed. SHOW also makes use of this data Another note, you will probably want to have the following in your diff --git a/sql/handler.h b/sql/handler.h index be188f7cacd..91c5be9ba39 100644 --- a/sql/handler.h +++ b/sql/handler.h @@ -672,7 +672,7 @@ public: key_range *max_key) { return (ha_rows) 10; } virtual void position(const byte *record)=0; - virtual void info(uint)=0; + virtual void info(uint)=0; // see my_base.h for full description virtual int extra(enum ha_extra_function operation) { return 0; } virtual int extra_opt(enum ha_extra_function operation, ulong cache_size) From 06887bc3304b4e6323ca8aa4c1d73d32b3f960c8 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Nov 2005 19:15:17 +0300 Subject: [PATCH 37/69] Enabled back bunch of tests for stored routines which were disabled earlier because of various features/checks missing (these features/checks are now implemented). mysql-test/r/sp.result: Enabled back bunch of tests which were previously disabled because of various features/checks missing (since these features/checks are now implemented). mysql-test/t/sp.test: Enabled back bunch of tests which were previously disabled because of various features/checks missing (since these features/checks are now implemented). --- mysql-test/r/sp.result | 126 ++++++++++++++++++++++++++++++++++++++++- mysql-test/t/sp.test | 65 ++++++++------------- 2 files changed, 148 insertions(+), 43 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 231ca329f3d..bb09bf62f40 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -988,6 +988,10 @@ end| select f5(1)| f5(1) 1 +select f5(2)| +ERROR HY000: Recursive stored functions and triggers are not allowed. +select f5(3)| +ERROR HY000: Recursive stored functions and triggers are not allowed. create function f6() returns int begin declare n int; @@ -1035,6 +1039,12 @@ select * from v1| ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them create function f1() returns int return (select sum(data) from t1) + (select sum(data) from v1)| +select f1()| +ERROR HY000: Recursive stored functions and triggers are not allowed. +select * from v1| +ERROR HY000: Recursive stored functions and triggers are not allowed. +select * from v2| +ERROR HY000: Recursive stored functions and triggers are not allowed. drop function f1| create function f1() returns int return (select sum(data) from t1)| @@ -1053,7 +1063,7 @@ f0() select *, f0() from v0| f0() f0() 100 100 -lock tables t1 read, t1 as t11 read, mysql.proc read| +lock tables t1 read, t1 as t11 read| select f3()| f3() 1 @@ -1251,6 +1261,62 @@ drop procedure opp| drop procedure ip| show procedure status like '%p%'| Db Name Type Definer Modified Created Security_type Comment +drop table if exists fib| +create table fib ( f bigint unsigned not null )| +drop procedure if exists fib| +create procedure fib(n int unsigned) +begin +if n > 1 then +begin +declare x, y bigint unsigned; +declare c cursor for select f from fib order by f desc limit 2; +open c; +fetch c into y; +fetch c into x; +close c; +insert into fib values (x+y); +call fib(n-1); +end; +end if; +end| +set @@max_sp_recursion_depth= 20| +insert into fib values (0), (1)| +call fib(3)| +select * from fib order by f asc| +f +0 +1 +1 +2 +delete from fib| +insert into fib values (0), (1)| +call fib(20)| +select * from fib order by f asc| +f +0 +1 +1 +2 +3 +5 +8 +13 +21 +34 +55 +89 +144 +233 +377 +610 +987 +1597 +2584 +4181 +6765 +drop table fib| +drop procedure fib| +set @@max_sp_recursion_depth= 0| drop procedure if exists bar| create procedure bar(x char(16), y int) comment "111111111111" sql security invoker @@ -1479,6 +1545,52 @@ select @x2| @x2 2 drop procedure bug2260| +drop procedure if exists bug2267_1| +create procedure bug2267_1() +begin +show procedure status; +end| +drop procedure if exists bug2267_2| +create procedure bug2267_2() +begin +show function status; +end| +drop procedure if exists bug2267_3| +create procedure bug2267_3() +begin +show create procedure bug2267_1; +end| +drop procedure if exists bug2267_4| +drop function if exists bug2267_4| +create procedure bug2267_4() +begin +show create function bug2267_4; +end| +create function bug2267_4() returns int return 100| +call bug2267_1()| +Db Name Type Definer Modified Created Security_type Comment +test bug2267_1 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +test bug2267_2 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +test bug2267_3 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +test bug2267_4 PROCEDURE root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +call bug2267_2()| +Db Name Type Definer Modified Created Security_type Comment +test bug2267_4 FUNCTION root@localhost 0000-00-00 00:00:00 0000-00-00 00:00:00 DEFINER +call bug2267_3()| +Procedure sql_mode Create Procedure +bug2267_1 CREATE PROCEDURE `bug2267_1`() +begin +show procedure status; +end +call bug2267_4()| +Function sql_mode Create Function +bug2267_4 CREATE FUNCTION `bug2267_4`() RETURNS int(11) +return 100 +drop procedure bug2267_1| +drop procedure bug2267_2| +drop procedure bug2267_3| +drop procedure bug2267_4| +drop function bug2267_4| drop procedure if exists bug2227| create procedure bug2227(x int) begin @@ -1490,6 +1602,18 @@ call bug2227(9)| 1.3 x y 42 z 1.3 9 2.6 42 zzz drop procedure bug2227| +drop procedure if exists bug2614| +create procedure bug2614() +begin +drop table if exists t3; +create table t3 (id int default '0' not null); +insert into t3 select 12; +insert into t3 select * from t3; +end| +call bug2614()| +call bug2614()| +drop table t3| +drop procedure bug2614| drop function if exists bug2674| create function bug2674() returns int return @@sort_buffer_size| diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index fba3cfcbfbc..d979c407b37 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -1211,15 +1211,13 @@ begin end if; end| select f5(1)| -# This should generate an error about insuficient number of tables locked -# Now this crash server ---disable_parsing # until bug#11394 fix ---error 1100 +# Since currently recursive functions are disallowed ER_SP_NO_RECURSION +# error will be returned, once we will allow them error about +# insufficient number of locked tables will be returned instead. +--error ER_SP_NO_RECURSION select f5(2)| -# But now it simply miserably fails because we are trying to use the same -# lex on the next iteration :/ It should generate some error too... +--error ER_SP_NO_RECURSION select f5(3)| ---enable_parsing # OTOH this should work create function f6() returns int @@ -1265,13 +1263,12 @@ select * from v1| # views and functions ? create function f1() returns int return (select sum(data) from t1) + (select sum(data) from v1)| -# This queries will crash server because we can't use LEX in -# reenterable fashion yet. Patch disabling recursion will heal this. ---disable_parsing +--error ER_SP_NO_RECURSION select f1()| +--error ER_SP_NO_RECURSION select * from v1| +--error ER_SP_NO_RECURSION select * from v2| ---enable_parsing # Back to the normal cases drop function f1| create function f1() returns int @@ -1289,9 +1286,7 @@ select *, f0() from v0| # # Let us test how well prelocking works with explicit LOCK TABLES. # -# Nowdays we have to lock mysql.proc to be able to read SP definitions. -# But Monty was going to fix this. -lock tables t1 read, t1 as t11 read, mysql.proc read| +lock tables t1 read, t1 as t11 read| # These should work well select f3()| select id, f3() from t1 as t11| @@ -1481,9 +1476,6 @@ show procedure status like '%p%'| # Fibonacci, for recursion test. (Yet Another Numerical series :) # -# This part of test is disabled until we implement support for -# recursive stored procedures. ---disable_parsing --disable_warnings drop table if exists fib| --enable_warnings @@ -1512,6 +1504,9 @@ begin end if; end| +# Enable recursion +set @@max_sp_recursion_depth= 20| + # Minimum test: recursion of 3 levels insert into fib values (0), (1)| @@ -1531,7 +1526,7 @@ call fib(20)| select * from fib order by f asc| drop table fib| drop procedure fib| ---enable_parsing +set @@max_sp_recursion_depth= 0| # # Comment & suid @@ -1800,16 +1795,8 @@ select @x2| drop procedure bug2260| # -# BUG#2267 +# BUG#2267 "Lost connect if stored procedure has SHOW FUNCTION STATUS" # -# NOTE: This test case will be fixed as soon as Monty -# will allow to open mysql.proc table under LOCK TABLES -# without mentioning in lock list. -# -# FIXME: Other solution would be to use preopened proc table -# instead of opening it anew. -# ---disable_parsing --disable_warnings drop procedure if exists bug2267_1| --enable_warnings @@ -1836,11 +1823,13 @@ end| --disable_warnings drop procedure if exists bug2267_4| +drop function if exists bug2267_4| --enable_warnings create procedure bug2267_4() begin - show create function fac; + show create function bug2267_4; end| +create function bug2267_4() returns int return 100| --replace_column 5 '0000-00-00 00:00:00' 6 '0000-00-00 00:00:00' call bug2267_1()| @@ -1853,7 +1842,7 @@ drop procedure bug2267_1| drop procedure bug2267_2| drop procedure bug2267_3| drop procedure bug2267_4| ---enable_parsing +drop function bug2267_4| # # BUG#2227 @@ -1873,23 +1862,16 @@ call bug2227(9)| drop procedure bug2227| # -# BUG#2614 +# BUG#2614 "Stored procedure with INSERT ... SELECT that does not +# contain any tables crashes server" # -# QQ The second insert doesn't work with temporary tables (it was an -# QQ ordinary table before we changed the locking scheme). It results -# QQ in an error: 1137: Can't reopen table: 't3' -# QQ which is a known limit with temporary tables. -# QQ For this reason we can't run this test any more (i.e., if we modify -# QQ it, it's no longer a test case for the bug), but we keep it here -# QQ anyway, for tracability. ---disable_parsing --disable_warnings drop procedure if exists bug2614| --enable_warnings create procedure bug2614() begin - drop temporary table if exists t3; - create temporary table t3 (id int default '0' not null); + drop table if exists t3; + create table t3 (id int default '0' not null); insert into t3 select 12; insert into t3 select * from t3; end| @@ -1898,9 +1880,8 @@ end| call bug2614()| --enable_warnings call bug2614()| -drop temporary table t3| +drop table t3| drop procedure bug2614| ---enable_parsing # # BUG#2674 From 8778a5df5ad07f16bc1bb07bed7a5b91ec82d740 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 26 Nov 2005 19:36:11 +0100 Subject: [PATCH 38/69] followup for for the bug#5686 --- myisam/ft_parser.c | 4 +++- mysql-test/r/fulltext.result | 3 +++ mysql-test/t/fulltext.test | 1 + 3 files changed, 7 insertions(+), 1 deletion(-) diff --git a/myisam/ft_parser.c b/myisam/ft_parser.c index 8e4769ebc75..fad8b5c4273 100644 --- a/myisam/ft_parser.c +++ b/myisam/ft_parser.c @@ -147,8 +147,10 @@ byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end, for (word->pos=doc; docprev='A'; /* be sure *prev is true_word_char */ word->len= (uint)(doc-word->pos) - mwc; diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result index 87551f96a13..ebd6880a10e 100644 --- a/mysql-test/r/fulltext.result +++ b/mysql-test/r/fulltext.result @@ -432,4 +432,7 @@ INSERT INTO t1 VALUES('testword\'\''); SELECT a FROM t1 WHERE MATCH a AGAINST('testword' IN BOOLEAN MODE); a testword'' +SELECT a FROM t1 WHERE MATCH a AGAINST('testword\'\'' IN BOOLEAN MODE); +a +testword'' DROP TABLE t1; diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test index 7c7927b638b..1399b9bfdff 100644 --- a/mysql-test/t/fulltext.test +++ b/mysql-test/t/fulltext.test @@ -354,6 +354,7 @@ SET myisam_repair_threads=@@global.myisam_repair_threads; # INSERT INTO t1 VALUES('testword\'\''); SELECT a FROM t1 WHERE MATCH a AGAINST('testword' IN BOOLEAN MODE); +SELECT a FROM t1 WHERE MATCH a AGAINST('testword\'\'' IN BOOLEAN MODE); DROP TABLE t1; # End of 4.1 tests From a9af48e9fc0b6bf91b272516dc8ec485b4faf7f3 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Nov 2005 12:41:44 +0400 Subject: [PATCH 39/69] item.cc, item.h: Fixing Item_param::safe_charset_converter to do less "new"s. sql/item.h: Fixing Item_param::safe_charset_converter to do less "new"s. sql/item.cc: Fixing Item_param::safe_charset_converter to do less "new"s. --- sql/item.cc | 26 ++++++++++---------------- sql/item.h | 4 ++++ 2 files changed, 14 insertions(+), 16 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 1767f9d97c1..0e45b8f2259 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -700,23 +700,15 @@ Item *Item_param::safe_charset_converter(CHARSET_INFO *tocs) { if (const_item()) { - Item_string *conv; uint cnv_errors; - char buf[MAX_FIELD_WIDTH]; - String tmp(buf, sizeof(buf), &my_charset_bin); - String cstr, *ostr= val_str(&tmp); - /* - As safe_charset_converter is not executed for - a parameter bound to NULL, ostr should never be 0. - */ - cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &cnv_errors); - if (cnv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(), - cstr.charset(), - collation.derivation))) - return NULL; - conv->str_value.copy(); - conv->str_value.mark_as_const(); - return conv; + String *ostr= val_str(&cnvstr); + cnvitem->str_value.copy(ostr->ptr(), ostr->length(), + ostr->charset(), tocs, &cnv_errors); + if (cnv_errors) + return NULL; + cnvitem->str_value.mark_as_const(); + cnvitem->max_length= cnvitem->str_value.numchars() * tocs->mbmaxlen; + return cnvitem; } return NULL; } @@ -2098,6 +2090,8 @@ Item_param::Item_param(unsigned pos_in_query_arg) : value is set. */ maybe_null= 1; + cnvitem= new Item_string("", 0, &my_charset_bin, DERIVATION_COERCIBLE); + cnvstr.set(cnvbuf, sizeof(cnvbuf), &my_charset_bin); } diff --git a/sql/item.h b/sql/item.h index 8bc659c3060..2b3a1ab3edb 100644 --- a/sql/item.h +++ b/sql/item.h @@ -1075,7 +1075,11 @@ public: class Item_param :public Item { + char cnvbuf[MAX_FIELD_WIDTH]; + String cnvstr; + Item *cnvitem; public: + enum enum_item_param_state { NO_VALUE, NULL_VALUE, INT_VALUE, REAL_VALUE, From 6cc4218f217de29de43aaae07f1137d9cdfb6e65 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Nov 2005 14:52:38 +0400 Subject: [PATCH 40/69] Fix for bug #12956: cast make differ rounding. sql/item_func.cc: Fix for bug #12956: cast make differ rounding. - call rint() as we do in the Field_*int*::store(double) --- mysql-test/r/ps.result | 14 +++++++------- mysql-test/t/count_distinct3.test | 2 +- sql/item_func.cc | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result index f1c3672083d..57272bda7d0 100644 --- a/mysql-test/r/ps.result +++ b/mysql-test/r/ps.result @@ -337,7 +337,7 @@ set @precision=10000000000; select rand(), cast(rand(10)*@precision as unsigned integer) from t1; rand() cast(rand(10)*@precision as unsigned integer) -- 6570515219 +- 6570515220 - 1282061302 - 6698761160 - 9647622201 @@ -348,23 +348,23 @@ prepare stmt from set @var=1; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 - +- 6570515220 - - 1282061302 - - 6698761160 - - 9647622201 - set @var=2; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 6555866465 -- 1282061302 1223466192 -- 6698761160 6449731873 +- 6570515220 6555866465 +- 1282061302 1223466193 +- 6698761160 6449731874 - 9647622201 8578261098 set @var=3; execute stmt using @var; rand() cast(rand(10)*@precision as unsigned integer) cast(rand(?)*@precision as unsigned integer) -- 6570515219 9057697559 +- 6570515220 9057697560 - 1282061302 3730790581 -- 6698761160 1480860534 +- 6698761160 1480860535 - 9647622201 6211931236 drop table t1; deallocate prepare stmt; diff --git a/mysql-test/t/count_distinct3.test b/mysql-test/t/count_distinct3.test index 52a4f271dac..f817b2c635d 100644 --- a/mysql-test/t/count_distinct3.test +++ b/mysql-test/t/count_distinct3.test @@ -17,7 +17,7 @@ while ($1) SET @rnd= RAND(); SET @id = CAST(@rnd * @rnd_max AS UNSIGNED); SET @id_rev= @rnd_max - @id; - SET @grp= CAST(128.0 * @rnd AS UNSIGNED); + SET @grp= CAST(127.0 * @rnd AS UNSIGNED); INSERT INTO t1 (id, grp, id_rev) VALUES (@id, @grp, @id_rev); dec $1; } diff --git a/sql/item_func.cc b/sql/item_func.cc index c20a774e57e..b4c4cf580cd 100644 --- a/sql/item_func.cc +++ b/sql/item_func.cc @@ -735,7 +735,7 @@ longlong Item_func_numhybrid::val_int() case INT_RESULT: return int_op(); case REAL_RESULT: - return (longlong)real_op(); + return (longlong) rint(real_op()); case STRING_RESULT: { int err_not_used; From 12de238b092c1d1d61b0707050e9fca841bd7243 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Nov 2005 17:06:57 +0400 Subject: [PATCH 41/69] grant.result: After merge fix. mysql-test/r/grant.result: After merge fix. --- mysql-test/r/grant.result | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result index a9f90e24556..448847bc919 100644 --- a/mysql-test/r/grant.result +++ b/mysql-test/r/grant.result @@ -594,3 +594,24 @@ flush privileges; set @user123="non-existent"; select * from mysql.db where user=@user123; Host Db User Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Grant_priv References_priv Index_priv Alter_priv Create_tmp_table_priv Lock_tables_priv Create_view_priv Show_view_priv Create_routine_priv Alter_routine_priv Execute_priv +set names koi8r; +create database бд; +grant select on бд.* to root@localhost; +select hex(Db) from mysql.db where Db='бд'; +hex(Db) +D0B1D0B4 +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT SELECT ON `бд`.* TO 'root'@'localhost' +flush privileges; +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +GRANT SELECT ON `бд`.* TO 'root'@'localhost' +drop database бд; +revoke all privileges on бд.* from root@localhost; +show grants for root@localhost; +Grants for root@localhost +GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION +set names latin1; From baff781ba45b7aac77a3efdcfc3bb8d5ef9e9135 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Nov 2005 15:07:20 +0100 Subject: [PATCH 42/69] Minor Win32 compile fixes for 4.1.16 release. sql/log_event.cc: Add missing cast needed for Win32 compilation. include/config-win.h: Win32 compile fix: quote multi-line macros with do { ... } while(0) to follow earlier changes in my_global.h. --- include/config-win.h | 8 ++++---- sql/log_event.cc | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/include/config-win.h b/include/config-win.h index 9663947683e..e1972051e67 100644 --- a/include/config-win.h +++ b/include/config-win.h @@ -278,10 +278,10 @@ inline double ulonglong2double(ulonglong value) *((T)+4)=(uchar) (((A) >> 32)); } #define int8store(T,A) *((ulonglong *) (T))= (ulonglong) (A) -#define doubleget(V,M) { *((long *) &V) = *((long*) M); \ - *(((long *) &V)+1) = *(((long*) M)+1); } -#define doublestore(T,V) { *((long *) T) = *((long*) &V); \ - *(((long *) T)+1) = *(((long*) &V)+1); } +#define doubleget(V,M) do { *((long *) &V) = *((long*) M); \ + *(((long *) &V)+1) = *(((long*) M)+1); } while(0) +#define doublestore(T,V) do { *((long *) T) = *((long*) &V); \ + *(((long *) T)+1) = *(((long*) &V)+1); } while(0) #define float4get(V,M) { *((long *) &(V)) = *((long*) (M)); } #define floatget(V,M) memcpy((byte*) &V,(byte*) (M),sizeof(float)) #define floatstore(T,V) memcpy((byte*)(T), (byte*)(&V), sizeof(float)) diff --git a/sql/log_event.cc b/sql/log_event.cc index be4654bccd3..3f545df5776 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -2035,7 +2035,7 @@ Rotate_log_event::Rotate_log_event(THD* thd_arg, llstr(pos_arg, buff), flags)); #endif if (flags & DUP_NAME) - new_log_ident= my_strdup_with_length(new_log_ident_arg, + new_log_ident= my_strdup_with_length((byte*) new_log_ident_arg, ident_len, MYF(MY_WME)); DBUG_VOID_RETURN; From c565ca2bf2a0e36df5587433446640de3c9d45cd Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Nov 2005 16:28:00 +0100 Subject: [PATCH 43/69] Include libyassl.la and libtaocrypt.la in libmysqlclient.la config/ac-macros/yassl.m4: Specify path to yassl libs libmysql/Makefile.am: Add yassl .la libs to libmysqlclient.la --- config/ac-macros/yassl.m4 | 2 ++ libmysql/Makefile.am | 4 ++-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/config/ac-macros/yassl.m4 b/config/ac-macros/yassl.m4 index d1216554862..77208faee0c 100644 --- a/config/ac-macros/yassl.m4 +++ b/config/ac-macros/yassl.m4 @@ -17,6 +17,7 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ yassl_dir="extra/yassl" yassl_libs="-L\$(top_srcdir)/extra/yassl/src -lyassl -L\$(top_srcdir)/extra/yassl/taocrypt/src -ltaocrypt" yassl_includes="-I\$(top_srcdir)/extra/yassl/include" + yassl_libs_with_path="\$(top_srcdir)/extra/yassl/src/libyassl.la \$(top_srcdir)/extra/yassl/taocrypt/src/libtaocrypt.la" AC_DEFINE([HAVE_OPENSSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) AC_DEFINE([HAVE_YASSL], [1], [Defined by configure. Using yaSSL for OpenSSL emulation.]) # System specific checks @@ -35,6 +36,7 @@ AC_DEFUN([MYSQL_CHECK_YASSL], [ AC_MSG_RESULT(no) fi AC_SUBST(yassl_libs) + AC_SUBST(yassl_libs_with_path) AC_SUBST(yassl_includes) AC_SUBST(yassl_dir) AM_CONDITIONAL([HAVE_YASSL], [ test "with_yassl" = "yes" ]) diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am index 319a9913255..a3e16b521a9 100644 --- a/libmysql/Makefile.am +++ b/libmysql/Makefile.am @@ -22,14 +22,14 @@ target = libmysqlclient.la target_defs = -DUNDEF_THREADS_HACK -DDONT_USE_RAID @LIB_EXTRA_CCFLAGS@ -LIBS = @CLIENT_LIBS@ @yassl_libs@ +LIBS = @CLIENT_LIBS@ INCLUDES = -I$(top_builddir)/include -I$(top_srcdir)/include \ $(openssl_includes) $(yassl_includes) @ZLIB_INCLUDES@ include $(srcdir)/Makefile.shared libmysqlclient_la_SOURCES = $(target_sources) -libmysqlclient_la_LIBADD = $(target_libadd) +libmysqlclient_la_LIBADD = $(target_libadd) $(yassl_libs_with_path) libmysqlclient_la_LDFLAGS = $(target_ldflags) EXTRA_DIST = Makefile.shared libmysql.def noinst_HEADERS = client_settings.h From afaf1fd3a34d9cd0203ed07d9ae0f269e53d944b Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 28 Nov 2005 22:15:43 +0300 Subject: [PATCH 44/69] Changed mysqld.dsp to avoid compilation error in VC++ VC++Files/sql/mysqld.dsp: Corrected wrong path to ha_archive.cpp (causes compilation error in VC++) --- VC++Files/sql/mysqld.dsp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp index 7a9ad3e1c76..817e3224ea4 100644 --- a/VC++Files/sql/mysqld.dsp +++ b/VC++Files/sql/mysqld.dsp @@ -456,7 +456,7 @@ SOURCE=.\gstream.cpp # End Source File # Begin Source File -SOURCE=.\examples\ha_archive.cpp +SOURCE=.\ha_archive.cpp # End Source File # Begin Source File From 9e33fc73aed7649c518c6f3bd9c9aaf181215411 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Nov 2005 12:15:48 +0400 Subject: [PATCH 45/69] Fix for bug#14221 SSL support breaks going from OpenSSL 0.9.7i to 0.9.8a added SSL_library_init() --- vio/viosslfactories.c | 21 ++++++++++----------- 1 file changed, 10 insertions(+), 11 deletions(-) diff --git a/vio/viosslfactories.c b/vio/viosslfactories.c index 498d10da0ee..46306cf48bb 100644 --- a/vio/viosslfactories.c +++ b/vio/viosslfactories.c @@ -191,9 +191,6 @@ void netware_ssl_cleanup() /* NetWare SSL initialization */ static void netware_ssl_init() { - /* initialize OpenSSL library */ - SSL_library_init(); - /* cleanup OpenSSL library */ NXVmRegisterExitHandler(netware_ssl_cleanup, NULL); } @@ -231,16 +228,17 @@ new_VioSSLConnectorFd(const char* key_file, ptr->ssl_method= 0; /* FIXME: constants! */ -#ifdef __NETWARE__ - netware_ssl_init(); -#endif - if (!ssl_algorithms_added) { DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); ssl_algorithms_added = TRUE; + SSL_library_init(); OpenSSL_add_all_algorithms(); } +#ifdef __NETWARE__ + netware_ssl_init(); +#endif + if (!ssl_error_strings_loaded) { DBUG_PRINT("info", ("todo:SSL_load_error_strings()")); @@ -325,17 +323,18 @@ new_VioSSLAcceptorFd(const char *key_file, /* FIXME: constants! */ ptr->session_id_context= ptr; -#ifdef __NETWARE__ - netware_ssl_init(); -#endif - if (!ssl_algorithms_added) { DBUG_PRINT("info", ("todo: OpenSSL_add_all_algorithms()")); ssl_algorithms_added = TRUE; + SSL_library_init(); OpenSSL_add_all_algorithms(); } +#ifdef __NETWARE__ + netware_ssl_init(); +#endif + if (!ssl_error_strings_loaded) { DBUG_PRINT("info", ("todo: SSL_load_error_strings()")); From c6f9e7bf6e67377ff178439673d5fb1744a65a6b Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Nov 2005 13:42:45 +0100 Subject: [PATCH 46/69] Moved long running query to type_newdecimal-big.test Removed warnings that depends on floating point comparisions in type_newdecimal.test which caused failures in some setups [Backported from mysql-5.1-new @1.1961.1.1] mysql-test/r/type_newdecimal.result: Moved long running query to type_newdecimal-big.test Removed warnings that depends on floating point comparisions [Backported from mysql-5.1-new] mysql-test/t/type_newdecimal.test: Moved long running query to type_newdecimal-big.test Removed warnings that depends on floating point comparisions [Backported from mysql-5.1-new] --- mysql-test/r/type_newdecimal-big.result | 11 +++++ mysql-test/r/type_newdecimal.result | 56 ---------------------- mysql-test/t/type_newdecimal-big.test | 31 ++++++++++++ mysql-test/t/type_newdecimal.test | 64 ++++++++++--------------- 4 files changed, 66 insertions(+), 96 deletions(-) create mode 100644 mysql-test/r/type_newdecimal-big.result create mode 100644 mysql-test/t/type_newdecimal-big.test diff --git a/mysql-test/r/type_newdecimal-big.result b/mysql-test/r/type_newdecimal-big.result new file mode 100644 index 00000000000..e95f2f3f781 --- /dev/null +++ b/mysql-test/r/type_newdecimal-big.result @@ -0,0 +1,11 @@ +drop procedure if exists sp1; +create procedure sp1 () begin +declare v1, v2, v3, v4 decimal(16,12); declare v5 int; +set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; +while v5 < 100000 do +set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; +end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// +call sp1()// +v1 v2 v3 * 0.000000000001 v4 * 0.000000000001 +1.000000100000 1.999999900000 1.000000100000 1.999999900000 +drop procedure sp1; diff --git a/mysql-test/r/type_newdecimal.result b/mysql-test/r/type_newdecimal.result index 7d7fe7efa35..938dccc864c 100644 --- a/mysql-test/r/type_newdecimal.result +++ b/mysql-test/r/type_newdecimal.result @@ -678,16 +678,6 @@ select -18.3=18.3; select 0.8 = 0.7 + 0.1; 0.8 = 0.7 + 0.1 1 -create procedure p1 () begin -declare v1, v2, v3, v4 decimal(16,12); declare v5 int; -set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; -while v5 < 100000 do -set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; -end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// -call p1()// -v1 v2 v3 * 0.000000000001 v4 * 0.000000000001 -1.000000100000 1.999999900000 1.000000100000 1.999999900000 -drop procedure p1; drop table if exists t1; Warnings: Note 1051 Unknown table 't1' @@ -1267,34 +1257,6 @@ CAST(my_varchar AS DECIMAL(65,30)) my_varchar 0.011754943450000000000000000000 1.175494345e-2 0.117549434500000000000000000000 1.175494345e-1 UPDATE t1 SET my_decimal = my_float; -Warnings: -Note 1265 Data truncated for column 'my_decimal' at row 1 -Note 1265 Data truncated for column 'my_decimal' at row 2 -Note 1265 Data truncated for column 'my_decimal' at row 3 -Note 1265 Data truncated for column 'my_decimal' at row 4 -Note 1265 Data truncated for column 'my_decimal' at row 5 -Note 1265 Data truncated for column 'my_decimal' at row 6 -Note 1265 Data truncated for column 'my_decimal' at row 7 -Note 1265 Data truncated for column 'my_decimal' at row 8 -Note 1265 Data truncated for column 'my_decimal' at row 9 -Note 1265 Data truncated for column 'my_decimal' at row 10 -Note 1265 Data truncated for column 'my_decimal' at row 11 -Note 1265 Data truncated for column 'my_decimal' at row 12 -Note 1265 Data truncated for column 'my_decimal' at row 13 -Note 1265 Data truncated for column 'my_decimal' at row 14 -Note 1265 Data truncated for column 'my_decimal' at row 15 -Note 1265 Data truncated for column 'my_decimal' at row 16 -Note 1265 Data truncated for column 'my_decimal' at row 17 -Note 1265 Data truncated for column 'my_decimal' at row 19 -Note 1265 Data truncated for column 'my_decimal' at row 20 -Note 1265 Data truncated for column 'my_decimal' at row 21 -Note 1265 Data truncated for column 'my_decimal' at row 22 -Note 1265 Data truncated for column 'my_decimal' at row 23 -Note 1265 Data truncated for column 'my_decimal' at row 26 -Note 1265 Data truncated for column 'my_decimal' at row 27 -Note 1265 Data truncated for column 'my_decimal' at row 30 -Note 1265 Data truncated for column 'my_decimal' at row 31 -Note 1265 Data truncated for column 'my_decimal' at row 32 SELECT my_decimal, my_float FROM t1; my_decimal my_float 0.000000000000000000000000000000 1.17549e-32 @@ -1330,24 +1292,6 @@ my_decimal my_float 0.011754943057894710000000000000 0.0117549 0.117549434304237400000000000000 0.117549 UPDATE t1 SET my_decimal = my_double; -Warnings: -Note 1265 Data truncated for column 'my_decimal' at row 1 -Note 1265 Data truncated for column 'my_decimal' at row 2 -Note 1265 Data truncated for column 'my_decimal' at row 3 -Note 1265 Data truncated for column 'my_decimal' at row 4 -Note 1265 Data truncated for column 'my_decimal' at row 5 -Note 1265 Data truncated for column 'my_decimal' at row 6 -Note 1265 Data truncated for column 'my_decimal' at row 7 -Note 1265 Data truncated for column 'my_decimal' at row 8 -Note 1265 Data truncated for column 'my_decimal' at row 9 -Note 1265 Data truncated for column 'my_decimal' at row 10 -Note 1265 Data truncated for column 'my_decimal' at row 11 -Note 1265 Data truncated for column 'my_decimal' at row 13 -Note 1265 Data truncated for column 'my_decimal' at row 14 -Note 1265 Data truncated for column 'my_decimal' at row 16 -Note 1265 Data truncated for column 'my_decimal' at row 18 -Note 1265 Data truncated for column 'my_decimal' at row 20 -Note 1265 Data truncated for column 'my_decimal' at row 31 SELECT my_decimal, my_double FROM t1; my_decimal my_double 0.000000000000000000000000000000 1.175494345e-32 diff --git a/mysql-test/t/type_newdecimal-big.test b/mysql-test/t/type_newdecimal-big.test new file mode 100644 index 00000000000..e200017f2ba --- /dev/null +++ b/mysql-test/t/type_newdecimal-big.test @@ -0,0 +1,31 @@ +--source include/big_test.inc + +--disable_warnings +drop procedure if exists sp1; +--enable_warnings + +# +#-- 2. Adding (one millionth) one million times should be the same as +#-- adding 1. So a stored procedure with many iterations will show if +#-- small errors accumulate. +# + +delimiter //; +# +create procedure sp1 () begin + declare v1, v2, v3, v4 decimal(16,12); declare v5 int; + set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; + while v5 < 100000 do + set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; + end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// +# +call sp1()// +#-- should return +# -- v1=1.0000001 +# -- v2=1.999999900000 +# -- v3=1.0000001 +# -- v4=1.999999900000 +# +delimiter ;// +# +drop procedure sp1; diff --git a/mysql-test/t/type_newdecimal.test b/mysql-test/t/type_newdecimal.test index ad71ffa02e5..e2fe9767432 100644 --- a/mysql-test/t/type_newdecimal.test +++ b/mysql-test/t/type_newdecimal.test @@ -473,7 +473,7 @@ drop table wl1612_4; # #-- Additional tests for WL#1612 Precision math # -#-- 1. Comparisons should show that a number is +#-- Comparisons should show that a number is #-- exactly equal to its value as displayed. # set sql_mode=''; @@ -487,34 +487,9 @@ select 18.3=18.3; select -18.3=18.3; # select 0.8 = 0.7 + 0.1; + # -#-- 2. Adding (one millionth) one million times should be the same as -#-- adding 1. So a stored procedure with many iterations will show if -#-- small errors accumulate. -# -#drop procedure p1; -# -delimiter //; -# -create procedure p1 () begin - declare v1, v2, v3, v4 decimal(16,12); declare v5 int; - set v1 = 1; set v2 = 2; set v3 = 1000000000000; set v4 = 2000000000000; set v5 = 0; - while v5 < 100000 do - set v1 = v1 + 0.000000000001; set v2 = v2 - 0.000000000001; set v3 = v3 + 1; set v4 = v4 - 1; set v5 = v5 + 1; - end while; select v1, v2, v3 * 0.000000000001, v4 * 0.000000000001; end;// -# -call p1()// -#-- should return -# -- v1=1.0000001 -# -- v2=1.999999900000 -# -- v3=1.0000001 -# -- v4=1.999999900000 -# -delimiter ;// -# -drop procedure p1; -# -#-- 3. It should be possible to define a column +#-- It should be possible to define a column #-- with up to 38 digits precision either before #-- or after the decimal point. Any number which #-- is inserted, if it's within the range, should @@ -565,7 +540,7 @@ select * from t1; # drop table t1; # -#-- 4. The usual arithmetic operators / * + - should work. +#-- The usual arithmetic operators / * + - should work. # #select 77777777777777777777777777777777777777 / 7777777777777777777777777777777777777 = 10; #-- should return 0 (false). @@ -668,7 +643,7 @@ select truncate(99999999999999999999999999999999999999,-31); #drop procedure p1; #drop table t1; # -#-- 7. When I say DECIMAL(x) I should be able to store x digits. +#-- When I say DECIMAL(x) I should be able to store x digits. #-- If I can't, there should be an error at CREATE time. # #drop table if exists t1; @@ -676,7 +651,8 @@ select truncate(99999999999999999999999999999999999999,-31); #create table t1 (col1 decimal(254)); #-- should return SQLSTATE 22003 numeric value out of range # -#-- 8. When I say DECIMAL(x,y) there should be no silent change of precision or scale. +#-- When I say DECIMAL(x,y) there should be no silent change of precision or +#-- scale. # #drop table if exists t1; # @@ -694,7 +670,7 @@ select truncate(99999999999999999999999999999999999999,-31); # #drop table t1; # -#-- 9. From WL#1612 "The future" point 2.: +#-- From WL#1612 "The future" point 2.: #-- The standard requires that we treat numbers like "0.5" as #-- DECIMAL or NUMERIC, not as floating-point. # @@ -715,7 +691,7 @@ show create table t1; # drop table t1; # -#-- 10. From WL#1612, "The future", point 3.: We have to start rounding correctly. +#-- From WL#1612, "The future", point 3.: We have to start rounding correctly. # select round(1.5),round(2.5); #-- should return: @@ -725,13 +701,13 @@ select round(1.5),round(2.5); #| 2 | 3 | #+------------+------------+ # -#-- 11. From WL#1612, "The future", point 4.: "select 0.07 * 0.07;" should return 0.0049, not 0.00. +#-- From WL#1612, "The future", point 4.: "select 0.07 * 0.07;" should return 0.0049, not 0.00. #-- If operand#1 has scale X and operand#2 has scale Y, then result should have scale (X+Y). # select 0.07 * 0.07; #-- should return 0.0049 # -#-- 12. From WL#1612, "The future", point 5.: Division by zero is an error. +#-- From WL#1612, "The future", point 5.: Division by zero is an error. # set sql_mode='traditional'; # @@ -752,7 +728,7 @@ select 1 / 0; #+-------+ #1 row in set, 1 warning (0.00 sec) # -#-- 13. From WL#1612 "The future" point 6.: Overflow is an error. +#-- From WL#1612 "The future" point 6.: Overflow is an error. # #set sql_mode=''; # @@ -793,7 +769,8 @@ select 1 / 0; #drop table t2; #drop table t1; # -#-- 15. From WL#1612 "The future" point 8.: Stop storing leading "+" signs and leading "0"s. +#-- From WL#1612 "The future" point 8.: Stop storing leading "+" signs and +# leading "0"s. # #drop table if exists t1; # @@ -805,7 +782,7 @@ select 1 / 0; # #drop table t1; # -#-- 16. From WL#1612, The future" point 9.: +#-- From WL#1612, The future" point 9.: #-- Accept the data type and precision and scale as the user #-- asks, or return an error, but don't change to something else. # @@ -817,7 +794,7 @@ select 1 / 0; # #drop table t1; # -#-- 17. The scripts in the following bugs should work: +#-- The scripts in the following bugs should work: # #BUG#559 Maximum precision for DECIMAL column ... @@ -833,7 +810,7 @@ select 1 / 0; #BUG#6048 Stored procedure causes operating system reboot #BUG#6053 DOUBLE PRECISION literal --- 18. Tests from 'traditional' mode tests +-- Tests from 'traditional' mode tests # set sql_mode='ansi,traditional'; # @@ -1077,10 +1054,17 @@ SELECT CAST(my_float AS DECIMAL(65,30)), my_float FROM t1; SELECT CAST(my_double AS DECIMAL(65,30)), my_double FROM t1; SELECT CAST(my_varchar AS DECIMAL(65,30)), my_varchar FROM t1; +# We have to disable warnings here as the test in +# Field_new_decimal::store(double): +# if (nr2 != nr) +# fails randomly depending on compiler options + +--disable_warnings UPDATE t1 SET my_decimal = my_float; SELECT my_decimal, my_float FROM t1; UPDATE t1 SET my_decimal = my_double; SELECT my_decimal, my_double FROM t1; +--enable_warnings UPDATE t1 SET my_decimal = my_varchar; SELECT my_decimal, my_varchar FROM t1; From 2985bc7a4d73501a202393f40836eea370943692 Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Nov 2005 16:46:51 +0400 Subject: [PATCH 47/69] test fixed mysql-test/r/type_ranges.result: result fixed --- mysql-test/r/type_ranges.result | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index ff07dcca106..bcdba3dca76 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -215,7 +215,7 @@ Field Type Collation Null Key Default Extra Privileges Comment auto int(5) unsigned NULL NO MUL NULL auto_increment # string char(10) latin1_swedish_ci YES newdefault # tiny tinyint(4) NULL NO MUL 0 # -short smallint(6) NULL NO MUL 0 # +short smallint(6) NULL NO MUL # medium mediumint(8) NULL NO MUL 0 # long_int int(11) NULL NO 0 # longlong bigint(13) NULL NO MUL 0 # From d54359ffdada0d949931c7cbe1ba816c3724d49f Mon Sep 17 00:00:00 2001 From: unknown Date: Tue, 29 Nov 2005 18:06:58 +0400 Subject: [PATCH 48/69] Addition to fix for bug #12956: cast make differ rounding. - use rint() in some other val_int() methods as well. --- sql/field.cc | 4 ++-- sql/item.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sql/field.cc b/sql/field.cc index b70e2a92618..6de2a731030 100644 --- a/sql/field.cc +++ b/sql/field.cc @@ -3953,7 +3953,7 @@ longlong Field_float::val_int(void) else #endif memcpy_fixed((byte*) &j,ptr,sizeof(j)); - return ((longlong) j); + return (longlong) rint(j); } @@ -4241,7 +4241,7 @@ longlong Field_double::val_int(void) else #endif doubleget(j,ptr); - return ((longlong) j); + return (longlong) rint(j); } diff --git a/sql/item.h b/sql/item.h index 3c03cd23e2c..718b995bc5a 100644 --- a/sql/item.h +++ b/sql/item.h @@ -159,7 +159,7 @@ struct Hybrid_type_traits { val->real/= ulonglong2double(u); } virtual longlong val_int(Hybrid_type *val, bool unsigned_flag) const - { return (longlong) val->real; } + { return (longlong) rint(val->real); } virtual double val_real(Hybrid_type *val) const { return val->real; } virtual my_decimal *val_decimal(Hybrid_type *val, my_decimal *buf) const; virtual String *val_str(Hybrid_type *val, String *buf, uint8 decimals) const; @@ -1341,7 +1341,7 @@ public: { return LONGLONG_MAX; } - return (longlong) (value+(value > 0 ? 0.5 : -0.5)); + return (longlong) rint(value); } String *val_str(String*); my_decimal *val_decimal(my_decimal *); From 490a1e2855078d661b584ef690a05ca4defceebd Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Nov 2005 11:17:25 +0400 Subject: [PATCH 49/69] Addition to fix for bug #12956: cast make differ rounding. - use rint() in some other val_int() methods as well. --- sql/item.cc | 4 ++-- sql/item_func.h | 4 ++-- sql/item_sum.cc | 6 +++--- sql/item_sum.h | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/sql/item.cc b/sql/item.cc index 94dea1a7dd7..8a55049df84 100644 --- a/sql/item.cc +++ b/sql/item.cc @@ -2467,7 +2467,7 @@ longlong Item_param::val_int() { switch (state) { case REAL_VALUE: - return (longlong) (value.real + (value.real > 0 ? 0.5 : -0.5)); + return (longlong) rint(value.real); case INT_VALUE: return value.integer; case DECIMAL_VALUE: @@ -5439,7 +5439,7 @@ void Item_cache_real::store(Item *item) longlong Item_cache_real::val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) (value+(value > 0 ? 0.5 : -0.5)); + return (longlong) rint(value); } diff --git a/sql/item_func.h b/sql/item_func.h index ed39cb86d3e..76647fd5cb2 100644 --- a/sql/item_func.h +++ b/sql/item_func.h @@ -199,7 +199,7 @@ public: String *val_str(String*str); my_decimal *val_decimal(my_decimal *decimal_value); longlong val_int() - { DBUG_ASSERT(fixed == 1); return (longlong) val_real(); } + { DBUG_ASSERT(fixed == 1); return (longlong) rint(val_real()); } enum Item_result result_type () const { return REAL_RESULT; } void fix_length_and_dec() { decimals= NOT_FIXED_DEC; max_length= float_length(decimals); } @@ -943,7 +943,7 @@ class Item_func_udf_float :public Item_udf_func longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) Item_func_udf_float::val_real(); + return (longlong) rint(Item_func_udf_float::val_real()); } my_decimal *val_decimal(my_decimal *dec_buf) { diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 506d2a16108..626eb63d04f 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -452,7 +452,7 @@ longlong Item_sum_sum::val_int() &result); return result; } - return (longlong) val_real(); + return (longlong) rint(val_real()); } @@ -1285,7 +1285,7 @@ longlong Item_sum_hybrid::val_int() return sum_int; } default: - return (longlong) Item_sum_hybrid::val_real(); + return (longlong) rint(Item_sum_hybrid::val_real()); } } @@ -2001,7 +2001,7 @@ double Item_avg_field::val_real() longlong Item_avg_field::val_int() { - return (longlong) val_real(); + return (longlong) rint(val_real()); } diff --git a/sql/item_sum.h b/sql/item_sum.h index 87cc248e5e4..2c2bcedab9b 100644 --- a/sql/item_sum.h +++ b/sql/item_sum.h @@ -126,7 +126,7 @@ public: longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) val_real(); /* Real as default */ + return (longlong) rint(val_real()); /* Real as default */ } String *val_str(String*str); my_decimal *val_decimal(my_decimal *); @@ -392,7 +392,7 @@ public: bool add(); double val_real(); // In SPs we might force the "wrong" type with select into a declare variable - longlong val_int() { return (longlong)val_real(); } + longlong val_int() { return (longlong) rint(val_real()); } my_decimal *val_decimal(my_decimal *); String *val_str(String *str); void reset_field(); @@ -421,7 +421,7 @@ public: enum Type type() const {return FIELD_VARIANCE_ITEM; } double val_real(); longlong val_int() - { /* can't be fix_fields()ed */ return (longlong) val_real(); } + { /* can't be fix_fields()ed */ return (longlong) rint(val_real()); } String *val_str(String*); my_decimal *val_decimal(my_decimal *); bool is_null() { (void) val_int(); return null_value; } @@ -699,7 +699,7 @@ class Item_sum_udf_float :public Item_udf_sum longlong val_int() { DBUG_ASSERT(fixed == 1); - return (longlong) Item_sum_udf_float::val_real(); + return (longlong) rint(Item_sum_udf_float::val_real()); } double val_real(); String *val_str(String*str); From e3f575522824ee79ade046cf96f4f3679d68c1a3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Nov 2005 12:52:12 +0200 Subject: [PATCH 50/69] Fix for BUG#14920 Ordering aggregated result sets corrupts resultset. The cause of the bug was the use of end_write_group instead of end_write in the case when ORDER BY required a temporary table, which didn't take into account the fact that loose index scan already computes the result of MIN/MAX aggregate functions (and performs grouping). The solution is to call end_write instead of end_write_group and to add the MIN/MAX functions to the list of regular functions so that their values are inserted into the temporary table. mysql-test/r/group_min_max.result: Test for BUG#14920 mysql-test/t/group_min_max.test: Test for BUG#14920 sql/sql_class.cc: Added new member to TMP_TABLE_PARAM. sql/sql_class.h: Added new member to TMP_TABLE_PARAM. sql/sql_select.cc: Enable result rows generated by loose index scan being written into a temporary table. The change is necessary because loose index scan already computes the result of GROUP BY and the MIN/MAX aggregate functions. This is realized by three changes: - create_tmp_table allocates space for aggregate functions in the list of regular functions, - use end_write instead of end_write group, - copy the pointers to the MIN/MAX aggregate functions to the list of regular functions TMP_TABLE_PARAM::items_to_copy. sql/sql_select.h: New parameter to create_tmp_table. --- mysql-test/r/group_min_max.result | 31 +++++++++++++++ mysql-test/t/group_min_max.test | 13 +++++++ sql/sql_class.cc | 1 + sql/sql_class.h | 9 ++++- sql/sql_select.cc | 65 +++++++++++++++++++++++++------ sql/sql_select.h | 6 +++ 6 files changed, 113 insertions(+), 12 deletions(-) diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result index 038d0c75f74..636fb719c81 100644 --- a/mysql-test/r/group_min_max.result +++ b/mysql-test/r/group_min_max.result @@ -2002,3 +2002,34 @@ a count(a) 1 1 NULL 1 drop table t1; +create table t1 (c1 int not null,c2 int not null, primary key(c1,c2)); +insert into t1 (c1,c2) values +(10,1),(10,2),(10,3),(20,4),(20,5),(20,6),(30,7),(30,8),(30,9); +select distinct c1, c2 from t1 order by c2; +c1 c2 +10 1 +10 2 +10 3 +20 4 +20 5 +20 6 +30 7 +30 8 +30 9 +select c1,min(c2) as c2 from t1 group by c1 order by c2; +c1 c2 +10 1 +20 4 +30 7 +select c1,c2 from t1 group by c1,c2 order by c2; +c1 c2 +10 1 +10 2 +10 3 +20 4 +20 5 +20 6 +30 7 +30 8 +30 9 +drop table t1; diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test index 3d751f4a571..f6be6170976 100644 --- a/mysql-test/t/group_min_max.test +++ b/mysql-test/t/group_min_max.test @@ -693,3 +693,16 @@ create table t1(a int, key(a)) engine=innodb; insert into t1 values(1); select a, count(a) from t1 group by a with rollup; drop table t1; + +# +# Bug #14920 Ordering aggregated result sets with composite primary keys +# corrupts resultset +# + +create table t1 (c1 int not null,c2 int not null, primary key(c1,c2)); +insert into t1 (c1,c2) values +(10,1),(10,2),(10,3),(20,4),(20,5),(20,6),(30,7),(30,8),(30,9); +select distinct c1, c2 from t1 order by c2; +select c1,min(c2) as c2 from t1 group by c1 order by c2; +select c1,c2 from t1 group by c1,c2 order by c2; +drop table t1; diff --git a/sql/sql_class.cc b/sql/sql_class.cc index c52addf3995..4b3d6486ef7 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1802,6 +1802,7 @@ void TMP_TABLE_PARAM::init() group_parts= group_length= group_null_parts= 0; quick_group= 1; table_charset= 0; + precomputed_group_by= 0; } diff --git a/sql/sql_class.h b/sql/sql_class.h index ed6f5732ca8..c5f661cebd5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1819,11 +1819,18 @@ public: uint convert_blob_length; CHARSET_INFO *table_charset; bool schema_table; + /* + True if GROUP BY and its aggregate functions are already computed + by a table access method (e.g. by loose index scan). In this case + query execution should not perform aggregation and should treat + aggregate functions as normal functions. + */ + bool precomputed_group_by; TMP_TABLE_PARAM() :copy_field(0), group_parts(0), group_length(0), group_null_parts(0), convert_blob_length(0), - schema_table(0) + schema_table(0), precomputed_group_by(0) {} ~TMP_TABLE_PARAM() { diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 9c7df461a3e..adebf9b4a52 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -1007,6 +1007,20 @@ JOIN::optimize() } having= 0; + /* + The loose index scan access method guarantees that all grouping or + duplicate row elimination (for distinct) is already performed + during data retrieval, and that all MIN/MAX functions are already + computed for each group. Thus all MIN/MAX functions should be + treated as regular functions, and there is no need to perform + grouping in the main execution loop. + Notice that currently loose index scan is applicable only for + single table queries, thus it is sufficient to test only the first + join_tab element of the plan for its access method. + */ + if (join_tab->is_using_loose_index_scan()) + tmp_table_param.precomputed_group_by= TRUE; + /* Create a tmp table if distinct or if the sort is too complicated */ if (need_tmp) { @@ -1410,6 +1424,15 @@ JOIN::exec() else { /* group data to new table */ + + /* + If the access method is loose index scan then all MIN/MAX + functions are precomputed, and should be treated as regular + functions. See extended comment in JOIN::exec. + */ + if (curr_join->join_tab->is_using_loose_index_scan()) + curr_join->tmp_table_param.precomputed_group_by= TRUE; + if (!(curr_tmp_table= exec_tmp_table2= create_tmp_table(thd, &curr_join->tmp_table_param, @@ -8279,6 +8302,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, MEM_ROOT *mem_root_save, own_root; TABLE *table; uint i,field_count,null_count,null_pack_length; + uint copy_func_count= param->func_count; uint hidden_null_count, hidden_null_pack_length, hidden_field_count; uint blob_count,group_null_items, string_count; uint temp_pool_slot=MY_BIT_NONE; @@ -8342,6 +8366,16 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, field_count=param->field_count+param->func_count+param->sum_func_count; hidden_field_count=param->hidden_field_count; + /* + When loose index scan is employed as access method, it already + computes all groups and the result of all aggregate functions. We + make space for the items of the aggregate function in the list of + functions TMP_TABLE_PARAM::items_to_copy, so that the values of + these items are stored in the temporary table. + */ + if (param->precomputed_group_by) + copy_func_count+= param->sum_func_count; + init_sql_alloc(&own_root, TABLE_ALLOC_BLOCK_SIZE, 0); if (!multi_alloc_root(&own_root, @@ -8349,7 +8383,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List &fields, ®_field, sizeof(Field*) * (field_count+1), &blob_field, sizeof(uint)*(field_count+1), &from_field, sizeof(Field*)*field_count, - ©_func, sizeof(*copy_func)*(param->func_count+1), + ©_func, sizeof(*copy_func)*(copy_func_count+1), ¶m->keyinfo, sizeof(*param->keyinfo), &key_part_info, sizeof(*key_part_info)*(param->group_parts+1), @@ -9241,11 +9275,13 @@ bool create_myisam_from_heap(THD *thd, TABLE *table, TMP_TABLE_PARAM *param, Next_select_func setup_end_select_func(JOIN *join) { TABLE *table= join->tmp_table; + TMP_TABLE_PARAM *tmp_tbl= &join->tmp_table_param; Next_select_func end_select; + /* Set up select_end */ if (table) { - if (table->group && join->tmp_table_param.sum_func_count) + if (table->group && tmp_tbl->sum_func_count) { if (table->s->keys) { @@ -9258,7 +9294,7 @@ Next_select_func setup_end_select_func(JOIN *join) end_select=end_unique_update; } } - else if (join->sort_and_group) + else if (join->sort_and_group && !tmp_tbl->precomputed_group_by) { DBUG_PRINT("info",("Using end_write_group")); end_select=end_write_group; @@ -9267,19 +9303,27 @@ Next_select_func setup_end_select_func(JOIN *join) { DBUG_PRINT("info",("Using end_write")); end_select=end_write; + if (tmp_tbl->precomputed_group_by) + { + /* + A preceding call to create_tmp_table in the case when loose + index scan is used guarantees that + TMP_TABLE_PARAM::items_to_copy has enough space for the group + by functions. It is OK here to use memcpy since we copy + Item_sum pointers into an array of Item pointers. + */ + memcpy(tmp_tbl->items_to_copy + tmp_tbl->func_count, + join->sum_funcs, + sizeof(Item*)*tmp_tbl->sum_func_count); + tmp_tbl->items_to_copy[tmp_tbl->func_count+tmp_tbl->sum_func_count]= 0; + } } } else { - /* Test if data is accessed via QUICK_GROUP_MIN_MAX_SELECT. */ - bool is_using_quick_group_min_max_select= - (join->join_tab->select && join->join_tab->select->quick && - (join->join_tab->select->quick->get_type() == - QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)); - if ((join->sort_and_group || (join->procedure && join->procedure->flags & PROC_GROUP)) && - !is_using_quick_group_min_max_select) + !tmp_tbl->precomputed_group_by) end_select= end_send_group; else end_select= end_send; @@ -10553,7 +10597,6 @@ end_write(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)), { copy_fields(&join->tmp_table_param); copy_funcs(join->tmp_table_param.items_to_copy); - #ifdef TO_BE_DELETED if (!table->uniques) // If not unique handling { diff --git a/sql/sql_select.h b/sql/sql_select.h index 2f53c9a3b35..b3abd59f2b4 100644 --- a/sql/sql_select.h +++ b/sql/sql_select.h @@ -140,6 +140,12 @@ typedef struct st_join_table { nested_join_map embedding_map; void cleanup(); + inline bool is_using_loose_index_scan() + { + return (select && select->quick && + (select->quick->get_type() == + QUICK_SELECT_I::QS_TYPE_GROUP_MIN_MAX)); + } } JOIN_TAB; enum_nested_loop_state sub_select_cache(JOIN *join, JOIN_TAB *join_tab, bool From 7c38fc51d533d342592b6d9765698b204a772ba0 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Nov 2005 19:06:58 +0200 Subject: [PATCH 51/69] WL#2486 - natural/using join according to SQL:2003. Implemented specialized regression test for the WL. mysql-test/r/join.result: Test results for natural join tests. mysql-test/t/join.test: Specialized test for natural join, and join ... on. --- mysql-test/r/join.result | 306 +++++++++++++++++++++++++++++++++++++++ mysql-test/t/join.test | 207 ++++++++++++++++++++++++++ 2 files changed, 513 insertions(+) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index c887dc9d6a7..e27881a2a30 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -391,3 +391,309 @@ i i i 2 NULL 4 2 2 2 drop table t1,t2,t3; +create table t1 (c int, b int); +create table t2 (a int, b int); +create table t3 (b int, c int); +create table t4 (y int, c int); +create table t5 (y int, z int); +create table t6 (a int, c int); +insert into t1 values (10,1); +insert into t1 values (3 ,1); +insert into t1 values (3 ,2); +insert into t2 values (2, 1); +insert into t3 values (1, 3); +insert into t3 values (1,10); +insert into t4 values (11,3); +insert into t4 values (2, 3); +insert into t5 values (11,4); +insert into t6 values (2, 3); +create algorithm=merge view v1a as +select * from t1 natural join t2; +create algorithm=merge view v1b(a,b,c) as +select * from t1 natural join t2; +create algorithm=merge view v1c as +select b as a, c as b, a as c from t1 natural join t2; +create algorithm=merge view v1d(b, a, c) as +select a as c, c as b, b as a from t1 natural join t2; +create algorithm=merge view v2a as +select t1.c, t1.b, t2.a from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +create algorithm=merge view v2b as +select t1.c as b, t1.b as a, t2.a as c +from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +create algorithm=merge view v3a as +select * from t1 natural join t2 natural join t3; +create algorithm=merge view v3b as +select * from t1 natural join (t2 natural join t3); +create algorithm=merge view v4 as +select * from v2a natural join v3a; +select * from (t1 natural join t2) natural join (t3 natural join t4); +b c a y +1 3 2 11 +1 3 2 2 +select * from (t1 natural join t2) natural left join (t3 natural join t4); +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +select * from (t3 natural join t4) natural right join (t1 natural join t2); +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +select * from (t1 natural left join t2) natural left join (t3 natural left join t4); +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +2 3 NULL NULL +select * from (t4 natural right join t3) natural right join (t2 natural right join t1); +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +2 3 NULL NULL +select * from t1 natural join t2 natural join t3 natural join t4; +c b a y +3 1 2 11 +3 1 2 2 +select * from ((t1 natural join t2) natural join t3) natural join t4; +c b a y +3 1 2 11 +3 1 2 2 +select * from t1 natural join (t2 natural join (t3 natural join t4)); +c b a y +3 1 2 11 +3 1 2 2 +select * from ((t3 natural left join (t1 natural left join t2)) natural left join t4) natural left join t5; +y c b a z +11 3 1 2 4 +2 3 1 2 NULL +NULL 10 1 2 NULL +select * from t5 natural right join (t4 natural right join ((t2 natural right join t1) natural right join t3)); +y c b a z +11 3 1 2 4 +2 3 1 2 NULL +NULL 10 1 2 NULL +select * from (t1 natural join t2), (t3 natural join t4); +b c a c b y +1 10 2 3 1 11 +1 10 2 3 1 2 +1 3 2 3 1 11 +1 3 2 3 1 2 +select * from (t1 join t2 using (b)) join (t3 join t4 using (c)) using (c); +c b a b y +3 1 2 1 11 +3 1 2 1 2 +select * from (t1 join t2 using (b)) natural join (t3 join t4 using (c)); +b c a y +1 3 2 11 +1 3 2 2 +select a,b,c from (t1 natural join t2) natural join (t3 natural join t4) +where b + 1 = y or b + 10 = y group by b,c,a having min(b) < max(y) order by a; +a b c +2 1 3 +select * from (t1 natural join t2) natural left join (t3 natural join t4) +where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y; +b c a y +1 3 2 2 +1 3 2 11 +select * from (t3 natural join t4) natural right join (t1 natural join t2) +where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y; +b c a y +1 3 2 2 +1 3 2 11 +select * from t1 natural join t2 where t1.c > t2.a; +b c a +1 10 2 +1 3 2 +select * from t1 natural join t2 where t1.b > t2.b; +b c a +select * from t1 natural left join (t4 natural join t5) where t5.z is not NULL; +c b y z +3 1 11 4 +3 2 11 4 +select * from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +c b a b y c +3 1 2 1 2 3 +3 2 2 1 2 3 +select * from (t2 join t4 on b + 1 = y) join t1 on t1.c = t4.c; +a b y c c b +2 1 2 3 3 1 +2 1 2 3 3 2 +select * from t1 natural join (t2 join t4 on b + 1 = y); +c b a y +3 1 2 2 +select * from (t1 cross join t2) join (t3 cross join t4) on (a < y and t2.b < t3.c); +c b a b b c y c +10 1 2 1 1 3 11 3 +10 1 2 1 1 10 11 3 +3 1 2 1 1 3 11 3 +3 1 2 1 1 10 11 3 +3 2 2 1 1 3 11 3 +3 2 2 1 1 10 11 3 +select * from (t1, t2) join (t3, t4) on (a < y and t2.b < t3.c); +c b a b b c y c +10 1 2 1 1 3 11 3 +10 1 2 1 1 10 11 3 +3 1 2 1 1 3 11 3 +3 1 2 1 1 10 11 3 +3 2 2 1 1 3 11 3 +3 2 2 1 1 10 11 3 +select * from (t1 natural join t2) join (t3 natural join t4) on a = y; +b c a c b y +1 10 2 3 1 2 +1 3 2 3 1 2 +select * from ((t3 join (t1 join t2 on c > a) on t3.b < t2.a) join t4 on y > t1.c) join t5 on z = t1.b + 3; +b c c b a b y c y z +1 3 10 1 2 1 11 3 11 4 +1 10 10 1 2 1 11 3 11 4 +1 3 3 1 2 1 11 3 11 4 +1 10 3 1 2 1 11 3 11 4 +select * from t1 natural join t2 where t1.b > 0; +b c a +1 10 2 +1 3 2 +select * from t1 natural join (t4 natural join t5) where t4.y > 7; +c b y z +3 1 11 4 +3 2 11 4 +select * from (t4 natural join t5) natural join t1 where t4.y > 7; +c y z b +3 11 4 1 +3 11 4 2 +select * from t1 natural left join (t4 natural join t5) where t4.y > 7; +c b y z +3 1 11 4 +3 2 11 4 +select * from (t4 natural join t5) natural right join t1 where t4.y > 7; +c b y z +3 1 11 4 +3 2 11 4 +select * from (t1 natural join t2) join (t3 natural join t4) on t1.b = t3.b; +b c a c b y +1 10 2 3 1 11 +1 10 2 3 1 2 +1 3 2 3 1 11 +1 3 2 3 1 2 +select t1.*, t2.* from t1 natural join t2; +c b a b +10 1 2 1 +3 1 2 1 +select t1.*, t2.*, t3.*, t4.* from (t1 natural join t2) natural join (t3 natural join t4); +c b a b b c y c +3 1 2 1 1 3 11 3 +3 1 2 1 1 3 2 3 +select * from (select * from t1 natural join t2) as t12 +natural join +(select * from t3 natural join t4) as t34; +b c a y +1 3 2 11 +1 3 2 2 +select * from (select * from t1 natural join t2) as t12 +natural left join +(select * from t3 natural join t4) as t34; +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +select * from (select * from t3 natural join t4) as t34 +natural right join +(select * from t1 natural join t2) as t12; +b c a y +1 10 2 NULL +1 3 2 11 +1 3 2 2 +select * from v1a; +b c a +1 10 2 +1 3 2 +select * from v1b; +a b c +1 10 2 +1 3 2 +select * from v1c; +a b c +1 10 2 +1 3 2 +select * from v1d; +b a c +2 10 1 +2 3 1 +select * from v2a; +c b a +3 1 2 +3 2 2 +select * from v2b; +b a c +3 1 2 +3 2 2 +select * from v3a; +b c a +1 10 2 +1 3 2 +select * from v3b; +c b a +10 1 2 +3 1 2 +select * from v4; +c b a +3 1 2 +select * from v1a natural join v2a; +b c a +1 3 2 +select v2a.* from v1a natural join v2a; +c b a +3 1 2 +select * from v1b join v2a on v1b.b = v2a.c; +a b c c b a +1 3 2 3 1 2 +1 3 2 3 2 2 +select * from v1c join v2a on v1c.b = v2a.c; +a b c c b a +1 3 2 3 1 2 +1 3 2 3 2 2 +select * from v1d join v2a on v1d.a = v2a.c; +b a c c b a +2 3 1 3 1 2 +2 3 1 3 2 2 +select * from v1a join (t3 natural join t4) on a = y; +b c a c b y +1 10 2 3 1 2 +1 3 2 3 1 2 +select * from t1 natural join (t3 cross join t4); +ERROR 23000: Column 'c' in from clause is ambiguous +select * from (t3 cross join t4) natural join t1; +ERROR 23000: Column 'c' in from clause is ambiguous +select * from t1 join (t2, t3) using (b); +ERROR 23000: Column 'b' in from clause is ambiguous +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; +ERROR 23000: Column 'c' in from clause is ambiguous +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; +ERROR 23000: Column 'c' in from clause is ambiguous +select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4); +ERROR 23000: Column 'b' in from clause is ambiguous +select * from (t3 natural join t4) natural join (t1 join t2 on t1.b=t2.b); +ERROR 23000: Column 'b' in from clause is ambiguous +select * from (t3 join (t4 natural join t5) on (b < z)) +natural join +(t1 natural join t2); +ERROR 23000: Column 'c' in from clause is ambiguous +select t1.b from v1a; +ERROR 42S22: Unknown column 't1.b' in 'field list' +select * from v1a join v1b on t1.b = t2.b; +ERROR 42S22: Unknown column 't1.b' in 'on clause' +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table t5; +drop table t6; +drop view v1a; +drop view v1b; +drop view v1c; +drop view v1d; +drop view v2a; +drop view v2b; +drop view v3a; +drop view v3b; +drop view v4; diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index bb82a93c6c4..632b76794de 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -334,3 +334,210 @@ select t1.i,t2.i,t3.i from t2 right join t3 on (t2.i=t3.i),t1 order by t1.i,t2.i drop table t1,t2,t3; # End of 4.1 tests + +# +# Tests for WL#2486 Natural/using join according to SQL:2003. +# +# NOTICE: +# - The tests are designed so that all statements, except MySQL +# extensions run on any SQL server. Please do no change. +# - Tests marked with TODO will be submitted as bugs. +# + +create table t1 (c int, b int); +create table t2 (a int, b int); +create table t3 (b int, c int); +create table t4 (y int, c int); +create table t5 (y int, z int); +create table t6 (a int, c int); + +insert into t1 values (10,1); +insert into t1 values (3 ,1); +insert into t1 values (3 ,2); +insert into t2 values (2, 1); +insert into t3 values (1, 3); +insert into t3 values (1,10); +insert into t4 values (11,3); +insert into t4 values (2, 3); +insert into t5 values (11,4); +insert into t6 values (2, 3); + +-- Views with simple natural join. +create algorithm=merge view v1a as +select * from t1 natural join t2; +-- as above, but column names are cross-renamed: a->c, c->b, b->a +create algorithm=merge view v1b(a,b,c) as +select * from t1 natural join t2; +-- as above, but column names are aliased: a->c, c->b, b->a +create algorithm=merge view v1c as +select b as a, c as b, a as c from t1 natural join t2; +-- as above, but column names are cross-renamed, and aliased +-- a->c->b, c->b->a, b->a->c +create algorithm=merge view v1d(b, a, c) as +select a as c, c as b, b as a from t1 natural join t2; + +-- Views with JOIN ... ON +create algorithm=merge view v2a as +select t1.c, t1.b, t2.a from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +create algorithm=merge view v2b as +select t1.c as b, t1.b as a, t2.a as c +from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; + +-- Views with bigger natural join +create algorithm=merge view v3a as +select * from t1 natural join t2 natural join t3; +create algorithm=merge view v3b as +select * from t1 natural join (t2 natural join t3); + +-- View over views with mixed natural join and join ... on +create algorithm=merge view v4 as +select * from v2a natural join v3a; + +-- Nested natural/using joins. +select * from (t1 natural join t2) natural join (t3 natural join t4); +select * from (t1 natural join t2) natural left join (t3 natural join t4); +select * from (t3 natural join t4) natural right join (t1 natural join t2); +select * from (t1 natural left join t2) natural left join (t3 natural left join t4); +select * from (t4 natural right join t3) natural right join (t2 natural right join t1); +select * from t1 natural join t2 natural join t3 natural join t4; +select * from ((t1 natural join t2) natural join t3) natural join t4; +select * from t1 natural join (t2 natural join (t3 natural join t4)); +-- BUG#15355: this query fails in 'prepared statements' mode +-- select * from ((t3 natural join (t1 natural join t2)) natural join t4) natural join t5; +select * from ((t3 natural left join (t1 natural left join t2)) natural left join t4) natural left join t5; +select * from t5 natural right join (t4 natural right join ((t2 natural right join t1) natural right join t3)); +select * from (t1 natural join t2), (t3 natural join t4); +-- MySQL extension - nested comma ',' operator instead of cross join. +-- BUG#15357 - natural join with nested cross-join results in incorrect columns +-- select * from t5 natural join ((t1 natural join t2), (t3 natural join t4)); +-- select * from ((t1 natural join t2), (t3 natural join t4)) natural join t5; +-- select * from t5 natural join ((t1 natural join t2) cross join (t3 natural join t4)); +-- select * from ((t1 natural join t2) cross join (t3 natural join t4)) natural join t5; + +select * from (t1 join t2 using (b)) join (t3 join t4 using (c)) using (c); +select * from (t1 join t2 using (b)) natural join (t3 join t4 using (c)); + + +-- Other clauses refer to NJ columns. +select a,b,c from (t1 natural join t2) natural join (t3 natural join t4) +where b + 1 = y or b + 10 = y group by b,c,a having min(b) < max(y) order by a; +select * from (t1 natural join t2) natural left join (t3 natural join t4) +where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y; +select * from (t3 natural join t4) natural right join (t1 natural join t2) +where b + 1 = y or b + 10 = y group by b,c,a,y having min(b) < max(y) order by a, y; + +-- Qualified column references to NJ columns. +select * from t1 natural join t2 where t1.c > t2.a; +select * from t1 natural join t2 where t1.b > t2.b; +select * from t1 natural left join (t4 natural join t5) where t5.z is not NULL; + +-- Nested 'join ... on' - name resolution of ON conditions +select * from t1 join (t2 join t4 on b + 1 = y) on t1.c = t4.c; +select * from (t2 join t4 on b + 1 = y) join t1 on t1.c = t4.c; +select * from t1 natural join (t2 join t4 on b + 1 = y); +select * from (t1 cross join t2) join (t3 cross join t4) on (a < y and t2.b < t3.c); + +-- MySQL extension - 'join ... on' over nested comma operator +select * from (t1, t2) join (t3, t4) on (a < y and t2.b < t3.c); +select * from (t1 natural join t2) join (t3 natural join t4) on a = y; +select * from ((t3 join (t1 join t2 on c > a) on t3.b < t2.a) join t4 on y > t1.c) join t5 on z = t1.b + 3; + +-- MySQL extension - refererence qualified coalesced columns +select * from t1 natural join t2 where t1.b > 0; +select * from t1 natural join (t4 natural join t5) where t4.y > 7; +select * from (t4 natural join t5) natural join t1 where t4.y > 7; +select * from t1 natural left join (t4 natural join t5) where t4.y > 7; +select * from (t4 natural join t5) natural right join t1 where t4.y > 7; +select * from (t1 natural join t2) join (t3 natural join t4) on t1.b = t3.b; + +-- MySQL extension - select qualified columns of NJ columns +select t1.*, t2.* from t1 natural join t2; +select t1.*, t2.*, t3.*, t4.* from (t1 natural join t2) natural join (t3 natural join t4); + +-- Queries over subselects in the FROM clause +select * from (select * from t1 natural join t2) as t12 + natural join + (select * from t3 natural join t4) as t34; +select * from (select * from t1 natural join t2) as t12 + natural left join + (select * from t3 natural join t4) as t34; +select * from (select * from t3 natural join t4) as t34 + natural right join + (select * from t1 natural join t2) as t12; + +-- Queries over views +select * from v1a; +select * from v1b; +select * from v1c; +select * from v1d; +select * from v2a; +select * from v2b; +select * from v3a; +select * from v3b; +select * from v4; +select * from v1a natural join v2a; +select v2a.* from v1a natural join v2a; +select * from v1b join v2a on v1b.b = v2a.c; +select * from v1c join v2a on v1c.b = v2a.c; +select * from v1d join v2a on v1d.a = v2a.c; +select * from v1a join (t3 natural join t4) on a = y; + +-- TODO: add tests with correlated subqueries for natural join/join on. +-- related to BUG#15269 + + +---------------------------------------------------------------------- +-- Negative tests (tests for errors) +---------------------------------------------------------------------- +-- error 1052 +select * from t1 natural join (t3 cross join t4); -- works in Oracle - bug +-- error 1052 +select * from (t3 cross join t4) natural join t1; -- works in Oracle - bug +-- error 1052 +select * from t1 join (t2, t3) using (b); +-- error 1052 +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; +-- error 1052 +select * from ((t1 natural join t2), (t3 natural join t4)) natural join t6; +-- error 1052 +-- BUG#15357: doesn't detect non-unique column 'c', as in the above query. +-- select * from t6 natural join ((t1 natural join t2), (t3 natural join t4)); +-- error 1052 +select * from (t1 join t2 on t1.b=t2.b) natural join (t3 natural join t4); +-- error 1052 +select * from (t3 natural join t4) natural join (t1 join t2 on t1.b=t2.b); +-- this one is OK, the next equivalent one is incorrect (bug in Oracle) +-- error 1052 +select * from (t3 join (t4 natural join t5) on (b < z)) + natural join + (t1 natural join t2); +-- error 1052 +-- BUG#15357: this query should return an ambiguous column error +-- Expected result: the query must return error with duplicate column 'c' +--select * from (t1 natural join t2) +-- natural join +-- (t3 join (t4 natural join t5) on (b < z)); + +-- error 1054 +select t1.b from v1a; +-- error 1054 +select * from v1a join v1b on t1.b = t2.b; + +drop table t1; +drop table t2; +drop table t3; +drop table t4; +drop table t5; +drop table t6; + +drop view v1a; +drop view v1b; +drop view v1c; +drop view v1d; +drop view v2a; +drop view v2b; +drop view v3a; +drop view v3b; +drop view v4; + +# End of tests for WL#2486 - natural/using join From e26eb47b4b2b0b7767601282cdb1b572349118f4 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Nov 2005 19:13:29 +0200 Subject: [PATCH 52/69] WL#2486 - natural/using join according to SQL:2003 Commented out one failing query in the regression test (reported as a bug). mysql-test/r/join.result: Commented out failing query. mysql-test/t/join.test: Commented out failing query. --- mysql-test/r/join.result | 5 ----- mysql-test/t/join.test | 2 +- 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/mysql-test/r/join.result b/mysql-test/r/join.result index e27881a2a30..724d1b1e39f 100644 --- a/mysql-test/r/join.result +++ b/mysql-test/r/join.result @@ -464,11 +464,6 @@ select * from t1 natural join (t2 natural join (t3 natural join t4)); c b a y 3 1 2 11 3 1 2 2 -select * from ((t3 natural left join (t1 natural left join t2)) natural left join t4) natural left join t5; -y c b a z -11 3 1 2 4 -2 3 1 2 NULL -NULL 10 1 2 NULL select * from t5 natural right join (t4 natural right join ((t2 natural right join t1) natural right join t3)); y c b a z 11 3 1 2 4 diff --git a/mysql-test/t/join.test b/mysql-test/t/join.test index 632b76794de..553aaf987bb 100644 --- a/mysql-test/t/join.test +++ b/mysql-test/t/join.test @@ -404,7 +404,7 @@ select * from ((t1 natural join t2) natural join t3) natural join t4; select * from t1 natural join (t2 natural join (t3 natural join t4)); -- BUG#15355: this query fails in 'prepared statements' mode -- select * from ((t3 natural join (t1 natural join t2)) natural join t4) natural join t5; -select * from ((t3 natural left join (t1 natural left join t2)) natural left join t4) natural left join t5; +-- select * from ((t3 natural left join (t1 natural left join t2)) natural left join t4) natural left join t5; select * from t5 natural right join (t4 natural right join ((t2 natural right join t1) natural right join t3)); select * from (t1 natural join t2), (t3 natural join t4); -- MySQL extension - nested comma ',' operator instead of cross join. From 598cc2db7dc5c86156929c6c2b88b2e95af427c5 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Nov 2005 21:50:09 +0100 Subject: [PATCH 53/69] Raise the version number (as 4.1.16 has been cloned). --- configure.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.in b/configure.in index 41475ffcd4a..9afd2034796 100644 --- a/configure.in +++ b/configure.in @@ -5,7 +5,7 @@ AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! # remember to also change ndb version below and update version.c in ndb -AM_INIT_AUTOMAKE(mysql, 4.1.16) +AM_INIT_AUTOMAKE(mysql, 4.1.17) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 @@ -16,7 +16,7 @@ SHARED_LIB_VERSION=14:0:0 # ndb version NDB_VERSION_MAJOR=4 NDB_VERSION_MINOR=1 -NDB_VERSION_BUILD=16 +NDB_VERSION_BUILD=17 NDB_VERSION_STATUS="" # Set all version vars based on $VERSION. How do we do this more elegant ? From b775d23faaa98297ddd5ed6978b5a214432516d3 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 30 Nov 2005 13:10:08 -0800 Subject: [PATCH 54/69] Fix union.result mysql-test/r/union.result: Fix order of test results --- mysql-test/r/union.result | 52 +++++++++++++++++++-------------------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result index 48aac1b3a0a..f2708a50c77 100644 --- a/mysql-test/r/union.result +++ b/mysql-test/r/union.result @@ -1220,6 +1220,32 @@ show columns from t2; Field Type Null Key Default Extra a varchar(3) YES NULL drop table t2, t1; +create table t1 (f1 decimal(60,25), f2 decimal(60,25)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +f1 +0.0000000000000000000000000 +0.0000000000000000000000000 +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +description f1 +XXXXXXXXXXXXXXXXXXXX 0.0000000000000000000000000 +YYYYYYYYYYYYYYYYYYYY 0.0000000000000000000000000 +drop table t1; +create table t1 (f1 decimal(60,24), f2 decimal(60,24)); +insert into t1 values (0.0,0.0); +select f1 from t1 union all select f2 from t1; +f1 +0.000000000000000000000000 +0.000000000000000000000000 +select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 +union all +select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; +description f1 +XXXXXXXXXXXXXXXXXXXX 0.000000000000000000000000 +YYYYYYYYYYYYYYYYYYYY 0.000000000000000000000000 +drop table t1; create table t1 (a varchar(5)); create table t2 select * from t1 union select 'abcdefghijkl'; show create table t2; @@ -1270,29 +1296,3 @@ id 5 99 drop table t1; -create table t1 (f1 decimal(60,25), f2 decimal(60,25)); -insert into t1 values (0.0,0.0); -select f1 from t1 union all select f2 from t1; -f1 -0.0000000000000000000000000 -0.0000000000000000000000000 -select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 -union all -select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; -description f1 -XXXXXXXXXXXXXXXXXXXX 0.0000000000000000000000000 -YYYYYYYYYYYYYYYYYYYY 0.0000000000000000000000000 -drop table t1; -create table t1 (f1 decimal(60,24), f2 decimal(60,24)); -insert into t1 values (0.0,0.0); -select f1 from t1 union all select f2 from t1; -f1 -0.000000000000000000000000 -0.000000000000000000000000 -select 'XXXXXXXXXXXXXXXXXXXX' as description, f1 from t1 -union all -select 'YYYYYYYYYYYYYYYYYYYY' as description, f2 from t1; -description f1 -XXXXXXXXXXXXXXXXXXXX 0.000000000000000000000000 -YYYYYYYYYYYYYYYYYYYY 0.000000000000000000000000 -drop table t1; From ba079bad06d99a353f1eadb177541ca23635f886 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 11:00:33 +0400 Subject: [PATCH 55/69] Fix for bug#14476 `information_schema`.`TABLES`.`TABLE_TYPE` with empty value store TABLES.TABLE_TYPE in case of error during table opening mysql-test/r/information_schema.result: Fix for bug#14476 `information_schema`.`TABLES`.`TABLE_TYPE` with empty value test case mysql-test/t/information_schema.test: Fix for bug#14476 `information_schema`.`TABLES`.`TABLE_TYPE` with empty value test case --- mysql-test/r/information_schema.result | 8 ++++++++ mysql-test/t/information_schema.test | 10 ++++++++++ sql/sql_show.cc | 6 ++++++ 3 files changed, 24 insertions(+) diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 079a1af1184..6224b30b70e 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -1048,3 +1048,11 @@ blob 65535 65535 text 65535 65535 text 65535 32767 drop table t1; +create table t1 (f1 int(11)); +create view v1 as select * from t1; +drop table t1; +select table_type from information_schema.tables +where table_name="v1"; +table_type +VIEW +drop view v1; diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test index 1cd55926e80..acbc62f1364 100644 --- a/mysql-test/t/information_schema.test +++ b/mysql-test/t/information_schema.test @@ -738,3 +738,13 @@ create table t1(a blob, b text charset utf8, c text charset ucs2); select data_type, character_octet_length, character_maximum_length from information_schema.columns where table_name='t1'; drop table t1; + +# +# Bug#14476 `information_schema`.`TABLES`.`TABLE_TYPE` with empty value +# +create table t1 (f1 int(11)); +create view v1 as select * from t1; +drop table t1; +select table_type from information_schema.tables +where table_name="v1"; +drop view v1; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index cb537a43053..82870d46e6c 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -2315,6 +2315,12 @@ static int get_schema_tables_record(THD *thd, struct st_table_list *tables, there was errors during opening tables */ const char *error= thd->net.last_error; + if (tables->view) + table->field[3]->store(STRING_WITH_LEN("VIEW"), cs); + else if (tables->schema_table) + table->field[3]->store(STRING_WITH_LEN("SYSTEM VIEW"), cs); + else + table->field[3]->store(STRING_WITH_LEN("BASE TABLE"), cs); table->field[20]->store(error, strlen(error), cs); thd->clear_error(); } From 2061a3a6b6548572e5149194d8185867a3c92865 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 12:01:38 +0200 Subject: [PATCH 56/69] We should not skip temptable view along with other derived tables during query tables registration. (BUG#15119) mysql-test/r/view_query_cache.result: Tests for temptable views in the query cache. mysql-test/t/view_query_cache.test: Tests for temptable views in the query cache. sql/sql_cache.cc: We should not skip temptable view along with other derived tables during query tables registration. --- mysql-test/r/view_query_cache.result | 61 ++++++++++++++++++++++++++++ mysql-test/t/view_query_cache.test | 31 ++++++++++++++ sql/sql_cache.cc | 2 +- 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/view_query_cache.result b/mysql-test/r/view_query_cache.result index 944e1db34c9..03430bd504b 100644 --- a/mysql-test/r/view_query_cache.result +++ b/mysql-test/r/view_query_cache.result @@ -132,4 +132,65 @@ unlock tables; set query_cache_wlock_invalidate=default; drop view v1; drop table t1; +flush status; +create table t1 (a int, b int); +create algorithm=temptable view v1 as select * from t1; +select * from v1; +a b +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +select * from v1; +a b +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +insert into t1 values (1,1); +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +select * from v1; +a b +1 1 +select * from v1; +a b +1 1 +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +drop view v1; +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 0 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 2 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 2 +drop table t1; set GLOBAL query_cache_size=default; diff --git a/mysql-test/t/view_query_cache.test b/mysql-test/t/view_query_cache.test index 81994407641..d4ebe45b7ac 100644 --- a/mysql-test/t/view_query_cache.test +++ b/mysql-test/t/view_query_cache.test @@ -96,4 +96,35 @@ unlock tables; set query_cache_wlock_invalidate=default; drop view v1; drop table t1; + +# +# BUG#15119: returning temptable view from the query cache. +# +flush status; +create table t1 (a int, b int); +create algorithm=temptable view v1 as select * from t1; +select * from v1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +select * from v1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +insert into t1 values (1,1); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +select * from v1; +select * from v1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +drop view v1; +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +drop table t1; + +# Reset default environment. set GLOBAL query_cache_size=default; diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 3965079988b..24ab27c587d 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -2184,7 +2184,7 @@ Query_cache::register_tables_from_list(TABLE_LIST *tables_used, tables_used; tables_used= tables_used->next_global, n++, block_table++) { - if (tables_used->derived) + if (tables_used->derived && !tables_used->view) { DBUG_PRINT("qcache", ("derived table skipped")); n--; From 3e4d4a365662bb12a50bdda4e0efd348189f2068 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 12:15:48 +0200 Subject: [PATCH 57/69] View creation code fixed to expect empty TABLE_LIST::table pointer (BUG#15096). mysql-test/r/view.result: BUG#15096 test suite. mysql-test/t/view.test: BUG#15096 test suite. sql/sql_view.cc: View placed in a function never get TABLE during view creation, because we have never executed that function in this process. So we should expect empty TABLE_LIST::table pointer. --- mysql-test/r/view.result | 15 +++++++++++++++ mysql-test/t/view.test | 21 +++++++++++++++++++++ sql/sql_view.cc | 35 ++++++++++++++++++++++------------- 3 files changed, 58 insertions(+), 13 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index ebb2c190eb1..16ed023fdac 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2424,3 +2424,18 @@ f1 sum(f2) NULL 12 drop view v1; drop table t1; +CREATE VIEW v1 AS SELECT 42 AS Meaning; +DROP FUNCTION IF EXISTS f1; +CREATE FUNCTION f1() RETURNS INTEGER +BEGIN +DECLARE retn INTEGER; +SELECT Meaning FROM v1 INTO retn; +RETURN retn; +END +// +CREATE VIEW v2 AS SELECT f1(); +select * from v2; +f1() +42 +drop view v2,v1; +drop function f1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index ac103278f08..8a19b9fce08 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2280,3 +2280,24 @@ create view v1 as select * from t1; select f1, sum(f2) from v1 group by f1; drop view v1; drop table t1; + +# +# BUG#15096: using function with view for view creation +# +CREATE VIEW v1 AS SELECT 42 AS Meaning; +--disable_warnings +DROP FUNCTION IF EXISTS f1; +--enable_warnings +DELIMITER //; +CREATE FUNCTION f1() RETURNS INTEGER +BEGIN + DECLARE retn INTEGER; + SELECT Meaning FROM v1 INTO retn; + RETURN retn; +END +// +DELIMITER ;// +CREATE VIEW v2 AS SELECT f1(); +select * from v2; +drop view v2,v1; +drop function f1; diff --git a/sql/sql_view.cc b/sql/sql_view.cc index e03d3b22b89..31c5e5fed0a 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -350,15 +350,6 @@ bool mysql_create_view(THD *thd, */ for (tbl= lex->query_tables; tbl; tbl= tbl->next_global) { - /* is this table temporary and is not view? */ - if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view && - !tbl->schema_table) - { - my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias); - res= TRUE; - goto err; - } - /* is this table view and the same view which we creates now? */ if (tbl->view && strcmp(tbl->view_db.str, view->db) == 0 && @@ -370,11 +361,29 @@ bool mysql_create_view(THD *thd, } /* - Copy the privileges of the underlying VIEWs which were filled by - fill_effective_table_privileges - (they were not copied at derived tables processing) + tbl->table can be NULL when tbl is a placeholder for a view + that is indirectly referenced via a stored function from the + view being created. We don't check these indirectly + referenced views in CREATE VIEW so they don't have table + object. */ - tbl->table->grant.privilege= tbl->grant.privilege; + if (tbl->table) + { + /* is this table temporary and is not view? */ + if (tbl->table->s->tmp_table != NO_TMP_TABLE && !tbl->view && + !tbl->schema_table) + { + my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias); + res= TRUE; + goto err; + } + /* + Copy the privileges of the underlying VIEWs which were filled by + fill_effective_table_privileges + (they were not copied at derived tables processing) + */ + tbl->table->grant.privilege= tbl->grant.privilege; + } } /* prepare select to resolve all fields */ From f853fbc9f43e76018752cab3b91e04157dd9b097 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 14:26:46 +0400 Subject: [PATCH 58/69] Fix for bug #14304: auto_increment field incorrect set from within stored procedure (insert select). sql/sp_head.cc: Fix for bug #14304: auto_increment field incorrect set from within stored procedure (insert select). - call thd->cleanup_after_query() to clean next_insert_id. sql/sql_class.cc: Fix for bug #14304: auto_increment field incorrect set from within stored procedure (insert select). - save/restore clear_next_insert_id sql/sql_class.h: Fix for bug #14304: auto_increment field incorrect set from within stored procedure (insert select). - clear_next_insert_id added --- mysql-test/r/sp.result | 24 ++++++++++++++++++++++++ mysql-test/t/sp.test | 31 +++++++++++++++++++++++++++++++ sql/sp_head.cc | 2 +- sql/sql_class.cc | 2 ++ sql/sql_class.h | 2 +- 5 files changed, 59 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 694cf903d35..454ff0b615f 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4046,4 +4046,28 @@ boo 2 drop procedure bug14643_1| drop procedure bug14643_2| +drop procedure if exists bug14304| +drop table if exists t3, t4| +create table t3(a int primary key auto_increment)| +create table t4(a int primary key auto_increment)| +create procedure bug14304() +begin +insert into t3 set a=null; +insert into t4 set a=null; +insert into t4 set a=null; +insert into t4 set a=null; +insert into t4 set a=null; +insert into t4 set a=null; +insert into t4 select null as a; +insert into t3 set a=null; +insert into t3 set a=null; +select * from t3; +end| +call bug14304()| +a +1 +2 +3 +drop procedure bug14304| +drop table t3, t4| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 5bbe9258461..676cc3cda1e 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4823,6 +4823,37 @@ call bug14643_2()| drop procedure bug14643_1| drop procedure bug14643_2| +# +# BUG#14304: auto_increment field incorrect set in SP +# +--disable_warnings +drop procedure if exists bug14304| +drop table if exists t3, t4| +--enable_warnings + +create table t3(a int primary key auto_increment)| +create table t4(a int primary key auto_increment)| + +create procedure bug14304() +begin + insert into t3 set a=null; + insert into t4 set a=null; + insert into t4 set a=null; + insert into t4 set a=null; + insert into t4 set a=null; + insert into t4 set a=null; + insert into t4 select null as a; + + insert into t3 set a=null; + insert into t3 set a=null; + + select * from t3; +end| + +call bug14304()| + +drop procedure bug14304| +drop table t3, t4| # # BUG#NNNN: New bug synopsis diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 9b7ce44c14a..81e10e59a9b 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1069,7 +1069,7 @@ int sp_head::execute(THD *thd) } /* we should cleanup free_list and memroot, used by instruction */ - thd->free_items(); + thd->cleanup_after_query(); free_root(&execute_mem_root, MYF(0)); /* diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 70dfaca53d3..00669ee5c73 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -1948,6 +1948,7 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, backup->last_insert_id= last_insert_id; backup->next_insert_id= next_insert_id; backup->insert_id_used= insert_id_used; + backup->clear_next_insert_id= clear_next_insert_id; backup->limit_found_rows= limit_found_rows; backup->examined_row_count= examined_row_count; backup->sent_row_count= sent_row_count; @@ -1999,6 +2000,7 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup) last_insert_id= backup->last_insert_id; next_insert_id= backup->next_insert_id; insert_id_used= backup->insert_id_used; + clear_next_insert_id= backup->clear_next_insert_id; limit_found_rows= backup->limit_found_rows; sent_row_count= backup->sent_row_count; client_capabilities= backup->client_capabilities; diff --git a/sql/sql_class.h b/sql/sql_class.h index 33be70ee674..0a5a615fe64 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -1090,7 +1090,7 @@ public: ha_rows cuted_fields, sent_row_count, examined_row_count; ulong client_capabilities; uint in_sub_stmt; - bool enable_slow_log, insert_id_used; + bool enable_slow_log, insert_id_used, clear_next_insert_id; my_bool no_send_ok; SAVEPOINT *savepoints; }; From a050707b61d29dec3f39ef89f3102c6a72edb90a Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 14:26:19 +0200 Subject: [PATCH 59/69] We should skip beggining '(' characters when test query on possibility to be in the query cache. (BUG#14652) mysql-test/r/query_cache.result: BUG#14652 test suite. mysql-test/t/query_cache.test: BUG#14652 test suite. sql/sql_cache.cc: We should skip beggining '(' characters when test query on possibility to be in the query cache. --- mysql-test/r/query_cache.result | 25 +++++++++++++++++++++++++ mysql-test/t/query_cache.test | 15 +++++++++++++++ sql/sql_cache.cc | 28 +++++++++++++++++++--------- 3 files changed, 59 insertions(+), 9 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index ed87e2be2b4..24363ea27ab 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -982,4 +982,29 @@ show status like "Qcache_hits"; Variable_name Value Qcache_hits 1 drop table t1; +create table t1 (a int); +flush status; +(select a from t1) union (select a from t1); +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +(select a from t1) union (select a from t1); +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +drop table t1; set GLOBAL query_cache_size=0; diff --git a/mysql-test/t/query_cache.test b/mysql-test/t/query_cache.test index d08dc5fb352..3140739309e 100644 --- a/mysql-test/t/query_cache.test +++ b/mysql-test/t/query_cache.test @@ -712,6 +712,21 @@ show status like "Qcache_inserts"; show status like "Qcache_hits"; drop table t1; +# +# BUG#14652: Queries with leading '(' characters. +# +create table t1 (a int); +flush status; +(select a from t1) union (select a from t1); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +(select a from t1) union (select a from t1); +show status like "Qcache_queries_in_cache"; +show status like "Qcache_inserts"; +show status like "Qcache_hits"; +drop table t1; + set GLOBAL query_cache_size=0; # End of 4.1 tests diff --git a/sql/sql_cache.cc b/sql/sql_cache.cc index 4214c9a7c07..b40257511f7 100644 --- a/sql/sql_cache.cc +++ b/sql/sql_cache.cc @@ -956,16 +956,26 @@ Query_cache::send_result_to_client(THD *thd, char *sql, uint query_length) goto err; } - /* - Test if the query is a SELECT - (pre-space is removed in dispatch_command) - */ - if (my_toupper(system_charset_info, sql[0]) != 'S' || - my_toupper(system_charset_info, sql[1]) != 'E' || - my_toupper(system_charset_info,sql[2]) !='L') { - DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); - goto err; + uint i= 0; + /* + Skip '(' characters in queries like following: + (select a from t1) union (select a from t1); + */ + while (sql[i]=='(') + i++; + + /* + Test if the query is a SELECT + (pre-space is removed in dispatch_command) + */ + if (my_toupper(system_charset_info, sql[i]) != 'S' || + my_toupper(system_charset_info, sql[i + 1]) != 'E' || + my_toupper(system_charset_info, sql[i + 2]) != 'L') + { + DBUG_PRINT("qcache", ("The statement is not a SELECT; Not cached")); + goto err; + } } STRUCT_LOCK(&structure_guard_mutex); From b97a5c537b556b79e589655e25e7fac452053f6f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 17:13:54 +0200 Subject: [PATCH 60/69] postmerge fix --- mysql-test/r/query_cache.result | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index c4521b4a71e..405669e95f8 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -850,31 +850,6 @@ group_concat(a) set group_concat_max_len=default; drop table t1; create table t1 (a int); -flush status; -(select a from t1) union (select a from t1); -a -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 1 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 1 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 0 -(select a from t1) union (select a from t1); -a -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 1 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 1 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 1 -drop table t1; -create table t1 (a int); show status like "Qcache_queries_in_cache"; Variable_name Value Qcache_queries_in_cache 0 @@ -1047,6 +1022,31 @@ Variable_name Value Qcache_hits 1 drop table t1; create table t1 (a int); +flush status; +(select a from t1) union (select a from t1); +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +(select a from t1) union (select a from t1); +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +drop table t1; +create table t1 (a int); insert into t1 values (1),(2); CREATE PROCEDURE `p1`() begin From 4b4f7f7612083abf43876ed4beaaef6cb5dba5f9 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 11:11:03 -0800 Subject: [PATCH 61/69] Enable key lengths of up to 3K on 32-bit platforms. mysql-test/r/bdb.result: Add new results mysql-test/r/innodb.result: Add new results mysql-test/t/bdb.test: Add simple test that large keys are allowed mysql-test/t/innodb.test: Add simple test that large keys are allowed sql/unireg.h: Allow key length of 3K even on 32-bit platforms --- mysql-test/r/bdb.result | 14 ++++++++++++++ mysql-test/r/innodb.result | 14 ++++++++++++++ mysql-test/t/bdb.test | 19 +++++++++++++++++++ mysql-test/t/innodb.test | 19 +++++++++++++++++++ sql/unireg.h | 6 +----- 5 files changed, 67 insertions(+), 5 deletions(-) diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result index 5cdf9612300..ac14f891622 100644 --- a/mysql-test/r/bdb.result +++ b/mysql-test/r/bdb.result @@ -1891,3 +1891,17 @@ t1 CREATE TABLE `t1` ( ) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 drop table t1; set storage_engine=MyISAM; +create table t1 (a varchar(255) character set utf8, +b varchar(255) character set utf8, +c varchar(255) character set utf8, +d varchar(255) character set utf8, +key (a,b,c,d)) engine=bdb; +drop table t1; +create table t1 (a varchar(255) character set utf8, +b varchar(255) character set utf8, +c varchar(255) character set utf8, +d varchar(255) character set utf8, +e varchar(255) character set utf8, +key (a,b,c,d,e)) engine=bdb; +ERROR 42000: Specified key was too long; max key length is 3072 bytes +End of 5.0 tests diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index dc4893c3bfa..aabc83a71b8 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -2772,3 +2772,17 @@ insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); drop table t1; drop table t2; commit; +create table t1 (a varchar(255) character set utf8, +b varchar(255) character set utf8, +c varchar(255) character set utf8, +d varchar(255) character set utf8, +key (a,b,c,d)) engine=innodb; +drop table t1; +create table t1 (a varchar(255) character set utf8, +b varchar(255) character set utf8, +c varchar(255) character set utf8, +d varchar(255) character set utf8, +e varchar(255) character set utf8, +key (a,b,c,d,e)) engine=innodb; +ERROR 42000: Specified key was too long; max key length is 3072 bytes +End of 5.0 tests diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test index 97d8f28cd3f..72b3ee89ed5 100644 --- a/mysql-test/t/bdb.test +++ b/mysql-test/t/bdb.test @@ -974,3 +974,22 @@ drop table t1; # End varchar test eval set storage_engine=$default; + +# +# Test that we can create a large key +# +create table t1 (a varchar(255) character set utf8, + b varchar(255) character set utf8, + c varchar(255) character set utf8, + d varchar(255) character set utf8, + key (a,b,c,d)) engine=bdb; +drop table t1; +--error ER_TOO_LONG_KEY +create table t1 (a varchar(255) character set utf8, + b varchar(255) character set utf8, + c varchar(255) character set utf8, + d varchar(255) character set utf8, + e varchar(255) character set utf8, + key (a,b,c,d,e)) engine=bdb; + +--echo End of 5.0 tests diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index cf0e08e2e66..a73ecf7c3eb 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1751,3 +1751,22 @@ insert into t2 values (4,_ucs2 0x05612020,_ucs2 0x05612020,'taken'); drop table t1; drop table t2; commit; + +# +# Test that we can create a large (>1K) key +# +create table t1 (a varchar(255) character set utf8, + b varchar(255) character set utf8, + c varchar(255) character set utf8, + d varchar(255) character set utf8, + key (a,b,c,d)) engine=innodb; +drop table t1; +--error ER_TOO_LONG_KEY +create table t1 (a varchar(255) character set utf8, + b varchar(255) character set utf8, + c varchar(255) character set utf8, + d varchar(255) character set utf8, + e varchar(255) character set utf8, + key (a,b,c,d,e)) engine=innodb; + +--echo End of 5.0 tests diff --git a/sql/unireg.h b/sql/unireg.h index 8f21dd1d2db..40499261a4d 100644 --- a/sql/unireg.h +++ b/sql/unireg.h @@ -50,11 +50,7 @@ #define MAX_SYS_VAR_LENGTH 32 #define MAX_KEY 64 /* Max used keys */ #define MAX_REF_PARTS 16 /* Max parts used as ref */ -#if SIZEOF_CHARP > 4 -#define MAX_KEY_LENGTH 3072 /* max possible key, if 64 bits */ -#else -#define MAX_KEY_LENGTH 1024 /* max possible key, if 32 bits */ -#endif +#define MAX_KEY_LENGTH 3072 /* max possible key */ #if SIZEOF_OFF_T > 4 #define MAX_REFLENGTH 8 /* Max length for record ref */ #else From 136c81732a36c3410c8a30aa64652b3c18679a0f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 23:22:20 +0300 Subject: [PATCH 62/69] Fix bug#15028 Multitable update returns different numbers of matched rows depending on table order multi_update::send_data() was counting updates, not updated rows. Thus if one record have several updates it will be counted several times in 'rows matched' but updated only once. multi_update::send_data() now counts only unique rows. sql/sql_update.cc: Fix bug#15028 Multitable update returns different numbers of matched rows depending on table order multi_update::send_data() now counts only unique rows. mysql-test/t/update.test: Test case for bug#15028 Multitable update returns different numbers of matched rows depending on table order mysql-test/r/update.result: Test case for bug#15028 Multitable update returns different numbers of matched rows depending on table order --- mysql-test/r/update.result | 13 +++++++++++++ mysql-test/t/update.test | 17 +++++++++++++++++ sql/sql_update.cc | 13 +++++++------ 3 files changed, 37 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 74c628f96c4..7854fd773a1 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -345,3 +345,16 @@ f1 2000-01-01 2002-02-02 drop table t1; +create table t1 (f1 int); +create table t2 (f2 int); +insert into t1 values(1),(2); +insert into t2 values(1),(1); +update t1,t2 set f1=3,f2=3 where f1=f2 and f1=1; +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +update t2 set f2=1; +update t1 set f1=1 where f1=3; +update t2,t1 set f1=3,f2=3 where f1=f2 and f1=1; +affected rows: 3 +info: Rows matched: 3 Changed: 3 Warnings: 0 +drop table t1,t2; diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index a21d10b6571..95adb40962c 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -270,4 +270,21 @@ insert into t1 values('2000-01-01'),('0000-00-00'); update t1 set f1='2002-02-02' where f1 is null; select * from t1; drop table t1; + +# +# Bug#15028 Multitable update returns different numbers of matched rows +# depending on table order +create table t1 (f1 int); +create table t2 (f2 int); +insert into t1 values(1),(2); +insert into t2 values(1),(1); +--enable_info +update t1,t2 set f1=3,f2=3 where f1=f2 and f1=1; +--disable_info +update t2 set f2=1; +update t1 set f1=1 where f1=3; +--enable_info +update t2,t1 set f1=3,f2=3 where f1=f2 and f1=1; +--disable_info +drop table t1,t2; # End of 4.1 tests diff --git a/sql/sql_update.cc b/sql/sql_update.cc index cb8064bef87..05e13c64aa7 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -1082,22 +1082,23 @@ bool multi_update::send_data(List ¬_used_values) int error; TABLE *tmp_table= tmp_tables[offset]; fill_record(tmp_table->field+1, *values_for_table[offset], 1); - found++; /* Store pointer to row */ memcpy((char*) tmp_table->field[0]->ptr, (char*) table->file->ref, table->file->ref_length); /* Write row, ignoring duplicated updates to a row */ - if ((error= tmp_table->file->write_row(tmp_table->record[0])) && - (error != HA_ERR_FOUND_DUPP_KEY && - error != HA_ERR_FOUND_DUPP_UNIQUE)) + if (error= tmp_table->file->write_row(tmp_table->record[0])) { - if (create_myisam_from_heap(thd, tmp_table, tmp_table_param + offset, - error, 1)) + if (error != HA_ERR_FOUND_DUPP_KEY && + error != HA_ERR_FOUND_DUPP_UNIQUE && + create_myisam_from_heap(thd, tmp_table, + tmp_table_param + offset, error, 1)) { do_update=0; DBUG_RETURN(1); // Not a table_is_full error } } + else + found++; } } DBUG_RETURN(0); From 025d8c14f64c9df4e5942de963234516adf7ffea Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 1 Dec 2005 15:10:35 -0800 Subject: [PATCH 63/69] Post-merge result file cleanup mysql-test/r/mysqldump.result: Fix results --- mysql-test/r/mysqldump.result | 132 ++++++++++++++++++---------------- 1 file changed, 69 insertions(+), 63 deletions(-) diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result index 7cc1cb10984..62d2b46e617 100644 --- a/mysql-test/r/mysqldump.result +++ b/mysql-test/r/mysqldump.result @@ -655,69 +655,6 @@ UNLOCK TABLES; /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; /*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; -create table t1 (a binary(1), b blob); -insert into t1 values ('',''); - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -DROP TABLE IF EXISTS `t1`; -CREATE TABLE `t1` ( - `a` binary(1) default NULL, - `b` blob -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - - -/*!40000 ALTER TABLE `t1` DISABLE KEYS */; -LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('',''); -UNLOCK TABLES; -/*!40000 ALTER TABLE `t1` ENABLE KEYS */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - - -/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; -/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; -/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; -/*!40101 SET NAMES utf8 */; -/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; -/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; -/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; -/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; -DROP TABLE IF EXISTS `t1`; -CREATE TABLE `t1` ( - `a` binary(1) default NULL, - `b` blob -) ENGINE=MyISAM DEFAULT CHARSET=latin1; - - -/*!40000 ALTER TABLE `t1` DISABLE KEYS */; -LOCK TABLES `t1` WRITE; -INSERT INTO `t1` VALUES ('',''); -UNLOCK TABLES; -/*!40000 ALTER TABLE `t1` ENABLE KEYS */; - -/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; -/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; -/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; -/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; -/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; -/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; -/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; - -drop table t1; /*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; /*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; @@ -2613,3 +2550,72 @@ DELIMITER ; DROP TRIGGER tr1; DROP TABLE t1; +create table t1 (a binary(1), b blob); +insert into t1 values ('',''); + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` binary(1) default NULL, + `b` blob +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES (0x00,''); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + + +/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */; +/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */; +/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */; +/*!40101 SET NAMES utf8 */; +/*!40103 SET @OLD_TIME_ZONE=@@TIME_ZONE */; +/*!40103 SET TIME_ZONE='+00:00' */; +/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */; +/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */; +/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' */; +/*!40111 SET @OLD_SQL_NOTES=@@SQL_NOTES, SQL_NOTES=0 */; +DROP TABLE IF EXISTS `t1`; +CREATE TABLE `t1` ( + `a` binary(1) default NULL, + `b` blob +) ENGINE=MyISAM DEFAULT CHARSET=latin1; + + +/*!40000 ALTER TABLE `t1` DISABLE KEYS */; +LOCK TABLES `t1` WRITE; +INSERT INTO `t1` VALUES (0x00,''); +UNLOCK TABLES; +/*!40000 ALTER TABLE `t1` ENABLE KEYS */; +/*!40103 SET TIME_ZONE=@OLD_TIME_ZONE */; + +/*!40101 SET SQL_MODE=@OLD_SQL_MODE */; +/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */; +/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */; +/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; +/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; +/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; +/*!40111 SET SQL_NOTES=@OLD_SQL_NOTES */; + +drop table t1; From a1a803b46cb6607111f7d74a97a34a3d0f14feac Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Dec 2005 09:27:06 +0100 Subject: [PATCH 64/69] BUG#15425 Small window for NF during backup failing without error ndb/src/kernel/blocks/backup/Backup.cpp: If crash 10018 is inserted on a 2 node cluster with fast CPU and slower disk, all nodes can respond with BACKUP_FRAGMENT_CONF for all fragments before the error in FSAPPENDCONF is hit. This would mean that no error code was set for the backup and that it would be incomplete as not all IO had been written to disk before the node crash. This would not be reported to the user. So the backup would appear to succeed but it really didn't. The window for this is rather small though. ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Assert is incorrect for testBackup NFSlave test (causes crash insert 10015 to fail) --- ndb/src/kernel/blocks/backup/Backup.cpp | 15 ++++++++++----- ndb/src/kernel/blocks/dbdict/Dbdict.cpp | 1 - 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp index 56af24c5cf0..9997d365fa4 100644 --- a/ndb/src/kernel/blocks/backup/Backup.cpp +++ b/ndb/src/kernel/blocks/backup/Backup.cpp @@ -786,13 +786,17 @@ Backup::checkNodeFail(Signal* signal, pos= &ref->nodeId - signal->getDataPtr(); break; } + case GSN_WAIT_GCP_REQ: + case GSN_DROP_TRIG_REQ: case GSN_CREATE_TRIG_REQ: case GSN_ALTER_TRIG_REQ: - case GSN_WAIT_GCP_REQ: + ptr.p->setErrorCode(AbortBackupOrd::BackupFailureDueToNodeFail); + return; case GSN_UTIL_SEQUENCE_REQ: case GSN_UTIL_LOCK_REQ: - case GSN_DROP_TRIG_REQ: return; + default: + ndbrequire(false); } for(Uint32 i = 0; (i = mask.find(i+1)) != NdbNodeBitmask::NotFound; ) @@ -1803,7 +1807,7 @@ Backup::execBACKUP_FRAGMENT_CONF(Signal* signal) const Uint32 nodeId = refToNode(signal->senderBlockRef()); const Uint32 noOfBytes = conf->noOfBytes; const Uint32 noOfRecords = conf->noOfRecords; - + BackupRecordPtr ptr; c_backupPool.getPtr(ptr, ptrI); @@ -1880,7 +1884,7 @@ Backup::execBACKUP_FRAGMENT_REF(Signal* signal) } } } - ndbrequire(false); + goto err; done: ptr.p->masterData.sendCounter--; @@ -1892,7 +1896,8 @@ done: masterAbort(signal, ptr); return; }//if - + +err: AbortBackupOrd *ord = (AbortBackupOrd*)signal->getDataPtrSend(); ord->backupId = ptr.p->backupId; ord->backupPtr = ptr.i; diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp index 5bd35812b47..6564963f61a 100644 --- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp +++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp @@ -11694,7 +11694,6 @@ Dbdict::alterTrigger_toDropLocal(Signal* signal, OpAlterTriggerPtr opPtr) // broken trigger allowed if force if (! (triggerPtr.p->triggerLocal & TriggerRecord::TL_CREATED_LQH)) { jam(); - ndbrequire(opPtr.p->m_requestFlag & RequestFlag::RF_FORCE); alterTrigger_sendReply(signal, opPtr, false); return; } From a9086bc75cbd676eb065ca660edab222df0b097e Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Dec 2005 14:30:42 +0100 Subject: [PATCH 65/69] Post-review fixes for BUG#14376: MySQL crash on scoped variable (re)initialization sql/sp_pcontext.cc: Count boundary for variable visibility from the frame end instead. sql/sp_pcontext.h: Count boundary for variable visibility from the frame end instead. Updated comments. sql/sql_yacc.yy: Changed tabs to spaces. --- sql/sp_pcontext.cc | 3 +-- sql/sp_pcontext.h | 17 +++++++++-------- sql/sql_yacc.yy | 10 +++++----- 3 files changed, 15 insertions(+), 15 deletions(-) diff --git a/sql/sp_pcontext.cc b/sql/sp_pcontext.cc index cca3e03d69c..f5ad7e31b43 100644 --- a/sql/sp_pcontext.cc +++ b/sql/sp_pcontext.cc @@ -150,7 +150,7 @@ sp_pcontext::diff_cursors(sp_pcontext *ctx) sp_pvar_t * sp_pcontext::find_pvar(LEX_STRING *name, my_bool scoped) { - uint i= m_pboundary; + uint i= m_pvar.elements - m_pboundary; while (i--) { @@ -186,7 +186,6 @@ sp_pcontext::push_pvar(LEX_STRING *name, enum enum_field_types type, p->offset= current_pvars(); p->dflt= NULL; insert_dynamic(&m_pvar, (gptr)&p); - m_pboundary= m_pvar.elements; } } diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h index fbeac37c058..24fd76f52fa 100644 --- a/sql/sp_pcontext.h +++ b/sql/sp_pcontext.h @@ -164,7 +164,6 @@ class sp_pcontext : public Sql_alloc { while (num--) pop_dynamic(&m_pvar); - m_pboundary= m_pvar.elements; } // Find by name @@ -184,12 +183,14 @@ class sp_pcontext : public Sql_alloc return p; } - // Set the current scope boundary (for default values) - // The argument is the number of variables to skip. + /* + Set the current scope boundary (for default values) + The argument is the number of variables to skip. + */ inline void declare_var_boundary(uint n) { - m_pboundary= m_pvar.elements-n; + m_pboundary= n; } // @@ -297,10 +298,10 @@ private: uint m_poffset; // Variable offset for this context uint m_coffset; // Cursor offset for this context /* - Boundary for finding variables in this in this context. - This is normally the same as m_pvar.elements, but differs during - parsing of DECLARE ... DEFAULT, to get the scope right for DEFAULT - values. + Boundary for finding variables in this context. This is the number + of variables currently "invisible" to default clauses. + This is normally 0, but will be larger during parsing of + DECLARE ... DEFAULT, to get the scope right for DEFAULT values. */ uint m_pboundary; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index c3c53b2f611..a2b6529663c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -1661,11 +1661,11 @@ sp_decls: sp_decl: DECLARE_SYM sp_decl_idents type { - LEX *lex= Lex; + LEX *lex= Lex; - lex->sphead->reset_lex(YYTHD); - lex->spcont->declare_var_boundary($2); - } + lex->sphead->reset_lex(YYTHD); + lex->spcont->declare_var_boundary($2); + } sp_opt_default { LEX *lex= Lex; @@ -1695,7 +1695,7 @@ sp_decl: lex->sphead->add_instr(in); ctx->set_default(i, it); } - ctx->declare_var_boundary(0); + ctx->declare_var_boundary(0); lex->sphead->restore_lex(YYTHD); $$.vars= $2; $$.conds= $$.hndlrs= $$.curs= 0; From 6a8935ca60133b259edc7e866cb34e0d7a20ff52 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Dec 2005 18:29:15 +0100 Subject: [PATCH 66/69] Bug #11731 mysqltest in multi-statement queries ignores errors in non-1st queries - Add tests to mysqltest.test - Problem no longer exists mysql-test/r/mysqltest.result: Update result file for new tests mysql-test/t/mysqltest.test: Add tests for bug#11731 --- mysql-test/r/mysqltest.result | 22 +++++++++++++++++ mysql-test/t/mysqltest.test | 46 +++++++++++++++++++++++++++++++++++ 2 files changed, 68 insertions(+) diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 54bdb1b45d8..56ee329fb28 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -391,3 +391,25 @@ root@localhost -------------------------------------------------------------------------------- this will be executed this will be executed +mysqltest: At line 2: query 'create table t1 (a int primary key); +insert into t1 values (1); +select 'select-me'; +insertz 'error query'' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz 'error query'' at line 1 +drop table t1; +drop table t1; +create table t1 (a int primary key); +insert into t1 values (1); +select 'select-me'; +insertz error query|||| +select-me +select-me +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz error query' at line 1 +drop table t1; +create table t1 (a int primary key); +insert into t1 values (1); +select 'select-me'; +insertz error query|||| +select-me +select-me +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz error query' at line 1 +drop table t1; diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 3d9dff4d373..6e56fac2f86 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -945,3 +945,49 @@ select "this will not be executed"; --enable_parsing select "this will be executed"; --enable_query_log + + +# +# Bug #11731 mysqltest in multi-statement queries ignores errors in +# non-1st queries +# + +# Failing multi statement query +--exec echo "delimiter ||||;" > var/tmp/bug11731.sql +--exec echo "create table t1 (a int primary key);" >> var/tmp/bug11731.sql +--exec echo "insert into t1 values (1);" >> var/tmp/bug11731.sql +--exec echo "select 'select-me';" >> var/tmp/bug11731.sql +--exec echo "insertz 'error query'||||" >> var/tmp/bug11731.sql +--exec echo "delimiter ;||||" >> var/tmp/bug11731.sql + +--error 1 +--exec $MYSQL_TEST -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql 2>&1 +drop table t1; + +--error 1 +--exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out +# The .out file should be empty, cat will fail! +--error 1 +--exec cat $MYSQL_TEST_DIR/var/tmp/bug11731.out +drop table t1; + + +# Using expected error +--exec echo "delimiter ||||;" > var/tmp/bug11731.sql +--exec echo "--error 1064" >> var/tmp/bug11731.sql +--exec echo "create table t1 (a int primary key);" >> var/tmp/bug11731.sql +--exec echo "insert into t1 values (1);" >> var/tmp/bug11731.sql +--exec echo "select 'select-me';" >> var/tmp/bug11731.sql +--exec echo "insertz "error query"||||" >> var/tmp/bug11731.sql +--exec echo "delimiter ;||||" >> var/tmp/bug11731.sql + +# These two should work since the error is expected +--exec $MYSQL_TEST -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql 2>&1 +drop table t1; + +--exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out +--exec cat $MYSQL_TEST_DIR/var/tmp/bug11731.out +drop table t1; + + + From 4fc48f319f170d74d3c29d94c99010d15b640c4f Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Dec 2005 21:05:23 +0300 Subject: [PATCH 67/69] query_cache.result: After merge fix mysql-test/r/query_cache.result: After merge fix --- mysql-test/r/query_cache.result | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 590f325cee7..405669e95f8 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -1022,6 +1022,31 @@ Variable_name Value Qcache_hits 1 drop table t1; create table t1 (a int); +flush status; +(select a from t1) union (select a from t1); +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 0 +(select a from t1) union (select a from t1); +a +show status like "Qcache_queries_in_cache"; +Variable_name Value +Qcache_queries_in_cache 1 +show status like "Qcache_inserts"; +Variable_name Value +Qcache_inserts 1 +show status like "Qcache_hits"; +Variable_name Value +Qcache_hits 1 +drop table t1; +create table t1 (a int); insert into t1 values (1),(2); CREATE PROCEDURE `p1`() begin @@ -1287,28 +1312,3 @@ Variable_name Value Last_query_cost 0.000000 drop table t1; SET GLOBAL query_cache_size=0; -create table t1 (a int); -flush status; -(select a from t1) union (select a from t1); -a -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 1 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 1 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 0 -(select a from t1) union (select a from t1); -a -show status like "Qcache_queries_in_cache"; -Variable_name Value -Qcache_queries_in_cache 1 -show status like "Qcache_inserts"; -Variable_name Value -Qcache_inserts 1 -show status like "Qcache_hits"; -Variable_name Value -Qcache_hits 1 -drop table t1; From 4202271065969a00c310f832cd496cb6f3c095e5 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Dec 2005 21:18:12 +0200 Subject: [PATCH 68/69] Now we shall store only position (index of first character) of SELECT from query begining, to be independet of query buffer allocation. Correct procedure used to find beginning of the current statement during parsing (BUG#14885). mysql-test/r/view.result: BUG#14885 test suite. mysql-test/t/view.test: BUG#14885 test suite. sql/sp_head.cc: The debug print statement fixed to prevent crash in case of NULL in m_next_cached_sp. sql/sql_lex.h: Now we shall store only position (index of first character) of SELECT from query beginning. sql/sql_view.cc: Position of the SELECT used to output it to .frm. sql/sql_yacc.yy: Now we shall store only position (index of first character) of SELECT from query beginning. Correct procedure used to find beginning of the current statement during parsing. --- mysql-test/r/view.result | 12 ++++++++++++ mysql-test/t/view.test | 19 +++++++++++++++++++ sql/sp_head.cc | 8 ++++++-- sql/sql_lex.h | 4 ++-- sql/sql_view.cc | 5 ++--- sql/sql_yacc.yy | 16 ++++++++++++---- 6 files changed, 53 insertions(+), 11 deletions(-) diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index ebb2c190eb1..5da6a4f95fd 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -2424,3 +2424,15 @@ f1 sum(f2) NULL 12 drop view v1; drop table t1; +drop procedure if exists p1; +create procedure p1 () deterministic +begin +create view v1 as select 1; +end; +// +call p1(); +show create view v1; +View Create View +v1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select 1 AS `1` +drop view v1; +drop procedure p1; diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index ac103278f08..be4fb571320 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -2280,3 +2280,22 @@ create view v1 as select * from t1; select f1, sum(f2) from v1 group by f1; drop view v1; drop table t1; + +# +# BUG#14885: incorrect SOURCE in view created in a procedure +# TODO: here SOURCE string must be shown when it will be possible +# +--disable_warnings +drop procedure if exists p1; +--enable_warnings +delimiter //; +create procedure p1 () deterministic +begin +create view v1 as select 1; +end; +// +delimiter ;// +call p1(); +show create view v1; +drop view v1; +drop procedure p1; diff --git a/sql/sp_head.cc b/sql/sp_head.cc index a6e88c08789..179eebc0caf 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -954,8 +954,12 @@ int sp_head::execute(THD *thd) m_first_instance->m_first_free_instance= m_next_cached_sp; DBUG_PRINT("info", ("first free for 0x%lx ++: 0x%lx->0x%lx, level: %lu, flags %x", (ulong)m_first_instance, this, m_next_cached_sp, - m_next_cached_sp->m_recursion_level, - m_next_cached_sp->m_flags)); + (m_next_cached_sp ? + m_next_cached_sp->m_recursion_level : + 0), + (m_next_cached_sp ? + m_next_cached_sp->m_flags : + 0))); /* Check that if there are not any instances after this one then pointer to the last instance points on this instance or if there are diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 372bbc5576b..c3198beb4e9 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -738,8 +738,8 @@ typedef struct st_lex TABLE_LIST **query_tables_last; /* store original leaf_tables for INSERT SELECT and PS/SP */ TABLE_LIST *leaf_tables_insert; - char *create_view_start; - char *create_view_select_start; + /* Position (first character index) of SELECT of CREATE VIEW statement */ + uint create_view_select_start; /* The definer of the object being created (view, trigger, stored routine). diff --git a/sql/sql_view.cc b/sql/sql_view.cc index e03d3b22b89..3ca592dfd44 100644 --- a/sql/sql_view.cc +++ b/sql/sql_view.cc @@ -641,10 +641,9 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view, /* fill structure */ view->query.str= (char*)str.ptr(); view->query.length= str.length()-1; // we do not need last \0 - view->source.str= thd->lex->create_view_select_start; + view->source.str= thd->query + thd->lex->create_view_select_start; view->source.length= (thd->query_length - - (thd->lex->create_view_select_start - - thd->lex->create_view_start)); + thd->lex->create_view_select_start); view->file_version= 1; view->calc_md5(md5); view->md5.str= md5; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 671e2b1740d..88cc224308c 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -3374,7 +3374,6 @@ alter: THD *thd= YYTHD; LEX *lex= thd->lex; lex->sql_command= SQLCOM_CREATE_VIEW; - lex->create_view_start= thd->query; lex->create_view_mode= VIEW_ALTER; /* first table in list is target VIEW name */ lex->select_lex.add_table_to_list(thd, $6, NULL, 0); @@ -8978,7 +8977,6 @@ view_tail: THD *thd= YYTHD; LEX *lex= thd->lex; lex->sql_command= SQLCOM_CREATE_VIEW; - lex->create_view_start= thd->query; /* first table in list is target VIEW name */ if (!lex->select_lex.add_table_to_list(thd, $3, NULL, 0)) YYABORT; @@ -9009,11 +9007,21 @@ view_list: view_select: SELECT_SYM remember_name select_init2 { - Lex->create_view_select_start= $2; + THD *thd=YYTHD; + LEX *lex= thd->lex; + char *stmt_beg= (lex->sphead ? + (char *)lex->sphead->m_tmp_query : + thd->query); + lex->create_view_select_start= $2 - stmt_beg; } | '(' remember_name select_paren ')' union_opt { - Lex->create_view_select_start= $2; + THD *thd=YYTHD; + LEX *lex= thd->lex; + char *stmt_beg= (lex->sphead ? + (char *)lex->sphead->m_tmp_query : + thd->query); + lex->create_view_select_start= $2 - stmt_beg; } ; From eeec92c50b66e105a3e9f1420cca55d4f755d551 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 2 Dec 2005 22:43:56 +0300 Subject: [PATCH 69/69] Add a test case for Bug#5967 "Stored procedure declared variable used instead of column", the bug is to be fixed later. mysql-test/r/sp.result: Test results were fixed (Bug#5967) --- mysql-test/r/sp.result | 54 ++++++++++++++++++++++++++++++++++++++++++ mysql-test/t/sp.test | 45 +++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 9ea43e5aeb3..6f0a8623a4c 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4099,4 +4099,58 @@ call bug14376(4711)| x 4711 drop procedure bug14376| +drop procedure if exists p1| +Warnings: +Note 1305 PROCEDURE p1 does not exist +drop table if exists t1| +create table t1 (a varchar(255))| +insert into t1 (a) values ("a - table column")| +create procedure p1(a varchar(255)) +begin +declare i varchar(255); +declare c cursor for select a from t1; +select a; +select a from t1 into i; +select i as 'Parameter takes precedence over table column'; open c; +fetch c into i; +close c; +select i as 'Parameter takes precedence over table column in cursors'; +begin +declare a varchar(255) default 'a - local variable'; +declare c1 cursor for select a from t1; +select a as 'A local variable takes precedence over parameter'; +open c1; +fetch c1 into i; +close c1; +select i as 'A local variable takes precedence over parameter in cursors'; +begin +declare a varchar(255) default 'a - local variable in a nested compound statement'; +declare c2 cursor for select a from t1; +select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement'; +select a from t1 into i; +select i as 'A local variable in a nested compound statement takes precedence over table column'; +open c2; +fetch c2 into i; +close c2; +select i as 'A local variable in a nested compound statement takes precedence over table column in cursors'; +end; +end; +end| +call p1("a - stored procedure parameter")| +a +a - stored procedure parameter +Parameter takes precedence over table column +a - stored procedure parameter +Parameter takes precedence over table column in cursors +a - stored procedure parameter +A local variable takes precedence over parameter +a - local variable +A local variable takes precedence over parameter in cursors +a - local variable +A local variable in a nested compound statement takes precedence over a local variable in the outer statement +a - local variable in a nested compound statement +A local variable in a nested compound statement takes precedence over table column +a - local variable in a nested compound statement +A local variable in a nested compound statement takes precedence over table column in cursors +a - local variable in a nested compound statement drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 0563835de09..760110b0a64 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -4898,7 +4898,52 @@ call bug14376(4711)| drop procedure bug14376| +# +# Bug#5967 "Stored procedure declared variable used instead of column" +# The bug should be fixed later. +# Test precedence of names of parameters, variable declarations, +# variable declarations in nested compound statements, table columns, +# table columns in cursor declarations. +# According to the standard, table columns take precedence over +# variable declarations. In MySQL 5.0 it's vice versa. +# +drop procedure if exists p1| +drop table if exists t1| +create table t1 (a varchar(255))| +insert into t1 (a) values ("a - table column")| +create procedure p1(a varchar(255)) +begin + declare i varchar(255); + declare c cursor for select a from t1; + select a; + select a from t1 into i; + select i as 'Parameter takes precedence over table column'; open c; + fetch c into i; + close c; + select i as 'Parameter takes precedence over table column in cursors'; + begin + declare a varchar(255) default 'a - local variable'; + declare c1 cursor for select a from t1; + select a as 'A local variable takes precedence over parameter'; + open c1; + fetch c1 into i; + close c1; + select i as 'A local variable takes precedence over parameter in cursors'; + begin + declare a varchar(255) default 'a - local variable in a nested compound statement'; + declare c2 cursor for select a from t1; + select a as 'A local variable in a nested compound statement takes precedence over a local variable in the outer statement'; + select a from t1 into i; + select i as 'A local variable in a nested compound statement takes precedence over table column'; + open c2; + fetch c2 into i; + close c2; + select i as 'A local variable in a nested compound statement takes precedence over table column in cursors'; + end; + end; +end| +call p1("a - stored procedure parameter")| # # BUG#NNNN: New bug synopsis