Merge bk-internal.mysql.com:/home/bk/mysql-5.1

into  janus.mylan:/usr/home/serg/Abk/mysql-5.1
This commit is contained in:
serg@janus.mylan 2007-12-17 14:28:10 +01:00
commit a2eb9e01ed
72 changed files with 5593 additions and 629 deletions

View file

@ -8018,7 +8018,6 @@ REPLACE *init_replace(char * *from, char * *to,uint count,
if (!len)
{
errno=EINVAL;
my_message(0,"No to-string for last from-string",MYF(ME_BELL));
DBUG_RETURN(0);
}
states+=len+1;

View file

@ -203,14 +203,10 @@ typedef struct st_net {
unsigned int *return_status;
unsigned char reading_or_writing;
char save_char;
my_bool no_send_ok; /* For SPs and other things that do multiple stmts */
my_bool unused0; /* Please remove with the next incompatible ABI change. */
my_bool unused; /* Please remove with the next incompatible ABI change */
my_bool compress;
/*
Set if OK packet is already sent, and we do not need to send error
messages
*/
my_bool no_send_error;
my_bool unused1; /* Please remove with the next incompatible ABI change. */
/*
Pointer to query object in query cache, do not equal NULL (0) for
queries in cache that have not stored its results yet
@ -221,11 +217,14 @@ typedef struct st_net {
functions and methods to maintain proper locking.
*/
unsigned char *query_cache_query;
unsigned int last_errno;
unsigned char error;
my_bool report_error; /* We should report error (we have unreported error) */
unsigned int client_last_errno;
unsigned char error;
my_bool unused2; /* Please remove with the next incompatible ABI change. */
my_bool return_errno;
char last_error[MYSQL_ERRMSG_SIZE], sqlstate[SQLSTATE_LENGTH+1];
/** Client library error message buffer. Actually belongs to struct MYSQL. */
char client_last_error[MYSQL_ERRMSG_SIZE];
/** Client library sqlstate buffer. Set along with the error message. */
char sqlstate[SQLSTATE_LENGTH+1];
void *extension;
} NET;

View file

@ -537,16 +537,16 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned
unsigned int * return_status;
unsigned char reading_or_writing;
char save_char;
my_bool no_send_ok;
my_bool unused0;
my_bool unused;
my_bool compress;
my_bool no_send_error;
my_bool unused1;
unsigned char * query_cache_query;
unsigned int last_errno;
unsigned int client_last_errno;
unsigned char error;
my_bool report_error;
my_bool unused2;
my_bool return_errno;
char last_error[512];
char client_last_error[512];
char sqlstate[(5 + 1)];
void * extension;
};

View file

@ -440,11 +440,11 @@ static void expand_error(MYSQL* mysql, int error)
char tmp[MYSQL_ERRMSG_SIZE];
char *p;
uint err_length;
strmake(tmp, mysql->net.last_error, MYSQL_ERRMSG_SIZE-1);
p = strmake(mysql->net.last_error, ER(error), MYSQL_ERRMSG_SIZE-1);
err_length= (uint) (p - mysql->net.last_error);
strmake(tmp, mysql->net.client_last_error, MYSQL_ERRMSG_SIZE-1);
p = strmake(mysql->net.client_last_error, ER(error), MYSQL_ERRMSG_SIZE-1);
err_length= (uint) (p - mysql->net.client_last_error);
strmake(p, tmp, MYSQL_ERRMSG_SIZE-1 - err_length);
mysql->net.last_errno = error;
mysql->net.client_last_errno = error;
}
/*
@ -870,9 +870,10 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename)
VOID(my_net_write(net,(const uchar*) "",0)); /* Server needs one packet */
net_flush(net);
strmov(net->sqlstate, unknown_sqlstate);
net->last_errno= (*options->local_infile_error)(li_ptr,
net->last_error,
sizeof(net->last_error)-1);
net->client_last_errno=
(*options->local_infile_error)(li_ptr,
net->client_last_error,
sizeof(net->client_last_error)-1);
goto err;
}
@ -899,9 +900,10 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename)
if (readcount < 0)
{
net->last_errno= (*options->local_infile_error)(li_ptr,
net->last_error,
sizeof(net->last_error)-1);
net->client_last_errno=
(*options->local_infile_error)(li_ptr,
net->client_last_error,
sizeof(net->client_last_error)-1);
goto err;
}
@ -1395,7 +1397,7 @@ const char *cli_read_statistics(MYSQL *mysql)
if (!mysql->net.read_pos[0])
{
set_mysql_error(mysql, CR_WRONG_HOST_INFO, unknown_sqlstate);
return mysql->net.last_error;
return mysql->net.client_last_error;
}
return (char*) mysql->net.read_pos;
}
@ -1406,7 +1408,7 @@ mysql_stat(MYSQL *mysql)
{
DBUG_ENTER("mysql_stat");
if (simple_command(mysql,COM_STATISTICS,0,0,0))
DBUG_RETURN(mysql->net.last_error);
DBUG_RETURN(mysql->net.client_last_error);
DBUG_RETURN((*mysql->methods->read_statistics)(mysql));
}
@ -1771,7 +1773,7 @@ static my_bool my_realloc_str(NET *net, ulong length)
if (res)
{
strmov(net->sqlstate, unknown_sqlstate);
strmov(net->last_error, ER(net->last_errno));
strmov(net->client_last_error, ER(net->client_last_errno));
}
net->write_pos= net->buff+ buf_length;
}
@ -1822,13 +1824,15 @@ void set_stmt_error(MYSQL_STMT * stmt, int errcode,
void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net)
{
DBUG_ENTER("set_stmt_errmsg");
DBUG_PRINT("enter", ("error: %d/%s '%s'", net->last_errno, net->sqlstate,
net->last_error));
DBUG_PRINT("enter", ("error: %d/%s '%s'",
net->client_last_errno,
net->sqlstate,
net->client_last_error));
DBUG_ASSERT(stmt != 0);
stmt->last_errno= net->last_errno;
if (net->last_error && net->last_error[0])
strmov(stmt->last_error, net->last_error);
stmt->last_errno= net->client_last_errno;
if (net->client_last_error && net->client_last_error[0])
strmov(stmt->last_error, net->client_last_error);
strmov(stmt->sqlstate, net->sqlstate);
DBUG_VOID_RETURN;

View file

@ -160,7 +160,7 @@ MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
msg_len=strlen(msg_buf);
if (my_net_write(&con->net,(uchar*) msg_buf,msg_len) || net_flush(&con->net))
{
con->last_errno=con->net.last_errno;
con->last_errno=con->net.client_last_errno;
strmov(con->last_error,"Write error on socket");
goto err;
}

View file

@ -482,7 +482,7 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src)
*prev_row= NULL;
data->embedded_info->prev_ptr= prev_row;
return_ok:
send_eof(thd);
net_send_eof(thd, thd->server_status, thd->total_warn_count);
DBUG_RETURN(0);
err:
DBUG_RETURN(1);

View file

@ -79,3 +79,4 @@ public:
uint emb_count_querycache_size(THD *thd);
int emb_load_querycache_result(THD *thd, Querycache_stream *src);
void emb_store_querycache_result(Querycache_stream *dst, THD* thd);
void net_send_eof(THD *thd, uint server_status, uint total_warn_count);

View file

@ -61,8 +61,8 @@ void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data)
{
NET *net= &mysql->net;
struct embedded_query_result *ei= data->embedded_info;
net->last_errno= ei->last_errno;
strmake(net->last_error, ei->info, sizeof(net->last_error));
net->client_last_errno= ei->last_errno;
strmake(net->client_last_error, ei->info, sizeof(net->client_last_error)-1);
memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
mysql->server_status= ei->server_status;
my_free(data, MYF(0));
@ -88,6 +88,7 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
/* Clear result variables */
thd->clear_error();
thd->main_da.reset_diagnostics_area();
mysql->affected_rows= ~(my_ulonglong) 0;
mysql->field_count= 0;
net_clear_error(net);
@ -111,12 +112,11 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
arg_length= header_length;
}
thd->net.no_send_error= 0;
result= dispatch_command(command, thd, (char *) arg, arg_length);
thd->cur_data= 0;
if (!skip_check)
result= thd->net.last_errno ? -1 : 0;
result= thd->is_error() ? -1 : 0;
return result;
}
@ -373,7 +373,7 @@ static void emb_free_embedded_thd(MYSQL *mysql)
static const char * emb_read_statistics(MYSQL *mysql)
{
THD *thd= (THD*)mysql->thd;
return thd->net.last_error;
return thd->is_error() ? thd->main_da.message() : "";
}
@ -628,6 +628,7 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
strmake(sctx->priv_host, (char*) my_localhost, MAX_HOSTNAME-1);
sctx->priv_user= sctx->user= my_strdup(mysql->user, MYF(0));
result= check_user(thd, COM_CONNECT, NULL, 0, db, true);
net_end_statement(thd);
emb_read_query_result(mysql);
return result;
}
@ -677,8 +678,10 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
err:
{
NET *net= &mysql->net;
memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error));
memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate));
strmake(net->client_last_error, thd->main_da.message(), sizeof(net->client_last_error)-1);
memcpy(net->sqlstate,
mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
sizeof(net->sqlstate)-1);
}
return result;
}
@ -701,9 +704,8 @@ void THD::clear_data_list()
void THD::clear_error()
{
net.last_error[0]= 0;
net.last_errno= 0;
net.report_error= 0;
if (main_da.is_error())
main_da.reset_diagnostics_area();
}
static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
@ -766,20 +768,18 @@ MYSQL_DATA *THD::alloc_new_dataset()
}
/*
stores server_status and warning_count in the current
query result structures
/**
Stores server_status and warning_count in the current
query result structures.
SYNOPSIS
write_eof_packet()
thd current thread
NOTES
should be called to after we get the recordset-result
@param thd current thread
@note Should be called after we get the recordset-result.
*/
static void write_eof_packet(THD *thd)
static
void
write_eof_packet(THD *thd, uint server_status, uint total_warn_count)
{
if (!thd->mysql) // bootstrap file handling
return;
@ -790,13 +790,13 @@ static void write_eof_packet(THD *thd)
*/
if (thd->is_fatal_error)
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
thd->cur_data->embedded_info->server_status= thd->server_status;
thd->cur_data->embedded_info->server_status= server_status;
/*
Don't send warn count during SP execution, as the warn_list
is cleared between substatements, and mysqltest gets confused
*/
thd->cur_data->embedded_info->warning_count=
(thd->spcont ? 0 : min(thd->total_warn_count, 65535));
(thd->spcont ? 0 : min(total_warn_count, 65535));
}
@ -952,7 +952,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
}
if (flags & SEND_EOF)
write_eof_packet(thd);
write_eof_packet(thd, thd->server_status, thd->total_warn_count);
DBUG_RETURN(prepare_for_send(list));
err:
@ -992,17 +992,35 @@ bool Protocol_binary::write()
return false;
}
/**
Embedded library implementation of OK response.
This function is used by the server to write 'OK' packet to
the "network" when the server is compiled as an embedded library.
Since there is no network in the embedded configuration,
a different implementation is necessary.
Instead of marshalling response parameters to a network representation
and then writing it to the socket, here we simply copy the data to the
corresponding client-side connection structures.
@sa Server implementation of net_send_ok in protocol.cc for
description of the arguments.
@return The function does not return errors.
*/
void
send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
net_send_ok(THD *thd,
uint server_status, uint total_warn_count,
ha_rows affected_rows, ulonglong id, const char *message)
{
DBUG_ENTER("send_ok");
DBUG_ENTER("emb_net_send_ok");
MYSQL_DATA *data;
MYSQL *mysql= thd->mysql;
if (!mysql) // bootstrap file handling
DBUG_VOID_RETURN;
if (thd->net.no_send_ok) // hack for re-parsing queries
DBUG_VOID_RETURN;
if (!(data= thd->alloc_new_dataset()))
return;
data->embedded_info->affected_rows= affected_rows;
@ -1011,15 +1029,24 @@ send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
strmake(data->embedded_info->info, message,
sizeof(data->embedded_info->info)-1);
write_eof_packet(thd);
write_eof_packet(thd, server_status, total_warn_count);
thd->cur_data= 0;
DBUG_VOID_RETURN;
}
/**
Embedded library implementation of EOF response.
@sa net_send_ok
@return This function does not return errors.
*/
void
send_eof(THD *thd)
net_send_eof(THD *thd, uint server_status, uint total_warn_count)
{
write_eof_packet(thd);
write_eof_packet(thd, server_status, total_warn_count);
thd->cur_data= 0;
}

View file

