mirror of
https://github.com/MariaDB/server.git
synced 2025-01-15 19:42:28 +01:00
Added more descriptive error message of why statement was automaticly dropped
Print information if net_clear() skipped bytes (As this otherwise hides critical timeing bugs) Added DBUG_ASSERT if we get packets out of order mysql_change_user() could on error send multiple packets, which caused mysql_client_test to randomly fail include/errmsg.h: Added more descriptive error message of why statement was automaticly dropped libmysql/client_settings.h: Added more descriptive error message of why statement was automaticly dropped libmysql/errmsg.c: Added more descriptive error message of why statement was automaticly dropped libmysql/libmysql.c: Added more descriptive error message of why statement was automaticly dropped sql-common/client.c: Added more descriptive error message of why statement was automaticly dropped sql/net_serv.cc: Print information if net_clear() skipped bytes (As this otherwise hides critical timeing bugs) Added DBUG_ASSERT if we get packets out of order sql/sql_class.cc: We need to set killed to NOT_KILLED after cleanup() if we want to continue using THD (If not, the connection will be closed after the current stmt) sql/sql_parse.cc: mysql_change_user() could on error send multiple packets, which caused mysql_client_test to randomly fail tests/mysql_client_test.c: More DBUG information Better usage of --silent Always print 'OK' the same way. Disable test_bug17667 if run outside of mysql-test-run
This commit is contained in:
parent
2671ba0230
commit
f3efb3dcfa
9 changed files with 112 additions and 73 deletions
|
@ -95,6 +95,7 @@ extern const char *client_errors[]; /* Error messages */
|
|||
#define CR_NO_RESULT_SET 2053
|
||||
#define CR_NOT_IMPLEMENTED 2054
|
||||
#define CR_SERVER_LOST_EXTENDED 2055
|
||||
#define CR_ERROR_LAST /*Copy last error nr:*/ 2055
|
||||
#define CR_STMT_CLOSED 2056
|
||||
#define CR_ERROR_LAST /*Copy last error nr:*/ 2056
|
||||
/* Add error numbers before CR_ERROR_LAST and change it accordingly. */
|
||||
|
||||
|
|
|
@ -41,7 +41,7 @@ my_bool handle_local_infile(MYSQL *mysql, const char *net_filename);
|
|||
|
||||
void mysql_read_default_options(struct st_mysql_options *options,
|
||||
const char *filename,const char *group);
|
||||
void mysql_detach_stmt_list(LIST **stmt_list);
|
||||
void mysql_detach_stmt_list(LIST **stmt_list, const char *func_name);
|
||||
MYSQL *
|
||||
cli_mysql_real_connect(MYSQL *mysql,const char *host, const char *user,
|
||||
const char *passwd, const char *db,
|
||||
|
|
|
@ -83,6 +83,7 @@ const char *client_errors[]=
|
|||
"Attempt to read a row while there is no result set associated with the statement",
|
||||
"This feature is not implemented yet",
|
||||
"Lost connection to MySQL server at '%s', system error: %d",
|
||||
"Statement closed indirectly because of a preceeding %s() call",
|
||||
""
|
||||
};
|
||||
|
||||
|
@ -147,6 +148,7 @@ const char *client_errors[]=
|
|||
"Attempt to read a row while there is no result set associated with the statement",
|
||||
"This feature is not implemented yet",
|
||||
"Lost connection to MySQL server at '%s', system error: %d",
|
||||
"Statement closed indirectly because of a preceeding %s() call",
|
||||
""
|
||||
};
|
||||
|
||||
|
@ -209,6 +211,7 @@ const char *client_errors[]=
|
|||
"Attempt to read a row while there is no result set associated with the statement",
|
||||
"This feature is not implemented yet",
|
||||
"Lost connection to MySQL server at '%s', system error: %d",
|
||||
"Statement closed indirectly because of a preceeding %s() call",
|
||||
""
|
||||
};
|
||||
#endif
|
||||
|
|
|
@ -715,7 +715,7 @@ my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
|
|||
The server will close all statements no matter was the attempt
|
||||
to change user successful or not.
|
||||
*/
|
||||
mysql_detach_stmt_list(&mysql->stmts);
|
||||
mysql_detach_stmt_list(&mysql->stmts, "mysql_change_user");
|
||||
if (rc == 0)
|
||||
{
|
||||
/* Free old connect information */
|
||||
|
@ -2872,7 +2872,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
|
|||
|
||||
if (!mysql)
|
||||
{
|
||||
set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate);
|
||||
/* Error is already set in mysql_detatch_stmt_list */
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
|
|
|
@ -2596,24 +2596,32 @@ static void mysql_close_free(MYSQL *mysql)
|
|||
SYNOPSYS
|
||||
mysql_detach_stmt_list()
|
||||
stmt_list pointer to mysql->stmts
|
||||
func_name name of calling function
|
||||
|
||||
NOTE
|
||||
There is similar code in mysql_reconnect(), so changes here
|
||||
should also be reflected there.
|
||||
*/
|
||||
|
||||
void mysql_detach_stmt_list(LIST **stmt_list __attribute__((unused)))
|
||||
void mysql_detach_stmt_list(LIST **stmt_list __attribute__((unused)),
|
||||
const char *func_name)
|
||||
{
|
||||
#ifdef MYSQL_CLIENT
|
||||
/* Reset connection handle in all prepared statements. */
|
||||
LIST *element= *stmt_list;
|
||||
char buff[MYSQL_ERRMSG_SIZE];
|
||||
DBUG_ENTER("mysql_detach_stmt_list");
|
||||
|
||||
my_snprintf(buff, sizeof(buff)-1, ER(CR_STMT_CLOSED), func_name);
|
||||
for (; element; element= element->next)
|
||||
{
|
||||
MYSQL_STMT *stmt= (MYSQL_STMT *) element->data;
|
||||
set_stmt_errmsg(stmt, buff, CR_STMT_CLOSED, unknown_sqlstate);
|
||||
stmt->mysql= 0;
|
||||
/* No need to call list_delete for statement here */
|
||||
}
|
||||
*stmt_list= 0;
|
||||
DBUG_VOID_RETURN;
|
||||
#endif /* MYSQL_CLIENT */
|
||||
}
|
||||
|
||||
|
@ -2634,7 +2642,7 @@ void STDCALL mysql_close(MYSQL *mysql)
|
|||
}
|
||||
mysql_close_free_options(mysql);
|
||||
mysql_close_free(mysql);
|
||||
mysql_detach_stmt_list(&mysql->stmts);
|
||||
mysql_detach_stmt_list(&mysql->stmts, "mysql_close");
|
||||
#ifndef TO_BE_DELETED
|
||||
/* free/close slave list */
|
||||
if (mysql->rpl_pivot)
|
||||
|
|
|
@ -298,7 +298,7 @@ void net_clear(NET *net, my_bool clear_buffer)
|
|||
{
|
||||
DBUG_PRINT("info",("skipped %d bytes from file: %s",
|
||||
count, vio_description(net->vio)));
|
||||
#if defined(EXTRA_DEBUG) && (MYSQL_VERSION_ID < 50100)
|
||||
#if defined(EXTRA_DEBUG)
|
||||
fprintf(stderr,"Error: net_clear() skipped %d bytes from file: %s\n",
|
||||
count, vio_description(net->vio));
|
||||
#endif
|
||||
|
@ -903,9 +903,12 @@ my_real_read(NET *net, ulong *complen)
|
|||
(int) net->buff[net->where_b + 3],
|
||||
net->pkt_nr));
|
||||
#ifdef EXTRA_DEBUG
|
||||
fflush(stdout);
|
||||
fprintf(stderr,"Error: Packets out of order (Found: %d, expected %d)\n",
|
||||
(int) net->buff[net->where_b + 3],
|
||||
(uint) (uchar) net->pkt_nr);
|
||||
fflush(stderr);
|
||||
DBUG_ASSERT(0);
|
||||
#endif
|
||||
}
|
||||
len= packet_error;
|
||||
|
|
|
@ -420,6 +420,7 @@ void THD::init_for_queries()
|
|||
void THD::change_user(void)
|
||||
{
|
||||
cleanup();
|
||||
killed= NOT_KILLED;
|
||||
cleanup_done= 0;
|
||||
init();
|
||||
stmt_map.reset();
|
||||
|
|
|
@ -784,7 +784,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
char *save_db;
|
||||
uint passwd_len= (thd->client_capabilities & CLIENT_SECURE_CONNECTION ?
|
||||
*passwd++ : strlen(passwd));
|
||||
uint dummy_errors, save_db_length, db_length, res;
|
||||
uint dummy_errors, save_db_length, db_length;
|
||||
int res;
|
||||
Security_context save_security_ctx= *thd->security_ctx;
|
||||
USER_CONN *save_user_connect;
|
||||
|
||||
|
@ -831,6 +832,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
|
|||
/* authentication failure, we shall restore old user */
|
||||
if (res > 0)
|
||||
my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
|
||||
else
|
||||
thd->clear_error(); // Error already sent to client
|
||||
x_free(thd->security_ctx->user);
|
||||
*thd->security_ctx= save_security_ctx;
|
||||
thd->user_connect= save_user_connect;
|
||||
|
|
|
@ -83,6 +83,7 @@ struct my_tests_st
|
|||
};
|
||||
|
||||
#define myheader(str) \
|
||||
DBUG_PRINT("test", ("name: %s", str)); \
|
||||
if (opt_silent < 2) \
|
||||
{ \
|
||||
fprintf(stdout, "\n\n#####################################\n"); \
|
||||
|
@ -90,7 +91,9 @@ if (opt_silent < 2) \
|
|||
opt_count, str); \
|
||||
fprintf(stdout, " \n#####################################\n"); \
|
||||
}
|
||||
|
||||
#define myheader_r(str) \
|
||||
DBUG_PRINT("test", ("name: %s", str)); \
|
||||
if (!opt_silent) \
|
||||
{ \
|
||||
fprintf(stdout, "\n\n#####################################\n"); \
|
||||
|
@ -298,7 +301,7 @@ static void client_connect(ulong flag)
|
|||
mysql->reconnect= 1;
|
||||
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, " OK");
|
||||
fprintf(stdout, "OK");
|
||||
|
||||
/* set AUTOCOMMIT to ON*/
|
||||
mysql_autocommit(mysql, TRUE);
|
||||
|
@ -321,7 +324,7 @@ static void client_connect(ulong flag)
|
|||
have_innodb= check_have_innodb(mysql);
|
||||
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, " OK");
|
||||
fprintf(stdout, "OK");
|
||||
}
|
||||
|
||||
|
||||
|
@ -341,12 +344,13 @@ static void client_disconnect()
|
|||
|
||||
mysql_query(mysql, query);
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, " OK");
|
||||
fprintf(stdout, "OK");
|
||||
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, "\n closing the connection ...");
|
||||
mysql_close(mysql);
|
||||
fprintf(stdout, " OK\n");
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, "OK\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2498,7 +2502,7 @@ static void test_ps_query_cache()
|
|||
exit(1);
|
||||
}
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, " OK");
|
||||
fprintf(stdout, "OK");
|
||||
mysql= lmysql;
|
||||
}
|
||||
|
||||
|
@ -4940,7 +4944,7 @@ static void test_stmt_close()
|
|||
}
|
||||
lmysql->reconnect= 1;
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, " OK");
|
||||
fprintf(stdout, "OK");
|
||||
|
||||
|
||||
/* set AUTOCOMMIT to ON*/
|
||||
|
@ -7471,7 +7475,7 @@ static void test_prepare_grant()
|
|||
}
|
||||
lmysql->reconnect= 1;
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, " OK");
|
||||
fprintf(stdout, "OK");
|
||||
|
||||
mysql= lmysql;
|
||||
rc= mysql_query(mysql, "INSERT INTO test_grant VALUES(NULL)");
|
||||
|
@ -7932,7 +7936,7 @@ static void test_drop_temp()
|
|||
}
|
||||
lmysql->reconnect= 1;
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, " OK");
|
||||
fprintf(stdout, "OK");
|
||||
|
||||
mysql= lmysql;
|
||||
rc= mysql_query(mysql, "INSERT INTO t1 VALUES(10, 'C')");
|
||||
|
@ -12018,16 +12022,24 @@ static void test_bug5315()
|
|||
stmt= mysql_stmt_init(mysql);
|
||||
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
|
||||
DIE_UNLESS(rc == 0);
|
||||
if (!opt_silent)
|
||||
printf("Excuting mysql_change_user\n");
|
||||
mysql_change_user(mysql, opt_user, opt_password, current_db);
|
||||
if (!opt_silent)
|
||||
printf("Excuting mysql_stmt_execute\n");
|
||||
rc= mysql_stmt_execute(stmt);
|
||||
DIE_UNLESS(rc != 0);
|
||||
if (rc)
|
||||
{
|
||||
if (!opt_silent)
|
||||
printf("Got error (as expected):\n%s", mysql_stmt_error(stmt));
|
||||
printf("Got error (as expected): '%s'\n", mysql_stmt_error(stmt));
|
||||
}
|
||||
/* check that connection is OK */
|
||||
if (!opt_silent)
|
||||
printf("Excuting mysql_stmt_close\n");
|
||||
mysql_stmt_close(stmt);
|
||||
if (!opt_silent)
|
||||
printf("Excuting mysql_stmt_init\n");
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
|
||||
DIE_UNLESS(rc == 0);
|
||||
|
@ -12716,6 +12728,7 @@ static void test_rewind(void)
|
|||
|
||||
/* retreive all result sets till we are at the end */
|
||||
while(!mysql_stmt_fetch(stmt))
|
||||
if (!opt_silent)
|
||||
printf("fetched result:%ld\n", Data);
|
||||
|
||||
DIE_UNLESS(rc != MYSQL_NO_DATA);
|
||||
|
@ -12726,6 +12739,7 @@ static void test_rewind(void)
|
|||
/* now we should be able to fetch the results again */
|
||||
/* but mysql_stmt_fetch returns MYSQL_NO_DATA */
|
||||
while(!(rc= mysql_stmt_fetch(stmt)))
|
||||
if (!opt_silent)
|
||||
printf("fetched result after seek:%ld\n", Data);
|
||||
|
||||
DIE_UNLESS(rc == MYSQL_NO_DATA);
|
||||
|
@ -13276,7 +13290,7 @@ static void test_bug8378()
|
|||
exit(1);
|
||||
}
|
||||
if (!opt_silent)
|
||||
fprintf(stdout, " OK");
|
||||
fprintf(stdout, "OK");
|
||||
|
||||
len= mysql_real_escape_string(mysql, out, TEST_BUG8378_IN, 4);
|
||||
|
||||
|
@ -13445,7 +13459,8 @@ static void test_bug9520()
|
|||
|
||||
DIE_UNLESS(rc == MYSQL_NO_DATA);
|
||||
|
||||
printf("Fetched %d rows\n", row_count);
|
||||
if (!opt_silent)
|
||||
printf("Fetched %d rows\n", row_count);
|
||||
DBUG_ASSERT(row_count == 3);
|
||||
|
||||
mysql_stmt_close(stmt);
|
||||
|
@ -15345,8 +15360,28 @@ static void test_bug17667()
|
|||
|
||||
myheader("test_bug17667");
|
||||
|
||||
master_log_filename = (char *) malloc(strlen(opt_vardir) + strlen("/log/master.log") + 1);
|
||||
strxmov(master_log_filename, opt_vardir, "/log/master.log", NullS);
|
||||
if (!opt_silent)
|
||||
printf("Opening '%s'\n", master_log_filename);
|
||||
log_file= my_fopen(master_log_filename, (int) (O_RDONLY | O_BINARY), MYF(0));
|
||||
free(master_log_filename);
|
||||
|
||||
if (log_file == NULL)
|
||||
{
|
||||
if (!opt_silent)
|
||||
{
|
||||
printf("Could not find the log file, VARDIR/log/master.log, so "
|
||||
"test_bug17667 is not run.\n"
|
||||
"Run test from the mysql-test/mysql-test-run* program to set up "
|
||||
"correct environment for this test.\n\n");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
for (statement_cursor= statements; statement_cursor->buffer != NULL;
|
||||
statement_cursor++) {
|
||||
statement_cursor++)
|
||||
{
|
||||
if (statement_cursor->qt == QT_NORMAL)
|
||||
{
|
||||
/* Run statement as normal query */
|
||||
|
@ -15357,10 +15392,10 @@ static void test_bug17667()
|
|||
else if (statement_cursor->qt == QT_PREPARED)
|
||||
{
|
||||
/*
|
||||
Run as prepared statement
|
||||
Run as prepared statement
|
||||
|
||||
NOTE! All these queries should be in the log twice,
|
||||
one time for prepare and one time for execute
|
||||
NOTE! All these queries should be in the log twice,
|
||||
one time for prepare and one time for execute
|
||||
*/
|
||||
stmt= mysql_stmt_init(mysql);
|
||||
|
||||
|
@ -15383,66 +15418,49 @@ static void test_bug17667()
|
|||
rc= mysql_query(mysql, "flush logs");
|
||||
myquery(rc);
|
||||
|
||||
master_log_filename = (char *) malloc(strlen(opt_vardir) + strlen("/log/master.log") + 1);
|
||||
strcpy(master_log_filename, opt_vardir);
|
||||
strcat(master_log_filename, "/log/master.log");
|
||||
printf("Opening '%s'\n", master_log_filename);
|
||||
log_file= my_fopen(master_log_filename, (int) (O_RDONLY | O_BINARY), MYF(MY_WME));
|
||||
free(master_log_filename);
|
||||
for (statement_cursor= statements; statement_cursor->buffer != NULL;
|
||||
statement_cursor++)
|
||||
{
|
||||
int expected_hits= 1, hits= 0;
|
||||
char line_buffer[MAX_TEST_QUERY_LENGTH*2];
|
||||
/* more than enough room for the query and some marginalia. */
|
||||
|
||||
if (log_file != NULL) {
|
||||
/* Prepared statments always occurs twice in log */
|
||||
if (statement_cursor->qt == QT_PREPARED)
|
||||
expected_hits++;
|
||||
|
||||
for (statement_cursor= statements; statement_cursor->buffer != NULL;
|
||||
statement_cursor++) {
|
||||
int expected_hits= 1, hits= 0;
|
||||
char line_buffer[MAX_TEST_QUERY_LENGTH*2];
|
||||
/* more than enough room for the query and some marginalia. */
|
||||
|
||||
/* Prepared statments always occurs twice in log */
|
||||
if (statement_cursor->qt == QT_PREPARED)
|
||||
expected_hits++;
|
||||
|
||||
/* Loop until we found expected number of log entries */
|
||||
/* Loop until we found expected number of log entries */
|
||||
do {
|
||||
/* Loop until statement is found in log */
|
||||
do {
|
||||
/* Loop until statement is found in log */
|
||||
do {
|
||||
memset(line_buffer, '/', MAX_TEST_QUERY_LENGTH*2);
|
||||
memset(line_buffer, '/', MAX_TEST_QUERY_LENGTH*2);
|
||||
|
||||
if(fgets(line_buffer, MAX_TEST_QUERY_LENGTH*2, log_file) == NULL)
|
||||
{
|
||||
/* If fgets returned NULL, it indicates either error or EOF */
|
||||
if (feof(log_file))
|
||||
DIE("Found EOF before all statements where found");
|
||||
if(fgets(line_buffer, MAX_TEST_QUERY_LENGTH*2, log_file) == NULL)
|
||||
{
|
||||
/* If fgets returned NULL, it indicates either error or EOF */
|
||||
if (feof(log_file))
|
||||
DIE("Found EOF before all statements where found");
|
||||
|
||||
fprintf(stderr, "Got error %d while reading from file\n",
|
||||
ferror(log_file));
|
||||
DIE("Read error");
|
||||
}
|
||||
fprintf(stderr, "Got error %d while reading from file\n",
|
||||
ferror(log_file));
|
||||
DIE("Read error");
|
||||
}
|
||||
|
||||
} while (my_memmem(line_buffer, MAX_TEST_QUERY_LENGTH*2,
|
||||
statement_cursor->buffer,
|
||||
statement_cursor->length) == NULL);
|
||||
hits++;
|
||||
} while (hits < expected_hits);
|
||||
} while (my_memmem(line_buffer, MAX_TEST_QUERY_LENGTH*2,
|
||||
statement_cursor->buffer,
|
||||
statement_cursor->length) == NULL);
|
||||
hits++;
|
||||
} while (hits < expected_hits);
|
||||
|
||||
if (!opt_silent)
|
||||
printf("Found statement starting with \"%s\"\n",
|
||||
statement_cursor->buffer);
|
||||
}
|
||||
}
|
||||
|
||||
if (!opt_silent)
|
||||
printf("success. All queries found intact in the log.\n");
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "Could not find the log file, VARDIR/log/master.log, so "
|
||||
"test_bug17667 is \ninconclusive. Run test from the "
|
||||
"mysql-test/mysql-test-run* program \nto set up the correct "
|
||||
"environment for this test.\n\n");
|
||||
}
|
||||
|
||||
if (log_file != NULL)
|
||||
my_fclose(log_file, MYF(0));
|
||||
|
||||
my_fclose(log_file, MYF(0));
|
||||
}
|
||||
|
||||
|
||||
|
@ -16008,12 +16026,14 @@ static void test_bug21635()
|
|||
for (i= 0; i < field_count; ++i)
|
||||
{
|
||||
field= mysql_fetch_field_direct(result, i);
|
||||
printf("%s -> %s ... ", expr[i * 2], field->name);
|
||||
if (!opt_silent)
|
||||
printf("%s -> %s ... ", expr[i * 2], field->name);
|
||||
fflush(stdout);
|
||||
DIE_UNLESS(field->db[0] == 0 && field->org_table[0] == 0 &&
|
||||
field->table[0] == 0 && field->org_name[0] == 0);
|
||||
DIE_UNLESS(strcmp(field->name, expr[i * 2 + 1]) == 0);
|
||||
puts("OK");
|
||||
if (!opt_silent)
|
||||
puts("OK");
|
||||
}
|
||||
|
||||
mysql_free_result(result);
|
||||
|
|
Loading…
Reference in a new issue