mirror of
https://github.com/MariaDB/server.git
synced 2025-07-29 05:21:33 +03:00
client/mysqltest.c
added send/reap/dirty_close include/mysql.h mysql_send_query()/mysql_reap_query() libmysql/libmysql.c mysql_send_query()/mysql_reap_query() mysys/my_vsnprintf.c fixed critical bug that codedumped when connection aborted sql/sql_parse.cc 0 mysql-test/r/dirty-close.result New BitKeeper file ``mysql-test/r/dirty-close.result'' mysql-test/t/dirty-close.test New BitKeeper file ``mysql-test/t/dirty-close.test'' client/mysqltest.c: added send/reap/dirty_close include/mysql.h: mysql_send_query()/mysql_reap_query() libmysql/libmysql.c: mysql_send_query()/mysql_reap_query() mysys/my_vsnprintf.c: fixed critical bug that codedumped when connection aborted sql/sql_parse.cc: 0
This commit is contained in:
@ -61,6 +61,7 @@
|
|||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
#include <violite.h>
|
||||||
|
|
||||||
#define MAX_QUERY 65536
|
#define MAX_QUERY 65536
|
||||||
#define PAD_SIZE 128
|
#define PAD_SIZE 128
|
||||||
@ -71,6 +72,8 @@
|
|||||||
#define MIN_VAR_ALLOC 32
|
#define MIN_VAR_ALLOC 32
|
||||||
#define BLOCK_STACK_DEPTH 32
|
#define BLOCK_STACK_DEPTH 32
|
||||||
#define MAX_EXPECTED_ERRORS 10
|
#define MAX_EXPECTED_ERRORS 10
|
||||||
|
#define QUERY_SEND 1
|
||||||
|
#define QUERY_REAP 2
|
||||||
|
|
||||||
static int record = 0, verbose = 0, silent = 0, opt_sleep=0;
|
static int record = 0, verbose = 0, silent = 0, opt_sleep=0;
|
||||||
static char *db = 0, *pass=0;
|
static char *db = 0, *pass=0;
|
||||||
@ -147,14 +150,14 @@ struct st_query
|
|||||||
Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE,
|
Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE,
|
||||||
Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK,
|
Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK,
|
||||||
Q_SYSTEM, Q_RESULT, Q_REQUIRE, Q_SAVE_MASTER_POS,
|
Q_SYSTEM, Q_RESULT, Q_REQUIRE, Q_SAVE_MASTER_POS,
|
||||||
Q_SYNC_WITH_MASTER, Q_ERROR,
|
Q_SYNC_WITH_MASTER, Q_ERROR, Q_SEND, Q_REAP, Q_DIRTY_CLOSE,
|
||||||
Q_UNKNOWN, Q_COMMENT, Q_COMMENT_WITH_COMMAND} type;
|
Q_UNKNOWN, Q_COMMENT, Q_COMMENT_WITH_COMMAND} type;
|
||||||
};
|
};
|
||||||
|
|
||||||
const char *command_names[] = {
|
const char *command_names[] = {
|
||||||
"connection", "query","connect","sleep","inc","dec","source","disconnect",
|
"connection", "query","connect","sleep","inc","dec","source","disconnect",
|
||||||
"let","echo","while","end","system","result", "require", "save_master_pos",
|
"let","echo","while","end","system","result", "require", "save_master_pos",
|
||||||
"sync_with_master", "error", 0
|
"sync_with_master", "error", "send", "reap", "dirty_close", 0
|
||||||
};
|
};
|
||||||
|
|
||||||
TYPELIB command_typelib= {array_elements(command_names),"",
|
TYPELIB command_typelib= {array_elements(command_names),"",
|
||||||
@ -661,6 +664,15 @@ int close_connection(struct st_query* q)
|
|||||||
{
|
{
|
||||||
if (!strcmp(con->name, name))
|
if (!strcmp(con->name, name))
|
||||||
{
|
{
|
||||||
|
if(q->type == Q_DIRTY_CLOSE)
|
||||||
|
{
|
||||||
|
if(con->mysql.net.vio)
|
||||||
|
{
|
||||||
|
vio_delete(con->mysql.net.vio);
|
||||||
|
con->mysql.net.vio = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
mysql_close(&con->mysql);
|
mysql_close(&con->mysql);
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
}
|
}
|
||||||
@ -1211,7 +1223,7 @@ void reject_dump(const char* record_file, char* buf, int size)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
int run_query(MYSQL* mysql, struct st_query* q)
|
int run_query(MYSQL* mysql, struct st_query* q, int flags)
|
||||||
{
|
{
|
||||||
MYSQL_RES* res = 0;
|
MYSQL_RES* res = 0;
|
||||||
MYSQL_FIELD* fields;
|
MYSQL_FIELD* fields;
|
||||||
@ -1220,6 +1232,7 @@ int run_query(MYSQL* mysql, struct st_query* q)
|
|||||||
unsigned long* lengths;
|
unsigned long* lengths;
|
||||||
char* val;
|
char* val;
|
||||||
int len;
|
int len;
|
||||||
|
int q_error = 0 ;
|
||||||
DYNAMIC_STRING *ds;
|
DYNAMIC_STRING *ds;
|
||||||
DYNAMIC_STRING ds_tmp;
|
DYNAMIC_STRING ds_tmp;
|
||||||
DBUG_ENTER("run_query");
|
DBUG_ENTER("run_query");
|
||||||
@ -1231,8 +1244,14 @@ int run_query(MYSQL* mysql, struct st_query* q)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
ds= &ds_res;
|
ds= &ds_res;
|
||||||
|
|
||||||
if (mysql_query(mysql, q->query))
|
if((flags & QUERY_SEND) &&
|
||||||
|
(q_error = mysql_send_query(mysql, q->query)))
|
||||||
|
die("At line %u: unable to send query '%s'", start_lineno, q->query);
|
||||||
|
if(!(flags & QUERY_REAP))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (mysql_reap_query(mysql))
|
||||||
{
|
{
|
||||||
if (q->require_file)
|
if (q->require_file)
|
||||||
abort_not_supported_test();
|
abort_not_supported_test();
|
||||||
@ -1416,7 +1435,9 @@ int main(int argc, char** argv)
|
|||||||
switch (q->type) {
|
switch (q->type) {
|
||||||
case Q_CONNECT: do_connect(q); break;
|
case Q_CONNECT: do_connect(q); break;
|
||||||
case Q_CONNECTION: select_connection(q); break;
|
case Q_CONNECTION: select_connection(q); break;
|
||||||
case Q_DISCONNECT: close_connection(q); break;
|
case Q_DISCONNECT:
|
||||||
|
case Q_DIRTY_CLOSE:
|
||||||
|
close_connection(q); break;
|
||||||
case Q_SOURCE: do_source(q); break;
|
case Q_SOURCE: do_source(q); break;
|
||||||
case Q_SLEEP: do_sleep(q); break;
|
case Q_SLEEP: do_sleep(q); break;
|
||||||
case Q_INC: do_inc(q); break;
|
case Q_INC: do_inc(q); break;
|
||||||
@ -1425,15 +1446,25 @@ int main(int argc, char** argv)
|
|||||||
case Q_SYSTEM: do_system(q); break;
|
case Q_SYSTEM: do_system(q); break;
|
||||||
case Q_LET: do_let(q); break;
|
case Q_LET: do_let(q); break;
|
||||||
case Q_QUERY:
|
case Q_QUERY:
|
||||||
|
case Q_REAP:
|
||||||
{
|
{
|
||||||
|
int flags = QUERY_REAP;
|
||||||
|
if(q->type == Q_QUERY)
|
||||||
|
flags |= QUERY_SEND;
|
||||||
|
|
||||||
if (save_file[0])
|
if (save_file[0])
|
||||||
{
|
{
|
||||||
strmov(q->record_file,save_file);
|
strmov(q->record_file,save_file);
|
||||||
q->require_file=require_file;
|
q->require_file=require_file;
|
||||||
save_file[0]=0;
|
save_file[0]=0;
|
||||||
}
|
}
|
||||||
error |= run_query(&cur_con->mysql, q); break;
|
error |= run_query(&cur_con->mysql, q, QUERY_SEND|QUERY_REAP);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
case Q_SEND:
|
||||||
|
q->query += q->first_word_len;
|
||||||
|
error |= run_query(&cur_con->mysql, q, QUERY_SEND);
|
||||||
|
break;
|
||||||
case Q_RESULT:
|
case Q_RESULT:
|
||||||
get_file_name(save_file,q);
|
get_file_name(save_file,q);
|
||||||
require_file=0;
|
require_file=0;
|
||||||
|
@ -229,8 +229,12 @@ MYSQL * STDCALL mysql_real_connect(MYSQL *mysql, const char *host,
|
|||||||
void STDCALL mysql_close(MYSQL *sock);
|
void STDCALL mysql_close(MYSQL *sock);
|
||||||
int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
|
int STDCALL mysql_select_db(MYSQL *mysql, const char *db);
|
||||||
int STDCALL mysql_query(MYSQL *mysql, const char *q);
|
int STDCALL mysql_query(MYSQL *mysql, const char *q);
|
||||||
|
int STDCALL mysql_send_query(MYSQL *mysql, const char *q);
|
||||||
|
int STDCALL mysql_reap_query(MYSQL *mysql);
|
||||||
int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
|
int STDCALL mysql_real_query(MYSQL *mysql, const char *q,
|
||||||
unsigned int length);
|
unsigned int length);
|
||||||
|
int STDCALL mysql_real_send_query(MYSQL *mysql, const char *q,
|
||||||
|
unsigned int len);
|
||||||
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
|
int STDCALL mysql_create_db(MYSQL *mysql, const char *DB);
|
||||||
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
|
int STDCALL mysql_drop_db(MYSQL *mysql, const char *DB);
|
||||||
int STDCALL mysql_shutdown(MYSQL *mysql);
|
int STDCALL mysql_shutdown(MYSQL *mysql);
|
||||||
|
@ -1708,6 +1708,71 @@ mysql_query(MYSQL *mysql, const char *query)
|
|||||||
return mysql_real_query(mysql,query, (uint) strlen(query));
|
return mysql_real_query(mysql,query, (uint) strlen(query));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int STDCALL
|
||||||
|
mysql_send_query(MYSQL* mysql, const char* query)
|
||||||
|
{
|
||||||
|
return mysql_real_send_query(mysql, query, strlen(query));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* send the query and return so we can do something else */
|
||||||
|
/* needs to be followed by mysql_reap_query() when we want to
|
||||||
|
finish processing it
|
||||||
|
*/
|
||||||
|
int STDCALL
|
||||||
|
mysql_real_send_query(MYSQL* mysql, const char* query, uint len)
|
||||||
|
{
|
||||||
|
return simple_command(mysql, COM_QUERY, query, len, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
int STDCALL
|
||||||
|
mysql_reap_query(MYSQL* mysql)
|
||||||
|
{
|
||||||
|
uchar *pos;
|
||||||
|
ulong field_count;
|
||||||
|
MYSQL_DATA *fields;
|
||||||
|
uint len;
|
||||||
|
DBUG_ENTER("mysql_reap_query");
|
||||||
|
DBUG_PRINT("enter",("handle: %lx",mysql));
|
||||||
|
if((len = net_safe_read(mysql)) == packet_error)
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
free_old_query(mysql); /* Free old result */
|
||||||
|
get_info:
|
||||||
|
pos=(uchar*) mysql->net.read_pos;
|
||||||
|
if ((field_count= net_field_length(&pos)) == 0)
|
||||||
|
{
|
||||||
|
mysql->affected_rows= net_field_length_ll(&pos);
|
||||||
|
mysql->insert_id= net_field_length_ll(&pos);
|
||||||
|
if (mysql->server_capabilities & CLIENT_TRANSACTIONS)
|
||||||
|
{
|
||||||
|
mysql->server_status=uint2korr(pos); pos+=2;
|
||||||
|
}
|
||||||
|
if (pos < mysql->net.read_pos+len && net_field_length(&pos))
|
||||||
|
mysql->info=(char*) pos;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
|
||||||
|
{
|
||||||
|
int error=send_file_to_server(mysql,(char*) pos);
|
||||||
|
if ((len=net_safe_read(mysql)) == packet_error || error)
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
goto get_info; /* Get info packet */
|
||||||
|
}
|
||||||
|
if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
|
||||||
|
mysql->server_status|= SERVER_STATUS_IN_TRANS;
|
||||||
|
|
||||||
|
mysql->extra_info= net_field_length_ll(&pos); /* Maybe number of rec */
|
||||||
|
if (!(fields=read_rows(mysql,(MYSQL_FIELD*) 0,5)))
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
if (!(mysql->fields=unpack_fields(fields,&mysql->field_alloc,
|
||||||
|
(uint) field_count,0,
|
||||||
|
(my_bool) test(mysql->server_capabilities &
|
||||||
|
CLIENT_LONG_FLAG))))
|
||||||
|
DBUG_RETURN(-1);
|
||||||
|
mysql->status=MYSQL_STATUS_GET_RESULT;
|
||||||
|
mysql->field_count=field_count;
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
int STDCALL
|
int STDCALL
|
||||||
mysql_real_query(MYSQL *mysql, const char *query, uint length)
|
mysql_real_query(MYSQL *mysql, const char *query, uint length)
|
||||||
|
4
mysql-test/r/dirty-close.result
Normal file
4
mysql-test/r/dirty-close.result
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
n
|
||||||
|
1
|
||||||
|
2
|
||||||
|
3
|
10
mysql-test/t/dirty-close.test
Normal file
10
mysql-test/t/dirty-close.test
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
connect (con1,localhost,root,,test,0,mysql-master.sock);
|
||||||
|
connect (con2,localhost,root,,test,0,mysql-master.sock);
|
||||||
|
connection con1;
|
||||||
|
dirty_close con1;
|
||||||
|
connection con2;
|
||||||
|
drop table if exists t1;
|
||||||
|
create table t1 (n int);
|
||||||
|
insert into t1 values (1),(2),(3);
|
||||||
|
select * from t1;
|
||||||
|
drop table t1;
|
@ -24,7 +24,6 @@
|
|||||||
int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
|
int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
|
||||||
{
|
{
|
||||||
char *start=to, *end=to+n-1;
|
char *start=to, *end=to+n-1;
|
||||||
|
|
||||||
for (; *fmt ; fmt++)
|
for (; *fmt ; fmt++)
|
||||||
{
|
{
|
||||||
if (fmt[0] != '%')
|
if (fmt[0] != '%')
|
||||||
@ -38,10 +37,14 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
|
|||||||
fmt++;
|
fmt++;
|
||||||
while (isdigit(*fmt) || *fmt == '.' || *fmt == '-')
|
while (isdigit(*fmt) || *fmt == '.' || *fmt == '-')
|
||||||
fmt++;
|
fmt++;
|
||||||
|
if(*fmt == 'l')
|
||||||
|
fmt++;
|
||||||
if (*fmt == 's') /* String parameter */
|
if (*fmt == 's') /* String parameter */
|
||||||
{
|
{
|
||||||
reg2 char *par = va_arg(ap, char *);
|
reg2 char *par = va_arg(ap, char *);
|
||||||
uint plen = (uint) strlen(par);
|
uint plen;
|
||||||
|
if(!par) par = (char*)"(null)";
|
||||||
|
plen = (uint) strlen(par);
|
||||||
if ((uint) (end-to) > plen) /* Replace if possible */
|
if ((uint) (end-to) > plen) /* Replace if possible */
|
||||||
{
|
{
|
||||||
to=strmov(to,par);
|
to=strmov(to,par);
|
||||||
@ -68,3 +71,35 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
|
|||||||
*to='\0'; /* End of errmessage */
|
*to='\0'; /* End of errmessage */
|
||||||
return (uint) (to - start);
|
return (uint) (to - start);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef MAIN
|
||||||
|
static void my_printf(const char * fmt, ...)
|
||||||
|
{
|
||||||
|
char buf[32];
|
||||||
|
int n;
|
||||||
|
va_list ar;
|
||||||
|
va_start(ar, fmt);
|
||||||
|
n = my_vsnprintf(buf, sizeof(buf),fmt, ar);
|
||||||
|
printf(buf);
|
||||||
|
printf("n=%d, strlen=%d\n", n, strlen(buf));
|
||||||
|
va_end(ar);
|
||||||
|
}
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
|
||||||
|
my_printf("Hello\n");
|
||||||
|
my_printf("Hello int, %d\n", 1);
|
||||||
|
my_printf("Hello string '%s'\n", "I am a string");
|
||||||
|
my_printf("Hello hack hack hack hack hack hack hack %d\n", 1);
|
||||||
|
my_printf("Hello %d hack %d\n", 1, 4);
|
||||||
|
my_printf("Hello %d hack hack hack hack hack %d\n", 1, 4);
|
||||||
|
my_printf("Hello '%s' hhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhhh\n", "hack");
|
||||||
|
my_printf("Hello hhhhhhhhhhhhhh %d sssssssssssssss\n", 1);
|
||||||
|
my_printf("Hello %u\n", 1);
|
||||||
|
my_printf("conn %ld to: '%-.64s' user: '%-.32s' host:\
|
||||||
|
`%-.64s' (%-.64s)", 1, 0,0,0,0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@ -408,7 +408,7 @@ pthread_handler_decl(handle_one_connection,arg)
|
|||||||
{
|
{
|
||||||
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
|
sql_print_error(ER(ER_NEW_ABORTING_CONNECTION),
|
||||||
thd->thread_id,(thd->db ? thd->db : "unconnected"),
|
thd->thread_id,(thd->db ? thd->db : "unconnected"),
|
||||||
thd->user,
|
thd->user ? thd->user : "unauthenticated",
|
||||||
(thd->host ? thd->host : thd->ip ? thd->ip : "unknown"),
|
(thd->host ? thd->host : thd->ip ? thd->ip : "unknown"),
|
||||||
(net->last_errno ? ER(net->last_errno) :
|
(net->last_errno ? ER(net->last_errno) :
|
||||||
ER(ER_UNKNOWN_ERROR)));
|
ER(ER_UNKNOWN_ERROR)));
|
||||||
|
Reference in New Issue
Block a user