@ -209,8 +209,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
DBUG_RETURN(mysql);
error:
DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno,
mysql->net.last_error));
DBUG_PRINT("error",("message: %u (%s)",
mysql->net.client_last_errno,
mysql->net.client_last_error));
{
/* Free alloced memory */
my_bool free_me=mysql->free_me;

View file

@ -304,6 +304,7 @@ sub mtr_report_stats ($) {
/Slave: Error .*Unknown table/ or
/Slave: Error in Write_rows event: / or
/Slave: Field .* of table .* has no default value/ or
/Slave: Field .* doesn't have a default value/ or
/Slave: Query caused different errors on master and slave/ or
/Slave: Table .* doesn't exist/ or
/Slave: Table width mismatch/ or

View file

@ -403,9 +403,10 @@ ERROR 42S02: Table 'mysql.event' doesn't exist
DROP DATABASE IF EXISTS mysqltest_no_such_database;
Warnings:
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
Error 1146 Table 'mysql.event' doesn't exist
CREATE DATABASE mysqltest_db2;
DROP DATABASE mysqltest_db2;
Warnings:
Error 1146 Table 'mysql.event' doesn't exist
OK, there is an unnecessary warning about the non-existent table
but it's not easy to fix and no one complained about it.
A similar warning is printed if mysql.proc is missing.

View file

@ -1269,9 +1269,7 @@ use test;
FLUSH PRIVILEGES without procs_priv table.
RENAME TABLE mysql.procs_priv TO mysql.procs_gone;
FLUSH PRIVILEGES;
Warnings:
Error 1146 Table 'mysql.procs_priv' doesn't exist
Error 1548 Cannot load from mysql.mysql.procs_priv. The table is probably corrupted
ERROR 42S02: Table 'mysql.procs_priv' doesn't exist
Assigning privileges without procs_priv table.
CREATE DATABASE mysqltest1;
CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER

View file

@ -113,4 +113,34 @@ handler t1 open;
ERROR HY000: Table storage engine for 't1' doesn't have this option
--> client 1
drop table t1;
drop table if exists t1;
create table t1 (i int);
connection: default
lock tables t1 write;
connection: flush
flush tables with read lock;;
connection: default
alter table t1 add column j int;
connection: insert
insert into t1 values (1,2);;
connection: default
unlock tables;
connection: flush
select * from t1;
i j
unlock tables;
select * from t1;
i j
1 2
drop table t1;
drop table if exists t1;
create table t1 (i int);
connection: default
lock tables t1 write;
connection: flush
flush tables with read lock;;
connection: default
flush tables;
unlock tables;
drop table t1;
End of 5.1 tests

View file

@ -7,3 +7,7 @@ select 1+2;
SHOW GLOBAL VARIABLES LIKE 'thread_handling';
Variable_name Value
thread_handling no-threads
select @@session.thread_handling;
ERROR HY000: Variable 'thread_handling' is a GLOBAL variable
set GLOBAL thread_handling='one-thread';
ERROR HY000: Variable 'thread_handling' is a read only variable

2329
mysql-test/r/ps_ddl.result Normal file

File diff suppressed because it is too large Load diff

View file

@ -97,3 +97,31 @@ Note 1051 Unknown table 'ttt'
set global read_only=0;
drop table t1,t2;
drop user test@localhost;
#
# Bug #27440 read_only allows create and drop database
#
set global read_only= 1;
drop database if exists mysqltest_db1;
drop database if exists mysqltest_db2;
delete from mysql.user where User like 'mysqltest_%';
delete from mysql.db where User like 'mysqltest_%';
delete from mysql.tables_priv where User like 'mysqltest_%';
delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
grant all on mysqltest_db2.* to `mysqltest_u1`@`%`;
create database mysqltest_db1;
grant all on mysqltest_db1.* to `mysqltest_u1`@`%`;
flush privileges;
create database mysqltest_db2;
ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement
show databases like '%mysqltest_db2%';
Database (%mysqltest_db2%)
drop database mysqltest_db1;
ERROR HY000: The MySQL server is running with the --read-only option so it cannot execute this statement
delete from mysql.user where User like 'mysqltest_%';
delete from mysql.db where User like 'mysqltest_%';
delete from mysql.tables_priv where User like 'mysqltest_%';
delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
drop database mysqltest_db1;
set global read_only=0;

View file

@ -448,4 +448,18 @@ DROP TABLE t1;
DROP DATABASE mysqltest_db1;
USE test;
End of 5.0 tests.
drop table if exists t1;
create table t1 (i int);
connection: default
lock tables t1 write;
connection: flush
flush tables with read lock;;
connection: default
create trigger t1_bi before insert on t1 for each row begin end;
unlock tables;
connection: flush
unlock tables;
select * from t1;
i
drop table t1;
End of 5.1 tests.

View file

@ -123,7 +123,7 @@ Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1364
Last_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef.
Last_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef. Field 'x' doesn't have a default value
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
@ -141,7 +141,7 @@ Master_SSL_Verify_Server_Cert No
Last_IO_Errno 0
Last_IO_Error
Last_SQL_Errno 1364
Last_SQL_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef.
Last_SQL_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef. Field 'x' doesn't have a default value
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
INSERT INTO t9 VALUES (2);

View file

@ -123,7 +123,7 @@ Replicate_Ignore_Table
Replicate_Wild_Do_Table
Replicate_Wild_Ignore_Table
Last_Errno 1364
Last_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef.
Last_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef. Field 'x' doesn't have a default value
Skip_Counter 0
Exec_Master_Log_Pos #
Relay_Log_Space #
@ -141,7 +141,7 @@ Master_SSL_Verify_Server_Cert No
Last_IO_Errno 0
Last_IO_Error
Last_SQL_Errno 1364
Last_SQL_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef.
Last_SQL_Error Error in Write_rows event: error during transaction execution on table test.t1_nodef. Field 'x' doesn't have a default value
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
START SLAVE;
INSERT INTO t9 VALUES (2);

View file

@ -20,6 +20,6 @@ lowercase_table3 : Bug#32667 lowercase_table3.test reports to error log
kill : Bug#29149: Test "kill" fails on Windows
innodb_mysql : Bug#32724: innodb_mysql.test fails randomly
wait_timeout : Bug#32801 wait_timeout.test fails randomly
kill : Bug#29149 Test "kill" fails on Windows
ctype_create : Bug#32965 main.ctype_create fails
status : Bug#32966 main.status fails
ps_ddl : Bug#12093 2007-12-14 pending WL#4165 / WL#4166

View file

@ -1362,6 +1362,7 @@ use test;
#
--echo FLUSH PRIVILEGES without procs_priv table.
RENAME TABLE mysql.procs_priv TO mysql.procs_gone;
--error ER_NO_SUCH_TABLE
FLUSH PRIVILEGES;
--echo Assigning privileges without procs_priv table.
CREATE DATABASE mysqltest1;

View file

@ -150,7 +150,7 @@ send SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1;
connection locker;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Locked" and info =
where state = "Waiting for table" and info =
"SELECT user.Select_priv FROM user, db WHERE user.user = db.user LIMIT 1";
--source include/wait_condition.inc
# Make test case independent from earlier grants.
@ -343,4 +343,100 @@ handler t1 open;
connection default;
drop table t1;
#
# Bug#32395 Alter table under a impending global read lock causes a server crash
#
#
# Test ALTER TABLE under LOCK TABLES and FLUSH TABLES WITH READ LOCK
#
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (i int);
connect (flush,localhost,root,,test,,);
connection default;
--echo connection: default
lock tables t1 write;
connection flush;
--echo connection: flush
--send flush tables with read lock;
connection default;
--echo connection: default
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Flushing tables";
--source include/wait_condition.inc
alter table t1 add column j int;
connect (insert,localhost,root,,test,,);
connection insert;
--echo connection: insert
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Flushing tables";
--source include/wait_condition.inc
--send insert into t1 values (1,2);
--echo connection: default
connection default;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for release of readlock";
--source include/wait_condition.inc
unlock tables;
connection flush;
--echo connection: flush
--reap
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Waiting for release of readlock";
--source include/wait_condition.inc
select * from t1;
unlock tables;
connection insert;
--reap
connection default;
select * from t1;
drop table t1;
disconnect flush;
disconnect insert;
#
# Test that FLUSH TABLES under LOCK TABLES protects write locked tables
# from a impending FLUSH TABLES WITH READ LOCK
#
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (i int);
connect (flush,localhost,root,,test,,);
connection default;
--echo connection: default
lock tables t1 write;
connection flush;
--echo connection: flush
--send flush tables with read lock;
connection default;
--echo connection: default
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Flushing tables";
--source include/wait_condition.inc
flush tables;
let $wait_condition=
select count(*) = 1 from information_schema.processlist
where state = "Flushing tables";
--source include/wait_condition.inc
unlock tables;
let $wait_condition=
select count(*) = 0 from information_schema.processlist
where state = "Flushing tables";
--source include/wait_condition.inc
connection flush;
--reap
connection default;
disconnect flush;
drop table t1;
--echo End of 5.1 tests

View file

@ -4,3 +4,13 @@
select 1+1;
select 1+2;
SHOW GLOBAL VARIABLES LIKE 'thread_handling';
#
# Bug #30651 Problems with thread_handling system variable
#
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
select @@session.thread_handling;
--error ER_INCORRECT_GLOBAL_LOCAL_VAR
set GLOBAL thread_handling='one-thread';

1851
mysql-test/t/ps_ddl.test Normal file

File diff suppressed because it is too large Load diff

View file

@ -225,3 +225,38 @@ connection default;
set global read_only=0;
drop table t1,t2;
drop user test@localhost;
--echo #
--echo # Bug #27440 read_only allows create and drop database
--echo #
set global read_only= 1;
--disable_warnings
drop database if exists mysqltest_db1;
drop database if exists mysqltest_db2;
--enable_warnings
delete from mysql.user where User like 'mysqltest_%';
delete from mysql.db where User like 'mysqltest_%';
delete from mysql.tables_priv where User like 'mysqltest_%';
delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
grant all on mysqltest_db2.* to `mysqltest_u1`@`%`;
create database mysqltest_db1;
grant all on mysqltest_db1.* to `mysqltest_u1`@`%`;
flush privileges;
connect (con_bug27440,127.0.0.1,mysqltest_u1,,test,$MASTER_MYPORT,);
connection con_bug27440;
--error ER_OPTION_PREVENTS_STATEMENT
create database mysqltest_db2;
show databases like '%mysqltest_db2%';
--error ER_OPTION_PREVENTS_STATEMENT
drop database mysqltest_db1;
disconnect con_bug27440;
connection default;
delete from mysql.user where User like 'mysqltest_%';
delete from mysql.db where User like 'mysqltest_%';
delete from mysql.tables_priv where User like 'mysqltest_%';
delete from mysql.columns_priv where User like 'mysqltest_%';
flush privileges;
drop database mysqltest_db1;
set global read_only=0;

View file

@ -880,8 +880,9 @@ USE test;
# Bug#23713 LOCK TABLES + CREATE TRIGGER + FLUSH TABLES WITH READ LOCK = deadlock
#
# Test temporarily disable due to Bug#32395
--disable_parsing
--disable_warnings
drop table if exists t1;
--enable_warnings
create table t1 (i int);
connect (flush,localhost,root,,test,,);
connection default;
@ -906,6 +907,5 @@ connection default;
select * from t1;
drop table t1;
disconnect flush;
--enable_parsing
--echo End of 5.1 tests.

View file

@ -257,7 +257,7 @@ int Mysql_connection::do_command()
return 1;
if (thread_registry->is_shutdown())
return 1;
net_send_error(&net, net.last_errno);
net_send_error(&net, net.client_last_errno);
net.error= 0;
return 0;
}

View file

@ -289,8 +289,8 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
DBUG_ASSERT(mysql != 0);
net= &mysql->net;
net->last_errno= errcode;
strmov(net->last_error, ER(errcode));
net->client_last_errno= errcode;
strmov(net->client_last_error, ER(errcode));
strmov(net->sqlstate, sqlstate);
DBUG_VOID_RETURN;
@ -304,8 +304,8 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
void net_clear_error(NET *net)
{
net->last_errno= 0;
net->last_error[0]= '\0';
net->client_last_errno= 0;
net->client_last_error[0]= '\0';
strmov(net->sqlstate, not_error_sqlstate);
}
@ -331,9 +331,9 @@ static void set_mysql_extended_error(MYSQL *mysql, int errcode,
DBUG_ASSERT(mysql != 0);
net= &mysql->net;
net->last_errno= errcode;
net->client_last_errno= errcode;
va_start(args, format);
my_vsnprintf(net->last_error, sizeof(net->last_error)-1,
my_vsnprintf(net->client_last_error, sizeof(net->client_last_error)-1,
format, args);
va_end(args);
strmov(net->sqlstate, sqlstate);
@ -667,7 +667,7 @@ cli_safe_read(MYSQL *mysql)
return (packet_error);
#endif /*MYSQL_SERVER*/
end_server(mysql);
set_mysql_error(mysql, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
set_mysql_error(mysql, net->client_last_errno == ER_NET_PACKET_TOO_LARGE ?
CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
return (packet_error);
}
@ -676,7 +676,7 @@ cli_safe_read(MYSQL *mysql)
if (len > 3)
{
char *pos=(char*) net->read_pos+1;
net->last_errno=uint2korr(pos);
net->client_last_errno=uint2korr(pos);
pos+=2;
len-=2;
if (protocol_41(mysql) && pos[0] == '#')
@ -684,8 +684,8 @@ cli_safe_read(MYSQL *mysql)
strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH);
pos+= SQLSTATE_LENGTH+1;
}
(void) strmake(net->last_error,(char*) pos,
min((uint) len,(uint) sizeof(net->last_error)-1));
(void) strmake(net->client_last_error,(char*) pos,
min((uint) len,(uint) sizeof(net->client_last_error)-1));
}
else
set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
@ -701,7 +701,9 @@ cli_safe_read(MYSQL *mysql)
mysql->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
DBUG_PRINT("error",("Got error: %d/%s (%s)",
net->last_errno, net->sqlstate, net->last_error));
net->client_last_errno,
net->sqlstate,
net->client_last_error));
return(packet_error);
}
return len;
@ -744,7 +746,6 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
}
net_clear_error(net);
net->report_error=0;
mysql->info=0;
mysql->affected_rows= ~(my_ulonglong) 0;
/*
@ -759,7 +760,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
{
DBUG_PRINT("error",("Can't send command to server. Error: %d",
socket_errno));
if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
if (net->client_last_errno == ER_NET_PACKET_TOO_LARGE)
{
set_mysql_error(mysql, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
goto end;
@ -836,16 +837,15 @@ static my_bool is_NT(void)
#ifdef CHECK_LICENSE
/*
/**
Check server side variable 'license'.
If the variable does not exist or does not contain 'Commercial',
If the variable does not exist or does not contain 'Commercial',
we're talking to non-commercial server from commercial client.
SYNOPSIS
check_license()
RETURN VALUE
0 success
!0 network error or the server is not commercial.
Error code is saved in mysql->net.last_errno.
@retval 0 success
@retval !0 network error or the server is not commercial.
Error code is saved in mysql->net.client_last_errno.
*/
static int check_license(MYSQL *mysql)
@ -858,7 +858,7 @@ static int check_license(MYSQL *mysql)
if (mysql_real_query(mysql, query, sizeof(query)-1))
{
if (net->last_errno == ER_UNKNOWN_SYSTEM_VARIABLE)
if (net->client_last_errno == ER_UNKNOWN_SYSTEM_VARIABLE)
{
set_mysql_extended_error(mysql, CR_WRONG_LICENSE, unknown_sqlstate,
ER(CR_WRONG_LICENSE), required_license);
@ -873,7 +873,7 @@ static int check_license(MYSQL *mysql)
two is ever true for server variables now), or column value
mismatch, set wrong license error.
*/
if (!net->last_errno &&
if (!net->client_last_errno &&
(!row || !row[0] ||
strncmp(row[0], required_license, sizeof(required_license))))
{
@ -881,7 +881,7 @@ static int check_license(MYSQL *mysql)
ER(CR_WRONG_LICENSE), required_license);
}
mysql_free_result(res);
return net->last_errno;
return net->client_last_errno;
}
#endif /* CHECK_LICENSE */
@ -2090,7 +2090,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
if ((pkt_length=cli_safe_read(mysql)) == packet_error)
{
if (mysql->net.last_errno == CR_SERVER_LOST)
if (mysql->net.client_last_errno == CR_SERVER_LOST)
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
ER(CR_SERVER_LOST_EXTENDED),
"reading initial communication packet",
@ -2324,7 +2324,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
if ((pkt_length=cli_safe_read(mysql)) == packet_error)
{
if (mysql->net.last_errno == CR_SERVER_LOST)
if (mysql->net.client_last_errno == CR_SERVER_LOST)
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
ER(CR_SERVER_LOST_EXTENDED),
"reading authorization packet",
@ -2352,7 +2352,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
/* Read what server thinks about out new auth message report */
if (cli_safe_read(mysql) == packet_error)
{
if (mysql->net.last_errno == CR_SERVER_LOST)
if (mysql->net.client_last_errno == CR_SERVER_LOST)
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
ER(CR_SERVER_LOST_EXTENDED),
"reading final connect information",
@ -2371,7 +2371,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
if (db && mysql_select_db(mysql, db))
{
if (mysql->net.last_errno == CR_SERVER_LOST)
if (mysql->net.client_last_errno == CR_SERVER_LOST)
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
ER(CR_SERVER_LOST_EXTENDED),
"Setting intital database",
@ -2415,7 +2415,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
error:
reset_sigpipe(mysql);
DBUG_PRINT("error",("message: %u/%s (%s)",
net->last_errno, net->sqlstate, net->last_error));
net->client_last_errno,
net->sqlstate,
net->client_last_error));
{
/* Free alloced memory */
end_server(mysql);
@ -2473,8 +2475,8 @@ my_bool mysql_reconnect(MYSQL *mysql)
mysql->db, mysql->port, mysql->unix_socket,
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
{
mysql->net.last_errno= tmp_mysql.net.last_errno;
strmov(mysql->net.last_error, tmp_mysql.net.last_error);
mysql->net.client_last_errno= tmp_mysql.net.client_last_errno;
strmov(mysql->net.client_last_error, tmp_mysql.net.client_last_error);
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
DBUG_RETURN(1);
}
@ -2483,8 +2485,8 @@ my_bool mysql_reconnect(MYSQL *mysql)
DBUG_PRINT("error", ("mysql_set_character_set() failed"));
bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options));
mysql_close(&tmp_mysql);
mysql->net.last_errno= tmp_mysql.net.last_errno;
strmov(mysql->net.last_error, tmp_mysql.net.last_error);
mysql->net.client_last_errno= tmp_mysql.net.client_last_errno;
strmov(mysql->net.client_last_error, tmp_mysql.net.client_last_error);
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
DBUG_RETURN(1);
}
@ -3077,13 +3079,13 @@ unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
uint STDCALL mysql_errno(MYSQL *mysql)
{
return mysql->net.last_errno;
return mysql->net.client_last_errno;
}
const char * STDCALL mysql_error(MYSQL *mysql)
{
return mysql->net.last_error;
return mysql->net.client_last_error;
}
@ -3152,7 +3154,7 @@ int STDCALL mysql_set_character_set(MYSQL *mysql, const char *cs_name)
ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
}
charsets_dir= save_csdir;
return mysql->net.last_errno;
return mysql->net.client_last_errno;
}

View file

@ -577,7 +577,7 @@ int ha_ndbcluster::ndb_err(NdbTransaction *trans)
bzero((char*) &table_list,sizeof(table_list));
table_list.db= m_dbname;
table_list.alias= table_list.table_name= m_tabname;
close_cached_tables(thd, 0, &table_list);
close_cached_tables(thd, &table_list, FALSE, FALSE, FALSE);
break;
}
default:
@ -8125,7 +8125,7 @@ int handle_trailing_share(NDB_SHARE *share)
table_list.db= share->db;
table_list.alias= table_list.table_name= share->table_name;
safe_mutex_assert_owner(&LOCK_open);
close_cached_tables(thd, 0, &table_list, TRUE);
close_cached_tables(thd, &table_list, TRUE, FALSE, FALSE);
pthread_mutex_lock(&ndbcluster_mutex);
/* ndb_share reference temporary free */

View file

