mirror of
https://github.com/VCMP-SqMod/SqMod.git
synced 2024-11-14 03:37:16 +01:00
2001 lines
46 KiB
C
2001 lines
46 KiB
C
/* Copyright (C) 2012 MariaDB Services and Kristian Nielsen
|
|
2015 MariaDB Corporation
|
|
|
|
This library is free software; you can redistribute it and/or
|
|
modify it under the terms of the GNU Library General Public
|
|
License as published by the Free Software Foundation; either
|
|
version 2 of the License, or (at your option) any later version.
|
|
|
|
This library 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
|
|
Library General Public License for more details.
|
|
|
|
You should have received a copy of the GNU Library General Public
|
|
License along with this library; if not, write to the Free
|
|
Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
|
|
/*
|
|
MySQL non-blocking client library functions.
|
|
*/
|
|
|
|
#include <string.h>
|
|
#include "my_global.h"
|
|
#include "my_sys.h"
|
|
#include "mysql.h"
|
|
#include "errmsg.h"
|
|
#ifndef LIBMARIADB
|
|
#include "sql_common.h"
|
|
#else
|
|
#include "mysql_com.h"
|
|
#include "ma_common.h"
|
|
#endif
|
|
#include "my_context.h"
|
|
#include "violite.h"
|
|
#include "mysql_async.h"
|
|
|
|
|
|
#ifdef _WIN32
|
|
/*
|
|
Windows does not support MSG_DONTWAIT for send()/recv(). So we need to ensure
|
|
that the socket is non-blocking at the start of every operation.
|
|
*/
|
|
#define WIN_SET_NONBLOCKING(mysql) { \
|
|
my_bool old_mode; \
|
|
if ((mysql)->net.vio) vio_blocking((mysql)->net.vio, FALSE, &old_mode); \
|
|
}
|
|
#else
|
|
#define WIN_SET_NONBLOCKING(mysql)
|
|
#endif
|
|
|
|
extern void mysql_close_slow_part(MYSQL *mysql);
|
|
|
|
|
|
void
|
|
my_context_install_suspend_resume_hook(struct mysql_async_context *b,
|
|
void (*hook)(my_bool, void *),
|
|
void *user_data)
|
|
{
|
|
b->suspend_resume_hook= hook;
|
|
b->suspend_resume_hook_user_data= user_data;
|
|
}
|
|
|
|
|
|
/* Asynchronous connect(); socket must already be set non-blocking. */
|
|
int
|
|
my_connect_async(struct mysql_async_context *b, my_socket fd,
|
|
const struct sockaddr *name, uint namelen, int vio_timeout)
|
|
{
|
|
int res;
|
|
size_socket s_err_size;
|
|
|
|
/* Make the socket non-blocking. */
|
|
#ifdef _WIN32
|
|
ulong arg= 1;
|
|
ioctlsocket(fd, FIONBIO, (void *)&arg);
|
|
#else
|
|
fcntl(fd, F_SETFL, O_NONBLOCK);
|
|
#endif
|
|
|
|
b->events_to_wait_for= 0;
|
|
/*
|
|
Start to connect asynchronously.
|
|
If this will block, we suspend the call and return control to the
|
|
application context. The application will then resume us when the socket
|
|
polls ready for write, indicating that the connection attempt completed.
|
|
*/
|
|
res= connect(fd, name, namelen);
|
|
if (res != 0)
|
|
{
|
|
#ifdef _WIN32
|
|
int wsa_err= WSAGetLastError();
|
|
if (wsa_err != WSAEWOULDBLOCK)
|
|
return res;
|
|
b->events_to_wait_for|= MYSQL_WAIT_EXCEPT;
|
|
#else
|
|
int err= errno;
|
|
if (err != EINPROGRESS && err != EALREADY && err != EAGAIN)
|
|
return res;
|
|
#endif
|
|
b->events_to_wait_for|= MYSQL_WAIT_WRITE;
|
|
if (vio_timeout >= 0)
|
|
{
|
|
b->timeout_value= vio_timeout;
|
|
b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
|
|
}
|
|
else
|
|
b->timeout_value= 0;
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
|
|
my_context_yield(&b->async_context);
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
|
|
if (b->events_occured & MYSQL_WAIT_TIMEOUT)
|
|
return -1;
|
|
|
|
s_err_size= sizeof(res);
|
|
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0)
|
|
return -1;
|
|
if (res)
|
|
{
|
|
errno= res;
|
|
return -1;
|
|
}
|
|
}
|
|
return res;
|
|
}
|
|
|
|
#define IS_BLOCKING_ERROR() \
|
|
IF_WIN(WSAGetLastError() != WSAEWOULDBLOCK, \
|
|
(errno != EAGAIN && errno != EINTR))
|
|
|
|
#ifdef _AIX
|
|
#ifndef MSG_DONTWAIT
|
|
#define MSG_DONTWAIT 0
|
|
#endif
|
|
#endif
|
|
|
|
ssize_t
|
|
my_recv_async(struct mysql_async_context *b, int fd,
|
|
unsigned char *buf, size_t size, int timeout)
|
|
{
|
|
ssize_t res;
|
|
|
|
for (;;)
|
|
{
|
|
res= recv(fd, buf, size, IF_WIN(0, MSG_DONTWAIT));
|
|
if (res >= 0 || IS_BLOCKING_ERROR())
|
|
return res;
|
|
b->events_to_wait_for= MYSQL_WAIT_READ;
|
|
if (timeout >= 0)
|
|
{
|
|
b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
|
|
b->timeout_value= timeout;
|
|
}
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
|
|
my_context_yield(&b->async_context);
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
|
|
if (b->events_occured & MYSQL_WAIT_TIMEOUT)
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
ssize_t
|
|
my_send_async(struct mysql_async_context *b, int fd,
|
|
const unsigned char *buf, size_t size, int timeout)
|
|
{
|
|
ssize_t res;
|
|
|
|
for (;;)
|
|
{
|
|
res= send(fd, buf, size, IF_WIN(0, MSG_DONTWAIT));
|
|
if (res >= 0 || IS_BLOCKING_ERROR())
|
|
return res;
|
|
b->events_to_wait_for= MYSQL_WAIT_WRITE;
|
|
if (timeout >= 0)
|
|
{
|
|
b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
|
|
b->timeout_value= timeout;
|
|
}
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
|
|
my_context_yield(&b->async_context);
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
|
|
if (b->events_occured & MYSQL_WAIT_TIMEOUT)
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
|
|
my_bool
|
|
my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event,
|
|
int timeout)
|
|
{
|
|
switch (event)
|
|
{
|
|
case VIO_IO_EVENT_READ:
|
|
b->events_to_wait_for = MYSQL_WAIT_READ;
|
|
break;
|
|
case VIO_IO_EVENT_WRITE:
|
|
b->events_to_wait_for = MYSQL_WAIT_WRITE;
|
|
break;
|
|
case VIO_IO_EVENT_CONNECT:
|
|
b->events_to_wait_for = MYSQL_WAIT_WRITE | IF_WIN(0, MYSQL_WAIT_EXCEPT);
|
|
break;
|
|
}
|
|
|
|
if (timeout >= 0)
|
|
{
|
|
b->events_to_wait_for |= MYSQL_WAIT_TIMEOUT;
|
|
b->timeout_value= timeout;
|
|
}
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
|
|
my_context_yield(&b->async_context);
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
|
|
return (b->events_occured & MYSQL_WAIT_TIMEOUT) ? 0 : 1;
|
|
}
|
|
|
|
|
|
#ifdef HAVE_OPENSSL
|
|
static my_bool
|
|
my_ssl_async_check_result(int res, struct mysql_async_context *b, SSL *ssl)
|
|
{
|
|
int ssl_err;
|
|
b->events_to_wait_for= 0;
|
|
if (res >= 0)
|
|
return 1;
|
|
ssl_err= SSL_get_error(ssl, res);
|
|
if (ssl_err == SSL_ERROR_WANT_READ)
|
|
b->events_to_wait_for|= MYSQL_WAIT_READ;
|
|
else if (ssl_err == SSL_ERROR_WANT_WRITE)
|
|
b->events_to_wait_for|= MYSQL_WAIT_WRITE;
|
|
else
|
|
return 1;
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
|
|
my_context_yield(&b->async_context);
|
|
if (b->suspend_resume_hook)
|
|
(*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
|
|
return 0;
|
|
}
|
|
|
|
int
|
|
my_ssl_read_async(struct mysql_async_context *b, SSL *ssl,
|
|
void *buf, int size)
|
|
{
|
|
int res;
|
|
|
|
for (;;)
|
|
{
|
|
res= SSL_read(ssl, buf, size);
|
|
if (my_ssl_async_check_result(res, b, ssl))
|
|
return res;
|
|
}
|
|
}
|
|
|
|
int
|
|
my_ssl_write_async(struct mysql_async_context *b, SSL *ssl,
|
|
const void *buf, int size)
|
|
{
|
|
int res;
|
|
|
|
for (;;)
|
|
{
|
|
res= SSL_write(ssl, buf, size);
|
|
if (my_ssl_async_check_result(res, b, ssl))
|
|
return res;
|
|
}
|
|
}
|
|
#endif /* HAVE_OPENSSL */
|
|
|
|
/*
|
|
Legacy support of the MariaDB 5.5 version, where timeouts where only in
|
|
seconds resolution. Applications that use this will be asked to set a timeout
|
|
at the nearest higher whole-seconds value.
|
|
*/
|
|
unsigned int STDCALL
|
|
mysql_get_timeout_value(const MYSQL *mysql)
|
|
{
|
|
unsigned int timeout= mysql->options.extension->async_context->timeout_value;
|
|
/* Avoid overflow. */
|
|
if (timeout > UINT_MAX - 999)
|
|
return (timeout - 1)/1000 + 1;
|
|
else
|
|
return (timeout+999)/1000;
|
|
}
|
|
|
|
|
|
unsigned int STDCALL
|
|
mysql_get_timeout_value_ms(const MYSQL *mysql)
|
|
{
|
|
return mysql->options.extension->async_context->timeout_value;
|
|
}
|
|
|
|
|
|
/*
|
|
Now create non-blocking definitions for all the calls that may block.
|
|
|
|
Each call FOO gives rise to FOO_start() that prepares the MYSQL object for
|
|
doing non-blocking calls that can suspend operation mid-way, and then starts
|
|
the call itself. And a FOO_start_internal trampoline to assist with running
|
|
the real call in a co-routine that can be suspended. And a FOO_cont() that
|
|
can continue a suspended operation.
|
|
*/
|
|
|
|
#define MK_ASYNC_INTERNAL_BODY(call, invoke_args, mysql_val, ret_type, ok_val)\
|
|
struct call ## _params *parms= (struct call ## _params *)d; \
|
|
ret_type ret; \
|
|
struct mysql_async_context *b= \
|
|
(mysql_val)->options.extension->async_context; \
|
|
\
|
|
ret= call invoke_args; \
|
|
b->ret_result. ok_val = ret; \
|
|
b->events_to_wait_for= 0;
|
|
|
|
#define MK_ASYNC_START_BODY(call, mysql_val, parms_assign, err_val, ok_val, extra1) \
|
|
int res; \
|
|
struct mysql_async_context *b; \
|
|
struct call ## _params parms; \
|
|
\
|
|
extra1 \
|
|
b= mysql_val->options.extension->async_context; \
|
|
parms_assign \
|
|
\
|
|
b->active= 1; \
|
|
res= my_context_spawn(&b->async_context, call ## _start_internal, &parms); \
|
|
b->active= b->suspended= 0; \
|
|
if (res > 0) \
|
|
{ \
|
|
/* Suspended. */ \
|
|
b->suspended= 1; \
|
|
return b->events_to_wait_for; \
|
|
} \
|
|
if (res < 0) \
|
|
{ \
|
|
set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
|
|
*ret= err_val; \
|
|
} \
|
|
else \
|
|
*ret= b->ret_result. ok_val; \
|
|
return 0;
|
|
|
|
#define MK_ASYNC_CONT_BODY(mysql_val, err_val, ok_val) \
|
|
int res; \
|
|
struct mysql_async_context *b= \
|
|
(mysql_val)->options.extension->async_context; \
|
|
if (!b->suspended) \
|
|
{ \
|
|
set_mysql_error((mysql_val), CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); \
|
|
*ret= err_val; \
|
|
return 0; \
|
|
} \
|
|
\
|
|
b->active= 1; \
|
|
b->events_occured= ready_status; \
|
|
res= my_context_continue(&b->async_context); \
|
|
b->active= 0; \
|
|
if (res > 0) \
|
|
return b->events_to_wait_for; /* (Still) suspended */ \
|
|
b->suspended= 0; \
|
|
if (res < 0) \
|
|
{ \
|
|
set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
|
|
*ret= err_val; \
|
|
} \
|
|
else \
|
|
*ret= b->ret_result. ok_val; /* Finished. */ \
|
|
return 0;
|
|
|
|
#define MK_ASYNC_INTERNAL_BODY_VOID_RETURN(call, invoke_args, mysql_val) \
|
|
struct call ## _params *parms= (struct call ## _params *)d; \
|
|
struct mysql_async_context *b= \
|
|
(mysql_val)->options.extension->async_context; \
|
|
\
|
|
call invoke_args; \
|
|
b->events_to_wait_for= 0;
|
|
|
|
#define MK_ASYNC_START_BODY_VOID_RETURN(call, mysql_val, parms_assign, extra1)\
|
|
int res; \
|
|
struct mysql_async_context *b; \
|
|
struct call ## _params parms; \
|
|
\
|
|
extra1 \
|
|
b= mysql_val->options.extension->async_context; \
|
|
parms_assign \
|
|
\
|
|
b->active= 1; \
|
|
res= my_context_spawn(&b->async_context, call ## _start_internal, &parms); \
|
|
b->active= b->suspended= 0; \
|
|
if (res > 0) \
|
|
{ \
|
|
/* Suspended. */ \
|
|
b->suspended= 1; \
|
|
return b->events_to_wait_for; \
|
|
} \
|
|
if (res < 0) \
|
|
set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
|
|
return 0;
|
|
|
|
#define MK_ASYNC_CONT_BODY_VOID_RETURN(mysql_val) \
|
|
int res; \
|
|
struct mysql_async_context *b= \
|
|
(mysql_val)->options.extension->async_context; \
|
|
if (!b->suspended) \
|
|
{ \
|
|
set_mysql_error((mysql_val), CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); \
|
|
return 0; \
|
|
} \
|
|
\
|
|
b->active= 1; \
|
|
b->events_occured= ready_status; \
|
|
res= my_context_continue(&b->async_context); \
|
|
b->active= 0; \
|
|
if (res > 0) \
|
|
return b->events_to_wait_for; /* (Still) suspended */ \
|
|
b->suspended= 0; \
|
|
if (res < 0) \
|
|
set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
|
|
return 0;
|
|
|
|
|
|
/* Structure used to pass parameters from mysql_real_connect_start(). */
|
|
struct mysql_real_connect_params {
|
|
MYSQL *mysql;
|
|
const char *host;
|
|
const char *user;
|
|
const char *passwd;
|
|
const char *db;
|
|
unsigned int port;
|
|
const char *unix_socket;
|
|
unsigned long client_flags;
|
|
};
|
|
static void
|
|
mysql_real_connect_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_real_connect,
|
|
(parms->mysql, parms->host, parms->user, parms->passwd, parms->db,
|
|
parms->port, parms->unix_socket, parms->client_flags),
|
|
parms->mysql,
|
|
MYSQL *,
|
|
r_ptr)
|
|
}
|
|
int STDCALL
|
|
mysql_real_connect_start(MYSQL **ret, MYSQL *mysql, const char *host,
|
|
const char *user, const char *passwd, const char *db,
|
|
unsigned int port, const char *unix_socket,
|
|
unsigned long client_flags)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_real_connect,
|
|
mysql,
|
|
{
|
|
parms.mysql= mysql;
|
|
parms.host= host;
|
|
parms.user= user;
|
|
parms.passwd= passwd;
|
|
parms.db= db;
|
|
parms.port= port;
|
|
parms.unix_socket= unix_socket;
|
|
parms.client_flags= client_flags;
|
|
},
|
|
NULL,
|
|
r_ptr,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
NULL,
|
|
r_ptr)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_real_query_start(). */
|
|
struct mysql_real_query_params {
|
|
MYSQL *mysql;
|
|
const char *stmt_str;
|
|
unsigned long length;
|
|
};
|
|
static void
|
|
mysql_real_query_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_real_query,
|
|
(parms->mysql, parms->stmt_str, parms->length),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_real_query_start(int *ret, MYSQL *mysql, const char *stmt_str, unsigned long length)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_real_query,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.stmt_str= stmt_str;
|
|
parms.length= length;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_real_query_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_fetch_row_start(). */
|
|
struct mysql_fetch_row_params {
|
|
MYSQL_RES *result;
|
|
};
|
|
static void
|
|
mysql_fetch_row_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_fetch_row,
|
|
(parms->result),
|
|
parms->result->handle,
|
|
MYSQL_ROW,
|
|
r_ptr)
|
|
}
|
|
int STDCALL
|
|
mysql_fetch_row_start(MYSQL_ROW *ret, MYSQL_RES *result)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_fetch_row,
|
|
result->handle,
|
|
{
|
|
WIN_SET_NONBLOCKING(result->handle)
|
|
parms.result= result;
|
|
},
|
|
NULL,
|
|
r_ptr,
|
|
/*
|
|
If we already fetched all rows from server (eg. mysql_store_result()),
|
|
then result->handle will be NULL and we cannot suspend. But that is fine,
|
|
since in this case mysql_fetch_row cannot block anyway. Just return
|
|
directly.
|
|
*/
|
|
if (!result->handle)
|
|
{
|
|
*ret= mysql_fetch_row(result);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
result->handle,
|
|
NULL,
|
|
r_ptr)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_set_character_set_start(). */
|
|
struct mysql_set_character_set_params {
|
|
MYSQL *mysql;
|
|
const char *csname;
|
|
};
|
|
static void
|
|
mysql_set_character_set_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_set_character_set,
|
|
(parms->mysql, parms->csname),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_set_character_set_start(int *ret, MYSQL *mysql, const char *csname)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_set_character_set,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.csname= csname;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_set_character_set_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_sekect_db_start(). */
|
|
struct mysql_select_db_params {
|
|
MYSQL *mysql;
|
|
const char *db;
|
|
};
|
|
static void
|
|
mysql_select_db_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_select_db,
|
|
(parms->mysql, parms->db),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_select_db_start(int *ret, MYSQL *mysql, const char *db)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_select_db,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.db= db;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_select_db_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_send_query_start(). */
|
|
struct mysql_send_query_params {
|
|
MYSQL *mysql;
|
|
const char *q;
|
|
unsigned long length;
|
|
};
|
|
static void
|
|
mysql_send_query_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_send_query,
|
|
(parms->mysql, parms->q, parms->length),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_send_query_start(int *ret, MYSQL *mysql, const char *q, unsigned long length)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_send_query,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.q= q;
|
|
parms.length= length;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_send_query_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_store_result_start(). */
|
|
struct mysql_store_result_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_store_result_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_store_result,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
MYSQL_RES *,
|
|
r_ptr)
|
|
}
|
|
int STDCALL
|
|
mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_store_result,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
NULL,
|
|
r_ptr,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
NULL,
|
|
r_ptr)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_free_result_start(). */
|
|
struct mysql_free_result_params {
|
|
MYSQL_RES *result;
|
|
};
|
|
static void
|
|
mysql_free_result_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY_VOID_RETURN(
|
|
mysql_free_result,
|
|
(parms->result),
|
|
parms->result->handle)
|
|
}
|
|
int STDCALL
|
|
mysql_free_result_start(MYSQL_RES *result)
|
|
{
|
|
MK_ASYNC_START_BODY_VOID_RETURN(
|
|
mysql_free_result,
|
|
result->handle,
|
|
{
|
|
WIN_SET_NONBLOCKING(result->handle)
|
|
parms.result= result;
|
|
},
|
|
/*
|
|
mysql_free_result() can have NULL in result->handle (this happens when all
|
|
rows have been fetched and mysql_fetch_row() returned NULL.)
|
|
So we cannot suspend, but it does not matter, as in this case
|
|
mysql_free_result() cannot block.
|
|
It is also legitimate to have NULL result, which will do nothing.
|
|
*/
|
|
if (!result || !result->handle)
|
|
{
|
|
mysql_free_result(result);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_free_result_cont(MYSQL_RES *result, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY_VOID_RETURN(result->handle)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_close_slow_part_start(). */
|
|
struct mysql_close_slow_part_params {
|
|
MYSQL *sock;
|
|
};
|
|
/*
|
|
We need special handling for mysql_close(), as the first part may block,
|
|
while the last part needs to free our extra library context stack.
|
|
|
|
So we do the first part (mysql_close_slow_part()) non-blocking, but the last
|
|
part blocking.
|
|
*/
|
|
static void
|
|
mysql_close_slow_part_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY_VOID_RETURN(
|
|
mysql_close_slow_part,
|
|
(parms->sock),
|
|
parms->sock)
|
|
}
|
|
|
|
int STDCALL
|
|
mysql_close_slow_part_start(MYSQL *sock)
|
|
{
|
|
MK_ASYNC_START_BODY_VOID_RETURN(
|
|
mysql_close_slow_part,
|
|
sock,
|
|
{
|
|
WIN_SET_NONBLOCKING(sock)
|
|
parms.sock= sock;
|
|
},
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_close_slow_part_cont(MYSQL *sock, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY_VOID_RETURN(sock)
|
|
}
|
|
int STDCALL
|
|
mysql_close_start(MYSQL *sock)
|
|
{
|
|
int res;
|
|
|
|
/* It is legitimate to have NULL sock argument, which will do nothing. */
|
|
if (sock && sock->net.vio)
|
|
{
|
|
res= mysql_close_slow_part_start(sock);
|
|
/* If we need to block, return now and do the rest in mysql_close_cont(). */
|
|
if (res)
|
|
return res;
|
|
}
|
|
mysql_close(sock);
|
|
return 0;
|
|
}
|
|
int STDCALL
|
|
mysql_close_cont(MYSQL *sock, int ready_status)
|
|
{
|
|
int res;
|
|
|
|
res= mysql_close_slow_part_cont(sock, ready_status);
|
|
if (res)
|
|
return res;
|
|
mysql_close(sock);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
These following are not available inside the server (neither blocking or
|
|
non-blocking).
|
|
*/
|
|
#ifndef MYSQL_SERVER
|
|
/* Structure used to pass parameters from mysql_change_user_start(). */
|
|
struct mysql_change_user_params {
|
|
MYSQL *mysql;
|
|
const char *user;
|
|
const char *passwd;
|
|
const char *db;
|
|
};
|
|
static void
|
|
mysql_change_user_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_change_user,
|
|
(parms->mysql, parms->user, parms->passwd, parms->db),
|
|
parms->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_change_user_start(my_bool *ret, MYSQL *mysql, const char *user, const char *passwd, const char *db)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_change_user,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.user= user;
|
|
parms.passwd= passwd;
|
|
parms.db= db;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_change_user_cont(my_bool *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_query_start(). */
|
|
struct mysql_query_params {
|
|
MYSQL *mysql;
|
|
const char *q;
|
|
};
|
|
static void
|
|
mysql_query_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_query,
|
|
(parms->mysql, parms->q),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_query_start(int *ret, MYSQL *mysql, const char *q)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_query,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.q= q;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_query_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_shutdown_start(). */
|
|
struct mysql_shutdown_params {
|
|
MYSQL *mysql;
|
|
enum mysql_enum_shutdown_level shutdown_level;
|
|
};
|
|
static void
|
|
mysql_shutdown_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_shutdown,
|
|
(parms->mysql, parms->shutdown_level),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_shutdown_start(int *ret, MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_shutdown,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.shutdown_level= shutdown_level;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_shutdown_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_dump_debug_info_start(). */
|
|
struct mysql_dump_debug_info_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_dump_debug_info_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_dump_debug_info,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_dump_debug_info_start(int *ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_dump_debug_info,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_dump_debug_info_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_refresh_start(). */
|
|
struct mysql_refresh_params {
|
|
MYSQL *mysql;
|
|
unsigned int refresh_options;
|
|
};
|
|
static void
|
|
mysql_refresh_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_refresh,
|
|
(parms->mysql, parms->refresh_options),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_refresh_start(int *ret, MYSQL *mysql, unsigned int refresh_options)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_refresh,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.refresh_options= refresh_options;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_refresh_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_kill_start(). */
|
|
struct mysql_kill_params {
|
|
MYSQL *mysql;
|
|
unsigned long pid;
|
|
};
|
|
static void
|
|
mysql_kill_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_kill,
|
|
(parms->mysql, parms->pid),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_kill_start(int *ret, MYSQL *mysql, unsigned long pid)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_kill,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.pid= pid;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_kill_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_set_server_option_start(). */
|
|
struct mysql_set_server_option_params {
|
|
MYSQL *mysql;
|
|
enum enum_mysql_set_option option;
|
|
};
|
|
static void
|
|
mysql_set_server_option_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_set_server_option,
|
|
(parms->mysql, parms->option),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_set_server_option_start(int *ret, MYSQL *mysql,
|
|
enum enum_mysql_set_option option)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_set_server_option,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.option= option;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_set_server_option_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_ping_start(). */
|
|
struct mysql_ping_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_ping_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_ping,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_ping_start(int *ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_ping,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_ping_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stat_start(). */
|
|
struct mysql_stat_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_stat_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stat,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
const char *,
|
|
r_const_ptr)
|
|
}
|
|
int STDCALL
|
|
mysql_stat_start(const char **ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stat,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
NULL,
|
|
r_const_ptr,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_stat_cont(const char **ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
NULL,
|
|
r_const_ptr)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_list_dbs_start(). */
|
|
struct mysql_list_dbs_params {
|
|
MYSQL *mysql;
|
|
const char *wild;
|
|
};
|
|
static void
|
|
mysql_list_dbs_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_list_dbs,
|
|
(parms->mysql, parms->wild),
|
|
parms->mysql,
|
|
MYSQL_RES *,
|
|
r_ptr)
|
|
}
|
|
int STDCALL
|
|
mysql_list_dbs_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_list_dbs,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.wild= wild;
|
|
},
|
|
NULL,
|
|
r_ptr,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_list_dbs_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
NULL,
|
|
r_ptr)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_list_tables_start(). */
|
|
struct mysql_list_tables_params {
|
|
MYSQL *mysql;
|
|
const char *wild;
|
|
};
|
|
static void
|
|
mysql_list_tables_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_list_tables,
|
|
(parms->mysql, parms->wild),
|
|
parms->mysql,
|
|
MYSQL_RES *,
|
|
r_ptr)
|
|
}
|
|
int STDCALL
|
|
mysql_list_tables_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_list_tables,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.wild= wild;
|
|
},
|
|
NULL,
|
|
r_ptr,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_list_tables_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
NULL,
|
|
r_ptr)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_list_processes_start(). */
|
|
struct mysql_list_processes_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_list_processes_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_list_processes,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
MYSQL_RES *,
|
|
r_ptr)
|
|
}
|
|
int STDCALL
|
|
mysql_list_processes_start(MYSQL_RES **ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_list_processes,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
NULL,
|
|
r_ptr,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
NULL,
|
|
r_ptr)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_list_fields_start(). */
|
|
struct mysql_list_fields_params {
|
|
MYSQL *mysql;
|
|
const char *table;
|
|
const char *wild;
|
|
};
|
|
static void
|
|
mysql_list_fields_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_list_fields,
|
|
(parms->mysql, parms->table, parms->wild),
|
|
parms->mysql,
|
|
MYSQL_RES *,
|
|
r_ptr)
|
|
}
|
|
int STDCALL
|
|
mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql, const char *table,
|
|
const char *wild)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_list_fields,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.table= table;
|
|
parms.wild= wild;
|
|
},
|
|
NULL,
|
|
r_ptr,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
NULL,
|
|
r_ptr)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_read_query_result_start(). */
|
|
struct mysql_read_query_result_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_read_query_result_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_read_query_result,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_read_query_result_start(my_bool *ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_read_query_result,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_read_query_result_cont(my_bool *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_prepare_start(). */
|
|
struct mysql_stmt_prepare_params {
|
|
MYSQL_STMT *stmt;
|
|
const char *query;
|
|
unsigned long length;
|
|
};
|
|
static void
|
|
mysql_stmt_prepare_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_prepare,
|
|
(parms->stmt, parms->query, parms->length),
|
|
parms->stmt->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt, const char *query,
|
|
unsigned long length)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_prepare,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
parms.query= query;
|
|
parms.length= length;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* If stmt->mysql==NULL then we will not block so can call directly. */
|
|
if (!stmt->mysql)
|
|
{
|
|
*ret= mysql_stmt_prepare(stmt, query, length);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_execute_start(). */
|
|
struct mysql_stmt_execute_params {
|
|
MYSQL_STMT *stmt;
|
|
};
|
|
static void
|
|
mysql_stmt_execute_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_execute,
|
|
(parms->stmt),
|
|
parms->stmt->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_execute,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
},
|
|
1,
|
|
r_int,
|
|
/*
|
|
If eg. mysql_change_user(), stmt->mysql will be NULL.
|
|
In this case, we cannot block.
|
|
*/
|
|
if (!stmt->mysql)
|
|
{
|
|
*ret= mysql_stmt_execute(stmt);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_fetch_start(). */
|
|
struct mysql_stmt_fetch_params {
|
|
MYSQL_STMT *stmt;
|
|
};
|
|
static void
|
|
mysql_stmt_fetch_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_fetch,
|
|
(parms->stmt),
|
|
parms->stmt->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_fetch,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* If stmt->mysql==NULL then we will not block so can call directly. */
|
|
if (!stmt->mysql)
|
|
{
|
|
*ret= mysql_stmt_fetch(stmt);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_store_result_start(). */
|
|
struct mysql_stmt_store_result_params {
|
|
MYSQL_STMT *stmt;
|
|
};
|
|
static void
|
|
mysql_stmt_store_result_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_store_result,
|
|
(parms->stmt),
|
|
parms->stmt->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_store_result,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* If stmt->mysql==NULL then we will not block so can call directly. */
|
|
if (!stmt->mysql)
|
|
{
|
|
*ret= mysql_stmt_store_result(stmt);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_close_start(). */
|
|
struct mysql_stmt_close_params {
|
|
MYSQL_STMT *stmt;
|
|
};
|
|
static void
|
|
mysql_stmt_close_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_close,
|
|
(parms->stmt),
|
|
parms->stmt->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_close,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* If stmt->mysql==NULL then we will not block so can call directly. */
|
|
if (!stmt->mysql)
|
|
{
|
|
*ret= mysql_stmt_close(stmt);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_reset_start(). */
|
|
struct mysql_stmt_reset_params {
|
|
MYSQL_STMT *stmt;
|
|
};
|
|
static void
|
|
mysql_stmt_reset_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_reset,
|
|
(parms->stmt),
|
|
parms->stmt->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT *stmt)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_reset,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* If stmt->mysql==NULL then we will not block so can call directly. */
|
|
if (!stmt->mysql)
|
|
{
|
|
*ret= mysql_stmt_reset(stmt);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_free_result_start(). */
|
|
struct mysql_stmt_free_result_params {
|
|
MYSQL_STMT *stmt;
|
|
};
|
|
static void
|
|
mysql_stmt_free_result_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_free_result,
|
|
(parms->stmt),
|
|
parms->stmt->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_free_result,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* If stmt->mysql==NULL then we will not block so can call directly. */
|
|
if (!stmt->mysql)
|
|
{
|
|
*ret= mysql_stmt_free_result(stmt);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_send_long_data_start(). */
|
|
struct mysql_stmt_send_long_data_params {
|
|
MYSQL_STMT *stmt;
|
|
unsigned int param_number;
|
|
const char *data;
|
|
unsigned long length;
|
|
};
|
|
static void
|
|
mysql_stmt_send_long_data_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_send_long_data,
|
|
(parms->stmt, parms->param_number, parms->data, parms->length),
|
|
parms->stmt->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt,
|
|
unsigned int param_number,
|
|
const char *data, unsigned long length)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_send_long_data,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
parms.param_number= param_number;
|
|
parms.data= data;
|
|
parms.length= length;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* If stmt->mysql==NULL then we will not block so can call directly. */
|
|
if (!stmt->mysql)
|
|
{
|
|
*ret= mysql_stmt_send_long_data(stmt, param_number, data, length);
|
|
return 0;
|
|
})
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_commit_start(). */
|
|
struct mysql_commit_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_commit_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_commit,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_commit_start(my_bool *ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_commit,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_commit_cont(my_bool *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_rollback_start(). */
|
|
struct mysql_rollback_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_rollback_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_rollback,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_rollback_start(my_bool *ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_rollback,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_rollback_cont(my_bool *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_autocommit_start(). */
|
|
struct mysql_autocommit_params {
|
|
MYSQL *mysql;
|
|
my_bool auto_mode;
|
|
};
|
|
static void
|
|
mysql_autocommit_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_autocommit,
|
|
(parms->mysql, parms->auto_mode),
|
|
parms->mysql,
|
|
my_bool,
|
|
r_my_bool)
|
|
}
|
|
int STDCALL
|
|
mysql_autocommit_start(my_bool *ret, MYSQL *mysql, my_bool auto_mode)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_autocommit,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
parms.auto_mode= auto_mode;
|
|
},
|
|
TRUE,
|
|
r_my_bool,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_autocommit_cont(my_bool *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
TRUE,
|
|
r_my_bool)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_next_result_start(). */
|
|
struct mysql_next_result_params {
|
|
MYSQL *mysql;
|
|
};
|
|
static void
|
|
mysql_next_result_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_next_result,
|
|
(parms->mysql),
|
|
parms->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_next_result_start(int *ret, MYSQL *mysql)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_next_result,
|
|
mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(mysql)
|
|
parms.mysql= mysql;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_next_result_cont(int *ret, MYSQL *mysql, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
|
|
/* Structure used to pass parameters from mysql_stmt_next_result_start(). */
|
|
struct mysql_stmt_next_result_params {
|
|
MYSQL_STMT *stmt;
|
|
};
|
|
static void
|
|
mysql_stmt_next_result_start_internal(void *d)
|
|
{
|
|
MK_ASYNC_INTERNAL_BODY(
|
|
mysql_stmt_next_result,
|
|
(parms->stmt),
|
|
parms->stmt->mysql,
|
|
int,
|
|
r_int)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_next_result_start(int *ret, MYSQL_STMT *stmt)
|
|
{
|
|
MK_ASYNC_START_BODY(
|
|
mysql_stmt_next_result,
|
|
stmt->mysql,
|
|
{
|
|
WIN_SET_NONBLOCKING(stmt->mysql)
|
|
parms.stmt= stmt;
|
|
},
|
|
1,
|
|
r_int,
|
|
/* Nothing */)
|
|
}
|
|
int STDCALL
|
|
mysql_stmt_next_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
|
|
{
|
|
MK_ASYNC_CONT_BODY(
|
|
stmt->mysql,
|
|
1,
|
|
r_int)
|
|
}
|
|
#endif
|
|
|
|
|
|
/*
|
|
The following functions are deprecated, and so have no non-blocking version:
|
|
|
|
mysql_connect
|
|
mysql_create_db
|
|
mysql_drop_db
|
|
*/
|
|
|
|
/*
|
|
The following functions can newer block, and so do not have special
|
|
non-blocking versions:
|
|
|
|
mysql_num_rows()
|
|
mysql_num_fields()
|
|
mysql_eof()
|
|
mysql_fetch_field_direct()
|
|
mysql_fetch_fields()
|
|
mysql_row_tell()
|
|
mysql_field_tell()
|
|
mysql_field_count()
|
|
mysql_affected_rows()
|
|
mysql_insert_id()
|
|
mysql_errno()
|
|
mysql_error()
|
|
mysql_sqlstate()
|
|
mysql_warning_count()
|
|
mysql_info()
|
|
mysql_thread_id()
|
|
mysql_character_set_name()
|
|
mysql_init()
|
|
mysql_ssl_set()
|
|
mysql_get_ssl_cipher()
|
|
mysql_use_result()
|
|
mysql_get_character_set_info()
|
|
mysql_set_local_infile_handler()
|
|
mysql_set_local_infile_default()
|
|
mysql_get_server_info()
|
|
mysql_get_server_name()
|
|
mysql_get_client_info()
|
|
mysql_get_client_version()
|
|
mysql_get_host_info()
|
|
mysql_get_server_version()
|
|
mysql_get_proto_info()
|
|
mysql_options()
|
|
mysql_data_seek()
|
|
mysql_row_seek()
|
|
mysql_field_seek()
|
|
mysql_fetch_lengths()
|
|
mysql_fetch_field()
|
|
mysql_escape_string()
|
|
mysql_hex_string()
|
|
mysql_real_escape_string()
|
|
mysql_debug()
|
|
myodbc_remove_escape()
|
|
mysql_thread_safe()
|
|
mysql_embedded()
|
|
mariadb_connection()
|
|
mysql_stmt_init()
|
|
mysql_stmt_fetch_column()
|
|
mysql_stmt_param_count()
|
|
mysql_stmt_attr_set()
|
|
mysql_stmt_attr_get()
|
|
mysql_stmt_bind_param()
|
|
mysql_stmt_bind_result()
|
|
mysql_stmt_result_metadata()
|
|
mysql_stmt_param_metadata()
|
|
mysql_stmt_errno()
|
|
mysql_stmt_error()
|
|
mysql_stmt_sqlstate()
|
|
mysql_stmt_row_seek()
|
|
mysql_stmt_row_tell()
|
|
mysql_stmt_data_seek()
|
|
mysql_stmt_num_rows()
|
|
mysql_stmt_affected_rows()
|
|
mysql_stmt_insert_id()
|
|
mysql_stmt_field_count()
|
|
mysql_more_results()
|
|
mysql_get_socket()
|
|
mysql_get_timeout_value()
|
|
*/
|