diff --git a/include/my_sys.h b/include/my_sys.h index c6339890..4a1ff1f7 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -616,9 +616,9 @@ void load_defaults(const char *conf_file, const char **groups, int *argc, char ***argv); void free_defaults(char **argv); void print_defaults(const char *conf_file, const char **groups); -my_bool my_compress(unsigned char *, ulong *, ulong *); -my_bool my_uncompress(unsigned char *, ulong *, ulong *); -unsigned char *my_compress_alloc(const unsigned char *packet, ulong *len, ulong *complen); +my_bool my_compress(unsigned char *, size_t *, size_t *); +my_bool my_uncompress(unsigned char *, size_t *, size_t *); +unsigned char *my_compress_alloc(const unsigned char *packet, size_t *len, size_t *complen); ulong checksum(const unsigned char *mem, uint count); #if defined(_MSC_VER) && !defined(_WIN32) diff --git a/include/mysql_com.h b/include/mysql_com.h index d8b8c5bd..1331a32f 100644 --- a/include/mysql_com.h +++ b/include/mysql_com.h @@ -317,7 +317,7 @@ int net_flush(NET *net); int my_net_write(NET *net,const char *packet, size_t len); int net_write_command(NET *net,unsigned char command,const char *packet, size_t len); -int net_real_write(NET *net,const char *packet,unsigned long len); +int net_real_write(NET *net,const char *packet, size_t len); unsigned long my_net_read(NET *net); struct rand_struct { diff --git a/include/violite.h b/include/violite.h index 0ab9d926..75a5bf2b 100644 --- a/include/violite.h +++ b/include/violite.h @@ -69,11 +69,8 @@ void vio_reset(Vio* vio, enum enum_vio_type type, * vio_read and vio_write should have the same semantics * as read(2) and write(2). */ -int vio_read( Vio* vio, - gptr buf, int size); -int vio_write( Vio* vio, - const gptr buf, - int size); +size_t vio_read(Vio* vio, gptr buf, size_t size); +size_t vio_write(Vio* vio, const gptr buf, size_t size); /* * Whenever the socket is set to blocking mode or not. */ diff --git a/libmariadb/libmariadb.c b/libmariadb/libmariadb.c index c2ab8b0d..1c0bc547 100644 --- a/libmariadb/libmariadb.c +++ b/libmariadb/libmariadb.c @@ -417,7 +417,7 @@ restart: my_set_error(mysql, CR_UNKNOWN_ERROR, SQLSTATE_UNKNOWN, 0); } - mysql->server_status= ~SERVER_MORE_RESULTS_EXIST; + mysql->server_status&= ~SERVER_MORE_RESULTS_EXIST; DBUG_PRINT("error",("Got error: %d (%s)", net->last_errno, net->last_error)); diff --git a/libmariadb/my_compress.c b/libmariadb/my_compress.c index 8c73c247..23b39f2b 100644 --- a/libmariadb/my_compress.c +++ b/libmariadb/my_compress.c @@ -29,7 +29,7 @@ ** *complen is 0 if the packet wasn't compressed */ -my_bool my_compress(unsigned char *packet, ulong *len, ulong *complen) +my_bool my_compress(unsigned char *packet, size_t *len, size_t *complen) { if (*len < MIN_COMPRESS_LENGTH) *complen=0; @@ -39,12 +39,13 @@ my_bool my_compress(unsigned char *packet, ulong *len, ulong *complen) if (!compbuf) return *complen ? 0 : 1; memcpy(packet,compbuf,*len); - my_free(compbuf,MYF(MY_WME)); } + my_free(compbuf,MYF(MY_WME)); + } return 0; } -unsigned char *my_compress_alloc(const unsigned char *packet, ulong *len, ulong *complen) +unsigned char *my_compress_alloc(const unsigned char *packet, size_t *len, size_t *complen) { unsigned char *compbuf; *complen = *len * 120 / 100 + 12; @@ -67,7 +68,7 @@ unsigned char *my_compress_alloc(const unsigned char *packet, ulong *len, ulong } -my_bool my_uncompress (unsigned char *packet, ulong *len, ulong *complen) +my_bool my_uncompress (unsigned char *packet, size_t *len, size_t *complen) { if (*complen) /* If compressed */ { diff --git a/libmariadb/my_stmt.c b/libmariadb/my_stmt.c index 48efc159..417000ee 100644 --- a/libmariadb/my_stmt.c +++ b/libmariadb/my_stmt.c @@ -1436,8 +1436,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) DBUG_PRINT("info",("request_len=%ld", request_len)); ret= test(simple_command(stmt->mysql, MYSQL_COM_STMT_EXECUTE, request, request_len, 1, stmt) || - (stmt->mysql->methods->db_read_stmt_result && stmt->mysql->methods->db_read_stmt_result(stmt->mysql))); - + (stmt->mysql && stmt->mysql->methods->db_read_stmt_result && stmt->mysql->methods->db_read_stmt_result(stmt->mysql))); if (request) my_free(request, MYF(0)); diff --git a/libmariadb/my_thr_init.c b/libmariadb/my_thr_init.c index 19cbb82d..c0d546dc 100644 --- a/libmariadb/my_thr_init.c +++ b/libmariadb/my_thr_init.c @@ -22,6 +22,7 @@ #include "mysys_priv.h" #include +#include #ifdef THREAD #ifdef USE_TLS @@ -123,49 +124,41 @@ static long thread_id=0; my_bool my_thread_init(void) { struct st_my_thread_var *tmp; -#if !defined(_WIN32) || defined(USE_TLS) || ! defined(SAFE_MUTEX) - pthread_mutex_lock(&THR_LOCK_lock); -#endif -#if !defined(_WIN32) || defined(USE_TLS) + my_bool rc= 0; if (my_pthread_getspecific(struct st_my_thread_var *,THR_KEY_mysys)) { - pthread_mutex_unlock(&THR_LOCK_lock); + DBUG_PRINT("info", ("my_thread_init was already called. Thread id: %lu", + pthread_self())); return 0; /* Safequard */ } - /* We must have many calloc() here because these are freed on - pthread_exit */ + /* We must have many calloc() here because these are freed on + pthread_exit */ if (!(tmp=(struct st_my_thread_var *) calloc(1,sizeof(struct st_my_thread_var)))) { - pthread_mutex_unlock(&THR_LOCK_lock); return 1; } pthread_setspecific(THR_KEY_mysys,tmp); -#else - tmp= &THR_KEY_mysys; if (tmp->initialized) /* Already initialized */ { -#if !defined(_WIN32) || defined(USE_TLS) || ! defined(SAFE_MUTEX) - pthread_mutex_unlock(&THR_LOCK_lock); -#endif return 0; } - tmp= &THR_KEY_mysys; -#endif - tmp->id= ++thread_id; + pthread_mutex_init(&tmp->mutex,MY_MUTEX_INIT_FAST); pthread_cond_init(&tmp->suspend, NULL); -#if !defined(_WIN32) || defined(USE_TLS) || ! defined(SAFE_MUTEX) + pthread_mutex_lock(&THR_LOCK_lock); + tmp->id= ++thread_id; pthread_mutex_unlock(&THR_LOCK_lock); -#endif tmp->initialized= TRUE; return 0; } void my_thread_end(void) { - struct st_my_thread_var *tmp=my_thread_var; + struct st_my_thread_var *tmp= + my_pthread_getspecific(struct st_my_thread_var *, THR_KEY_mysys); + if (tmp && tmp->initialized) { #if !defined(DBUG_OFF) diff --git a/libmariadb/net.c b/libmariadb/net.c index cc8bd085..784a9617 100644 --- a/libmariadb/net.c +++ b/libmariadb/net.c @@ -110,11 +110,12 @@ int my_net_init(NET *net, Vio* vio) return 1; if (net_buffer_length > max_allowed_packet) max_allowed_packet=net_buffer_length; + net->max_packet_size= 0xFFFFFF; net->buff_end=net->buff+(net->max_packet=net_buffer_length); net->vio = vio; net->error=0; net->return_status=0; net->read_timeout=(uint) net_read_timeout; /* Timeout for read */ - net->pkt_nr=0; + net->compress_pkt_nr= net->pkt_nr= 0; net->write_pos=net->read_pos = net->buff; net->last_error[0]= net->sqlstate[0] =0; @@ -173,7 +174,7 @@ static my_bool net_realloc(NET *net, size_t length) DBUG_RETURN(0); } -#if defined(DBUG_OFF) || defined(USE_NET_CLEAR) +#if !defined(DBUG_OFF1) || defined(USE_NET_CLEAR) static int net_check_if_data_available(Vio *vio) { my_socket sd= vio->sd; @@ -185,7 +186,7 @@ static int net_check_if_data_available(Vio *vio) FD_SET(sd, &sockset); memset(&tv, 0, sizeof(tv)); - rc= select(sd + 1, &sockset, NULL, NULL, &tv); + rc= select((int)(sd + 1), &sockset, NULL, NULL, &tv); if (rc <= 0) return 0; return FD_ISSET(sd, &sockset); @@ -196,7 +197,7 @@ static int net_check_if_data_available(Vio *vio) void net_clear(NET *net) { -#if defined(DBUG_OFF) || defined(USE_NET_CLEAR) +#if !defined(DBUG_OFF1) || defined(USE_NET_CLEAR) int available= 0; size_t count; /* One may get 'unused' warning */ bool is_blocking=vio_is_blocking(net->vio); @@ -204,7 +205,7 @@ void net_clear(NET *net) DBUG_ENTER("net_clear"); while ((available= net_check_if_data_available(net->vio)) > 0) { - if ((count= vio_read(net->vio, (char *)net->buff, net->max_packet))) + if ((long)(count= vio_read(net->vio, (char *)net->buff, net->max_packet)) > 0) { DBUG_PRINT("info",("skipped %d bytes from file: %s", count,vio_description(net->vio))); @@ -235,7 +236,7 @@ void net_clear(NET *net) #else DBUG_ENTER("net_clear"); #endif - net->pkt_nr=0; /* Ready for new command */ + net->compress_pkt_nr= net->pkt_nr=0; /* Ready for new command */ net->write_pos=net->buff; DBUG_VOID_RETURN; } @@ -253,6 +254,8 @@ int net_flush(NET *net) (uint) (net->write_pos - net->buff)); net->write_pos=net->buff; } + if (net->compress) + net->pkt_nr= net->compress_pkt_nr; DBUG_RETURN(error); } @@ -273,17 +276,24 @@ int my_net_write(NET *net, const char *packet, size_t len) { uchar buff[NET_HEADER_SIZE]; - if (len >= MAX_PACKET_LENGTH) + while (len >= MAX_PACKET_LENGTH) { - net->error=1; - net->last_errno=ER_NET_PACKET_TOO_LARGE; - return 1; + const ulong max_len= MAX_PACKET_LENGTH; + int3store(buff,max_len); + buff[3]= (uchar)net->pkt_nr++; + if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE) || + net_write_buff(net, packet, max_len)) + return 1; + packet+= max_len; + len-= max_len; } - int3store(buff,len); - buff[3]= (net->compress) ? 0 : (uchar) (net->pkt_nr++); - if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE)) + /* write last remaining packet, size can be zero */ + int3store(buff, len); + buff[3]= (uchar)net->pkt_nr++; + if (net_write_buff(net,(char*) buff,NET_HEADER_SIZE) || + net_write_buff(net, packet, len)) return 1; - return net_write_buff(net,packet,len); + return 0; } int @@ -327,7 +337,13 @@ net_write_command(NET *net, uchar command, static int net_write_buff(NET *net,const char *packet, size_t len) { - size_t left_length=(size_t) (net->buff_end - net->write_pos); + size_t left_length; + + if (net->max_packet > MAX_PACKET_LENGTH && + net->compress) + left_length= (size_t)(MAX_PACKET_LENGTH - (net->write_pos - net->buff)); + else + left_length=(size_t) (net->buff_end - net->write_pos); if (len > left_length) { @@ -341,6 +357,19 @@ net_write_buff(NET *net,const char *packet, size_t len) len-=left_length; net->write_pos= net->buff; } + if (net->compress) + { + /* uncompressed length is stored in 3 bytes,so + packet can't be > 0xFFFFFF */ + left_length= MAX_PACKET_LENGTH; + while (len > left_length) + { + if (net_real_write(net, packet, left_length)) + return 1; + packet+= left_length; + len-= left_length; + } + } if (len > net->max_packet) return(test(net_real_write(net, packet, len))); } @@ -352,9 +381,9 @@ net_write_buff(NET *net,const char *packet, size_t len) /* Read and write using timeouts */ int -net_real_write(NET *net,const char *packet,ulong len) +net_real_write(NET *net,const char *packet,size_t len) { - int length; + size_t length; char *pos,*end; thr_alarm_t alarmed; #if !defined(_WIN32) && !defined(__EMX__) && !defined(OS2) @@ -371,16 +400,14 @@ net_real_write(NET *net,const char *packet,ulong len) #ifdef HAVE_COMPRESS if (net->compress) { - ulong complen; + size_t complen; uchar *b; uint header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE; - if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE, + if (!(b=(uchar*) my_malloc(len + NET_HEADER_SIZE + COMP_HEADER_SIZE + 1, MYF(MY_WME)))) { -#ifdef MYSQL_SERVER net->last_errno=ER_OUT_OF_RESOURCES; net->error=2; -#endif net->reading_or_writing=0; DBUG_RETURN(1); } @@ -394,25 +421,18 @@ net_real_write(NET *net,const char *packet,ulong len) } int3store(&b[NET_HEADER_SIZE],complen); int3store(b,len); - b[3]=(uchar) (net->pkt_nr++); + b[3]=(uchar) (net->compress_pkt_nr++); len+= header_length; packet= (char*) b; } #endif /* HAVE_COMPRESS */ - /* DBUG_DUMP("net",packet,len); */ -#ifdef MYSQL_SERVER - thr_alarm_init(&alarmed); - if (net_blocking) - thr_alarm(&alarmed,(uint) net_write_timeout,&alarm_buff); -#else alarmed=0; -#endif /* MYSQL_SERVER */ pos=(char*) packet; end=pos+len; while (pos != end) { - if ((int) (length=vio_write(net->vio,pos,(int) (end-pos))) <= 0) + if ((long) (length=vio_write(net->vio,pos,(int) (end-pos))) <= 0) { my_bool interrupted = vio_should_retry(net->vio); #if (!defined(_WIN32) && !defined(__EMX__) && !defined(OS2)) @@ -432,6 +452,8 @@ net_real_write(NET *net,const char *packet,ulong len) my_progname,vio_errno(net->vio)); #endif /* EXTRA_DEBUG */ net->error=2; /* Close socket */ + net->last_errno= (interrupted ? + ER_NET_WRITE_INTERRUPTED : ER_NET_ERROR_ON_WRITE); goto end; } } @@ -459,10 +481,8 @@ net_real_write(NET *net,const char *packet,ulong len) } #endif /* defined(THREAD_SAFE_CLIENT) && !defined(MYSQL_SERVER) */ net->error=2; /* Close socket */ -#ifdef MYSQL_SERVER net->last_errno= (interrupted ? ER_NET_WRITE_INTERRUPTED : ER_NET_ERROR_ON_WRITE); -#endif /* MYSQL_SERVER */ break; } pos+=length; @@ -648,7 +668,7 @@ my_real_read(NET *net, size_t *complen) #endif goto end; } - net->pkt_nr++; + net->compress_pkt_nr= ++net->pkt_nr; #ifdef HAVE_COMPRESS if (net->compress) { @@ -692,7 +712,7 @@ end: ulong my_net_read(NET *net) { - ulong len,complen; + size_t len,complen; #ifdef HAVE_COMPRESS if (!net->compress) @@ -720,58 +740,62 @@ ulong my_net_read(NET *net) return len; #ifdef HAVE_COMPRESS } - if (net->remain_in_buf) - net->buff[net->buf_length - net->remain_in_buf]=net->save_char; - for (;;) + else { if (net->remain_in_buf) { - uchar *pos = net->buff + net->buf_length - net->remain_in_buf; - if (net->remain_in_buf >= 4) - { - net->length = uint3korr(pos); - if (net->length <= net->remain_in_buf - 4) - { - /* We have a full packet */ - len=net->length; - net->remain_in_buf -= net->length + 4; - net->read_pos=pos + 4; - break; /* We have a full packet */ - } - } - /* Move data down to read next data packet after current one */ - if (net->buf_length != net->remain_in_buf) - { - memmove(net->buff,pos,net->remain_in_buf); - net->buf_length=net->remain_in_buf; - } - net->where_b=net->buf_length; + /* restore 0 character */ + net->buff[net->buf_length - net->remain_in_buf]=net->save_char; } - else + for (;;) { - net->where_b=0; - net->buf_length=0; - } + if (net->remain_in_buf) + { + uchar *pos = net->buff + net->buf_length - net->remain_in_buf; + if (net->remain_in_buf >= 4) + { + net->length = uint3korr(pos); + if (net->length <= net->remain_in_buf - 4) + { + /* We have a full packet */ + len=net->length; + net->remain_in_buf -= net->length + 4; + net->read_pos=pos + 4; + break; /* We have a full packet */ + } + } + /* Move data down to read next data packet after current one */ + if (net->buf_length != net->remain_in_buf) + { + memmove(net->buff,pos,net->remain_in_buf); + net->buf_length=net->remain_in_buf; + } + net->where_b=net->buf_length; + } + else + { + net->where_b=0; + net->buf_length=0; + } - if ((len = my_real_read(net,(size_t *)&complen)) == packet_error) - break; - if (my_uncompress((unsigned char*) net->buff + net->where_b, &len, &complen)) - { - len= packet_error; - net->error=2; /* caller will close socket */ -#ifdef MYSQL_SERVER - net->last_errno=ER_NET_UNCOMPRESS_ERROR; -#endif - break; + if ((len = my_real_read(net,(size_t *)&complen)) == packet_error) + break; + if (my_uncompress((unsigned char*) net->buff + net->where_b, &len, &complen)) + { + len= packet_error; + net->error=2; /* caller will close socket */ + net->last_errno=ER_NET_UNCOMPRESS_ERROR; + break; + } + net->buf_length+=len; + net->remain_in_buf+=len; + } + if (len != packet_error) + { + net->save_char= net->read_pos[len]; /* Must be saved */ + net->read_pos[len]=0; /* Safeguard for mysql_use_result */ } - net->buf_length+=len; - net->remain_in_buf+=len; } - if (len != packet_error) - { - net->save_char= net->read_pos[len]; /* Must be saved */ - net->read_pos[len]=0; /* Safeguard for mysql_use_result */ - } - return len; #endif + return len; } diff --git a/libmariadb/violite.c b/libmariadb/violite.c index 3f95d98d..e8d368d4 100644 --- a/libmariadb/violite.c +++ b/libmariadb/violite.c @@ -186,12 +186,12 @@ int vio_errno(Vio *vio __attribute__((unused))) } -int vio_read(Vio * vio, gptr buf, int size) +size_t vio_read(Vio * vio, gptr buf, size_t size) { - int r; + size_t r; DBUG_ENTER("vio_read"); DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size)); - + #ifdef HAVE_OPENSSL if (vio->type == VIO_TYPE_SSL) { @@ -219,19 +219,19 @@ int vio_read(Vio * vio, gptr buf, int size) r = read(vio->sd, buf, size); #endif /* _WIN32 */ #ifndef DBUG_OFF - if (r < 0) + if ((size_t)r == -1) { DBUG_PRINT("vio_error", ("Got error %d during read",socket_errno)); } #endif /* DBUG_OFF */ - DBUG_PRINT("exit", ("%d", r)); + DBUG_PRINT("exit", ("%u", (uint)r)); DBUG_RETURN(r); } -int vio_write(Vio * vio, const gptr buf, int size) +size_t vio_write(Vio * vio, const gptr buf, size_t size) { - int r; + size_t r; DBUG_ENTER("vio_write"); DBUG_PRINT("enter", ("sd=%d size=%d", vio->sd, size)); #ifdef HAVE_OPENSSL @@ -259,12 +259,12 @@ int vio_write(Vio * vio, const gptr buf, int size) r = write(vio->sd, buf, size); #endif /* _WIN32 */ #ifndef DBUG_OFF - if (r < 0) + if ((size_t)r == -1) { DBUG_PRINT("vio_error", ("Got error on write: %d",socket_errno)); } #endif /* DBUG_OFF */ - DBUG_PRINT("exit", ("%d", r)); + DBUG_PRINT("exit", ("%u", (uint)r)); DBUG_RETURN(r); } diff --git a/unittest/libmariadb/basic-t.c b/unittest/libmariadb/basic-t.c index 8446fe2a..77077389 100644 --- a/unittest/libmariadb/basic-t.c +++ b/unittest/libmariadb/basic-t.c @@ -530,7 +530,32 @@ static int test_reconnect_maxpackage(MYSQL *my) return OK; } +static int test_compressed(MYSQL *my) +{ + int rc; + MYSQL *mysql= mysql_init(NULL); + MYSQL_RES *res; + char *query; + + mysql_options(mysql, MYSQL_OPT_COMPRESS, (void *)1); + FAIL_IF(!mysql_real_connect(mysql, hostname, username, password, schema, + port, socketname, + CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS), mysql_error(mysql)); + mysql->reconnect= 1; + + rc= mysql_query(mysql, "SHOW VARIABLES"); + check_mysql_rc(rc, mysql); + + if ((res= mysql_store_result(mysql))) + mysql_free_result(res); + + mysql_close(mysql); + + return OK; +} + struct my_tests_st my_tests[] = { + {"test_compressed", test_compressed, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_reconnect_maxpackage", test_reconnect_maxpackage, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"basic_connect", basic_connect, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"use_utf8", use_utf8, TEST_CONNECTION_NEW, 0, opt_utf8, NULL}, diff --git a/unittest/libmariadb/charset.c b/unittest/libmariadb/charset.c index ee8cdb30..c88d2dce 100644 --- a/unittest/libmariadb/charset.c +++ b/unittest/libmariadb/charset.c @@ -543,6 +543,7 @@ static int test_bug30472(MYSQL *mysql) } /* Retrieve character set information. */ + mysql_set_character_set(mysql, "latin1"); bug30472_retrieve_charset_info(mysql, character_set_name_1, character_set_client_1, @@ -572,6 +573,7 @@ static int test_bug30472(MYSQL *mysql) FAIL_UNLESS(strcmp(character_set_results_2, "utf8") == 0, "cs_result != ut8"); FAIL_UNLESS(strcmp(collation_connnection_2, "utf8_general_ci") == 0, "collation != utf8_general_ci"); + diag("%s %s", character_set_name_1, character_set_name_2); FAIL_UNLESS(strcmp(character_set_name_1, character_set_name_2) != 0, "cs_name1 = cs_name2"); FAIL_UNLESS(strcmp(character_set_client_1, character_set_client_2) != 0, "cs_client1 = cs_client2"); FAIL_UNLESS(strcmp(character_set_results_1, character_set_results_2) != 0, "cs_result1 = cs_result2"); @@ -580,6 +582,7 @@ static int test_bug30472(MYSQL *mysql) /* Call mysql_change_user() with the same username, password, database. */ rc= mysql_change_user(mysql, username, password, (schema) ? schema : "test"); + mysql_set_character_set(mysql, "latin1"); check_mysql_rc(rc, mysql); /* Retrieve character set information. */ diff --git a/unittest/libmariadb/thread.c b/unittest/libmariadb/thread.c index e1e36765..6024b8ab 100644 --- a/unittest/libmariadb/thread.c +++ b/unittest/libmariadb/thread.c @@ -36,22 +36,105 @@ static int basic_connect(MYSQL *mysql) return OK; } +pthread_mutex_t LOCK_test; + +#ifndef _WIN32 +int thread_conc27(void); +#else +DWORD WINAPI thread_conc27(void); +#endif + +#define THREAD_NUM 100 + static int test_conc_27(MYSQL *mysql) { + int rc; + int i; + MYSQL_ROW row; + MYSQL_RES *res; +#ifndef _WIN32 + pthread_t threads[THREAD_NUM]; +#else + HANDLE hthreads[THREAD_NUM]; + DWORD threads[THREAD_NUM]; +#endif - mysql_thread_init(); + rc= mysql_query(mysql, "DROP TABLE IF EXISTS t_conc27"); + check_mysql_rc(rc, mysql); - rc= mysql_query(mysql, "SET @a:=1"); + rc= mysql_query(mysql, "CREATE TABLE t_conc27(a int)"); + check_mysql_rc(rc, mysql); + + rc= mysql_query(mysql, "INSERT INTO t_conc27 VALUES(0)"); + check_mysql_rc(rc, mysql); + + pthread_mutex_init(&LOCK_test, NULL); + for (i=0; i < THREAD_NUM; i++) + { +#ifndef _WIN32 + pthread_create(&threads[i], NULL, (void *)thread_conc27, NULL); +#else + hthreads[i]= CreateThread(NULL, 0, thread_conc27, NULL, 0, &threads[i]); + if (hthreads[i]==NULL) + diag("error while starting thread"); +#endif + } + for (i=0; i < THREAD_NUM; i++) + { +#ifndef _WIN32 + pthread_join(threads[i], NULL); +#else + WaitForSingleObject(hthreads[i], INFINITE); +#endif + } + pthread_mutex_destroy(&LOCK_test); + + rc= mysql_query(mysql, "SELECT a FROM t_conc27"); check_mysql_rc(rc,mysql); - mysql_thread_end(); - rc= mysql_query(mysql, "SET @a:=2"); - check_mysql_rc(rc,mysql); - mysql_thread_end(); + res= mysql_store_result(mysql); + FAIL_IF(!res, "invalid result"); + + row= mysql_fetch_row(res); + FAIL_IF(!row, "can't fetch row"); + + diag("row=%s", row[0]); + FAIL_IF(atoi(row[0]) != 100, "expected value 100"); + mysql_free_result(res); + return OK; } +#ifndef _WIN32 +int thread_conc27(void) +#else +DWORD WINAPI thread_conc27(void) +#endif +{ + MYSQL *mysql; + int rc; + mysql_thread_init(); + mysql= mysql_init(NULL); + if(!mysql_real_connect(mysql, hostname, username, password, schema, + port, socketname, 0)) + { + diag("Error: %s", mysql_error(mysql)); + mysql_close(mysql); + mysql_thread_end(); + goto end; + } + pthread_mutex_lock(&LOCK_test); + rc= mysql_query(mysql, "UPDATE t_conc27 SET a=a+1"); + check_mysql_rc(rc, mysql); + pthread_mutex_unlock(&LOCK_test); + mysql_close(mysql); + mysql_thread_end(); +end: + mysql_thread_end(); + return 0; +} + struct my_tests_st my_tests[] = { {"basic_connect", basic_connect, TEST_CONNECTION_NONE, 0, NULL, NULL}, {"test_conc_27", test_conc_27, TEST_CONNECTION_NEW, 0, NULL, NULL},