@ -261,6 +261,10 @@ static void run_query(THD *thd, char *buf, char *end,
thd->options&= ~OPTION_BIN_LOG;
DBUG_PRINT("query", ("%s", thd->query));
DBUG_ASSERT(!thd->in_sub_stmt);
DBUG_ASSERT(!thd->prelocked_mode);
mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
if (no_print_error && thd->is_slave_error)
@ -269,14 +273,27 @@ static void run_query(THD *thd, char *buf, char *end,
Thd_ndb *thd_ndb= get_thd_ndb(thd);
for (i= 0; no_print_error[i]; i++)
if ((thd_ndb->m_error_code == no_print_error[i]) ||
(thd->net.last_errno == (unsigned)no_print_error[i]))
(thd->main_da.sql_errno() == (unsigned) no_print_error[i]))
break;
if (!no_print_error[i])
sql_print_error("NDB: %s: error %s %d(ndb: %d) %d %d",
buf, thd->net.last_error, thd->net.last_errno,
buf,
thd->main_da.message(),
thd->main_da.sql_errno(),
thd_ndb->m_error_code,
(int) thd->is_error(), thd->is_slave_error);
}
/*
XXX: this code is broken. mysql_parse()/mysql_reset_thd_for_next_command()
can not be called from within a statement, and
run_query() can be called from anywhere, including from within
a sub-statement.
This particular reset is a temporary hack to avoid an assert
for double assignment of the diagnostics area when run_query()
is called from ndbcluster_reset_logs(), which is called from
mysql_flush().
*/
thd->main_da.reset_diagnostics_area();
thd->options= save_thd_options;
thd->query_length= save_thd_query_length;
@ -892,7 +909,7 @@ int ndbcluster_setup_binlog_table_shares(THD *thd)
{
if (ndb_extra_logging)
sql_print_information("NDB Binlog: ndb tables writable");
close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0, TRUE);
close_cached_tables(NULL, NULL, TRUE, FALSE, FALSE);
}
pthread_mutex_unlock(&LOCK_open);
/* Signal injector thread that all is setup */
@ -1692,7 +1709,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
bzero((char*) &table_list,sizeof(table_list));
table_list.db= (char *)dbname;
table_list.alias= table_list.table_name= (char *)tabname;
close_cached_tables(thd, 0, &table_list, TRUE);
close_cached_tables(thd, &table_list, TRUE, FALSE, FALSE);
if ((error= ndbcluster_binlog_open_table(thd, share,
table_share, table, 1)))
@ -1798,7 +1815,7 @@ ndb_handle_schema_change(THD *thd, Ndb *ndb, NdbEventOperation *pOp,
bzero((char*) &table_list,sizeof(table_list));
table_list.db= (char *)dbname;
table_list.alias= table_list.table_name= (char *)tabname;
close_cached_tables(thd, 0, &table_list);
close_cached_tables(thd, &table_list, FALSE, FALSE, FALSE);
/* ndb_share reference create free */
DBUG_PRINT("NDB_SHARE", ("%s create free use_count: %u",
share->key, share->use_count));
@ -1917,7 +1934,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
bzero((char*) &table_list,sizeof(table_list));
table_list.db= schema->db;
table_list.alias= table_list.table_name= schema->name;
close_cached_tables(thd, 0, &table_list, FALSE);
close_cached_tables(thd, &table_list, FALSE, FALSE, FALSE);
}
/* ndb_share reference temporary free */
if (share)
@ -2041,7 +2058,7 @@ ndb_binlog_thread_handle_schema_event(THD *thd, Ndb *ndb,
pthread_mutex_unlock(&ndb_schema_share_mutex);
/* end protect ndb_schema_share */
close_cached_tables((THD*) 0, 0, (TABLE_LIST*) 0, FALSE);
close_cached_tables(NULL, NULL, FALSE, FALSE, FALSE);
// fall through
case NDBEVENT::TE_ALTER:
ndb_handle_schema_change(thd, ndb, pOp, tmp_share);
@ -2198,7 +2215,7 @@ ndb_binlog_thread_handle_schema_event_post_epoch(THD *thd,
bzero((char*) &table_list,sizeof(table_list));
table_list.db= schema->db;
table_list.alias= table_list.table_name= schema->name;
close_cached_tables(thd, 0, &table_list, FALSE);
close_cached_tables(thd, &table_list, FALSE, FALSE, FALSE);
}
if (schema_type != SOT_ALTER_TABLE)
break;
@ -2309,9 +2326,12 @@ static int open_ndb_binlog_index(THD *thd, TABLE_LIST *tables,
thd->clear_error();
if (open_tables(thd, &tables, &counter, MYSQL_LOCK_IGNORE_FLUSH))
{
sql_print_error("NDB Binlog: Opening ndb_binlog_index: %d, '%s'",
thd->net.last_errno,
thd->net.last_error ? thd->net.last_error : "");
if (thd->killed)
sql_print_error("NDB Binlog: Opening ndb_binlog_index: killed");
else
sql_print_error("NDB Binlog: Opening ndb_binlog_index: %d, '%s'",
thd->main_da.sql_errno(),
thd->main_da.message());
thd->proc_info= save_proc_info;
return -1;
}

View file

@ -1765,6 +1765,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
return part_elem;
}
DBUG_ASSERT(0);
my_error(ER_OUT_OF_RESOURCES, MYF(0));
current_thd->fatal_error(); // Abort
return NULL;
}

View file

@ -2949,7 +2949,6 @@ udf_handler::fix_fields(THD *thd, Item_result_field *func,
}
}
}
thd->net.last_error[0]=0;
Udf_func_init init= u_d->func_init;
if ((error=(uchar) init(&initid, &f_args, init_msg_buff)))
{

View file

@ -280,29 +280,34 @@ void Log_to_csv_event_handler::cleanup()
/* log event handlers */
/*
/**
Log command to the general log table
SYNOPSIS
log_general()
Log given command to the general log table.
event_time command start timestamp
user_host the pointer to the string with user@host info
user_host_len length of the user_host string. this is computed once
and passed to all general log event handlers
thread_id Id of the thread, issued a query
command_type the type of the command being logged
command_type_len the length of the string above
sql_text the very text of the query being executed
sql_text_len the length of sql_text string
@param event_time command start timestamp
@param user_host the pointer to the string with user@host info
@param user_host_len length of the user_host string. this is computed
once and passed to all general log event handlers
@param thread_id Id of the thread, issued a query
@param command_type the type of the command being logged
@param command_type_len the length of the string above
@param sql_text the very text of the query being executed
@param sql_text_len the length of sql_text string
DESCRIPTION
Log given command to the general log table
@return This function attempts to never call my_error(). This is
necessary, because general logging happens already after a statement
status has been sent to the client, so the client can not see the
error anyway. Besides, the error is not related to the statement
being executed and is internal, and thus should be handled
internally (@todo: how?).
If a write to the table has failed, the function attempts to
write to a short error message to the file. The failure is also
indicated in the return value.
RETURN
FALSE - OK
TRUE - error occured
@retval FALSE OK
@retval TRUE error occured
*/
bool Log_to_csv_event_handler::
@ -342,6 +347,20 @@ bool Log_to_csv_event_handler::
table_list.db= MYSQL_SCHEMA_NAME.str;
table_list.db_length= MYSQL_SCHEMA_NAME.length;
/*
1) open_performance_schema_table generates an error of the
table can not be opened or is corrupted.
2) "INSERT INTO general_log" can generate warning sometimes.
Suppress these warnings and errors, they can't be dealt with
properly anyway.
QQ: this problem needs to be studied in more detail.
Comment this 2 lines and run "cast.test" to see what's happening.
*/
thd->push_internal_handler(& error_handler);
need_pop= TRUE;
if (!(table= open_performance_schema_table(thd, & table_list,
& open_tables_backup)))
goto err;
@ -357,14 +376,6 @@ bool Log_to_csv_event_handler::
/* Honor next number columns if present */
table->next_number_field= table->found_next_number_field;
/*
"INSERT INTO general_log" can generate warning sometimes.
QQ: this problem needs to be studied in more details.
Comment this 2 lines and run "cast.test" to see what's happening:
*/
thd->push_internal_handler(& error_handler);
need_pop= TRUE;
/*
NOTE: we do not call restore_record() here, as all fields are
filled by the Logger (=> no need to load default ones).

View file

@ -1611,7 +1611,8 @@ Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
if (killed_status_arg == THD::KILLED_NO_VALUE)
killed_status_arg= thd_arg->killed;
error_code=
(killed_status_arg == THD::NOT_KILLED) ? thd_arg->net.last_errno :
(killed_status_arg == THD::NOT_KILLED) ?
(thd_arg->is_error() ? thd_arg->main_da.sql_errno() : 0) :
((thd_arg->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? 0 :
thd_arg->killed_errno());
@ -2332,7 +2333,7 @@ START SLAVE; . Query: '%s'", expected_error, thd->query);
}
/* If the query was not ignored, it is printed to the general log */
if (thd->net.last_errno != ER_SLAVE_IGNORED_TABLE)
if (!thd->is_error() || thd->main_da.sql_errno() != ER_SLAVE_IGNORED_TABLE)
general_log_write(thd, COM_QUERY, thd->query, thd->query_length);
compare_errors:
@ -2341,9 +2342,10 @@ compare_errors:
If we expected a non-zero error code, and we don't get the same error
code, and none of them should be ignored.
*/
DBUG_PRINT("info",("expected_error: %d last_errno: %d",
expected_error, thd->net.last_errno));
if ((expected_error != (actual_error= thd->net.last_errno)) &&
actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0;
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
expected_error, actual_error));
if ((expected_error != actual_error) &&
expected_error &&
!ignored_error_code(actual_error) &&
!ignored_error_code(expected_error))
@ -2355,7 +2357,7 @@ Error on master: '%s' (%d), Error on slave: '%s' (%d). \
Default database: '%s'. Query: '%s'",
ER_SAFE(expected_error),
expected_error,
actual_error ? thd->net.last_error: "no error",
actual_error ? thd->main_da.message() : "no error",
actual_error,
print_slave_db_safe(db), query_arg);
thd->is_slave_error= 1;
@ -2377,7 +2379,7 @@ Default database: '%s'. Query: '%s'",
{
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on query. Default database: '%s'. Query: '%s'",
(actual_error ? thd->net.last_error :
(actual_error ? thd->main_da.message() :
"unexpected success or fatal error"),
print_slave_db_safe(thd->db), query_arg);
thd->is_slave_error= 1;
@ -3720,8 +3722,11 @@ error:
/* this err/sql_errno code is copy-paste from net_send_error() */
const char *err;
int sql_errno;
if ((err=thd->net.last_error)[0])
sql_errno=thd->net.last_errno;
if (thd->is_error())
{
err= thd->main_da.message();
sql_errno= thd->main_da.sql_errno();
}
else
{
sql_errno=ER_UNKNOWN_ERROR;
@ -6222,10 +6227,10 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
Error reporting borrowed from Query_log_event with many excessive
simplifications (we don't honour --slave-skip-errors)
*/
uint actual_error= thd->net.last_errno;
uint actual_error= thd->main_da.sql_errno();
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' in %s event: when locking tables",
(actual_error ? thd->net.last_error :
(actual_error ? thd->main_da.message():
"unexpected success or fatal error"),
get_type_str());
thd->is_fatal_error= 1;
@ -6266,10 +6271,10 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
Error reporting borrowed from Query_log_event with many excessive
simplifications (we don't honour --slave-skip-errors)
*/
uint actual_error= thd->net.last_errno;
uint actual_error= thd->main_da.sql_errno();
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on reopening tables",
(actual_error ? thd->net.last_error :
(actual_error ? thd->main_da.message() :
"unexpected success or fatal error"));
thd->is_slave_error= 1;
}
@ -6425,10 +6430,11 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
break;
default:
rli->report(ERROR_LEVEL, thd->net.last_errno,
rli->report(ERROR_LEVEL,
thd->is_error() ? thd->main_da.sql_errno() : 0,
"Error in %s event: row application failed. %s",
get_type_str(),
thd->net.last_error ? thd->net.last_error : "");
thd->is_error() ? thd->main_da.message() : "");
thd->is_slave_error= 1;
break;
}
@ -6475,12 +6481,13 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
if (error)
{ /* error has occured during the transaction */
rli->report(ERROR_LEVEL, thd->net.last_errno,
rli->report(ERROR_LEVEL,
thd->is_error() ? thd->main_da.sql_errno() : 0,
"Error in %s event: error during transaction execution "
"on table %s.%s. %s",
get_type_str(), table->s->db.str,
table->s->table_name.str,
thd->net.last_error ? thd->net.last_error : "");
thd->is_error() ? thd->main_da.message() : "");
/*
If one day we honour --skip-slave-errors in row-based replication, and
@ -7094,10 +7101,10 @@ int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
Error reporting borrowed from Query_log_event with many excessive
simplifications (we don't honour --slave-skip-errors)
*/
uint actual_error= thd->net.last_errno;
uint actual_error= thd->main_da.sql_errno();
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on opening table `%s`.`%s`",
(actual_error ? thd->net.last_error :
(actual_error ? thd->main_da.message() :
"unexpected success or fatal error"),
table_list->db, table_list->table_name);
thd->is_slave_error= 1;
@ -7625,8 +7632,11 @@ Write_rows_log_event::do_exec_row(const Relay_log_info *const rli)
DBUG_ASSERT(m_table != NULL);
int error= write_row(rli, TRUE /* overwrite */);
if (error && !thd->net.last_errno)
thd->net.last_errno= error;
if (error && !thd->is_error())
{
DBUG_ASSERT(0);
my_error(ER_UNKNOWN_ERROR, MYF(0));
}
return error;
}

View file

@ -74,10 +74,10 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli
Error reporting borrowed from Query_log_event with many excessive
simplifications (we don't honour --slave-skip-errors)
*/
uint actual_error= thd->net.last_errno;
uint actual_error= thd->main_da.sql_errno();
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' in %s event: when locking tables",
(actual_error ? thd->net.last_error :
(actual_error ? thd->main_da.message() :
"unexpected success or fatal error"),
ev->get_type_str());
thd->is_fatal_error= 1;
@ -118,10 +118,10 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli
Error reporting borrowed from Query_log_event with many excessive
simplifications (we don't honour --slave-skip-errors)
*/
uint actual_error= thd->net.last_errno;
uint actual_error= thd->main_da.sql_errno();
rli->report(ERROR_LEVEL, actual_error,
"Error '%s' on reopening tables",
(actual_error ? thd->net.last_error :
(actual_error ? thd->main_da.message() :
"unexpected success or fatal error"));
thd->is_slave_error= 1;
}
@ -251,10 +251,10 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli
break;
default:
rli->report(ERROR_LEVEL, thd->net.last_errno,
rli->report(ERROR_LEVEL, thd->main_da.sql_errno(),
"Error in %s event: row application failed. %s",
ev->get_type_str(),
thd->net.last_error ? thd->net.last_error : "");
thd->is_error() ? thd->main_da.message() : "");
thd->is_slave_error= 1;
break;
}
@ -280,12 +280,12 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli
if (error)
{ /* error has occured during the transaction */
rli->report(ERROR_LEVEL, thd->net.last_errno,
rli->report(ERROR_LEVEL, thd->main_da.sql_errno(),
"Error in %s event: error during transaction execution "
"on table %s.%s. %s",
ev->get_type_str(), table->s->db.str,
table->s->table_name.str,
thd->net.last_error ? thd->net.last_error : "");
thd->is_error() ? thd->main_da.message() : "");
/*
If one day we honour --skip-slave-errors in row-based replication, and

View file

@ -1631,7 +1631,8 @@ TABLE *open_performance_schema_table(THD *thd, TABLE_LIST *one_table,
Open_tables_state *backup);
void close_performance_schema_table(THD *thd, Open_tables_state *backup);
bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables, bool have_lock = FALSE);
bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
bool wait_for_refresh, bool wait_for_placeholders);
bool close_cached_connection_tables(THD *thd, bool wait_for_refresh,
LEX_STRING *connect_string,
bool have_lock = FALSE);

View file

@ -492,7 +492,7 @@ ulong thread_id=1L,current_pid;
ulong slow_launch_threads = 0, sync_binlog_period;
ulong expire_logs_days = 0;
ulong rpl_recovery_rank=0;
const char *log_output_str= "TABLE";
const char *log_output_str= "FILE";
time_t server_start_time;
@ -2603,21 +2603,8 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
MYSQL_ERROR::WARN_LEVEL_ERROR))
DBUG_RETURN(0);
if (thd->spcont &&
thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
{
DBUG_RETURN(0);
}
thd->is_slave_error= 1; // needed to catch query errors during replication
if (!thd->no_warnings_for_error)
{
thd->no_warnings_for_error= TRUE;
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
thd->no_warnings_for_error= FALSE;
}
/*
thd->lex->current_select == 0 if lex structure is not inited
(not query command (COM_QUERY))
@ -2634,14 +2621,39 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
}
else
{
NET *net= &thd->net;
net->report_error= 1;
query_cache_abort(net);
if (!net->last_error[0]) // Return only first message
if (! thd->main_da.is_error()) // Return only first message
{
strmake(net->last_error, str, sizeof(net->last_error)-1);
net->last_errno= error ? error : ER_UNKNOWN_ERROR;
if (error == 0)
error= ER_UNKNOWN_ERROR;
if (str == NULL)
str= ER(error);
thd->main_da.set_error_status(thd, error, str);
}
query_cache_abort(&thd->net);
}
/*
If a continue handler is found, the error message will be cleared
by the stored procedures code.
*/
if (thd->spcont &&
thd->spcont->handle_error(error, MYSQL_ERROR::WARN_LEVEL_ERROR, thd))
{
/*
Do not push any warnings, a handled error must be completely
silenced.
*/
DBUG_RETURN(0);
}
if (!thd->no_warnings_for_error)
{
/*
Suppress infinite recursion if there a memory allocation error
inside push_warning.
*/
thd->no_warnings_for_error= TRUE;
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, str);
thd->no_warnings_for_error= FALSE;
}
}
if (!thd || MyFlags & ME_NOREFRESH)
@ -7495,7 +7507,7 @@ mysqld_get_one_option(int optid,
{
if (!argument || !argument[0])
{
log_output_options= LOG_TABLE;
log_output_options= LOG_FILE;
log_output_str= log_output_typelib.type_names[1];
}
else

View file

@ -123,20 +123,18 @@ my_bool my_net_init(NET *net, Vio* vio)
MYF(MY_WME))))
DBUG_RETURN(1);
net->buff_end=net->buff+net->max_packet;
net->no_send_ok= net->no_send_error= 0;
net->error=0; net->return_errno=0; net->return_status=0;
net->pkt_nr=net->compress_pkt_nr=0;
net->write_pos=net->read_pos = net->buff;
net->last_error[0]=0;
net->client_last_error[0]=0;
net->compress=0; net->reading_or_writing=0;
net->where_b = net->remain_in_buf=0;
net->last_errno=0;
net->client_last_errno=0;
#ifdef USE_QUERY_CACHE
query_cache_init_query(net);
#else
net->query_cache_query= 0;
#endif
net->report_error= 0;
if (vio != 0) /* If real connection */
{
@ -176,9 +174,12 @@ my_bool net_realloc(NET *net, size_t length)
{
DBUG_PRINT("error", ("Packet too large. Max size: %lu",
net->max_packet_size));
/* @todo: 1 and 2 codes are identical. */
net->error= 1;
net->report_error= 1;
net->last_errno= ER_NET_PACKET_TOO_LARGE;
net->client_last_errno= ER_NET_PACKET_TOO_LARGE;
#ifdef MYSQL_SERVER
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
#endif
DBUG_RETURN(1);
}
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
@ -190,9 +191,10 @@ my_bool net_realloc(NET *net, size_t length)
NET_HEADER_SIZE + COMP_HEADER_SIZE,
MYF(MY_WME))))
{
/* @todo: 1 and 2 codes are identical. */
net->error= 1;
net->report_error= 1;
net->last_errno= ER_OUT_OF_RESOURCES;
net->client_last_errno= ER_OUT_OF_RESOURCES;
/* In the server the error is reported by MY_WME flag. */
DBUG_RETURN(1);
}
net->buff=net->write_pos=buff;
@ -582,12 +584,9 @@ net_real_write(NET *net,const uchar *packet, size_t len)
if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE +
COMP_HEADER_SIZE, MYF(MY_WME))))
{
#ifdef MYSQL_SERVER
net->last_errno= ER_OUT_OF_RESOURCES;
net->error= 2;
/* TODO is it needed to set this variable if we have no socket */
net->report_error= 1;
#endif
net->client_last_errno= ER_OUT_OF_RESOURCES;
/* In the server, the error is reported by MY_WME flag. */
net->reading_or_writing= 0;
DBUG_RETURN(1);
}
@ -638,11 +637,11 @@ net_real_write(NET *net,const uchar *packet, size_t len)
"%s: my_net_write: fcntl returned error %d, aborting thread\n",
my_progname,vio_errno(net->vio));
#endif /* EXTRA_DEBUG */
#ifdef MYSQL_SERVER
net->last_errno= ER_NET_ERROR_ON_WRITE;
#endif
net->error= 2; /* Close socket */
net->report_error= 1;
net->client_last_errno= ER_NET_PACKET_TOO_LARGE;
#ifdef MYSQL_SERVER
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
#endif
goto end;
}
retry_count=0;
@ -669,10 +668,10 @@ net_real_write(NET *net,const uchar *packet, size_t len)
}
#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
net->error= 2; /* Close socket */
net->report_error= 1;
net->client_last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
ER_NET_ERROR_ON_WRITE);
#ifdef MYSQL_SERVER
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
ER_NET_ERROR_ON_WRITE);
my_error(net->client_last_errno, MYF(0));
#endif /* MYSQL_SERVER */
break;
}
@ -849,9 +848,9 @@ my_real_read(NET *net, size_t *complen)
#endif /* EXTRA_DEBUG */
len= packet_error;
net->error= 2; /* Close socket */
net->report_error= 1;
net->client_last_errno= ER_NET_FCNTL_ERROR;
#ifdef MYSQL_SERVER
net->last_errno= ER_NET_FCNTL_ERROR;
my_error(ER_NET_FCNTL_ERROR, MYF(0));
#endif
goto end;
}
@ -881,10 +880,11 @@ my_real_read(NET *net, size_t *complen)
remain, vio_errno(net->vio), (long) length));
len= packet_error;
net->error= 2; /* Close socket */
net->report_error= 1;
net->client_last_errno= (vio_was_interrupted(net->vio) ?
ER_NET_READ_INTERRUPTED :
ER_NET_READ_ERROR);
#ifdef MYSQL_SERVER
net->last_errno= (vio_was_interrupted(net->vio) ? ER_NET_READ_INTERRUPTED :
ER_NET_READ_ERROR);
my_error(net->client_last_errno, MYF(0));
#endif
goto end;
}
@ -915,9 +915,9 @@ my_real_read(NET *net, size_t *complen)
#endif
}
len= packet_error;
net->report_error= 1;
/* Not a NET error on the client. XXX: why? */
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER;
my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
#endif
goto end;
}
@ -1101,9 +1101,9 @@ my_net_read(NET *net)
&complen))
{
net->error= 2; /* caller will close socket */
net->report_error= 1;
net->client_last_errno= ER_NET_UNCOMPRESS_ERROR;
#ifdef MYSQL_SERVER
net->last_errno=ER_NET_UNCOMPRESS_ERROR;
my_error(ER_NET_UNCOMPRESS_ERROR, MYF(0));
#endif
return packet_error;
}

