summaryrefslogtreecommitdiff
path: root/ext/mysql/libmysql/libmysql.c
diff options
context:
space:
mode:
Diffstat (limited to 'ext/mysql/libmysql/libmysql.c')
-rw-r--r--ext/mysql/libmysql/libmysql.c332
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;
+}