mirror of
https://github.com/MariaDB/server.git
synced 2025-02-01 11:31:51 +01:00
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:
commit
a2eb9e01ed
72 changed files with 5593 additions and 629 deletions
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
2329
mysql-test/r/ps_ddl.result
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
1851
mysql-test/t/ps_ddl.test
Normal file
File diff suppressed because it is too large
Load diff
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)))
|
||||
{
|
||||
|
|
61
sql/log.cc
61
sql/log.cc
|
@ -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).
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
228
sql/protocol.cc
228
sql/protocol.cc
|
@ -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:
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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")) ||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
|
@ -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:
|
||||
|
|
60
sql/slave.cc
60
sql/slave.cc
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
102
sql/sql_base.cc
102
sql/sql_base.cc
|
@ -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, ¬_used)))
|
||||
flags, ¬_used)))
|
||||
{
|
||||
thd->locked_tables=mysql_lock_merge(thd->locked_tables,lock);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
155
sql/sql_class.cc
155
sql/sql_class.cc
|
@ -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;
|
||||
|
|
161
sql/sql_class.h
161
sql/sql_class.h
|
@ -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 {
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
210
sql/sql_parse.cc
210
sql/sql_parse.cc
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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.
|
||||
|
|
27
sql/table.cc
27
sql/table.cc
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Add table
Reference in a new issue