View file

@ -1274,7 +1274,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
the storage engine calls in question happen to never fail with the
existing storage engines.
*/
thd->net.report_error= 1; /* purecov: inspected */
my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */
/* Caller will free the memory */
goto failure; /* purecov: inspected */
}

View file

@ -170,6 +170,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
if(error)
{
tl->table->file->print_error(error, MYF(0));
tl->table->in_use->fatal_error();
return error;
}
count*= tl->table->file->stats.records;
@ -418,6 +419,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE
/* HA_ERR_LOCK_DEADLOCK or some other error */
table->file->print_error(error, MYF(0));
table->in_use->fatal_error();
return(error);
}
removed_tables|= table->map;

View file

@ -23,13 +23,20 @@
#endif
#include "mysql_priv.h"
#include "sp_rcontext.h"
#include <stdarg.h>
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
/* Declared non-static only because of the embedded library. */
void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
void
net_send_ok(THD *thd,
uint server_status, uint total_warn_count,
ha_rows affected_rows, ulonglong id, const char *message);
void
net_send_eof(THD *thd, uint server_status, uint total_warn_count);
#ifndef EMBEDDED_LIBRARY
static void write_eof_packet(THD *thd, NET *net);
static void write_eof_packet(THD *thd, NET *net,
uint server_status, uint total_warn_count);
#endif
#ifndef EMBEDDED_LIBRARY
@ -67,62 +74,26 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length)
*/
void net_send_error(THD *thd, uint sql_errno, const char *err)
{
NET *net= &thd->net;
bool generate_warning= thd->killed != THD::KILL_CONNECTION;
DBUG_ENTER("net_send_error");
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
err ? err : net->last_error[0] ?
net->last_error : "NULL"));
DBUG_ASSERT(!thd->spcont);
DBUG_ASSERT(sql_errno);
DBUG_ASSERT(err && err[0]);
if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
{
thd->killed= THD::NOT_KILLED;
thd->mysys_var->abort= 0;
}
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
if (net && net->no_send_error)
{
thd->clear_error();
thd->is_fatal_error= 0; // Error message is given
DBUG_PRINT("info", ("sending error messages prohibited"));
DBUG_VOID_RETURN;
}
thd->is_slave_error= 1; // needed to catch query errors during replication
if (!err)
{
if (sql_errno)
err=ER(sql_errno);
else
{
if ((err=net->last_error)[0])
{
sql_errno=net->last_errno;
generate_warning= 0; // This warning has already been given
}
else
{
sql_errno=ER_UNKNOWN_ERROR;
err=ER(sql_errno); /* purecov: inspected */
}
}
}
if (generate_warning)
{
/* Error that we have not got with my_error() */
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, sql_errno, err);
}
/*
It's one case when we can push an error even though there
is an OK or EOF already.
*/
thd->main_da.can_overwrite_status= TRUE;
/* Abort multi-result sets */
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
net_send_error_packet(thd, sql_errno, err);
thd->is_fatal_error= 0; // Error message is given
thd->net.report_error= 0;
thd->main_da.can_overwrite_status= FALSE;
DBUG_VOID_RETURN;
}
@ -150,23 +121,21 @@ void net_send_error(THD *thd, uint sql_errno, const char *err)
warning_count Stored in 2 bytes; New in 4.1 protocol
message Stored as packed length (1-9 bytes) + message
Is not stored if no message
If net->no_send_ok return without sending packet
*/
#ifndef EMBEDDED_LIBRARY
void
send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
net_send_ok(THD *thd,
uint server_status, uint total_warn_count,
ha_rows affected_rows, ulonglong id, const char *message)
{
NET *net= &thd->net;
uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
DBUG_ENTER("send_ok");
if (net->no_send_ok || !net->vio) // hack for re-parsing queries
if (! net->vio) // hack for re-parsing queries
{
DBUG_PRINT("info", ("no send ok: %s, vio present: %s",
(net->no_send_ok ? "YES" : "NO"),
(net->vio ? "YES" : "NO")));
DBUG_PRINT("info", ("vio present: NO"));
DBUG_VOID_RETURN;
}
@ -179,28 +148,29 @@ send_ok(THD *thd, ha_rows affected_rows, ulonglong id, const char *message)
("affected_rows: %lu id: %lu status: %u warning_count: %u",
(ulong) affected_rows,
(ulong) id,
(uint) (thd->server_status & 0xffff),
(uint) thd->total_warn_count));
int2store(pos,thd->server_status);
(uint) (server_status & 0xffff),
(uint) total_warn_count));
int2store(pos, server_status);
pos+=2;
/* We can only return up to 65535 warnings in two bytes */
uint tmp= min(thd->total_warn_count, 65535);
uint tmp= min(total_warn_count, 65535);
int2store(pos, tmp);
pos+= 2;
}
else if (net->return_status) // For 4.0 protocol
{
int2store(pos,thd->server_status);
int2store(pos, server_status);
pos+=2;
}
if (message)
thd->main_da.can_overwrite_status= TRUE;
if (message && message[0])
pos= net_store_data(pos, (uchar*) message, strlen(message));
VOID(my_net_write(net, buff, (size_t) (pos-buff)));
VOID(net_flush(net));
/* We can't anymore send an error to the client */
thd->net.report_error= 0;
thd->net.no_send_error= 1;
thd->main_da.can_overwrite_status= FALSE;
DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
DBUG_VOID_RETURN;
@ -212,7 +182,7 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
Send eof (= end of result set) to the client
SYNOPSIS
send_eof()
net_send_eof()
thd Thread handler
no_flush Set to 1 if there will be more data to the client,
like in send_fields().
@ -231,15 +201,17 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
*/
void
send_eof(THD *thd)
net_send_eof(THD *thd, uint server_status, uint total_warn_count)
{
NET *net= &thd->net;
DBUG_ENTER("send_eof");
DBUG_ENTER("net_send_eof");
/* Set to TRUE if no active vio, to work well in case of --init-file */
if (net->vio != 0)
{
write_eof_packet(thd, net);
thd->main_da.can_overwrite_status= TRUE;
write_eof_packet(thd, net, server_status, total_warn_count);
VOID(net_flush(net));
thd->net.no_send_error= 1;
thd->main_da.can_overwrite_status= FALSE;
DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
}
DBUG_VOID_RETURN;
@ -251,7 +223,9 @@ send_eof(THD *thd)
write it to the network output buffer.
*/
static void write_eof_packet(THD *thd, NET *net)
static void write_eof_packet(THD *thd, NET *net,
uint server_status,
uint total_warn_count)
{
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
{
@ -260,7 +234,7 @@ static void write_eof_packet(THD *thd, NET *net)
Don't send warn count during SP execution, as the warn_list
is cleared between substatements, and mysqltest gets confused
*/
uint tmp= (thd->spcont ? 0 : min(thd->total_warn_count, 65535));
uint tmp= min(total_warn_count, 65535);
buff[0]= 254;
int2store(buff+1, tmp);
/*
@ -269,8 +243,8 @@ static void write_eof_packet(THD *thd, NET *net)
other queries (see the if test in dispatch_command / COM_QUERY)
*/
if (thd->is_fatal_error)
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
int2store(buff+3, thd->server_status);
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
int2store(buff + 3, server_status);
VOID(my_net_write(net, buff, 5));
}
else
@ -364,6 +338,96 @@ static uchar *net_store_length_fast(uchar *packet, uint length)
return packet+2;
}
/**
Send the status of the current statement execution over network.
@param thd in fact, carries two parameters, NET for the transport and
Diagnostics_area as the source of status information.
In MySQL, there are two types of SQL statements: those that return
a result set and those that return status information only.
If a statement returns a result set, it consists of 3 parts:
- result set meta-data
- variable number of result set rows (can be 0)
- followed and terminated by EOF or ERROR packet
Once the client has seen the meta-data information, it always
expects an EOF or ERROR to terminate the result set. If ERROR is
received, the result set rows are normally discarded (this is up
to the client implementation, libmysql at least does discard them).
EOF, on the contrary, means "successfully evaluated the entire
result set". Since we don't know how many rows belong to a result
set until it's evaluated, EOF/ERROR is the indicator of the end
of the row stream. Note, that we can not buffer result set rows
on the server -- there may be an arbitrary number of rows. But
we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
delay sending it till the very end of execution (here), to be able to
change EOF to an ERROR if commit failed or some other error occurred
during the last cleanup steps taken after execution.
A statement that does not return a result set doesn't send result
set meta-data either. Instead it returns one of:
- OK packet
- ERROR packet.
Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
packet is "buffered" in the diagnostics area and sent to the client
in the end of statement.
@pre The diagnostics area is assigned or disabled. It can not be empty
-- we assume that every SQL statement or COM_* command
generates OK, ERROR, or EOF status.
@post The status information is encoded to protocol format and sent to the
client.
@return We conventionally return void, since the only type of error
that can happen here is a NET (transport) error, and that one
will become visible when we attempt to read from the NET the
next command.
Diagnostics_area::is_sent is set for debugging purposes only.
*/
void net_end_statement(THD *thd)
{
DBUG_ASSERT(! thd->main_da.is_sent);
/* Can not be true, but do not take chances in production. */
if (thd->main_da.is_sent)
return;
switch (thd->main_da.status()) {
case Diagnostics_area::DA_ERROR:
/* The query failed, send error to log and abort bootstrap. */
net_send_error(thd,
thd->main_da.sql_errno(),
thd->main_da.message());
break;
case Diagnostics_area::DA_EOF:
net_send_eof(thd,
thd->main_da.server_status(),
thd->main_da.total_warn_count());
break;
case Diagnostics_area::DA_OK:
net_send_ok(thd,
thd->main_da.server_status(),
thd->main_da.total_warn_count(),
thd->main_da.affected_rows(),
thd->main_da.last_insert_id(),
thd->main_da.message());
break;
case Diagnostics_area::DA_DISABLED:
break;
case Diagnostics_area::DA_EMPTY:
default:
DBUG_ASSERT(0);
net_send_ok(thd, thd->server_status, thd->total_warn_count,
0, 0, NULL);
break;
}
thd->main_da.is_sent= TRUE;
}
/****************************************************************************
Functions used by the protocol functions (like send_ok) to store strings
@ -412,6 +476,17 @@ void Protocol::init(THD *thd_arg)
#endif
}
/**
Finish the result set with EOF packet, as is expected by the client,
if there is an error evaluating the next row and a continue handler
for the error.
*/
void Protocol::end_partial_result_set(THD *thd)
{
net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
}
bool Protocol::flush()
{
@ -577,7 +652,14 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
}
if (flags & SEND_EOF)
write_eof_packet(thd, &thd->net);
{
/*
Mark the end of meta-data result set, and store thd->server_status,
to show that there is no cursor.
Send no warning information, as it will be sent at statement end.
*/
write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
}
DBUG_RETURN(prepare_for_send(list));
err:

View file

@ -75,6 +75,7 @@ public:
return 0;
}
virtual bool flush();
virtual void end_partial_result_set(THD *thd);
virtual void prepare_for_resend()=0;
virtual bool store_null()=0;
@ -173,9 +174,7 @@ public:
void send_warning(THD *thd, uint sql_errno, const char *err=0);
void net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0);
void send_eof(THD *thd);
void net_end_statement(THD *thd);
bool send_old_password_request(THD *thd);
uchar *net_store_data(uchar *to,const uchar *from, size_t length);
uchar *net_store_data(uchar *to,int32 from);

