automerge
This commit is contained in:
commit
eecf716a83
78
mysql-test/include/wait_show_condition.inc
Normal file
78
mysql-test/include/wait_show_condition.inc
Normal file
@ -0,0 +1,78 @@
|
||||
# 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;
|
||||
}
|
||||
|
17
mysql-test/r/innodb_bug42419.result
Normal file
17
mysql-test/r/innodb_bug42419.result
Normal file
@ -0,0 +1,17 @@
|
||||
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;
|
||||
1
|
||||
drop table t1;
|
||||
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
|
||||
|
@ -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)
|
||||
0
|
||||
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;
|
||||
|
77
mysql-test/t/innodb_bug42419.test
Normal file
77
mysql-test/t/innodb_bug42419.test
Normal file
@ -0,0 +1,77 @@
|
||||
#
|
||||
# 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
|
||||
error 1;
|
||||
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
|
||||
|
@ -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;
|
||||
|
||||
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;
|
||||
|
77
sql/item.cc
77
sql/item.cc
@ -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_charsets(DTCollation &coll, const char *fname,
|
||||
Item **args, uint nargs, uint flags, int item_sep)
|
||||
bool agg_item_set_converter(DTCollation &coll, const char *fname,
|
||||
Item **args, uint nargs, uint flags, int item_sep)
|
||||
{
|
||||
Item **arg, *safe_args[2];
|
||||
if (agg_item_collations(coll, fname, args, nargs, flags, item_sep))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
For better error reporting: save the first and the second argument.
|
||||
@ -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)
|
||||
{
|
||||
tmp_field->table_name= tmp_field->org_table_name= table_name;
|
||||
@ -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);
|
||||
/* Here str_value is guaranteed to be in final_character_set_of_str_value */
|
||||
|
||||
max_length= str_value.length();
|
||||
max_length= str_value.numchars() * str_value.charset()->mbmaxlen;
|
||||
decimals= 0;
|
||||
/*
|
||||
str_value_ptr is returned from val_str(). It must be not alloced
|
||||
|
@ -1169,6 +1169,8 @@ bool agg_item_collations(DTCollation &c, const char *name,
|
||||
Item **items, uint nitems, uint flags, int item_sep);
|
||||
bool agg_item_collations_for_comparison(DTCollation &c, const char *name,
|
||||
Item **items, uint nitems, uint flags);
|
||||
bool agg_item_set_converter(DTCollation &coll, const char *fname,
|
||||
Item **args, uint nargs, uint flags, int item_sep);
|
||||
bool agg_item_charsets(DTCollation &c, const char *name,
|
||||
Item **items, uint nitems, uint flags, int item_sep);
|
||||
|
||||
|
@ -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());
|
||||
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;
|
||||
}
|
||||
@ -835,6 +836,16 @@ int Arg_comparator::set_cmp_func(Item_bool_func2 *owner_arg,
|
||||
get_value_func= &get_time_value;
|
||||
return 0;
|
||||
}
|
||||
else if (type == STRING_RESULT &&
|
||||
(*a)->result_type() == STRING_RESULT &&
|
||||
(*b)->result_type() == STRING_RESULT)
|
||||
{
|
||||
DTCollation coll;
|
||||
coll.set((*a)->collation.collation);
|
||||
if (agg_item_set_converter(coll, owner_arg->func_name(),
|
||||
b, 1, MY_COLL_CMP_CONV, 1))
|
||||
return 1;
|
||||
}
|
||||
|
||||
return set_compare_func(owner_arg, type);
|
||||
}
|
||||
|
@ -976,7 +976,7 @@ void Log_event::print_header(FILE* file, PRINT_EVENT_INFO* print_event_info)
|
||||
|
||||
fputc('#', 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));
|
||||
|
||||
/* mysqlbinlog --hexdump */
|
||||
|
@ -2373,11 +2373,12 @@ typedef struct st_sargable_param
|
||||
*/
|
||||
|
||||
static bool
|
||||
make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
||||
make_join_statistics(JOIN *join, TABLE_LIST *tables_arg, COND *conds,
|
||||
DYNAMIC_ARRAY *keyuse_array)
|
||||
{
|
||||
int error;
|
||||
TABLE *table;
|
||||
TABLE_LIST *tables= tables_arg;
|
||||
uint i,table_count,const_count,key;
|
||||
table_map found_const_table_map, all_table_map, found_ref, refs;
|
||||
key_map const_ref, eq_part;
|
||||
@ -2415,10 +2416,10 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
||||
table_vector[i]=s->table=table=tables->table;
|
||||
table->pos_in_table_list= tables;
|
||||
error= table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
|
||||
if(error)
|
||||
if (error)
|
||||
{
|
||||
table->file->print_error(error, MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
table->file->print_error(error, MYF(0));
|
||||
goto error;
|
||||
}
|
||||
table->quick_keys.clear_all();
|
||||
table->reginfo.join_tab=s;
|
||||
@ -2503,7 +2504,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
||||
{
|
||||
join->tables=0; // Don't use join->table
|
||||
my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
|
||||
DBUG_RETURN(1);
|
||||
goto error;
|
||||
}
|
||||
s->key_dependent= s->dependent;
|
||||
}
|
||||
@ -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,
|
||||
conds, join->cond_equal,
|
||||
~outer_join, join->select_lex, &sargables))
|
||||
DBUG_RETURN(1);
|
||||
goto error;
|
||||
|
||||
/* Read tables with 0 or 1 rows (system tables) */
|
||||
join->const_table_map= 0;
|
||||
@ -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 > 0)
|
||||
DBUG_RETURN(1); // Fatal error
|
||||
goto error; // Fatal error
|
||||
}
|
||||
else
|
||||
found_const_table_map|= s->table->map;
|
||||
@ -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 > 0)
|
||||
DBUG_RETURN(1); // Fatal error
|
||||
goto error; // Fatal error
|
||||
}
|
||||
else
|
||||
found_const_table_map|= table->map;
|
||||
@ -2650,12 +2651,12 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
||||
set_position(join,const_count++,s,start_keyuse);
|
||||
if (create_ref_for_key(join, s, start_keyuse,
|
||||
found_const_table_map))
|
||||
DBUG_RETURN(1);
|
||||
goto error;
|
||||
if ((tmp=join_read_const_table(s,
|
||||
join->positions+const_count-1)))
|
||||
{
|
||||
if (tmp > 0)
|
||||
DBUG_RETURN(1); // Fatal error
|
||||
goto error; // Fatal error
|
||||
}
|
||||
else
|
||||
found_const_table_map|= table->map;
|
||||
@ -2732,7 +2733,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
||||
*s->on_expr_ref ? *s->on_expr_ref : conds,
|
||||
1, &error);
|
||||
if (!select)
|
||||
DBUG_RETURN(1);
|
||||
goto error;
|
||||
records= get_quick_record_count(join->thd, select, s->table,
|
||||
&s->const_keys, join->row_limit);
|
||||
s->quick=select->quick;
|
||||
@ -2778,7 +2779,7 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
||||
{
|
||||
optimize_keyuse(join, keyuse_array);
|
||||
if (choose_plan(join, all_table_map & ~join->const_table_map))
|
||||
DBUG_RETURN(TRUE);
|
||||
goto error;
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -2788,6 +2789,17 @@ make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
|
||||
}
|
||||
/* Generate an execution plan from the found optimal join order. */
|
||||
DBUG_RETURN(join->thd->killed || get_best_combination(join));
|
||||
|
||||
error:
|
||||
/*
|
||||
Need to clean up join_tab from TABLEs in case of error.
|
||||
They won't get cleaned up by JOIN::cleanup() because JOIN::join_tab
|
||||
may not be assigned yet by this function (which is building join_tab).
|
||||
Dangling TABLE::reginfo.join_tab may cause part_of_refkey to choke.
|
||||
*/
|
||||
for (tables= tables_arg; tables; tables= tables->next_leaf)
|
||||
tables->table->reginfo.join_tab= NULL;
|
||||
DBUG_RETURN (1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -16410,6 +16410,69 @@ static void test_bug36326()
|
||||
|
||||
#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(¶m, 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, ¶m);
|
||||
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
|
||||
@ -16713,6 +16776,7 @@ static struct my_tests_st my_tests[]= {
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
{ "test_bug36326", test_bug36326 },
|
||||
#endif
|
||||
{ "test_bug41078", test_bug41078 },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user