Commit eecf716a authored by Patrick Crews's avatar Patrick Crews

automerge

parents ac46e344 c02752a0
# include/wait_show_condition.inc
#
# SUMMARY
#
# Waits until the show statement ($show_statement) has at least within one of
# the rows of the result set for the field ($field) a value which fulfils
# a condition ($condition), or the operation times out.
#
#
# USAGE
#
# let $show_statement= SHOW PROCESSLIST;
# let $field= State;
# let $condition= = 'Updating';
# --source include/wait_show_condition.inc
#
# OR
#
# let $wait_timeout= 60; # Override default of 30 seconds with 60.
# let $show_statement= SHOW PROCESSLIST;
# let $field= State;
# let $condition= = 'Updating';
# --source include/wait_show_condition.inc
#
# Please do not use this use routine if you can replace the SHOW statement
# with a select. In such a case include/wait_condition.inc is recommended.
#
# Created: 2009-02-18 mleich
#
let $max_run_time= 30;
if ($wait_timeout)
{
let $max_run_time= $wait_timeout;
}
# Reset $wait_timeout so that its value won't be used on subsequent
# calls, and default will be used instead.
let $wait_timeout= 0;
# The smallest timespan till UNIX_TIMESTAMP() gets incremented is ~0 seconds.
# We add one second to avoid the case that somebody measures timespans on a
# real clock with fractions of seconds, detects that n seconds are sufficient,
# assigns n to this routine and suffers because he sometimes gets n - 1
# seconds in reality.
inc $max_run_time;
let $found= 0;
let $max_end_time= `SELECT UNIX_TIMESTAMP() + $max_run_time`;
while (`SELECT UNIX_TIMESTAMP() <= $max_end_time AND $found = 0`)
{
# Sleep a bit to avoid too heavy load.
real_sleep 0.2;
let $rowno= 1;
let $process_result= 1;
while (`SELECT $process_result = 1 AND $found = 0`)
{
let $field_value= query_get_value($show_statement, $field, $rowno);
if (`SELECT '$field_value' $condition`)
{
let $found= 1;
}
if (`SELECT '$field_value' = 'No such row'`)
{
# We are behind the last row of the result set.
let $process_result= 0;
}
inc $rowno;
}
}
if (!$found)
{
echo # Timeout in include/wait_show_condition.inc for $wait_condition;
echo # show_statement : $show_statement;
echo # field : $field;
echo # condition : $condition;
echo # max_run_time : $max_run_time;
}
CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE = InnoDB;
INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
COMMIT;
SET AUTOCOMMIT = 0;
CREATE TEMPORARY TABLE t1_tmp ( b INT );
INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 3;
INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 2;
SET AUTOCOMMIT = 0;
CREATE TEMPORARY TABLE t2_tmp ( a int, new_a int );
INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53);
UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1;
UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2;
INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 1;
ERROR 40001: Deadlock found when trying to get lock; try restarting transaction
Reap the server message for connection user2 UPDATE t1 ...
UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3;
DROP TABLE t1;
...@@ -369,4 +369,14 @@ drop table t1; ...@@ -369,4 +369,14 @@ drop table t1;
1 1
drop table t1; drop table t1;
shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql
set @@global.server_id= 4294967295;
reset master;
select
(@a:=load_file("MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog"))
is not null;
(@a:=load_file("MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog"))
is not null
1
*** Unsigned server_id 4294967295 is found: 1 ***
set @@global.server_id= 1;
End of 5.0 tests End of 5.0 tests
...@@ -443,3 +443,17 @@ SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a; ...@@ -443,3 +443,17 @@ SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a;
ROW(a, 1) IN (SELECT SUM(b), 3) ROW(a, 1) IN (SELECT SUM(b), 3)
0 0
DROP TABLE t1; DROP TABLE t1;
create table t1 (a varchar(200),
b int unsigned not null primary key auto_increment)
default character set 'utf8';
create table t2 (c varchar(200),
d int unsigned not null primary key auto_increment)
default character set 'latin1';
insert into t1 (a) values('abc');
insert into t2 (c) values('abc');
select * from t1,t2 where (a,b) = (c,d);
a b c d
abc 1 abc 1
select host,user from mysql.user where (host,user) = ('localhost','test');
host user
drop table t1,t2;
#
# Testcase for InnoDB
# Bug#42419 Server crash with "Pure virtual method called" on two concurrent connections
#
--source include/have_innodb.inc
let $innodb_lock_wait_timeout= query_get_value(SHOW VARIABLES LIKE 'innodb_lock_wait_timeout%', Value, 1);
if (`SELECT $innodb_lock_wait_timeout < 10`)
{
--echo # innodb_lock_wait_timeout must be >= 10 seconds
--echo # so that this test can work all time fine on an overloaded testing box
SHOW VARIABLES LIKE 'innodb_lock_wait_timeout';
exit;
}
# Save the initial number of concurrent sessions
--source include/count_sessions.inc
# First session
connection default;
--enable_warnings
CREATE TABLE t1 (a INT AUTO_INCREMENT PRIMARY KEY, b INT) ENGINE = InnoDB;
INSERT INTO t1 VALUES (1,1),(2,2),(3,3);
COMMIT;
SET AUTOCOMMIT = 0;
CREATE TEMPORARY TABLE t1_tmp ( b INT );
INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 3;
INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 2;
# Second session
connect (user2,localhost,root,,,$MASTER_MYPORT,$MASTER_MYSOCK);
SET AUTOCOMMIT = 0;
CREATE TEMPORARY TABLE t2_tmp ( a int, new_a int );
INSERT INTO t2_tmp VALUES (1,51),(2,52),(3,53);
UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 1;
send
UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 2;
# The last update will wait for a lock held by the first session
# First session
connection default;
# Poll till the UPDATE of the second session waits for lock
let $show_statement= SHOW PROCESSLIST;
let $field= State;
let $condition= = 'Updating';
--source include/wait_show_condition.inc
# If the testing box is overloadeded and innodb_lock_wait_timeout is too small
# we might get here ER_LOCK_WAIT_TIMEOUT.
--error ER_LOCK_DEADLOCK
INSERT INTO t1_tmp (b) SELECT b FROM t1 WHERE a = 1;
# Second session
connection user2;
--echo Reap the server message for connection user2 UPDATE t1 ...
reap;
# The server crashed when executing this UPDATE or the succeeding SQL command.
UPDATE t1 SET a = (SELECT new_a FROM t2_tmp WHERE t2_tmp.a = t1.a) WHERE a = 3;
connection default;
disconnect user2;
DROP TABLE t1;
# Wait till all disconnects are completed
--source include/wait_until_count_sessions.inc
...@@ -272,4 +272,24 @@ echo shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql ...@@ -272,4 +272,24 @@ echo shell> mysqlbinlog std_data/corrupt-relay-bin.000624 > var/tmp/bug31793.sql
error 1; error 1;
exec $MYSQL_BINLOG $MYSQL_TEST_DIR/std_data/corrupt-relay-bin.000624 > $MYSQLTEST_VARDIR/tmp/bug31793.sql; exec $MYSQL_BINLOG $MYSQL_TEST_DIR/std_data/corrupt-relay-bin.000624 > $MYSQLTEST_VARDIR/tmp/bug31793.sql;
#
# Bug #37313 BINLOG Contains Incorrect server id
#
let $save_server_id= `select @@global.server_id`;
let $s_id_max=`select (1 << 32) - 1`;
eval set @@global.server_id= $s_id_max;
reset master;
--exec $MYSQL_BINLOG $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog
--replace_result $MYSQLTEST_VARDIR MYSQLTEST_VARDIR
eval select
(@a:=load_file("$MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog"))
is not null;
let $s_id_unsigned= `select @a like "%server id $s_id_max%" /* must return 1 */`;
echo *** Unsigned server_id $s_id_max is found: $s_id_unsigned ***;
eval set @@global.server_id= $save_server_id;
--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_bug37313.binlog
--echo End of 5.0 tests --echo End of 5.0 tests
...@@ -237,3 +237,21 @@ SELECT ROW(a, 1) IN (SELECT SUM(b), 1) FROM t1 GROUP BY a; ...@@ -237,3 +237,21 @@ SELECT ROW(a, 1) IN (SELECT SUM(b), 1) FROM t1 GROUP BY a;
SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a; SELECT ROW(a, 1) IN (SELECT SUM(b), 3) FROM t1 GROUP BY a;
DROP TABLE t1; DROP TABLE t1;
#
# Bug#37601 Cast Is Not Done On Row Comparison
#
create table t1 (a varchar(200),
b int unsigned not null primary key auto_increment)
default character set 'utf8';
create table t2 (c varchar(200),
d int unsigned not null primary key auto_increment)
default character set 'latin1';
insert into t1 (a) values('abc');
insert into t2 (c) values('abc');
select * from t1,t2 where (a,b) = (c,d);
select host,user from mysql.user where (host,user) = ('localhost','test');
drop table t1,t2;
...@@ -1608,42 +1608,11 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname, ...@@ -1608,42 +1608,11 @@ bool agg_item_collations_for_comparison(DTCollation &c, const char *fname,
} }
/*
Collect arguments' character sets together.
We allow to apply automatic character set conversion in some cases.
The conditions when conversion is possible are:
- arguments A and B have different charsets
- A wins according to coercibility rules
(i.e. a column is stronger than a string constant,
an explicit COLLATE clause is stronger than a column)
- character set of A is either superset for character set of B,
or B is a string constant which can be converted into the
character set of A without data loss.
If all of the above is true, then it's possible to convert
B into the character set of A, and then compare according
to the collation of A.
For functions with more than two arguments:
collect(A,B,C) ::= collect(collect(A,B),C)
Since this function calls THD::change_item_tree() on the passed Item **
pointers, it is necessary to pass the original Item **'s, not copies.
Otherwise their values will not be properly restored (see BUG#20769).
If the items are not consecutive (eg. args[2] and args[5]), use the
item_sep argument, ie.
agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
*/ bool agg_item_set_converter(DTCollation &coll, const char *fname,
bool agg_item_charsets(DTCollation &coll, const char *fname,
Item **args, uint nargs, uint flags, int item_sep) Item **args, uint nargs, uint flags, int item_sep)
{ {
Item **arg, *safe_args[2]; Item **arg, *safe_args[2];
if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
return TRUE;
/* /*
For better error reporting: save the first and the second argument. For better error reporting: save the first and the second argument.
...@@ -1724,6 +1693,46 @@ bool agg_item_charsets(DTCollation &coll, const char *fname, ...@@ -1724,6 +1693,46 @@ bool agg_item_charsets(DTCollation &coll, const char *fname,
} }
/*
Collect arguments' character sets together.
We allow to apply automatic character set conversion in some cases.
The conditions when conversion is possible are:
- arguments A and B have different charsets
- A wins according to coercibility rules
(i.e. a column is stronger than a string constant,
an explicit COLLATE clause is stronger than a column)
- character set of A is either superset for character set of B,
or B is a string constant which can be converted into the
character set of A without data loss.
If all of the above is true, then it's possible to convert
B into the character set of A, and then compare according
to the collation of A.
For functions with more than two arguments:
collect(A,B,C) ::= collect(collect(A,B),C)
Since this function calls THD::change_item_tree() on the passed Item **
pointers, it is necessary to pass the original Item **'s, not copies.
Otherwise their values will not be properly restored (see BUG#20769).
If the items are not consecutive (eg. args[2] and args[5]), use the
item_sep argument, ie.
agg_item_charsets(coll, fname, &args[2], 2, flags, 3)
*/
bool agg_item_charsets(DTCollation &coll, const char *fname,
Item **args, uint nargs, uint flags, int item_sep)
{
if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
return TRUE;
return agg_item_set_converter(coll, fname, args, nargs, flags, item_sep);
}
void Item_ident_for_show::make_field(Send_field *tmp_field) void Item_ident_for_show::make_field(Send_field *tmp_field)
{ {
tmp_field->table_name= tmp_field->org_table_name= table_name; tmp_field->table_name= tmp_field->org_table_name= table_name;
...@@ -3010,7 +3019,7 @@ bool Item_param::convert_str_value(THD *thd) ...@@ -3010,7 +3019,7 @@ bool Item_param::convert_str_value(THD *thd)
str_value.set_charset(value.cs_info.final_character_set_of_str_value); str_value.set_charset(value.cs_info.final_character_set_of_str_value);
/* Here str_value is guaranteed to be in final_character_set_of_str_value */ /* Here str_value is guaranteed to be in final_character_set_of_str_value */
max_length= str_value.length(); max_length= str_value.numchars() * str_value.charset()->mbmaxlen;
decimals= 0; decimals= 0;
/* /*
str_value_ptr is returned from val_str(). It must be not alloced str_value_ptr is returned from val_str(). It must be not alloced
......
...@@ -1169,6 +1169,8 @@ bool agg_item_collations(DTCollation &c, const char *name, ...@@ -1169,6 +1169,8 @@ bool agg_item_collations(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags, int item_sep); Item **items, uint nitems, uint flags, int item_sep);
bool agg_item_collations_for_comparison(DTCollation &c, const char *name, bool agg_item_collations_for_comparison(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags); Item **items, uint nitems, uint flags);
bool agg_item_set_converter(DTCollation &coll, const char *fname,
Item **args, uint nargs, uint flags, int item_sep);
bool agg_item_charsets(DTCollation &c, const char *name, bool agg_item_charsets(DTCollation &c, const char *name,
Item **items, uint nitems, uint flags, int item_sep); Item **items, uint nitems, uint flags, int item_sep);
......
...@@ -490,7 +490,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type) ...@@ -490,7 +490,8 @@ int Arg_comparator::set_compare_func(Item_bool_func2 *item, Item_result type)
my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols()); my_error(ER_OPERAND_COLUMNS, MYF(0), (*a)->element_index(i)->cols());
return 1; return 1;
} }
comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)); if (comparators[i].set_cmp_func(owner, (*a)->addr(i), (*b)->addr(i)))
return 1;
} }
break; break;
} }
...@@ -835,6 +836,16 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg, ...@@ -835,6 +836,16 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
get_value_func= &get_time_value; get_value_func= &get_time_value;
return 0; return 0;
} }
else if (type == STRING_RESULT &&
(*a)->result_type() == STRING_RESULT &&
(*b)->result_type() == STRING_RESULT)
{
DTCollation coll;
coll.set((*a)->collation.collation);
if (agg_item_set_converter(coll, owner_arg->func_name(),
b, 1, MY_COLL_CMP_CONV, 1))
return 1;
}
return set_compare_func(owner_arg, type); return set_compare_func(owner_arg, type);
} }
......
...@@ -976,7 +976,7 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info) ...@@ -976,7 +976,7 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info)
fputc('#', file); fputc('#', file);
print_timestamp(file); print_timestamp(file);
fprintf(file, " server id %d end_log_pos %s ", server_id, fprintf(file, " server id %lu end_log_pos %s ", server_id,
llstr(log_pos,llbuff)); llstr(log_pos,llbuff));
/* mysqlbinlog --hexdump */ /* mysqlbinlog --hexdump */
......
...@@ -2373,11 +2373,12 @@ typedef struct st_sargable_param ...@@ -2373,11 +2373,12 @@ typedef struct st_sargable_param
*/ */
static bool static bool
make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
DYNAMIC_ARRAY *keyuse_array) DYNAMIC_ARRAY *keyuse_array)
{ {
int error; int error;
TABLE *table; TABLE *table;
TABLE_LIST *tables= tables_arg;
uint i,table_count,const_count,key; uint i,table_count,const_count,key;
table_map found_const_table_map, all_table_map, found_ref, refs; table_map found_const_table_map, all_table_map, found_ref, refs;
key_map const_ref, eq_part; key_map const_ref, eq_part;
...@@ -2415,10 +2416,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2415,10 +2416,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
table_vector[i]=s->table=table=tables->table; table_vector[i]=s->table=table=tables->table;
table->pos_in_table_list= tables; table->pos_in_table_list= tables;
error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
if(error) if (error)
{ {
table->file->print_error(error, MYF(0)); table->file->print_error(error, MYF(0));
DBUG_RETURN(1); goto error;
} }
table->quick_keys.clear_all(); table->quick_keys.clear_all();
table->reginfo.join_tab=s; table->reginfo.join_tab=s;
...@@ -2503,7 +2504,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2503,7 +2504,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
{ {
join->tables=0; // Don't use join->table join->tables=0; // Don't use join->table
my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0)); my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
DBUG_RETURN(1); goto error;
} }
s->key_dependent= s->dependent; s->key_dependent= s->dependent;
} }
...@@ -2513,7 +2514,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2513,7 +2514,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables, if (update_ref_and_keys(join->thd, keyuse_array, stat, join->tables,
conds, join->cond_equal, conds, join->cond_equal,
~outer_join, join->select_lex, &sargables)) ~outer_join, join->select_lex, &sargables))
DBUG_RETURN(1); goto error;
/* Read tables with 0 or 1 rows (system tables) */ /* Read tables with 0 or 1 rows (system tables) */
join->const_table_map= 0; join->const_table_map= 0;
...@@ -2529,7 +2530,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2529,7 +2530,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if ((tmp=join_read_const_table(s, p_pos))) if ((tmp=join_read_const_table(s, p_pos)))
{ {
if (tmp > 0) if (tmp > 0)
DBUG_RETURN(1); // Fatal error goto error; // Fatal error
} }
else else
found_const_table_map|= s->table->map; found_const_table_map|= s->table->map;
...@@ -2601,7 +2602,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2601,7 +2602,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
if ((tmp= join_read_const_table(s, join->positions+const_count-1))) if ((tmp= join_read_const_table(s, join->positions+const_count-1)))
{ {
if (tmp > 0) if (tmp > 0)
DBUG_RETURN(1); // Fatal error goto error; // Fatal error
} }
else else
found_const_table_map|= table->map; found_const_table_map|= table->map;
...@@ -2650,12 +2651,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2650,12 +2651,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
set_position(join,const_count++,s,start_keyuse); set_position(join,const_count++,s,start_keyuse);
if (create_ref_for_key(join, s, start_keyuse, if (create_ref_for_key(join, s, start_keyuse,
found_const_table_map)) found_const_table_map))
DBUG_RETURN(1); goto error;
if ((tmp=join_read_const_table(s, if ((tmp=join_read_const_table(s,
join->positions+const_count-1))) join->positions+const_count-1)))
{ {
if (tmp > 0) if (tmp > 0)
DBUG_RETURN(1); // Fatal error goto error; // Fatal error
} }
else else
found_const_table_map|= table->map; found_const_table_map|= table->map;
...@@ -2732,7 +2733,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2732,7 +2733,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
*s->on_expr_ref ? *s->on_expr_ref : conds, *s->on_expr_ref ? *s->on_expr_ref : conds,
1, &error); 1, &error);
if (!select) if (!select)
DBUG_RETURN(1); goto error;
records= get_quick_record_count(join->thd, select, s->table, records= get_quick_record_count(join->thd, select, s->table,
&s->const_keys, join->row_limit); &s->const_keys, join->row_limit);
s->quick=select->quick; s->quick=select->quick;
...@@ -2778,7 +2779,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2778,7 +2779,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
{ {
optimize_keyuse(join, keyuse_array); optimize_keyuse(join, keyuse_array);
if (choose_plan(join, all_table_map & ~join->const_table_map)) if (choose_plan(join, all_table_map & ~join->const_table_map))
DBUG_RETURN(TRUE); goto error;
} }
else else
{ {
...@@ -2788,6 +2789,17 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds, ...@@ -2788,6 +2789,17 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
} }
/* Generate an execution plan from the found optimal join order. */ /* Generate an execution plan from the found optimal join order. */
DBUG_RETURN(join->thd->killed || get_best_combination(join)); DBUG_RETURN(join->thd->killed || get_best_combination(join));
error:
/*
Need to clean up join_tab from TABLEs in case of error.
They won't get cleaned up by JOIN::cleanup() because JOIN::join_tab
may not be assigned yet by this function (which is building join_tab).
Dangling TABLE::reginfo.join_tab may cause part_of_refkey to choke.
*/
for (tables= tables_arg; tables; tables= tables->next_leaf)
tables->table->reginfo.join_tab= NULL;
DBUG_RETURN (1);
} }
......
...@@ -16410,6 +16410,69 @@ static void test_bug36326() ...@@ -16410,6 +16410,69 @@ static void test_bug36326()
#endif #endif
/**
Bug#41078: With CURSOR_TYPE_READ_ONLY mysql_stmt_fetch() returns short
string value.
*/
static void test_bug41078(void)
{
uint rc;
MYSQL_STMT *stmt= 0;
MYSQL_BIND param, result;
ulong cursor_type= CURSOR_TYPE_READ_ONLY;
ulong len;
char str[64];
const char param_str[]= "abcdefghijklmn";
my_bool is_null, error;
DBUG_ENTER("test_bug41078");
rc= mysql_query(mysql, "SET NAMES UTF8");
myquery(rc);
stmt= mysql_simple_prepare(mysql, "SELECT ?");
check_stmt(stmt);
verify_param_count(stmt, 1);
rc= mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, &cursor_type);
check_execute(stmt, rc);
bzero(&param, sizeof(param));
param.buffer_type= MYSQL_TYPE_STRING;
param.buffer= (void *) param_str;
len= sizeof(param_str) - 1;
param.length= &len;
rc= mysql_stmt_bind_param(stmt, &param);
check_execute(stmt, rc);
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
bzero(&result, sizeof(result));
result.buffer_type= MYSQL_TYPE_STRING;
result.buffer= str;
result.buffer_length= sizeof(str);
result.is_null= &is_null;
result.length= &len;
result.error= &error;
rc= mysql_stmt_bind_result(stmt, &result);
check_execute(stmt, rc);
rc= mysql_stmt_store_result(stmt);
check_execute(stmt, rc);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
DIE_UNLESS(len == sizeof(param_str) - 1 && !strcmp(str, param_str));
mysql_stmt_close(stmt);
DBUG_VOID_RETURN;
}
/* /*
Read and parse arguments and MySQL options from my.cnf Read and parse arguments and MySQL options from my.cnf
...@@ -16713,6 +16776,7 @@ static struct my_tests_st my_tests[]= { ...@@ -16713,6 +16776,7 @@ static struct my_tests_st my_tests[]= {
#ifdef HAVE_QUERY_CACHE #ifdef HAVE_QUERY_CACHE
{ "test_bug36326", test_bug36326 }, { "test_bug36326", test_bug36326 },
#endif #endif
{ "test_bug41078", test_bug41078 },
{ 0, 0 } { 0, 0 }
}; };
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment