diff options
Diffstat (limited to 'ext/mysql/libmysql/libmysql.c')
-rw-r--r-- | ext/mysql/libmysql/libmysql.c | 332 |
1 files changed, 244 insertions, 88 deletions
diff --git a/ext/mysql/libmysql/libmysql.c b/ext/mysql/libmysql/libmysql.c index 888d0e22c9..ebee8b6e10 100644 --- a/ext/mysql/libmysql/libmysql.c +++ b/ext/mysql/libmysql/libmysql.c @@ -1,10 +1,8 @@ -/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB - This file is public domain and comes with NO WARRANTY of any kind */ - -#define PROTOCOL_VERSION 10 +/* Copyright Abandoned 1996 TCX DataKonsult AB & Monty Program KB & Detron HB +This file is public domain and comes with NO WARRANTY of any kind */ #define DONT_USE_RAID -#if defined(__WIN32__) || defined(WIN32) +#if defined(__WIN__) || defined(_WIN32) || defined(_WIN64) #include <winsock.h> #include <odbcinst.h> #endif @@ -20,10 +18,11 @@ #include <violite.h> #include <sys/stat.h> #include <signal.h> +#include <time.h> #ifdef HAVE_PWD_H #include <pwd.h> #endif -#if !defined(MSDOS) && !defined(__WIN32__) +#if !defined(MSDOS) && !defined(__WIN__) #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> @@ -38,7 +37,7 @@ #ifdef HAVE_SYS_UN_H # include <sys/un.h> #endif -#if defined(THREAD) && !defined(__WIN32__) +#if defined(THREAD) && !defined(__WIN__) #include <my_pthread.h> /* because of signal() */ #endif #ifndef INADDR_NONE @@ -46,17 +45,16 @@ #endif static my_bool mysql_client_init=0; -static MYSQL *current_mysql; uint mysql_port=0; my_string mysql_unix_port=0; -#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES) +#define CLIENT_CAPABILITIES (CLIENT_LONG_PASSWORD | CLIENT_LONG_FLAG | CLIENT_LOCAL_FILES | CLIENT_TRANSACTIONS) -#if defined(MSDOS) || defined(__WIN32__) +#if defined(MSDOS) || defined(__WIN__) #define ERRNO WSAGetLastError() #define perror(A) #else -#include <sys/errno.h> +#include <errno.h> #define ERRNO errno #define SOCKET_ERROR -1 #define closesocket(A) close(A) @@ -68,20 +66,21 @@ static MYSQL_DATA *read_rows (MYSQL *mysql,MYSQL_FIELD *fields, static int read_one_row(MYSQL *mysql,uint fields,MYSQL_ROW row, ulong *lengths); static void end_server(MYSQL *mysql); -static void remember_connection(MYSQL *mysql); static void read_user_name(char *name); static void append_wild(char *to,char *end,const char *wild); static my_bool mysql_reconnect(MYSQL *mysql); static int send_file_to_server(MYSQL *mysql,const char *filename); static sig_handler pipe_sig_handler(int sig); +static ulong mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, + const char *from, ulong length); /* 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. */ -#if !defined(__WIN32__) && defined(SIGPIPE) && !defined(THREAD) -#define init_sigpipe_variables sig_return old_signal_handler; +#if !defined(__WIN__) && defined(SIGPIPE) && !defined(THREAD) +#define init_sigpipe_variables sig_return old_signal_handler=(sig_return) 0; #define set_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) old_signal_handler=signal(SIGPIPE,pipe_sig_handler) #define reset_sigpipe(mysql) if ((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE) signal(SIGPIPE,old_signal_handler); #else @@ -101,13 +100,14 @@ static sig_handler pipe_sig_handler(int sig); static int connect2(File s, const struct sockaddr *name, uint namelen, uint to) { -#if defined(__WIN32__) +#if defined(__WIN__) return connect(s, (struct sockaddr*) name, namelen); #else int flags, res, s_err; size_socket s_err_size = sizeof(uint); fd_set sfds; struct timeval tv; + time_t start_time, now_time; /* If they passed us a timeout of zero, we should behave * exactly like the normal connect() call does. @@ -150,11 +150,25 @@ static int connect2(File s, const struct sockaddr *name, uint namelen, uint to) FD_ZERO(&sfds); FD_SET(s, &sfds); - tv.tv_sec = (long) to; - tv.tv_usec = 0; - res = select(s+1, NULL, &sfds, NULL, &tv); - if (res <= 0) /* Never became writable */ - return(-1); + /* + * select could be interrupted by a signal, and if it is, + * the timeout should be adjusted and the select restarted + * to work around OSes that don't restart select and + * implementations of select that don't adjust tv upon + * failure to reflect the time remaining + */ + start_time = time(NULL); + for (;;) + { + tv.tv_sec = (long) to; + tv.tv_usec = 0; + if ((res = select(s+1, NULL, &sfds, NULL, &tv)) >= 0) + break; + now_time=time(NULL); + to-= (uint) (now_time - start_time); + if (errno != EINTR || (int) to <= 0) + return -1; + } /* select() returned something more interesting than zero, let's * see if we have any errors. If the next two statements pass, @@ -178,7 +192,7 @@ static int connect2(File s, const struct sockaddr *name, uint namelen, uint to) ** Create a named pipe connection */ -#ifdef __WIN32__ +#ifdef __WIN__ HANDLE create_named_pipe(NET *net, uint connect_timeout, char **arg_host, char **arg_unix_socket) @@ -270,7 +284,9 @@ net_safe_read(MYSQL *mysql) DBUG_PRINT("error",("Wrong connection or packet. fd: %s len: %d", vio_description(net->vio),len)); end_server(mysql); - net->last_errno=CR_SERVER_LOST; + 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)); return(packet_error); } @@ -409,23 +425,21 @@ simple_command(MYSQL *mysql,enum enum_server_command command, const char *arg, mysql->net.last_errno=0; mysql->info=0; mysql->affected_rows= ~(my_ulonglong) 0; - remember_connection(mysql); net_clear(net); /* Clear receive buffer */ if (!arg) arg=""; if (net_write_command(net,(uchar) command,arg, - length ? length :strlen(arg))) + length ? length : (ulong) strlen(arg))) { DBUG_PRINT("error",("Can't send command to server. Error: %d",errno)); end_server(mysql); if (mysql_reconnect(mysql) || net_write_command(net,(uchar) command,arg, - length ? length :strlen(arg))) + length ? length : (ulong) strlen(arg))) { net->last_errno=CR_SERVER_GONE_ERROR; strmov(net->last_error,ER(net->last_errno)); - reset_sigpipe(mysql); goto end; } } @@ -455,7 +469,7 @@ struct passwd *getpwuid(uid_t); char* getlogin(void); #endif -#if !defined(MSDOS) && ! defined(VMS) && !defined(__WIN32__) +#if !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__) static void read_user_name(char *name) { DBUG_ENTER("read_user_name"); @@ -502,7 +516,7 @@ static void read_user_name(char *name) #endif -#ifdef __WIN32__ +#ifdef __WIN__ static my_bool is_NT(void) { char *os=getenv("OS"); @@ -574,17 +588,6 @@ mysql_debug(const char *debug) /************************************************************************** -** Store the server socket currently in use -** Used by pipe_handler if error on socket interrupt -**************************************************************************/ - -static void -remember_connection(MYSQL *mysql) -{ - current_mysql = mysql; -} - -/************************************************************************** ** Close the server connection if we get a SIGPIPE ARGSUSED **************************************************************************/ @@ -660,12 +663,13 @@ mysql_free_result(MYSQL_RES *result) static const char *default_options[]= {"port","socket","compress","password","pipe", "timeout", "user", "init-command", "host", "database", "debug", "return-found-rows", -#ifdef HAVE_OPENSSL "ssl_key" ,"ssl_cert" ,"ssl_ca" ,"ssl_capath", -#endif /* HAVE_OPENSSL */ + "character-set-dir", "default-character-set", NullS }; -static TYPELIB option_types={array_elements(default_options)-1,(char*) "options",(char **) default_options}; + +static TYPELIB option_types={array_elements(default_options)-1, + "options",default_options}; static void mysql_read_default_options(struct st_mysql_options *options, const char *filename,const char *group) @@ -775,7 +779,21 @@ static 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; +#else + case 13: /* Ignore SSL options */ + case 14: + case 15: + case 16: + break; #endif /* HAVE_OPENSSL */ + case 17: /* charset-lib */ + my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR)); + options->charset_dir = my_strdup(opt_arg, MYF(MY_WME)); + break; + case 18: + my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR)); + options->charset_name = my_strdup(opt_arg, MYF(MY_WME)); + break; default: DBUG_PRINT("warning",("unknown option: %s",option[0])); } @@ -966,9 +984,13 @@ mysql_init(MYSQL *mysql) } else bzero((char*) (mysql),sizeof(*(mysql))); -#ifdef __WIN32__ +#ifdef __WIN__ mysql->options.connect_timeout=20; #endif +#if defined(SIGPIPE) && defined(THREAD) + if (!((mysql)->client_flag & CLIENT_IGNORE_SIGPIPE)) + (void) signal(SIGPIPE,pipe_sig_handler); +#endif return mysql; } @@ -997,7 +1019,7 @@ static void mysql_once_init() if (!mysql_unix_port) { char *env; -#ifdef __WIN32__ +#ifdef __WIN__ mysql_unix_port = (char*) MYSQL_NAMEDPIPE; #else mysql_unix_port = (char*) MYSQL_UNIX_ADDR; @@ -1006,7 +1028,7 @@ static void mysql_once_init() mysql_unix_port = env; } mysql_debug(NullS); -#if defined(SIGPIPE) +#if defined(SIGPIPE) && !defined(THREAD) (void) signal(SIGPIPE,SIG_IGN); #endif } @@ -1062,7 +1084,7 @@ mysql_ssl_clear(MYSQL *mysql) mysql->options.ssl_ca = 0; mysql->options.ssl_capath = 0; mysql->options.use_ssl = false; - delete reinterpret_cast<VioConnectorFd*>(mysql->connector_fd); + mysql->connector_fd->delete(); mysql->connector_fd = 0; return 0; } @@ -1101,13 +1123,13 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, const char *passwd, const char *db, uint port, const char *unix_socket,uint client_flag) { - char buff[100],*end,*host_info; + char buff[100],charset_name_buff[16],*end,*host_info, *charset_name; int sock; - ulong ip_addr; + uint32 ip_addr; struct sockaddr_in sock_addr; uint pkt_length; - NET *net; -#ifdef __WIN32__ + NET *net= &mysql->net; +#ifdef __WIN__ HANDLE hPipe=INVALID_HANDLE_VALUE; #endif #ifdef HAVE_SYS_UN_H @@ -1123,6 +1145,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, /* Don't give sigpipe errors if the client doesn't want them */ set_sigpipe(mysql); + net->vio = 0; /* If something goes wrong */ /* use default options */ if (mysql->options.my_cnf_file || mysql->options.my_cnf_group) { @@ -1155,10 +1178,8 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if (!unix_socket) unix_socket=mysql->options.unix_socket; - remember_connection(mysql); mysql->reconnect=1; /* Reconnect as default */ - net= &mysql->net; - net->vio = 0; /* If something goes wrong */ + mysql->server_status=SERVER_STATUS_AUTOCOMMIT; /* ** Grab a socket and connect it to the server @@ -1192,7 +1213,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, } } else -#elif defined(__WIN32__) +#elif defined(__WIN__) { if ((unix_socket || !host && is_NT() || @@ -1250,7 +1271,7 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, if ((int) (ip_addr = inet_addr(host)) != (int) INADDR_NONE) { - memcpy(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); + memcpy_fixed(&sock_addr.sin_addr,&ip_addr,sizeof(ip_addr)); } else #if defined(HAVE_GETHOSTBYNAME_R) && defined(_REENTRANT) && defined(THREAD) @@ -1323,17 +1344,53 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, mysql->thread_id=uint4korr(end+1); end+=5; strmake(mysql->scramble_buff,end,8); - if (pkt_length > (uint) (end+9 - (char*) net->read_pos)) - mysql->server_capabilities=uint2korr(end+9); + end+=9; + if (pkt_length >= (uint) (end+1 - (char*) net->read_pos)) + mysql->server_capabilities=uint2korr(end); + if (pkt_length >= (uint) (end+18 - (char*) net->read_pos)) + { + /* New protocol with 16 bytes to describe server characteristics */ + mysql->server_language=end[2]; + mysql->server_status=uint2korr(end+3); + } + + /* Set character set */ + if ((charset_name=mysql->options.charset_name)) + { + const char *save=charsets_dir; + if (mysql->options.charset_dir) + charsets_dir=mysql->options.charset_dir; + mysql->charset=get_charset_by_name(mysql->options.charset_name, + MYF(MY_WME)); + charsets_dir=save; + } + else if (mysql->server_language) + { + charset_name=charset_name_buff; + sprintf(charset_name,"%d",mysql->server_language); /* In case of errors */ + mysql->charset=get_charset((uint8) mysql->server_language, MYF(MY_WME)); + } + else + mysql->charset=default_charset_info; + + if (!mysql->charset) + { + net->last_errno=CR_CANT_READ_CHARSET; + sprintf(net->last_error,ER(net->last_errno), + charset_name ? charset_name : "unknown", + mysql->options.charset_dir ? mysql->options.charset_dir : + "default"); + goto error; + } /* Save connection information */ if (!user) user=""; if (!passwd) passwd=""; if (!my_multi_malloc(MYF(0), - &mysql->host_info,strlen(host_info)+1, - &mysql->host,strlen(host)+1, - &mysql->unix_socket,unix_socket ? strlen(unix_socket)+1 - :1, + &mysql->host_info, (uint) strlen(host_info)+1, + &mysql->host, (uint) strlen(host)+1, + &mysql->unix_socket,unix_socket ? + (uint) strlen(unix_socket)+1 : (uint) 1, &mysql->server_version, (uint) (end - (char*) net->read_pos), NullS) || @@ -1352,8 +1409,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, strmov(mysql->server_version,(char*) net->read_pos+1); mysql->port=port; mysql->client_flag=client_flag | mysql->options.client_flag; - DBUG_PRINT("info",("Server version = '%s' capabilites: %ld", - mysql->server_version,mysql->server_capabilities)); + DBUG_PRINT("info",("Server version = '%s' capabilites: %ld status: %d", + mysql->server_version,mysql->server_capabilities, + mysql->server_status)); /* Send client information for access check */ client_flag|=CLIENT_CAPABILITIES; @@ -1415,6 +1473,9 @@ mysql_real_connect(MYSQL *mysql,const char *host, const char *user, strmake(buff+5,user,32); else read_user_name((char*) buff+5); +#ifdef _CUSTOMCONFIG_ +#include "_cust_libmysql.h"; +#endif DBUG_PRINT("info",("user: %s",buff+5)); end=scramble(strend(buff+5)+1, mysql->scramble_buff, passwd, (my_bool) (mysql->protocol_version == 9)); @@ -1465,8 +1526,13 @@ static my_bool mysql_reconnect(MYSQL *mysql) MYSQL tmp_mysql; DBUG_ENTER("mysql_reconnect"); - if (!mysql->reconnect || !mysql->host_info) + if (!mysql->reconnect || + (mysql->server_status & SERVER_STATUS_IN_TRANS) || !mysql->host_info) + { + /* Allov reconnect next time */ + mysql->server_status&= ~SERVER_STATUS_IN_TRANS; DBUG_RETURN(1); + } mysql_init(&tmp_mysql); tmp_mysql.options=mysql->options; if (!mysql_real_connect(&tmp_mysql,mysql->host,mysql->user,mysql->passwd, @@ -1475,9 +1541,9 @@ static my_bool mysql_reconnect(MYSQL *mysql) DBUG_RETURN(1); tmp_mysql.free_me=mysql->free_me; mysql->free_me=0; - bzero((char*) &mysql->options,sizeof(&mysql->options)); + bzero((char*) &mysql->options,sizeof(mysql->options)); mysql_close(mysql); - memcpy(mysql,&tmp_mysql,sizeof(tmp_mysql)); + *mysql=tmp_mysql; net_clear(&mysql->net); mysql->affected_rows= ~(my_ulonglong) 0; DBUG_RETURN(0); @@ -1528,7 +1594,7 @@ mysql_select_db(MYSQL *mysql, const char *db) DBUG_ENTER("mysql_select_db"); DBUG_PRINT("enter",("db: '%s'",db)); - if ((error=simple_command(mysql,COM_INIT_DB,db,strlen(db),0))) + if ((error=simple_command(mysql,COM_INIT_DB,db,(uint) strlen(db),0))) DBUG_RETURN(error); my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); mysql->db=my_strdup(db,MYF(MY_WME)); @@ -1560,11 +1626,14 @@ mysql_close(MYSQL *mysql) my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.init_command,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.user,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.host,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.password,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.db,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR)); my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); + my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); /* Clear pointers for better safety */ mysql->host_info=mysql->user=mysql->passwd=mysql->db=0; bzero((char*) &mysql->options,sizeof(mysql->options)); @@ -1588,12 +1657,12 @@ mysql_close(MYSQL *mysql) int STDCALL mysql_query(MYSQL *mysql, const char *query) { - return mysql_real_query(mysql,query,strlen(query)); + return mysql_real_query(mysql,query, (uint) strlen(query)); } int STDCALL -mysql_real_query(MYSQL *mysql, const char *query,uint length) +mysql_real_query(MYSQL *mysql, const char *query, uint length) { uchar *pos; ulong field_count; @@ -1612,6 +1681,10 @@ mysql_real_query(MYSQL *mysql, const char *query,uint length) { 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+length && net_field_length(&pos)) mysql->info=(char*) pos; DBUG_RETURN(0); @@ -1623,6 +1696,9 @@ mysql_real_query(MYSQL *mysql, const char *query,uint length) 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); @@ -1820,6 +1896,7 @@ mysql_fetch_row(MYSQL_RES *res) } else { + DBUG_PRINT("info",("end of data")); res->eof=1; res->handle->status=MYSQL_STATUS_READY; } @@ -1829,7 +1906,10 @@ mysql_fetch_row(MYSQL_RES *res) { MYSQL_ROW tmp; if (!res->data_cursor) + { + DBUG_PRINT("info",("end of data")); DBUG_RETURN(res->current_row=(MYSQL_ROW) NULL); + } tmp = res->data_cursor->data; res->data_cursor = res->data_cursor->next; DBUG_RETURN(res->current_row=tmp); @@ -1880,7 +1960,7 @@ void STDCALL mysql_data_seek(MYSQL_RES *result, my_ulonglong row) { MYSQL_ROWS *tmp=0; - DBUG_PRINT("info",("mysql_data_seek(%d)",row)); + DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row)); if (result->data) for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ; result->current_row=0; @@ -1889,7 +1969,7 @@ mysql_data_seek(MYSQL_RES *result, my_ulonglong row) /************************************************************************* ** put the row or field cursor one a position one got from mysql_row_tell() -** This dosen't restore any data. The next mysql_fetch_row or +** This doesn't restore any data. The next mysql_fetch_row or ** mysql_fetch_field will return the next row or field after the last used *************************************************************************/ @@ -2146,6 +2226,14 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) my_free(mysql->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR)); mysql->options.my_cnf_group=my_strdup(arg,MYF(MY_WME)); break; + case MYSQL_SET_CHARSET_DIR: + my_free(mysql->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.charset_dir=my_strdup(arg,MYF(MY_WME)); + break; + case MYSQL_SET_CHARSET_NAME: + my_free(mysql->options.charset_name,MYF(MY_ALLOW_ZERO_PTR)); + mysql->options.charset_name=my_strdup(arg,MYF(MY_WME)); + break; default: DBUG_RETURN(-1); } @@ -2158,78 +2246,93 @@ mysql_options(MYSQL *mysql,enum mysql_option option, const char *arg) ****************************************************************************/ /* MYSQL_RES */ -my_ulonglong mysql_num_rows(MYSQL_RES *res) +my_ulonglong STDCALL mysql_num_rows(MYSQL_RES *res) { return res->row_count; } -unsigned int mysql_num_fields(MYSQL_RES *res) +unsigned int STDCALL mysql_num_fields(MYSQL_RES *res) { return res->field_count; } -my_bool mysql_eof(MYSQL_RES *res) +my_bool STDCALL mysql_eof(MYSQL_RES *res) { return res->eof; } -MYSQL_FIELD *mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr) +MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr) { return &(res)->fields[fieldnr]; } -MYSQL_FIELD *mysql_fetch_fields(MYSQL_RES *res) +MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res) { return (res)->fields; } -MYSQL_ROWS *mysql_row_tell(MYSQL_RES *res) +MYSQL_ROWS * STDCALL mysql_row_tell(MYSQL_RES *res) { return res->data_cursor; } -uint mysql_field_tell(MYSQL_RES *res) +uint STDCALL mysql_field_tell(MYSQL_RES *res) { return (res)->current_field; } /* MYSQL */ -unsigned int mysql_field_count(MYSQL *mysql) +unsigned int STDCALL mysql_field_count(MYSQL *mysql) { return mysql->field_count; } -my_ulonglong mysql_affected_rows(MYSQL *mysql) +my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql) { return (mysql)->affected_rows; } -my_ulonglong mysql_insert_id(MYSQL *mysql) +my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql) { return (mysql)->insert_id; } -uint mysql_errno(MYSQL *mysql) +uint STDCALL mysql_errno(MYSQL *mysql) { return (mysql)->net.last_errno; } -char *mysql_error(MYSQL *mysql) +char * STDCALL mysql_error(MYSQL *mysql) { return (mysql)->net.last_error; } -char *mysql_info(MYSQL *mysql) +char *STDCALL mysql_info(MYSQL *mysql) { return (mysql)->info; } -ulong mysql_thread_id(MYSQL *mysql) +ulong STDCALL mysql_thread_id(MYSQL *mysql) { return (mysql)->thread_id; } +const char * STDCALL mysql_character_set_name(MYSQL *mysql) +{ + return mysql->charset->name; +} + + +uint STDCALL mysql_thread_safe(void) +{ +#ifdef THREAD + return 1; +#else + return 0; +#endif +} + /**************************************************************************** ** Some support functions ****************************************************************************/ @@ -2243,13 +2346,31 @@ ulong mysql_thread_id(MYSQL *mysql) ulong STDCALL mysql_escape_string(char *to,const char *from,ulong length) { + return mysql_sub_escape_string(default_charset_info,to,from,length); +} + +ulong STDCALL +mysql_real_escape_string(MYSQL *mysql, char *to,const char *from, + ulong length) +{ + return mysql_sub_escape_string(mysql->charset,to,from,length); +} + + +static ulong +mysql_sub_escape_string(CHARSET_INFO *charset_info, char *to, + const char *from, ulong length) +{ const char *to_start=to; const char *end; +#ifdef USE_MB + my_bool use_mb_flag=use_mb(charset_info); +#endif for (end=from+length; from != end ; from++) { #ifdef USE_MB int l; - if ((l = ismbchar(from, end))) + if (use_mb_flag && (l = my_ismbchar(charset_info, from, end))) { while (l--) *to++ = *from++; @@ -2296,7 +2417,8 @@ mysql_escape_string(char *to,const char *from,ulong length) char * STDCALL -mysql_odbc_escape_string(char *to, ulong to_length, +mysql_odbc_escape_string(MYSQL *mysql, + char *to, ulong to_length, const char *from, ulong from_length, void *param, char * (*extend_buffer) @@ -2304,6 +2426,9 @@ mysql_odbc_escape_string(char *to, ulong to_length, { char *to_end=to+to_length-5; const char *end; +#ifdef USE_MB + my_bool use_mb_flag=use_mb(mysql->charset); +#endif for (end=from+from_length; from != end ; from++) { @@ -2317,7 +2442,7 @@ mysql_odbc_escape_string(char *to, ulong to_length, #ifdef USE_MB { int l; - if ((l = ismbchar(from, end))) + if (use_mb_flag && (l = my_ismbchar(mysql->charset, from, end))) { while (l--) *to++ = *from++; @@ -2361,3 +2486,34 @@ mysql_odbc_escape_string(char *to, ulong to_length, } return to; } + +void STDCALL +myodbc_remove_escape(MYSQL *mysql,char *name) +{ + char *to; +#ifdef USE_MB + my_bool use_mb_flag=use_mb(mysql->charset); + char *end; + LINT_INIT(end); + if (use_mb_flag) + for (end=name; *end ; end++) ; +#endif + + for (to=name ; *name ; name++) + { +#ifdef USE_MB + int l; + if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) ) + { + while (l--) + *to++ = *name++; + name--; + continue; + } +#endif + if (*name == '\\' && name[1]) + name++; + *to++= *name; + } + *to=0; +} |