Commit b6717496 authored by unknown's avatar unknown

Merge mysql.com:/home/mydev/mysql-5.1

into  mysql.com:/home/mydev/mysql-5.1-bug8841

parents 78bec853 13adc06f
...@@ -1443,38 +1443,40 @@ int do_system(struct st_query *q) ...@@ -1443,38 +1443,40 @@ int do_system(struct st_query *q)
/* /*
Print the content between echo and <delimiter> to result file. Print the content between echo and <delimiter> to result file.
If content is a variable, the variable value will be retrieved Evaluate all variables in the string before printing, allow
for variable names to be escaped using \
SYNOPSIS SYNOPSIS
do_echo() do_echo()
q called command q called command
DESCRIPTION DESCRIPTION
Usage 1:
echo text echo text
Print the text after echo until end of command to result file Print the text after echo until end of command to result file
Usage 2:
echo $<var_name> echo $<var_name>
Print the content of the variable <var_name> to result file Print the content of the variable <var_name> to result file
echo Some text $<var_name>
Print "Some text" plus the content of the variable <var_name> to
result file
echo Some text \$<var_name>
Print "Some text" plus $<var_name> to result file
*/ */
int do_echo(struct st_query *q) int do_echo(struct st_query *command)
{ {
char *p= q->first_argument; DYNAMIC_STRING *ds, ds_echo;
DYNAMIC_STRING *ds;
VAR v;
var_init(&v,0,0,0,0);
ds= &ds_res; ds= &ds_res;
eval_expr(&v, p, 0); /* NULL terminated */ init_dynamic_string(&ds_echo, "", 256, 256);
if (v.str_val_len) do_eval(&ds_echo, command->first_argument);
dynstr_append_mem(ds, v.str_val, v.str_val_len); dynstr_append_mem(ds, ds_echo.str, ds_echo.length);
dynstr_append_mem(ds, "\n", 1); dynstr_append_mem(ds, "\n", 1);
var_free(&v); dynstr_free(&ds_echo);
q->last_argument= q->end; command->last_argument= command->end;
return 0; return 0;
} }
...@@ -3733,7 +3735,7 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, ...@@ -3733,7 +3735,7 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt,
if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s", die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s",
mysql_stmt_error(stmt), mysql_stmt_errno(stmt)); mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
free_replace_column(); free_replace_column();
...@@ -4199,7 +4201,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, ...@@ -4199,7 +4201,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
if (mysql_stmt_prepare(stmt, query, query_len)) if (mysql_stmt_prepare(stmt, query, query_len))
{ {
handle_error(query, command, mysql_stmt_errno(stmt), handle_error(query, command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end; goto end;
} }
...@@ -4215,29 +4217,34 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, ...@@ -4215,29 +4217,34 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
parameter markers. parameter markers.
*/ */
#ifdef BUG14013_FIXED
/*
Use cursor when retrieving result
*/
if (cursor_protocol_enabled) if (cursor_protocol_enabled)
{ {
/*
Use cursor when retrieving result
*/
ulong type= CURSOR_TYPE_READ_ONLY; ulong type= CURSOR_TYPE_READ_ONLY;
if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type)) if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type))
die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s", die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
} }
#endif
/* /*
Execute the query Execute the query
*/ */
if (mysql_stmt_execute(stmt)) if (mysql_stmt_execute(stmt))
{ {
handle_error(query, command, mysql_stmt_errno(stmt), handle_error(query, command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end; goto end;
} }
/*
When running in cursor_protocol get the warnings from execute here
and keep them in a separate string for later.
*/
if (cursor_protocol_enabled && !disable_warnings)
append_warnings(&ds_execute_warnings, mysql);
/* /*
We instruct that we want to update the "max_length" field in We instruct that we want to update the "max_length" field in
mysql_stmt_store_result(), this is our only way to know how much mysql_stmt_store_result(), this is our only way to know how much
...@@ -4247,7 +4254,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, ...@@ -4247,7 +4254,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
my_bool one= 1; my_bool one= 1;
if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one)) if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one))
die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s", die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s",
mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
} }
/* /*
...@@ -4257,7 +4264,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, ...@@ -4257,7 +4264,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
if (mysql_stmt_store_result(stmt)) if (mysql_stmt_store_result(stmt))
{ {
handle_error(query, command, mysql_stmt_errno(stmt), handle_error(query, command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
goto end; goto end;
} }
...@@ -4278,10 +4285,10 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, ...@@ -4278,10 +4285,10 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
uint num_fields= mysql_num_fields(res); uint num_fields= mysql_num_fields(res);
if (display_metadata) if (display_metadata)
append_metadata(ds, fields, num_fields); append_metadata(ds, fields, num_fields);
if (!display_result_vertically) if (!display_result_vertically)
append_table_headings(ds, fields, num_fields); append_table_headings(ds, fields, num_fields);
append_stmt_result(ds, stmt, fields, num_fields); append_stmt_result(ds, stmt, fields, num_fields);
...@@ -4303,10 +4310,11 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, ...@@ -4303,10 +4310,11 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command,
/* Append warnings to ds - if there are any */ /* Append warnings to ds - if there are any */
if (append_warnings(&ds_execute_warnings, mysql) || if (append_warnings(&ds_execute_warnings, mysql) ||
ds_prepare_warnings.length || ds_execute_warnings.length ||
ds_warnings->length) ds_prepare_warnings.length ||
ds_warnings->length)
{ {
dynstr_append_mem(ds, "Warnings:\n", 10); dynstr_append_mem(ds, "Warnings:\n", 10);
if (ds_warnings->length) if (ds_warnings->length)
dynstr_append_mem(ds, ds_warnings->str, dynstr_append_mem(ds, ds_warnings->str,
ds_warnings->length); ds_warnings->length);
......
...@@ -2002,6 +2002,7 @@ mysql_stmt_init(MYSQL *mysql) ...@@ -2002,6 +2002,7 @@ mysql_stmt_init(MYSQL *mysql)
stmt->mysql= mysql; stmt->mysql= mysql;
stmt->read_row_func= stmt_read_row_no_result_set; stmt->read_row_func= stmt_read_row_no_result_set;
stmt->prefetch_rows= DEFAULT_PREFETCH_ROWS; stmt->prefetch_rows= DEFAULT_PREFETCH_ROWS;
strmov(stmt->sqlstate, not_error_sqlstate);
/* The rest of statement members was bzeroed inside malloc */ /* The rest of statement members was bzeroed inside malloc */
DBUG_RETURN(stmt); DBUG_RETURN(stmt);
...@@ -4751,12 +4752,39 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) ...@@ -4751,12 +4752,39 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
if (!stmt->field_count) if (!stmt->field_count)
DBUG_RETURN(0); DBUG_RETURN(0);
if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE ||
mysql->status != MYSQL_STATUS_GET_RESULT) if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE)
{
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(1);
}
if (mysql->status == MYSQL_STATUS_READY &&
stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
{
/*
Server side cursor exist, tell server to start sending the rows
*/
NET *net= &mysql->net;
char buff[4 /* statement id */ +
4 /* number of rows to fetch */];
/* Send row request to the server */
int4store(buff, stmt->stmt_id);
int4store(buff + 4, (int)~0); /* number of rows to fetch */
if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
NullS, 0, 1))
{
set_stmt_errmsg(stmt, net->last_error, net->last_errno, net->sqlstate);
DBUG_RETURN(1);
}
}
else if (mysql->status != MYSQL_STATUS_GET_RESULT)
{ {
set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
DBUG_RETURN(1); DBUG_RETURN(1);
} }
if (result->data) if (result->data)
{ {
free_root(&result->alloc, MYF(MY_KEEP_PREALLOC)); free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
...@@ -4797,6 +4825,10 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) ...@@ -4797,6 +4825,10 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
DBUG_RETURN(1); DBUG_RETURN(1);
} }
/* Assert that if there was a cursor, all rows have been fetched */
DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY ||
(mysql->server_status & SERVER_STATUS_LAST_ROW_SENT));
if (stmt->update_max_length) if (stmt->update_max_length)
{ {
MYSQL_ROWS *cur= result->data; MYSQL_ROWS *cur= result->data;
......
create database if not exists events_test; create database if not exists events_test;
use events_test; use events_test;
CREATE USER pauline@localhost;
CREATE DATABASE db_x;
GRANT EVENT ON db_x.* TO pauline@localhost;
USE db_x;
CREATE TABLE x_table(a int);
CREATE EVENT e_x1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE db_x;
CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
SHOW DATABASES LIKE 'db_x';
Database (db_x)
db_x
SET GLOBAL event_scheduler=1;
SHOW DATABASES LIKE 'db_x';
Database (db_x)
db_x
SHOW TABLES FROM db_x;
Tables_in_db_x
x_table
SET GLOBAL event_scheduler=0;
DROP EVENT e_x1;
DROP EVENT e_x2;
DROP DATABASE db_x;
DROP USER pauline@localhost;
USE events_test;
SET GLOBAL event_scheduler=0;
drop event if exists event1; drop event if exists event1;
Warnings: Warnings:
Note 1305 Event event1 does not exist Note 1305 Event event1 does not exist
...@@ -20,6 +44,14 @@ select db, name, body, status, interval_field, interval_value from mysql.event; ...@@ -20,6 +44,14 @@ select db, name, body, status, interval_field, interval_value from mysql.event;
db name body status interval_field interval_value db name body status interval_field interval_value
events_test e_43 set @a = 4 ENABLED SECOND 1 events_test e_43 set @a = 4 ENABLED SECOND 1
drop event e_43; drop event e_43;
"Let's check whether we can use non-qualified names"
create table non_qualif(a int);
create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219);
select * from non_qualif;
a
800219
drop event non_qualif_ev;
drop table non_qualif;
set global event_scheduler = 0; set global event_scheduler = 0;
create table t_event3 (a int, b float); create table t_event3 (a int, b float);
drop event if exists event3; drop event if exists event3;
...@@ -331,8 +363,8 @@ create event закачка on schedule every 10 hour do select get_lock("test_l ...@@ -331,8 +363,8 @@ create event закачка on schedule every 10 hour do select get_lock("test_l
show processlist; show processlist;
Id User Host db Command Time State Info Id User Host db Command Time State Info
# root localhost events_test Query # NULL show processlist # root localhost events_test Query # NULL show processlist
# event_scheduler NULL Connect # Sleeping NULL # event_scheduler connecting host NULL Connect # Sleeping NULL
# root events_test Connect # User lock select get_lock("test_lock2", 20) # root localhost events_test Connect # User lock select get_lock("test_lock2", 20)
"Release the mutex, the event worker should finish." "Release the mutex, the event worker should finish."
select release_lock("test_lock2"); select release_lock("test_lock2");
release_lock("test_lock2") release_lock("test_lock2")
...@@ -350,8 +382,7 @@ set global event_scheduler=0; ...@@ -350,8 +382,7 @@ set global event_scheduler=0;
show processlist; show processlist;
Id User Host db Command Time State Info Id User Host db Command Time State Info
# root localhost events_test Query # NULL show processlist # root localhost events_test Query # NULL show processlist
# event_scheduler NULL Connect # Sleeping NULL # event_scheduler connecting host NULL Connect # Sleeping NULL
# root events_test Connect # User lock select get_lock("test_lock2_1", 20)
"Release the lock so the child process should finish. Hence the scheduler also" "Release the lock so the child process should finish. Hence the scheduler also"
select release_lock("test_lock2_1"); select release_lock("test_lock2_1");
release_lock("test_lock2_1") release_lock("test_lock2_1")
......
CREATE DATABASE IF NOT EXISTS events_test;
CREATE DATABASE events_test2;
USE events_test2;
CREATE EVENT ev_drop1 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop3 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
USE events_test;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
COUNT(*)
3
DROP DATABASE events_test2;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
COUNT(*)
0
"Now testing stability - dropping db -> events while they are running"
CREATE DATABASE events_test2;
USE events_test2;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
COUNT(*)
1000
SET GLOBAL event_scheduler=1;
DROP DATABASE events_test2;
SET GLOBAL event_scheduler=0;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
COUNT(*)
0
CREATE DATABASE events_test3;
USE events_test3;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test3';
COUNT(*)
950
CREATE DATABASE events_test4;
USE events_test4;
CREATE DATABASE events_test2;
USE events_test2;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
COUNT(*)
1050
DROP DATABASE events_test2;
SET GLOBAL event_scheduler=0;
DROP DATABASE events_test3;
SET GLOBAL event_scheduler=1;
DROP DATABASE events_test4;
SET GLOBAL event_scheduler=1;
USE events_test;
DROP DATABASE events_test;
...@@ -201,8 +201,14 @@ source database ...@@ -201,8 +201,14 @@ source database
- world''s most - world''s most
-- popular open -- popular open
# source database # source database
'$message' '# MySQL: The
"$message" - world''s most
-- popular open
# source database'
"# MySQL: The
- world''s most
-- popular open
# source database"
hej hej
hej hej
hej hej
...@@ -221,6 +227,15 @@ mysqltest: At line 1: Missing arguments to let ...@@ -221,6 +227,15 @@ mysqltest: At line 1: Missing arguments to let
mysqltest: At line 1: Missing variable name in let mysqltest: At line 1: Missing variable name in let
mysqltest: At line 1: Missing variable name in let mysqltest: At line 1: Missing variable name in let
mysqltest: At line 1: Missing assignment operator in let mysqltest: At line 1: Missing assignment operator in let
# Execute: --echo # <whatever> success: $success
# <whatever> success: 1
# Execute: echo # <whatever> success: $success ;
# <whatever> success: 1
# The next two variants work fine and expand the content of $success
# Execute: --echo $success
1
# Execute: echo $success ;
1
mysqltest: At line 1: Missing file name in source mysqltest: At line 1: Missing file name in source
mysqltest: At line 1: Could not open file ./non_existingFile mysqltest: At line 1: Could not open file ./non_existingFile
mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": At line 1: Source directives are nesting too deep mysqltest: In included file "MYSQLTEST_VARDIR/tmp/recursive.sql": At line 1: Source directives are nesting too deep
......
...@@ -8,8 +8,6 @@ a b c ...@@ -8,8 +8,6 @@ a b c
2 two two 2 two two
alter table t1 drop index c; alter table t1 drop index c;
select * from t1 where c = 'two'; select * from t1 where c = 'two';
ERROR HY000: Table definition has changed, please retry transaction
select * from t1 where c = 'two';
a b c a b c
2 two two 2 two two
drop table t1; drop table t1;
......
...@@ -30,14 +30,6 @@ drop table t1; ...@@ -30,14 +30,6 @@ drop table t1;
create table t1 (a int) engine=ndbcluster; create table t1 (a int) engine=ndbcluster;
insert into t1 value (2); insert into t1 value (2);
select * from t1; select * from t1;
ERROR HY000: Table definition has changed, please retry transaction
show warnings;
Level Code Message
Error 1296 Got error 241 'Invalid schema object version' from NDB
Error 1412 Table definition has changed, please retry transaction
Error 1105 Unknown error
flush table t1;
select * from t1;
a a
2 2
flush status; flush status;
...@@ -58,15 +50,9 @@ a ...@@ -58,15 +50,9 @@ a
select * from t3; select * from t3;
a b c last_col a b c last_col
1 Hi! 89 Longtext column 1 Hi! 89 Longtext column
show status like 'handler_discover%';
Variable_name Value
Handler_discover 1
show tables like 't4'; show tables like 't4';
Tables_in_test (t4) Tables_in_test (t4)
t4 t4
show status like 'handler_discover%';
Variable_name Value
Handler_discover 2
show tables; show tables;
Tables_in_test Tables_in_test
t1 t1
...@@ -74,4 +60,3 @@ t2 ...@@ -74,4 +60,3 @@ t2
t3 t3
t4 t4
drop table t1, t2, t3, t4; drop table t1, t2, t3, t4;
drop table t1, t3, t4;
...@@ -300,3 +300,16 @@ select * from t1 where f1 = 10; ...@@ -300,3 +300,16 @@ select * from t1 where f1 = 10;
f1 f2 f1 f2
10 1 10 1
drop table t1; drop table t1;
set session storage_engine= 'memory';
create table t1 (f_int1 int(11) default null) engine = memory
partition by range (f_int1) subpartition by hash (f_int1)
(partition part1 values less than (1000)
(subpartition subpart11 engine = memory));
drop table t1;
set session storage_engine='myisam';
create table t1 (f_int1 integer, f_int2 integer, primary key (f_int1))
partition by hash(f_int1) partitions 2;
insert into t1 values (1,1),(2,2);
replace into t1 values (1,1),(2,2);
drop table t1;
End of 5.1 tests
...@@ -20,7 +20,6 @@ ndb_autodiscover2 : Needs to be fixed w.r.t binlog ...@@ -20,7 +20,6 @@ ndb_autodiscover2 : Needs to be fixed w.r.t binlog
ndb_binlog_basic : Results are not deterministic, Tomas will fix ndb_binlog_basic : Results are not deterministic, Tomas will fix
ndb_binlog_ddl_multi : Bug#17038 [PATCH PENDING] ndb_binlog_ddl_multi : Bug#17038 [PATCH PENDING]
ndb_gis : garbled msgs from corrupt THD* ndb_gis : garbled msgs from corrupt THD*
ndb_load : Bug#17233
partition_03ndb : Bug#16385 partition_03ndb : Bug#16385
ps_7ndb : dbug assert in RBR mode when executing test suite ps_7ndb : dbug assert in RBR mode when executing test suite
rpl_bit_npk : Bug#13418 rpl_bit_npk : Bug#13418
......
create database if not exists events_test; create database if not exists events_test;
use events_test; use events_test;
#
# START: BUG #17289 Events: missing privilege check for drop database
#
CREATE USER pauline@localhost;
CREATE DATABASE db_x;
GRANT EVENT ON db_x.* TO pauline@localhost;
USE db_x;
CREATE TABLE x_table(a int);
connect (priv_conn,localhost,pauline,,db_x);
CREATE EVENT e_x1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE db_x;
CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
connection default;
SHOW DATABASES LIKE 'db_x';
SET GLOBAL event_scheduler=1;
--sleep 2
SHOW DATABASES LIKE 'db_x';
SHOW TABLES FROM db_x;
SET GLOBAL event_scheduler=0;
--sleep 1
connection priv_conn;
DROP EVENT e_x1;
DROP EVENT e_x2;
disconnect priv_conn;
connection default;
DROP DATABASE db_x;
DROP USER pauline@localhost;
USE events_test;
#
# END: BUG #17289 Events: missing privilege check for drop database
#
SET GLOBAL event_scheduler=0;
--sleep 1
drop event if exists event1; drop event if exists event1;
create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end; create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end;
alter event event1 rename to event2 enable; alter event event1 rename to event2 enable;
...@@ -23,6 +56,14 @@ alter event e_43 do alter event e_43 do set @a = 4; ...@@ -23,6 +56,14 @@ alter event e_43 do alter event e_43 do set @a = 4;
select db, name, body, status, interval_field, interval_value from mysql.event; select db, name, body, status, interval_field, interval_value from mysql.event;
drop event e_43; drop event e_43;
--sleep 1 --sleep 1
--echo "Let's check whether we can use non-qualified names"
create table non_qualif(a int);
create event non_qualif_ev on schedule every 10 minute do insert into non_qualif values (800219);
--sleep 2
select * from non_qualif;
drop event non_qualif_ev;
drop table non_qualif;
set global event_scheduler = 0; set global event_scheduler = 0;
create table t_event3 (a int, b float); create table t_event3 (a int, b float);
...@@ -241,7 +282,6 @@ drop event one_event; ...@@ -241,7 +282,6 @@ drop event one_event;
--echo "Sleep a bit so the server closes the second connection" --echo "Sleep a bit so the server closes the second connection"
--sleep 2 --sleep 2
create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5; create event e_26 on schedule at '2017-01-01 00:00:00' disable do set @a = 5;
select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event; select db, name, body, definer, convert_tz(execute_at, 'UTC', 'SYSTEM'), on_completion from mysql.event;
drop event e_26; drop event e_26;
......
CREATE DATABASE IF NOT EXISTS events_test;
#
# DROP DATABASE test start (bug #16406)
#
CREATE DATABASE events_test2;
USE events_test2;
CREATE EVENT ev_drop1 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop2 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
CREATE EVENT ev_drop3 ON SCHEDULE EVERY 10 MINUTE DISABLE DO SELECT 1;
USE events_test;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
DROP DATABASE events_test2;
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
--echo "Now testing stability - dropping db -> events while they are running"
CREATE DATABASE events_test2;
USE events_test2;
--disable_query_log
let $1= 1000;
while ($1)
{
eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
dec $1;
}
--enable_query_log
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
SET GLOBAL event_scheduler=1;
--sleep 4
DROP DATABASE events_test2;
SET GLOBAL event_scheduler=0;
--sleep 2
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
CREATE DATABASE events_test3;
USE events_test3;
--disable_query_log
let $1= 950;
while ($1)
{
eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
dec $1;
}
--enable_query_log
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test3';
--sleep 3
CREATE DATABASE events_test4;
USE events_test4;
--disable_query_log
let $1= 860;
while ($1)
{
eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
dec $1;
}
--enable_query_log
CREATE DATABASE events_test2;
USE events_test2;
--disable_query_log
let $1= 1050;
while ($1)
{
eval CREATE EVENT ev_drop$1 ON SCHEDULE EVERY 1 SECOND DO SELECT $1;
dec $1;
}
--enable_query_log
SELECT COUNT(*) FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_SCHEMA='events_test2';
--sleep 6
DROP DATABASE events_test2;
SET GLOBAL event_scheduler=0;
DROP DATABASE events_test3;
SET GLOBAL event_scheduler=1;
DROP DATABASE events_test4;
SET GLOBAL event_scheduler=1;
USE events_test;
#
# DROP DATABASE test end (bug #16406)
#
DROP DATABASE events_test;
...@@ -538,6 +538,19 @@ echo $novar1; ...@@ -538,6 +538,19 @@ echo $novar1;
--error 1 --error 1
--exec echo "let hi;" | $MYSQL_TEST 2>&1 --exec echo "let hi;" | $MYSQL_TEST 2>&1
# More advanced test for bug#17280
let $success= 1;
--echo # Execute: --echo # <whatever> success: \$success
--echo # <whatever> success: $success
--echo # Execute: echo # <whatever> success: \$success ;
echo # <whatever> success: $success ;
--echo # The next two variants work fine and expand the content of \$success
--echo # Execute: --echo \$success
--echo $success
--echo # Execute: echo \$success ;
echo $success ;
# ---------------------------------------------------------------------------- # ----------------------------------------------------------------------------
# Test to assign let from query # Test to assign let from query
# let $<var_name>=`<query>`; # let $<var_name>=`<query>`;
......
...@@ -17,8 +17,6 @@ select * from t1 where c = 'two'; ...@@ -17,8 +17,6 @@ select * from t1 where c = 'two';
connection server1; connection server1;
alter table t1 drop index c; alter table t1 drop index c;
connection server2; connection server2;
-- error 1412
select * from t1 where c = 'two';
select * from t1 where c = 'two'; select * from t1 where c = 'two';
connection server1; connection server1;
drop table t1; drop table t1;
......
...@@ -41,11 +41,12 @@ drop table t1; ...@@ -41,11 +41,12 @@ drop table t1;
create table t1 (a int) engine=ndbcluster; create table t1 (a int) engine=ndbcluster;
insert into t1 value (2); insert into t1 value (2);
connection server1; connection server1;
# Currently a retry is required remotely ## Currently a retry is required remotely
--error 1412 #--error 1412
select * from t1; #select * from t1;
show warnings; #show warnings;
flush table t1; #flush table t1;
# Table definition change should be propagated automatically
select * from t1; select * from t1;
# Connect to server2 and use the tables from there # Connect to server2 and use the tables from there
...@@ -65,13 +66,9 @@ create table t4 (pk int primary key, b int) engine=ndb; ...@@ -65,13 +66,9 @@ create table t4 (pk int primary key, b int) engine=ndb;
connection server1; connection server1;
select * from t1; select * from t1;
select * from t3; select * from t3;
show status like 'handler_discover%';
show tables like 't4'; show tables like 't4';
show status like 'handler_discover%';
show tables; show tables;
drop table t1, t2, t3, t4; drop table t1, t2, t3, t4;
connection server2;
drop table t1, t3, t4;
# End of 4.1 tests # End of 4.1 tests
...@@ -380,3 +380,25 @@ partition partf values less than (10000)); ...@@ -380,3 +380,25 @@ partition partf values less than (10000));
insert into t1 values(10,1); insert into t1 values(10,1);
select * from t1 where f1 = 10; select * from t1 where f1 = 10;
drop table t1; drop table t1;
#
# Bug #16775: Wrong engine type stored for subpartition
#
set session storage_engine= 'memory';
create table t1 (f_int1 int(11) default null) engine = memory
partition by range (f_int1) subpartition by hash (f_int1)
(partition part1 values less than (1000)
(subpartition subpart11 engine = memory));
drop table t1;
set session storage_engine='myisam';
#
# Bug #16782: Crash using REPLACE on table with primary key
#
create table t1 (f_int1 integer, f_int2 integer, primary key (f_int1))
partition by hash(f_int1) partitions 2;
insert into t1 values (1,1),(2,2);
replace into t1 values (1,1),(2,2);
drop table t1;
--echo End of 5.1 tests
This diff is collapsed.
...@@ -79,6 +79,8 @@ class event_timed ...@@ -79,6 +79,8 @@ class event_timed
{ {
event_timed(const event_timed &); /* Prevent use of these */ event_timed(const event_timed &); /* Prevent use of these */
void operator=(event_timed &); void operator=(event_timed &);
my_bool in_spawned_thread;
ulong locked_by_thread_id;
my_bool running; my_bool running;
pthread_mutex_t LOCK_running; pthread_mutex_t LOCK_running;
...@@ -117,13 +119,14 @@ class event_timed ...@@ -117,13 +119,14 @@ class event_timed
bool free_sphead_on_delete; bool free_sphead_on_delete;
uint flags;//all kind of purposes uint flags;//all kind of purposes
event_timed():running(0), status_changed(false), last_executed_changed(false), event_timed():in_spawned_thread(0),locked_by_thread_id(0),
expression(0), created(0), modified(0), running(0), status_changed(false),
on_completion(MYSQL_EVENT_ON_COMPLETION_DROP), last_executed_changed(false), expression(0), created(0),
status(MYSQL_EVENT_ENABLED), sphead(0), sql_mode(0), modified(0), on_completion(MYSQL_EVENT_ON_COMPLETION_DROP),
body_begin(0), dropped(false), free_sphead_on_delete(true), status(MYSQL_EVENT_ENABLED), sphead(0), sql_mode(0),
flags(0) body_begin(0), dropped(false),
free_sphead_on_delete(true), flags(0)
{ {
pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST); pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST);
init(); init();
...@@ -200,11 +203,55 @@ class event_timed ...@@ -200,11 +203,55 @@ class event_timed
return ret; return ret;
} }
void free_sp() /*
Checks whether the object is being used in a spawned thread.
This method is for very basic checking. Use ::can_spawn_now_n_lock()
for most of the cases.
*/
my_bool
can_spawn_now()
{
my_bool ret;
VOID(pthread_mutex_lock(&this->LOCK_running));
ret= !in_spawned_thread;
VOID(pthread_mutex_unlock(&this->LOCK_running));
return ret;
}
/*
Checks whether this thread can lock the object for modification ->
preventing being spawned for execution, and locks if possible.
use ::can_spawn_now() only for basic checking because a race
condition may occur between the check and eventual modification (deletion)
of the object.
*/
my_bool
can_spawn_now_n_lock(THD *thd);
int
spawn_unlock(THD *thd);
int
spawn_now(void * (*thread_func)(void*));
void
spawn_thread_finish(THD *thd);
void
free_sp()
{ {
delete sphead; delete sphead;
sphead= 0; sphead= 0;
} }
protected:
bool
change_security_context(THD *thd, Security_context *s_ctx,
Security_context **backup);
void
restore_security_context(THD *thd, Security_context *backup);
}; };
...@@ -233,6 +280,10 @@ event_reconstruct_interval_expression(String *buf, ...@@ -233,6 +280,10 @@ event_reconstruct_interval_expression(String *buf,
interval_type interval, interval_type interval,
longlong expression); longlong expression);
int
evex_drop_db_events(THD *thd, char *db);
int int
init_events(); init_events();
......
This diff is collapsed.
...@@ -19,6 +19,10 @@ ...@@ -19,6 +19,10 @@
#include "mysql_priv.h" #include "mysql_priv.h"
#define EVENT_EXEC_STARTED 0
#define EVENT_EXEC_ALREADY_EXEC 1
#define EVENT_EXEC_CANT_FORK 2
#define EVEX_USE_QUEUE #define EVEX_USE_QUEUE
#define UNLOCK_MUTEX_AND_BAIL_OUT(__mutex, __label) \ #define UNLOCK_MUTEX_AND_BAIL_OUT(__mutex, __label) \
...@@ -32,10 +36,10 @@ int ...@@ -32,10 +36,10 @@ int
my_time_compare(TIME *a, TIME *b); my_time_compare(TIME *a, TIME *b);
int int
evex_db_find_event_aux(THD *thd, const LEX_STRING dbname, evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING rname, const LEX_STRING ev_name,
const LEX_STRING definer, const LEX_STRING user_name,
TABLE *table); TABLE *table);
int int
event_timed_compare_q(void *vptr, byte* a, byte *b); event_timed_compare_q(void *vptr, byte* a, byte *b);
......
...@@ -412,21 +412,30 @@ event_timed::init_definer(THD *thd) ...@@ -412,21 +412,30 @@ event_timed::init_definer(THD *thd)
{ {
DBUG_ENTER("event_timed::init_definer"); DBUG_ENTER("event_timed::init_definer");
DBUG_PRINT("info",("init definer_user thd->mem_root=0x%lx "
"thd->sec_ctx->priv_user=0x%lx", thd->mem_root,
thd->security_ctx->priv_user));
definer_user.str= strdup_root(thd->mem_root, thd->security_ctx->priv_user); definer_user.str= strdup_root(thd->mem_root, thd->security_ctx->priv_user);
definer_user.length= strlen(thd->security_ctx->priv_user); definer_user.length= strlen(thd->security_ctx->priv_user);
DBUG_PRINT("info",("init definer_host thd->s_c->priv_host=0x%lx",
thd->security_ctx->priv_host));
definer_host.str= strdup_root(thd->mem_root, thd->security_ctx->priv_host); definer_host.str= strdup_root(thd->mem_root, thd->security_ctx->priv_host);
definer_host.length= strlen(thd->security_ctx->priv_host); definer_host.length= strlen(thd->security_ctx->priv_host);
DBUG_PRINT("info",("init definer as whole"));
definer.length= definer_user.length + definer_host.length + 1; definer.length= definer_user.length + definer_host.length + 1;
definer.str= alloc_root(thd->mem_root, definer.length + 1); definer.str= alloc_root(thd->mem_root, definer.length + 1);
DBUG_PRINT("info",("copy the user"));
memcpy(definer.str, definer_user.str, definer_user.length); memcpy(definer.str, definer_user.str, definer_user.length);
definer.str[definer_user.length]= '@'; definer.str[definer_user.length]= '@';
DBUG_PRINT("info",("copy the host"));
memcpy(definer.str + definer_user.length + 1, definer_host.str, memcpy(definer.str + definer_user.length + 1, definer_host.str,
definer_host.length); definer_host.length);
definer.str[definer.length]= '\0'; definer.str[definer.length]= '\0';
DBUG_PRINT("info",("definer initted"));
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -908,7 +917,7 @@ event_timed::drop(THD *thd) ...@@ -908,7 +917,7 @@ event_timed::drop(THD *thd)
Saves status and last_executed_at to the disk if changed. Saves status and last_executed_at to the disk if changed.
SYNOPSIS SYNOPSIS
event_timed::drop() event_timed::update_fields()
thd - thread context thd - thread context
RETURN VALUE RETURN VALUE
...@@ -945,7 +954,7 @@ event_timed::update_fields(THD *thd) ...@@ -945,7 +954,7 @@ event_timed::update_fields(THD *thd)
} }
if ((ret= evex_db_find_event_aux(thd, dbname, name, definer, table))) if ((ret= evex_db_find_event_by_name(thd, dbname, name, definer, table)))
goto done; goto done;
store_record(table,record[1]); store_record(table,record[1]);
...@@ -1061,6 +1070,7 @@ event_timed::get_create_event(THD *thd, String *buf) ...@@ -1061,6 +1070,7 @@ event_timed::get_create_event(THD *thd, String *buf)
RETURNS RETURNS
0 success 0 success
-99 No rights on this.dbname.str
-100 event in execution (parallel execution is impossible) -100 event in execution (parallel execution is impossible)
others retcodes of sp_head::execute_procedure() others retcodes of sp_head::execute_procedure()
*/ */
...@@ -1068,10 +1078,14 @@ event_timed::get_create_event(THD *thd, String *buf) ...@@ -1068,10 +1078,14 @@ event_timed::get_create_event(THD *thd, String *buf)
int int
event_timed::execute(THD *thd, MEM_ROOT *mem_root) event_timed::execute(THD *thd, MEM_ROOT *mem_root)
{ {
List<Item> empty_item_list; Security_context *save_ctx;
/* this one is local and not needed after exec */
Security_context security_ctx;
int ret= 0; int ret= 0;
DBUG_ENTER("event_timed::execute"); DBUG_ENTER("event_timed::execute");
DBUG_PRINT("info", (" EVEX EXECUTING event %s.%s [EXPR:%d]",
dbname.str, name.str, (int) expression));
VOID(pthread_mutex_lock(&this->LOCK_running)); VOID(pthread_mutex_lock(&this->LOCK_running));
if (running) if (running)
...@@ -1082,30 +1096,110 @@ event_timed::execute(THD *thd, MEM_ROOT *mem_root) ...@@ -1082,30 +1096,110 @@ event_timed::execute(THD *thd, MEM_ROOT *mem_root)
running= true; running= true;
VOID(pthread_mutex_unlock(&this->LOCK_running)); VOID(pthread_mutex_unlock(&this->LOCK_running));
// TODO Andrey : make this as member variable and delete in destructor DBUG_PRINT("info", ("master_access=%d db_access=%d",
empty_item_list.empty(); thd->security_ctx->master_access, thd->security_ctx->db_access));
change_security_context(thd, &security_ctx, &save_ctx);
DBUG_PRINT("info", ("master_access=%d db_access=%d",
thd->security_ctx->master_access, thd->security_ctx->db_access));
if (!sphead && (ret= compile(thd, mem_root))) if (!sphead && (ret= compile(thd, mem_root)))
goto done; goto done;
/* Now we are sure we have valid this->sphead so we can copy the context */
ret= sphead->execute_procedure(thd, &empty_item_list); sphead->m_security_ctx= security_ctx;
thd->db= dbname.str;
thd->db_length= dbname.length;
if (!check_access(thd, EVENT_ACL,dbname.str, 0, 0, 0,is_schema_db(dbname.str)))
{
List<Item> empty_item_list;
empty_item_list.empty();
ret= sphead->execute_procedure(thd, &empty_item_list);
}
else
{
DBUG_PRINT("error", ("%s@%s has no rights on %s", definer_user.str,
definer_host.str, dbname.str));
ret= -99;
}
restore_security_context(thd, save_ctx);
DBUG_PRINT("info", ("master_access=%d db_access=%d",
thd->security_ctx->master_access, thd->security_ctx->db_access));
thd->db= 0;
VOID(pthread_mutex_lock(&this->LOCK_running)); VOID(pthread_mutex_lock(&this->LOCK_running));
running= false; running= false;
VOID(pthread_mutex_unlock(&this->LOCK_running)); VOID(pthread_mutex_unlock(&this->LOCK_running));
done: done:
// Don't cache sphead if allocated on another mem_root /*
1. Don't cache sphead if allocated on another mem_root
2. Don't call security_ctx.destroy() because this will free our dbname.str
name.str and definer.str
*/
if (mem_root && sphead) if (mem_root && sphead)
{ {
delete sphead; delete sphead;
sphead= 0; sphead= 0;
} }
DBUG_PRINT("info", (" EVEX EXECUTED event %s.%s [EXPR:%d]. RetCode=%d",
dbname.str, name.str, (int) expression, ret));
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
/*
Switches the security context
Synopsis
event_timed::change_security_context()
thd - thread
backup - where to store the old context
RETURN
0 - OK
1 - Error (generates error too)
*/
bool
event_timed::change_security_context(THD *thd, Security_context *s_ctx,
Security_context **backup)
{
DBUG_ENTER("event_timed::change_security_context");
DBUG_PRINT("info",("%s@%s@%s",definer_user.str,definer_host.str, dbname.str));
#ifndef NO_EMBEDDED_ACCESS_CHECKS
s_ctx->init();
*backup= 0;
if (acl_getroot_no_password(s_ctx, definer_user.str, definer_host.str,
definer_host.str, dbname.str))
{
my_error(ER_NO_SUCH_USER, MYF(0), definer_user.str, definer_host.str);
DBUG_RETURN(TRUE);
}
*backup= thd->security_ctx;
thd->security_ctx= s_ctx;
#endif
DBUG_RETURN(FALSE);
}
/*
Restores the security context
Synopsis
event_timed::restore_security_context()
thd - thread
backup - switch to this context
*/
void
event_timed::restore_security_context(THD *thd, Security_context *backup)
{
DBUG_ENTER("event_timed::change_security_context");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (backup)
thd->security_ctx= backup;
#endif
DBUG_VOID_RETURN;
}
/* /*
Compiles an event before it's execution. Compiles the anonymous Compiles an event before it's execution. Compiles the anonymous
sp_head object held by the event sp_head object held by the event
...@@ -1128,6 +1222,7 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root) ...@@ -1128,6 +1222,7 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
MEM_ROOT *tmp_mem_root= 0; MEM_ROOT *tmp_mem_root= 0;
LEX *old_lex= thd->lex, lex; LEX *old_lex= thd->lex, lex;
char *old_db; char *old_db;
int old_db_length;
event_timed *ett; event_timed *ett;
sp_name *spn; sp_name *spn;
char *old_query; char *old_query;
...@@ -1161,7 +1256,9 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root) ...@@ -1161,7 +1256,9 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
old_query_len= thd->query_length; old_query_len= thd->query_length;
old_query= thd->query; old_query= thd->query;
old_db= thd->db; old_db= thd->db;
old_db_length= thd->db_length;
thd->db= dbname.str; thd->db= dbname.str;
thd->db_length= dbname.length;
get_create_event(thd, &show_create); get_create_event(thd, &show_create);
...@@ -1227,3 +1324,135 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root) ...@@ -1227,3 +1324,135 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
DBUG_RETURN(ret); DBUG_RETURN(ret);
} }
/*
Checks whether this thread can lock the object for modification ->
preventing being spawned for execution, and locks if possible.
use ::can_spawn_now() only for basic checking because a race
condition may occur between the check and eventual modification (deletion)
of the object.
Returns
true - locked
false - cannot lock
*/
my_bool
event_timed::can_spawn_now_n_lock(THD *thd)
{
my_bool ret= FALSE;
VOID(pthread_mutex_lock(&this->LOCK_running));
if (!in_spawned_thread)
{
in_spawned_thread= TRUE;
ret= TRUE;
locked_by_thread_id= thd->thread_id;
}
VOID(pthread_mutex_unlock(&this->LOCK_running));
return ret;
}
extern pthread_attr_t connection_attrib;
/*
Checks whether is possible and forks a thread. Passes self as argument.
Returns
EVENT_EXEC_STARTED - OK
EVENT_EXEC_ALREADY_EXEC - Thread not forked, already working
EVENT_EXEC_CANT_FORK - Unable to spawn thread (error)
*/
int
event_timed::spawn_now(void * (*thread_func)(void*))
{
int ret= EVENT_EXEC_STARTED;
static uint exec_num= 0;
DBUG_ENTER("event_timed::spawn_now");
DBUG_PRINT("info", ("[%s.%s]", dbname.str, name.str));
VOID(pthread_mutex_lock(&this->LOCK_running));
if (!in_spawned_thread)
{
pthread_t th;
in_spawned_thread= true;
if (pthread_create(&th, &connection_attrib, thread_func, (void*)this))
{
DBUG_PRINT("info", ("problem while spawning thread"));
ret= EVENT_EXEC_CANT_FORK;
in_spawned_thread= false;
}
#ifndef DBUG_OFF
else
{
sql_print_information("SCHEDULER: Started thread %d", ++exec_num);
DBUG_PRINT("info", ("thread spawned"));
}
#endif
}
else
{
DBUG_PRINT("info", ("already in spawned thread. skipping"));
ret= EVENT_EXEC_ALREADY_EXEC;
}
VOID(pthread_mutex_unlock(&this->LOCK_running));
DBUG_RETURN(ret);
}
void
event_timed::spawn_thread_finish(THD *thd)
{
DBUG_ENTER("event_timed::spawn_thread_finish");
VOID(pthread_mutex_lock(&this->LOCK_running));
in_spawned_thread= false;
if ((flags & EVENT_EXEC_NO_MORE) || status == MYSQL_EVENT_DISABLED)
{
DBUG_PRINT("info", ("%s exec no more. to drop=%d", name.str, dropped));
if (dropped)
drop(thd);
VOID(pthread_mutex_unlock(&this->LOCK_running));
delete this;
DBUG_VOID_RETURN;
}
VOID(pthread_mutex_unlock(&this->LOCK_running));
DBUG_VOID_RETURN;
}
/*
Unlocks the object after it has been locked with ::can_spawn_now_n_lock()
Returns
0 - ok
1 - not locked by this thread
*/
int
event_timed::spawn_unlock(THD *thd)
{
int ret= 0;
VOID(pthread_mutex_lock(&this->LOCK_running));
if (!in_spawned_thread)
{
if (locked_by_thread_id == thd->thread_id)
{
in_spawned_thread= FALSE;
locked_by_thread_id= 0;
}
else
{
sql_print_error("A thread tries to unlock when he hasn't locked. "
"thread_id=%ld locked by %ld",
thd->thread_id, locked_by_thread_id);
DBUG_ASSERT(0);
ret= 1;
}
}
VOID(pthread_mutex_unlock(&this->LOCK_running));
return ret;
}
This diff is collapsed.
...@@ -237,10 +237,33 @@ void ndbcluster_binlog_init_share(NDB_SHARE *share, TABLE *_table) ...@@ -237,10 +237,33 @@ void ndbcluster_binlog_init_share(NDB_SHARE *share, TABLE *_table)
{ {
THD *thd= current_thd; THD *thd= current_thd;
MEM_ROOT *mem_root= &share->mem_root; MEM_ROOT *mem_root= &share->mem_root;
int do_event_op= ndb_binlog_running;
share->op= 0; share->op= 0;
share->table= 0; share->table= 0;
if (!ndb_binlog_running)
if (!schema_share &&
strcmp(share->db, NDB_REP_DB) == 0 &&
strcmp(share->table_name, NDB_SCHEMA_TABLE) == 0)
do_event_op= 1;
{
int i, no_nodes= g_ndb_cluster_connection->no_db_nodes();
share->subscriber_bitmap= (MY_BITMAP*)
alloc_root(mem_root, no_nodes * sizeof(MY_BITMAP));
for (i= 0; i < no_nodes; i++)
{
bitmap_init(&share->subscriber_bitmap[i],
(Uint32*)alloc_root(mem_root, max_ndb_nodes/8),
max_ndb_nodes, false);
bitmap_clear_all(&share->subscriber_bitmap[i]);
}
bitmap_init(&share->slock_bitmap, share->slock,
sizeof(share->slock)*8, false);
bitmap_clear_all(&share->slock_bitmap);
}
if (!do_event_op)
{ {
if (_table) if (_table)
{ {
...@@ -315,21 +338,6 @@ void ndbcluster_binlog_init_share(NDB_SHARE *share, TABLE *_table) ...@@ -315,21 +338,6 @@ void ndbcluster_binlog_init_share(NDB_SHARE *share, TABLE *_table)
share->ndb_value[1]= (NdbValue*) share->ndb_value[1]= (NdbValue*)
alloc_root(mem_root, sizeof(NdbValue) * table->s->fields alloc_root(mem_root, sizeof(NdbValue) * table->s->fields
+1 /*extra for hidden key*/); +1 /*extra for hidden key*/);
{
int i, no_nodes= g_ndb_cluster_connection->no_db_nodes();
share->subscriber_bitmap= (MY_BITMAP*)
alloc_root(mem_root, no_nodes * sizeof(MY_BITMAP));
for (i= 0; i < no_nodes; i++)
{
bitmap_init(&share->subscriber_bitmap[i],
(Uint32*)alloc_root(mem_root, max_ndb_nodes/8),
max_ndb_nodes, false);
bitmap_clear_all(&share->subscriber_bitmap[i]);
}
bitmap_init(&share->slock_bitmap, share->slock,
sizeof(share->slock)*8, false);
bitmap_clear_all(&share->slock_bitmap);
}
if (table->s->primary_key == MAX_KEY) if (table->s->primary_key == MAX_KEY)
share->flags|= NSF_HIDDEN_PK; share->flags|= NSF_HIDDEN_PK;
if (table->s->blob_fields != 0) if (table->s->blob_fields != 0)
...@@ -648,11 +656,8 @@ static int ndbcluster_create_apply_status_table(THD *thd) ...@@ -648,11 +656,8 @@ static int ndbcluster_create_apply_status_table(THD *thd)
if so, remove it since there is none in Ndb if so, remove it since there is none in Ndb
*/ */
{ {
strxnmov(buf, sizeof(buf), build_table_filename(buf, sizeof(buf),
mysql_data_home, NDB_REP_DB, NDB_APPLY_TABLE, reg_ext);
"/" NDB_REP_DB "/" NDB_APPLY_TABLE,
reg_ext, NullS);
unpack_filename(buf,buf);
my_delete(buf, MYF(0)); my_delete(buf, MYF(0));
} }
...@@ -700,11 +705,8 @@ static int ndbcluster_create_schema_table(THD *thd) ...@@ -700,11 +705,8 @@ static int ndbcluster_create_schema_table(THD *thd)
if so, remove it since there is none in Ndb if so, remove it since there is none in Ndb
*/ */
{ {
strxnmov(buf, sizeof(buf), build_table_filename(buf, sizeof(buf),
mysql_data_home, NDB_REP_DB, NDB_SCHEMA_TABLE, reg_ext);
"/" NDB_REP_DB "/" NDB_SCHEMA_TABLE,
reg_ext, NullS);
unpack_filename(buf,buf);
my_delete(buf, MYF(0)); my_delete(buf, MYF(0));
} }
...@@ -929,8 +931,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share, ...@@ -929,8 +931,7 @@ int ndbcluster_log_schema_op(THD *thd, NDB_SHARE *share,
if (get_a_share) if (get_a_share)
{ {
char key[FN_REFLEN]; char key[FN_REFLEN];
(void)strxnmov(key, FN_REFLEN, share_prefix, db, build_table_filename(key, sizeof(key), db, table_name, "");
"/", table_name, NullS);
share= get_share(key, 0, false, false); share= get_share(key, 0, false, false);
} }
...@@ -1358,6 +1359,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, ...@@ -1358,6 +1359,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
switch (ev_type) switch (ev_type)
{ {
case NDBEVENT::TE_UPDATE: case NDBEVENT::TE_UPDATE:
/* fall through */
case NDBEVENT::TE_INSERT: case NDBEVENT::TE_INSERT:
{ {
Cluster_replication_schema *schema= (Cluster_replication_schema *) Cluster_replication_schema *schema= (Cluster_replication_schema *)
...@@ -1375,21 +1377,20 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, ...@@ -1375,21 +1377,20 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
{ {
case SOT_DROP_TABLE: case SOT_DROP_TABLE:
/* binlog dropping table after any table operations */ /* binlog dropping table after any table operations */
post_epoch_log_list->push_back(schema, mem_root); if (ndb_binlog_running)
post_epoch_log_list->push_back(schema, mem_root);
log_query= 0; log_query= 0;
break; break;
case SOT_RENAME_TABLE: case SOT_RENAME_TABLE:
/* fall through */ /* fall through */
case SOT_ALTER_TABLE: case SOT_ALTER_TABLE:
/* fall through */ if (ndb_binlog_running)
if (!ndb_binlog_running)
{ {
log_query= 1; log_query= 1;
break; /* discovery will be handled by binlog */ break; /* discovery will be handled by binlog */
} }
/* fall through */ /* fall through */
case SOT_CREATE_TABLE: case SOT_CREATE_TABLE:
/* fall through */
pthread_mutex_lock(&LOCK_open); pthread_mutex_lock(&LOCK_open);
if (ndb_create_table_from_engine(thd, schema->db, schema->name)) if (ndb_create_table_from_engine(thd, schema->db, schema->name))
{ {
...@@ -1407,7 +1408,8 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, ...@@ -1407,7 +1408,8 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
TRUE, /* print error */ TRUE, /* print error */
TRUE); /* don't binlog the query */ TRUE); /* don't binlog the query */
/* binlog dropping database after any table operations */ /* binlog dropping database after any table operations */
post_epoch_log_list->push_back(schema, mem_root); if (ndb_binlog_running)
post_epoch_log_list->push_back(schema, mem_root);
log_query= 0; log_query= 0;
break; break;
case SOT_CREATE_DB: case SOT_CREATE_DB:
...@@ -1422,8 +1424,8 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, ...@@ -1422,8 +1424,8 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
case SOT_CLEAR_SLOCK: case SOT_CLEAR_SLOCK:
{ {
char key[FN_REFLEN]; char key[FN_REFLEN];
(void)strxnmov(key, FN_REFLEN, share_prefix, schema->db, build_table_filename(key, sizeof(key),
"/", schema->name, NullS); schema->db, schema->name, "");
NDB_SHARE *share= get_share(key, 0, false, false); NDB_SHARE *share= get_share(key, 0, false, false);
if (share) if (share)
{ {
...@@ -1463,7 +1465,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb, ...@@ -1463,7 +1465,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
} }
} }
if (log_query) if (log_query && ndb_binlog_running)
{ {
char *thd_db_save= thd->db; char *thd_db_save= thd->db;
thd->db= schema->db; thd->db= schema->db;
...@@ -1752,6 +1754,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, ...@@ -1752,6 +1754,7 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
const char *table_name, const char *table_name,
my_bool share_may_exist) my_bool share_may_exist)
{ {
int do_event_op= ndb_binlog_running;
DBUG_ENTER("ndbcluster_create_binlog_setup"); DBUG_ENTER("ndbcluster_create_binlog_setup");
DBUG_PRINT("enter",("key: %s key_len: %d %s.%s share_may_exist: %d", DBUG_PRINT("enter",("key: %s key_len: %d %s.%s share_may_exist: %d",
key, key_len, db, table_name, share_may_exist)); key, key_len, db, table_name, share_may_exist));
...@@ -1792,7 +1795,12 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key, ...@@ -1792,7 +1795,12 @@ int ndbcluster_create_binlog_setup(Ndb *ndb, const char *key,
"allocating table share for %s failed", key); "allocating table share for %s failed", key);
} }
if (!ndb_binlog_running) if (!schema_share &&
strcmp(share->db, NDB_REP_DB) == 0 &&
strcmp(share->table_name, NDB_SCHEMA_TABLE) == 0)
do_event_op= 1;
if (!do_event_op)
{ {
share->flags|= NSF_NO_BINLOG; share->flags|= NSF_NO_BINLOG;
pthread_mutex_unlock(&ndbcluster_mutex); pthread_mutex_unlock(&ndbcluster_mutex);
......
...@@ -360,7 +360,7 @@ int ha_partition::ha_initialise() ...@@ -360,7 +360,7 @@ int ha_partition::ha_initialise()
other parameters are calculated on demand. other parameters are calculated on demand.
HA_FILE_BASED is always set for partition handler since we use a HA_FILE_BASED is always set for partition handler since we use a
special file for handling names of partitions, engine types. special file for handling names of partitions, engine types.
HA_CAN_GEOMETRY, HA_CAN_FULLTEXT, HA_CAN_SQL_HANDLER, HA_CAN_GEOMETRY, HA_CAN_FULLTEXT, HA_CAN_SQL_HANDLER, HA_DUPP_POS,
HA_CAN_INSERT_DELAYED is disabled until further investigated. HA_CAN_INSERT_DELAYED is disabled until further investigated.
*/ */
m_table_flags= m_file[0]->table_flags(); m_table_flags= m_file[0]->table_flags();
...@@ -383,8 +383,8 @@ int ha_partition::ha_initialise() ...@@ -383,8 +383,8 @@ int ha_partition::ha_initialise()
m_pkey_is_clustered= FALSE; m_pkey_is_clustered= FALSE;
m_table_flags&= file->table_flags(); m_table_flags&= file->table_flags();
} while (*(++file_array)); } while (*(++file_array));
m_table_flags&= ~(HA_CAN_GEOMETRY & HA_CAN_FULLTEXT & m_table_flags&= ~(HA_CAN_GEOMETRY | HA_CAN_FULLTEXT | HA_DUPP_POS |
HA_CAN_SQL_HANDLER & HA_CAN_INSERT_DELAYED); HA_CAN_SQL_HANDLER | HA_CAN_INSERT_DELAYED);
m_table_flags|= HA_FILE_BASED | HA_REC_NOT_IN_SEQ; m_table_flags|= HA_FILE_BASED | HA_REC_NOT_IN_SEQ;
DBUG_RETURN(0); DBUG_RETURN(0);
} }
...@@ -1937,7 +1937,8 @@ bool ha_partition::create_handler_file(const char *name) ...@@ -1937,7 +1937,8 @@ bool ha_partition::create_handler_file(const char *name)
name_buffer_ptr+= name_add(name_buffer_ptr, name_buffer_ptr+= name_add(name_buffer_ptr,
part_name, part_name,
subpart_name); subpart_name);
*engine_array= (uchar) ha_legacy_type(part_elem->engine_type); *engine_array= (uchar) ha_legacy_type(subpart_elem->engine_type);
DBUG_PRINT("info", ("engine: %u", *engine_array));
engine_array++; engine_array++;
} }
} }
...@@ -1954,7 +1955,7 @@ bool ha_partition::create_handler_file(const char *name) ...@@ -1954,7 +1955,7 @@ bool ha_partition::create_handler_file(const char *name)
Create and write and close file Create and write and close file
to be used at open, delete_table and rename_table to be used at open, delete_table and rename_table
*/ */
fn_format(file_name, name, "", ".par", MY_APPEND_EXT); fn_format(file_name, name, "", ha_par_ext, MY_APPEND_EXT);
if ((file= my_create(file_name, CREATE_MODE, O_RDWR | O_TRUNC, if ((file= my_create(file_name, CREATE_MODE, O_RDWR | O_TRUNC,
MYF(MY_WME))) >= 0) MYF(MY_WME))) >= 0)
{ {
...@@ -4683,6 +4684,7 @@ int ha_partition::extra(enum ha_extra_function operation) ...@@ -4683,6 +4684,7 @@ int ha_partition::extra(enum ha_extra_function operation)
case HA_EXTRA_PREPARE_FOR_UPDATE: case HA_EXTRA_PREPARE_FOR_UPDATE:
case HA_EXTRA_PREPARE_FOR_DELETE: case HA_EXTRA_PREPARE_FOR_DELETE:
case HA_EXTRA_FORCE_REOPEN: case HA_EXTRA_FORCE_REOPEN:
case HA_EXTRA_FLUSH_CACHE:
{ {
if (m_myisam) if (m_myisam)
DBUG_RETURN(loop_extra(operation)); DBUG_RETURN(loop_extra(operation));
......
...@@ -3488,7 +3488,7 @@ byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b) ...@@ -3488,7 +3488,7 @@ byte *sys_var_thd_dbug::value_ptr(THD *thd, enum_var_type type, LEX_STRING *b)
DBUG_EXPLAIN_INITIAL(buf, sizeof(buf)); DBUG_EXPLAIN_INITIAL(buf, sizeof(buf));
else else
DBUG_EXPLAIN(buf, sizeof(buf)); DBUG_EXPLAIN(buf, sizeof(buf));
(byte*) thd->strdup(buf); return (byte*) thd->strdup(buf);
} }
/**************************************************************************** /****************************************************************************
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "mysql_priv.h" #include "mysql_priv.h"
#include <mysys_err.h> #include <mysys_err.h>
#include "sp.h" #include "sp.h"
#include "event.h"
#include <my_dir.h> #include <my_dir.h>
#include <m_ctype.h> #include <m_ctype.h>
#ifdef __WIN__ #ifdef __WIN__
...@@ -870,6 +871,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent) ...@@ -870,6 +871,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
exit: exit:
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */ (void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
(void)evex_drop_db_events(thd, db); /* QQ Ignore errors for now */
start_waiting_global_read_lock(thd); start_waiting_global_read_lock(thd);
/* /*
If this database was the client's selected database, we silently change the If this database was the client's selected database, we silently change the
......
...@@ -211,8 +211,13 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level, ...@@ -211,8 +211,13 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
TRUE Error sending data to client TRUE Error sending data to client
*/ */
static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"}; LEX_STRING warning_level_names[]=
static int warning_level_length[]= { 4, 7, 5, 1 }; {
{(char*) STRING_WITH_LEN("Note")},
{(char*) STRING_WITH_LEN("Warning")},
{(char*) STRING_WITH_LEN("Error")},
{(char*) STRING_WITH_LEN("?")}
};
bool mysqld_show_warnings(THD *thd, ulong levels_to_show) bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{ {
...@@ -246,8 +251,8 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show) ...@@ -246,8 +251,8 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
if (idx > unit->select_limit_cnt) if (idx > unit->select_limit_cnt)
break; break;
protocol->prepare_for_resend(); protocol->prepare_for_resend();
protocol->store(warning_level_names[err->level], protocol->store(warning_level_names[err->level].str,
warning_level_length[err->level], system_charset_info); warning_level_names[err->level].length, system_charset_info);
protocol->store((uint32) err->code); protocol->store((uint32) err->code);
protocol->store(err->msg, strlen(err->msg), system_charset_info); protocol->store(err->msg, strlen(err->msg), system_charset_info);
if (protocol->write()) if (protocol->write())
......
...@@ -191,10 +191,8 @@ public: ...@@ -191,10 +191,8 @@ public:
int flush() const; int flush() const;
private: private:
STATIC_CONST( MAX_FILE_NAME_SIZE = 128 );
FILE* m_file; FILE* m_file;
char m_fileName[MAX_FILE_NAME_SIZE]; char m_fileName[PATH_MAX];
const char* m_fileMode; const char* m_fileMode;
/* Prohibit */ /* Prohibit */
File_class (const File_class& aCopy); File_class (const File_class& aCopy);
......
...@@ -64,11 +64,11 @@ NdbConfig_NdbCfgName(int with_ndb_home){ ...@@ -64,11 +64,11 @@ NdbConfig_NdbCfgName(int with_ndb_home){
int len= 0; int len= 0;
if (with_ndb_home) { if (with_ndb_home) {
buf= NdbConfig_AllocHomePath(128); buf= NdbConfig_AllocHomePath(PATH_MAX);
len= strlen(buf); len= strlen(buf);
} else } else
buf= NdbMem_Allocate(128); buf= NdbMem_Allocate(PATH_MAX);
basestring_snprintf(buf+len, 128, "Ndb.cfg"); basestring_snprintf(buf+len, PATH_MAX, "Ndb.cfg");
return buf; return buf;
} }
...@@ -90,56 +90,56 @@ char *get_prefix_buf(int len, int node_id) ...@@ -90,56 +90,56 @@ char *get_prefix_buf(int len, int node_id)
char* char*
NdbConfig_ErrorFileName(int node_id){ NdbConfig_ErrorFileName(int node_id){
char *buf= get_prefix_buf(128, node_id); char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf); int len= strlen(buf);
basestring_snprintf(buf+len, 128, "_error.log"); basestring_snprintf(buf+len, PATH_MAX, "_error.log");
return buf; return buf;
} }
char* char*
NdbConfig_ClusterLogFileName(int node_id){ NdbConfig_ClusterLogFileName(int node_id){
char *buf= get_prefix_buf(128, node_id); char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf); int len= strlen(buf);
basestring_snprintf(buf+len, 128, "_cluster.log"); basestring_snprintf(buf+len, PATH_MAX, "_cluster.log");
return buf; return buf;
} }
char* char*
NdbConfig_SignalLogFileName(int node_id){ NdbConfig_SignalLogFileName(int node_id){
char *buf= get_prefix_buf(128, node_id); char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf); int len= strlen(buf);
basestring_snprintf(buf+len, 128, "_signal.log"); basestring_snprintf(buf+len, PATH_MAX, "_signal.log");
return buf; return buf;
} }
char* char*
NdbConfig_TraceFileName(int node_id, int file_no){ NdbConfig_TraceFileName(int node_id, int file_no){
char *buf= get_prefix_buf(128, node_id); char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf); int len= strlen(buf);
basestring_snprintf(buf+len, 128, "_trace.log.%u", file_no); basestring_snprintf(buf+len, PATH_MAX, "_trace.log.%u", file_no);
return buf; return buf;
} }
char* char*
NdbConfig_NextTraceFileName(int node_id){ NdbConfig_NextTraceFileName(int node_id){
char *buf= get_prefix_buf(128, node_id); char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf); int len= strlen(buf);
basestring_snprintf(buf+len, 128, "_trace.log.next"); basestring_snprintf(buf+len, PATH_MAX, "_trace.log.next");
return buf; return buf;
} }
char* char*
NdbConfig_PidFileName(int node_id){ NdbConfig_PidFileName(int node_id){
char *buf= get_prefix_buf(128, node_id); char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf); int len= strlen(buf);
basestring_snprintf(buf+len, 128, ".pid"); basestring_snprintf(buf+len, PATH_MAX, ".pid");
return buf; return buf;
} }
char* char*
NdbConfig_StdoutFileName(int node_id){ NdbConfig_StdoutFileName(int node_id){
char *buf= get_prefix_buf(128, node_id); char *buf= get_prefix_buf(PATH_MAX, node_id);
int len= strlen(buf); int len= strlen(buf);
basestring_snprintf(buf+len, 128, "_out.log"); basestring_snprintf(buf+len, PATH_MAX, "_out.log");
return buf; return buf;
} }
...@@ -67,7 +67,7 @@ File_class::File_class(const char* aFileName, const char* mode) : ...@@ -67,7 +67,7 @@ File_class::File_class(const char* aFileName, const char* mode) :
m_file(NULL), m_file(NULL),
m_fileMode(mode) m_fileMode(mode)
{ {
BaseString::snprintf(m_fileName, MAX_FILE_NAME_SIZE, aFileName); BaseString::snprintf(m_fileName, PATH_MAX, aFileName);
} }
bool bool
...@@ -83,7 +83,7 @@ File_class::open(const char* aFileName, const char* mode) ...@@ -83,7 +83,7 @@ File_class::open(const char* aFileName, const char* mode)
/** /**
* Only copy if it's not the same string * Only copy if it's not the same string
*/ */
BaseString::snprintf(m_fileName, MAX_FILE_NAME_SIZE, aFileName); BaseString::snprintf(m_fileName, PATH_MAX, aFileName);
} }
m_fileMode = mode; m_fileMode = mode;
bool rc = true; bool rc = true;
......
...@@ -1049,7 +1049,10 @@ void stmt_fetch_close(Stmt_fetch *fetch) ...@@ -1049,7 +1049,10 @@ void stmt_fetch_close(Stmt_fetch *fetch)
reading from the rest. reading from the rest.
*/ */
my_bool fetch_n(const char **query_list, unsigned query_count) enum fetch_type { USE_ROW_BY_ROW_FETCH= 0, USE_STORE_RESULT= 1 };
my_bool fetch_n(const char **query_list, unsigned query_count,
enum fetch_type fetch_type)
{ {
unsigned open_statements= query_count; unsigned open_statements= query_count;
int rc, error_count= 0; int rc, error_count= 0;
...@@ -1065,6 +1068,15 @@ my_bool fetch_n(const char **query_list, unsigned query_count) ...@@ -1065,6 +1068,15 @@ my_bool fetch_n(const char **query_list, unsigned query_count)
query_list[fetch - fetch_array]); query_list[fetch - fetch_array]);
} }
if (fetch_type == USE_STORE_RESULT)
{
for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
{
rc= mysql_stmt_store_result(fetch->handle);
check_execute(fetch->handle, rc);
}
}
while (open_statements) while (open_statements)
{ {
for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch) for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
...@@ -11867,7 +11879,8 @@ static void test_basic_cursors() ...@@ -11867,7 +11879,8 @@ static void test_basic_cursors()
fill_tables(basic_tables, sizeof(basic_tables)/sizeof(*basic_tables)); fill_tables(basic_tables, sizeof(basic_tables)/sizeof(*basic_tables));
fetch_n(queries, sizeof(queries)/sizeof(*queries)); fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH);
fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -11880,7 +11893,8 @@ static void test_cursors_with_union() ...@@ -11880,7 +11893,8 @@ static void test_cursors_with_union()
"SELECT t1.id FROM t1 WHERE t1.id < 5" "SELECT t1.id FROM t1 WHERE t1.id < 5"
}; };
myheader("test_cursors_with_union"); myheader("test_cursors_with_union");
fetch_n(queries, sizeof(queries)/sizeof(*queries)); fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_ROW_BY_ROW_FETCH);
fetch_n(queries, sizeof(queries)/sizeof(*queries), USE_STORE_RESULT);
} }
/* /*
...@@ -14729,6 +14743,21 @@ static void test_bug12744() ...@@ -14729,6 +14743,21 @@ static void test_bug12744()
client_connect(0); client_connect(0);
} }
/* Bug #16143: mysql_stmt_sqlstate returns an empty string instead of '00000' */
static void test_bug16143()
{
MYSQL_STMT *stmt;
myheader("test_bug16143");
stmt= mysql_stmt_init(mysql);
/* Check mysql_stmt_sqlstate return "no error" */
DIE_UNLESS(strcmp(mysql_stmt_sqlstate(stmt), "00000") == 0);
mysql_stmt_close(stmt);
}
/* Bug #16144: mysql_stmt_attr_get type error */ /* Bug #16144: mysql_stmt_attr_get type error */
static void test_bug16144() static void test_bug16144()
...@@ -15072,6 +15101,7 @@ static struct my_tests_st my_tests[]= { ...@@ -15072,6 +15101,7 @@ static struct my_tests_st my_tests[]= {
{ "test_opt_reconnect", test_opt_reconnect }, { "test_opt_reconnect", test_opt_reconnect },
{ "test_bug15510", test_bug15510}, { "test_bug15510", test_bug15510},
{ "test_bug12744", test_bug12744 }, { "test_bug12744", test_bug12744 },
{ "test_bug16143", test_bug16143 },
{ "test_bug16144", test_bug16144 }, { "test_bug16144", test_bug16144 },
{ "test_bug15613", test_bug15613 }, { "test_bug15613", test_bug15613 },
{ 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