From f1ff71072808e452b201b448811a0e0474510d05 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 9 Oct 2003 00:13:15 +0300 Subject: [PATCH 01/13] added worning about changing requested size of query cache (BUG#1502) include/mysqld_error.h: new warning mysql-test/r/query_cache.result: new warning sql/set_var.cc: issue warning is size changed in other way sql/share/czech/errmsg.txt: new warning sql/share/danish/errmsg.txt: new warning sql/share/dutch/errmsg.txt: new warning sql/share/english/errmsg.txt: new warning sql/share/estonian/errmsg.txt: new warning sql/share/french/errmsg.txt: new warning sql/share/german/errmsg.txt: new warning sql/share/greek/errmsg.txt: new warning sql/share/hungarian/errmsg.txt: new warning sql/share/italian/errmsg.txt: new warning sql/share/japanese/errmsg.txt: new warning sql/share/korean/errmsg.txt: new warning sql/share/norwegian-ny/errmsg.txt: new warning sql/share/norwegian/errmsg.txt: new warning sql/share/polish/errmsg.txt: new warning sql/share/portuguese/errmsg.txt: new warning sql/share/romanian/errmsg.txt: new warning sql/share/russian/errmsg.txt: new warning sql/share/serbian/errmsg.txt: new warning sql/share/slovak/errmsg.txt: new warning sql/share/spanish/errmsg.txt: new warning sql/share/swedish/errmsg.txt: new warning sql/share/ukrainian/errmsg.txt: new warning --- include/mysqld_error.h | 3 ++- mysql-test/r/query_cache.result | 8 ++++++++ sql/set_var.cc | 5 +++++ sql/share/czech/errmsg.txt | 1 + sql/share/danish/errmsg.txt | 1 + sql/share/dutch/errmsg.txt | 1 + sql/share/english/errmsg.txt | 1 + sql/share/estonian/errmsg.txt | 1 + sql/share/french/errmsg.txt | 1 + sql/share/german/errmsg.txt | 1 + sql/share/greek/errmsg.txt | 1 + sql/share/hungarian/errmsg.txt | 1 + sql/share/italian/errmsg.txt | 1 + sql/share/japanese/errmsg.txt | 1 + sql/share/korean/errmsg.txt | 1 + sql/share/norwegian-ny/errmsg.txt | 1 + sql/share/norwegian/errmsg.txt | 1 + sql/share/polish/errmsg.txt | 1 + sql/share/portuguese/errmsg.txt | 1 + sql/share/romanian/errmsg.txt | 1 + sql/share/russian/errmsg.txt | 1 + sql/share/serbian/errmsg.txt | 1 + sql/share/slovak/errmsg.txt | 1 + sql/share/spanish/errmsg.txt | 1 + sql/share/swedish/errmsg.txt | 1 + sql/share/ukrainian/errmsg.txt | 1 + 26 files changed, 38 insertions(+), 1 deletion(-) diff --git a/include/mysqld_error.h b/include/mysqld_error.h index 3c20202603f..a280dbc5223 100644 --- a/include/mysqld_error.h +++ b/include/mysqld_error.h @@ -295,4 +295,5 @@ #define ER_BAD_SLAVE_UNTIL_COND 1276 #define ER_MISSING_SKIP_SLAVE 1277 #define ER_UNTIL_COND_IGNORED 1278 -#define ER_ERROR_MESSAGES 279 +#define ER_WARN_QC_RESIZE 1279 +#define ER_ERROR_MESSAGES 280 diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index a6aca2f983c..3a3a8d99348 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -579,24 +579,32 @@ query_cache_size 0 select * from t1; a set GLOBAL query_cache_size=1024; +Warnings: +Warning 1279 Query cache failed to set size 1024, new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 select * from t1; a set GLOBAL query_cache_size=10240; +Warnings: +Warning 1279 Query cache failed to set size 10240, new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 select * from t1; a set GLOBAL query_cache_size=20480; +Warnings: +Warning 1279 Query cache failed to set size 20480, new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 select * from t1; a set GLOBAL query_cache_size=40960; +Warnings: +Warning 1279 Query cache failed to set size 40960, new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 diff --git a/sql/set_var.cc b/sql/set_var.cc index a5024363545..dc3df660d9b 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -801,7 +801,12 @@ static void fix_net_retry_count(THD *thd __attribute__(unused), static void fix_query_cache_size(THD *thd, enum_var_type type) { #ifdef HAVE_QUERY_CACHE + ulong requested= query_cache_size; query_cache.resize(query_cache_size); + if (requested != query_cache_size) + push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_WARN, + ER_WARN_QC_RESIZE, ER(ER_WARN_QC_RESIZE), + requested, query_cache_size); #endif } diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt index 29d8b255251..2b22419f488 100644 --- a/sql/share/czech/errmsg.txt +++ b/sql/share/czech/errmsg.txt @@ -291,3 +291,4 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt index d603555727b..4acb5c5c222 100644 --- a/sql/share/danish/errmsg.txt +++ b/sql/share/danish/errmsg.txt @@ -285,3 +285,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt index 53a19464745..31da5acc391 100644 --- a/sql/share/dutch/errmsg.txt +++ b/sql/share/dutch/errmsg.txt @@ -293,3 +293,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt index c54f56b2529..fafc524a239 100644 --- a/sql/share/english/errmsg.txt +++ b/sql/share/english/errmsg.txt @@ -282,3 +282,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt index 2997a4d4501..f76d92683ef 100644 --- a/sql/share/estonian/errmsg.txt +++ b/sql/share/estonian/errmsg.txt @@ -287,3 +287,4 @@ character-set=latin7 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt index cd346270ea8..19ab8d1833e 100644 --- a/sql/share/french/errmsg.txt +++ b/sql/share/french/errmsg.txt @@ -282,3 +282,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt index 4fd38fdb6da..74411aee53f 100644 --- a/sql/share/german/errmsg.txt +++ b/sql/share/german/errmsg.txt @@ -291,3 +291,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt index 31259e9e02f..469eec15a52 100644 --- a/sql/share/greek/errmsg.txt +++ b/sql/share/greek/errmsg.txt @@ -282,3 +282,4 @@ character-set=greek "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt index 52dfb702231..1f7c2dd9c61 100644 --- a/sql/share/hungarian/errmsg.txt +++ b/sql/share/hungarian/errmsg.txt @@ -284,3 +284,4 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt index 7efca542348..560444bd163 100644 --- a/sql/share/italian/errmsg.txt +++ b/sql/share/italian/errmsg.txt @@ -282,3 +282,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt index f7d6d7be29b..38f8da64220 100644 --- a/sql/share/japanese/errmsg.txt +++ b/sql/share/japanese/errmsg.txt @@ -284,3 +284,4 @@ character-set=ujis "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt index 654081c6895..2c9095987da 100644 --- a/sql/share/korean/errmsg.txt +++ b/sql/share/korean/errmsg.txt @@ -282,3 +282,4 @@ character-set=euckr "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt index 76f725a9419..e8040bed116 100644 --- a/sql/share/norwegian-ny/errmsg.txt +++ b/sql/share/norwegian-ny/errmsg.txt @@ -284,3 +284,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt index fe15f7c9b8b..1dd306752ff 100644 --- a/sql/share/norwegian/errmsg.txt +++ b/sql/share/norwegian/errmsg.txt @@ -284,3 +284,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt index 12e1d539e76..f9704e0014e 100644 --- a/sql/share/polish/errmsg.txt +++ b/sql/share/polish/errmsg.txt @@ -286,3 +286,4 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt index 49ca7ee5c56..b5dc8b35b23 100644 --- a/sql/share/portuguese/errmsg.txt +++ b/sql/share/portuguese/errmsg.txt @@ -283,3 +283,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt index 30e87fe3d0a..ec902d958df 100644 --- a/sql/share/romanian/errmsg.txt +++ b/sql/share/romanian/errmsg.txt @@ -286,3 +286,4 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt index b444348612f..94a71bec96e 100644 --- a/sql/share/russian/errmsg.txt +++ b/sql/share/russian/errmsg.txt @@ -284,3 +284,4 @@ character-set=koi8r "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Кеш запросов не может установить размер %lu, новый размер кеша зпросов - %lu", diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt index 32b94548bc5..a0418808f8e 100644 --- a/sql/share/serbian/errmsg.txt +++ b/sql/share/serbian/errmsg.txt @@ -277,3 +277,4 @@ character-set=cp1250 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt index 45e40caedee..60947ea3d06 100644 --- a/sql/share/slovak/errmsg.txt +++ b/sql/share/slovak/errmsg.txt @@ -290,3 +290,4 @@ character-set=latin2 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt index bce03456941..591684817cf 100644 --- a/sql/share/spanish/errmsg.txt +++ b/sql/share/spanish/errmsg.txt @@ -284,3 +284,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt index 827419d76e7..51a916e012d 100644 --- a/sql/share/swedish/errmsg.txt +++ b/sql/share/swedish/errmsg.txt @@ -282,3 +282,4 @@ character-set=latin1 "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Query cache failed to set size %lu, new query cache size is %lu", diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt index fcf0c695c29..5ae8e25b870 100644 --- a/sql/share/ukrainian/errmsg.txt +++ b/sql/share/ukrainian/errmsg.txt @@ -287,3 +287,4 @@ character-set=koi8u "Wrong parameter or combination of parameters for START SLAVE UNTIL" "It is recommended to run with --skip-slave-start when doing step-by-step replication with START SLAVE UNTIL, otherwise you are not safe in case of unexpected slave's mysqld restart" "SQL thread is not to be started so UNTIL options are ignored" +"Кеш запит╕в неспроможен встановити розм╕р %lu, новий розм╕р кеша запит╕в - %lu", From 1ba35900d661ef789257193541d472ced62d464c Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 24 Oct 2003 20:09:57 +0300 Subject: [PATCH 02/13] made 'TODO' --- sql/sql_parse.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index e8870b20d99..c4f70a6bfb3 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3668,7 +3668,6 @@ mysql_new_select(LEX *lex, bool move_down) unit->link_prev= 0; unit->return_to= lex->current_select; select_lex->include_down(unit); - // TODO: assign resolve_mode for fake subquery after merging with new tree } else { @@ -3688,6 +3687,7 @@ mysql_new_select(LEX *lex, bool move_down) fake->make_empty_select(); fake->linkage= GLOBAL_OPTIONS_TYPE; fake->select_limit= lex->thd->variables.select_limit; + fake->resolve_mode= SELECT_LEX::SELECT_MODE; } } From 7f6d7aa1dda116d0d89d87616256aa536707fcdd Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Oct 2003 01:38:42 +0300 Subject: [PATCH 03/13] sql_parse.cc: URGENT: MONTY AND SERGEI should check this patch! The patch fixes the memory corruption reported by a user. It happened because the code did not keep correct a count of how many connections a user has, and the user object got freed too soon if the same user had more than 1 connection. Also fix a typo by Sanja: 'and' is not a C operator, I think it should be && sql/sql_parse.cc: URGENT: MONTY AND SERGEI should check this patch! The patch fixes the memory corruption reported by a user. It happened because the code did not keep correct a count of how many connections a user has, and the user object got freed too soon if the same user had more than 1 connection. Also fix a typo by Sanja: 'and' is not a C operator, I think it should be && --- sql/sql_parse.cc | 56 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 48 insertions(+), 8 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 00d7f190fc8..361a678164c 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -157,7 +157,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, uc->user_len= user_len; uc->host=uc->user + uc->user_len + 1; uc->len = temp_len; - uc->connections = 1; + uc->connections = 0; /* BUG FIX by Heikki Oct 25, 2003 */ uc->questions=uc->updates=uc->conn_per_hour=0; uc->user_resources=*mqh; if (max_user_connections && mqh->connections > max_user_connections) @@ -314,11 +314,29 @@ int check_user(THD *thd, enum enum_server_command command, thd->db_access=0; /* Don't allow user to connect if he has done too many queries */ - if ((ur.questions || ur.updates || - ur.connections || max_user_connections) && + + /* + BUG FIX by Heikki Oct 25, 2003: since get_or_create_user_conn() + creates or finds the user object and does NOT check anything about ur, + we should call it always. + */ + + if ( /* (ur.questions || ur.updates || + ur.connections || max_user_connections) && */ get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur)) DBUG_RETURN(1); - if (thd->user_connect && thd->user_connect->user_resources.connections && + + /* + BUG FIX by Heikki Oct 25, 2003: since + check_for_max_user_connections() keeps the count of user connections, + and we delete the user object when the number of connections drops to + zero, we must call it always to keep the count right! Otherwise the + user object can get deleted too early, which caused memory corruption + to a user in Oct 2003. + */ + + if (thd->user_connect && + /* thd->user_connect->user_resources.connections && */ check_for_max_user_connections(thd, thd->user_connect)) DBUG_RETURN(1); @@ -390,6 +408,13 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) int error=0; DBUG_ENTER("check_for_max_user_connections"); + /* + FIX by Heikki Oct 25, 2003: protect the operation with a mutex: is there + a race condition here otherwise? + */ + + (void) pthread_mutex_lock(&LOCK_user_conn); + if (max_user_connections && (max_user_connections < (uint) uc->connections)) { @@ -397,7 +422,9 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) error=1; goto end; } + uc->connections++; + if (uc->user_resources.connections && uc->conn_per_hour++ >= uc->user_resources.connections) { @@ -407,6 +434,9 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) error=1; } end: + + (void) pthread_mutex_unlock(&LOCK_user_conn); + DBUG_RETURN(error); } @@ -414,13 +444,23 @@ end: static void decrease_user_connections(USER_CONN *uc) { DBUG_ENTER("decrease_user_connections"); + + /* + FIX by Heikki Oct 25, 2003: protect the operation with a mutex: is there + a race condition here otherwise? + */ + + (void) pthread_mutex_lock(&LOCK_user_conn); + if ((uc->connections && !--uc->connections) && !mqh_used) { /* Last connection for user; Delete it */ - (void) pthread_mutex_lock(&LOCK_user_conn); + (void) hash_delete(&hash_user_connections,(byte*) uc); - (void) pthread_mutex_unlock(&LOCK_user_conn); } + + (void) pthread_mutex_unlock(&LOCK_user_conn); + DBUG_VOID_RETURN; } @@ -4673,10 +4713,10 @@ Item * all_any_subquery_creator(Item *left_expr, bool all, SELECT_LEX *select_lex) { - if ((cmp == &comp_eq_creator) and !all) // = ANY <=> IN + if ((cmp == &comp_eq_creator) && !all) // = ANY <=> IN return new Item_in_subselect(left_expr, select_lex); - if ((cmp == &comp_ne_creator) and all) // <> ALL <=> NOT IN + if ((cmp == &comp_ne_creator) && all) // <> ALL <=> NOT IN return new Item_func_not(new Item_in_subselect(left_expr, select_lex)); Item_allany_subselect *it= From d679b52e0fdef5f7dfc8117a6bd3e2db1c922f1a Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Oct 2003 16:29:35 +0300 Subject: [PATCH 04/13] fixed unlinking SELECT methods --- sql/sql_lex.cc | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 5b05bf096cb..352a79843a9 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -1112,8 +1112,11 @@ void st_select_lex_unit::exclude_level() SELECT_LEX_UNIT *units= 0, **units_last= &units; for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { + // unlink current level from global SELECTs list if (sl->link_prev && (*sl->link_prev= sl->link_next)) sl->link_next->link_prev= sl->link_prev; + + // bring up underlay levels SELECT_LEX_UNIT **last= 0; for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit()) { @@ -1128,11 +1131,20 @@ void st_select_lex_unit::exclude_level() } if (units) { + // include brought up levels in place of current (*prev)= units; (*units_last)= (SELECT_LEX_UNIT*)next; + if (next) + next->prev= (SELECT_LEX_NODE**)units_last; + units->prev= prev; } else + { + // exclude currect unit from list of nodes (*prev)= next; + if (next) + next->prev= prev; + } } @@ -1147,15 +1159,20 @@ void st_select_lex_unit::exclude_tree() SELECT_LEX_UNIT *units= 0, **units_last= &units; for (SELECT_LEX *sl= first_select(); sl; sl= sl->next_select()) { + // unlink current level from global SELECTs list if (sl->link_prev && (*sl->link_prev= sl->link_next)) sl->link_next->link_prev= sl->link_prev; + // unlink underlay levels for (SELECT_LEX_UNIT *u= sl->first_inner_unit(); u; u= u->next_unit()) { u->exclude_level(); } } + // exclude currect unit from list of nodes (*prev)= next; + if (next) + next->prev= prev; } From 3affc8103a78da77251b7d6c387541d872832708 Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Oct 2003 15:53:41 +0200 Subject: [PATCH 05/13] A major overhaul to adopt to recent changes. It now passes all tests. Note: - All test results haven't been inspected in detail to see if they are correct. - Some result set printing seems to have the wrong field width; most notably date/time fields and type fields (e.g. "int(4)"). - There are still some valgrind complaints, but they seem to be in assert() or in libmysql. tests/client_test.c: A major overhaul to adopt to recent changes: - SHOW TABLE result has changed (more columns) - EXPLAIN result has VAR_STRING types now - Added missing mysql_bind_result() calls - Adopted to mysql_fetch_column() semantics: Don't use same pointers in MYSQL_BIND structs for fetch_column as for binding. - Removed a number of duplicated calls to tests - Added missing initialization of MYSQL_BIND structs fields (lenght fields), to shutup valgrind. --- tests/client_test.c | 216 ++++++++++++++++++++++++++++---------------- 1 file changed, 138 insertions(+), 78 deletions(-) diff --git a/tests/client_test.c b/tests/client_test.c index 388d5743cfb..bae47a19f97 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -1289,6 +1289,8 @@ static void test_double_compare() /* tinyint */ bind[0].buffer_type=FIELD_TYPE_TINY; bind[0].buffer=(char *)&tiny_data; + bind[0].buffer_length= 0; + bind[0].length= 0; bind[0].is_null= 0; /* Can never be null */ /* string->float */ @@ -1302,6 +1304,8 @@ static void test_double_compare() /* double */ bind[2].buffer_type=FIELD_TYPE_DOUBLE; bind[2].buffer= (char *)&double_data; + bind[2].buffer_length= 0; + bind[2].length= 0; bind[2].is_null= 0; tiny_data = 1; @@ -1369,6 +1373,7 @@ static void test_null() bind[0].buffer_type=MYSQL_TYPE_LONG; bind[0].is_null= &is_null[0]; + bind[0].length= 0; is_null[0]= 1; bind[1]=bind[0]; @@ -1742,6 +1747,8 @@ static void test_select() bind[0].buffer=(char *)&nData; bind[0].buffer_type=FIELD_TYPE_LONG; + bind[0].buffer_length= 0; + bind[0].length= 0; bind[0].is_null= 0; rc = mysql_bind_param(stmt,bind); @@ -1848,7 +1855,6 @@ static void test_bug1180() MYSQL_BIND bind[1]; ulong length[1]; char szData[11]; - int nData=1; myheader("test_select_bug"); @@ -2035,6 +2041,8 @@ static void test_simple_update() bind[1].buffer=(char *) &nData; bind[1].buffer_type=FIELD_TYPE_LONG; + bind[1].buffer_length= 0; + bind[1].length= 0; bind[1].is_null= 0; rc = mysql_bind_param(stmt,bind); @@ -2105,6 +2113,8 @@ static void test_long_data() bind[0].buffer=(char *)&int_data; bind[0].buffer_type=FIELD_TYPE_LONG; bind[0].is_null=0; + bind[0].buffer_length= 0; + bind[0].length= 0; bind[1].buffer_type=FIELD_TYPE_STRING; bind[1].is_null=0; @@ -2191,6 +2201,8 @@ static void test_long_data_str() bind[0].buffer = (char *)&length; bind[0].buffer_type = FIELD_TYPE_LONG; bind[0].is_null= &is_null[0]; + bind[0].buffer_length= 0; + bind[0].length= 0; is_null[0]=0; length= 0; @@ -2368,6 +2380,8 @@ static void test_long_data_bin() bind[0].buffer = (char *)&length; bind[0].buffer_type = FIELD_TYPE_LONG; + bind[0].buffer_length= 0; + bind[0].length= 0; bind[0].is_null= 0; length= 0; @@ -2470,6 +2484,8 @@ static void test_simple_delete() bind[0].buffer=(char *)&nData; bind[0].buffer_type=FIELD_TYPE_LONG; + bind[0].buffer_length= 0; + bind[0].length= 0; bind[0].is_null= 0; rc = mysql_bind_param(stmt,bind); @@ -2547,6 +2563,8 @@ static void test_update() bind[1].buffer=(char *)&nData; bind[1].buffer_type=FIELD_TYPE_LONG; + bind[1].buffer_length= 0; + bind[1].length= 0; bind[1].is_null= 0; rc = mysql_bind_param(stmt,bind); @@ -2573,6 +2591,8 @@ static void test_update() length[0]= my_sprintf(szData, (szData, "updated-data")); bind[1].buffer=(char *)&nData; bind[1].buffer_type=FIELD_TYPE_LONG; + bind[1].buffer_length= 0; + bind[1].length= 0; bind[1].is_null= 0; rc = mysql_bind_param(stmt,bind); @@ -2917,24 +2937,31 @@ static void test_bind_result_ext1() bind[1].buffer_type=MYSQL_TYPE_FLOAT; bind[1].buffer=(char *)&s_data; + bind[1].buffer_length= 0; bind[2].buffer_type=MYSQL_TYPE_SHORT; bind[2].buffer=(char *)&i_data; + bind[2].buffer_length= 0; bind[3].buffer_type=MYSQL_TYPE_TINY; bind[3].buffer=(char *)&b_data; + bind[3].buffer_length= 0; bind[4].buffer_type=MYSQL_TYPE_LONG; bind[4].buffer=(char *)&f_data; + bind[4].buffer_length= 0; bind[5].buffer_type=MYSQL_TYPE_STRING; bind[5].buffer=(char *)d_data; + bind[5].buffer_length= sizeof(d_data); bind[6].buffer_type=MYSQL_TYPE_LONG; bind[6].buffer=(char *)&bData; + bind[6].buffer_length= 0; bind[7].buffer_type=MYSQL_TYPE_DOUBLE; bind[7].buffer=(char *)&szData; + bind[7].buffer_length= 0; for (i= 0; i < array_elements(bind); i++) { @@ -3011,6 +3038,7 @@ static void bind_fetch(int row_count) { bind[i].buffer_type= MYSQL_TYPE_LONG; bind[i].buffer= (char *) &data[i]; + bind[i].length= 0; bind[i].is_null= 0; } rc = mysql_bind_param(stmt, bind); @@ -3564,7 +3592,11 @@ static void test_prepare_ext() bind[5].buffer= (char *)&bData; for (i= 0; i < array_elements(bind); i++) + { bind[i].is_null=0; + bind[i].buffer_length= 0; + bind[i].length= 0; + } rc = mysql_bind_param(stmt,bind); mystmt(stmt, rc); @@ -3955,6 +3987,8 @@ static void test_stmt_close() count= 100; bind[0].buffer=(char *)&count; bind[0].buffer_type=MYSQL_TYPE_LONG; + bind[0].buffer_length= 0; + bind[0].length= 0; bind[0].is_null=0; rc = mysql_bind_param(stmt_x, bind); @@ -4387,12 +4421,14 @@ static void test_multi_stmt() bind[0].buffer_type= MYSQL_TYPE_SHORT; bind[0].buffer= (char *)&id; bind[0].is_null= &is_null[0]; + bind[0].buffer_length= 0; bind[0].length= &length[0]; is_null[0]= 0; length[0]= 0; bind[1].buffer_type = MYSQL_TYPE_STRING; bind[1].buffer = (char *)name; + bind[1].buffer_length= sizeof(name); bind[1].length = &length[1]; bind[1].is_null= &is_null[1]; @@ -4650,8 +4686,11 @@ static void test_prepare_alter() verify_param_count(stmt,1); + is_null= 0; bind[0].buffer_type= MYSQL_TYPE_SHORT; bind[0].buffer= (char *)&id; + bind[0].buffer_length= 0; + bind[0].length= 0; bind[0].is_null= &is_null; rc = mysql_bind_param(stmt, bind); @@ -6359,7 +6398,7 @@ static void test_frm_bug() mytest(row); fprintf(stdout,"\n Comment: %s", row[15]); - myassert(row[15] != 0); + myassert(row[17] != 0); mysql_free_result(result); mysql_stmt_close(stmt); @@ -6503,22 +6542,22 @@ static void test_explain_bug() mysql_num_fields(result)); myassert(6 == mysql_num_fields(result)); - verify_prepare_field(result,0,"Field","",MYSQL_TYPE_STRING, + verify_prepare_field(result,0,"Field","",MYSQL_TYPE_VAR_STRING, "","","",NAME_LEN,0); - verify_prepare_field(result,1,"Type","",MYSQL_TYPE_STRING, + verify_prepare_field(result,1,"Type","",MYSQL_TYPE_VAR_STRING, "","","",40,0); - verify_prepare_field(result,2,"Null","",MYSQL_TYPE_STRING, + verify_prepare_field(result,2,"Null","",MYSQL_TYPE_VAR_STRING, "","","",1,0); - verify_prepare_field(result,3,"Key","",MYSQL_TYPE_STRING, + verify_prepare_field(result,3,"Key","",MYSQL_TYPE_VAR_STRING, "","","",3,0); - verify_prepare_field(result,4,"Default","",MYSQL_TYPE_STRING, + verify_prepare_field(result,4,"Default","",MYSQL_TYPE_VAR_STRING, "","","",NAME_LEN,0); - verify_prepare_field(result,5,"Extra","",MYSQL_TYPE_STRING, + verify_prepare_field(result,5,"Extra","",MYSQL_TYPE_VAR_STRING, "","","",20,0); mysql_free_result(result); @@ -6542,31 +6581,31 @@ static void test_explain_bug() verify_prepare_field(result,0,"id","",MYSQL_TYPE_LONGLONG, "","","",3,0); - verify_prepare_field(result,1,"select_type","",MYSQL_TYPE_STRING, + verify_prepare_field(result,1,"select_type","",MYSQL_TYPE_VAR_STRING, "","","",19,0); - verify_prepare_field(result,2,"table","",MYSQL_TYPE_STRING, + verify_prepare_field(result,2,"table","",MYSQL_TYPE_VAR_STRING, "","","",NAME_LEN,0); - verify_prepare_field(result,3,"type","",MYSQL_TYPE_STRING, + verify_prepare_field(result,3,"type","",MYSQL_TYPE_VAR_STRING, "","","",10,0); - verify_prepare_field(result,4,"possible_keys","",MYSQL_TYPE_STRING, + verify_prepare_field(result,4,"possible_keys","",MYSQL_TYPE_VAR_STRING, "","","",NAME_LEN*32,0); - verify_prepare_field(result,5,"key","",MYSQL_TYPE_STRING, + verify_prepare_field(result,5,"key","",MYSQL_TYPE_VAR_STRING, "","","",NAME_LEN,0); verify_prepare_field(result,6,"key_len","",MYSQL_TYPE_LONGLONG, "","","",3,0); - verify_prepare_field(result,7,"ref","",MYSQL_TYPE_STRING, + verify_prepare_field(result,7,"ref","",MYSQL_TYPE_VAR_STRING, "","","",NAME_LEN*16,0); verify_prepare_field(result,8,"rows","",MYSQL_TYPE_LONGLONG, "","","",10,0); - verify_prepare_field(result,9,"Extra","",MYSQL_TYPE_STRING, + verify_prepare_field(result,9,"Extra","",MYSQL_TYPE_VAR_STRING, "","","",255,0); mysql_free_result(result); @@ -7088,6 +7127,9 @@ static void test_fetch_offset() rc = mysql_fetch_column(stmt,bind,0,0); mystmt_r(stmt,rc); + rc = mysql_bind_result(stmt, bind); + mystmt(stmt,rc); + rc = mysql_stmt_store_result(stmt); mystmt(stmt,rc); @@ -7137,11 +7179,10 @@ static void test_fetch_offset() static void test_fetch_column() { MYSQL_STMT *stmt; - MYSQL_BIND bind[1]; - char c2[20]; - ulong l1, l2; - int rc, c1; - + MYSQL_BIND bind[2]; + char c2[20], bc2[20]; + ulong l1, l2, bl1, bl2; + int rc, c1, bc1; myheader("test_fetch_column"); @@ -7157,25 +7198,41 @@ static void test_fetch_column() stmt = mysql_prepare(mysql,"select * from test_column",50); mystmt_init(stmt); + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (char *)&bc1; + bind[0].buffer_length= 0; + bind[0].is_null= 0; + bind[0].length= &bl1; + bind[1].buffer_type= MYSQL_TYPE_STRING; + bind[1].buffer= (char *)bc2; + bind[1].buffer_length= 7; + bind[1].is_null= 0; + bind[1].length= &bl2; + + rc = mysql_execute(stmt); + mystmt(stmt,rc); + + rc = mysql_bind_result(stmt, bind); + mystmt(stmt,rc); + + rc = mysql_stmt_store_result(stmt); + mystmt(stmt,rc); + + rc = mysql_fetch_column(stmt,bind,1,0); /* No-op at this point */ + mystmt_r(stmt,rc); + + rc = mysql_fetch(stmt); + mystmt(stmt,rc); + + fprintf(stdout, "\n row 0: %d,%s", bc1,bc2); + + c2[0]= '\0'; l2= 0; bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= (char *)c2; bind[0].buffer_length= 7; bind[0].is_null= 0; bind[0].length= &l2; - rc = mysql_execute(stmt); - mystmt(stmt,rc); - - rc = mysql_stmt_store_result(stmt); - mystmt(stmt,rc); - - rc = mysql_fetch_column(stmt,bind,1,0); - mystmt_r(stmt,rc); - - rc = mysql_fetch(stmt); - mystmt(stmt,rc); - - c2[0]= '\0'; l2= 0; rc = mysql_fetch_column(stmt,bind,1,0); mystmt(stmt,rc); fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); @@ -7187,8 +7244,7 @@ static void test_fetch_column() fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); myassert(strcmp(c2,"venu")==0 && l2 == 4); - c1= 0; - + c1= 0; bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&c1; bind[0].buffer_length= 0; @@ -7206,15 +7262,15 @@ static void test_fetch_column() rc = mysql_fetch(stmt); mystmt(stmt,rc); + fprintf(stdout, "\n row 1: %d,%s", bc1,bc2); + + c2[0]= '\0'; l2= 0; bind[0].buffer_type= MYSQL_TYPE_STRING; bind[0].buffer= (char *)c2; bind[0].buffer_length= 7; bind[0].is_null= 0; bind[0].length= &l2; - fprintf(stdout, "\n row 1: %d,%s", c1,c2); - - c2[0]= '\0'; l2= 0; rc = mysql_fetch_column(stmt,bind,1,0); mystmt(stmt,rc); fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); @@ -7227,7 +7283,6 @@ static void test_fetch_column() myassert(strcmp(c2,"mysql")==0 && l2 == 5); c1= 0; - bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&c1; bind[0].buffer_length= 0; @@ -7359,8 +7414,8 @@ static void test_free_result() MYSQL_STMT *stmt; MYSQL_BIND bind[1]; char c2[5]; - ulong length; - int rc, c1; + ulong bl1, l2; + int rc, c1, bc1; myheader("test_free_result"); @@ -7376,39 +7431,47 @@ static void test_free_result() stmt = mysql_prepare(mysql,"select * from test_free_result",50); mystmt_init(stmt); - bind[0].buffer_type= MYSQL_TYPE_STRING; - bind[0].buffer= (char *)c2; - bind[0].buffer_length= 7; + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (char *)&bc1; + bind[0].buffer_length= 0; bind[0].is_null= 0; - bind[0].length= &length; + bind[0].length= &bl1; rc = mysql_execute(stmt); mystmt(stmt,rc); + rc = mysql_bind_result(stmt, bind); + mystmt(stmt,rc); + rc = mysql_fetch(stmt); mystmt(stmt,rc); - c2[0]= '\0'; length= 0; + c2[0]= '\0'; l2= 0; + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (char *)c2; + bind[0].buffer_length= 7; + bind[0].is_null= 0; + bind[0].length= &l2; + rc = mysql_fetch_column(stmt,bind,0,0); mystmt(stmt,rc); - fprintf(stdout, "\n col 1: %s(%ld)", c2, length); - myassert(strncmp(c2,"1",1)==0 && length == 1); + fprintf(stdout, "\n col 0: %s(%ld)", c2, l2); + myassert(strncmp(c2,"1",1)==0 && l2 == 1); rc = mysql_fetch(stmt); mystmt(stmt,rc); - c1= 0, length= 0; - + c1= 0, l2= 0; bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&c1; bind[0].buffer_length= 0; bind[0].is_null= 0; - bind[0].length= &length; + bind[0].length= &l2; rc = mysql_fetch_column(stmt,bind,0,0); mystmt(stmt,rc); - fprintf(stdout, "\n col 0: %d(%ld)", c1, length); - myassert(c1 == 2 && length == 4); + fprintf(stdout, "\n col 0: %d(%ld)", c1, l2); + myassert(c1 == 2 && l2 == 4); rc = mysql_query(mysql,"drop table test_free_result"); myquery_r(rc); /* error should be, COMMANDS OUT OF SYNC */ @@ -7430,8 +7493,8 @@ static void test_free_store_result() MYSQL_STMT *stmt; MYSQL_BIND bind[1]; char c2[5]; - ulong length; - int rc, c1; + ulong bl1, l2; + int rc, c1, bc1; myheader("test_free_store_result"); @@ -7447,42 +7510,50 @@ static void test_free_store_result() stmt = mysql_prepare(mysql,"select * from test_free_result",50); mystmt_init(stmt); - bind[0].buffer_type= MYSQL_TYPE_STRING; - bind[0].buffer= (char *)c2; - bind[0].buffer_length= 7; + bind[0].buffer_type= MYSQL_TYPE_LONG; + bind[0].buffer= (char *)&bc1; + bind[0].buffer_length= 0; bind[0].is_null= 0; - bind[0].length= &length; + bind[0].length= &bl1; rc = mysql_execute(stmt); mystmt(stmt,rc); + rc = mysql_bind_result(stmt, bind); + mystmt(stmt,rc); + rc = mysql_stmt_store_result(stmt); mystmt(stmt,rc); rc = mysql_fetch(stmt); mystmt(stmt,rc); - c2[0]= '\0'; length= 0; + c2[0]= '\0'; l2= 0; + bind[0].buffer_type= MYSQL_TYPE_STRING; + bind[0].buffer= (char *)c2; + bind[0].buffer_length= 7; + bind[0].is_null= 0; + bind[0].length= &l2; + rc = mysql_fetch_column(stmt,bind,0,0); mystmt(stmt,rc); - fprintf(stdout, "\n col 1: %s(%ld)", c2, length); - myassert(strncmp(c2,"1",1)==0 && length == 1); + fprintf(stdout, "\n col 1: %s(%ld)", c2, l2); + myassert(strncmp(c2,"1",1)==0 && l2 == 1); rc = mysql_fetch(stmt); mystmt(stmt,rc); - c1= 0, length= 0; - + c1= 0, l2= 0; bind[0].buffer_type= MYSQL_TYPE_LONG; bind[0].buffer= (char *)&c1; bind[0].buffer_length= 0; bind[0].is_null= 0; - bind[0].length= &length; + bind[0].length= &l2; rc = mysql_fetch_column(stmt,bind,0,0); mystmt(stmt,rc); - fprintf(stdout, "\n col 0: %d(%ld)", c1, length); - myassert(c1 == 2 && length == 4); + fprintf(stdout, "\n col 0: %d(%ld)", c1, l2); + myassert(c1 == 2 && l2 == 4); rc = mysql_stmt_free_result(stmt); mystmt(stmt,rc); @@ -7866,7 +7937,6 @@ int main(int argc, char **argv) test_count= 1; start_time= time((time_t *)0); - client_query(); /* simple client query test */ #if NOT_YET_WORKING /* Used for internal new development debugging */ @@ -7915,7 +7985,6 @@ int main(int argc, char **argv) test_simple_update(); /* simple prepare with update */ test_simple_delete(); /* prepare with delete */ test_double_compare(); /* float comparision */ - client_query(); /* simple client query test */ client_store_result(); /* usage of mysql_store_result() */ client_use_result(); /* usage of mysql_use_result() */ test_tran_bdb(); /* transaction test on BDB table type */ @@ -7959,9 +8028,6 @@ int main(int argc, char **argv) test_nstmts(); /* test n statements */ test_logs(); ; /* to test logs */ test_cuted_rows(); /* to test for WARNINGS from cuted rows */ - test_fetch_seek(); /* to test stmt seek() functions */ - test_fetch_nobuffs(); /* to fecth without prior bound buffers */ - test_open_direct(); /* direct execution in the middle of open stmts */ test_fetch_offset(); /* to test mysql_fetch_column with offset */ test_fetch_column(); /* to test mysql_fetch_column */ test_mem_overun(); /* test DBD ovverun bug */ @@ -7969,15 +8035,10 @@ int main(int argc, char **argv) test_free_result(); /* test mysql_stmt_free_result() */ test_free_store_result(); /* test to make sure stmt results are cleared during stmt_free_result() */ - test_mem_overun(); /* memory ovverun bug */ - test_list_fields(); /* list_fields test */ - test_fetch_offset(); /* to test mysql_fetch_column with offset */ - test_fetch_column(); /* to test mysql_fetch_column */ test_sqlmode(); /* test for SQL_MODE */ test_ts(); /* test for timestamp BR#819 */ test_bug1115(); /* BUG#1115 */ test_bug1180(); /* BUG#1180 */ - end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); @@ -7990,4 +8051,3 @@ int main(int argc, char **argv) return(0); } - From 302b8b5bf3330018526f27e267996068486a6a2d Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Oct 2003 17:19:35 +0200 Subject: [PATCH 06/13] A few more fixes. And added new test for BUG#1644. (Disabled for now, not fixed yet.) tests/client_test.c: A few more fixes: - Avoid buffer overruns in printf(). - Corrected index for comment field in show table status output. And added new test for BUG#1644. (Disabled for now, not fixed yet.) --- tests/client_test.c | 113 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 111 insertions(+), 2 deletions(-) diff --git a/tests/client_test.c b/tests/client_test.c index bae47a19f97..d6c4fb78ef9 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -1923,6 +1923,110 @@ static void test_bug1180() mysql_stmt_close(stmt); } +/* + test BUG#1644 (Insertion of more than 3 NULL columns with + parameter binding fails) +*/ +static void test_bug1644() +{ + MYSQL_STMT *stmt; + MYSQL_RES *result; + MYSQL_ROW row; + MYSQL_BIND bind[4]; + int num; + my_bool isnull; + int rc, i; + + myheader("test_bug1644"); + + rc= mysql_query(mysql, "DROP TABLE IF EXISTS foo_dfr"); + myquery(rc); + + rc= mysql_query(mysql, + "CREATE TABLE foo_dfr(col1 int, col2 int, col3 int, col4 int);"); + myquery(rc); + + strmov(query, "INSERT INTO foo_dfr VALUES (?,?,?,? )"); + stmt = mysql_prepare(mysql, query, strlen(query)); + mystmt_init(stmt); + + verify_param_count(stmt, 4); + + num= 22; + isnull= 0; + for (i = 0 ; i < 4 ; i++) + { + bind[i].buffer_type= FIELD_TYPE_LONG; + bind[i].buffer= (char *)# + bind[i].buffer_length= 0; + bind[i].length= 0; + bind[i].is_null= &isnull; + } + + rc= mysql_bind_param(stmt, bind); + mystmt(stmt, rc); + + rc= mysql_execute(stmt); + mystmt(stmt, rc); + + isnull= 1; + for (i = 0 ; i < 4 ; i++) + bind[i].is_null= &isnull; + + rc= mysql_bind_param(stmt, bind); + mystmt(stmt, rc); + + rc= mysql_execute(stmt); + mystmt(stmt, rc); + + isnull= 0; + num= 88; + for (i = 0 ; i < 4 ; i++) + bind[i].is_null= &isnull; + + rc= mysql_bind_param(stmt, bind); + mystmt(stmt, rc); + + rc= mysql_execute(stmt); + mystmt(stmt, rc); + + mysql_stmt_close(stmt); + + rc= mysql_query(mysql, "SELECT * FROM foo_dfr"); + myquery(rc); + + result= mysql_store_result(mysql); + mytest(result); + + myassert(3 == my_process_result_set(result)); + + mysql_data_seek(result, 0); + + row= mysql_fetch_row(result); + mytest(row); + for (i = 0 ; i < 4 ; i++) + { + myassert(strcmp(row[i], "22") == 0); + } + row= mysql_fetch_row(result); + mytest(row); + for (i = 0 ; i < 4 ; i++) + { + myassert(row[i] == 0); + } + row= mysql_fetch_row(result); + mytest(row); + for (i = 0 ; i < 4 ; i++) + { + myassert(strcmp(row[i], "88") == 0); + } + row= mysql_fetch_row(result); + mytest_r(row); + + mysql_free_result(result); +} + + /******************************************************** * to test simple select show * *********************************************************/ @@ -5551,6 +5655,8 @@ static void test_buffers() rc = mysql_execute(stmt); mystmt(stmt, rc); + bzero(buffer, 20); /* Avoid overruns in printf() */ + bind[0].length= &length; bind[0].is_null= &is_null; bind[0].buffer_length= 1; @@ -6397,8 +6503,8 @@ static void test_frm_bug() row= mysql_fetch_row(result); mytest(row); - fprintf(stdout,"\n Comment: %s", row[15]); - myassert(row[17] != 0); + fprintf(stdout,"\n Comment: %s", row[16]); + myassert(row[16] != 0); mysql_free_result(result); mysql_stmt_close(stmt); @@ -8039,6 +8145,9 @@ int main(int argc, char **argv) test_ts(); /* test for timestamp BR#819 */ test_bug1115(); /* BUG#1115 */ test_bug1180(); /* BUG#1180 */ +#if NOT_YET_FIXED + test_bug1644(); /* BUG#1644 */ +#endif end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); From f081a5413068a1491a25b60e0cee5a6619fbfa1e Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 25 Oct 2003 19:12:29 +0300 Subject: [PATCH 07/13] sql_parse.cc: Add diagnostic printf to chack that number of connections for a user never drops below zero sql/sql_parse.cc: Add diagnostic printf to chack that number of connections for a user never drops below zero --- sql/sql_parse.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index d9837291f73..99f22993393 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -452,6 +452,9 @@ static void decrease_user_connections(USER_CONN *uc) (void) pthread_mutex_lock(&LOCK_user_conn); + if (uc->connections == 0) + printf("Error: trying to decrease user %s connections below zero!\n", + uc->user); if ((uc->connections && !--uc->connections) && !mqh_used) { /* Last connection for user; Delete it */ From ae437f393f6b38dfc10076a37754e63d905d5c91 Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 26 Oct 2003 20:56:52 +0200 Subject: [PATCH 08/13] sql_parse.cc: Fix yet another race condition in sql_parse.cc: thd->user_connect object could get deleted too soon, before the call of check_for_max_user_connections sql/sql_parse.cc: Fix yet another race condition in sql_parse.cc: thd->user_connect object could get deleted too soon, before the call of check_for_max_user_connections --- sql/sql_parse.cc | 62 +++++++++++++++++++++++++++--------------------- 1 file changed, 35 insertions(+), 27 deletions(-) diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 99f22993393..36a7d19a3c5 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -124,6 +124,16 @@ static bool end_active_trans(THD *thd) static HASH hash_user_connections; +/* + get_or_create_user_conn() + + RETURN VALUE + 0 OK; thd->user_connect is set, thd->user_connect->connections is + incremented by one (so that the user_connect object cannot be dropped + while we are using it) + 1 error +*/ + static int get_or_create_user_conn(THD *thd, const char *user, const char *host, USER_RESOURCES *mqh) @@ -157,7 +167,7 @@ static int get_or_create_user_conn(THD *thd, const char *user, uc->user_len= user_len; uc->host=uc->user + uc->user_len + 1; uc->len = temp_len; - uc->connections = 0; /* BUG FIX by Heikki Oct 25, 2003 */ + uc->connections = 1; /* Another BUG FIX by Heikki Oct 26, 2003 */ uc->questions=uc->updates=uc->conn_per_hour=0; uc->user_resources=*mqh; if (max_user_connections && mqh->connections > max_user_connections) @@ -170,12 +180,14 @@ static int get_or_create_user_conn(THD *thd, const char *user, return_val=1; goto end; } + } else { + uc->connections++; /* BUG FIX by Heikki Oct 26, 2003 */ } + thd->user_connect=uc; end: (void) pthread_mutex_unlock(&LOCK_user_conn); return return_val; - } #ifndef NO_EMBEDDED_ACCESS_CHECKS @@ -199,8 +211,9 @@ end: are 'IN'. RETURN VALUE - 0 OK; thd->user, thd->master_access, thd->priv_user, thd->db and - thd->db_access are updated; OK is sent to client; + 0 OK; thd->user, thd->master_access, thd->priv_user, thd->db, + thd->db_access, and thd->user_connect->connections are updated; OK is + sent to client; -1 access denied or handshake error; error is sent to client; >0 error, not sent to client */ @@ -316,29 +329,24 @@ int check_user(THD *thd, enum enum_server_command command, /* Don't allow user to connect if he has done too many queries */ /* - BUG FIX by Heikki Oct 25, 2003: since get_or_create_user_conn() - creates or finds the user object and does NOT check anything about ur, - we should call it always. + BUG FIXes by Heikki Oct 26, 2003 + + NOTE that the call get_or_create_user_conn() increments the connection + count by 1 if it succeeds! This is to prevent the dropping of the + thd->user_connect object before we check the connection limits in + check_for_max_user_connections. */ - if ( /* (ur.questions || ur.updates || - ur.connections || max_user_connections) && */ - get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur)) - DBUG_RETURN(1); - - /* - BUG FIX by Heikki Oct 25, 2003: since - check_for_max_user_connections() keeps the count of user connections, - and we delete the user object when the number of connections drops to - zero, we must call it always to keep the count right! Otherwise the - user object can get deleted too early, which caused memory corruption - to a user in Oct 2003. - */ + if (get_or_create_user_conn(thd,thd->user,thd->host_or_ip,&ur)) + DBUG_RETURN(1); if (thd->user_connect && - /* thd->user_connect->user_resources.connections && */ check_for_max_user_connections(thd, thd->user_connect)) + { + decrease_user_connections(thd->user_connect); + DBUG_RETURN(1); + } /* Change database if necessary: OK or FAIL is sent in mysql_change_db */ if (db && db[0]) @@ -416,15 +424,13 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) (void) pthread_mutex_lock(&LOCK_user_conn); if (max_user_connections && - (max_user_connections < (uint) uc->connections)) + (max_user_connections < (uint) uc->connections)) { net_printf(thd,ER_TOO_MANY_USER_CONNECTIONS, uc->user); error=1; goto end; } - uc->connections++; - if (uc->user_resources.connections && uc->conn_per_hour++ >= uc->user_resources.connections) { @@ -433,6 +439,7 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc) (long) uc->user_resources.connections); error=1; } + end: (void) pthread_mutex_unlock(&LOCK_user_conn); @@ -455,9 +462,10 @@ static void decrease_user_connections(USER_CONN *uc) if (uc->connections == 0) printf("Error: trying to decrease user %s connections below zero!\n", uc->user); - if ((uc->connections && !--uc->connections) && !mqh_used) + if ((!--uc->connections) && !mqh_used) { - /* Last connection for user; Delete it */ + /* Last connection for user; delete it if we do not need the object + for keeping maximum-queries-per-hour statistics (mqh) */ (void) hash_delete(&hash_user_connections,(byte*) uc); } @@ -1296,7 +1304,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd, else { /* we've authenticated new user */ - if (max_connections && save_uc) + if (save_uc) /* BUG FIX by Heikki Oct 26, 2003: always keep the count */ decrease_user_connections(save_uc); x_free((gptr) save_db); x_free((gptr) save_user); From a8577081ffde9ed2660907beedf61d9c682c590e Mon Sep 17 00:00:00 2001 From: unknown Date: Sun, 26 Oct 2003 22:01:00 +0200 Subject: [PATCH 09/13] after-merge fix --- mysql-test/r/query_cache.result | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/query_cache.result b/mysql-test/r/query_cache.result index 3a3a8d99348..1a1eec1f915 100644 --- a/mysql-test/r/query_cache.result +++ b/mysql-test/r/query_cache.result @@ -580,7 +580,7 @@ select * from t1; a set GLOBAL query_cache_size=1024; Warnings: -Warning 1279 Query cache failed to set size 1024, new query cache size is 0 +Warning 1280 Query cache failed to set size 1024, new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -588,7 +588,7 @@ select * from t1; a set GLOBAL query_cache_size=10240; Warnings: -Warning 1279 Query cache failed to set size 10240, new query cache size is 0 +Warning 1280 Query cache failed to set size 10240, new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -596,7 +596,7 @@ select * from t1; a set GLOBAL query_cache_size=20480; Warnings: -Warning 1279 Query cache failed to set size 20480, new query cache size is 0 +Warning 1280 Query cache failed to set size 20480, new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 @@ -604,7 +604,7 @@ select * from t1; a set GLOBAL query_cache_size=40960; Warnings: -Warning 1279 Query cache failed to set size 40960, new query cache size is 0 +Warning 1280 Query cache failed to set size 40960, new query cache size is 0 show global variables like "query_cache_size"; Variable_name Value query_cache_size 0 From 30764334f7bee7a7baec99c2a4c894b5503318d1 Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Oct 2003 01:01:27 +0200 Subject: [PATCH 10/13] fixed ALL/ANY optimisation with union (BUG#1668) code cleanup mysql-test/r/subselect.result: test for BUG#1668 mysql-test/t/subselect.test: test for BUG#1668 sql/item_subselect.cc: removed unused class field fixed min_max subquery used_tables()/const() fixed ALL/ANY optimisation for unions sql/item_subselect.h: removed unused class field fixed min_max subquery used_tables()/const() sql/sql_union.cc: fixed result object assignment --- mysql-test/r/subselect.result | 14 ++++++++++++++ mysql-test/t/subselect.test | 10 ++++++++++ sql/item_subselect.cc | 27 +++++++++++++++++++++------ sql/item_subselect.h | 8 +++++--- sql/sql_union.cc | 7 ++++++- 5 files changed, 56 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result index a196b05b142..a2e83729513 100644 --- a/mysql-test/r/subselect.result +++ b/mysql-test/r/subselect.result @@ -1489,3 +1489,17 @@ set sort_buffer_size = (select s1 from t1); ERROR 21000: Subquery returns more than 1 row do (select * from t1); drop table t1; +create table t1 (s1 char); +insert into t1 values ('e'); +select * from t1 where 'f' > any (select s1 from t1); +s1 +e +select * from t1 where 'f' > any (select s1 from t1 union select s1 from t1); +s1 +e +explain select * from t1 where 'f' > any (select s1 from t1 union select s1 from t1); +id select_type table type possible_keys key key_len ref rows Extra +1 PRIMARY t1 system NULL NULL NULL NULL 1 +2 SUBQUERY t1 system NULL NULL NULL NULL 1 +3 UNION t1 system NULL NULL NULL NULL 1 +drop table t1; diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test index e585375b385..3648210b943 100644 --- a/mysql-test/t/subselect.test +++ b/mysql-test/t/subselect.test @@ -1010,3 +1010,13 @@ insert into t1 values (2); set sort_buffer_size = (select s1 from t1); do (select * from t1); drop table t1; + +# +# optimized ALL/ANY with union +# +create table t1 (s1 char); +insert into t1 values ('e'); +select * from t1 where 'f' > any (select s1 from t1); +select * from t1 where 'f' > any (select s1 from t1 union select s1 from t1); +explain select * from t1 where 'f' > any (select s1 from t1 union select s1 from t1); +drop table t1; diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc index 6ac191af267..589a41052c5 100644 --- a/sql/item_subselect.cc +++ b/sql/item_subselect.cc @@ -35,7 +35,7 @@ inline Item * and_items(Item* cond, Item *item) } Item_subselect::Item_subselect(): - Item_result_field(), engine_owner(1), value_assigned(0), substitution(0), + Item_result_field(), value_assigned(0), substitution(0), engine(0), used_tables_cache(0), have_to_be_excluded(0), const_item_cache(1), engine_changed(0) { @@ -66,8 +66,7 @@ void Item_subselect::init(st_select_lex *select_lex, Item_subselect::~Item_subselect() { - if (engine_owner) - delete engine; + delete engine; } Item_subselect::trans_res @@ -183,7 +182,8 @@ Item_singlerow_subselect::Item_singlerow_subselect(st_select_lex *select_lex) DBUG_VOID_RETURN; } -Item_maxmin_subselect::Item_maxmin_subselect(st_select_lex *select_lex, +Item_maxmin_subselect::Item_maxmin_subselect(Item_subselect *parent, + st_select_lex *select_lex, bool max) :Item_singlerow_subselect() { @@ -192,6 +192,14 @@ Item_maxmin_subselect::Item_maxmin_subselect(st_select_lex *select_lex, max_columns= 1; maybe_null= 1; max_columns= 1; + + /* + Following information was collected during performing fix_fields() + of Items belonged to subquery, which will be not repeated + */ + used_tables_cache= parent->get_used_tables_cache(); + const_item_cache= parent->get_const_item_cache(); + DBUG_VOID_RETURN; } @@ -527,9 +535,16 @@ Item_in_subselect::single_value_transformer(JOIN *join, func == &Item_bool_func2::ge_creator || func == &Item_bool_func2::le_creator)) { + if (substitution) + { + // It is second (third, ...) SELECT of UNION => All is done + DBUG_RETURN(RES_OK); + } + Item *subs; if (!select_lex->group_list.elements && - !select_lex->with_sum_func) + !select_lex->with_sum_func && + !(select_lex->next_select())) { Item *item; subs_type type= substype(); @@ -565,7 +580,7 @@ Item_in_subselect::single_value_transformer(JOIN *join, // remove LIMIT placed by ALL/ANY subquery select_lex->master_unit()->global_parameters->select_limit= HA_POS_ERROR; - subs= new Item_maxmin_subselect(select_lex, + subs= new Item_maxmin_subselect(this, select_lex, (func == &Item_bool_func2::le_creator || func == &Item_bool_func2::lt_creator)); } diff --git a/sql/item_subselect.h b/sql/item_subselect.h index 3a543ff288c..7e735165c02 100644 --- a/sql/item_subselect.h +++ b/sql/item_subselect.h @@ -33,7 +33,6 @@ typedef Item_bool_func2* (*compare_func_creator)(Item*, Item*); class Item_subselect :public Item_result_field { - my_bool engine_owner; /* Is this item owner of engine */ my_bool value_assigned; /* value already assigned to subselect */ protected: /* thread handler, will be assigned in fix_fields only */ @@ -90,6 +89,8 @@ public: virtual void fix_length_and_dec(); table_map used_tables() const; bool const_item() const; + inline table_map get_used_tables_cache() { return used_tables_cache; } + inline bool get_const_item_cache() { return const_item_cache; } void update_used_tables(); void print(String *str) { @@ -144,10 +145,11 @@ public: }; /* used in static ALL/ANY optimisation */ -class Item_maxmin_subselect: public Item_singlerow_subselect +class Item_maxmin_subselect :public Item_singlerow_subselect { public: - Item_maxmin_subselect(st_select_lex *select_lex, bool max); + Item_maxmin_subselect(Item_subselect *parent, + st_select_lex *select_lex, bool max); }; /* exists subselect */ diff --git a/sql/sql_union.cc b/sql/sql_union.cc index 3a903d2e896..de2bb4a786c 100644 --- a/sql/sql_union.cc +++ b/sql/sql_union.cc @@ -119,13 +119,18 @@ int st_select_lex_unit::prepare(THD *thd, select_result *sel_result, SELECT_LEX *select_cursor,*sl; DBUG_ENTER("st_select_lex_unit::prepare"); + /* + result object should be reassigned even if preparing already done for + max/min subquery (ALL/ANY optimization) + */ + result= sel_result; + if (prepared) DBUG_RETURN(0); prepared= 1; res= 0; found_rows_for_union= first_select_in_union()->options & OPTION_FOUND_ROWS; TMP_TABLE_PARAM tmp_table_param; - result= sel_result; t_and_f= tables_and_fields_initied; bzero((char *)&tmp_table_param,sizeof(TMP_TABLE_PARAM)); From 87eb9ea2b10e5ae9d251444e9f3372b958f6a7ea Mon Sep 17 00:00:00 2001 From: unknown Date: Mon, 27 Oct 2003 10:50:18 +0100 Subject: [PATCH 11/13] BUG#1644: Insertion of more than 3 NULL columns with parameter binding fails Fixed. Enabled test case in client_test.c. sql/sql_prepare.cc: BUG#1644: Insertion of more than 3 NULL columns with parameter binding fails Added missing parentheses in IS_PARAM_NULL to get the right bit. tests/client_test.c: BUG#1644: Insertion of more than 3 NULL columns with parameter binding fails Fixed. Enabled test case. --- sql/sql_prepare.cc | 2 +- tests/client_test.c | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc index 522879c863a..da62fc0a262 100644 --- a/sql/sql_prepare.cc +++ b/sql/sql_prepare.cc @@ -72,7 +72,7 @@ Long data handling: #include "sql_select.h" // for JOIN #include // for isspace() -#define IS_PARAM_NULL(pos, param_no) pos[param_no/8] & (1 << param_no & 7) +#define IS_PARAM_NULL(pos, param_no) (pos[param_no/8] & (1 << (param_no & 7))) #define STMT_QUERY_LOG_LENGTH 8192 diff --git a/tests/client_test.c b/tests/client_test.c index d6c4fb78ef9..fd9eb380228 100644 --- a/tests/client_test.c +++ b/tests/client_test.c @@ -8145,9 +8145,8 @@ int main(int argc, char **argv) test_ts(); /* test for timestamp BR#819 */ test_bug1115(); /* BUG#1115 */ test_bug1180(); /* BUG#1180 */ -#if NOT_YET_FIXED test_bug1644(); /* BUG#1644 */ -#endif + end_time= time((time_t *)0); total_time+= difftime(end_time, start_time); From 35c1b4bcf2616dd74115c8d27120b6b333bc98e5 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Oct 2003 12:44:25 +0300 Subject: [PATCH 12/13] added fixed= 1 to the end of Item_in_optimizer::fix_fields() --- sql/item_cmpfunc.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc index 4e6301d2626..2680d5de017 100644 --- a/sql/item_cmpfunc.cc +++ b/sql/item_cmpfunc.cc @@ -421,6 +421,7 @@ bool Item_in_optimizer::fix_left(THD *thd, not_null_tables_cache= args[0]->not_null_tables(); with_sum_func= args[0]->with_sum_func; const_item_cache= args[0]->const_item(); + fixed= 1; return 0; } From a4161274ef18a38eff95272cf9f05f46fb08fcb7 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 30 Oct 2003 13:09:38 +0300 Subject: [PATCH 13/13] small fix in comment --- sql/item_sum.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/item_sum.cc b/sql/item_sum.cc index 9da1b21db72..ed2a03beccf 100644 --- a/sql/item_sum.cc +++ b/sql/item_sum.cc @@ -1822,7 +1822,7 @@ bool Item_func_group_concat::setup(THD *thd) if (select_lex->linkage == GLOBAL_OPTIONS_TYPE) DBUG_RETURN(1); /* - all not constant fields are push to list and create temp table + push all not constant fields to list and create temp table */ always_null= 0; for (uint i= 0; i < arg_count; i++)