Bug#12713 "Error in a stored function called from a SELECT doesn't
cause ROLLBACK of statement", part 1. Review fixes. Do not send OK/EOF packets to the client until we reached the end of the current statement. This is a consolidation, to keep the functionality that is shared by all SQL statements in one place in the server. Currently this functionality includes: - close_thread_tables() - log_slow_statement(). After this patch and the subsequent patch for Bug#12713, it shall also include: - ha_autocommit_or_rollback() - net_end_statement() - query_cache_end_of_result(). In future it may also include: - mysql_reset_thd_for_next_command().
This commit is contained in:
parent
aa5786eb0f
commit
ebb9c5d983
@ -203,14 +203,10 @@ typedef struct st_net {
|
|||||||
unsigned int *return_status;
|
unsigned int *return_status;
|
||||||
unsigned char reading_or_writing;
|
unsigned char reading_or_writing;
|
||||||
char save_char;
|
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 unused; /* Please remove with the next incompatible ABI change */
|
||||||
my_bool compress;
|
my_bool compress;
|
||||||
/*
|
my_bool unused1; /* Please remove with the next incompatible ABI change. */
|
||||||
Set if OK packet is already sent, and we do not need to send error
|
|
||||||
messages
|
|
||||||
*/
|
|
||||||
my_bool no_send_error;
|
|
||||||
/*
|
/*
|
||||||
Pointer to query object in query cache, do not equal NULL (0) for
|
Pointer to query object in query cache, do not equal NULL (0) for
|
||||||
queries in cache that have not stored its results yet
|
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.
|
functions and methods to maintain proper locking.
|
||||||
*/
|
*/
|
||||||
unsigned char *query_cache_query;
|
unsigned char *query_cache_query;
|
||||||
unsigned int last_errno;
|
unsigned int client_last_errno;
|
||||||
unsigned char error;
|
unsigned char error;
|
||||||
my_bool report_error; /* We should report error (we have unreported error) */
|
my_bool unused2; /* Please remove with the next incompatible ABI change. */
|
||||||
my_bool return_errno;
|
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;
|
void *extension;
|
||||||
} NET;
|
} NET;
|
||||||
|
|
||||||
|
@ -537,16 +537,16 @@ struct __attribute__((aligned(__alignof__(void *)), aligned(__alignof__(unsigned
|
|||||||
unsigned int * return_status;
|
unsigned int * return_status;
|
||||||
unsigned char reading_or_writing;
|
unsigned char reading_or_writing;
|
||||||
char save_char;
|
char save_char;
|
||||||
my_bool no_send_ok;
|
my_bool unused0;
|
||||||
my_bool unused;
|
my_bool unused;
|
||||||
my_bool compress;
|
my_bool compress;
|
||||||
my_bool no_send_error;
|
my_bool unused1;
|
||||||
unsigned char * query_cache_query;
|
unsigned char * query_cache_query;
|
||||||
unsigned int last_errno;
|
unsigned int client_last_errno;
|
||||||
unsigned char error;
|
unsigned char error;
|
||||||
my_bool report_error;
|
my_bool unused2;
|
||||||
my_bool return_errno;
|
my_bool return_errno;
|
||||||
char last_error[512];
|
char client_last_error[512];
|
||||||
char sqlstate[(5 + 1)];
|
char sqlstate[(5 + 1)];
|
||||||
void * extension;
|
void * extension;
|
||||||
};
|
};
|
||||||
|
@ -440,11 +440,11 @@ static void expand_error(MYSQL* mysql, int error)
|
|||||||
char tmp[MYSQL_ERRMSG_SIZE];
|
char tmp[MYSQL_ERRMSG_SIZE];
|
||||||
char *p;
|
char *p;
|
||||||
uint err_length;
|
uint err_length;
|
||||||
strmake(tmp, mysql->net.last_error, MYSQL_ERRMSG_SIZE-1);
|
strmake(tmp, mysql->net.client_last_error, MYSQL_ERRMSG_SIZE-1);
|
||||||
p = strmake(mysql->net.last_error, ER(error), MYSQL_ERRMSG_SIZE-1);
|
p = strmake(mysql->net.client_last_error, ER(error), MYSQL_ERRMSG_SIZE-1);
|
||||||
err_length= (uint) (p - mysql->net.last_error);
|
err_length= (uint) (p - mysql->net.client_last_error);
|
||||||
strmake(p, tmp, MYSQL_ERRMSG_SIZE-1 - err_length);
|
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 */
|
VOID(my_net_write(net,(const uchar*) "",0)); /* Server needs one packet */
|
||||||
net_flush(net);
|
net_flush(net);
|
||||||
strmov(net->sqlstate, unknown_sqlstate);
|
strmov(net->sqlstate, unknown_sqlstate);
|
||||||
net->last_errno= (*options->local_infile_error)(li_ptr,
|
net->client_last_errno=
|
||||||
net->last_error,
|
(*options->local_infile_error)(li_ptr,
|
||||||
sizeof(net->last_error)-1);
|
net->client_last_error,
|
||||||
|
sizeof(net->client_last_error)-1);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -899,9 +900,10 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename)
|
|||||||
|
|
||||||
if (readcount < 0)
|
if (readcount < 0)
|
||||||
{
|
{
|
||||||
net->last_errno= (*options->local_infile_error)(li_ptr,
|
net->client_last_errno=
|
||||||
net->last_error,
|
(*options->local_infile_error)(li_ptr,
|
||||||
sizeof(net->last_error)-1);
|
net->client_last_error,
|
||||||
|
sizeof(net->client_last_error)-1);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1395,7 +1397,7 @@ const char *cli_read_statistics(MYSQL *mysql)
|
|||||||
if (!mysql->net.read_pos[0])
|
if (!mysql->net.read_pos[0])
|
||||||
{
|
{
|
||||||
set_mysql_error(mysql, CR_WRONG_HOST_INFO, unknown_sqlstate);
|
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;
|
return (char*) mysql->net.read_pos;
|
||||||
}
|
}
|
||||||
@ -1406,7 +1408,7 @@ mysql_stat(MYSQL *mysql)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_stat");
|
DBUG_ENTER("mysql_stat");
|
||||||
if (simple_command(mysql,COM_STATISTICS,0,0,0))
|
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));
|
DBUG_RETURN((*mysql->methods->read_statistics)(mysql));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1771,7 +1773,7 @@ static my_bool my_realloc_str(NET *net, ulong length)
|
|||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
strmov(net->sqlstate, unknown_sqlstate);
|
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;
|
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)
|
void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("set_stmt_errmsg");
|
DBUG_ENTER("set_stmt_errmsg");
|
||||||
DBUG_PRINT("enter", ("error: %d/%s '%s'", net->last_errno, net->sqlstate,
|
DBUG_PRINT("enter", ("error: %d/%s '%s'",
|
||||||
net->last_error));
|
net->client_last_errno,
|
||||||
|
net->sqlstate,
|
||||||
|
net->client_last_error));
|
||||||
DBUG_ASSERT(stmt != 0);
|
DBUG_ASSERT(stmt != 0);
|
||||||
|
|
||||||
stmt->last_errno= net->last_errno;
|
stmt->last_errno= net->client_last_errno;
|
||||||
if (net->last_error && net->last_error[0])
|
if (net->client_last_error && net->client_last_error[0])
|
||||||
strmov(stmt->last_error, net->last_error);
|
strmov(stmt->last_error, net->client_last_error);
|
||||||
strmov(stmt->sqlstate, net->sqlstate);
|
strmov(stmt->sqlstate, net->sqlstate);
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
@ -160,7 +160,7 @@ MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con,
|
|||||||
msg_len=strlen(msg_buf);
|
msg_len=strlen(msg_buf);
|
||||||
if (my_net_write(&con->net,(uchar*) msg_buf,msg_len) || net_flush(&con->net))
|
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");
|
strmov(con->last_error,"Write error on socket");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
@ -61,8 +61,8 @@ void embedded_get_error(MYSQL *mysql, MYSQL_DATA *data)
|
|||||||
{
|
{
|
||||||
NET *net= &mysql->net;
|
NET *net= &mysql->net;
|
||||||
struct embedded_query_result *ei= data->embedded_info;
|
struct embedded_query_result *ei= data->embedded_info;
|
||||||
net->last_errno= ei->last_errno;
|
net->client_last_errno= ei->last_errno;
|
||||||
strmake(net->last_error, ei->info, sizeof(net->last_error));
|
strmake(net->client_last_error, ei->info, sizeof(net->client_last_error)-1);
|
||||||
memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
|
memcpy(net->sqlstate, ei->sqlstate, sizeof(net->sqlstate));
|
||||||
my_free(data, MYF(0));
|
my_free(data, MYF(0));
|
||||||
}
|
}
|
||||||
@ -110,12 +110,11 @@ emb_advanced_command(MYSQL *mysql, enum enum_server_command command,
|
|||||||
arg_length= header_length;
|
arg_length= header_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
thd->net.no_send_error= 0;
|
|
||||||
result= dispatch_command(command, thd, (char *) arg, arg_length);
|
result= dispatch_command(command, thd, (char *) arg, arg_length);
|
||||||
thd->cur_data= 0;
|
thd->cur_data= 0;
|
||||||
|
|
||||||
if (!skip_check)
|
if (!skip_check)
|
||||||
result= thd->net.last_errno ? -1 : 0;
|
result= thd->is_error() ? -1 : 0;
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -370,7 +369,7 @@ static void emb_free_embedded_thd(MYSQL *mysql)
|
|||||||
static const char * emb_read_statistics(MYSQL *mysql)
|
static const char * emb_read_statistics(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
THD *thd= (THD*)mysql->thd;
|
THD *thd= (THD*)mysql->thd;
|
||||||
return thd->net.last_error;
|
return thd->is_error() ? thd->main_da.message() : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -675,8 +674,10 @@ int check_embedded_connection(MYSQL *mysql, const char *db)
|
|||||||
err:
|
err:
|
||||||
{
|
{
|
||||||
NET *net= &mysql->net;
|
NET *net= &mysql->net;
|
||||||
memcpy(net->last_error, thd->net.last_error, sizeof(net->last_error));
|
strmake(net->client_last_error, thd->main_da.message(), sizeof(net->client_last_error)-1);
|
||||||
memcpy(net->sqlstate, thd->net.sqlstate, sizeof(net->sqlstate));
|
memcpy(net->sqlstate,
|
||||||
|
mysql_errno_to_sqlstate(thd->main_da.sql_errno()),
|
||||||
|
sizeof(net->sqlstate)-1);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@ -699,9 +700,8 @@ void THD::clear_data_list()
|
|||||||
|
|
||||||
void THD::clear_error()
|
void THD::clear_error()
|
||||||
{
|
{
|
||||||
net.last_error[0]= 0;
|
if (main_da.is_error())
|
||||||
net.last_errno= 0;
|
main_da.reset_diagnostics_area();
|
||||||
net.report_error= 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
|
static char *dup_str_aux(MEM_ROOT *root, const char *from, uint length,
|
||||||
@ -764,20 +764,18 @@ MYSQL_DATA *THD::alloc_new_dataset()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
stores server_status and warning_count in the current
|
Stores server_status and warning_count in the current
|
||||||
query result structures
|
query result structures.
|
||||||
|
|
||||||
SYNOPSIS
|
@param thd current thread
|
||||||
write_eof_packet()
|
|
||||||
thd current thread
|
|
||||||
|
|
||||||
NOTES
|
|
||||||
should be called to after we get the recordset-result
|
|
||||||
|
|
||||||
|
@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
|
if (!thd->mysql) // bootstrap file handling
|
||||||
return;
|
return;
|
||||||
@ -788,13 +786,13 @@ static void write_eof_packet(THD *thd)
|
|||||||
*/
|
*/
|
||||||
if (thd->is_fatal_error)
|
if (thd->is_fatal_error)
|
||||||
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
|
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
|
Don't send warn count during SP execution, as the warn_list
|
||||||
is cleared between substatements, and mysqltest gets confused
|
is cleared between substatements, and mysqltest gets confused
|
||||||
*/
|
*/
|
||||||
thd->cur_data->embedded_info->warning_count=
|
thd->cur_data->embedded_info->warning_count=
|
||||||
(thd->spcont ? 0 : min(thd->total_warn_count, 65535));
|
(thd->spcont ? 0 : min(total_warn_count, 65535));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -950,7 +948,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SEND_EOF)
|
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));
|
DBUG_RETURN(prepare_for_send(list));
|
||||||
err:
|
err:
|
||||||
@ -990,17 +988,35 @@ bool Protocol_binary::write()
|
|||||||
return false;
|
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
|
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_DATA *data;
|
||||||
MYSQL *mysql= thd->mysql;
|
MYSQL *mysql= thd->mysql;
|
||||||
|
|
||||||
if (!mysql) // bootstrap file handling
|
if (!mysql) // bootstrap file handling
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
if (thd->net.no_send_ok) // hack for re-parsing queries
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
if (!(data= thd->alloc_new_dataset()))
|
if (!(data= thd->alloc_new_dataset()))
|
||||||
return;
|
return;
|
||||||
data->embedded_info->affected_rows= affected_rows;
|
data->embedded_info->affected_rows= affected_rows;
|
||||||
@ -1009,15 +1025,24 @@ send_ok(THD *thd,ha_rows affected_rows,ulonglong id,const char *message)
|
|||||||
strmake(data->embedded_info->info, message,
|
strmake(data->embedded_info->info, message,
|
||||||
sizeof(data->embedded_info->info)-1);
|
sizeof(data->embedded_info->info)-1);
|
||||||
|
|
||||||
write_eof_packet(thd);
|
write_eof_packet(thd, server_status, total_warn_count);
|
||||||
thd->cur_data= 0;
|
thd->cur_data= 0;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Embedded library implementation of EOF response.
|
||||||
|
|
||||||
|
@sa net_send_ok
|
||||||
|
|
||||||
|
@return This function does not return errors.
|
||||||
|
*/
|
||||||
|
|
||||||
void
|
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;
|
thd->cur_data= 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -209,8 +209,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
|||||||
DBUG_RETURN(mysql);
|
DBUG_RETURN(mysql);
|
||||||
|
|
||||||
error:
|
error:
|
||||||
DBUG_PRINT("error",("message: %u (%s)", mysql->net.last_errno,
|
DBUG_PRINT("error",("message: %u (%s)",
|
||||||
mysql->net.last_error));
|
mysql->net.client_last_errno,
|
||||||
|
mysql->net.client_last_error));
|
||||||
{
|
{
|
||||||
/* Free alloced memory */
|
/* Free alloced memory */
|
||||||
my_bool free_me=mysql->free_me;
|
my_bool free_me=mysql->free_me;
|
||||||
|
@ -403,9 +403,10 @@ ERROR 42S02: Table 'mysql.event' doesn't exist
|
|||||||
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
DROP DATABASE IF EXISTS mysqltest_no_such_database;
|
||||||
Warnings:
|
Warnings:
|
||||||
Note 1008 Can't drop database 'mysqltest_no_such_database'; database doesn't exist
|
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;
|
CREATE DATABASE mysqltest_db2;
|
||||||
DROP 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
|
OK, there is an unnecessary warning about the non-existent table
|
||||||
but it's not easy to fix and no one complained about it.
|
but it's not easy to fix and no one complained about it.
|
||||||
A similar warning is printed if mysql.proc is missing.
|
A similar warning is printed if mysql.proc is missing.
|
||||||
|
@ -1229,9 +1229,7 @@ set names default;
|
|||||||
FLUSH PRIVILEGES without procs_priv table.
|
FLUSH PRIVILEGES without procs_priv table.
|
||||||
RENAME TABLE mysql.procs_priv TO mysql.procs_gone;
|
RENAME TABLE mysql.procs_priv TO mysql.procs_gone;
|
||||||
FLUSH PRIVILEGES;
|
FLUSH PRIVILEGES;
|
||||||
Warnings:
|
ERROR 42S02: Table 'mysql.procs_priv' doesn't exist
|
||||||
Error 1146 Table 'mysql.procs_priv' doesn't exist
|
|
||||||
Error 1548 Cannot load from mysql.mysql.procs_priv. The table is probably corrupted
|
|
||||||
Assigning privileges without procs_priv table.
|
Assigning privileges without procs_priv table.
|
||||||
CREATE DATABASE mysqltest1;
|
CREATE DATABASE mysqltest1;
|
||||||
CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER
|
CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER
|
||||||
|
@ -123,7 +123,7 @@ Replicate_Ignore_Table
|
|||||||
Replicate_Wild_Do_Table
|
Replicate_Wild_Do_Table
|
||||||
Replicate_Wild_Ignore_Table
|
Replicate_Wild_Ignore_Table
|
||||||
Last_Errno 1364
|
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
|
Skip_Counter 0
|
||||||
Exec_Master_Log_Pos #
|
Exec_Master_Log_Pos #
|
||||||
Relay_Log_Space #
|
Relay_Log_Space #
|
||||||
@ -141,7 +141,7 @@ Master_SSL_Verify_Server_Cert No
|
|||||||
Last_IO_Errno 0
|
Last_IO_Errno 0
|
||||||
Last_IO_Error
|
Last_IO_Error
|
||||||
Last_SQL_Errno 1364
|
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;
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
INSERT INTO t9 VALUES (2);
|
INSERT INTO t9 VALUES (2);
|
||||||
|
@ -123,7 +123,7 @@ Replicate_Ignore_Table
|
|||||||
Replicate_Wild_Do_Table
|
Replicate_Wild_Do_Table
|
||||||
Replicate_Wild_Ignore_Table
|
Replicate_Wild_Ignore_Table
|
||||||
Last_Errno 1364
|
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
|
Skip_Counter 0
|
||||||
Exec_Master_Log_Pos #
|
Exec_Master_Log_Pos #
|
||||||
Relay_Log_Space #
|
Relay_Log_Space #
|
||||||
@ -141,7 +141,7 @@ Master_SSL_Verify_Server_Cert No
|
|||||||
Last_IO_Errno 0
|
Last_IO_Errno 0
|
||||||
Last_IO_Error
|
Last_IO_Error
|
||||||
Last_SQL_Errno 1364
|
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;
|
SET GLOBAL SQL_SLAVE_SKIP_COUNTER=2;
|
||||||
START SLAVE;
|
START SLAVE;
|
||||||
INSERT INTO t9 VALUES (2);
|
INSERT INTO t9 VALUES (2);
|
||||||
|
@ -1284,6 +1284,7 @@ set names default;
|
|||||||
#
|
#
|
||||||
--echo FLUSH PRIVILEGES without procs_priv table.
|
--echo FLUSH PRIVILEGES without procs_priv table.
|
||||||
RENAME TABLE mysql.procs_priv TO mysql.procs_gone;
|
RENAME TABLE mysql.procs_priv TO mysql.procs_gone;
|
||||||
|
--error ER_NO_SUCH_TABLE
|
||||||
FLUSH PRIVILEGES;
|
FLUSH PRIVILEGES;
|
||||||
--echo Assigning privileges without procs_priv table.
|
--echo Assigning privileges without procs_priv table.
|
||||||
CREATE DATABASE mysqltest1;
|
CREATE DATABASE mysqltest1;
|
||||||
|
@ -257,7 +257,7 @@ int Mysql_connection::do_command()
|
|||||||
return 1;
|
return 1;
|
||||||
if (thread_registry->is_shutdown())
|
if (thread_registry->is_shutdown())
|
||||||
return 1;
|
return 1;
|
||||||
net_send_error(&net, net.last_errno);
|
net_send_error(&net, net.client_last_errno);
|
||||||
net.error= 0;
|
net.error= 0;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -289,8 +289,8 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
|
|||||||
DBUG_ASSERT(mysql != 0);
|
DBUG_ASSERT(mysql != 0);
|
||||||
|
|
||||||
net= &mysql->net;
|
net= &mysql->net;
|
||||||
net->last_errno= errcode;
|
net->client_last_errno= errcode;
|
||||||
strmov(net->last_error, ER(errcode));
|
strmov(net->client_last_error, ER(errcode));
|
||||||
strmov(net->sqlstate, sqlstate);
|
strmov(net->sqlstate, sqlstate);
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -304,8 +304,8 @@ void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate)
|
|||||||
|
|
||||||
void net_clear_error(NET *net)
|
void net_clear_error(NET *net)
|
||||||
{
|
{
|
||||||
net->last_errno= 0;
|
net->client_last_errno= 0;
|
||||||
net->last_error[0]= '\0';
|
net->client_last_error[0]= '\0';
|
||||||
strmov(net->sqlstate, not_error_sqlstate);
|
strmov(net->sqlstate, not_error_sqlstate);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -331,9 +331,9 @@ static void set_mysql_extended_error(MYSQL *mysql, int errcode,
|
|||||||
DBUG_ASSERT(mysql != 0);
|
DBUG_ASSERT(mysql != 0);
|
||||||
|
|
||||||
net= &mysql->net;
|
net= &mysql->net;
|
||||||
net->last_errno= errcode;
|
net->client_last_errno= errcode;
|
||||||
va_start(args, format);
|
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);
|
format, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
strmov(net->sqlstate, sqlstate);
|
strmov(net->sqlstate, sqlstate);
|
||||||
@ -667,7 +667,7 @@ cli_safe_read(MYSQL *mysql)
|
|||||||
return (packet_error);
|
return (packet_error);
|
||||||
#endif /*MYSQL_SERVER*/
|
#endif /*MYSQL_SERVER*/
|
||||||
end_server(mysql);
|
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);
|
CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
|
||||||
return (packet_error);
|
return (packet_error);
|
||||||
}
|
}
|
||||||
@ -676,7 +676,7 @@ cli_safe_read(MYSQL *mysql)
|
|||||||
if (len > 3)
|
if (len > 3)
|
||||||
{
|
{
|
||||||
char *pos=(char*) net->read_pos+1;
|
char *pos=(char*) net->read_pos+1;
|
||||||
net->last_errno=uint2korr(pos);
|
net->client_last_errno=uint2korr(pos);
|
||||||
pos+=2;
|
pos+=2;
|
||||||
len-=2;
|
len-=2;
|
||||||
if (protocol_41(mysql) && pos[0] == '#')
|
if (protocol_41(mysql) && pos[0] == '#')
|
||||||
@ -684,8 +684,8 @@ cli_safe_read(MYSQL *mysql)
|
|||||||
strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH);
|
strmake(net->sqlstate, pos+1, SQLSTATE_LENGTH);
|
||||||
pos+= SQLSTATE_LENGTH+1;
|
pos+= SQLSTATE_LENGTH+1;
|
||||||
}
|
}
|
||||||
(void) strmake(net->last_error,(char*) pos,
|
(void) strmake(net->client_last_error,(char*) pos,
|
||||||
min((uint) len,(uint) sizeof(net->last_error)-1));
|
min((uint) len,(uint) sizeof(net->client_last_error)-1));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate);
|
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;
|
mysql->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
|
||||||
|
|
||||||
DBUG_PRINT("error",("Got error: %d/%s (%s)",
|
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(packet_error);
|
||||||
}
|
}
|
||||||
return len;
|
return len;
|
||||||
@ -744,7 +746,6 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command,
|
|||||||
}
|
}
|
||||||
|
|
||||||
net_clear_error(net);
|
net_clear_error(net);
|
||||||
net->report_error=0;
|
|
||||||
mysql->info=0;
|
mysql->info=0;
|
||||||
mysql->affected_rows= ~(my_ulonglong) 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",
|
DBUG_PRINT("error",("Can't send command to server. Error: %d",
|
||||||
socket_errno));
|
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);
|
set_mysql_error(mysql, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
|
||||||
goto end;
|
goto end;
|
||||||
@ -836,16 +837,15 @@ static my_bool is_NT(void)
|
|||||||
|
|
||||||
|
|
||||||
#ifdef CHECK_LICENSE
|
#ifdef CHECK_LICENSE
|
||||||
/*
|
/**
|
||||||
Check server side variable '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.
|
we're talking to non-commercial server from commercial client.
|
||||||
SYNOPSIS
|
|
||||||
check_license()
|
@retval 0 success
|
||||||
RETURN VALUE
|
@retval !0 network error or the server is not commercial.
|
||||||
0 success
|
Error code is saved in mysql->net.client_last_errno.
|
||||||
!0 network error or the server is not commercial.
|
|
||||||
Error code is saved in mysql->net.last_errno.
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int check_license(MYSQL *mysql)
|
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 (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,
|
set_mysql_extended_error(mysql, CR_WRONG_LICENSE, unknown_sqlstate,
|
||||||
ER(CR_WRONG_LICENSE), required_license);
|
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
|
two is ever true for server variables now), or column value
|
||||||
mismatch, set wrong license error.
|
mismatch, set wrong license error.
|
||||||
*/
|
*/
|
||||||
if (!net->last_errno &&
|
if (!net->client_last_errno &&
|
||||||
(!row || !row[0] ||
|
(!row || !row[0] ||
|
||||||
strncmp(row[0], required_license, sizeof(required_license))))
|
strncmp(row[0], required_license, sizeof(required_license))))
|
||||||
{
|
{
|
||||||
@ -881,7 +881,7 @@ static int check_license(MYSQL *mysql)
|
|||||||
ER(CR_WRONG_LICENSE), required_license);
|
ER(CR_WRONG_LICENSE), required_license);
|
||||||
}
|
}
|
||||||
mysql_free_result(res);
|
mysql_free_result(res);
|
||||||
return net->last_errno;
|
return net->client_last_errno;
|
||||||
}
|
}
|
||||||
#endif /* CHECK_LICENSE */
|
#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 ((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,
|
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
|
||||||
ER(CR_SERVER_LOST_EXTENDED),
|
ER(CR_SERVER_LOST_EXTENDED),
|
||||||
"reading initial communication packet",
|
"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 ((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,
|
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
|
||||||
ER(CR_SERVER_LOST_EXTENDED),
|
ER(CR_SERVER_LOST_EXTENDED),
|
||||||
"reading authorization packet",
|
"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 */
|
/* Read what server thinks about out new auth message report */
|
||||||
if (cli_safe_read(mysql) == packet_error)
|
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,
|
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
|
||||||
ER(CR_SERVER_LOST_EXTENDED),
|
ER(CR_SERVER_LOST_EXTENDED),
|
||||||
"reading final connect information",
|
"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 (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,
|
set_mysql_extended_error(mysql, CR_SERVER_LOST, unknown_sqlstate,
|
||||||
ER(CR_SERVER_LOST_EXTENDED),
|
ER(CR_SERVER_LOST_EXTENDED),
|
||||||
"Setting intital database",
|
"Setting intital database",
|
||||||
@ -2415,7 +2415,9 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
|
|||||||
error:
|
error:
|
||||||
reset_sigpipe(mysql);
|
reset_sigpipe(mysql);
|
||||||
DBUG_PRINT("error",("message: %u/%s (%s)",
|
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 */
|
/* Free alloced memory */
|
||||||
end_server(mysql);
|
end_server(mysql);
|
||||||
@ -2473,8 +2475,8 @@ my_bool mysql_reconnect(MYSQL *mysql)
|
|||||||
mysql->db, mysql->port, mysql->unix_socket,
|
mysql->db, mysql->port, mysql->unix_socket,
|
||||||
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
|
mysql->client_flag | CLIENT_REMEMBER_OPTIONS))
|
||||||
{
|
{
|
||||||
mysql->net.last_errno= tmp_mysql.net.last_errno;
|
mysql->net.client_last_errno= tmp_mysql.net.client_last_errno;
|
||||||
strmov(mysql->net.last_error, tmp_mysql.net.last_error);
|
strmov(mysql->net.client_last_error, tmp_mysql.net.client_last_error);
|
||||||
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
|
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -2483,8 +2485,8 @@ my_bool mysql_reconnect(MYSQL *mysql)
|
|||||||
DBUG_PRINT("error", ("mysql_set_character_set() failed"));
|
DBUG_PRINT("error", ("mysql_set_character_set() failed"));
|
||||||
bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options));
|
bzero((char*) &tmp_mysql.options,sizeof(tmp_mysql.options));
|
||||||
mysql_close(&tmp_mysql);
|
mysql_close(&tmp_mysql);
|
||||||
mysql->net.last_errno= tmp_mysql.net.last_errno;
|
mysql->net.client_last_errno= tmp_mysql.net.client_last_errno;
|
||||||
strmov(mysql->net.last_error, tmp_mysql.net.last_error);
|
strmov(mysql->net.client_last_error, tmp_mysql.net.client_last_error);
|
||||||
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
|
strmov(mysql->net.sqlstate, tmp_mysql.net.sqlstate);
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -3077,13 +3079,13 @@ unsigned int STDCALL mysql_num_fields(MYSQL_RES *res)
|
|||||||
|
|
||||||
uint STDCALL mysql_errno(MYSQL *mysql)
|
uint STDCALL mysql_errno(MYSQL *mysql)
|
||||||
{
|
{
|
||||||
return mysql->net.last_errno;
|
return mysql->net.client_last_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const char * STDCALL mysql_error(MYSQL *mysql)
|
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);
|
ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
|
||||||
}
|
}
|
||||||
charsets_dir= save_csdir;
|
charsets_dir= save_csdir;
|
||||||
return mysql->net.last_errno;
|
return mysql->net.client_last_errno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -257,6 +257,10 @@ static void run_query(THD *thd, char *buf, char *end,
|
|||||||
thd->options&= ~OPTION_BIN_LOG;
|
thd->options&= ~OPTION_BIN_LOG;
|
||||||
|
|
||||||
DBUG_PRINT("query", ("%s", thd->query));
|
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);
|
mysql_parse(thd, thd->query, thd->query_length, &found_semicolon);
|
||||||
|
|
||||||
if (no_print_error && thd->is_slave_error)
|
if (no_print_error && thd->is_slave_error)
|
||||||
@ -265,14 +269,27 @@ static void run_query(THD *thd, char *buf, char *end,
|
|||||||
Thd_ndb *thd_ndb= get_thd_ndb(thd);
|
Thd_ndb *thd_ndb= get_thd_ndb(thd);
|
||||||
for (i= 0; no_print_error[i]; i++)
|
for (i= 0; no_print_error[i]; i++)
|
||||||
if ((thd_ndb->m_error_code == no_print_error[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;
|
break;
|
||||||
if (!no_print_error[i])
|
if (!no_print_error[i])
|
||||||
sql_print_error("NDB: %s: error %s %d(ndb: %d) %d %d",
|
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,
|
thd_ndb->m_error_code,
|
||||||
(int) thd->is_error(), thd->is_slave_error);
|
(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->options= save_thd_options;
|
||||||
thd->query_length= save_query_length;
|
thd->query_length= save_query_length;
|
||||||
@ -2301,8 +2318,8 @@ static int open_ndb_binlog_index(THD *thd, TABLE_LIST *tables,
|
|||||||
if (open_tables(thd, &tables, &counter, MYSQL_LOCK_IGNORE_FLUSH))
|
if (open_tables(thd, &tables, &counter, MYSQL_LOCK_IGNORE_FLUSH))
|
||||||
{
|
{
|
||||||
sql_print_error("NDB Binlog: Opening ndb_binlog_index: %d, '%s'",
|
sql_print_error("NDB Binlog: Opening ndb_binlog_index: %d, '%s'",
|
||||||
thd->net.last_errno,
|
thd->main_da.sql_errno(),
|
||||||
thd->net.last_error ? thd->net.last_error : "");
|
thd->main_da.message());
|
||||||
thd->proc_info= save_proc_info;
|
thd->proc_info= save_proc_info;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -1753,6 +1753,7 @@ partition_element *ha_partition::find_partition_element(uint part_id)
|
|||||||
return part_elem;
|
return part_elem;
|
||||||
}
|
}
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
current_thd->fatal_error(); // Abort
|
current_thd->fatal_error(); // Abort
|
||||||
return NULL;
|
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;
|
Udf_func_init init= u_d->func_init;
|
||||||
if ((error=(uchar) init(&initid, &f_args, init_msg_buff)))
|
if ((error=(uchar) init(&initid, &f_args, init_msg_buff)))
|
||||||
{
|
{
|
||||||
|
@ -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)
|
if (killed_status_arg == THD::KILLED_NO_VALUE)
|
||||||
killed_status_arg= thd_arg->killed;
|
killed_status_arg= thd_arg->killed;
|
||||||
error_code=
|
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->system_thread & SYSTEM_THREAD_DELAYED_INSERT) ? 0 :
|
||||||
thd_arg->killed_errno());
|
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 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);
|
general_log_write(thd, COM_QUERY, thd->query, thd->query_length);
|
||||||
|
|
||||||
compare_errors:
|
compare_errors:
|
||||||
@ -2341,9 +2342,10 @@ compare_errors:
|
|||||||
If we expected a non-zero error code, and we don't get the same error
|
If we expected a non-zero error code, and we don't get the same error
|
||||||
code, and none of them should be ignored.
|
code, and none of them should be ignored.
|
||||||
*/
|
*/
|
||||||
DBUG_PRINT("info",("expected_error: %d last_errno: %d",
|
actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0;
|
||||||
expected_error, thd->net.last_errno));
|
DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
|
||||||
if ((expected_error != (actual_error= thd->net.last_errno)) &&
|
expected_error, actual_error));
|
||||||
|
if ((expected_error != actual_error) &&
|
||||||
expected_error &&
|
expected_error &&
|
||||||
!ignored_error_code(actual_error) &&
|
!ignored_error_code(actual_error) &&
|
||||||
!ignored_error_code(expected_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'",
|
Default database: '%s'. Query: '%s'",
|
||||||
ER_SAFE(expected_error),
|
ER_SAFE(expected_error),
|
||||||
expected_error,
|
expected_error,
|
||||||
actual_error ? thd->net.last_error: "no error",
|
actual_error ? thd->main_da.message() : "no error",
|
||||||
actual_error,
|
actual_error,
|
||||||
print_slave_db_safe(db), query_arg);
|
print_slave_db_safe(db), query_arg);
|
||||||
thd->is_slave_error= 1;
|
thd->is_slave_error= 1;
|
||||||
@ -2377,7 +2379,7 @@ Default database: '%s'. Query: '%s'",
|
|||||||
{
|
{
|
||||||
rli->report(ERROR_LEVEL, actual_error,
|
rli->report(ERROR_LEVEL, actual_error,
|
||||||
"Error '%s' on query. Default database: '%s'. Query: '%s'",
|
"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"),
|
"unexpected success or fatal error"),
|
||||||
print_slave_db_safe(thd->db), query_arg);
|
print_slave_db_safe(thd->db), query_arg);
|
||||||
thd->is_slave_error= 1;
|
thd->is_slave_error= 1;
|
||||||
@ -3720,8 +3722,11 @@ error:
|
|||||||
/* this err/sql_errno code is copy-paste from net_send_error() */
|
/* this err/sql_errno code is copy-paste from net_send_error() */
|
||||||
const char *err;
|
const char *err;
|
||||||
int sql_errno;
|
int sql_errno;
|
||||||
if ((err=thd->net.last_error)[0])
|
if (thd->is_error())
|
||||||
sql_errno=thd->net.last_errno;
|
{
|
||||||
|
err= thd->main_da.message();
|
||||||
|
sql_errno= thd->main_da.sql_errno();
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
sql_errno=ER_UNKNOWN_ERROR;
|
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
|
Error reporting borrowed from Query_log_event with many excessive
|
||||||
simplifications (we don't honour --slave-skip-errors)
|
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,
|
rli->report(ERROR_LEVEL, actual_error,
|
||||||
"Error '%s' in %s event: when locking tables",
|
"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"),
|
"unexpected success or fatal error"),
|
||||||
get_type_str());
|
get_type_str());
|
||||||
thd->is_fatal_error= 1;
|
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
|
Error reporting borrowed from Query_log_event with many excessive
|
||||||
simplifications (we don't honour --slave-skip-errors)
|
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,
|
rli->report(ERROR_LEVEL, actual_error,
|
||||||
"Error '%s' on reopening tables",
|
"Error '%s' on reopening tables",
|
||||||
(actual_error ? thd->net.last_error :
|
(actual_error ? thd->main_da.message() :
|
||||||
"unexpected success or fatal error"));
|
"unexpected success or fatal error"));
|
||||||
thd->is_slave_error= 1;
|
thd->is_slave_error= 1;
|
||||||
}
|
}
|
||||||
@ -6425,10 +6430,11 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
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",
|
"Error in %s event: row application failed. %s",
|
||||||
get_type_str(),
|
get_type_str(),
|
||||||
thd->net.last_error ? thd->net.last_error : "");
|
thd->is_error() ? thd->main_da.message() : "");
|
||||||
thd->is_slave_error= 1;
|
thd->is_slave_error= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -6475,12 +6481,13 @@ int Rows_log_event::do_apply_event(Relay_log_info const *rli)
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{ /* error has occured during the transaction */
|
{ /* 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 "
|
"Error in %s event: error during transaction execution "
|
||||||
"on table %s.%s. %s",
|
"on table %s.%s. %s",
|
||||||
get_type_str(), table->s->db.str,
|
get_type_str(), table->s->db.str,
|
||||||
table->s->table_name.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
|
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
|
Error reporting borrowed from Query_log_event with many excessive
|
||||||
simplifications (we don't honour --slave-skip-errors)
|
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,
|
rli->report(ERROR_LEVEL, actual_error,
|
||||||
"Error '%s' on opening table `%s`.`%s`",
|
"Error '%s' on opening table `%s`.`%s`",
|
||||||
(actual_error ? thd->net.last_error :
|
(actual_error ? thd->main_da.message() :
|
||||||
"unexpected success or fatal error"),
|
"unexpected success or fatal error"),
|
||||||
table_list->db, table_list->table_name);
|
table_list->db, table_list->table_name);
|
||||||
thd->is_slave_error= 1;
|
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);
|
DBUG_ASSERT(m_table != NULL);
|
||||||
int error= write_row(rli, TRUE /* overwrite */);
|
int error= write_row(rli, TRUE /* overwrite */);
|
||||||
|
|
||||||
if (error && !thd->net.last_errno)
|
if (error && !thd->is_error())
|
||||||
thd->net.last_errno= error;
|
{
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
my_error(ER_UNKNOWN_ERROR, MYF(0));
|
||||||
|
}
|
||||||
|
|
||||||
return error;
|
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
|
Error reporting borrowed from Query_log_event with many excessive
|
||||||
simplifications (we don't honour --slave-skip-errors)
|
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,
|
rli->report(ERROR_LEVEL, actual_error,
|
||||||
"Error '%s' in %s event: when locking tables",
|
"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"),
|
"unexpected success or fatal error"),
|
||||||
ev->get_type_str());
|
ev->get_type_str());
|
||||||
thd->is_fatal_error= 1;
|
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
|
Error reporting borrowed from Query_log_event with many excessive
|
||||||
simplifications (we don't honour --slave-skip-errors)
|
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,
|
rli->report(ERROR_LEVEL, actual_error,
|
||||||
"Error '%s' on reopening tables",
|
"Error '%s' on reopening tables",
|
||||||
(actual_error ? thd->net.last_error :
|
(actual_error ? thd->main_da.message() :
|
||||||
"unexpected success or fatal error"));
|
"unexpected success or fatal error"));
|
||||||
thd->is_slave_error= 1;
|
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;
|
break;
|
||||||
|
|
||||||
default:
|
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",
|
"Error in %s event: row application failed. %s",
|
||||||
ev->get_type_str(),
|
ev->get_type_str(),
|
||||||
thd->net.last_error ? thd->net.last_error : "");
|
thd->is_error() ? thd->main_da.message() : "");
|
||||||
thd->is_slave_error= 1;
|
thd->is_slave_error= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -280,12 +280,12 @@ Old_rows_log_event::do_apply_event(Rows_log_event *ev, const Relay_log_info *rli
|
|||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
{ /* error has occured during the transaction */
|
{ /* 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 "
|
"Error in %s event: error during transaction execution "
|
||||||
"on table %s.%s. %s",
|
"on table %s.%s. %s",
|
||||||
ev->get_type_str(), table->s->db.str,
|
ev->get_type_str(), table->s->db.str,
|
||||||
table->s->table_name.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
|
If one day we honour --skip-slave-errors in row-based replication, and
|
||||||
|
@ -2587,21 +2587,8 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
|
|||||||
MYSQL_ERROR::WARN_LEVEL_ERROR))
|
MYSQL_ERROR::WARN_LEVEL_ERROR))
|
||||||
DBUG_RETURN(0);
|
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
|
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
|
thd->lex->current_select == 0 if lex structure is not inited
|
||||||
(not query command (COM_QUERY))
|
(not query command (COM_QUERY))
|
||||||
@ -2618,14 +2605,39 @@ int my_message_sql(uint error, const char *str, myf MyFlags)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
NET *net= &thd->net;
|
if (! thd->main_da.is_error()) // Return only first message
|
||||||
net->report_error= 1;
|
|
||||||
query_cache_abort(net);
|
|
||||||
if (!net->last_error[0]) // Return only first message
|
|
||||||
{
|
{
|
||||||
strmake(net->last_error, str, sizeof(net->last_error)-1);
|
if (error == 0)
|
||||||
net->last_errno= error ? error : ER_UNKNOWN_ERROR;
|
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)
|
if (!thd || MyFlags & ME_NOREFRESH)
|
||||||
|
@ -123,20 +123,18 @@ my_bool my_net_init(NET *net, Vio* vio)
|
|||||||
MYF(MY_WME))))
|
MYF(MY_WME))))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
net->buff_end=net->buff+net->max_packet;
|
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->error=0; net->return_errno=0; net->return_status=0;
|
||||||
net->pkt_nr=net->compress_pkt_nr=0;
|
net->pkt_nr=net->compress_pkt_nr=0;
|
||||||
net->write_pos=net->read_pos = net->buff;
|
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->compress=0; net->reading_or_writing=0;
|
||||||
net->where_b = net->remain_in_buf=0;
|
net->where_b = net->remain_in_buf=0;
|
||||||
net->last_errno=0;
|
net->client_last_errno=0;
|
||||||
#ifdef USE_QUERY_CACHE
|
#ifdef USE_QUERY_CACHE
|
||||||
query_cache_init_query(net);
|
query_cache_init_query(net);
|
||||||
#else
|
#else
|
||||||
net->query_cache_query= 0;
|
net->query_cache_query= 0;
|
||||||
#endif
|
#endif
|
||||||
net->report_error= 0;
|
|
||||||
|
|
||||||
if (vio != 0) /* If real connection */
|
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",
|
DBUG_PRINT("error", ("Packet too large. Max size: %lu",
|
||||||
net->max_packet_size));
|
net->max_packet_size));
|
||||||
|
/* @todo: 1 and 2 codes are identical. */
|
||||||
net->error= 1;
|
net->error= 1;
|
||||||
net->report_error= 1;
|
net->client_last_errno= ER_NET_PACKET_TOO_LARGE;
|
||||||
net->last_errno= ER_NET_PACKET_TOO_LARGE;
|
#ifdef MYSQL_SERVER
|
||||||
|
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
|
||||||
|
#endif
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-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,
|
NET_HEADER_SIZE + COMP_HEADER_SIZE,
|
||||||
MYF(MY_WME))))
|
MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
|
/* @todo: 1 and 2 codes are identical. */
|
||||||
net->error= 1;
|
net->error= 1;
|
||||||
net->report_error= 1;
|
net->client_last_errno= ER_OUT_OF_RESOURCES;
|
||||||
net->last_errno= ER_OUT_OF_RESOURCES;
|
/* In the server the error is reported by MY_WME flag. */
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
net->buff=net->write_pos=buff;
|
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 +
|
if (!(b= (uchar*) my_malloc(len + NET_HEADER_SIZE +
|
||||||
COMP_HEADER_SIZE, MYF(MY_WME))))
|
COMP_HEADER_SIZE, MYF(MY_WME))))
|
||||||
{
|
{
|
||||||
#ifdef MYSQL_SERVER
|
|
||||||
net->last_errno= ER_OUT_OF_RESOURCES;
|
|
||||||
net->error= 2;
|
net->error= 2;
|
||||||
/* TODO is it needed to set this variable if we have no socket */
|
net->client_last_errno= ER_OUT_OF_RESOURCES;
|
||||||
net->report_error= 1;
|
/* In the server, the error is reported by MY_WME flag. */
|
||||||
#endif
|
|
||||||
net->reading_or_writing= 0;
|
net->reading_or_writing= 0;
|
||||||
DBUG_RETURN(1);
|
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",
|
"%s: my_net_write: fcntl returned error %d, aborting thread\n",
|
||||||
my_progname,vio_errno(net->vio));
|
my_progname,vio_errno(net->vio));
|
||||||
#endif /* EXTRA_DEBUG */
|
#endif /* EXTRA_DEBUG */
|
||||||
#ifdef MYSQL_SERVER
|
|
||||||
net->last_errno= ER_NET_ERROR_ON_WRITE;
|
|
||||||
#endif
|
|
||||||
net->error= 2; /* Close socket */
|
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;
|
goto end;
|
||||||
}
|
}
|
||||||
retry_count=0;
|
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) */
|
#endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */
|
||||||
net->error= 2; /* Close socket */
|
net->error= 2; /* Close socket */
|
||||||
net->report_error= 1;
|
net->client_last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
|
||||||
#ifdef MYSQL_SERVER
|
|
||||||
net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED :
|
|
||||||
ER_NET_ERROR_ON_WRITE);
|
ER_NET_ERROR_ON_WRITE);
|
||||||
|
#ifdef MYSQL_SERVER
|
||||||
|
my_error(net->client_last_errno, MYF(0));
|
||||||
#endif /* MYSQL_SERVER */
|
#endif /* MYSQL_SERVER */
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -849,9 +848,9 @@ my_real_read(NET *net, size_t *complen)
|
|||||||
#endif /* EXTRA_DEBUG */
|
#endif /* EXTRA_DEBUG */
|
||||||
len= packet_error;
|
len= packet_error;
|
||||||
net->error= 2; /* Close socket */
|
net->error= 2; /* Close socket */
|
||||||
net->report_error= 1;
|
net->client_last_errno= ER_NET_FCNTL_ERROR;
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno= ER_NET_FCNTL_ERROR;
|
my_error(ER_NET_FCNTL_ERROR, MYF(0));
|
||||||
#endif
|
#endif
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -881,10 +880,11 @@ my_real_read(NET *net, size_t *complen)
|
|||||||
remain, vio_errno(net->vio), (long) length));
|
remain, vio_errno(net->vio), (long) length));
|
||||||
len= packet_error;
|
len= packet_error;
|
||||||
net->error= 2; /* Close socket */
|
net->error= 2; /* Close socket */
|
||||||
net->report_error= 1;
|
net->client_last_errno= (vio_was_interrupted(net->vio) ?
|
||||||
#ifdef MYSQL_SERVER
|
ER_NET_READ_INTERRUPTED :
|
||||||
net->last_errno= (vio_was_interrupted(net->vio) ? ER_NET_READ_INTERRUPTED :
|
|
||||||
ER_NET_READ_ERROR);
|
ER_NET_READ_ERROR);
|
||||||
|
#ifdef MYSQL_SERVER
|
||||||
|
my_error(net->client_last_errno, MYF(0));
|
||||||
#endif
|
#endif
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -915,9 +915,9 @@ my_real_read(NET *net, size_t *complen)
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
len= packet_error;
|
len= packet_error;
|
||||||
net->report_error= 1;
|
/* Not a NET error on the client. XXX: why? */
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno=ER_NET_PACKETS_OUT_OF_ORDER;
|
my_error(ER_NET_PACKETS_OUT_OF_ORDER, MYF(0));
|
||||||
#endif
|
#endif
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
@ -1101,9 +1101,9 @@ my_net_read(NET *net)
|
|||||||
&complen))
|
&complen))
|
||||||
{
|
{
|
||||||
net->error= 2; /* caller will close socket */
|
net->error= 2; /* caller will close socket */
|
||||||
net->report_error= 1;
|
net->client_last_errno= ER_NET_UNCOMPRESS_ERROR;
|
||||||
#ifdef MYSQL_SERVER
|
#ifdef MYSQL_SERVER
|
||||||
net->last_errno=ER_NET_UNCOMPRESS_ERROR;
|
my_error(ER_NET_UNCOMPRESS_ERROR, MYF(0));
|
||||||
#endif
|
#endif
|
||||||
return packet_error;
|
return packet_error;
|
||||||
}
|
}
|
||||||
|
@ -1271,7 +1271,7 @@ int QUICK_RANGE_SELECT::init_ror_merged_scan(bool reuse_handler)
|
|||||||
the storage engine calls in question happen to never fail with the
|
the storage engine calls in question happen to never fail with the
|
||||||
existing storage engines.
|
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 */
|
/* Caller will free the memory */
|
||||||
goto failure; /* purecov: inspected */
|
goto failure; /* purecov: inspected */
|
||||||
}
|
}
|
||||||
|
@ -170,6 +170,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
|
|||||||
if(error)
|
if(error)
|
||||||
{
|
{
|
||||||
tl->table->file->print_error(error, MYF(0));
|
tl->table->file->print_error(error, MYF(0));
|
||||||
|
tl->table->in_use->fatal_error();
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
count*= tl->table->file->stats.records;
|
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
|
return HA_ERR_KEY_NOT_FOUND; // No rows matching WHERE
|
||||||
/* HA_ERR_LOCK_DEADLOCK or some other error */
|
/* HA_ERR_LOCK_DEADLOCK or some other error */
|
||||||
table->file->print_error(error, MYF(0));
|
table->file->print_error(error, MYF(0));
|
||||||
|
table->in_use->fatal_error();
|
||||||
return(error);
|
return(error);
|
||||||
}
|
}
|
||||||
removed_tables|= table->map;
|
removed_tables|= table->map;
|
||||||
|
227
sql/protocol.cc
227
sql/protocol.cc
@ -23,13 +23,20 @@
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "mysql_priv.h"
|
#include "mysql_priv.h"
|
||||||
#include "sp_rcontext.h"
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
|
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_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
|
#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
|
#endif
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
@ -68,58 +75,23 @@ bool Protocol_binary::net_store_data(const uchar *from, size_t length)
|
|||||||
void net_send_error(THD *thd, uint sql_errno, const char *err)
|
void net_send_error(THD *thd, uint sql_errno, const char *err)
|
||||||
{
|
{
|
||||||
NET *net= &thd->net;
|
NET *net= &thd->net;
|
||||||
bool generate_warning= thd->killed != THD::KILL_CONNECTION;
|
|
||||||
DBUG_ENTER("net_send_error");
|
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(!thd->spcont);
|
||||||
|
DBUG_ASSERT(sql_errno);
|
||||||
|
DBUG_ASSERT(err && err[0]);
|
||||||
|
|
||||||
if (thd->killed == THD::KILL_QUERY || thd->killed == THD::KILL_BAD_DATA)
|
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
|
||||||
{
|
|
||||||
thd->killed= THD::NOT_KILLED;
|
|
||||||
thd->mysys_var->abort= 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (net && net->no_send_error)
|
/*
|
||||||
{
|
It's one case when we can push an error even though there
|
||||||
thd->clear_error();
|
is an OK or EOF already.
|
||||||
thd->is_fatal_error= 0; // Error message is given
|
*/
|
||||||
DBUG_PRINT("info", ("sending error messages prohibited"));
|
thd->main_da.can_overwrite_status= TRUE;
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
net_send_error_packet(thd, sql_errno, err);
|
net_send_error_packet(thd, sql_errno, err);
|
||||||
|
|
||||||
thd->is_fatal_error= 0; // Error message is given
|
thd->main_da.can_overwrite_status= FALSE;
|
||||||
thd->net.report_error= 0;
|
|
||||||
|
|
||||||
/* Abort multi-result sets */
|
/* Abort multi-result sets */
|
||||||
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
|
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
|
||||||
@ -149,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
|
warning_count Stored in 2 bytes; New in 4.1 protocol
|
||||||
message Stored as packed length (1-9 bytes) + message
|
message Stored as packed length (1-9 bytes) + message
|
||||||
Is not stored if no message
|
Is not stored if no message
|
||||||
|
|
||||||
If net->no_send_ok return without sending packet
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
void
|
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;
|
NET *net= &thd->net;
|
||||||
uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
|
uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
|
||||||
DBUG_ENTER("send_ok");
|
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",
|
DBUG_PRINT("info", ("vio present: NO"));
|
||||||
(net->no_send_ok ? "YES" : "NO"),
|
|
||||||
(net->vio ? "YES" : "NO")));
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -178,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",
|
("affected_rows: %lu id: %lu status: %u warning_count: %u",
|
||||||
(ulong) affected_rows,
|
(ulong) affected_rows,
|
||||||
(ulong) id,
|
(ulong) id,
|
||||||
(uint) (thd->server_status & 0xffff),
|
(uint) (server_status & 0xffff),
|
||||||
(uint) thd->total_warn_count));
|
(uint) total_warn_count));
|
||||||
int2store(pos,thd->server_status);
|
int2store(pos, server_status);
|
||||||
pos+=2;
|
pos+=2;
|
||||||
|
|
||||||
/* We can only return up to 65535 warnings in two bytes */
|
/* 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);
|
int2store(pos, tmp);
|
||||||
pos+= 2;
|
pos+= 2;
|
||||||
}
|
}
|
||||||
else if (net->return_status) // For 4.0 protocol
|
else if (net->return_status) // For 4.0 protocol
|
||||||
{
|
{
|
||||||
int2store(pos,thd->server_status);
|
int2store(pos, server_status);
|
||||||
pos+=2;
|
pos+=2;
|
||||||
}
|
}
|
||||||
if (message)
|
thd->main_da.can_overwrite_status= TRUE;
|
||||||
|
|
||||||
|
if (message && message[0])
|
||||||
pos= net_store_data(pos, (uchar*) message, strlen(message));
|
pos= net_store_data(pos, (uchar*) message, strlen(message));
|
||||||
VOID(my_net_write(net, buff, (size_t) (pos-buff)));
|
VOID(my_net_write(net, buff, (size_t) (pos-buff)));
|
||||||
VOID(net_flush(net));
|
VOID(net_flush(net));
|
||||||
/* We can't anymore send an error to the client */
|
|
||||||
thd->net.report_error= 0;
|
thd->main_da.can_overwrite_status= FALSE;
|
||||||
thd->net.no_send_error= 1;
|
|
||||||
DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
|
DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -211,7 +182,7 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
|
|||||||
Send eof (= end of result set) to the client
|
Send eof (= end of result set) to the client
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
send_eof()
|
net_send_eof()
|
||||||
thd Thread handler
|
thd Thread handler
|
||||||
no_flush Set to 1 if there will be more data to the client,
|
no_flush Set to 1 if there will be more data to the client,
|
||||||
like in send_fields().
|
like in send_fields().
|
||||||
@ -230,15 +201,17 @@ static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
void
|
void
|
||||||
send_eof(THD *thd)
|
net_send_eof(THD *thd, uint server_status, uint total_warn_count)
|
||||||
{
|
{
|
||||||
NET *net= &thd->net;
|
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)
|
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));
|
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_PRINT("info", ("EOF sent, so no more error sending allowed"));
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
@ -250,7 +223,9 @@ send_eof(THD *thd)
|
|||||||
write it to the network output buffer.
|
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)
|
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
|
||||||
{
|
{
|
||||||
@ -259,7 +234,7 @@ static void write_eof_packet(THD *thd, NET *net)
|
|||||||
Don't send warn count during SP execution, as the warn_list
|
Don't send warn count during SP execution, as the warn_list
|
||||||
is cleared between substatements, and mysqltest gets confused
|
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;
|
buff[0]= 254;
|
||||||
int2store(buff+1, tmp);
|
int2store(buff+1, tmp);
|
||||||
/*
|
/*
|
||||||
@ -268,8 +243,8 @@ static void write_eof_packet(THD *thd, NET *net)
|
|||||||
other queries (see the if test in dispatch_command / COM_QUERY)
|
other queries (see the if test in dispatch_command / COM_QUERY)
|
||||||
*/
|
*/
|
||||||
if (thd->is_fatal_error)
|
if (thd->is_fatal_error)
|
||||||
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
|
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
|
||||||
int2store(buff+3, thd->server_status);
|
int2store(buff + 3, server_status);
|
||||||
VOID(my_net_write(net, buff, 5));
|
VOID(my_net_write(net, buff, 5));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -360,6 +335,96 @@ static uchar *net_store_length_fast(uchar *packet, uint length)
|
|||||||
return packet+2;
|
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
|
Functions used by the protocol functions (like send_ok) to store strings
|
||||||
@ -408,6 +473,17 @@ void Protocol::init(THD *thd_arg)
|
|||||||
#endif
|
#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()
|
bool Protocol::flush()
|
||||||
{
|
{
|
||||||
@ -573,7 +649,14 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (flags & SEND_EOF)
|
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));
|
DBUG_RETURN(prepare_for_send(list));
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -75,6 +75,7 @@ public:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
virtual bool flush();
|
virtual bool flush();
|
||||||
|
virtual void end_partial_result_set(THD *thd);
|
||||||
virtual void prepare_for_resend()=0;
|
virtual void prepare_for_resend()=0;
|
||||||
|
|
||||||
virtual bool store_null()=0;
|
virtual bool store_null()=0;
|
||||||
@ -173,9 +174,7 @@ public:
|
|||||||
|
|
||||||
void send_warning(THD *thd, uint sql_errno, const char *err=0);
|
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 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,
|
void net_end_statement(THD *thd);
|
||||||
const char *info=0);
|
|
||||||
void send_eof(THD *thd);
|
|
||||||
bool send_old_password_request(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,const uchar *from, size_t length);
|
||||||
uchar *net_store_data(uchar *to,int32 from);
|
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 */
|
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);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
mysql_options(mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char *) &slave_net_timeout);
|
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);
|
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
/* Clear the result of mysql_create_db(). */
|
||||||
|
thd->main_da.reset_diagnostics_area();
|
||||||
|
|
||||||
if (mysql_select_db(&mysql, db) ||
|
if (mysql_select_db(&mysql, db) ||
|
||||||
mysql_real_query(&mysql, STRING_WITH_LEN("SHOW TABLES")) ||
|
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))
|
if (check && ((f->flags & mask) == mask))
|
||||||
{
|
{
|
||||||
DBUG_ASSERT(log);
|
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` "
|
"Field `%s` of table `%s`.`%s` "
|
||||||
"has no default value and cannot be NULL",
|
"has no default value and cannot be NULL",
|
||||||
f->field_name, table->s->db.str,
|
f->field_name, table->s->db.str,
|
||||||
table->s->table_name.str);
|
table->s->table_name.str);
|
||||||
error = ER_NO_DEFAULT_FOR_FIELD;
|
my_error(error, MYF(0), f->field_name);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
f->set_default();
|
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 (\
|
sql_print_error("Failed to create a new relay log info file (\
|
||||||
file '%s', errno %d)", fname, my_errno);
|
file '%s', errno %d)", fname, my_errno);
|
||||||
msg= current_thd->net.last_error;
|
msg= current_thd->main_da.message();
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (init_io_cache(&rli->info_file, info_fd, IO_SIZE*2, READ_CACHE, 0L,0,
|
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'",
|
sql_print_error("Failed to create a cache on relay log info file '%s'",
|
||||||
fname);
|
fname);
|
||||||
msg= current_thd->net.last_error;
|
msg= current_thd->main_da.message();
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
56
sql/slave.cc
56
sql/slave.cc
@ -981,18 +981,25 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
|
|||||||
}
|
}
|
||||||
thd->query= query;
|
thd->query= query;
|
||||||
thd->is_slave_error = 0;
|
thd->is_slave_error = 0;
|
||||||
thd->net.no_send_ok = 1;
|
|
||||||
|
|
||||||
bzero((char*) &tables,sizeof(tables));
|
bzero((char*) &tables,sizeof(tables));
|
||||||
tables.db = (char*)db;
|
tables.db = (char*)db;
|
||||||
tables.alias= tables.table_name= (char*)table_name;
|
tables.alias= tables.table_name= (char*)table_name;
|
||||||
|
|
||||||
/* Drop the table if 'overwrite' is true */
|
/* Drop the table if 'overwrite' is true */
|
||||||
if (overwrite && mysql_rm_table(thd,&tables,1,0)) /* drop if exists */
|
if (overwrite)
|
||||||
|
{
|
||||||
|
if (mysql_rm_table(thd,&tables,1,0)) /* drop if exists */
|
||||||
{
|
{
|
||||||
sql_print_error("create_table_from_dump: failed to drop the table");
|
sql_print_error("create_table_from_dump: failed to drop the table");
|
||||||
goto err;
|
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 */
|
/* Create the table. We do not want to log the "create table" statement */
|
||||||
save_options = thd->options;
|
save_options = thd->options;
|
||||||
@ -1012,6 +1019,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
|
|||||||
if (thd->is_slave_error)
|
if (thd->is_slave_error)
|
||||||
goto err; // mysql_parse took care of the error send
|
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";
|
thd->proc_info = "Opening master dump table";
|
||||||
/*
|
/*
|
||||||
Note: If this function starts to fail for MERGE tables,
|
Note: If this function starts to fail for MERGE tables,
|
||||||
@ -1055,7 +1063,6 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
|
|||||||
|
|
||||||
err:
|
err:
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
thd->net.no_send_ok = 0;
|
|
||||||
DBUG_RETURN(error);
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1107,7 +1114,6 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
|
|||||||
error = 0;
|
error = 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
thd->net.no_send_ok = 0; // Clear up garbage after create_table_from_dump
|
|
||||||
if (!called_connected)
|
if (!called_connected)
|
||||||
mysql_close(mysql);
|
mysql_close(mysql);
|
||||||
if (errmsg && thd->vio_ok())
|
if (errmsg && thd->vio_ok())
|
||||||
@ -1721,26 +1727,31 @@ static int has_temporary_error(THD *thd)
|
|||||||
DBUG_ENTER("has_temporary_error");
|
DBUG_ENTER("has_temporary_error");
|
||||||
|
|
||||||
if (thd->is_fatal_error)
|
if (thd->is_fatal_error)
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("thd->net.last_errno: %s", ER(thd->net.last_errno)));
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
|
||||||
|
|
||||||
DBUG_EXECUTE_IF("all_errors_are_temporary_errors",
|
DBUG_EXECUTE_IF("all_errors_are_temporary_errors",
|
||||||
if (thd->net.last_errno)
|
if (thd->main_da.is_error())
|
||||||
thd->net.last_errno= ER_LOCK_DEADLOCK;);
|
{
|
||||||
|
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:
|
Temporary error codes:
|
||||||
currently, InnoDB deadlock detected by InnoDB or lock
|
currently, InnoDB deadlock detected by InnoDB or lock
|
||||||
wait timeout (innodb_lock_wait_timeout exceeded
|
wait timeout (innodb_lock_wait_timeout exceeded
|
||||||
*/
|
*/
|
||||||
if (thd->net.last_errno == ER_LOCK_DEADLOCK ||
|
if (thd->main_da.sql_errno() == ER_LOCK_DEADLOCK ||
|
||||||
thd->net.last_errno == ER_LOCK_WAIT_TIMEOUT)
|
thd->main_da.sql_errno() == ER_LOCK_WAIT_TIMEOUT)
|
||||||
{
|
|
||||||
DBUG_PRINT("info", ("thd->net.last_errno: %s", ER(thd->net.last_errno)));
|
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef HAVE_NDB_BINLOG
|
#ifdef HAVE_NDB_BINLOG
|
||||||
/*
|
/*
|
||||||
@ -2551,20 +2562,21 @@ Slave SQL thread aborted. Can't execute init_slave query");
|
|||||||
*/
|
*/
|
||||||
uint32 const last_errno= rli->last_error().number;
|
uint32 const last_errno= rli->last_error().number;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("thd->net.last_errno=%d; rli->last_error.number=%d",
|
if (thd->is_error())
|
||||||
thd->net.last_errno, last_errno));
|
|
||||||
if (thd->net.last_errno != 0)
|
|
||||||
{
|
{
|
||||||
char const *const errmsg=
|
char const *const errmsg= thd->main_da.message();
|
||||||
thd->net.last_error ? thd->net.last_error : "<no 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)
|
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",
|
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);
|
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)
|
if (i->free_list)
|
||||||
cleanup_items(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)
|
thd->query, thd->query_length) <= 0)
|
||||||
{
|
{
|
||||||
res= m_lex_keeper.reset_lex_and_exec_core(thd, nextp, FALSE, this);
|
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))
|
if (!res && unlikely(thd->enable_slow_log))
|
||||||
log_slow_statement(thd);
|
log_slow_statement(thd);
|
||||||
query_cache_end_of_result(thd);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
*nextp= m_ip+1;
|
*nextp= m_ip+1;
|
||||||
thd->query= query;
|
thd->query= query;
|
||||||
thd->query_length= query_length;
|
thd->query_length= query_length;
|
||||||
|
|
||||||
|
if (!thd->is_error())
|
||||||
|
thd->main_da.reset_diagnostics_area();
|
||||||
}
|
}
|
||||||
DBUG_RETURN(res);
|
DBUG_RETURN(res);
|
||||||
}
|
}
|
||||||
|
@ -287,7 +287,6 @@ sp_rcontext::find_handler(THD *thd, uint sql_errno,
|
|||||||
sql_errno The error code
|
sql_errno The error code
|
||||||
level Warning level
|
level Warning level
|
||||||
thd The current thread
|
thd The current thread
|
||||||
- thd->net.report_error is an optional output.
|
|
||||||
|
|
||||||
RETURN
|
RETURN
|
||||||
TRUE if a handler was found.
|
TRUE if a handler was found.
|
||||||
@ -298,7 +297,6 @@ sp_rcontext::handle_error(uint sql_errno,
|
|||||||
MYSQL_ERROR::enum_warning_level level,
|
MYSQL_ERROR::enum_warning_level level,
|
||||||
THD *thd)
|
THD *thd)
|
||||||
{
|
{
|
||||||
bool handled= FALSE;
|
|
||||||
MYSQL_ERROR::enum_warning_level elevated_level= level;
|
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;
|
elevated_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (find_handler(thd, sql_errno, elevated_level))
|
return 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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -695,7 +695,7 @@ my_bool acl_reload(THD *thd)
|
|||||||
if (simple_open_n_lock_tables(thd, tables))
|
if (simple_open_n_lock_tables(thd, tables))
|
||||||
{
|
{
|
||||||
sql_print_error("Fatal error: Can't open and lock privilege tables: %s",
|
sql_print_error("Fatal error: Can't open and lock privilege tables: %s",
|
||||||
thd->net.last_error);
|
thd->main_da.message());
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3800,11 +3800,11 @@ my_bool grant_reload(THD *thd)
|
|||||||
close_thread_tables(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.
|
working with 4.1 privilege tables.
|
||||||
*/
|
*/
|
||||||
if (grant_reload_procs_priv(thd))
|
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);
|
rw_wrlock(&LOCK_grant);
|
||||||
grant_version++;
|
grant_version++;
|
||||||
@ -5693,9 +5693,6 @@ bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
|
|||||||
if (result)
|
if (result)
|
||||||
my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr_safe());
|
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);
|
write_bin_log(thd, FALSE, thd->query, thd->query_length);
|
||||||
|
|
||||||
rw_unlock(&LOCK_grant);
|
rw_unlock(&LOCK_grant);
|
||||||
|
@ -491,9 +491,28 @@ static TABLE_SHARE
|
|||||||
int tmp;
|
int tmp;
|
||||||
DBUG_ENTER("get_table_share_with_create");
|
DBUG_ENTER("get_table_share_with_create");
|
||||||
|
|
||||||
if ((share= get_table_share(thd, table_list, key, key_length,
|
share= get_table_share(thd, table_list, key, key_length, db_flags, error);
|
||||||
db_flags, error)) ||
|
/*
|
||||||
thd->net.last_errno != ER_NO_SUCH_TABLE)
|
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);
|
DBUG_RETURN(share);
|
||||||
|
|
||||||
/* Table didn't exist. Check if some engine can provide it */
|
/* Table didn't exist. Check if some engine can provide it */
|
||||||
@ -502,9 +521,13 @@ static TABLE_SHARE
|
|||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
No such table in any engine.
|
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;
|
TABLE_LIST *view= table_list->belong_to_view;
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
|
@ -40,13 +40,6 @@ void mysql_client_binlog_statement(THD* thd)
|
|||||||
if (check_global_access(thd, SUPER_ACL))
|
if (check_global_access(thd, SUPER_ACL))
|
||||||
DBUG_VOID_RETURN;
|
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 coded_len= thd->lex->comment.length + 1;
|
||||||
size_t decoded_len= base64_needed_decoded_length(coded_len);
|
size_t decoded_len= base64_needed_decoded_length(coded_len);
|
||||||
DBUG_ASSERT(coded_len > 0);
|
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"));
|
DBUG_PRINT("info",("binlog base64 execution finished successfully"));
|
||||||
send_ok(thd);
|
send_ok(thd);
|
||||||
|
|
||||||
end:
|
end:
|
||||||
/*
|
|
||||||
Restore setting of no_send_ok
|
|
||||||
*/
|
|
||||||
thd->net.no_send_ok= nsok;
|
|
||||||
|
|
||||||
delete desc;
|
delete desc;
|
||||||
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
|
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
@ -1403,6 +1403,7 @@ def_week_frmt: %lu",
|
|||||||
|
|
||||||
thd->limit_found_rows = query->found_rows();
|
thd->limit_found_rows = query->found_rows();
|
||||||
thd->status_var.last_query_cost= 0.0;
|
thd->status_var.last_query_cost= 0.0;
|
||||||
|
thd->main_da.disable_status();
|
||||||
|
|
||||||
BLOCK_UNLOCK_RD(query_block);
|
BLOCK_UNLOCK_RD(query_block);
|
||||||
DBUG_RETURN(1); // Result sent to client
|
DBUG_RETURN(1); // Result sent to client
|
||||||
|
149
sql/sql_class.cc
149
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());
|
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,
|
||||||
|
ulong 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()
|
THD::THD()
|
||||||
@ -431,7 +549,6 @@ THD::THD()
|
|||||||
net.vio=0;
|
net.vio=0;
|
||||||
#endif
|
#endif
|
||||||
client_capabilities= 0; // minimalistic client
|
client_capabilities= 0; // minimalistic client
|
||||||
net.last_error[0]=0; // If error on boot
|
|
||||||
#ifdef HAVE_QUERY_CACHE
|
#ifdef HAVE_QUERY_CACHE
|
||||||
query_cache_init_query(&net); // If error on boot
|
query_cache_init_query(&net); // If error on boot
|
||||||
#endif
|
#endif
|
||||||
@ -1324,12 +1441,12 @@ void select_send::abort()
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("select_send::abort");
|
DBUG_ENTER("select_send::abort");
|
||||||
if (is_result_set_started && thd->spcont &&
|
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))
|
MYSQL_ERROR::WARN_LEVEL_ERROR))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
We're executing a stored procedure, have an open result
|
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,
|
In this situation we must abort the current statement,
|
||||||
silence the error and start executing the continue/exit
|
silence the error and start executing the continue/exit
|
||||||
handler.
|
handler.
|
||||||
@ -1337,9 +1454,7 @@ void select_send::abort()
|
|||||||
otherwise the client will hang due to the violation of the
|
otherwise the client will hang due to the violation of the
|
||||||
client/server protocol.
|
client/server protocol.
|
||||||
*/
|
*/
|
||||||
thd->net.report_error= 0;
|
thd->protocol->end_partial_result_set(thd);
|
||||||
send_eof();
|
|
||||||
thd->net.report_error= 1; // Abort SP
|
|
||||||
}
|
}
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -1391,12 +1506,14 @@ bool select_send::send_data(List<Item> &items)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
thd->sent_row_count++;
|
thd->sent_row_count++;
|
||||||
if (!thd->vio_ok())
|
if (thd->is_error())
|
||||||
DBUG_RETURN(0);
|
{
|
||||||
if (! thd->is_error())
|
|
||||||
DBUG_RETURN(protocol->write());
|
|
||||||
protocol->remove_last_row();
|
protocol->remove_last_row();
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
if (thd->vio_ok())
|
||||||
|
DBUG_RETURN(protocol->write());
|
||||||
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool select_send::send_eof()
|
bool select_send::send_eof()
|
||||||
@ -1414,14 +1531,9 @@ bool select_send::send_eof()
|
|||||||
mysql_unlock_tables(thd, thd->lock);
|
mysql_unlock_tables(thd, thd->lock);
|
||||||
thd->lock=0;
|
thd->lock=0;
|
||||||
}
|
}
|
||||||
if (! thd->is_error())
|
|
||||||
{
|
|
||||||
::send_eof(thd);
|
::send_eof(thd);
|
||||||
is_result_set_started= 0;
|
is_result_set_started= 0;
|
||||||
return 0;
|
return FALSE;
|
||||||
}
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2701,7 +2813,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
|||||||
{
|
{
|
||||||
backup->options= options;
|
backup->options= options;
|
||||||
backup->in_sub_stmt= in_sub_stmt;
|
backup->in_sub_stmt= in_sub_stmt;
|
||||||
backup->no_send_ok= net.no_send_ok;
|
|
||||||
backup->enable_slow_log= enable_slow_log;
|
backup->enable_slow_log= enable_slow_log;
|
||||||
backup->limit_found_rows= limit_found_rows;
|
backup->limit_found_rows= limit_found_rows;
|
||||||
backup->examined_row_count= examined_row_count;
|
backup->examined_row_count= examined_row_count;
|
||||||
@ -2732,9 +2843,6 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
|||||||
cuted_fields= 0;
|
cuted_fields= 0;
|
||||||
transaction.savepoints= 0;
|
transaction.savepoints= 0;
|
||||||
first_successful_insert_id_in_cur_stmt= 0;
|
first_successful_insert_id_in_cur_stmt= 0;
|
||||||
|
|
||||||
/* Surpress OK packets in case if we will execute statements */
|
|
||||||
net.no_send_ok= TRUE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -2757,7 +2865,6 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
|||||||
transaction.savepoints= backup->savepoints;
|
transaction.savepoints= backup->savepoints;
|
||||||
options= backup->options;
|
options= backup->options;
|
||||||
in_sub_stmt= backup->in_sub_stmt;
|
in_sub_stmt= backup->in_sub_stmt;
|
||||||
net.no_send_ok= backup->no_send_ok;
|
|
||||||
enable_slow_log= backup->enable_slow_log;
|
enable_slow_log= backup->enable_slow_log;
|
||||||
first_successful_insert_id_in_prev_stmt=
|
first_successful_insert_id_in_prev_stmt=
|
||||||
backup->first_successful_insert_id_in_prev_stmt;
|
backup->first_successful_insert_id_in_prev_stmt;
|
||||||
|
159
sql/sql_class.h
159
sql/sql_class.h
@ -913,7 +913,6 @@ public:
|
|||||||
uint in_sub_stmt;
|
uint in_sub_stmt;
|
||||||
bool enable_slow_log;
|
bool enable_slow_log;
|
||||||
bool last_insert_id_used;
|
bool last_insert_id_used;
|
||||||
my_bool no_send_ok;
|
|
||||||
SAVEPOINT *savepoints;
|
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,
|
||||||
|
ulong 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; }
|
||||||
|
|
||||||
|
ulong 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().
|
||||||
|
*/
|
||||||
|
ulong 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
|
@class THD
|
||||||
For each client connection we create a separate thread with THD serving as
|
For each client connection we create a separate thread with THD serving as
|
||||||
@ -1400,6 +1516,7 @@ public:
|
|||||||
List <MYSQL_ERROR> warn_list;
|
List <MYSQL_ERROR> warn_list;
|
||||||
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
|
uint warn_count[(uint) MYSQL_ERROR::WARN_LEVEL_END];
|
||||||
uint total_warn_count;
|
uint total_warn_count;
|
||||||
|
Diagnostics_area main_da;
|
||||||
/*
|
/*
|
||||||
Id of current query. Statement can be reused to execute several queries
|
Id of current query. Statement can be reused to execute several queries
|
||||||
query_id is global in context of the whole MySQL server.
|
query_id is global in context of the whole MySQL server.
|
||||||
@ -1714,12 +1831,18 @@ public:
|
|||||||
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
|
CHANGED_TABLE_LIST * changed_table_dup(const char *key, long key_length);
|
||||||
int send_explain_fields(select_result *result);
|
int send_explain_fields(select_result *result);
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#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()
|
inline void clear_error()
|
||||||
{
|
{
|
||||||
DBUG_ENTER("clear_error");
|
DBUG_ENTER("clear_error");
|
||||||
net.last_error[0]= 0;
|
if (main_da.is_error())
|
||||||
net.last_errno= 0;
|
main_da.reset_diagnostics_area();
|
||||||
net.report_error= 0;
|
|
||||||
is_slave_error= 0;
|
is_slave_error= 0;
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
@ -1728,10 +1851,14 @@ public:
|
|||||||
void clear_error();
|
void clear_error();
|
||||||
inline bool vio_ok() const { return true; }
|
inline bool vio_ok() const { return true; }
|
||||||
#endif
|
#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()
|
inline void fatal_error()
|
||||||
{
|
{
|
||||||
is_fatal_error= 1;
|
is_fatal_error= 1;
|
||||||
net.report_error= 1;
|
|
||||||
DBUG_PRINT("error",("Fatal error set"));
|
DBUG_PRINT("error",("Fatal error set"));
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
@ -1747,7 +1874,7 @@ public:
|
|||||||
|
|
||||||
To raise this flag, use my_error().
|
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; }
|
inline CHARSET_INFO *charset() { return variables.character_set_client; }
|
||||||
void update_charset();
|
void update_charset();
|
||||||
|
|
||||||
@ -1971,6 +2098,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) \
|
#define tmp_disable_binlog(A) \
|
||||||
{ulonglong tmp_disable_binlog__save_options= (A)->options; \
|
{ulonglong tmp_disable_binlog__save_options= (A)->options; \
|
||||||
(A)->options&= ~OPTION_BIN_LOG
|
(A)->options&= ~OPTION_BIN_LOG
|
||||||
@ -2508,6 +2653,7 @@ public:
|
|||||||
void send_error(uint errcode,const char *err);
|
void send_error(uint errcode,const char *err);
|
||||||
int do_deletes();
|
int do_deletes();
|
||||||
bool send_eof();
|
bool send_eof();
|
||||||
|
virtual void abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -2550,6 +2696,7 @@ public:
|
|||||||
void send_error(uint errcode,const char *err);
|
void send_error(uint errcode,const char *err);
|
||||||
int do_updates (bool from_send_error);
|
int do_updates (bool from_send_error);
|
||||||
bool send_eof();
|
bool send_eof();
|
||||||
|
virtual void abort();
|
||||||
};
|
};
|
||||||
|
|
||||||
class my_var : public Sql_alloc {
|
class my_var : public Sql_alloc {
|
||||||
|
@ -948,19 +948,20 @@ bool setup_connection_thread_globals(THD *thd)
|
|||||||
bool login_connection(THD *thd)
|
bool login_connection(THD *thd)
|
||||||
{
|
{
|
||||||
NET *net= &thd->net;
|
NET *net= &thd->net;
|
||||||
|
int error;
|
||||||
DBUG_ENTER("login_connection");
|
DBUG_ENTER("login_connection");
|
||||||
DBUG_PRINT("info", ("login_connection called by thread %lu",
|
DBUG_PRINT("info", ("login_connection called by thread %lu",
|
||||||
thd->thread_id));
|
thd->thread_id));
|
||||||
|
|
||||||
net->no_send_error= 0;
|
|
||||||
|
|
||||||
/* Use "connect_timeout" value during connection phase */
|
/* Use "connect_timeout" value during connection phase */
|
||||||
my_net_set_read_timeout(net, connect_timeout);
|
my_net_set_read_timeout(net, connect_timeout);
|
||||||
my_net_set_write_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
|
{ // Wrong permissions
|
||||||
net_send_error(thd);
|
|
||||||
#ifdef __NT__
|
#ifdef __NT__
|
||||||
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
|
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
|
||||||
my_sleep(1000); /* must wait after eof() */
|
my_sleep(1000); /* must wait after eof() */
|
||||||
@ -989,13 +990,12 @@ void end_connection(THD *thd)
|
|||||||
if (thd->user_connect)
|
if (thd->user_connect)
|
||||||
decrease_user_connections(thd->user_connect);
|
decrease_user_connections(thd->user_connect);
|
||||||
|
|
||||||
if (thd->killed ||
|
if (thd->killed || net->error && net->vio != 0)
|
||||||
net->error && net->vio != 0 && thd->is_error())
|
|
||||||
{
|
{
|
||||||
statistic_increment(aborted_threads,&LOCK_status);
|
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)
|
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"),
|
thd->thread_id,(thd->db ? thd->db : "unconnected"),
|
||||||
sctx->user ? sctx->user : "unauthenticated",
|
sctx->user ? sctx->user : "unauthenticated",
|
||||||
sctx->host_or_ip,
|
sctx->host_or_ip,
|
||||||
(net->last_errno ? ER(net->last_errno) :
|
(thd->main_da.is_error() ? thd->main_da.message() :
|
||||||
ER(ER_UNKNOWN_ERROR)));
|
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))
|
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(thd, &sys_init_connect, &LOCK_sys_init_connect);
|
||||||
/*
|
if (thd->is_error())
|
||||||
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)
|
|
||||||
{
|
{
|
||||||
thd->killed= THD::KILL_CONNECTION;
|
thd->killed= THD::KILL_CONNECTION;
|
||||||
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
|
sql_print_warning(ER(ER_NEW_ABORTING_CONNECTION),
|
||||||
thd->thread_id,(thd->db ? thd->db : "unconnected"),
|
thd->thread_id,(thd->db ? thd->db : "unconnected"),
|
||||||
sctx->user ? sctx->user : "unauthenticated",
|
sctx->user ? sctx->user : "unauthenticated",
|
||||||
sctx->host_or_ip, "init_connect command failed");
|
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->proc_info=0;
|
||||||
thd->set_time();
|
thd->set_time();
|
||||||
@ -1129,7 +1117,6 @@ pthread_handler_t handle_one_connection(void *arg)
|
|||||||
while (!net->error && net->vio != 0 &&
|
while (!net->error && net->vio != 0 &&
|
||||||
!(thd->killed == THD::KILL_CONNECTION))
|
!(thd->killed == THD::KILL_CONNECTION))
|
||||||
{
|
{
|
||||||
net->no_send_error= 0;
|
|
||||||
if (do_command(thd))
|
if (do_command(thd))
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -921,6 +921,8 @@ bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
|
|||||||
{
|
{
|
||||||
ha_drop_database(path);
|
ha_drop_database(path);
|
||||||
query_cache_invalidate1(db);
|
query_cache_invalidate1(db);
|
||||||
|
(void) sp_drop_db_routines(thd, db); /* @todo Do not ignore errors */
|
||||||
|
Events::drop_schema_events(thd, db);
|
||||||
error = 0;
|
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 */
|
/* These DDL methods and logging protected with LOCK_mysql_create_db */
|
||||||
mysql_bin_log.write(&qinfo);
|
mysql_bin_log.write(&qinfo);
|
||||||
}
|
}
|
||||||
|
thd->clear_error();
|
||||||
thd->server_status|= SERVER_STATUS_DB_DROPPED;
|
thd->server_status|= SERVER_STATUS_DB_DROPPED;
|
||||||
send_ok(thd, (ulong) deleted);
|
send_ok(thd, (ulong) deleted);
|
||||||
thd->server_status&= ~SERVER_STATUS_DB_DROPPED;
|
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:
|
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
|
If this database was the client's selected database, we silently
|
||||||
change the client's selected database to nothing (to have an empty
|
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 ... */
|
/* First send error what ever it is ... */
|
||||||
my_message(errcode, err, MYF(0));
|
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 */
|
/* the error was handled or nothing deleted and no side effects return */
|
||||||
if (error_handled ||
|
if (error_handled ||
|
||||||
!thd->transaction.stmt.modified_non_trans_table && !deleted)
|
!thd->transaction.stmt.modified_non_trans_table && !deleted)
|
||||||
|
@ -147,8 +147,9 @@ exit:
|
|||||||
/* Hide "Unknown column" or "Unknown function" error */
|
/* Hide "Unknown column" or "Unknown function" error */
|
||||||
if (orig_table_list->view)
|
if (orig_table_list->view)
|
||||||
{
|
{
|
||||||
if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
|
if (thd->is_error() &&
|
||||||
thd->net.last_errno == ER_SP_DOES_NOT_EXIST)
|
(thd->main_da.sql_errno() == ER_BAD_FIELD_ERROR ||
|
||||||
|
thd->main_da.sql_errno() == ER_SP_DOES_NOT_EXIST))
|
||||||
{
|
{
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
my_error(ER_VIEW_INVALID, MYF(0), orig_table_list->db,
|
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
|
main thread. Use of my_message will enable stored
|
||||||
procedures continue handlers.
|
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));
|
MYF(0));
|
||||||
}
|
}
|
||||||
di->unlock();
|
di->unlock();
|
||||||
@ -1993,7 +1993,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd)
|
|||||||
goto error;
|
goto error;
|
||||||
if (dead)
|
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;
|
goto error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2252,7 +2252,9 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
|||||||
#if !defined( __WIN__) /* Win32 calls this in pthread_create */
|
#if !defined( __WIN__) /* Win32 calls this in pthread_create */
|
||||||
if (my_thread_init())
|
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;
|
goto end;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -2261,8 +2263,10 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
|||||||
thd->thread_stack= (char*) &thd;
|
thd->thread_stack= (char*) &thd;
|
||||||
if (init_thr_lock() || thd->store_globals())
|
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();
|
thd->fatal_error();
|
||||||
strmov(thd->net.last_error,ER(thd->net.last_errno=ER_OUT_OF_RESOURCES));
|
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2665,7 +2669,7 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
{
|
{
|
||||||
/* This should never happen */
|
/* This should never happen */
|
||||||
table->file->print_error(error,MYF(0));
|
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"));
|
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed in loop"));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -2706,7 +2710,7 @@ bool Delayed_insert::handle_inserts(void)
|
|||||||
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
|
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
|
||||||
{ // This shouldn't happen
|
{ // This shouldn't happen
|
||||||
table->file->print_error(error,MYF(0));
|
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"));
|
DBUG_PRINT("error", ("HA_EXTRA_NO_CACHE failed after loop"));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
106
sql/sql_parse.cc
106
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;
|
save_vio= thd->net.vio;
|
||||||
thd->net.vio= 0;
|
thd->net.vio= 0;
|
||||||
thd->net.no_send_error= 0;
|
|
||||||
dispatch_command(COM_QUERY, thd,
|
dispatch_command(COM_QUERY, thd,
|
||||||
init_command_var->value,
|
init_command_var->value,
|
||||||
init_command_var->value_length);
|
init_command_var->value_length);
|
||||||
@ -397,8 +396,8 @@ pthread_handler_t handle_bootstrap(void *arg)
|
|||||||
/* purecov: begin tested */
|
/* purecov: begin tested */
|
||||||
if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
|
if (net_realloc(&(thd->net), 2 * thd->net.max_packet))
|
||||||
{
|
{
|
||||||
net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS);
|
net_end_statement(thd);
|
||||||
thd->fatal_error();
|
bootstrap_error= 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
buff= (char*) thd->net.buff;
|
buff= (char*) thd->net.buff;
|
||||||
@ -406,7 +405,7 @@ pthread_handler_t handle_bootstrap(void *arg)
|
|||||||
length+= (ulong) strlen(buff + length);
|
length+= (ulong) strlen(buff + length);
|
||||||
/* purecov: end */
|
/* purecov: end */
|
||||||
}
|
}
|
||||||
if (thd->is_fatal_error)
|
if (bootstrap_error)
|
||||||
break; /* purecov: inspected */
|
break; /* purecov: inspected */
|
||||||
|
|
||||||
while (length && (my_isspace(thd->charset(), buff[length-1]) ||
|
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);
|
mysql_parse(thd, thd->query, length, & found_semicolon);
|
||||||
close_thread_tables(thd); // Free tables
|
close_thread_tables(thd); // Free tables
|
||||||
|
|
||||||
if (thd->is_fatal_error)
|
bootstrap_error= thd->is_error();
|
||||||
break;
|
net_end_statement(thd);
|
||||||
|
|
||||||
if (thd->is_error())
|
if (bootstrap_error)
|
||||||
{
|
|
||||||
/* The query failed, send error to log and abort bootstrap */
|
|
||||||
net_send_error(thd);
|
|
||||||
thd->fatal_error();
|
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
|
|
||||||
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
|
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
|
||||||
#ifdef USING_TRANSACTIONS
|
#ifdef USING_TRANSACTIONS
|
||||||
@ -451,9 +445,6 @@ pthread_handler_t handle_bootstrap(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
/* Remember the exit code of bootstrap */
|
|
||||||
bootstrap_error= thd->is_fatal_error;
|
|
||||||
|
|
||||||
net_end(&thd->net);
|
net_end(&thd->net);
|
||||||
thd->cleanup();
|
thd->cleanup();
|
||||||
delete thd;
|
delete thd;
|
||||||
@ -712,7 +703,12 @@ bool do_command(THD *thd)
|
|||||||
*/
|
*/
|
||||||
my_net_set_read_timeout(net, thd->variables.net_wait_timeout);
|
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->clear_error(); // Clear error message
|
||||||
|
thd->main_da.reset_diagnostics_area();
|
||||||
|
|
||||||
net_new_transaction(net);
|
net_new_transaction(net);
|
||||||
if ((packet_length=my_net_read(net)) == packet_error)
|
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 */
|
/* 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)
|
if (net->error != 3)
|
||||||
DBUG_RETURN(TRUE); // We have to close it.
|
DBUG_RETURN(TRUE); // We have to close it.
|
||||||
|
|
||||||
net_send_error(thd, net->last_errno, NullS);
|
|
||||||
net->error= 0;
|
net->error= 0;
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
@ -860,7 +859,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
db.length= db_len;
|
db.length= db_len;
|
||||||
tbl_name= strmake(db.str, packet + 1, db_len)+1;
|
tbl_name= strmake(db.str, packet + 1, db_len)+1;
|
||||||
strmake(tbl_name, packet + db_len + 2, tbl_len);
|
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;
|
break;
|
||||||
}
|
}
|
||||||
case COM_CHANGE_USER:
|
case COM_CHANGE_USER:
|
||||||
@ -1024,7 +1024,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
while (!thd->killed && found_semicolon && ! thd->is_error())
|
while (!thd->killed && found_semicolon && ! thd->is_error())
|
||||||
{
|
{
|
||||||
char *next_packet= (char*) found_semicolon;
|
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
|
Multiple queries exits, execute them individually
|
||||||
*/
|
*/
|
||||||
@ -1125,6 +1127,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
/* We don't calculate statistics for this command */
|
/* We don't calculate statistics for this command */
|
||||||
general_log_print(thd, command, NullS);
|
general_log_print(thd, command, NullS);
|
||||||
net->error=0; // Don't give 'abort' message
|
net->error=0; // Don't give 'abort' message
|
||||||
|
thd->main_da.disable_status(); // Don't send anything back
|
||||||
error=TRUE; // End server
|
error=TRUE; // End server
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1241,16 +1244,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
DBUG_PRINT("quit",("Got shutdown command for level %u", level));
|
DBUG_PRINT("quit",("Got shutdown command for level %u", level));
|
||||||
general_log_print(thd, command, NullS);
|
general_log_print(thd, command, NullS);
|
||||||
send_eof(thd);
|
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
|
close_thread_tables(thd); // Free before kill
|
||||||
kill_mysql();
|
kill_mysql();
|
||||||
error=TRUE;
|
error=TRUE;
|
||||||
@ -1263,13 +1256,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
ulong uptime;
|
ulong uptime;
|
||||||
uint length;
|
uint length;
|
||||||
ulonglong queries_per_second1000;
|
ulonglong queries_per_second1000;
|
||||||
#ifndef EMBEDDED_LIBRARY
|
|
||||||
char buff[250];
|
char buff[250];
|
||||||
uint buff_len= sizeof(buff);
|
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);
|
general_log_print(thd, command, NullS);
|
||||||
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS]);
|
status_var_increment(thd->status_var.com_stat[SQLCOM_SHOW_STATUS]);
|
||||||
@ -1291,6 +1279,10 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
cached_open_tables(),
|
cached_open_tables(),
|
||||||
(uint) (queries_per_second1000 / 1000),
|
(uint) (queries_per_second1000 / 1000),
|
||||||
(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
|
#ifdef SAFEMALLOC
|
||||||
if (sf_malloc_cur_memory) // Using SAFEMALLOC
|
if (sf_malloc_cur_memory) // Using SAFEMALLOC
|
||||||
{
|
{
|
||||||
@ -1304,6 +1296,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
VOID(my_net_write(net, (uchar*) buff, length));
|
VOID(my_net_write(net, (uchar*) buff, length));
|
||||||
VOID(net_flush(net));
|
VOID(net_flush(net));
|
||||||
|
thd->main_da.disable_status();
|
||||||
#endif
|
#endif
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1383,10 +1376,19 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||||||
thd->transaction.xid_state.xid.null();
|
thd->transaction.xid_state.xid.null();
|
||||||
|
|
||||||
/* report error issued during command execution */
|
/* report error issued during command execution */
|
||||||
if (thd->killed_errno() && ! thd->is_error())
|
if (thd->killed_errno())
|
||||||
|
{
|
||||||
|
if (! thd->main_da.is_set())
|
||||||
thd->send_kill_message();
|
thd->send_kill_message();
|
||||||
if (thd->is_error())
|
}
|
||||||
net_send_error(thd);
|
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);
|
log_slow_statement(thd);
|
||||||
|
|
||||||
@ -1756,7 +1758,6 @@ mysql_execute_command(THD *thd)
|
|||||||
SELECT_LEX_UNIT *unit= &lex->unit;
|
SELECT_LEX_UNIT *unit= &lex->unit;
|
||||||
/* Saved variable value */
|
/* Saved variable value */
|
||||||
DBUG_ENTER("mysql_execute_command");
|
DBUG_ENTER("mysql_execute_command");
|
||||||
thd->net.no_send_error= 0;
|
|
||||||
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
#ifdef WITH_PARTITION_STORAGE_ENGINE
|
||||||
thd->work_part_info= 0;
|
thd->work_part_info= 0;
|
||||||
#endif
|
#endif
|
||||||
@ -2992,13 +2993,9 @@ end_with_restore_list:
|
|||||||
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
|
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK |
|
||||||
OPTION_SETUP_TABLES_DONE,
|
OPTION_SETUP_TABLES_DONE,
|
||||||
del_result, unit, select_lex);
|
del_result, unit, select_lex);
|
||||||
res|= thd->net.report_error;
|
res|= thd->is_error();
|
||||||
if (unlikely(res))
|
if (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");
|
|
||||||
del_result->abort();
|
del_result->abort();
|
||||||
}
|
|
||||||
delete del_result;
|
delete del_result;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -3931,8 +3928,6 @@ create_sp_error:
|
|||||||
goto 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 (sp->m_flags & sp_head::MULTI_RESULTS)
|
||||||
{
|
{
|
||||||
if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
|
if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
|
||||||
@ -3942,7 +3937,6 @@ create_sp_error:
|
|||||||
back
|
back
|
||||||
*/
|
*/
|
||||||
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
|
my_error(ER_SP_BADSELECT, MYF(0), sp->m_qname.str);
|
||||||
thd->net.no_send_ok= save_no_send_ok;
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
@ -3958,7 +3952,6 @@ create_sp_error:
|
|||||||
if (check_routine_access(thd, EXECUTE_ACL,
|
if (check_routine_access(thd, EXECUTE_ACL,
|
||||||
sp->m_db.str, sp->m_name.str, TRUE, FALSE))
|
sp->m_db.str, sp->m_name.str, TRUE, FALSE))
|
||||||
{
|
{
|
||||||
thd->net.no_send_ok= save_no_send_ok;
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@ -3983,7 +3976,6 @@ create_sp_error:
|
|||||||
|
|
||||||
thd->variables.select_limit= select_limit;
|
thd->variables.select_limit= select_limit;
|
||||||
|
|
||||||
thd->net.no_send_ok= save_no_send_ok;
|
|
||||||
thd->server_status&= ~bits_to_be_cleared;
|
thd->server_status&= ~bits_to_be_cleared;
|
||||||
|
|
||||||
if (!res)
|
if (!res)
|
||||||
@ -4624,6 +4616,9 @@ static bool execute_sqlcom_select(THD *thd, TABLE_LIST *all_tables)
|
|||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||||
ER_YES, str.ptr());
|
ER_YES, str.ptr());
|
||||||
}
|
}
|
||||||
|
if (res)
|
||||||
|
result->abort();
|
||||||
|
else
|
||||||
result->send_eof();
|
result->send_eof();
|
||||||
delete result;
|
delete result;
|
||||||
}
|
}
|
||||||
@ -5251,6 +5246,7 @@ void mysql_reset_thd_for_next_command(THD *thd)
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_reset_thd_for_next_command");
|
DBUG_ENTER("mysql_reset_thd_for_next_command");
|
||||||
DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
|
DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
|
||||||
|
DBUG_ASSERT(! thd->in_sub_stmt);
|
||||||
thd->free_list= 0;
|
thd->free_list= 0;
|
||||||
thd->select_number= 1;
|
thd->select_number= 1;
|
||||||
/*
|
/*
|
||||||
@ -5277,18 +5273,18 @@ void mysql_reset_thd_for_next_command(THD *thd)
|
|||||||
}
|
}
|
||||||
DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx);
|
DBUG_ASSERT(thd->security_ctx== &thd->main_security_ctx);
|
||||||
thd->thread_specific_used= FALSE;
|
thd->thread_specific_used= FALSE;
|
||||||
if (!thd->in_sub_stmt)
|
|
||||||
{
|
|
||||||
if (opt_bin_log)
|
if (opt_bin_log)
|
||||||
{
|
{
|
||||||
reset_dynamic(&thd->user_var_events);
|
reset_dynamic(&thd->user_var_events);
|
||||||
thd->user_var_events_alloc= thd->mem_root;
|
thd->user_var_events_alloc= thd->mem_root;
|
||||||
}
|
}
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
|
thd->main_da.reset_diagnostics_area();
|
||||||
thd->total_warn_count=0; // Warnings for this query
|
thd->total_warn_count=0; // Warnings for this query
|
||||||
thd->rand_used= 0;
|
thd->rand_used= 0;
|
||||||
thd->sent_row_count= thd->examined_row_count= 0;
|
thd->sent_row_count= thd->examined_row_count= 0;
|
||||||
}
|
|
||||||
/*
|
/*
|
||||||
Because we come here only for start of top-statements, binlog format is
|
Because we come here only for start of top-statements, binlog format is
|
||||||
constant inside a complex statement (using stored functions) etc.
|
constant inside a complex statement (using stored functions) etc.
|
||||||
@ -5526,7 +5522,6 @@ void mysql_parse(THD *thd, const char *inBuf, uint length,
|
|||||||
/* Actually execute the query */
|
/* Actually execute the query */
|
||||||
lex->set_trg_event_type_for_tables();
|
lex->set_trg_event_type_for_tables();
|
||||||
mysql_execute_command(thd);
|
mysql_execute_command(thd);
|
||||||
query_cache_end_of_result(thd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -6378,8 +6373,10 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
|||||||
}
|
}
|
||||||
if (thd)
|
if (thd)
|
||||||
{
|
{
|
||||||
(void)acl_reload(thd);
|
if (acl_reload(thd))
|
||||||
(void)grant_reload(thd);
|
result= 1;
|
||||||
|
if (grant_reload(thd))
|
||||||
|
result= 1;
|
||||||
}
|
}
|
||||||
if (tmp_thd)
|
if (tmp_thd)
|
||||||
{
|
{
|
||||||
@ -6496,7 +6493,6 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
|
|||||||
if (reset_master(thd))
|
if (reset_master(thd))
|
||||||
{
|
{
|
||||||
result=1;
|
result=1;
|
||||||
thd->fatal_error(); // Ensure client get error
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -2068,6 +2068,7 @@ char *generate_partition_syntax(partition_info *part_info,
|
|||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
/* We really shouldn't get here, no use in continuing from here */
|
/* We really shouldn't get here, no use in continuing from here */
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
current_thd->fatal_error();
|
current_thd->fatal_error();
|
||||||
DBUG_RETURN(NULL);
|
DBUG_RETURN(NULL);
|
||||||
}
|
}
|
||||||
|
@ -230,6 +230,8 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
|
|||||||
NET *net= &stmt->thd->net;
|
NET *net= &stmt->thd->net;
|
||||||
uchar buff[12];
|
uchar buff[12];
|
||||||
uint tmp;
|
uint tmp;
|
||||||
|
int error;
|
||||||
|
THD *thd= stmt->thd;
|
||||||
DBUG_ENTER("send_prep_stmt");
|
DBUG_ENTER("send_prep_stmt");
|
||||||
|
|
||||||
buff[0]= 0; /* OK packet indicator */
|
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
|
Send types and names of placeholders to the client
|
||||||
XXX: fix this nasty upcast from List<Item_param> to List<Item>
|
XXX: fix this nasty upcast from List<Item_param> to List<Item>
|
||||||
*/
|
*/
|
||||||
DBUG_RETURN(my_net_write(net, buff, sizeof(buff)) ||
|
error= my_net_write(net, buff, sizeof(buff));
|
||||||
(stmt->param_count &&
|
if (stmt->param_count && ! error)
|
||||||
stmt->thd->protocol_text.send_fields((List<Item> *)
|
{
|
||||||
|
error= thd->protocol_text.send_fields((List<Item> *)
|
||||||
&stmt->lex->param_list,
|
&stmt->lex->param_list,
|
||||||
Protocol::SEND_EOF)));
|
Protocol::SEND_EOF);
|
||||||
|
}
|
||||||
|
/* Flag that a response has already been sent */
|
||||||
|
thd->main_da.disable_status();
|
||||||
|
DBUG_RETURN(error);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static bool send_prep_stmt(Prepared_statement *stmt,
|
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_stmt_id= stmt->id;
|
||||||
thd->client_param_count= stmt->param_count;
|
thd->client_param_count= stmt->param_count;
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
|
thd->main_da.disable_status();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -2526,6 +2534,8 @@ void mysql_stmt_close(THD *thd, char *packet)
|
|||||||
DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE));
|
DBUG_ASSERT(! (stmt->flags & (uint) Prepared_statement::IS_IN_USE));
|
||||||
(void) stmt->deallocate();
|
(void) stmt->deallocate();
|
||||||
|
|
||||||
|
thd->main_da.disable_status();
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
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");
|
DBUG_ENTER("mysql_stmt_get_longdata");
|
||||||
|
|
||||||
status_var_increment(thd->status_var.com_stmt_send_long_data);
|
status_var_increment(thd->status_var.com_stmt_send_long_data);
|
||||||
|
|
||||||
|
thd->main_da.disable_status();
|
||||||
#ifndef EMBEDDED_LIBRARY
|
#ifndef EMBEDDED_LIBRARY
|
||||||
/* Minimal size of long data packet is 6 bytes */
|
/* Minimal size of long data packet is 6 bytes */
|
||||||
if (packet_length < MYSQL_LONG_DATA_HEADER)
|
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()
|
bool Select_fetch_protocol_binary::send_eof()
|
||||||
{
|
{
|
||||||
Protocol *save_protocol= thd->protocol;
|
|
||||||
|
|
||||||
thd->protocol= &protocol;
|
|
||||||
::send_eof(thd);
|
::send_eof(thd);
|
||||||
thd->protocol= save_protocol;
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3097,7 +3105,6 @@ bool Prepared_statement::execute(String *expanded_query, bool open_cursor)
|
|||||||
thd->query_length) <= 0)
|
thd->query_length) <= 0)
|
||||||
{
|
{
|
||||||
error= mysql_execute_command(thd);
|
error= mysql_execute_command(thd);
|
||||||
query_cache_end_of_result(thd);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -898,7 +898,6 @@ JOIN::optimize()
|
|||||||
}
|
}
|
||||||
if (res > 1)
|
if (res > 1)
|
||||||
{
|
{
|
||||||
thd->fatal_error();
|
|
||||||
error= res;
|
error= res;
|
||||||
DBUG_PRINT("error",("Error from opt_sum_query"));
|
DBUG_PRINT("error",("Error from opt_sum_query"));
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
@ -14454,6 +14453,7 @@ calc_group_buffer(JOIN *join,ORDER *group)
|
|||||||
default:
|
default:
|
||||||
/* This case should never be choosen */
|
/* This case should never be choosen */
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
join->thd->fatal_error();
|
join->thd->fatal_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -239,7 +239,7 @@ bool servers_reload(THD *thd)
|
|||||||
if (simple_open_n_lock_tables(thd, tables))
|
if (simple_open_n_lock_tables(thd, tables))
|
||||||
{
|
{
|
||||||
sql_print_error("Can't open and lock privilege tables: %s",
|
sql_print_error("Can't open and lock privilege tables: %s",
|
||||||
thd->net.last_error);
|
thd->main_da.message());
|
||||||
goto end;
|
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 */
|
/* Only one table for now, but VIEW can involve several tables */
|
||||||
if (open_normal_and_derived_tables(thd, table_list, 0))
|
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);
|
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
|
restore_record(table, s->default_values); // Get empty record
|
||||||
table->use_all_columns();
|
table->use_all_columns();
|
||||||
if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS |
|
if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS))
|
||||||
Protocol::SEND_EOF))
|
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
thd->protocol->flush();
|
send_eof(thd);
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2919,7 +2919,7 @@ static int fill_schema_table_names(THD *thd, TABLE *table,
|
|||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
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();
|
thd->clear_error();
|
||||||
return 0;
|
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,
|
res= open_normal_and_derived_tables(thd, show_table_list,
|
||||||
MYSQL_LOCK_IGNORE_FLUSH);
|
MYSQL_LOCK_IGNORE_FLUSH);
|
||||||
lex->sql_command= save_sql_command;
|
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.
|
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
|
there was errors during opening tables
|
||||||
*/
|
*/
|
||||||
const char *error= thd->net.last_error;
|
const char *error= thd->main_da.message();
|
||||||
if (tables->view)
|
if (tables->view)
|
||||||
table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
|
table->field[3]->store(STRING_WITH_LEN("VIEW"), cs);
|
||||||
else if (tables->schema_table)
|
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
|
rather than in SHOW COLUMNS
|
||||||
*/
|
*/
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
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();
|
thd->clear_error();
|
||||||
res= 0;
|
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
|
I.e. we are in SELECT FROM INFORMATION_SCHEMA.STATISTICS
|
||||||
rather than in SHOW KEYS
|
rather than in SHOW KEYS
|
||||||
*/
|
*/
|
||||||
if (thd->net.last_errno)
|
if (thd->is_error())
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
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();
|
thd->clear_error();
|
||||||
res= 0;
|
res= 0;
|
||||||
}
|
}
|
||||||
@ -4290,9 +4298,9 @@ static int get_schema_views_record(THD *thd, TABLE_LIST *tables,
|
|||||||
|
|
||||||
if (schema_table_store_record(thd, table))
|
if (schema_table_store_record(thd, table))
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
if (res && thd->net.last_errno)
|
if (res && thd->is_error())
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
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)
|
if (res)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
@ -4323,9 +4331,9 @@ static int get_schema_constraints_record(THD *thd, TABLE_LIST *tables,
|
|||||||
DBUG_ENTER("get_schema_constraints_record");
|
DBUG_ENTER("get_schema_constraints_record");
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
if (thd->net.last_errno)
|
if (thd->is_error())
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
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();
|
thd->clear_error();
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -4428,9 +4436,9 @@ static int get_schema_triggers_record(THD *thd, TABLE_LIST *tables,
|
|||||||
*/
|
*/
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
if (thd->net.last_errno)
|
if (thd->is_error())
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
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();
|
thd->clear_error();
|
||||||
DBUG_RETURN(0);
|
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");
|
DBUG_ENTER("get_schema_key_column_usage_record");
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
if (thd->net.last_errno)
|
if (thd->is_error())
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
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();
|
thd->clear_error();
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -4706,9 +4714,9 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
|
|||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
if (thd->net.last_errno)
|
if (thd->is_error())
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
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();
|
thd->clear_error();
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -4751,6 +4759,7 @@ static int get_schema_partitions_record(THD *thd, TABLE_LIST *tables,
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
|
my_error(ER_OUT_OF_RESOURCES, MYF(0));
|
||||||
current_thd->fatal_error();
|
current_thd->fatal_error();
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
}
|
}
|
||||||
@ -5243,9 +5252,9 @@ get_referential_constraints_record(THD *thd, TABLE_LIST *tables,
|
|||||||
|
|
||||||
if (res)
|
if (res)
|
||||||
{
|
{
|
||||||
if (thd->net.last_errno)
|
if (thd->is_error())
|
||||||
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
|
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();
|
thd->clear_error();
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
|
@ -1662,7 +1662,10 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
|
|||||||
!dont_log_query);
|
!dont_log_query);
|
||||||
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
|
if ((error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) &&
|
||||||
(if_exists || table_type == NULL))
|
(if_exists || table_type == NULL))
|
||||||
|
{
|
||||||
error= 0;
|
error= 0;
|
||||||
|
thd->clear_error();
|
||||||
|
}
|
||||||
if (error == HA_ERR_ROW_IS_REFERENCED)
|
if (error == HA_ERR_ROW_IS_REFERENCED)
|
||||||
{
|
{
|
||||||
/* the table is referenced by a foreign key constraint */
|
/* the table is referenced by a foreign key constraint */
|
||||||
@ -4191,18 +4194,22 @@ static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
|
|||||||
(table->table->file->ha_check_for_upgrade(check_opt) ==
|
(table->table->file->ha_check_for_upgrade(check_opt) ==
|
||||||
HA_ADMIN_NEEDS_ALTER))
|
HA_ADMIN_NEEDS_ALTER))
|
||||||
{
|
{
|
||||||
my_bool save_no_send_ok= thd->net.no_send_ok;
|
|
||||||
DBUG_PRINT("admin", ("recreating table"));
|
DBUG_PRINT("admin", ("recreating table"));
|
||||||
ha_autocommit_or_rollback(thd, 1);
|
ha_autocommit_or_rollback(thd, 1);
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
||||||
thd->net.no_send_ok= TRUE;
|
|
||||||
result_code= mysql_recreate_table(thd, table);
|
result_code= mysql_recreate_table(thd, table);
|
||||||
thd->net.no_send_ok= save_no_send_ok;
|
|
||||||
reenable_binlog(thd);
|
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;
|
goto send_result;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
|
DBUG_PRINT("admin", ("calling operator_func '%s'", operator_name));
|
||||||
@ -4296,7 +4303,6 @@ send_result_message:
|
|||||||
|
|
||||||
case HA_ADMIN_TRY_ALTER:
|
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
|
This is currently used only by InnoDB. ha_innobase::optimize() answers
|
||||||
"try with alter", so here we close the table, do an ALTER TABLE,
|
"try with alter", so here we close the table, do an ALTER TABLE,
|
||||||
@ -4308,10 +4314,16 @@ send_result_message:
|
|||||||
*save_next_global= table->next_global;
|
*save_next_global= table->next_global;
|
||||||
table->next_local= table->next_global= 0;
|
table->next_local= table->next_global= 0;
|
||||||
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
tmp_disable_binlog(thd); // binlogging is done by caller if wanted
|
||||||
thd->net.no_send_ok= TRUE;
|
|
||||||
result_code= mysql_recreate_table(thd, table);
|
result_code= mysql_recreate_table(thd, table);
|
||||||
thd->net.no_send_ok= save_no_send_ok;
|
|
||||||
reenable_binlog(thd);
|
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);
|
ha_autocommit_or_rollback(thd, 0);
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
if (!result_code) // recreation went ok
|
if (!result_code) // recreation went ok
|
||||||
@ -4322,9 +4334,10 @@ send_result_message:
|
|||||||
}
|
}
|
||||||
if (result_code) // either mysql_recreate_table or analyze failed
|
if (result_code) // either mysql_recreate_table or analyze failed
|
||||||
{
|
{
|
||||||
const char *err_msg;
|
DBUG_ASSERT(thd->is_error());
|
||||||
if ((err_msg= thd->net.last_error))
|
if (thd->is_error())
|
||||||
{
|
{
|
||||||
|
const char *err_msg= thd->main_da.message();
|
||||||
if (!thd->vio_ok())
|
if (!thd->vio_ok())
|
||||||
{
|
{
|
||||||
sql_print_error(err_msg);
|
sql_print_error(err_msg);
|
||||||
@ -4340,6 +4353,7 @@ send_result_message:
|
|||||||
protocol->store(table_name, system_charset_info);
|
protocol->store(table_name, system_charset_info);
|
||||||
protocol->store(operator_name, system_charset_info);
|
protocol->store(operator_name, system_charset_info);
|
||||||
}
|
}
|
||||||
|
thd->clear_error();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
|
result_code= result_code ? HA_ADMIN_FAILED : HA_ADMIN_OK;
|
||||||
|
@ -1696,7 +1696,11 @@ void multi_update::send_error(uint errcode,const char *err)
|
|||||||
{
|
{
|
||||||
/* First send error what ever it is ... */
|
/* First send error what ever it is ... */
|
||||||
my_error(errcode, MYF(0), err);
|
my_error(errcode, MYF(0), err);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void multi_update::abort()
|
||||||
|
{
|
||||||
/* the error was handled or nothing deleted and no side effects return */
|
/* the error was handled or nothing deleted and no side effects return */
|
||||||
if (error_handled ||
|
if (error_handled ||
|
||||||
!thd->transaction.stmt.modified_non_trans_table && !updated)
|
!thd->transaction.stmt.modified_non_trans_table && !updated)
|
||||||
|
25
sql/table.cc
25
sql/table.cc
@ -3275,31 +3275,32 @@ bool TABLE_LIST::prep_check_option(THD *thd, uint8 check_opt_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/**
|
||||||
Hide errors which show view underlying table information
|
Hide errors which show view underlying table information
|
||||||
|
|
||||||
SYNOPSIS
|
@param[in,out] thd thread handler
|
||||||
TABLE_LIST::hide_view_error()
|
|
||||||
thd thread handler
|
|
||||||
|
|
||||||
|
@pre This method can be called only if there is an error.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void TABLE_LIST::hide_view_error(THD *thd)
|
void TABLE_LIST::hide_view_error(THD *thd)
|
||||||
{
|
{
|
||||||
/* Hide "Unknown column" or "Unknown function" error */
|
/* Hide "Unknown column" or "Unknown function" error */
|
||||||
if (thd->net.last_errno == ER_BAD_FIELD_ERROR ||
|
DBUG_ASSERT(thd->is_error());
|
||||||
thd->net.last_errno == ER_SP_DOES_NOT_EXIST ||
|
|
||||||
thd->net.last_errno == ER_PROCACCESS_DENIED_ERROR ||
|
if (thd->main_da.sql_errno() == ER_BAD_FIELD_ERROR ||
|
||||||
thd->net.last_errno == ER_COLUMNACCESS_DENIED_ERROR ||
|
thd->main_da.sql_errno() == ER_SP_DOES_NOT_EXIST ||
|
||||||
thd->net.last_errno == ER_TABLEACCESS_DENIED_ERROR ||
|
thd->main_da.sql_errno() == ER_PROCACCESS_DENIED_ERROR ||
|
||||||
thd->net.last_errno == ER_TABLE_NOT_LOCKED ||
|
thd->main_da.sql_errno() == ER_COLUMNACCESS_DENIED_ERROR ||
|
||||||
thd->net.last_errno == ER_NO_SUCH_TABLE)
|
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();
|
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);
|
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();
|
TABLE_LIST *top= top_table();
|
||||||
thd->clear_error();
|
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))
|
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 "
|
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 */
|
/* We will try emulate that everything is ok */
|
||||||
return_val= time_zone_tables_exist= 0;
|
return_val= time_zone_tables_exist= 0;
|
||||||
goto end_with_setting_default_tz;
|
goto end_with_setting_default_tz;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user