View file

@ -685,7 +685,7 @@ int connect_to_master(THD *thd, MYSQL* mysql, Master_info* mi)
if (!mi->host || !*mi->host) /* empty host */
{
strmov(mysql->net.last_error, "Master is not configured");
strmov(mysql->net.client_last_error, "Master is not configured");
DBUG_RETURN(1);
}
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
@ -880,6 +880,8 @@ bool load_master_data(THD* thd)
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
goto err;
}
/* Clear the result of mysql_create_db(). */
thd->main_da.reset_diagnostics_area();
if (mysql_select_db(&mysql, db) ||
mysql_real_query(&mysql, STRING_WITH_LEN("SHOW TABLES")) ||

View file

@ -338,12 +338,13 @@ int prepare_record(const Slave_reporting_capability *const log,
if (check && ((f->flags & mask) == mask))
{
DBUG_ASSERT(log);
log->report(ERROR_LEVEL, ER_NO_DEFAULT_FOR_FIELD,
error= ER_NO_DEFAULT_FOR_FIELD;
log->report(ERROR_LEVEL, error,
"Field `%s` of table `%s`.`%s` "
"has no default value and cannot be NULL",
f->field_name, table->s->db.str,
table->s->table_name.str);
error = ER_NO_DEFAULT_FOR_FIELD;
my_error(error, MYF(0), f->field_name);
}
else
f->set_default();

View file

@ -166,7 +166,7 @@ int init_relay_log_info(Relay_log_info* rli,
{
sql_print_error("Failed to create a new relay log info file (\
file '%s', errno %d)", fname, my_errno);
msg= current_thd->net.last_error;
msg= current_thd->main_da.message();
goto err;
}
if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
@ -174,7 +174,7 @@ file '%s', errno %d)", fname, my_errno);
{
sql_print_error("Failed to create a cache on relay log info file '%s'",
fname);
msg= current_thd->net.last_error;
msg= current_thd->main_da.message();
goto err;
}

View file

@ -389,7 +389,7 @@ static sys_var_thd_ulong sys_trans_alloc_block_size(&vars, "transaction_alloc_bl
static sys_var_thd_ulong sys_trans_prealloc_size(&vars, "transaction_prealloc_size",
&SV::trans_prealloc_size,
0, fix_trans_mem_root);
sys_var_thd_enum sys_thread_handling(&vars, "thread_handling",
sys_var_enum_const sys_thread_handling(&vars, "thread_handling",
&SV::thread_handling,
&thread_handling_typelib,
NULL);
@ -1230,6 +1230,13 @@ uchar *sys_var_enum::value_ptr(THD *thd, enum_var_type type, LEX_STRING *base)
return (uchar*) enum_names->type_names[*value];
}
uchar *sys_var_enum_const::value_ptr(THD *thd, enum_var_type type,
LEX_STRING *base)
{
return (uchar*) enum_names->type_names[global_system_variables.*offset];
}
bool sys_var_thd_ulong::check(THD *thd, set_var *var)
{
return (get_unsigned(thd, var) ||
@ -3762,7 +3769,7 @@ bool sys_var_opt_readonly::update(THD *thd, set_var *var)
can cause to wait on a read lock, it's required for the client application
to unlock everything, and acceptable for the server to wait on all locks.
*/
if (result= close_cached_tables(thd, true, NULL, false))
if (result= close_cached_tables(thd, NULL, FALSE, TRUE, TRUE))
goto end_with_read_lock;
if (result= make_global_read_lock_block_commit(thd))

View file

@ -305,6 +305,24 @@ public:
};
class sys_var_enum_const :public sys_var
{
ulong SV::*offset;
TYPELIB *enum_names;
public:
sys_var_enum_const(sys_var_chain *chain, const char *name_arg, ulong SV::*offset_arg,
TYPELIB *typelib, sys_after_update_func func)
:sys_var(name_arg,func), offset(offset_arg), enum_names(typelib)
{ chain_sys_var(chain); }
bool check(THD *thd, set_var *var) { return 1; }
bool update(THD *thd, set_var *var) { return 1; }
SHOW_TYPE show_type() { return SHOW_CHAR; }
bool check_update_type(Item_result type) { return 1; }
bool is_readonly() const { return 1; }
uchar *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base);
};
class sys_var_thd :public sys_var
{
public:

View file

@ -982,17 +982,24 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
}
thd->query= query;
thd->is_slave_error = 0;
thd->net.no_send_ok = 1;
bzero((char*) &tables,sizeof(tables));
tables.db = (char*)db;
tables.alias= tables.table_name= (char*)table_name;
/* Drop the table if 'overwrite' is true */
if (overwrite && mysql_rm_table(thd,&tables,1,0)) /* drop if exists */
if (overwrite)
{
sql_print_error("create_table_from_dump: failed to drop the table");
goto err;
if (mysql_rm_table(thd,&tables,1,0)) /* drop if exists */
{
sql_print_error("create_table_from_dump: failed to drop the table");
goto err;
}
else
{
/* Clear the OK result of mysql_rm_table(). */
thd->main_da.reset_diagnostics_area();
}
}
/* Create the table. We do not want to log the "create table" statement */
@ -1013,6 +1020,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
if (thd->is_slave_error)
goto err; // mysql_parse took care of the error send
thd->main_da.reset_diagnostics_area(); /* cleanup from CREATE_TABLE */
thd->proc_info = "Opening master dump table";
/*
Note: If this function starts to fail for MERGE tables,
@ -1056,7 +1064,6 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
err:
close_thread_tables(thd);
thd->net.no_send_ok = 0;
DBUG_RETURN(error);
}
@ -1108,7 +1115,6 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
error = 0;
err:
thd->net.no_send_ok = 0; // Clear up garbage after create_table_from_dump
if (!called_connected)
mysql_close(mysql);
if (errmsg && thd->vio_ok())
@ -1722,26 +1728,31 @@ static int has_temporary_error(THD *thd)
DBUG_ENTER("has_temporary_error");
if (thd->is_fatal_error)
{
DBUG_PRINT("info", ("thd->net.last_errno: %s", ER(thd->net.last_errno)));
DBUG_RETURN(0);
}
DBUG_EXECUTE_IF("all_errors_are_temporary_errors",
if (thd->net.last_errno)
thd->net.last_errno= ER_LOCK_DEADLOCK;);
if (thd->main_da.is_error())
{
thd->clear_error();
my_error(ER_LOCK_DEADLOCK, MYF(0));
});
/*
If there is no message in THD, we can't say if it's a temporary
error or not. This is currently the case for Incident_log_event,
which sets no message. Return FALSE.
*/
if (!thd->is_error())
DBUG_RETURN(0);
/*
Temporary error codes:
currently, InnoDB deadlock detected by InnoDB or lock
wait timeout (innodb_lock_wait_timeout exceeded
*/
if (thd->net.last_errno == ER_LOCK_DEADLOCK ||
thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT)
{
DBUG_PRINT("info", ("thd->net.last_errno: %s", ER(thd->net.last_errno)));
if (thd->main_da.sql_errno() == ER_LOCK_DEADLOCK ||
thd->main_da.sql_errno() == ER_LOCK_WAIT_TIMEOUT)
DBUG_RETURN(1);
}
#ifdef HAVE_NDB_BINLOG
/*
@ -2556,20 +2567,21 @@ Slave SQL thread aborted. Can't execute init_slave query");
*/
uint32 const last_errno= rli->last_error().number;
DBUG_PRINT("info", ("thd->net.last_errno=%d; rli->last_error.number=%d",
thd->net.last_errno, last_errno));
if (thd->net.last_errno != 0)
if (thd->is_error())
{
char const *const errmsg=
thd->net.last_error ? thd->net.last_error : "<no message>";
char const *const errmsg= thd->main_da.message();
DBUG_PRINT("info",
("thd->main_da.sql_errno()=%d; rli->last_error.number=%d",
thd->main_da.sql_errno(), last_errno));
if (last_errno == 0)
{
rli->report(ERROR_LEVEL, thd->net.last_errno, errmsg);
rli->report(ERROR_LEVEL, thd->main_da.sql_errno(), errmsg);
}
else if (last_errno != thd->net.last_errno)
else if (last_errno != thd->main_da.sql_errno())
{
sql_print_error("Slave (additional info): %s Error_code: %d",
errmsg, thd->net.last_errno);
errmsg, thd->main_da.sql_errno());
}
}

View file

@ -1202,12 +1202,6 @@ sp_head::execute(THD *thd)
err_status= i->execute(thd, &ip);
/*
If this SP instruction have sent eof, it has caused no_send_error to be
set. Clear it back to allow the next instruction to send error. (multi-
statement execution code clears no_send_error between statements too)
*/
thd->net.no_send_error= 0;
if (i->free_list)
cleanup_items(i->free_list);
@ -2762,14 +2756,22 @@ sp_instr_stmt::execute(THD *thd, uint *nextp)
thd->query, thd->query_length) <= 0)
{
res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this);
if (thd->main_da.is_eof())
net_end_statement(thd);
query_cache_end_of_result(thd);
if (!res && unlikely(thd->enable_slow_log))
log_slow_statement(thd);
query_cache_end_of_result(thd);
}
else
*nextp= m_ip+1;
thd->query= query;
thd->query_length= query_length;
if (!thd->is_error())
thd->main_da.reset_diagnostics_area();
}
DBUG_RETURN(res);
}

View file

@ -287,7 +287,6 @@ sp_rcontext::find_handler(THD *thd, uint sql_errno,
sql_errno The error code
level Warning level
thd The current thread
- thd->net.report_error is an optional output.
RETURN
TRUE if a handler was found.
@ -298,7 +297,6 @@ sp_rcontext::handle_error(uint sql_errno,
MYSQL_ERROR::enum_warning_level level,
THD *thd)
{
bool handled= FALSE;
MYSQL_ERROR::enum_warning_level elevated_level= level;
@ -310,25 +308,7 @@ sp_rcontext::handle_error(uint sql_errno,
elevated_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
}
if (find_handler(thd, sql_errno, elevated_level))
{
if (elevated_level == MYSQL_ERROR::WARN_LEVEL_ERROR)
{
/*
Forces to abort the current instruction execution.
NOTE: This code is altering the original meaning of
the net.report_error flag (send an error to the client).
In the context of stored procedures with error handlers,
the flag is reused to cause error propagation,
until the error handler is reached.
No messages will be sent to the client in that context.
*/
thd->net.report_error= 1;
}
handled= TRUE;
}
return handled;
return find_handler(thd, sql_errno, elevated_level);
}
void

View file

@ -695,7 +695,7 @@ my_bool acl_reload(THD *thd)
if (simple_open_n_lock_tables(thd, tables))
{
sql_print_error("Fatal error: Can't open and lock privilege tables: %s",
thd->net.last_error);
thd->main_da.message());
goto end;
}
@ -3800,11 +3800,11 @@ my_bool grant_reload(THD *thd)
close_thread_tables(thd);
/*
It is ok failing to load procs_priv table because we may be
It is OK failing to load procs_priv table because we may be
working with 4.1 privilege tables.
*/
if (grant_reload_procs_priv(thd))
my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0), "mysql.procs_priv");
return_val= 1;
rw_wrlock(&LOCK_grant);
grant_version++;
@ -5693,9 +5693,6 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
if (result)
my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe());
DBUG_PRINT("info", ("thd->net.last_errno: %d", thd->net.last_errno));
DBUG_PRINT("info", ("thd->net.last_error: %s", thd->net.last_error));
write_bin_log(thd, FALSE, thd->query, thd->query_length);
rw_unlock(&LOCK_grant);

View file

