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
parent 4a065f5f
Branches unavailable
Tags unavailable
No related merge requests found
......@@ -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. */
/* Loop until we found expected number of log entries */
do {
/* Loop until statement is found in log */
do {
memset(line_buffer, '/', MAX_TEST_QUERY_LENGTH*2);
/* Prepared statments always occurs twice in log */
if (statement_cursor->qt == QT_PREPARED)
expected_hits++;
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");
/* Loop until we found expected number of log entries */
do {
/* Loop until statement is found in log */
do {
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");
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);
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);
if (!opt_silent)
printf("Found statement starting with \"%s\"\n",
statement_cursor->buffer);
}
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));
if (!opt_silent)
printf("success. All queries found intact in the log.\n");
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);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment