diff options
author | Alexander Nozdrin <alik@sun.com> | 2009-11-05 15:08:37 +0300 |
---|---|---|
committer | Alexander Nozdrin <alik@sun.com> | 2009-11-05 15:08:37 +0300 |
commit | d476bbb0becb27d7d3cb1fc5cc0ac4d401622893 (patch) | |
tree | 64caab6e7d4a7167ee56b4f7d6572bb07c30750a /sql-common | |
parent | 1a8f08b006616b0bb2a9e9e13969ebe406e9e3f2 (diff) | |
parent | 16b603a8b0c2bba16cb66b1769f21c0185435d33 (diff) | |
download | mariadb-git-d476bbb0becb27d7d3cb1fc5cc0ac4d401622893.tar.gz |
Auto-merge from mysql-next-mr.
Diffstat (limited to 'sql-common')
-rw-r--r-- | sql-common/client.c | 262 |
1 files changed, 140 insertions, 122 deletions
diff --git a/sql-common/client.c b/sql-common/client.c index a16883abf31..976a30a9566 100644 --- a/sql-common/client.c +++ b/sql-common/client.c @@ -710,10 +710,14 @@ err: } #endif -/***************************************************************************** +/** Read a packet from server. Give error message if socket was down or packet is an error message -*****************************************************************************/ + + @retval packet_error An error occurred during reading. + Error message is set. + @retval +*/ ulong cli_safe_read(MYSQL *mysql) @@ -879,31 +883,132 @@ void free_old_query(MYSQL *mysql) DBUG_VOID_RETURN; } + +/** + Finish reading of a partial result set from the server. + Get the EOF packet, and update mysql->status + and mysql->warning_count. + + @return TRUE if a communication or protocol error, an error + is set in this case, FALSE otherwise. +*/ + +my_bool flush_one_result(MYSQL *mysql) +{ + ulong packet_length; + + DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY); + + do + { + packet_length= cli_safe_read(mysql); + /* + There is an error reading from the connection, + or (sic!) there were no error and no + data in the stream, i.e. no more data from the server. + Since we know our position in the stream (somewhere in + the middle of a result set), this latter case is an error too + -- each result set must end with a EOF packet. + cli_safe_read() has set an error for us, just return. + */ + if (packet_length == packet_error) + return TRUE; + } + while (packet_length > 8 || mysql->net.read_pos[0] != 254); + + /* Analyze EOF packet of the result set. */ + + if (protocol_41(mysql)) + { + char *pos= (char*) mysql->net.read_pos + 1; + mysql->warning_count=uint2korr(pos); + pos+=2; + mysql->server_status=uint2korr(pos); + pos+=2; + } + return FALSE; +} + + +/** + Read a packet from network. If it's an OK packet, flush it. + + @return TRUE if error, FALSE otherwise. In case of + success, is_ok_packet is set to TRUE or FALSE, + based on what we got from network. +*/ + +my_bool opt_flush_ok_packet(MYSQL *mysql, my_bool *is_ok_packet) +{ + ulong packet_length= cli_safe_read(mysql); + + if (packet_length == packet_error) + return TRUE; + + /* cli_safe_read always reads a non-empty packet. */ + DBUG_ASSERT(packet_length); + + *is_ok_packet= mysql->net.read_pos[0] == 0; + if (*is_ok_packet) + { + uchar *pos= mysql->net.read_pos + 1; + + net_field_length_ll(&pos); /* affected rows */ + net_field_length_ll(&pos); /* insert id */ + + mysql->server_status=uint2korr(pos); + pos+=2; + + if (protocol_41(mysql)) + { + mysql->warning_count=uint2korr(pos); + pos+=2; + } + } + return FALSE; +} + + /* Flush result set sent from server */ -static void cli_flush_use_result(MYSQL *mysql) +static void cli_flush_use_result(MYSQL *mysql, my_bool flush_all_results) { /* Clear the current execution status */ DBUG_ENTER("cli_flush_use_result"); DBUG_PRINT("warning",("Not all packets read, clearing them")); - for (;;) + + if (flush_one_result(mysql)) + DBUG_VOID_RETURN; /* An error occurred */ + + if (! flush_all_results) + DBUG_VOID_RETURN; + + while (mysql->server_status & SERVER_MORE_RESULTS_EXISTS) { - ulong pkt_len; - if ((pkt_len=cli_safe_read(mysql)) == packet_error) - break; - if (pkt_len <= 8 && mysql->net.read_pos[0] == 254) + my_bool is_ok_packet; + if (opt_flush_ok_packet(mysql, &is_ok_packet)) + DBUG_VOID_RETURN; /* An error occurred. */ + if (is_ok_packet) { - if (protocol_41(mysql)) - { - char *pos= (char*) mysql->net.read_pos + 1; - mysql->warning_count=uint2korr(pos); pos+=2; - mysql->server_status=uint2korr(pos); pos+=2; - } - break; /* End of data */ + /* + Indeed what we got from network was an OK packet, and we + know that OK is the last one in a multi-result-set, so + just return. + */ + DBUG_VOID_RETURN; } + /* + It's a result set, not an OK packet. A result set contains + of two result set subsequences: field metadata, terminated + with EOF packet, and result set data, again terminated with + EOF packet. Read and flush them. + */ + if (flush_one_result(mysql) || flush_one_result(mysql)) + DBUG_VOID_RETURN; /* An error occurred. */ } + DBUG_VOID_RETURN; } @@ -1009,7 +1114,7 @@ mysql_free_result(MYSQL_RES *result) mysql->unbuffered_fetch_owner= 0; if (mysql->status == MYSQL_STATUS_USE_RESULT) { - (*mysql->methods->flush_use_result)(mysql); + (*mysql->methods->flush_use_result)(mysql, FALSE); mysql->status=MYSQL_STATUS_READY; if (mysql->unbuffered_fetch_owner) *mysql->unbuffered_fetch_owner= TRUE; @@ -1036,7 +1141,6 @@ static const char *default_options[]= "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath", "character-sets-dir", "default-character-set", "interactive-timeout", "connect-timeout", "local-infile", "disable-local-infile", - "replication-probe", "enable-reads-from-master", "repl-parse-query", "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name", "multi-results", "multi-statements", "multi-queries", "secure-auth", "report-data-truncation", @@ -1184,7 +1288,7 @@ void mysql_read_default_options(struct st_mysql_options *options, my_free(options->ssl_capath, MYF(MY_ALLOW_ZERO_PTR)); options->ssl_capath = my_strdup(opt_arg, MYF(MY_WME)); break; - case 26: /* ssl_cipher */ + case 23: /* ssl_cipher */ my_free(options->ssl_cipher, MYF(MY_ALLOW_ZERO_PTR)); options->ssl_cipher= my_strdup(opt_arg, MYF(MY_WME)); break; @@ -1193,7 +1297,7 @@ void mysql_read_default_options(struct st_mysql_options *options, case 14: case 15: case 16: - case 26: + case 23: break; #endif /* HAVE_OPENSSL */ case 17: /* charset-lib */ @@ -1216,24 +1320,11 @@ void mysql_read_default_options(struct st_mysql_options *options, case 22: options->client_flag&= ~CLIENT_LOCAL_FILES; break; - case 23: /* replication probe */ -#ifndef TO_BE_DELETED - options->rpl_probe= 1; -#endif - break; - case 24: /* enable-reads-from-master */ - options->no_master_reads= 0; - break; - case 25: /* repl-parse-query */ -#ifndef TO_BE_DELETED - options->rpl_parse= 1; -#endif - break; - case 27: + case 24: /* max-allowed-packet */ if (opt_arg) options->max_allowed_packet= atoi(opt_arg); break; - case 28: /* protocol */ + case 25: /* protocol */ if ((options->protocol= find_type(opt_arg, &sql_protocol_typelib,0)) <= 0) { @@ -1241,24 +1332,24 @@ void mysql_read_default_options(struct st_mysql_options *options, exit(1); } break; - case 29: /* shared_memory_base_name */ + case 26: /* shared_memory_base_name */ #ifdef HAVE_SMEM if (options->shared_memory_base_name != def_shared_memory_base_name) my_free(options->shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR)); options->shared_memory_base_name=my_strdup(opt_arg,MYF(MY_WME)); #endif break; - case 30: + case 27: /* multi-results */ options->client_flag|= CLIENT_MULTI_RESULTS; break; - case 31: - case 32: + case 28: /* multi-statements */ + case 29: /* multi-queries */ options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS; break; - case 33: /* secure-auth */ + case 30: /* secure-auth */ options->secure_auth= TRUE; break; - case 34: /* report-data-truncation */ + case 31: /* report-data-truncation */ options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1; break; default: @@ -1585,16 +1676,8 @@ mysql_init(MYSQL *mysql) else bzero((char*) (mysql), sizeof(*(mysql))); mysql->options.connect_timeout= CONNECT_TIMEOUT; - mysql->last_used_con= mysql->next_slave= mysql->master = mysql; mysql->charset=default_client_charset_info; strmov(mysql->net.sqlstate, not_error_sqlstate); - /* - By default, we are a replication pivot. The caller must reset it - after we return if this is not the case. - */ -#ifndef TO_BE_DELETED - mysql->rpl_pivot = 1; -#endif /* Only enable LOAD DATA INFILE by default if configured with @@ -2167,6 +2250,13 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, db ? db : "(Null)", user ? user : "(Null)")); + /* Test whether we're already connected */ + if (net->vio) + { + set_mysql_error(mysql, CR_ALREADY_CONNECTED, unknown_sqlstate); + DBUG_RETURN(0); + } + /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); mysql->methods= &client_methods; @@ -2774,11 +2864,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user, mysql->reconnect=reconnect; } -#ifndef TO_BE_DELETED - if (mysql->options.rpl_probe && mysql_rpl_probe(mysql)) - goto error; -#endif - DBUG_PRINT("exit", ("Mysql handler: 0x%lx", (long) mysql)); reset_sigpipe(mysql); DBUG_RETURN(mysql); @@ -2800,28 +2885,6 @@ error: } -/* needed when we move MYSQL structure to a different address */ - -#ifndef TO_BE_DELETED -static void mysql_fix_pointers(MYSQL* mysql, MYSQL* old_mysql) -{ - MYSQL *tmp, *tmp_prev; - if (mysql->master == old_mysql) - mysql->master= mysql; - if (mysql->last_used_con == old_mysql) - mysql->last_used_con= mysql; - if (mysql->last_used_slave == old_mysql) - mysql->last_used_slave= mysql; - for (tmp_prev = mysql, tmp = mysql->next_slave; - tmp != old_mysql;tmp = tmp->next_slave) - { - tmp_prev= tmp; - } - tmp_prev->next_slave= mysql; -} -#endif - - my_bool mysql_reconnect(MYSQL *mysql) { MYSQL tmp_mysql; @@ -2840,8 +2903,7 @@ my_bool mysql_reconnect(MYSQL *mysql) mysql_init(&tmp_mysql); tmp_mysql.options= mysql->options; tmp_mysql.options.my_cnf_file= tmp_mysql.options.my_cnf_group= 0; - tmp_mysql.rpl_pivot= mysql->rpl_pivot; - + if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, mysql->db, mysql->port, mysql->unix_socket, mysql->client_flag | CLIENT_REMEMBER_OPTIONS)) @@ -2875,7 +2937,6 @@ my_bool mysql_reconnect(MYSQL *mysql) mysql->free_me=0; mysql_close(mysql); *mysql=tmp_mysql; - mysql_fix_pointers(mysql, &tmp_mysql); /* adjust connection pointers */ net_clear(&mysql->net, 1); mysql->affected_rows= ~(my_ulonglong) 0; DBUG_RETURN(0); @@ -3053,23 +3114,6 @@ void STDCALL mysql_close(MYSQL *mysql) mysql_close_free_options(mysql); mysql_close_free(mysql); mysql_detach_stmt_list(&mysql->stmts, "mysql_close"); -#ifndef TO_BE_DELETED - /* free/close slave list */ - if (mysql->rpl_pivot) - { - MYSQL* tmp; - for (tmp = mysql->next_slave; tmp != mysql; ) - { - /* trick to avoid following freed pointer */ - MYSQL* tmp1 = tmp->next_slave; - mysql_close(tmp); - tmp = tmp1; - } - mysql->rpl_pivot=0; - } -#endif - if (mysql != mysql->master) - mysql_close(mysql->master); #ifndef MYSQL_SERVER if (mysql->thd) (*mysql->methods->free_embedded_thd)(mysql); @@ -3089,12 +3133,6 @@ static my_bool cli_read_query_result(MYSQL *mysql) ulong length; DBUG_ENTER("cli_read_query_result"); - /* - Read from the connection which we actually used, which - could differ from the original connection if we have slaves - */ - mysql = mysql->last_used_con; - if ((length = cli_safe_read(mysql)) == packet_error) DBUG_RETURN(1); free_old_query(mysql); /* Free old result */ @@ -3169,23 +3207,6 @@ int STDCALL mysql_send_query(MYSQL* mysql, const char* query, ulong length) { DBUG_ENTER("mysql_send_query"); - DBUG_PRINT("enter",("rpl_parse: %d rpl_pivot: %d", - mysql->options.rpl_parse, mysql->rpl_pivot)); -#ifndef TO_BE_DELETED - if (mysql->options.rpl_parse && mysql->rpl_pivot) - { - switch (mysql_rpl_query_type(query, length)) { - case MYSQL_RPL_MASTER: - DBUG_RETURN(mysql_master_send_query(mysql, query, length)); - case MYSQL_RPL_SLAVE: - DBUG_RETURN(mysql_slave_send_query(mysql, query, length)); - case MYSQL_RPL_ADMIN: - break; /* fall through */ - } - } - mysql->last_used_con = mysql; -#endif - DBUG_RETURN(simple_command(mysql, COM_QUERY, (uchar*) query, length, 1)); } @@ -3212,8 +3233,7 @@ MYSQL_RES * STDCALL mysql_store_result(MYSQL *mysql) { MYSQL_RES *result; DBUG_ENTER("mysql_store_result"); - /* read from the actually used connection */ - mysql = mysql->last_used_con; + if (!mysql->fields) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) @@ -3268,8 +3288,6 @@ static MYSQL_RES * cli_use_result(MYSQL *mysql) MYSQL_RES *result; DBUG_ENTER("cli_use_result"); - mysql = mysql->last_used_con; - if (!mysql->fields) DBUG_RETURN(0); if (mysql->status != MYSQL_STATUS_GET_RESULT) |