@ -130,7 +130,7 @@ void table_cache_free(void)
DBUG_ENTER("table_cache_free");
if (table_def_inited)
{
close_cached_tables((THD*) 0,0,(TABLE_LIST*) 0);
close_cached_tables(NULL, NULL, FALSE, FALSE, FALSE);
if (!open_cache.records) // Safety first
hash_free(&open_cache);
}
@ -491,9 +491,28 @@ static TABLE_SHARE
int tmp;
DBUG_ENTER("get_table_share_with_create");
if ((share= get_table_share(thd, table_list, key, key_length,
db_flags, error)) ||
thd->net.last_errno != ER_NO_SUCH_TABLE)
share= get_table_share(thd, table_list, key, key_length, db_flags, error);
/*
If share is not NULL, we found an existing share.
If share is NULL, and there is no error, we're inside
pre-locking, which silences 'ER_NO_SUCH_TABLE' errors
with the intention to silently drop non-existing tables
from the pre-locking list. In this case we still need to try
auto-discover before returning a NULL share.
If share is NULL and the error is ER_NO_SUCH_TABLE, this is
the same as above, only that the error was not silenced by
pre-locking. Once again, we need to try to auto-discover
the share.
Finally, if share is still NULL, it's a real error and we need
to abort.
@todo Rework alternative ways to deal with ER_NO_SUCH TABLE.
*/
if (share || thd->is_error() && thd->main_da.sql_errno() != ER_NO_SUCH_TABLE)
DBUG_RETURN(share);
/* Table didn't exist. Check if some engine can provide it */
@ -502,9 +521,13 @@ static TABLE_SHARE
{
/*
No such table in any engine.
Hide "Table doesn't exist" errors if table belong to view
Hide "Table doesn't exist" errors if the table belongs to a view.
The check for thd->is_error() is necessary to not push an
unwanted error in case of pre-locking, which silences
"no such table" errors.
@todo Rework the alternative ways to deal with ER_NO_SUCH TABLE.
*/
if (table_list->belong_to_view)
if (thd->is_error() && table_list->belong_to_view)
{
TABLE_LIST *view= table_list->belong_to_view;
thd->clear_error();
@ -885,16 +908,24 @@ void free_io_cache(TABLE *table)
/*
Close all tables which aren't in use by any thread
THD can be NULL, but then if_wait_for_refresh must be FALSE
and tables must be NULL.
@param thd Thread context
@param tables List of tables to remove from the cache
@param have_lock If LOCK_open is locked
@param wait_for_refresh Wait for a impending flush
@param wait_for_placeholders Wait for tables being reopened so that the GRL
won't proceed while write-locked tables are being reopened by other
threads.
@remark THD can be NULL, but then wait_for_refresh must be FALSE
and tables must be NULL.
*/
bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
TABLE_LIST *tables, bool have_lock)
bool close_cached_tables(THD *thd, TABLE_LIST *tables, bool have_lock,
bool wait_for_refresh, bool wait_for_placeholders)
{
bool result=0;
DBUG_ENTER("close_cached_tables");
DBUG_ASSERT(thd || (!if_wait_for_refresh && !tables));
DBUG_ASSERT(thd || (!wait_for_refresh && !tables));
if (!have_lock)
VOID(pthread_mutex_lock(&LOCK_open));
@ -918,7 +949,7 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
}
DBUG_PRINT("tcache", ("incremented global refresh_version to: %lu",
refresh_version));
if (if_wait_for_refresh)
if (wait_for_refresh)
{
/*
Other threads could wait in a loop in open_and_lock_tables(),
@ -975,13 +1006,13 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
found=1;
}
if (!found)
if_wait_for_refresh=0; // Nothing to wait for
wait_for_refresh=0; // Nothing to wait for
}
#ifndef EMBEDDED_LIBRARY
if (!tables)
kill_delayed_threads();
#endif
if (if_wait_for_refresh)
if (wait_for_refresh)
{
/*
If there is any table that has a lower refresh_version, wait until
@ -1004,6 +1035,9 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
for (uint idx=0 ; idx < open_cache.records ; idx++)
{
TABLE *table=(TABLE*) hash_element(&open_cache,idx);
/* Avoid a self-deadlock. */
if (table->in_use == thd)
continue;
/*
Note that we wait here only for tables which are actually open, and
not for placeholders with TABLE::open_placeholder set. Waiting for
@ -1018,7 +1052,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
are employed by CREATE TABLE as in this case table simply does not
exist yet.
*/
if (table->needs_reopen_or_name_lock() && table->db_stat)
if (table->needs_reopen_or_name_lock() && (table->db_stat ||
(table->open_placeholder && wait_for_placeholders)))
{
found=1;
DBUG_PRINT("signal", ("Waiting for COND_refresh"));
@ -1037,11 +1072,18 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
thd->in_lock_tables=0;
/* Set version for table */
for (TABLE *table=thd->open_tables; table ; table= table->next)
table->s->version= refresh_version;
{
/*
Preserve the version (0) of write locked tables so that a impending
global read lock won't sneak in.
*/
if (table->reginfo.lock_type < TL_WRITE_ALLOW_WRITE)
table->s->version= refresh_version;
}
}
if (!have_lock)
VOID(pthread_mutex_unlock(&LOCK_open));
if (if_wait_for_refresh)
if (wait_for_refresh)
{
pthread_mutex_lock(&thd->mysys_var->mutex);
thd->mysys_var->current_mutex= 0;
@ -1068,10 +1110,10 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh,
DBUG_ASSERT(thd);
bzero(&tmp, sizeof(TABLE_LIST));
if (!have_lock)
VOID(pthread_mutex_lock(&LOCK_open));
for (idx= 0; idx < table_def_cache.records; idx++)
{
TABLE_SHARE *share= (TABLE_SHARE *) hash_element(&table_def_cache, idx);
@ -1100,11 +1142,11 @@ bool close_cached_connection_tables(THD *thd, bool if_wait_for_refresh,
}
if (tables)
result= close_cached_tables(thd, FALSE, tables, TRUE);
result= close_cached_tables(thd, tables, TRUE, FALSE, FALSE);
if (!have_lock)
VOID(pthread_mutex_unlock(&LOCK_open));
if (if_wait_for_refresh)
{
pthread_mutex_lock(&thd->mysys_var->mutex);
@ -2204,7 +2246,7 @@ void wait_for_condition(THD *thd, pthread_mutex_t *mutex, pthread_cond_t *cond)
current thread.
@param thd current thread context
@param tables able list containing one table to open.
@param tables table list containing one table to open.
@return FALSE on success, TRUE otherwise.
*/
@ -3272,8 +3314,8 @@ static bool reattach_merge(THD *thd, TABLE **err_tables_p)
@param thd Thread context
@param get_locks Should we get locks after reopening tables ?
@param in_refresh Are we in FLUSH TABLES ? TODO: It seems that
we can remove this parameter.
@param mark_share_as_old Mark share as old to protect from a impending
global read lock.
@note Since this function can't properly handle prelocking and
create placeholders it should be used in very special
@ -3287,13 +3329,17 @@ static bool reattach_merge(THD *thd, TABLE **err_tables_p)
@return FALSE in case of success, TRUE - otherwise.
*/
bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
bool reopen_tables(THD *thd, bool get_locks, bool mark_share_as_old)
{
TABLE *table,*next,**prev;
TABLE **tables,**tables_ptr; // For locks
TABLE *err_tables= NULL;
bool error=0, not_used;
bool merge_table_found= FALSE;
const uint flags= MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN |
MYSQL_LOCK_IGNORE_GLOBAL_READ_LOCK |
MYSQL_LOCK_IGNORE_FLUSH;
DBUG_ENTER("reopen_tables");
if (!thd->open_tables)
@ -3354,7 +3400,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
/* Do not handle locks of MERGE children. */
if (get_locks && !db_stat && !table->parent)
*tables_ptr++= table; // need new lock on this
if (in_refresh)
if (mark_share_as_old)
{
table->s->version=0;
table->open_placeholder= 0;
@ -3387,7 +3433,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
*/
thd->some_tables_deleted=0;
if ((lock= mysql_lock_tables(thd, tables, (uint) (tables_ptr - tables),
MYSQL_LOCK_NOTIFY_IF_NEED_REOPEN, &not_used)))
flags, &not_used)))
{
thd->locked_tables=mysql_lock_merge(thd->locked_tables,lock);
}

View file

@ -40,13 +40,6 @@ void mysql_client_binlog_statement(THD* thd)
if (check_global_access(thd, SUPER_ACL))
DBUG_VOID_RETURN;
/*
Temporarily turn off send_ok, since different events handle this
differently
*/
my_bool nsok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE;
size_t coded_len= thd->lex->comment.length + 1;
size_t decoded_len= base64_needed_decoded_length(coded_len);
DBUG_ASSERT(coded_len > 0);
@ -193,20 +186,11 @@ void mysql_client_binlog_statement(THD* thd)
}
}
/*
Restore setting of no_send_ok
*/
thd->net.no_send_ok= nsok;
DBUG_PRINT("info",("binlog base64 execution finished successfully"));
send_ok(thd);
end:
/*
Restore setting of no_send_ok
*/
thd->net.no_send_ok= nsok;
delete desc;
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
DBUG_VOID_RETURN;

View file

@ -1403,6 +1403,7 @@ def_week_frmt: %lu",
thd->limit_found_rows = query->found_rows();
thd->status_var.last_query_cost= 0.0;
thd->main_da.disable_status();
BLOCK_UNLOCK_RD(query_block);
DBUG_RETURN(1); // Result sent to client

View file

@ -351,6 +351,124 @@ char *thd_security_context(THD *thd, char *buffer, unsigned int length,
return thd->strmake(str.ptr(), str.length());
}
/**
Clear this diagnostics area.
Normally called at the end of a statement.
*/
void
Diagnostics_area::reset_diagnostics_area()
{
#ifdef DBUG_OFF
can_overwrite_status= FALSE;
/** Don't take chances in production */
m_message[0]= '\0';
m_sql_errno= 0;
m_server_status= 0;
m_affected_rows= 0;
m_last_insert_id= 0;
m_total_warn_count= 0;
#endif
is_sent= FALSE;
/** Tiny reset in debug mode to see garbage right away */
m_status= DA_EMPTY;
}
/**
Set OK status -- ends commands that do not return a
result set, e.g. INSERT/UPDATE/DELETE.
*/
void
Diagnostics_area::set_ok_status(THD *thd, ha_rows affected_rows_arg,
ulonglong last_insert_id_arg,
const char *message_arg)
{
DBUG_ASSERT(! is_set());
#ifdef DBUG_OFF
/* In production, refuse to overwrite an error with an OK packet. */
if (is_error())
return;
#endif
/** Only allowed to report success if has not yet reported an error */
m_server_status= thd->server_status;
m_total_warn_count= thd->total_warn_count;
m_affected_rows= affected_rows_arg;
m_last_insert_id= last_insert_id_arg;
if (message_arg)
strmake(m_message, message_arg, sizeof(m_message));
else
m_message[0]= '\0';
m_status= DA_OK;
}
/**
Set EOF status.
*/
void
Diagnostics_area::set_eof_status(THD *thd)
{
/** Only allowed to report eof if has not yet reported an error */
DBUG_ASSERT(! is_set());
#ifdef DBUG_OFF
/* In production, refuse to overwrite an error with an EOF packet. */
if (is_error())
return;
#endif
m_server_status= thd->server_status;
/*
If inside a stored procedure, do not return the total
number of warnings, since they are not available to the client
anyway.
*/
m_total_warn_count= thd->spcont ? 0 : thd->total_warn_count;
m_status= DA_EOF;
}
/**
Set ERROR status.
*/
void
Diagnostics_area::set_error_status(THD *thd, uint sql_errno_arg,
const char *message_arg)
{
/*
Only allowed to report error if has not yet reported a success
The only exception is when we flush the message to the client,
an error can happen during the flush.
*/
DBUG_ASSERT(! is_set() || can_overwrite_status);
m_sql_errno= sql_errno_arg;
strmake(m_message, message_arg, sizeof(m_message));
m_status= DA_ERROR;
}
/**
Mark the diagnostics area as 'DISABLED'.
This is used in rare cases when the COM_ command at hand sends a response
in a custom format. One example is the query cache, another is
COM_STMT_PREPARE.
*/
void
Diagnostics_area::disable_status()
{
DBUG_ASSERT(! is_set());
m_status= DA_DISABLED;
}
THD::THD()
@ -431,7 +549,6 @@ THD::THD()
net.vio=0;
#endif
client_capabilities= 0; // minimalistic client
net.last_error[0]=0; // If error on boot
#ifdef HAVE_QUERY_CACHE
query_cache_init_query(&net); // If error on boot
#endif
@ -1324,12 +1441,12 @@ void select_send::abort()
{
DBUG_ENTER("select_send::abort");
if (is_result_set_started && thd->spcont &&
thd->spcont->find_handler(thd, thd->net.last_errno,
thd->spcont->find_handler(thd, thd->main_da.sql_errno(),
MYSQL_ERROR::WARN_LEVEL_ERROR))
{
/*
We're executing a stored procedure, have an open result
set, an SQL exception conditiona and a handler for it.
set, an SQL exception condition and a handler for it.
In this situation we must abort the current statement,
silence the error and start executing the continue/exit
handler.
@ -1337,9 +1454,7 @@ void select_send::abort()
otherwise the client will hang due to the violation of the
client/server protocol.
*/
thd->net.report_error= 0;
send_eof();
thd->net.report_error= 1; // Abort SP
thd->protocol->end_partial_result_set(thd);
}
DBUG_VOID_RETURN;
}
@ -1391,12 +1506,14 @@ bool select_send::send_data(List<Item> &items)
}
}
thd->sent_row_count++;
if (!thd->vio_ok())
DBUG_RETURN(0);
if (! thd->is_error())
if (thd->is_error())
{
protocol->remove_last_row();
DBUG_RETURN(1);
}
if (thd->vio_ok())
DBUG_RETURN(protocol->write());
protocol->remove_last_row();
DBUG_RETURN(1);
DBUG_RETURN(0);
}
bool select_send::send_eof()
@ -1414,14 +1531,9 @@ bool select_send::send_eof()
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
if (! thd->is_error())
{
::send_eof(thd);
is_result_set_started= 0;
return 0;
}
else
return 1;
::send_eof(thd);
is_result_set_started= 0;
return FALSE;
}
@ -2704,7 +2816,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
{
backup->options= options;
backup->in_sub_stmt= in_sub_stmt;
backup->no_send_ok= net.no_send_ok;
backup->enable_slow_log= enable_slow_log;
backup->limit_found_rows= limit_found_rows;
backup->examined_row_count= examined_row_count;
@ -2735,9 +2846,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
cuted_fields= 0;
transaction.savepoints= 0;
first_successful_insert_id_in_cur_stmt= 0;
/* Surpress OK packets in case if we will execute statements */
net.no_send_ok= TRUE;
}
@ -2760,7 +2868,6 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
transaction.savepoints= backup->savepoints;
options= backup->options;
in_sub_stmt= backup->in_sub_stmt;
net.no_send_ok= backup->no_send_ok;
enable_slow_log= backup->enable_slow_log;
first_successful_insert_id_in_prev_stmt=
backup->first_successful_insert_id_in_prev_stmt;

View file

