diff options
Diffstat (limited to 'sql-common/client.c')
-rw-r--r-- | sql-common/client.c | 231 |
1 files changed, 124 insertions, 107 deletions
diff --git a/sql-common/client.c b/sql-common/client.c index af64bb2b210..02fb1964eaa 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -286,7 +286,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, char **arg_unix_socket) { HANDLE hPipe=INVALID_HANDLE_VALUE; - char szPipeName [ 257 ]; + char pipe_name[1024]; DWORD dwMode; int i; my_bool testing_named_pipes=0; @@ -297,13 +297,15 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, if (!host || !strcmp(host,LOCAL_HOST)) host=LOCAL_HOST_NAMEDPIPE; - sprintf( szPipeName, "\\\\%s\\pipe\\%s", host, unix_socket); - DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", - host, unix_socket)); + + pipe_name[sizeof(pipe_name)-1]= 0; /* Safety if too long string */ + strxnmov(pipe_name, sizeof(pipe_name)-1, "\\\\", host, "\\pipe\\", + unix_socket, NullS); + DBUG_PRINT("info",("Server name: '%s'. Named Pipe: %s", host, unix_socket)); for (i=0 ; i < 100 ; i++) /* Don't retry forever */ { - if ((hPipe = CreateFile(szPipeName, + if ((hPipe = CreateFile(pipe_name, GENERIC_READ | GENERIC_WRITE, 0, NULL, @@ -320,7 +322,7 @@ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, return INVALID_HANDLE_VALUE; } /* wait for for an other instance */ - if (! WaitNamedPipe(szPipeName, connect_timeout*1000) ) + if (! WaitNamedPipe(pipe_name, connect_timeout*1000) ) { net->last_errno=CR_NAMEDPIPEWAIT_ERROR; strmov(net->sqlstate, unknown_sqlstate); @@ -583,11 +585,8 @@ net_safe_read(MYSQL *mysql) return (packet_error); #endif /*MYSQL_SERVER*/ end_server(mysql); - net->last_errno=(net->last_errno == ER_NET_PACKET_TOO_LARGE ? - CR_NET_PACKET_TOO_LARGE: - CR_SERVER_LOST); - strmov(net->last_error,ER(net->last_errno)); - strmov(net->sqlstate, unknown_sqlstate); + set_mysql_error(mysql, net->last_errno == ER_NET_PACKET_TOO_LARGE ? + CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate); return (packet_error); } if (net->read_pos[0] == 255) @@ -607,11 +606,8 @@ net_safe_read(MYSQL *mysql) min((uint) len,(uint) sizeof(net->last_error)-1)); } else - { - net->last_errno=CR_UNKNOWN_ERROR; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); - } + set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); + DBUG_PRINT("error",("Got error: %d/%s (%s)", net->last_errno, net->sqlstate, net->last_error)); return(packet_error); @@ -647,8 +643,7 @@ cli_advanced_command(MYSQL *mysql, enum enum_server_command command, } if (mysql->status != MYSQL_STATUS_READY) { - strmov(net->last_error,ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); - strmov(net->sqlstate, unknown_sqlstate); + set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); return 1; } @@ -702,6 +697,52 @@ void free_old_query(MYSQL *mysql) DBUG_VOID_RETURN; } +/* + Set the internal error message to mysql handler +*/ + +void set_mysql_error(MYSQL *mysql, int errcode, const char *sqlstate) +{ + NET *net; + DBUG_ENTER("set_mysql_error"); + DBUG_PRINT("enter", ("error :%d '%s'", errcode, ER(errcode))); + DBUG_ASSERT(mysql != 0); + + net= &mysql->net; + net->last_errno= errcode; + strmov(net->last_error, ER(errcode)); + strmov(net->sqlstate, sqlstate); + + DBUG_VOID_RETURN; +} + +/* + Flush result set sent from server +*/ + +void flush_use_result(MYSQL *mysql) +{ + /* Clear the current execution status */ + DBUG_PRINT("warning",("Not all packets read, clearing them")); + for (;;) + { + ulong pkt_len; + if ((pkt_len=net_safe_read(mysql)) == packet_error) + break; + if (pkt_len <= 8 && mysql->net.read_pos[0] == 254) + { + if (protocol_41(mysql)) + { + char *pos= (char*) mysql->net.read_pos; + mysql->warning_count=uint2korr(pos); pos+=2; + mysql->server_status=uint2korr(pos); pos+=2; + } + break; /* End of data */ + } + } +} + + #ifdef __WIN__ static my_bool is_NT(void) { @@ -739,26 +780,16 @@ mysql_free_result(MYSQL_RES *result) DBUG_PRINT("enter",("mysql_res: %lx",result)); if (result) { - if (result->handle && result->handle->status == MYSQL_STATUS_USE_RESULT) + MYSQL *mysql= result->handle; + if (mysql) { - DBUG_PRINT("warning",("Not all rows in set where read; Ignoring rows")); - for (;;) + if (mysql->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled) + mysql->unbuffered_fetch_owner= 0; + if (mysql->status == MYSQL_STATUS_USE_RESULT) { - ulong pkt_len; - if ((pkt_len=net_safe_read(result->handle)) == packet_error) - break; - if (pkt_len <= 8 && result->handle->net.read_pos[0] == 254) - { - if (protocol_41(result->handle)) - { - char *pos= (char*) result->handle->net.read_pos; - result->handle->warning_count=uint2korr(pos); pos+=2; - result->handle->server_status=uint2korr(pos); pos+=2; - } - break; /* End of data */ - } + flush_use_result(mysql); + mysql->status=MYSQL_STATUS_READY; } - result->handle->status=MYSQL_STATUS_READY; } free_rows(result->data); if (result->fields) @@ -1162,9 +1193,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, if (!(result=(MYSQL_DATA*) my_malloc(sizeof(MYSQL_DATA), MYF(MY_WME | MY_ZEROFILL)))) { - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(0); } init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */ @@ -1191,9 +1220,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, (fields+1)*sizeof(char *)+pkt_len)))) { free_rows(result); - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(0); } *prev_ptr=cur; @@ -1212,9 +1239,7 @@ MYSQL_DATA *cli_read_rows(MYSQL *mysql,MYSQL_FIELD *mysql_fields, if (len > (ulong) (end_to - to)) { free_rows(result); - net->last_errno=CR_MALFORMED_PACKET; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_MALFORMED_PACKET, unknown_sqlstate); DBUG_RETURN(0); } memcpy(to,(char*) cp,len); to[len]=0; @@ -1285,9 +1310,7 @@ read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths) { if (len > (ulong) (end_pos - pos)) { - net->last_errno=CR_UNKNOWN_ERROR; - strmov(net->last_error,ER(net->last_errno)); - strmov(net->sqlstate, unknown_sqlstate); + set_mysql_error(mysql, CR_UNKNOWN_ERROR, unknown_sqlstate); return -1; } row[field] = (char*) pos; @@ -1335,12 +1358,15 @@ mysql_init(MYSQL *mysql) Only enable LOAD DATA INFILE by default if configured with --enable-local-infile */ + #if defined(ENABLED_LOCAL_INFILE) && !defined(MYSQL_SERVER) mysql->options.client_flag|= CLIENT_LOCAL_FILES; #endif + #ifdef HAVE_SMEM mysql->options.shared_memory_base_name= (char*) def_shared_memory_base_name; #endif + mysql->options.methods_to_use= MYSQL_OPT_GUESS_CONNECTION; return mysql; } @@ -1420,8 +1446,9 @@ static MYSQL_METHODS client_methods= cli_read_binary_rows, cli_unbuffered_fetch, NULL, - cli_read_statistic, - cli_read_query_result + cli_read_statistics, + cli_read_query_result, + cli_read_change_user_result #endif }; @@ -1672,9 +1699,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, if (!net->vio) { DBUG_PRINT("error",("Unknow protocol %d ",mysql->options.protocol)); - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno= CR_CONN_UNKNOW_PROTOCOL; - strmov(net->last_error, ER(CR_CONN_UNKNOW_PROTOCOL)); + set_mysql_error(mysql, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate); goto error; } @@ -1682,9 +1707,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, { vio_delete(net->vio); net->vio = 0; - net->last_errno=CR_OUT_OF_MEMORY; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); goto error; } vio_keepalive(net->vio,TRUE); @@ -1701,9 +1724,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, if (mysql->options.connect_timeout && vio_poll_read(net->vio, mysql->options.connect_timeout)) { - net->last_errno= CR_SERVER_LOST; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); goto error; } @@ -1757,8 +1778,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, if (mysql->options.secure_auth && passwd[0] && !(mysql->server_capabilities & CLIENT_SECURE_CONNECTION)) { - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error, ER(net->last_errno=CR_SECURE_AUTH)); + set_mysql_error(mysql, CR_SECURE_AUTH, unknown_sqlstate); goto error; } @@ -1812,8 +1832,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, !(mysql->user=my_strdup(user,MYF(0))) || !(mysql->passwd=my_strdup(passwd,MYF(0)))) { - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error, ER(net->last_errno=CR_OUT_OF_MEMORY)); + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); goto error; } strmov(mysql->host_info,host_info); @@ -1880,9 +1899,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, struct st_mysql_options *options= &mysql->options; if (my_net_write(net,buff,(uint) (end-buff)) || net_flush(net)) { - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); goto error; } /* Do the SSL layering. */ @@ -1893,18 +1910,14 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, options->ssl_capath, options->ssl_cipher))) { - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno= CR_SSL_CONNECTION_ERROR; - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); goto error; } DBUG_PRINT("info", ("IO layer change in progress...")); if (sslconnect((struct st_VioSSLConnectorFd*)(mysql->connector_fd), mysql->net.vio, (long) (mysql->options.connect_timeout))) { - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno= CR_SSL_CONNECTION_ERROR; - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SSL_CONNECTION_ERROR, unknown_sqlstate); goto error; } DBUG_PRINT("info", ("IO layer change done!")); @@ -1953,9 +1966,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, /* Write authentication package */ if (my_net_write(net,buff,(ulong) (end-buff)) || net_flush(net)) { - strmov(net->sqlstate, unknown_sqlstate); - net->last_errno= CR_SERVER_LOST; - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); goto error; } @@ -1977,9 +1988,7 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, scramble_323(buff, mysql->scramble, passwd); if (my_net_write(net, buff, SCRAMBLE_LENGTH_323 + 1) || net_flush(net)) { - net->last_errno= CR_SERVER_LOST; - strmov(net->sqlstate, unknown_sqlstate); - strmov(net->last_error,ER(net->last_errno)); + set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate); goto error; } /* Read what server thinks about out new auth message report */ @@ -2035,7 +2044,7 @@ error: /* Free alloced memory */ end_server(mysql); mysql_close_free(mysql); - if (!(client_flag & CLIENT_REMEMBER_OPTIONS)) + if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS)) mysql_close_free_options(mysql); } DBUG_RETURN(0); @@ -2074,9 +2083,7 @@ my_bool mysql_reconnect(MYSQL *mysql) { /* Allow reconnect next time */ mysql->server_status&= ~SERVER_STATUS_IN_TRANS; - strmov(mysql->net.sqlstate, unknown_sqlstate); - mysql->net.last_errno=CR_SERVER_GONE_ERROR; - strmov(mysql->net.last_error,ER(mysql->net.last_errno)); + set_mysql_error(mysql, CR_SERVER_GONE_ERROR, unknown_sqlstate); DBUG_RETURN(1); } mysql_init(&tmp_mysql); @@ -2191,12 +2198,13 @@ void STDCALL mysql_close(MYSQL *mysql) #ifdef MYSQL_CLIENT if (mysql->stmts) { - /* Free any open prepared statements */ - LIST *element, *next_element; - for (element= mysql->stmts; element; element= next_element) + /* Reset connection handle in all prepared statements. */ + LIST *element; + for (element= mysql->stmts; element; element= element->next) { - next_element= element->next; - stmt_close((MYSQL_STMT *)element->data, 0); + MYSQL_STMT *stmt= (MYSQL_STMT *) element->data; + stmt->mysql= 0; + /* No need to call list_delete for statement here */ } mysql->stmts= 0; } @@ -2228,6 +2236,7 @@ void STDCALL mysql_close(MYSQL *mysql) DBUG_VOID_RETURN; } + static my_bool cli_read_query_result(MYSQL *mysql) { uchar *pos; @@ -2276,7 +2285,7 @@ get_info: #ifdef MYSQL_CLIENT if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */ { - int error=send_file_to_server(mysql,(char*) pos); + int error=handle_local_infile(mysql,(char*) pos); if ((length=net_safe_read(mysql)) == packet_error || error) DBUG_RETURN(1); goto get_info; /* Get info packet */ @@ -2360,9 +2369,7 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) { - strmov(mysql->net.sqlstate, unknown_sqlstate); - strmov(mysql->net.last_error, - ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); + set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); DBUG_RETURN(0); } mysql->status=MYSQL_STATUS_READY; /* server is ready */ @@ -2371,9 +2378,7 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql) mysql->field_count), MYF(MY_WME | MY_ZEROFILL)))) { - strmov(mysql->net.sqlstate, unknown_sqlstate); - mysql->net.last_errno=CR_OUT_OF_MEMORY; - strmov(mysql->net.last_error, ER(mysql->net.last_errno)); + set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate); DBUG_RETURN(0); } result->methods= mysql->methods; @@ -2390,9 +2395,10 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql) result->fields= mysql->fields; result->field_alloc= mysql->field_alloc; result->field_count= mysql->field_count; - result->current_field=0; - result->current_row=0; /* Must do a fetch first */ + /* The rest of result members is bzeroed in malloc */ mysql->fields=0; /* fields is now in result */ + /* just in case this was mistakenly called after mysql_stmt_execute() */ + mysql->unbuffered_fetch_owner= 0; DBUG_RETURN(result); /* Data fetched */ } @@ -2418,9 +2424,7 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) { - strmov(mysql->net.sqlstate, unknown_sqlstate); - strmov(mysql->net.last_error, - ER(mysql->net.last_errno=CR_COMMANDS_OUT_OF_SYNC)); + set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); DBUG_RETURN(0); } if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result)+ @@ -2443,6 +2447,7 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql) result->current_row= 0; mysql->fields=0; /* fields is now in result */ mysql->status=MYSQL_STATUS_USE_RESULT; + mysql->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled; DBUG_RETURN(result); /* Data is read to be fetched */ } @@ -2459,19 +2464,30 @@ mysql_fetch_row(MYSQL_RES *res) { /* Unbufferred fetch */ if (!res->eof) { - if (!(read_one_row(res->handle,res->field_count,res->row, res->lengths))) + MYSQL *mysql= res->handle; + if (mysql->status != MYSQL_STATUS_USE_RESULT) { - res->row_count++; - DBUG_RETURN(res->current_row=res->row); + set_mysql_error(mysql, + res->unbuffered_fetch_cancelled ? + CR_FETCH_CANCELLED : CR_COMMANDS_OUT_OF_SYNC, + unknown_sqlstate); } - else + else if (!(read_one_row(mysql, res->field_count, res->row, res->lengths))) { - DBUG_PRINT("info",("end of data")); - res->eof=1; - res->handle->status=MYSQL_STATUS_READY; - /* Don't clear handle in mysql_free_results */ - res->handle=0; + res->row_count++; + DBUG_RETURN(res->current_row=res->row); } + DBUG_PRINT("info",("end of data")); + res->eof=1; + mysql->status=MYSQL_STATUS_READY; + /* + Reset only if owner points to us: there is a chance that somebody + started new query after mysql_stmt_close(): + */ + if (mysql->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled) + mysql->unbuffered_fetch_owner= 0; + /* Don't clear handle in mysql_free_result */ + res->handle=0; } DBUG_RETURN((MYSQL_ROW) NULL); } @@ -2589,3 +2605,4 @@ const char * STDCALL mysql_error(MYSQL *mysql) { return mysql->net.last_error; } + |