diff options
author | Alexander Nozdrin <alik@sun.com> | 2009-12-11 12:39:38 +0300 |
---|---|---|
committer | Alexander Nozdrin <alik@sun.com> | 2009-12-11 12:39:38 +0300 |
commit | 567671368723c704d60902b4d0ccff951b414552 (patch) | |
tree | 965519a5b0af3f33624c7e16fd61b58d15f42372 /libmysql | |
parent | efee0608316e4cc034a3e62d05980eef8530843d (diff) | |
parent | ceefe7bb50b17b72e88851e3b98642e89a4cddae (diff) | |
download | mariadb-git-567671368723c704d60902b4d0ccff951b414552.tar.gz |
Manual merge from mysql-trunk.
Conflicts:
- client/mysqltest.cc
- mysql-test/collections/default.experimental
- mysql-test/suite/rpl/t/disabled.def
- sql/mysqld.cc
- sql/opt_range.cc
- sql/sp.cc
- sql/sql_acl.cc
- sql/sql_partition.cc
- sql/sql_table.cc
Diffstat (limited to 'libmysql')
-rwxr-xr-x | libmysql/CMakeLists.txt | 28 | ||||
-rw-r--r-- | libmysql/Makefile.shared | 2 | ||||
-rw-r--r-- | libmysql/client_settings.h | 16 | ||||
-rw-r--r-- | libmysql/errmsg.c | 9 | ||||
-rw-r--r-- | libmysql/libmysql.c | 520 | ||||
-rw-r--r-- | libmysql/libmysql.def | 9 | ||||
-rw-r--r-- | libmysql/manager.c | 269 |
7 files changed, 125 insertions, 728 deletions
diff --git a/libmysql/CMakeLists.txt b/libmysql/CMakeLists.txt index 55138e4aa06..84ad50e03e3 100755 --- a/libmysql/CMakeLists.txt +++ b/libmysql/CMakeLists.txt @@ -14,8 +14,6 @@ # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA INCLUDE("${PROJECT_SOURCE_DIR}/win/mysql_manifest.cmake") -SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") -SET(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -DSAFEMALLOC -DSAFE_MUTEX") # Note that we don't link with the libraries "strings" or "mysys" # here, instead we recompile the files needed and include them @@ -75,7 +73,7 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../mysys/hash.c ../mysys/my_sleep.c ../mysys/default_modify.c get_password.c ../strings/int2str.c ../strings/is_prefix.c libmysql.c ../mysys/list.c ../strings/llstr.c - ../strings/longlong2str.c manager.c ../mysys/mf_arr_appstr.c ../mysys/mf_cache.c + ../strings/longlong2str.c ../mysys/mf_arr_appstr.c ../mysys/mf_cache.c ../mysys/mf_dirname.c ../mysys/mf_fn_ext.c ../mysys/mf_format.c ../mysys/mf_iocache.c ../mysys/mf_iocache2.c ../mysys/mf_loadpath.c ../mysys/mf_pack.c ../mysys/mf_path.c ../mysys/mf_tempfile.c ../mysys/mf_unixpath.c @@ -98,33 +96,17 @@ SET(CLIENT_SOURCES ../mysys/array.c ../strings/bchange.c ../strings/bmove.c ../strings/strtoll.c ../strings/strtoull.c ../strings/strxmov.c ../strings/strxnmov.c ../mysys/thr_mutex.c ../mysys/typelib.c ../vio/vio.c ../vio/viosocket.c ../vio/viossl.c ../vio/viosslfactories.c ../strings/xml.c ../mysys/mf_qsort.c - ../mysys/my_getsystime.c ../mysys/my_sync.c ${LIB_SOURCES}) - -# Need to set USE_TLS for building the DLL, since __declspec(thread) -# approach to thread local storage does not work properly in DLLs. -# -# The static library might be used to form another DLL, as is the case -# with the ODBC driver, so it has to be compiled with USE_TLS as well. -# -# We create a third library without USE_TLS for internal use. We can't -# be sure that some client application part of this build doesn't go -# beond the documented API, and try access the Thread Local Storage. -# The "_notls" means no Tls*() functions used, i.e. "static" TLS. + ../mysys/my_getsystime.c ../mysys/my_sync.c ../mysys/my_winerr.c ../mysys/my_winfile.c ${LIB_SOURCES}) + + ADD_LIBRARY(mysqlclient STATIC ${CLIENT_SOURCES}) ADD_DEPENDENCIES(mysqlclient GenError) TARGET_LINK_LIBRARIES(mysqlclient) -ADD_LIBRARY(mysqlclient_notls STATIC ${CLIENT_SOURCES}) -ADD_DEPENDENCIES(mysqlclient_notls GenError) -TARGET_LINK_LIBRARIES(mysqlclient_notls) - ADD_LIBRARY(libmysql SHARED ${CLIENT_SOURCES} dll.c libmysql.def) -IF(WIN32) - SET_TARGET_PROPERTIES(libmysql mysqlclient PROPERTIES COMPILE_FLAGS "-DUSE_TLS") -ENDIF(WIN32) ADD_DEPENDENCIES(libmysql GenError) -TARGET_LINK_LIBRARIES(libmysql wsock32) +TARGET_LINK_LIBRARIES(libmysql) IF(EMBED_MANIFESTS) MYSQL_EMBED_MANIFEST("myTest" "asInvoker") diff --git a/libmysql/Makefile.shared b/libmysql/Makefile.shared index eb4fd75ed11..acc709bfb89 100644 --- a/libmysql/Makefile.shared +++ b/libmysql/Makefile.shared @@ -31,7 +31,7 @@ pkglib_LTLIBRARIES = $(target) noinst_PROGRAMS = conf_to_src -target_sources = libmysql.c password.c manager.c \ +target_sources = libmysql.c password.c \ get_password.c errmsg.c mystringsobjects = strmov.lo strxmov.lo strxnmov.lo strnmov.lo \ diff --git a/libmysql/client_settings.h b/libmysql/client_settings.h index f87e625771f..aaec08d1b1e 100644 --- a/libmysql/client_settings.h +++ b/libmysql/client_settings.h @@ -13,12 +13,22 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#ifndef CLIENT_SETTINGS_INCLUDED +#define CLIENT_SETTINGS_INCLUDED +#else +#error You have already included an client_settings.h and it should not be included twice +#endif /* CLIENT_SETTINGS_INCLUDED */ + extern uint mysql_port; extern char * mysql_unix_port; -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | \ - CLIENT_TRANSACTIONS | \ - CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION) +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | \ + CLIENT_LONG_FLAG | \ + CLIENT_TRANSACTIONS | \ + CLIENT_PROTOCOL_41 | \ + CLIENT_SECURE_CONNECTION | \ + CLIENT_MULTI_RESULTS | \ + CLIENT_PS_MULTI_RESULTS) sig_handler my_pipe_sig_handler(int sig); void read_user_name(char *name); diff --git a/libmysql/errmsg.c b/libmysql/errmsg.c index 95ee6862aa8..d0ed44bd7aa 100644 --- a/libmysql/errmsg.c +++ b/libmysql/errmsg.c @@ -85,6 +85,7 @@ const char *client_errors[]= "Lost connection to MySQL server at '%s', system error: %d", "Statement closed indirectly because of a preceeding %s() call", "The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again", + "This handle is already connected. Use a separate handle for each connection." "" }; @@ -151,6 +152,7 @@ const char *client_errors[]= "Lost connection to MySQL server at '%s', system error: %d", "Statement closed indirectly because of a preceeding %s() call", "The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again", + "This handle is already connected. Use a separate handle for each connection." "" }; @@ -215,10 +217,15 @@ const char *client_errors[]= "Lost connection to MySQL server at '%s', system error: %d", "Statement closed indirectly because of a preceeding %s() call", "The number of columns in the result set differs from the number of bound buffers. You must reset the statement, rebind the result set columns, and execute the statement again", + "This handle is already connected. Use a separate handle for each connection." "" }; #endif +const char** get_client_errmsgs() +{ + return client_errors; +} /* Register client error messages for use with my_error(). @@ -232,7 +239,7 @@ const char *client_errors[]= void init_client_errs(void) { - (void) my_error_register(client_errors, CR_ERROR_FIRST, CR_ERROR_LAST); + (void) my_error_register(get_client_errmsgs, CR_ERROR_FIRST, CR_ERROR_LAST); } diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c index 1264f2765ba..b8935333028 100644 --- a/libmysql/libmysql.c +++ b/libmysql/libmysql.c @@ -131,7 +131,7 @@ int STDCALL mysql_server_init(int argc __attribute__((unused)), mysql_port = MYSQL_PORT; #ifndef MSDOS { - struct servent *serv_ptr; + struct servent *serv_ptr __attribute__((unused)); char *env; /* @@ -249,16 +249,6 @@ void STDCALL mysql_thread_end() #endif } -/* - Let the user specify that we don't want SIGPIPE; This doesn't however work - with threaded applications as we can have multiple read in progress. -*/ -static MYSQL* spawn_init(MYSQL* parent, const char* host, - unsigned int port, - const char* user, - const char* passwd); - - /* Expand wildcard to a sql string @@ -320,7 +310,7 @@ mysql_debug(const char *debug __attribute__((unused))) /************************************************************************** - Close the server connection if we get a SIGPIPE + Ignore SIGPIPE handler ARGSUSED **************************************************************************/ @@ -333,305 +323,6 @@ my_pipe_sig_handler(int sig __attribute__((unused))) #endif } -/* perform query on master */ -my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q, - unsigned long length) -{ - DBUG_ENTER("mysql_master_query"); - if (mysql_master_send_query(mysql, q, length)) - DBUG_RETURN(1); - DBUG_RETURN((*mysql->methods->read_query_result)(mysql)); -} - -my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q, - unsigned long length) -{ - MYSQL *master = mysql->master; - DBUG_ENTER("mysql_master_send_query"); - if (!master->net.vio && !mysql_real_connect(master,0,0,0,0,0,0,0)) - DBUG_RETURN(1); - master->reconnect= 1; - mysql->last_used_con = master; - DBUG_RETURN(simple_command(master, COM_QUERY, (const uchar*) q, length, 1)); -} - - -/* perform query on slave */ -my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q, - unsigned long length) -{ - DBUG_ENTER("mysql_slave_query"); - if (mysql_slave_send_query(mysql, q, length)) - DBUG_RETURN(1); - DBUG_RETURN((*mysql->methods->read_query_result)(mysql)); -} - - -my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q, - unsigned long length) -{ - MYSQL* last_used_slave, *slave_to_use = 0; - DBUG_ENTER("mysql_slave_send_query"); - - if ((last_used_slave = mysql->last_used_slave)) - slave_to_use = last_used_slave->next_slave; - else - slave_to_use = mysql->next_slave; - /* - Next_slave is always safe to use - we have a circular list of slaves - if there are no slaves, mysql->next_slave == mysql - */ - mysql->last_used_con = mysql->last_used_slave = slave_to_use; - if (!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0, - 0,0,0,0)) - DBUG_RETURN(1); - slave_to_use->reconnect= 1; - DBUG_RETURN(simple_command(slave_to_use, COM_QUERY, (const uchar*) q, - length, 1)); -} - - -/* enable/disable parsing of all queries to decide - if they go on master or slave */ -void STDCALL mysql_enable_rpl_parse(MYSQL* mysql) -{ - mysql->options.rpl_parse = 1; -} - -void STDCALL mysql_disable_rpl_parse(MYSQL* mysql) -{ - mysql->options.rpl_parse = 0; -} - -/* get the value of the parse flag */ -int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql) -{ - return mysql->options.rpl_parse; -} - -/* enable/disable reads from master */ -void STDCALL mysql_enable_reads_from_master(MYSQL* mysql) -{ - mysql->options.no_master_reads = 0; -} - -void STDCALL mysql_disable_reads_from_master(MYSQL* mysql) -{ - mysql->options.no_master_reads = 1; -} - -/* get the value of the master read flag */ -my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql) -{ - return !(mysql->options.no_master_reads); -} - - -/* - We may get an error while doing replication internals. - In this case, we add a special explanation to the original - error -*/ - -static void expand_error(MYSQL* mysql, int error) -{ - char tmp[MYSQL_ERRMSG_SIZE]; - char *p; - uint err_length; - strmake(tmp, mysql->net.last_error, MYSQL_ERRMSG_SIZE-1); - p = strmake(mysql->net.last_error, ER(error), MYSQL_ERRMSG_SIZE-1); - err_length= (uint) (p - mysql->net.last_error); - strmake(p, tmp, MYSQL_ERRMSG_SIZE-1 - err_length); - mysql->net.last_errno = error; -} - -/* - This function assumes we have just called SHOW SLAVE STATUS and have - read the given result and row -*/ - -static my_bool get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row) -{ - MYSQL* master; - DBUG_ENTER("get_master"); - if (mysql_num_fields(res) < 3) - DBUG_RETURN(1); /* safety */ - - /* use the same username and password as the original connection */ - if (!(master = spawn_init(mysql, row[0], atoi(row[2]), 0, 0))) - DBUG_RETURN(1); - mysql->master = master; - DBUG_RETURN(0); -} - - -/* - Assuming we already know that mysql points to a master connection, - retrieve all the slaves -*/ - -static my_bool get_slaves_from_master(MYSQL* mysql) -{ - MYSQL_RES* res = 0; - MYSQL_ROW row; - my_bool error = 1; - int has_auth_info; - int port_ind; - DBUG_ENTER("get_slaves_from_master"); - - if (!mysql->net.vio && !mysql_real_connect(mysql,0,0,0,0,0,0,0)) - { - expand_error(mysql, CR_PROBE_MASTER_CONNECT); - DBUG_RETURN(1); - } - mysql->reconnect= 1; - - if (mysql_query(mysql, "SHOW SLAVE HOSTS") || - !(res = mysql_store_result(mysql))) - { - expand_error(mysql, CR_PROBE_SLAVE_HOSTS); - DBUG_RETURN(1); - } - - switch (mysql_num_fields(res)) { - case 5: - has_auth_info = 0; - port_ind=2; - break; - case 7: - has_auth_info = 1; - port_ind=4; - break; - default: - goto err; - } - - while ((row = mysql_fetch_row(res))) - { - MYSQL* slave; - const char* tmp_user, *tmp_pass; - - if (has_auth_info) - { - tmp_user = row[2]; - tmp_pass = row[3]; - } - else - { - tmp_user = mysql->user; - tmp_pass = mysql->passwd; - } - - if (!(slave = spawn_init(mysql, row[1], atoi(row[port_ind]), - tmp_user, tmp_pass))) - goto err; - - /* Now add slave into the circular linked list */ - slave->next_slave = mysql->next_slave; - mysql->next_slave = slave; - } - error = 0; -err: - if (res) - mysql_free_result(res); - DBUG_RETURN(error); -} - - -my_bool STDCALL mysql_rpl_probe(MYSQL* mysql) -{ - MYSQL_RES *res= 0; - MYSQL_ROW row; - my_bool error= 1; - DBUG_ENTER("mysql_rpl_probe"); - - /* - First determine the replication role of the server we connected to - the most reliable way to do this is to run SHOW SLAVE STATUS and see - if we have a non-empty master host. This is still not fool-proof - - it is not a sin to have a master that has a dormant slave thread with - a non-empty master host. However, it is more reliable to check - for empty master than whether the slave thread is actually running - */ - if (mysql_query(mysql, "SHOW SLAVE STATUS") || - !(res = mysql_store_result(mysql))) - { - expand_error(mysql, CR_PROBE_SLAVE_STATUS); - DBUG_RETURN(1); - } - - row= mysql_fetch_row(res); - /* - Check master host for emptiness/NULL - For MySQL 4.0 it's enough to check for row[0] - */ - if (row && row[0] && *(row[0])) - { - /* this is a slave, ask it for the master */ - if (get_master(mysql, res, row) || get_slaves_from_master(mysql)) - goto err; - } - else - { - mysql->master = mysql; - if (get_slaves_from_master(mysql)) - goto err; - } - - error = 0; -err: - if (res) - mysql_free_result(res); - DBUG_RETURN(error); -} - - -/* - Make a not so fool-proof decision on where the query should go, to - the master or the slave. Ideally the user should always make this - decision himself with mysql_master_query() or mysql_slave_query(). - However, to be able to more easily port the old code, we support the - option of an educated guess - this should work for most applications, - however, it may make the wrong decision in some particular cases. If - that happens, the user would have to change the code to call - mysql_master_query() or mysql_slave_query() explicitly in the place - where we have made the wrong decision -*/ - -enum mysql_rpl_type -STDCALL mysql_rpl_query_type(const char* q, int len) -{ - const char *q_end= q + len; - for (; q < q_end; ++q) - { - char c; - if (my_isalpha(&my_charset_latin1, (c= *q))) - { - switch (my_tolower(&my_charset_latin1,c)) { - case 'i': /* insert */ - case 'u': /* update or unlock tables */ - case 'l': /* lock tables or load data infile */ - case 'd': /* drop or delete */ - case 'a': /* alter */ - return MYSQL_RPL_MASTER; - case 'c': /* create or check */ - return my_tolower(&my_charset_latin1,q[1]) == 'h' ? MYSQL_RPL_ADMIN : - MYSQL_RPL_MASTER; - case 's': /* select or show */ - return my_tolower(&my_charset_latin1,q[1]) == 'h' ? MYSQL_RPL_ADMIN : - MYSQL_RPL_SLAVE; - case 'f': /* flush */ - case 'r': /* repair */ - case 'g': /* grant */ - return MYSQL_RPL_ADMIN; - default: - return MYSQL_RPL_SLAVE; - } - } - } - return MYSQL_RPL_MASTER; /* By default, send to master */ -} - /************************************************************************** Connect to sql server @@ -1093,68 +784,6 @@ mysql_query(MYSQL *mysql, const char *query) } -static MYSQL* spawn_init(MYSQL* parent, const char* host, - unsigned int port, const char* user, - const char* passwd) -{ - MYSQL* child; - DBUG_ENTER("spawn_init"); - if (!(child= mysql_init(0))) - DBUG_RETURN(0); - - child->options.user= my_strdup((user) ? user : - (parent->user ? parent->user : - parent->options.user), MYF(0)); - child->options.password= my_strdup((passwd) ? passwd : - (parent->passwd ? - parent->passwd : - parent->options.password), MYF(0)); - child->options.port= port; - child->options.host= my_strdup((host) ? host : - (parent->host ? - parent->host : - parent->options.host), MYF(0)); - if (parent->db) - child->options.db= my_strdup(parent->db, MYF(0)); - else if (parent->options.db) - child->options.db= my_strdup(parent->options.db, MYF(0)); - - /* - rpl_pivot is set to 1 in mysql_init(); Reset it as we are not doing - replication here - */ - child->rpl_pivot= 0; - DBUG_RETURN(child); -} - - -int -STDCALL mysql_set_master(MYSQL* mysql, const char* host, - unsigned int port, const char* user, - const char* passwd) -{ - if (mysql->master != mysql && !mysql->master->rpl_pivot) - mysql_close(mysql->master); - if (!(mysql->master = spawn_init(mysql, host, port, user, passwd))) - return 1; - return 0; -} - - -int -STDCALL mysql_add_slave(MYSQL* mysql, const char* host, - unsigned int port, - const char* user, - const char* passwd) -{ - MYSQL* slave; - if (!(slave = spawn_init(mysql, host, port, user, passwd))) - return 1; - slave->next_slave = mysql->next_slave; - mysql->next_slave = slave; - return 0; -} - /************************************************************************** Return next field of the query results **************************************************************************/ @@ -1483,17 +1112,17 @@ MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res) unsigned int STDCALL mysql_field_count(MYSQL *mysql) { - return mysql->last_used_con->field_count; + return mysql->field_count; } my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) { - return mysql->last_used_con->affected_rows; + return mysql->affected_rows; } my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) { - return mysql->last_used_con->insert_id; + return mysql->insert_id; } const char *STDCALL mysql_sqlstate(MYSQL *mysql) @@ -1858,7 +1487,6 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt) MYSQL_DATA *fields_data; DBUG_ENTER("cli_read_prepare_result"); - mysql= mysql->last_used_con; if ((packet_length= cli_safe_read(mysql)) == packet_error) DBUG_RETURN(1); mysql->warning_count= 0; @@ -2092,7 +1720,9 @@ static void alloc_stmt_fields(MYSQL_STMT *stmt) { MYSQL_FIELD *fields, *field, *end; MEM_ROOT *alloc= &stmt->mem_root; - MYSQL *mysql= stmt->mysql->last_used_con; + MYSQL *mysql= stmt->mysql; + + DBUG_ASSERT(mysql->field_count); stmt->field_count= mysql->field_count; @@ -2115,18 +1745,21 @@ static void alloc_stmt_fields(MYSQL_STMT *stmt) field= stmt->fields; field && fields < end; fields++, field++) { - field->db = strdup_root(alloc,fields->db); - field->table = strdup_root(alloc,fields->table); - field->org_table= strdup_root(alloc,fields->org_table); - field->name = strdup_root(alloc,fields->name); - field->org_name = strdup_root(alloc,fields->org_name); - field->charsetnr= fields->charsetnr; - field->length = fields->length; - field->type = fields->type; - field->flags = fields->flags; - field->decimals = fields->decimals; - field->def = fields->def ? strdup_root(alloc,fields->def): 0; - field->max_length= 0; + *field= *fields; /* To copy all numeric parts. */ + field->catalog= strmake_root(alloc, fields->catalog, + fields->catalog_length); + field->db= strmake_root(alloc, fields->db, fields->db_length); + field->table= strmake_root(alloc, fields->table, fields->table_length); + field->org_table= strmake_root(alloc, fields->org_table, + fields->org_table_length); + field->name= strmake_root(alloc, fields->name, fields->name_length); + field->org_name= strmake_root(alloc, fields->org_name, + fields->org_name_length); + field->def= fields->def ? strmake_root(alloc, fields->def, + fields->def_length) : 0; + field->def_length= field->def ? fields->def_length : 0; + field->extension= 0; /* Avoid dangling links. */ + field->max_length= 0; /* max_length is set in mysql_stmt_store_result() */ } } @@ -2479,7 +2112,6 @@ static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length) DBUG_ENTER("execute"); DBUG_DUMP("packet", (uchar *) packet, length); - mysql->last_used_con= mysql; int4store(buff, stmt->stmt_id); /* Send stmt id to server */ buff[4]= (char) stmt->flags; int4store(buff+5, 1); /* iteration count */ @@ -2854,6 +2486,33 @@ static void reinit_result_set_metadata(MYSQL_STMT *stmt) } +static void prepare_to_fetch_result(MYSQL_STMT *stmt) +{ + if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS) + { + stmt->mysql->status= MYSQL_STATUS_READY; + stmt->read_row_func= stmt_read_row_from_cursor; + } + else if (stmt->flags & CURSOR_TYPE_READ_ONLY) + { + /* + This is a single-row result set, a result set with no rows, EXPLAIN, + SHOW VARIABLES, or some other command which either a) bypasses the + cursors framework in the server and writes rows directly to the + network or b) is more efficient if all (few) result set rows are + precached on client and server's resources are freed. + */ + mysql_stmt_store_result(stmt); + } + else + { + stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled; + stmt->unbuffered_fetch_cancelled= FALSE; + stmt->read_row_func= stmt_read_row_unbuffered; + } +} + + /* Send placeholders data to server (if there are placeholders) and execute prepared statement. @@ -2921,28 +2580,7 @@ int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt) if (mysql->field_count) { reinit_result_set_metadata(stmt); - if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS) - { - mysql->status= MYSQL_STATUS_READY; - stmt->read_row_func= stmt_read_row_from_cursor; - } - else if (stmt->flags & CURSOR_TYPE_READ_ONLY) - { - /* - This is a single-row result set, a result set with no rows, EXPLAIN, - SHOW VARIABLES, or some other command which either a) bypasses the - cursors framework in the server and writes rows directly to the - network or b) is more efficient if all (few) result set rows are - precached on client and server's resources are freed. - */ - mysql_stmt_store_result(stmt); - } - else - { - stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled; - stmt->unbuffered_fetch_cancelled= FALSE; - stmt->read_row_func= stmt_read_row_unbuffered; - } + prepare_to_fetch_result(stmt); } DBUG_RETURN(test(stmt->last_errno)); } @@ -4407,7 +4045,6 @@ static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field) field->max_length= 10; /* 2003-11-11 */ param->skip_result= skip_result_with_length; break; - break; case MYSQL_TYPE_DATETIME: case MYSQL_TYPE_TIMESTAMP: param->skip_result= skip_result_with_length; @@ -4689,7 +4326,6 @@ int cli_read_binary_rows(MYSQL_STMT *stmt) } net = &mysql->net; - mysql= mysql->last_used_con; while ((pkt_len= cli_safe_read(mysql)) != packet_error) { @@ -4787,8 +4423,6 @@ int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt) DBUG_RETURN(1); } - mysql= mysql->last_used_con; - if (!stmt->field_count) DBUG_RETURN(0); @@ -4990,7 +4624,7 @@ static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags) if (stmt->field_count && mysql->status != MYSQL_STATUS_READY) { /* There is a result set and it belongs to this statement */ - (*mysql->methods->flush_use_result)(mysql); + (*mysql->methods->flush_use_result)(mysql, FALSE); if (mysql->unbuffered_fetch_owner) *mysql->unbuffered_fetch_owner= TRUE; mysql->status= MYSQL_STATUS_READY; @@ -5074,7 +4708,7 @@ my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt) Flush result set of the connection. If it does not belong to this statement, set a warning. */ - (*mysql->methods->flush_use_result)(mysql); + (*mysql->methods->flush_use_result)(mysql, TRUE); if (mysql->unbuffered_fetch_owner) *mysql->unbuffered_fetch_owner= TRUE; mysql->status= MYSQL_STATUS_READY; @@ -5193,8 +4827,7 @@ my_bool STDCALL mysql_more_results(MYSQL *mysql) my_bool res; DBUG_ENTER("mysql_more_results"); - res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ? - 1: 0); + res= ((mysql->server_status & SERVER_MORE_RESULTS_EXISTS) ? 1: 0); DBUG_PRINT("exit",("More results exists ? %d", res)); DBUG_RETURN(res); } @@ -5216,13 +4849,56 @@ int STDCALL mysql_next_result(MYSQL *mysql) net_clear_error(&mysql->net); mysql->affected_rows= ~(my_ulonglong) 0; - if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) + if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS) DBUG_RETURN((*mysql->methods->next_result)(mysql)); DBUG_RETURN(-1); /* No more results */ } +int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt) +{ + MYSQL *mysql= stmt->mysql; + int rc; + DBUG_ENTER("mysql_stmt_next_result"); + + if (!mysql) + DBUG_RETURN(1); + + if (stmt->last_errno) + DBUG_RETURN(stmt->last_errno); + + if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS) + { + if (reset_stmt_handle(stmt, RESET_STORE_RESULT)) + DBUG_RETURN(1); + } + + rc= mysql_next_result(mysql); + + if (rc) + { + set_stmt_errmsg(stmt, &mysql->net); + DBUG_RETURN(rc); + } + + stmt->state= MYSQL_STMT_EXECUTE_DONE; + stmt->bind_result_done= FALSE; + + if (mysql->field_count) + { + alloc_stmt_fields(stmt); + prepare_to_fetch_result(stmt); + } + else + { + stmt->field_count= mysql->field_count; + } + + DBUG_RETURN(0); +} + + MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql) { return (*mysql->methods->use_result)(mysql); diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def index 81f86dc8726..f6e93ca35fb 100644 --- a/libmysql/libmysql.def +++ b/libmysql/libmysql.def @@ -135,15 +135,6 @@ EXPORTS client_errors mysql_set_local_infile_default mysql_set_local_infile_handler - mysql_disable_reads_from_master - mysql_disable_rpl_parse - mysql_enable_reads_from_master - mysql_enable_rpl_parse - mysql_master_query - mysql_rpl_parse_enabled - mysql_rpl_probe - mysql_rpl_query_type - mysql_slave_query mysql_embedded mysql_server_init mysql_server_end diff --git a/libmysql/manager.c b/libmysql/manager.c deleted file mode 100644 index 53ffffa55c0..00000000000 --- a/libmysql/manager.c +++ /dev/null @@ -1,269 +0,0 @@ -/* Copyright (C) 2000-2004 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation. - - There are special exceptions to the terms and conditions of the GPL as it - is applied to this software. View the full text of the exception in file - EXCEPTIONS-CLIENT in the directory of this software distribution. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - -#include <my_global.h> -#if defined(THREAD) -#include <my_pthread.h> /* because of signal() */ -#endif -#include "mysql.h" -#include "mysql_version.h" -#include "mysqld_error.h" -#include <my_sys.h> -#include <mysys_err.h> -#include <m_string.h> -#include <m_ctype.h> -#include <my_net.h> -#include <errmsg.h> -#include <violite.h> -#include <sys/stat.h> -#include <signal.h> -#include <errno.h> - -#if defined(__NETWARE__) -#include <netdb.h> -#include <sys/select.h> -#include <sys/utsname.h> -#elif !defined( __WIN__) -#include <sys/resource.h> -#ifdef HAVE_SYS_UN_H -# include <sys/un.h> -#endif -#include <netdb.h> -#ifdef HAVE_SELECT_H -# include <select.h> -#endif -#ifdef HAVE_SYS_SELECT_H -#include <sys/select.h> -#endif -#include <sys/utsname.h> -#endif /* __WIN__ */ - -#ifndef INADDR_NONE -#define INADDR_NONE -1 -#endif - -#define RES_BUF_SHIFT 5 -#define NET_BUF_SIZE 2048 - -MYSQL_MANAGER* STDCALL mysql_manager_init(MYSQL_MANAGER* con) -{ - int net_buf_size=NET_BUF_SIZE; - if (!con) - { - if (!(con=(MYSQL_MANAGER*)my_malloc(sizeof(*con)+net_buf_size, - MYF(MY_WME|MY_ZEROFILL)))) - return 0; - con->free_me=1; - con->net_buf=(char*)con+sizeof(*con); - } - else - { - bzero((char*)con,sizeof(*con)); - if (!(con->net_buf=my_malloc(net_buf_size,MYF(0)))) - return 0; - } - con->net_buf_pos=con->net_data_end=con->net_buf; - con->net_buf_size=net_buf_size; - return con; -} - -MYSQL_MANAGER* STDCALL mysql_manager_connect(MYSQL_MANAGER* con, - const char* host, - const char* user, - const char* passwd, - unsigned int port) -{ - my_socket sock; - struct sockaddr_in sock_addr; - in_addr_t ip_addr; - char msg_buf[MAX_MYSQL_MANAGER_MSG]; - int msg_len; - Vio* vio; - my_bool not_used; - - if (!host) - host="localhost"; - if (!user) - user="root"; - if (!passwd) - passwd=""; - - if ((sock=(my_socket)socket(AF_INET,SOCK_STREAM,0)) == INVALID_SOCKET) - { - con->last_errno=errno; - strmov(con->last_error,"Cannot create socket"); - goto err; - } - if (!(vio=vio_new(sock,VIO_TYPE_TCPIP,FALSE))) - { - con->last_errno=ENOMEM; - strmov(con->last_error,"Cannot create network I/O object"); - goto err; - } - vio_blocking(vio, TRUE, ¬_used); - my_net_init(&con->net,vio); - bzero((char*) &sock_addr,sizeof(sock_addr)); - sock_addr.sin_family = AF_INET; - if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) - { - memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); - } - else - { - int tmp_errno; - struct hostent tmp_hostent,*hp; - char buff2[GETHOSTBYNAME_BUFF_SIZE]; - hp = my_gethostbyname_r(host,&tmp_hostent,buff2,sizeof(buff2), - &tmp_errno); - if (!hp) - { - con->last_errno=tmp_errno; - sprintf(con->last_error,"Could not resolve host '%-.64s'",host); - my_gethostbyname_r_free(); - goto err; - } - memcpy(&sock_addr.sin_addr,hp->h_addr, (size_t) hp->h_length); - my_gethostbyname_r_free(); - } - sock_addr.sin_port = (ushort) htons((ushort) port); - if (my_connect(sock,(struct sockaddr *) &sock_addr, sizeof(sock_addr), - 0)) - { - con->last_errno=errno; - sprintf(con->last_error ,"Could not connect to %-.64s", host); - goto err; - } - /* read the greating */ - if (my_net_read(&con->net) == packet_error) - { - con->last_errno=errno; - strmov(con->last_error,"Read error on socket"); - goto err; - } - sprintf(msg_buf,"%-.16s %-.16s\n",user,passwd); - msg_len=strlen(msg_buf); - if (my_net_write(&con->net,(uchar*) msg_buf,msg_len) || net_flush(&con->net)) - { - con->last_errno=con->net.last_errno; - strmov(con->last_error,"Write error on socket"); - goto err; - } - if (my_net_read(&con->net) == packet_error) - { - con->last_errno=errno; - strmov(con->last_error,"Read error on socket"); - goto err; - } - if ((con->cmd_status=atoi((char*) con->net.read_pos)) != MANAGER_OK) - { - strmov(con->last_error,"Access denied"); - goto err; - } - if (!my_multi_malloc(MYF(0), &con->host, (uint)strlen(host)+1, - &con->user, (uint)strlen(user)+1, - &con->passwd, (uint)strlen(passwd)+1, - NullS)) - { - con->last_errno=ENOMEM; - strmov(con->last_error,"Out of memory"); - goto err; - } - strmov(con->host,host); - strmov(con->user,user); - strmov(con->passwd,passwd); - return con; - -err: - { - my_bool free_me=con->free_me; - con->free_me=0; - mysql_manager_close(con); - con->free_me=free_me; - } - return 0; -} - -void STDCALL mysql_manager_close(MYSQL_MANAGER* con) -{ - /* - No need to free con->user and con->passwd, because they were - allocated in my_multimalloc() along with con->host, freeing - con->hosts frees the whole block - */ - my_free((uchar*)con->host,MYF(MY_ALLOW_ZERO_PTR)); - net_end(&con->net); - if (con->free_me) - my_free((uchar*)con,MYF(0)); -} - - -int STDCALL mysql_manager_command(MYSQL_MANAGER* con,const char* cmd, - int cmd_len) -{ - if (!cmd_len) - cmd_len=strlen(cmd); - if (my_net_write(&con->net,(const uchar*)cmd,cmd_len) || net_flush(&con->net)) - { - con->last_errno=errno; - strmov(con->last_error,"Write error on socket"); - return 1; - } - con->eof=0; - return 0; -} - - -int STDCALL mysql_manager_fetch_line(MYSQL_MANAGER* con, char* res_buf, - int res_buf_size) -{ - char* res_buf_end=res_buf+res_buf_size; - char* net_buf=(char*) con->net.read_pos, *net_buf_end; - int res_buf_shift=RES_BUF_SHIFT; - ulong num_bytes; - - if (res_buf_size<RES_BUF_SHIFT) - { - con->last_errno=ENOMEM; - strmov(con->last_error,"Result buffer too small"); - return 1; - } - - if ((num_bytes=my_net_read(&con->net)) == packet_error) - { - con->last_errno=errno; - strmov(con->last_error,"socket read failed"); - return 1; - } - - net_buf_end=net_buf+num_bytes; - - if ((con->eof=(net_buf[3]==' '))) - res_buf_shift--; - net_buf+=res_buf_shift; - res_buf_end[-1]=0; - for (;net_buf<net_buf_end && res_buf < res_buf_end;res_buf++,net_buf++) - { - if ((*res_buf=*net_buf) == '\r') - { - *res_buf=0; - break; - } - } - return 0; -} |