@ -913,7 +913,6 @@ public:
uint in_sub_stmt;
bool enable_slow_log;
bool last_insert_id_used;
my_bool no_send_ok;
SAVEPOINT *savepoints;
};
@ -975,6 +974,123 @@ public:
};
/**
Stores status of the currently executed statement.
Cleared at the beginning of the statement, and then
can hold either OK, ERROR, or EOF status.
Can not be assigned twice per statement.
*/
class Diagnostics_area
{
public:
enum enum_diagnostics_status
{
/** The area is cleared at start of a statement. */
DA_EMPTY= 0,
/** Set whenever one calls send_ok(). */
DA_OK,
/** Set whenever one calls send_eof(). */
DA_EOF,
/** Set whenever one calls my_error() or my_message(). */
DA_ERROR,
/** Set in case of a custom response, such as one from COM_STMT_PREPARE. */
DA_DISABLED
};
/** True if status information is sent to the client. */
bool is_sent;
/** Set to make set_error_status after set_{ok,eof}_status possible. */
bool can_overwrite_status;
void set_ok_status(THD *thd, ha_rows affected_rows_arg,
ulonglong last_insert_id_arg,
const char *message);
void set_eof_status(THD *thd);
void set_error_status(THD *thd, uint sql_errno_arg, const char *message_arg);
void disable_status();
void reset_diagnostics_area();
bool is_set() const { return m_status != DA_EMPTY; }
bool is_error() const { return m_status == DA_ERROR; }
bool is_eof() const { return m_status == DA_EOF; }
bool is_ok() const { return m_status == DA_OK; }
bool is_disabled() const { return m_status == DA_DISABLED; }
enum_diagnostics_status status() const { return m_status; }
const char *message() const
{ DBUG_ASSERT(m_status == DA_ERROR || m_status == DA_OK); return m_message; }
uint sql_errno() const
{ DBUG_ASSERT(m_status == DA_ERROR); return m_sql_errno; }
uint server_status() const
{
DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
return m_server_status;
}
ha_rows affected_rows() const
{ DBUG_ASSERT(m_status == DA_OK); return m_affected_rows; }
ulonglong last_insert_id() const
{ DBUG_ASSERT(m_status == DA_OK); return m_last_insert_id; }
uint total_warn_count() const
{
DBUG_ASSERT(m_status == DA_OK || m_status == DA_EOF);
return m_total_warn_count;
}
Diagnostics_area() { reset_diagnostics_area(); }
private:
/** Message buffer. Can be used by OK or ERROR status. */
char m_message[MYSQL_ERRMSG_SIZE];
/**
SQL error number. One of ER_ codes from share/errmsg.txt.
Set by set_error_status.
*/
uint m_sql_errno;
/**
Copied from thd->server_status when the diagnostics area is assigned.
We need this member as some places in the code use the following pattern:
thd->server_status|= ...
send_eof(thd);
thd->server_status&= ~...
Assigned by OK, EOF or ERROR.
*/
uint m_server_status;
/**
The number of rows affected by the last statement. This is
semantically close to thd->row_count_func, but has a different
life cycle. thd->row_count_func stores the value returned by
function ROW_COUNT() and is cleared only by statements that
update its value, such as INSERT, UPDATE, DELETE and few others.
This member is cleared at the beginning of the next statement.
We could possibly merge the two, but life cycle of thd->row_count_func
can not be changed.
*/
ha_rows m_affected_rows;
/**
Similarly to the previous member, this is a replacement of
thd->first_successful_insert_id_in_prev_stmt, which is used
to implement LAST_INSERT_ID().
*/
ulonglong m_last_insert_id;
/** The total number of warnings. */
uint m_total_warn_count;
enum_diagnostics_status m_status;
/**
@todo: the following THD members belong here:
- warn_list, warn_count,
*/
};
/**
@class THD
For each client connection we create a separate thread with THD serving as
@ -1398,6 +1514,7 @@ public:
List <MYSQL_ERROR> warn_list;
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
uint total_warn_count;
Diagnostics_area main_da;
/*
Id of current query. Statement can be reused to execute several queries
query_id is global in context of the whole MySQL server.
@ -1712,12 +1829,18 @@ public:
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
int send_explain_fields(select_result *result);
#ifndef EMBEDDED_LIBRARY
/**
Clear the current error, if any.
We do not clear is_fatal_error or is_fatal_sub_stmt_error since we
assume this is never called if the fatal error is set.
@todo: To silence an error, one should use Internal_error_handler
mechanism. In future this function will be removed.
*/
inline void clear_error()
{
DBUG_ENTER("clear_error");
net.last_error[0]= 0;
net.last_errno= 0;
net.report_error= 0;
if (main_da.is_error())
main_da.reset_diagnostics_area();
is_slave_error= 0;
DBUG_VOID_RETURN;
}
@ -1726,10 +1849,14 @@ public:
void clear_error();
inline bool vio_ok() const { return true; }
#endif
/**
Mark the current error as fatal. Warning: this does not
set any error, it sets a property of the error, so must be
followed or prefixed with my_error().
*/
inline void fatal_error()
{
is_fatal_error= 1;
net.report_error= 1;
DBUG_PRINT("error",("Fatal error set"));
}
/**
@ -1745,7 +1872,7 @@ public:
To raise this flag, use my_error().
*/
inline bool is_error() const { return net.report_error; }
inline bool is_error() const { return main_da.is_error(); }
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
@ -1969,6 +2096,24 @@ private:
};
/** A short cut for thd->main_da.set_ok_status(). */
inline void
send_ok(THD *thd, ha_rows affected_rows= 0, ulonglong id= 0,
const char *message= NULL)
{
thd->main_da.set_ok_status(thd, affected_rows, id, message);
}
/** A short cut for thd->main_da.set_eof_status(). */
inline void
send_eof(THD *thd)
{
thd->main_da.set_eof_status(thd);
}
#define tmp_disable_binlog(A) \
{ulonglong tmp_disable_binlog__save_options= (A)->options; \
(A)->options&= ~OPTION_BIN_LOG
@ -2506,6 +2651,7 @@ public:
void send_error(uint errcode,const char *err);
int do_deletes();
bool send_eof();
virtual void abort();
};
@ -2546,8 +2692,9 @@ public:
bool send_data(List<Item> &items);
bool initialize_tables (JOIN *join);
void send_error(uint errcode,const char *err);
int do_updates (bool from_send_error);
int do_updates();
bool send_eof();
virtual void abort();
};
class my_var : public Sql_alloc {

View file

@ -948,19 +948,20 @@ bool setup_connection_thread_globals(THD *thd)
bool login_connection(THD *thd)
{
NET *net= &thd->net;
int error;
DBUG_ENTER("login_connection");
DBUG_PRINT("info", ("login_connection called by thread %lu",
thd->thread_id));
net->no_send_error= 0;
/* Use "connect_timeout" value during connection phase */
my_net_set_read_timeout(net, connect_timeout);
my_net_set_write_timeout(net, connect_timeout);
if (check_connection(thd))
error= check_connection(thd);
net_end_statement(thd);
if (error)
{ // Wrong permissions
net_send_error(thd);
#ifdef __NT__
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
my_sleep(1000); /* must wait after eof() */
@ -989,13 +990,12 @@ void end_connection(THD *thd)
if (thd->user_connect)
decrease_user_connections(thd->user_connect);
if (thd->killed ||
net->error && net->vio != 0 && thd->is_error())
if (thd->killed || net->error && net->vio != 0)
{
statistic_increment(aborted_threads,&LOCK_status);
}
if (net->error && net->vio != 0 && thd->is_error())
if (net->error && net->vio != 0)
{
if (!thd->killed && thd->variables.log_warnings > 1)
{
@ -1005,11 +1005,9 @@ void end_connection(THD *thd)
thd->thread_id,(thd->db ? thd->db : "unconnected"),
sctx->user ? sctx->user : "unauthenticated",
sctx->host_or_ip,
(net->last_errno ? ER(net->last_errno) :
(thd->main_da.is_error() ? thd->main_da.message() :
ER(ER_UNKNOWN_ERROR)));
}
net_send_error(thd, net->last_errno, NullS);
}
}
@ -1045,24 +1043,14 @@ static void prepare_new_connection_state(THD* thd)
if (sys_init_connect.value_length && !(sctx->master_access & SUPER_ACL))
{
execute_init_command(thd, &sys_init_connect, &LOCK_sys_init_connect);
/*
execute_init_command calls net_send_error.
If there was an error during execution of the init statements,
the error at this moment is present in thd->net.last_error and also
thd->is_slave_error and thd->net.report_error are set.
net_send_error sends the contents of thd->net.last_error and
clears thd->net.report_error. It doesn't, however, clean
thd->is_slave_error or thd->net.last_error. Here we make use of this
fact.
*/
if (thd->is_slave_error)
if (thd->is_error())
{
thd->killed= THD::KILL_CONNECTION;
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
thd->thread_id,(thd->db ? thd->db : "unconnected"),
sctx->user ? sctx->user : "unauthenticated",
sctx->host_or_ip, "init_connect command failed");
sql_print_warning("%s", thd->net.last_error);
sql_print_warning("%s", thd->main_da.message());
}
thd->proc_info=0;
thd->set_time();
@ -1129,7 +1117,6 @@ pthread_handler_t handle_one_connection(void *arg)
while (!net->error && net->vio != 0 &&
!(thd->killed == THD::KILL_CONNECTION))
{
net->no_send_error= 0;
if (do_command(thd))
break;
}

View file

@ -921,6 +921,8 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
{
ha_drop_database(path);
query_cache_invalidate1(db);
(void) sp_drop_db_routines(thd, db); /* @todo Do not ignore errors */
Events::drop_schema_events(thd, db);
error = 0;
}
}
@ -956,6 +958,7 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
/* These DDL methods and logging protected with LOCK_mysql_create_db */
mysql_bin_log.write(&qinfo);
}
thd->clear_error();
thd->server_status|= SERVER_STATUS_DB_DROPPED;
send_ok(thd, (ulong) deleted);
thd->server_status&= ~SERVER_STATUS_DB_DROPPED;
@ -999,8 +1002,6 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
}
exit:
(void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now */
Events::drop_schema_events(thd, db);
/*
If this database was the client's selected database, we silently
change the client's selected database to nothing (to have an empty

View file

@ -728,6 +728,14 @@ void multi_delete::send_error(uint errcode,const char *err)
/* First send error what ever it is ... */
my_message(errcode, err, MYF(0));
DBUG_VOID_RETURN;
}
void multi_delete::abort()
{
DBUG_ENTER("multi_delete::abort");
/* the error was handled or nothing deleted and no side effects return */
if (error_handled ||
!thd->transaction.stmt.modified_non_trans_table && !deleted)

View file

@ -147,8 +147,9 @@ exit:
/* Hide "Unknown column" or "Unknown function" error */
if (orig_table_list->view)
{
if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
thd->net.last_errno == ER_SP_DOES_NOT_EXIST)
if (thd->is_error() &&
(thd->main_da.sql_errno() == ER_BAD_FIELD_ERROR ||
thd->main_da.sql_errno() == ER_SP_DOES_NOT_EXIST))
{
thd->clear_error();
my_error(ER_VIEW_INVALID, MYF(0), orig_table_list->db,

View file

@ -1916,7 +1916,7 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list)
main thread. Use of my_message will enable stored
procedures continue handlers.
*/
my_message(di->thd.net.last_errno, di->thd.net.last_error,
my_message(di->thd.main_da.sql_errno(), di->thd.main_da.message(),
MYF(0));
}
di->unlock();
@ -1993,7 +1993,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
goto error;
if (dead)
{
my_message(thd.net.last_errno, thd.net.last_error, MYF(0));
my_message(thd.main_da.sql_errno(), thd.main_da.message(), MYF(0));
goto error;
}
}
@ -2252,7 +2252,9 @@ pthread_handler_t handle_delayed_insert(void *arg)
#if !defined( __WIN__) /* Win32 calls this in pthread_create */
if (my_thread_init())
{
strmov(thd->net.last_error,ER(thd->net.last_errno=ER_OUT_OF_RESOURCES));
/* Can't use my_error since store_globals has not yet been called */
thd->main_da.set_error_status(thd, ER_OUT_OF_RESOURCES,
ER(ER_OUT_OF_RESOURCES));
goto end;
}
#endif
@ -2261,8 +2263,10 @@ pthread_handler_t handle_delayed_insert(void *arg)
thd->thread_stack= (char*) &thd;
if (init_thr_lock() || thd->store_globals())
{
/* Can't use my_error since store_globals has perhaps failed */
thd->main_da.set_error_status(thd, ER_OUT_OF_RESOURCES,
ER(ER_OUT_OF_RESOURCES));
thd->fatal_error();
strmov(thd->net.last_error,ER(thd->net.last_errno=ER_OUT_OF_RESOURCES));
goto err;
}
@ -2665,7 +2669,7 @@ bool Delayed_insert::handle_inserts(void)
{
/* This should never happen */
table->file->print_error(error,MYF(0));
sql_print_error("%s",thd.net.last_error);
sql_print_error("%s", thd.main_da.message());
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed in loop"));
goto err;
}
@ -2706,7 +2710,7 @@ bool Delayed_insert::handle_inserts(void)
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{ // This shouldn't happen
table->file->print_error(error,MYF(0));
sql_print_error("%s",thd.net.last_error);
sql_print_error("%s", thd.main_da.message());
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop"));
goto err;
}

View file

@ -328,7 +328,6 @@ void execute_init_command(THD *thd, sys_var_str *init_command_var,
*/
save_vio= thd->net.vio;
thd->net.vio= 0;
thd->net.no_send_error= 0;
dispatch_command(COM_QUERY, thd,
init_command_var->value,
init_command_var->value_length);
@ -397,8 +396,8 @@ pthread_handler_t handle_bootstrap(void *arg)
/* purecov: begin tested */
if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
{
net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS);
thd->fatal_error();
net_end_statement(thd);
bootstrap_error= 1;
break;
}
buff= (char*) thd->net.buff;
@ -406,7 +405,7 @@ pthread_handler_t handle_bootstrap(void *arg)
length+= (ulong) strlen(buff + length);
/* purecov: end */
}
if (thd->is_fatal_error)
if (bootstrap_error)
break; /* purecov: inspected */
while (length && (my_isspace(thd->charset(), buff[length-1]) ||
@ -433,16 +432,11 @@ pthread_handler_t handle_bootstrap(void *arg)
mysql_parse(thd, thd->query, length, & found_semicolon);
close_thread_tables(thd); // Free tables
if (thd->is_fatal_error)
break;
bootstrap_error= thd->is_error();
net_end_statement(thd);
if (thd->is_error())
{
/* The query failed, send error to log and abort bootstrap */
net_send_error(thd);
thd->fatal_error();
if (bootstrap_error)
break;
}
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
#ifdef USING_TRANSACTIONS
@ -451,9 +445,6 @@ pthread_handler_t handle_bootstrap(void *arg)
}
end:
/* Remember the exit code of bootstrap */
bootstrap_error= thd->is_fatal_error;
net_end(&thd->net);
thd->cleanup();
delete thd;
@ -712,7 +703,12 @@ bool do_command(THD *thd)
*/
my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
/*
XXX: this code is here only to clear possible errors of init_connect.
Consider moving to init_connect() instead.
*/
thd->clear_error(); // Clear error message
thd->main_da.reset_diagnostics_area();
net_new_transaction(net);
if ((packet_length=my_net_read(net)) == packet_error)
@ -723,10 +719,13 @@ bool do_command(THD *thd)
/* Check if we can continue without closing the connection */
/* The error must be set. */
DBUG_ASSERT(thd->is_error());
net_end_statement(thd);
if (net->error != 3)
DBUG_RETURN(TRUE); // We have to close it.
net_send_error(thd, net->last_errno, NullS);
net->error= 0;
DBUG_RETURN(FALSE);
}
@ -767,6 +766,74 @@ bool do_command(THD *thd)
#endif /* EMBEDDED_LIBRARY */
/**
@brief Determine if an attempt to update a non-temporary table while the
read-only option was enabled has been made.
This is a helper function to mysql_execute_command.
@note SQLCOM_MULTI_UPDATE is an exception and delt with elsewhere.
@see mysql_execute_command
@returns Status code
@retval TRUE The statement should be denied.
@retval FALSE The statement isn't updating any relevant tables.
*/
static my_bool deny_updates_if_read_only_option(THD *thd,
TABLE_LIST *all_tables)
{
DBUG_ENTER("deny_updates_if_read_only_option");
if (!opt_readonly)
DBUG_RETURN(FALSE);
LEX *lex= thd->lex;
const my_bool user_is_super=
((ulong)(thd->security_ctx->master_access & SUPER_ACL) ==
(ulong)SUPER_ACL);
if (user_is_super)
DBUG_RETURN(FALSE);
if (!(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA))
DBUG_RETURN(FALSE);
/* Multi update is an exception and is dealt with later. */
if (lex->sql_command == SQLCOM_UPDATE_MULTI)
DBUG_RETURN(FALSE);
const my_bool create_temp_tables=
(lex->sql_command == SQLCOM_CREATE_TABLE) &&
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE);
const my_bool drop_temp_tables=
(lex->sql_command == SQLCOM_DROP_TABLE) &&
lex->drop_temporary;
const my_bool update_real_tables=
some_non_temp_table_to_be_updated(thd, all_tables) &&
!(create_temp_tables || drop_temp_tables);
const my_bool create_or_drop_databases=
(lex->sql_command == SQLCOM_CREATE_DB) ||
(lex->sql_command == SQLCOM_DROP_DB);
if (update_real_tables || create_or_drop_databases)
{
/*
An attempt was made to modify one or more non-temporary tables.
*/
DBUG_RETURN(TRUE);
}
/* Assuming that only temporary tables are modified. */
DBUG_RETURN(FALSE);
}
/*
Perform one connection-level (COM_XXXX) command.
@ -860,7 +927,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
db.length= db_len;
tbl_name= strmake(db.str, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len);
mysql_table_dump(thd, &db, tbl_name);
if (mysql_table_dump(thd, &db, tbl_name) == 0)
thd->main_da.disable_status();
break;
}
case COM_CHANGE_USER:
@ -1024,7 +1092,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
while (!thd->killed && found_semicolon && ! thd->is_error())
{
char *next_packet= (char*) found_semicolon;
net->no_send_error= 0;
net_end_statement(thd);
query_cache_end_of_result(thd);
/*
Multiple queries exits, execute them individually
*/
@ -1125,6 +1195,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* We don't calculate statistics for this command */
general_log_print(thd, command, NullS);
net->error=0; // Don't give 'abort' message
thd->main_da.disable_status(); // Don't send anything back
error=TRUE; // End server
break;
@ -1241,16 +1312,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_PRINT("quit",("Got shutdown command for level %u", level));
general_log_print(thd, command, NullS);
send_eof(thd);
#ifdef __WIN__
sleep(1); // must wait after eof()
#endif
/*
The client is next going to send a COM_QUIT request (as part of
mysql_close()). Make the life simpler for the client by sending
the response for the coming COM_QUIT in advance
*/
send_eof(thd);
close_connection(thd, 0, 1);
close_thread_tables(thd); // Free before kill
kill_mysql();
error=TRUE;
@ -1263,13 +1324,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
ulong uptime;
uint length;
ulonglong queries_per_second1000;
#ifndef EMBEDDED_LIBRARY
char buff[250];
uint buff_len= sizeof(buff);
#else
char *buff= thd->net.last_error;
uint buff_len= sizeof(thd->net.last_error);
#endif
general_log_print(thd, command, NullS);
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS]);
@ -1291,6 +1347,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
cached_open_tables(),
(uint) (queries_per_second1000 / 1000),
(uint) (queries_per_second1000 % 1000));
#ifdef EMBEDDED_LIBRARY
/* Store the buffer in permanent memory */
send_ok(thd, 0, 0, buff);
#endif
#ifdef SAFEMALLOC
if (sf_malloc_cur_memory) // Using SAFEMALLOC
{
@ -1303,7 +1363,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
#endif
#ifndef EMBEDDED_LIBRARY
VOID(my_net_write(net, (uchar*) buff, length));
VOID(net_flush(net));
VOID(net_flush(net));
thd->main_da.disable_status();
#endif
break;
}
@ -1383,10 +1444,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
thd->transaction.xid_state.xid.null();
/* report error issued during command execution */
if (thd->killed_errno() && ! thd->is_error())
thd->send_kill_message();
if (thd->is_error())
net_send_error(thd);
if (thd->killed_errno())
{
if (! thd->main_da.is_set())
thd->send_kill_message();
}
if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
{
thd->killed= THD::NOT_KILLED;
thd->mysys_var->abort= 0;
}
net_end_statement(thd);
query_cache_end_of_result(thd);
log_slow_statement(thd);
@ -1756,7 +1826,6 @@ mysql_execute_command(THD *thd)
SELECT_LEX_UNIT *unit= &lex->unit;
/* Saved variable value */
DBUG_ENTER("mysql_execute_command");
thd->net.no_send_error= 0;
#ifdef WITH_PARTITION_STORAGE_ENGINE
thd->work_part_info= 0;
#endif
@ -1869,14 +1938,7 @@ mysql_execute_command(THD *thd)
When option readonly is set deny operations which change non-temporary
tables. Except for the replication thread and the 'super' users.
*/
if (opt_readonly &&
!(thd->security_ctx->master_access & SUPER_ACL) &&
(sql_command_flags[lex->sql_command] & CF_CHANGES_DATA) &&
!((lex->sql_command == SQLCOM_CREATE_TABLE) &&
(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE)) &&
!((lex->sql_command == SQLCOM_DROP_TABLE) && lex->drop_temporary) &&
((lex->sql_command != SQLCOM_UPDATE_MULTI) &&
some_non_temp_table_to_be_updated(thd, all_tables)))
if (deny_updates_if_read_only_option(thd, all_tables))
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
DBUG_RETURN(-1);
@ -2988,13 +3050,9 @@ end_with_restore_list:
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
OPTION_SETUP_TABLES_DONE,
del_result, unit, select_lex);
res|= thd->net.report_error;
if (unlikely(res))
{
/* If we had a another error reported earlier then this will be ignored */
del_result->send_error(ER_UNKNOWN_ERROR, "Execution of the query failed");
res|= thd->is_error();
if (res)
del_result->abort();
}
delete del_result;
}
else
@ -3927,8 +3985,6 @@ create_sp_error:
goto error;
}
my_bool save_no_send_ok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE;
if (sp->m_flags & sp_head::MULTI_RESULTS)
{
if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
@ -3938,7 +3994,6 @@ create_sp_error:
back
*/
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
thd->net.no_send_ok= save_no_send_ok;
goto error;
}
/*
@ -3953,7 +4008,6 @@ create_sp_error:
if (check_routine_access(thd, EXECUTE_ACL,
sp->m_db.str, sp->m_name.str, TRUE, FALSE))
{
thd->net.no_send_ok= save_no_send_ok;
goto error;
}
select_limit= thd->variables.select_limit;
@ -3977,7 +4031,6 @@ create_sp_error:
thd->variables.select_limit= select_limit;
thd->net.no_send_ok= save_no_send_ok;
thd->server_status&= ~bits_to_be_cleared;
if (!res)
@ -4618,7 +4671,10 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_YES, str.ptr());
}
result->send_eof();
if (res)
result->abort();
else
result->send_eof();
delete result;
}
else
@ -5231,6 +5287,7 @@ void mysql_reset_thd_for_next_command(THD *thd)
{
DBUG_ENTER("mysql_reset_thd_for_next_command");
DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
DBUG_ASSERT(! thd->in_sub_stmt);
thd->free_list= 0;
thd->select_number= 1;
/*
@ -5257,18 +5314,18 @@ void mysql_reset_thd_for_next_command(THD *thd)
}
DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx);
thd->thread_specific_used= FALSE;
if (!thd->in_sub_stmt)
if (opt_bin_log)
{
if (opt_bin_log)
{
reset_dynamic(&thd->user_var_events);
thd->user_var_events_alloc= thd->mem_root;
}
thd->clear_error();
thd->total_warn_count=0; // Warnings for this query
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
reset_dynamic(&thd->user_var_events);
thd->user_var_events_alloc= thd->mem_root;
}
thd->clear_error();
thd->main_da.reset_diagnostics_area();
thd->total_warn_count=0; // Warnings for this query
thd->rand_used= 0;
thd->sent_row_count= thd->examined_row_count= 0;
/*
Because we come here only for start of top-statements, binlog format is
constant inside a complex statement (using stored functions) etc.
@ -5506,7 +5563,6 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
/* Actually execute the query */
lex->set_trg_event_type_for_tables();
mysql_execute_command(thd);
query_cache_end_of_result(thd);
}
}
}
@ -6358,8 +6414,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
}
if (thd)
{
(void)acl_reload(thd);
(void)grant_reload(thd);
if (acl_reload(thd))
result= 1;
if (grant_reload(thd))
result= 1;
}
if (tmp_thd)
{
@ -6449,8 +6507,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
tmp_write_to_binlog= 0;
if (lock_global_read_lock(thd))
return 1; // Killed
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1,
tables);
result= close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
FALSE : TRUE, TRUE);
if (make_global_read_lock_block_commit(thd)) // Killed
{
/* Don't leave things in a half-locked state */
@ -6459,7 +6517,8 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
}
}
else
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables);
result= close_cached_tables(thd, tables, FALSE, (options & REFRESH_FAST) ?
FALSE : TRUE, FALSE);
my_dbopt_cleanup();
}
if (options & REFRESH_HOSTS)
@ -6476,7 +6535,6 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
if (reset_master(thd))
{
result=1;
thd->fatal_error(); // Ensure client get error
}
}
#endif

View file

@ -2068,6 +2068,7 @@ char *generate_partition_syntax(partition_info *part_info,
default:
DBUG_ASSERT(0);
/* We really shouldn't get here, no use in continuing from here */
my_error(ER_OUT_OF_RESOURCES, MYF(0));
current_thd->fatal_error();
DBUG_RETURN(NULL);
}

View file

@ -230,6 +230,8 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
NET *net= &stmt->thd->net;
uchar buff[12];
uint tmp;
int error;
THD *thd= stmt->thd;
DBUG_ENTER("send_prep_stmt");
buff[0]= 0; /* OK packet indicator */
@ -244,11 +246,16 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
Send types and names of placeholders to the client
XXX: fix this nasty upcast from List<Item_param> to List<Item>
*/
DBUG_RETURN(my_net_write(net, buff, sizeof(buff)) ||
(stmt->param_count &&
stmt->thd->protocol_text.send_fields((List<Item> *)
&stmt->lex->param_list,
Protocol::SEND_EOF)));
error= my_net_write(net, buff, sizeof(buff));
if (stmt->param_count && ! error)
{
error= thd->protocol_text.send_fields((List<Item> *)
&stmt->lex->param_list,
Protocol::SEND_EOF);
}
/* Flag that a response has already been sent */
thd->main_da.disable_status();
DBUG_RETURN(error);
}
#else
static bool send_prep_stmt(Prepared_statement *stmt,
@ -259,6 +266,7 @@ static bool send_prep_stmt(Prepared_statement *stmt,
thd->client_stmt_id= stmt->id;
thd->client_param_count= stmt->param_count;
thd->clear_error();
thd->main_da.disable_status();
return 0;
}
@ -2526,6 +2534,8 @@ void mysql_stmt_close(THD *thd, char *packet)
DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE));
(void) stmt->deallocate();
thd->main_da.disable_status();
DBUG_VOID_RETURN;
}
@ -2590,6 +2600,8 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
DBUG_ENTER("mysql_stmt_get_longdata");
status_var_increment(thd->status_var.com_stmt_send_long_data);
thd->main_da.disable_status();
#ifndef EMBEDDED_LIBRARY
/* Minimal size of long data packet is 6 bytes */
if (packet_length < MYSQL_LONG_DATA_HEADER)
@ -2664,11 +2676,7 @@ bool Select_fetch_protocol_binary::send_fields(List<Item> &list, uint flags)
bool Select_fetch_protocol_binary::send_eof()
{
Protocol *save_protocol= thd->protocol;
thd->protocol= &protocol;
::send_eof(thd);
thd->protocol= save_protocol;
return FALSE;
}
@ -3097,7 +3105,6 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
thd->query_length) <= 0)
{
error= mysql_execute_command(thd);
query_cache_end_of_result(thd);
}
}

View file

@ -898,7 +898,6 @@ JOIN::optimize()
}
if (res > 1)
{
thd->fatal_error();
error= res;
DBUG_PRINT("error",("Error from opt_sum_query"));
DBUG_RETURN(1);
@ -14518,6 +14517,7 @@ calc_group_buffer(JOIN *join,ORDER *group)
default:
/* This case should never be choosen */
DBUG_ASSERT(0);
my_error(ER_OUT_OF_RESOURCES, MYF(0));
join->thd->fatal_error();
}
}

View file

@ -239,7 +239,7 @@ bool servers_reload(THD *thd)
if (simple_open_n_lock_tables(thd, tables))
{
sql_print_error("Can't open and lock privilege tables: %s",
thd->net.last_error);
thd->main_da.message());
goto end;
}

View file

@ -578,7 +578,8 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
/* Only one table for now, but VIEW can involve several tables */
if (open_normal_and_derived_tables(thd, table_list, 0))
{
if (!table_list->view || thd->net.last_errno != ER_VIEW_INVALID)
if (!table_list->view ||
thd->is_error() && thd->main_da.sql_errno() != ER_VIEW_INVALID)
DBUG_RETURN(TRUE);
/*
@ -786,10 +787,9 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
}
restore_record(table, s->default_values); // Get empty record
table->use_all_columns();
if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS |
Protocol::SEND_EOF))
if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS))
DBUG_VOID_RETURN;
thd->protocol->flush();
send_eof(thd);
DBUG_VOID_RETURN;
}
@ -2919,7 +2919,7 @@ static int fill_schema_table_names(THD *thd, TABLE *table,
default:
DBUG_ASSERT(0);
}
if (thd->net.last_errno == ER_NO_SUCH_TABLE)
if (thd->is_error() && thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
{
thd->clear_error();
return 0;
@ -3267,8 +3267,16 @@ int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
res= open_normal_and_derived_tables(thd, show_table_list,
MYSQL_LOCK_IGNORE_FLUSH);
lex->sql_command= save_sql_command;
if (thd->net.last_errno == ER_NO_SUCH_TABLE)
/*
XXX: show_table_list has a flag i_is_requested,
and when it's set, open_normal_and_derived_tables()
can return an error without setting an error message
in THD, which is a hack. This is why we have to
check for res, then for thd->is_error() only then
for thd->main_da.sql_errno().
*/
if (res && thd->is_error() &&
thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
{
/*
Hide error for not existing table.
@ -3422,7 +3430,7 @@ static int get_schema_tables_record(THD *thd, TABLE_LIST *tables,
/*
there was errors during opening tables
*/
const char *error= thd->net.last_error;
const char *error= thd->main_da.message();
if (tables->view)
table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
else if (tables->schema_table)
@ -3624,7 +3632,7 @@ static int get_schema_column_record(THD *thd, TABLE_LIST *tables,
rather than in SHOW COLUMNS
*/
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error);
thd->main_da.sql_errno(), thd->main_da.message());
thd->clear_error();
res= 0;
}
@ -4098,9 +4106,9 @@ static int get_schema_stat_record(THD *thd, TABLE_LIST *tables,
I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
rather than in SHOW KEYS
*/
if (thd->net.last_errno)
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error);
thd->main_da.sql_errno(), thd->main_da.message());
thd->clear_error();
res= 0;
}
@ -4290,9 +4298,9 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
if (schema_table_store_record(thd, table))
DBUG_RETURN(1);
if (res && thd->net.last_errno)
if (res && thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error);
thd->main_da.sql_errno(), thd->main_da.message());
}
if (res)
thd->clear_error();
@ -4323,9 +4331,9 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
DBUG_ENTER("get_schema_constraints_record");
if (res)
{
if (thd->net.last_errno)
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error);
thd->main_da.sql_errno(), thd->main_da.message());
thd->clear_error();
DBUG_RETURN(0);
}
@ -4428,9 +4436,9 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
*/
if (res)
{
if (thd->net.last_errno)
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error);
thd->main_da.sql_errno(), thd->main_da.message());
thd->clear_error();
DBUG_RETURN(0);
}
@ -4511,9 +4519,9 @@ static int get_schema_key_column_usage_record(THD *thd,
DBUG_ENTER("get_schema_key_column_usage_record");
if (res)
{
if (thd->net.last_errno)
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error);
thd->main_da.sql_errno(), thd->main_da.message());
thd->clear_error();
DBUG_RETURN(0);
}
@ -4706,9 +4714,9 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
if (res)
{
if (thd->net.last_errno)
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error);
thd->main_da.sql_errno(), thd->main_da.message());
thd->clear_error();
DBUG_RETURN(0);
}
@ -4751,6 +4759,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
break;
default:
DBUG_ASSERT(0);
my_error(ER_OUT_OF_RESOURCES, MYF(0));
current_thd->fatal_error();
DBUG_RETURN(1);
}
@ -5243,9 +5252,9 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
if (res)
{
if (thd->net.last_errno)
if (thd->is_error())
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
thd->net.last_errno, thd->net.last_error);
thd->main_da.sql_errno(), thd->main_da.message());
thd->clear_error();
DBUG_RETURN(0);
}

View file

@ -1694,7 +1694,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
!dont_log_query);
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
(if_exists || table_type == NULL))
{
error= 0;
thd->clear_error();
}
if (error == HA_ERR_ROW_IS_REFERENCED)
{
/* the table is referenced by a foreign key constraint */
@ -4233,18 +4236,22 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
(table->table->file->ha_check_for_upgrade(check_opt) ==
HA_ADMIN_NEEDS_ALTER))
{
my_bool save_no_send_ok= thd->net.no_send_ok;
DBUG_PRINT("admin", ("recreating table"));
ha_autocommit_or_rollback(thd, 1);
close_thread_tables(thd);
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
thd->net.no_send_ok= TRUE;
result_code= mysql_recreate_table(thd, table);
thd->net.no_send_ok= save_no_send_ok;
reenable_binlog(thd);
/*
mysql_recreate_table() can push OK or ERROR.
Clear 'OK' status. If there is an error, keep it:
we will store the error message in a result set row
and then clear.
*/
if (thd->main_da.is_ok())
thd->main_da.reset_diagnostics_area();
goto send_result;
}
}
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
@ -4338,7 +4345,6 @@ send_result_message:
case HA_ADMIN_TRY_ALTER:
{
my_bool save_no_send_ok= thd->net.no_send_ok;
/*
This is currently used only by InnoDB. ha_innobase::optimize() answers
"try with alter", so here we close the table, do an ALTER TABLE,
@ -4350,10 +4356,16 @@ send_result_message:
*save_next_global= table->next_global;
table->next_local= table->next_global= 0;
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
thd->net.no_send_ok= TRUE;
result_code= mysql_recreate_table(thd, table);
thd->net.no_send_ok= save_no_send_ok;
reenable_binlog(thd);
/*
mysql_recreate_table() can push OK or ERROR.
Clear 'OK' status. If there is an error, keep it:
we will store the error message in a result set row
and then clear.
*/
if (thd->main_da.is_ok())
thd->main_da.reset_diagnostics_area();
ha_autocommit_or_rollback(thd, 0);
close_thread_tables(thd);
if (!result_code) // recreation went ok
@ -4364,9 +4376,10 @@ send_result_message:
}
if (result_code) // either mysql_recreate_table or analyze failed
{
const char *err_msg;
if ((err_msg= thd->net.last_error))
DBUG_ASSERT(thd->is_error());
if (thd->is_error())
{
const char *err_msg= thd->main_da.message();
if (!thd->vio_ok())
{
sql_print_error(err_msg);
@ -4382,6 +4395,7 @@ send_result_message:
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
}
thd->clear_error();
}
}
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
@ -6765,7 +6779,7 @@ view_err:
if (thd->locked_tables && new_name == table_name && new_db == db)
{
thd->in_lock_tables= 1;
error= reopen_tables(thd, 1, 0);
error= reopen_tables(thd, 1, 1);
thd->in_lock_tables= 0;
if (error)
goto err_with_placeholders;

View file

@ -1696,7 +1696,11 @@ void multi_update::send_error(uint errcode,const char *err)
{
/* First send error what ever it is ... */
my_error(errcode, MYF(0), err);
}
void multi_update::abort()
{
/* the error was handled or nothing deleted and no side effects return */
if (error_handled ||
!thd->transaction.stmt.modified_non_trans_table && !updated)
@ -1725,7 +1729,7 @@ void multi_update::send_error(uint errcode,const char *err)
todo/fixme: do_update() is never called with the arg 1.
should it change the signature to become argless?
*/
VOID(do_updates(0));
VOID(do_updates());
}
}
if (thd->transaction.stmt.modified_non_trans_table)
@ -1756,7 +1760,7 @@ void multi_update::send_error(uint errcode,const char *err)
}
int multi_update::do_updates(bool from_send_error)
int multi_update::do_updates()
{
TABLE_LIST *cur_table;
int local_error= 0;
@ -1903,7 +1907,6 @@ int multi_update::do_updates(bool from_send_error)
DBUG_RETURN(0);
err:
if (!from_send_error)
{
thd->fatal_error();
prepare_record_for_error_message(local_error, table);
@ -1945,7 +1948,7 @@ bool multi_update::send_eof()
Does updates for the last n - 1 tables, returns 0 if ok;
error takes into account killed status gained in do_updates()
*/
int local_error = (table_count) ? do_updates(0) : 0;
int local_error = (table_count) ? do_updates() : 0;
/*
if local_error is not set ON until after do_updates() then
later carried out killing should not affect binlogging.

View file

@ -3281,31 +3281,32 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type)
}
/*
/**
Hide errors which show view underlying table information
SYNOPSIS
TABLE_LIST::hide_view_error()
thd thread handler
@param[in,out] thd thread handler
@pre This method can be called only if there is an error.
*/
void TABLE_LIST::hide_view_error(THD *thd)
{
/* Hide "Unknown column" or "Unknown function" error */
if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
thd->net.last_errno == ER_SP_DOES_NOT_EXIST ||
thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR ||
thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR ||
thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR ||
thd->net.last_errno == ER_TABLE_NOT_LOCKED ||
thd->net.last_errno == ER_NO_SUCH_TABLE)
DBUG_ASSERT(thd->is_error());
if (thd->main_da.sql_errno() == ER_BAD_FIELD_ERROR ||
thd->main_da.sql_errno() == ER_SP_DOES_NOT_EXIST ||
thd->main_da.sql_errno() == ER_PROCACCESS_DENIED_ERROR ||
thd->main_da.sql_errno() == ER_COLUMNACCESS_DENIED_ERROR ||
thd->main_da.sql_errno() == ER_TABLEACCESS_DENIED_ERROR ||
thd->main_da.sql_errno() == ER_TABLE_NOT_LOCKED ||
thd->main_da.sql_errno() == ER_NO_SUCH_TABLE)
{
TABLE_LIST *top= top_table();
thd->clear_error();
thd->clear_error();
my_error(ER_VIEW_INVALID, MYF(0), top->view_db.str, top->view_name.str);
}
else if (thd->net.last_errno == ER_NO_DEFAULT_FOR_FIELD)
else if (thd->main_da.sql_errno() == ER_NO_DEFAULT_FOR_FIELD)
{
TABLE_LIST *top= top_table();
thd->clear_error();

View file

@ -1642,7 +1642,7 @@ my_tz_init(THD *org_thd, const char *default_tzname, my_bool bootstrap)
if (open_system_tables_for_read(thd, tz_tables, &open_tables_state_backup))
{
sql_print_warning("Can't open and lock time zone table: %s "
"trying to live without them", thd->net.last_error);
"trying to live without them", thd->main_da.message());
/* We will try emulate that everything is ok */
return_val= time_zone_tables_exist= 0;
goto end_with_setting_default_tz;

View file

@ -1407,10 +1407,8 @@ int ha_myisam::enable_indexes(uint mode)
might have been set by the first repair. They can still be seen
with SHOW WARNINGS then.
*/
#ifndef EMBEDDED_LIBRARY
if (! error)
thd->clear_error();
#endif /* EMBEDDED_LIBRARY */
}
info(HA_STATUS_CONST);
thd->proc_info=save_proc_info;