1/*
2 Copyright 2011 Kristian Nielsen and Monty Program Ab
3
4 This file is free software; you can redistribute it and/or
5 modify it under the terms of the GNU Lesser General Public
6 License as published by the Free Software Foundation; either
7 version 2.1 of the License, or (at your option) any later version.
8
9 This library is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 Lesser General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this. If not, see <http://www.gnu.org/licenses/>.
16*/
17
18/*
19 MySQL non-blocking client library functions.
20*/
21
22#include "my_global.h"
23#include "my_sys.h"
24#include "mysql.h"
25#include "errmsg.h"
26#include "sql_common.h"
27#include "my_context.h"
28#include "violite.h"
29#include "mysql_async.h"
30
31
32#ifdef __WIN__
33/*
34 Windows does not support MSG_DONTWAIT for send()/recv(). So we need to ensure
35 that the socket is non-blocking at the start of every operation.
36*/
37#define WIN_SET_NONBLOCKING(mysql) { \
38 my_bool old_mode; \
39 if ((mysql)->net.vio) vio_blocking((mysql)->net.vio, FALSE, &old_mode); \
40 }
41#else
42#define WIN_SET_NONBLOCKING(mysql)
43#endif
44
45
46void
47my_context_install_suspend_resume_hook(struct mysql_async_context *b,
48 void (*hook)(my_bool, void *),
49 void *user_data)
50{
51 b->suspend_resume_hook= hook;
52 b->suspend_resume_hook_user_data= user_data;
53}
54
55
56/* Asynchronous connect(); socket must already be set non-blocking. */
57int
58my_connect_async(struct mysql_async_context *b, my_socket fd,
59 const struct sockaddr *name, uint namelen, int vio_timeout)
60{
61 int res;
62 size_socket s_err_size;
63
64 /* Make the socket non-blocking. */
65#ifdef __WIN__
66 ulong arg= 1;
67 ioctlsocket(fd, FIONBIO, (void *)&arg);
68#else
69 fcntl(fd, F_SETFL, O_NONBLOCK);
70#endif
71
72 b->events_to_wait_for= 0;
73 /*
74 Start to connect asynchronously.
75 If this will block, we suspend the call and return control to the
76 application context. The application will then resume us when the socket
77 polls ready for write, indicating that the connection attempt completed.
78 */
79 res= connect(fd, name, namelen);
80 if (res != 0)
81 {
82#ifdef __WIN__
83 int wsa_err= WSAGetLastError();
84 if (wsa_err != WSAEWOULDBLOCK)
85 return res;
86 b->events_to_wait_for|= MYSQL_WAIT_EXCEPT;
87#else
88 int err= errno;
89 if (err != EINPROGRESS && err != EALREADY && err != EAGAIN)
90 return res;
91#endif
92 b->events_to_wait_for|= MYSQL_WAIT_WRITE;
93 if (vio_timeout >= 0)
94 {
95 b->timeout_value= vio_timeout;
96 b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
97 }
98 else
99 b->timeout_value= 0;
100 if (b->suspend_resume_hook)
101 (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
102 my_context_yield(&b->async_context);
103 if (b->suspend_resume_hook)
104 (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
105 if (b->events_occurred & MYSQL_WAIT_TIMEOUT)
106 return -1;
107
108 s_err_size= sizeof(res);
109 if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &res, &s_err_size) != 0)
110 return -1;
111 if (res)
112 {
113 errno= res;
114 return -1;
115 }
116 }
117 return res;
118}
119
120#define IS_BLOCKING_ERROR() \
121 IF_WIN(WSAGetLastError() != WSAEWOULDBLOCK, \
122 (errno != EAGAIN && errno != EINTR))
123
124#ifdef _AIX
125#ifndef MSG_DONTWAIT
126#define MSG_DONTWAIT 0
127#endif
128#endif
129
130ssize_t
131my_recv_async(struct mysql_async_context *b, my_socket fd,
132 unsigned char *buf, size_t size, int timeout)
133{
134 ssize_t res;
135
136 for (;;)
137 {
138 res= recv(fd, buf, (int)size, IF_WIN(0, MSG_DONTWAIT));
139 if (res >= 0 || IS_BLOCKING_ERROR())
140 return res;
141 b->events_to_wait_for= MYSQL_WAIT_READ;
142 if (timeout >= 0)
143 {
144 b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
145 b->timeout_value= timeout;
146 }
147 if (b->suspend_resume_hook)
148 (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
149 my_context_yield(&b->async_context);
150 if (b->suspend_resume_hook)
151 (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
152 if (b->events_occurred & MYSQL_WAIT_TIMEOUT)
153 return -1;
154 }
155}
156
157
158ssize_t
159my_send_async(struct mysql_async_context *b, my_socket fd,
160 const unsigned char *buf, size_t size, int timeout)
161{
162 ssize_t res;
163
164 for (;;)
165 {
166 res= send(fd, buf, (int)size, IF_WIN(0, MSG_DONTWAIT));
167 if (res >= 0 || IS_BLOCKING_ERROR())
168 return res;
169 b->events_to_wait_for= MYSQL_WAIT_WRITE;
170 if (timeout >= 0)
171 {
172 b->events_to_wait_for|= MYSQL_WAIT_TIMEOUT;
173 b->timeout_value= timeout;
174 }
175 if (b->suspend_resume_hook)
176 (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
177 my_context_yield(&b->async_context);
178 if (b->suspend_resume_hook)
179 (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
180 if (b->events_occurred & MYSQL_WAIT_TIMEOUT)
181 return -1;
182 }
183}
184
185
186my_bool
187my_io_wait_async(struct mysql_async_context *b, enum enum_vio_io_event event,
188 int timeout)
189{
190 switch (event)
191 {
192 case VIO_IO_EVENT_READ:
193 b->events_to_wait_for = MYSQL_WAIT_READ;
194 break;
195 case VIO_IO_EVENT_WRITE:
196 b->events_to_wait_for = MYSQL_WAIT_WRITE;
197 break;
198 case VIO_IO_EVENT_CONNECT:
199 b->events_to_wait_for = MYSQL_WAIT_WRITE | IF_WIN(0, MYSQL_WAIT_EXCEPT);
200 break;
201 }
202
203 if (timeout >= 0)
204 {
205 b->events_to_wait_for |= MYSQL_WAIT_TIMEOUT;
206 b->timeout_value= timeout;
207 }
208 if (b->suspend_resume_hook)
209 (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
210 my_context_yield(&b->async_context);
211 if (b->suspend_resume_hook)
212 (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
213 return (b->events_occurred & MYSQL_WAIT_TIMEOUT) ? 0 : 1;
214}
215
216
217#ifdef HAVE_OPENSSL
218static my_bool
219my_ssl_async_check_result(int res, struct mysql_async_context *b, SSL *ssl)
220{
221 int ssl_err;
222 b->events_to_wait_for= 0;
223 if (res >= 0)
224 return 1;
225 ssl_err= SSL_get_error(ssl, res);
226 if (ssl_err == SSL_ERROR_WANT_READ)
227 b->events_to_wait_for|= MYSQL_WAIT_READ;
228 else if (ssl_err == SSL_ERROR_WANT_WRITE)
229 b->events_to_wait_for|= MYSQL_WAIT_WRITE;
230 else
231 return 1;
232 if (b->suspend_resume_hook)
233 (*b->suspend_resume_hook)(TRUE, b->suspend_resume_hook_user_data);
234 my_context_yield(&b->async_context);
235 if (b->suspend_resume_hook)
236 (*b->suspend_resume_hook)(FALSE, b->suspend_resume_hook_user_data);
237 return 0;
238}
239
240int
241my_ssl_read_async(struct mysql_async_context *b, SSL *ssl,
242 void *buf, int size)
243{
244 int res;
245
246 for (;;)
247 {
248 res= SSL_read(ssl, buf, size);
249 if (my_ssl_async_check_result(res, b, ssl))
250 return res;
251 }
252}
253
254int
255my_ssl_write_async(struct mysql_async_context *b, SSL *ssl,
256 const void *buf, int size)
257{
258 int res;
259
260 for (;;)
261 {
262 res= SSL_write(ssl, buf, size);
263 if (my_ssl_async_check_result(res, b, ssl))
264 return res;
265 }
266}
267#endif /* HAVE_OPENSSL */
268
269/*
270 Legacy support of the MariaDB 5.5 version, where timeouts where only in
271 seconds resolution. Applications that use this will be asked to set a timeout
272 at the nearest higher whole-seconds value.
273*/
274unsigned int STDCALL
275mysql_get_timeout_value(const MYSQL *mysql)
276{
277 unsigned int timeout= mysql->options.extension->async_context->timeout_value;
278 /* Avoid overflow. */
279 if (timeout > UINT_MAX - 999)
280 return (timeout - 1)/1000 + 1;
281 else
282 return (timeout+999)/1000;
283}
284
285
286unsigned int STDCALL
287mysql_get_timeout_value_ms(const MYSQL *mysql)
288{
289 return mysql->options.extension->async_context->timeout_value;
290}
291
292
293/*
294 Now create non-blocking definitions for all the calls that may block.
295
296 Each call FOO gives rise to FOO_start() that prepares the MYSQL object for
297 doing non-blocking calls that can suspend operation mid-way, and then starts
298 the call itself. And a FOO_start_internal trampoline to assist with running
299 the real call in a co-routine that can be suspended. And a FOO_cont() that
300 can continue a suspended operation.
301*/
302
303#define MK_ASYNC_INTERNAL_BODY(call, invoke_args, mysql_val, ret_type, ok_val)\
304 struct call ## _params *parms= (struct call ## _params *)d; \
305 ret_type ret; \
306 struct mysql_async_context *b= \
307 (mysql_val)->options.extension->async_context; \
308 \
309 ret= call invoke_args; \
310 b->ret_result. ok_val = ret; \
311 b->events_to_wait_for= 0;
312
313#define MK_ASYNC_START_BODY(call, mysql_val, parms_assign, err_val, ok_val, extra1) \
314 int res; \
315 struct mysql_async_context *b; \
316 struct call ## _params parms; \
317 \
318 extra1 \
319 b= mysql_val->options.extension->async_context; \
320 parms_assign \
321 \
322 b->active= 1; \
323 res= my_context_spawn(&b->async_context, call ## _start_internal, &parms); \
324 b->active= b->suspended= 0; \
325 if (res > 0) \
326 { \
327 /* Suspended. */ \
328 b->suspended= 1; \
329 return b->events_to_wait_for; \
330 } \
331 if (res < 0) \
332 { \
333 set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
334 *ret= err_val; \
335 } \
336 else \
337 *ret= b->ret_result. ok_val; \
338 return 0;
339
340#define MK_ASYNC_CONT_BODY(mysql_val, err_val, ok_val) \
341 int res; \
342 struct mysql_async_context *b= \
343 (mysql_val)->options.extension->async_context; \
344 if (!b->suspended) \
345 { \
346 set_mysql_error((mysql_val), CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); \
347 *ret= err_val; \
348 return 0; \
349 } \
350 \
351 b->active= 1; \
352 b->events_occurred= ready_status; \
353 res= my_context_continue(&b->async_context); \
354 b->active= 0; \
355 if (res > 0) \
356 return b->events_to_wait_for; /* (Still) suspended */ \
357 b->suspended= 0; \
358 if (res < 0) \
359 { \
360 set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
361 *ret= err_val; \
362 } \
363 else \
364 *ret= b->ret_result. ok_val; /* Finished. */ \
365 return 0;
366
367#define MK_ASYNC_INTERNAL_BODY_VOID_RETURN(call, invoke_args, mysql_val) \
368 struct call ## _params *parms= (struct call ## _params *)d; \
369 struct mysql_async_context *b= \
370 (mysql_val)->options.extension->async_context; \
371 \
372 call invoke_args; \
373 b->events_to_wait_for= 0;
374
375#define MK_ASYNC_START_BODY_VOID_RETURN(call, mysql_val, parms_assign, extra1)\
376 int res; \
377 struct mysql_async_context *b; \
378 struct call ## _params parms; \
379 \
380 extra1 \
381 b= mysql_val->options.extension->async_context; \
382 parms_assign \
383 \
384 b->active= 1; \
385 res= my_context_spawn(&b->async_context, call ## _start_internal, &parms); \
386 b->active= b->suspended= 0; \
387 if (res > 0) \
388 { \
389 /* Suspended. */ \
390 b->suspended= 1; \
391 return b->events_to_wait_for; \
392 } \
393 if (res < 0) \
394 set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
395 return 0;
396
397#define MK_ASYNC_CONT_BODY_VOID_RETURN(mysql_val) \
398 int res; \
399 struct mysql_async_context *b= \
400 (mysql_val)->options.extension->async_context; \
401 if (!b->suspended) \
402 { \
403 set_mysql_error((mysql_val), CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate); \
404 return 0; \
405 } \
406 \
407 b->active= 1; \
408 b->events_occurred= ready_status; \
409 res= my_context_continue(&b->async_context); \
410 b->active= 0; \
411 if (res > 0) \
412 return b->events_to_wait_for; /* (Still) suspended */ \
413 b->suspended= 0; \
414 if (res < 0) \
415 set_mysql_error((mysql_val), CR_OUT_OF_MEMORY, unknown_sqlstate); \
416 return 0;
417
418
419/* Structure used to pass parameters from mysql_real_connect_start(). */
420struct mysql_real_connect_params {
421 MYSQL *mysql;
422 const char *host;
423 const char *user;
424 const char *passwd;
425 const char *db;
426 unsigned int port;
427 const char *unix_socket;
428 unsigned long client_flags;
429};
430static void
431mysql_real_connect_start_internal(void *d)
432{
433MK_ASYNC_INTERNAL_BODY(
434 mysql_real_connect,
435 (parms->mysql, parms->host, parms->user, parms->passwd, parms->db,
436 parms->port, parms->unix_socket, parms->client_flags),
437 parms->mysql,
438 MYSQL *,
439 r_ptr)
440}
441int STDCALL
442mysql_real_connect_start(MYSQL **ret, MYSQL *mysql, const char *host,
443 const char *user, const char *passwd, const char *db,
444 unsigned int port, const char *unix_socket,
445 unsigned long client_flags)
446{
447MK_ASYNC_START_BODY(
448 mysql_real_connect,
449 mysql,
450 {
451 parms.mysql= mysql;
452 parms.host= host;
453 parms.user= user;
454 parms.passwd= passwd;
455 parms.db= db;
456 parms.port= port;
457 parms.unix_socket= unix_socket;
458 /*
459 async wrapper enforce the CLIENT_REMEMBER_OPTIONS flag to be
460 functional (otherwise it can't operate)
461 */
462 parms.client_flags= client_flags | CLIENT_REMEMBER_OPTIONS;
463 },
464 NULL,
465 r_ptr,
466 /* Nothing */)
467}
468int STDCALL
469mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql, int ready_status)
470{
471MK_ASYNC_CONT_BODY(
472 mysql,
473 NULL,
474 r_ptr)
475}
476
477/* Structure used to pass parameters from mysql_real_query_start(). */
478struct mysql_real_query_params {
479 MYSQL *mysql;
480 const char *stmt_str;
481 unsigned long length;
482};
483static void
484mysql_real_query_start_internal(void *d)
485{
486MK_ASYNC_INTERNAL_BODY(
487 mysql_real_query,
488 (parms->mysql, parms->stmt_str, parms->length),
489 parms->mysql,
490 int,
491 r_int)
492}
493int STDCALL
494mysql_real_query_start(int *ret, MYSQL *mysql, const char *stmt_str, unsigned long length)
495{
496MK_ASYNC_START_BODY(
497 mysql_real_query,
498 mysql,
499 {
500 WIN_SET_NONBLOCKING(mysql)
501 parms.mysql= mysql;
502 parms.stmt_str= stmt_str;
503 parms.length= length;
504 },
505 1,
506 r_int,
507 /* Nothing */)
508}
509int STDCALL
510mysql_real_query_cont(int *ret, MYSQL *mysql, int ready_status)
511{
512MK_ASYNC_CONT_BODY(
513 mysql,
514 1,
515 r_int)
516}
517
518/* Structure used to pass parameters from mysql_fetch_row_start(). */
519struct mysql_fetch_row_params {
520 MYSQL_RES *result;
521};
522static void
523mysql_fetch_row_start_internal(void *d)
524{
525MK_ASYNC_INTERNAL_BODY(
526 mysql_fetch_row,
527 (parms->result),
528 parms->result->handle,
529 MYSQL_ROW,
530 r_ptr)
531}
532int STDCALL
533mysql_fetch_row_start(MYSQL_ROW *ret, MYSQL_RES *result)
534{
535MK_ASYNC_START_BODY(
536 mysql_fetch_row,
537 result->handle,
538 {
539 WIN_SET_NONBLOCKING(result->handle)
540 parms.result= result;
541 },
542 NULL,
543 r_ptr,
544 /*
545 If we already fetched all rows from server (eg. mysql_store_result()),
546 then result->handle will be NULL and we cannot suspend. But that is fine,
547 since in this case mysql_fetch_row cannot block anyway. Just return
548 directly.
549 */
550 if (!result->handle)
551 {
552 *ret= mysql_fetch_row(result);
553 return 0;
554 })
555}
556int STDCALL
557mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result, int ready_status)
558{
559MK_ASYNC_CONT_BODY(
560 result->handle,
561 NULL,
562 r_ptr)
563}
564
565/* Structure used to pass parameters from mysql_set_character_set_start(). */
566struct mysql_set_character_set_params {
567 MYSQL *mysql;
568 const char *csname;
569};
570static void
571mysql_set_character_set_start_internal(void *d)
572{
573MK_ASYNC_INTERNAL_BODY(
574 mysql_set_character_set,
575 (parms->mysql, parms->csname),
576 parms->mysql,
577 int,
578 r_int)
579}
580int STDCALL
581mysql_set_character_set_start(int *ret, MYSQL *mysql, const char *csname)
582{
583MK_ASYNC_START_BODY(
584 mysql_set_character_set,
585 mysql,
586 {
587 WIN_SET_NONBLOCKING(mysql)
588 parms.mysql= mysql;
589 parms.csname= csname;
590 },
591 1,
592 r_int,
593 /* Nothing */)
594}
595int STDCALL
596mysql_set_character_set_cont(int *ret, MYSQL *mysql, int ready_status)
597{
598MK_ASYNC_CONT_BODY(
599 mysql,
600 1,
601 r_int)
602}
603
604/* Structure used to pass parameters from mysql_sekect_db_start(). */
605struct mysql_select_db_params {
606 MYSQL *mysql;
607 const char *db;
608};
609static void
610mysql_select_db_start_internal(void *d)
611{
612MK_ASYNC_INTERNAL_BODY(
613 mysql_select_db,
614 (parms->mysql, parms->db),
615 parms->mysql,
616 int,
617 r_int)
618}
619int STDCALL
620mysql_select_db_start(int *ret, MYSQL *mysql, const char *db)
621{
622MK_ASYNC_START_BODY(
623 mysql_select_db,
624 mysql,
625 {
626 WIN_SET_NONBLOCKING(mysql)
627 parms.mysql= mysql;
628 parms.db= db;
629 },
630 1,
631 r_int,
632 /* Nothing */)
633}
634int STDCALL
635mysql_select_db_cont(int *ret, MYSQL *mysql, int ready_status)
636{
637MK_ASYNC_CONT_BODY(
638 mysql,
639 1,
640 r_int)
641}
642
643/* Structure used to pass parameters from mysql_send_query_start(). */
644struct mysql_send_query_params {
645 MYSQL *mysql;
646 const char *q;
647 unsigned long length;
648};
649static void
650mysql_send_query_start_internal(void *d)
651{
652MK_ASYNC_INTERNAL_BODY(
653 mysql_send_query,
654 (parms->mysql, parms->q, parms->length),
655 parms->mysql,
656 int,
657 r_int)
658}
659int STDCALL
660mysql_send_query_start(int *ret, MYSQL *mysql, const char *q, unsigned long length)
661{
662MK_ASYNC_START_BODY(
663 mysql_send_query,
664 mysql,
665 {
666 WIN_SET_NONBLOCKING(mysql)
667 parms.mysql= mysql;
668 parms.q= q;
669 parms.length= length;
670 },
671 1,
672 r_int,
673 /* Nothing */)
674}
675int STDCALL
676mysql_send_query_cont(int *ret, MYSQL *mysql, int ready_status)
677{
678MK_ASYNC_CONT_BODY(
679 mysql,
680 1,
681 r_int)
682}
683
684/* Structure used to pass parameters from mysql_store_result_start(). */
685struct mysql_store_result_params {
686 MYSQL *mysql;
687};
688static void
689mysql_store_result_start_internal(void *d)
690{
691MK_ASYNC_INTERNAL_BODY(
692 mysql_store_result,
693 (parms->mysql),
694 parms->mysql,
695 MYSQL_RES *,
696 r_ptr)
697}
698int STDCALL
699mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql)
700{
701MK_ASYNC_START_BODY(
702 mysql_store_result,
703 mysql,
704 {
705 WIN_SET_NONBLOCKING(mysql)
706 parms.mysql= mysql;
707 },
708 NULL,
709 r_ptr,
710 /* Nothing */)
711}
712int STDCALL
713mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
714{
715MK_ASYNC_CONT_BODY(
716 mysql,
717 NULL,
718 r_ptr)
719}
720
721/* Structure used to pass parameters from mysql_free_result_start(). */
722struct mysql_free_result_params {
723 MYSQL_RES *result;
724};
725static void
726mysql_free_result_start_internal(void *d)
727{
728MK_ASYNC_INTERNAL_BODY_VOID_RETURN(
729 mysql_free_result,
730 (parms->result),
731 parms->result->handle)
732}
733int STDCALL
734mysql_free_result_start(MYSQL_RES *result)
735{
736MK_ASYNC_START_BODY_VOID_RETURN(
737 mysql_free_result,
738 result->handle,
739 {
740 WIN_SET_NONBLOCKING(result->handle)
741 parms.result= result;
742 },
743 /*
744 mysql_free_result() can have NULL in result->handle (this happens when all
745 rows have been fetched and mysql_fetch_row() returned NULL.)
746 So we cannot suspend, but it does not matter, as in this case
747 mysql_free_result() cannot block.
748 It is also legitimate to have NULL result, which will do nothing.
749 */
750 if (!result || !result->handle)
751 {
752 mysql_free_result(result);
753 return 0;
754 })
755}
756int STDCALL
757mysql_free_result_cont(MYSQL_RES *result, int ready_status)
758{
759MK_ASYNC_CONT_BODY_VOID_RETURN(result->handle)
760}
761
762/* Structure used to pass parameters from mysql_close_slow_part_start(). */
763struct mysql_close_slow_part_params {
764 MYSQL *sock;
765};
766/*
767 We need special handling for mysql_close(), as the first part may block,
768 while the last part needs to free our extra library context stack.
769
770 So we do the first part (mysql_close_slow_part()) non-blocking, but the last
771 part blocking.
772*/
773static void
774mysql_close_slow_part_start_internal(void *d)
775{
776MK_ASYNC_INTERNAL_BODY_VOID_RETURN(
777 mysql_close_slow_part,
778 (parms->sock),
779 parms->sock)
780}
781int STDCALL
782mysql_close_slow_part_start(MYSQL *sock)
783{
784MK_ASYNC_START_BODY_VOID_RETURN(
785 mysql_close_slow_part,
786 sock,
787 {
788 WIN_SET_NONBLOCKING(sock)
789 parms.sock= sock;
790 },
791 /* Nothing */)
792}
793int STDCALL
794mysql_close_slow_part_cont(MYSQL *sock, int ready_status)
795{
796MK_ASYNC_CONT_BODY_VOID_RETURN(sock)
797}
798int STDCALL
799mysql_close_start(MYSQL *sock)
800{
801 int res;
802
803 /* It is legitimate to have NULL sock argument, which will do nothing. */
804 if (sock)
805 {
806 res= mysql_close_slow_part_start(sock);
807 /* If we need to block, return now and do the rest in mysql_close_cont(). */
808 if (res)
809 return res;
810 }
811 mysql_close(sock);
812 return 0;
813}
814int STDCALL
815mysql_close_cont(MYSQL *sock, int ready_status)
816{
817 int res;
818
819 res= mysql_close_slow_part_cont(sock, ready_status);
820 if (res)
821 return res;
822 mysql_close(sock);
823 return 0;
824}
825
826/*
827 These following are not available inside the server (neither blocking or
828 non-blocking).
829*/
830#ifndef MYSQL_SERVER
831/* Structure used to pass parameters from mysql_change_user_start(). */
832struct mysql_change_user_params {
833 MYSQL *mysql;
834 const char *user;
835 const char *passwd;
836 const char *db;
837};
838static void
839mysql_change_user_start_internal(void *d)
840{
841MK_ASYNC_INTERNAL_BODY(
842 mysql_change_user,
843 (parms->mysql, parms->user, parms->passwd, parms->db),
844 parms->mysql,
845 my_bool,
846 r_my_bool)
847}
848int STDCALL
849mysql_change_user_start(my_bool *ret, MYSQL *mysql, const char *user, const char *passwd, const char *db)
850{
851MK_ASYNC_START_BODY(
852 mysql_change_user,
853 mysql,
854 {
855 WIN_SET_NONBLOCKING(mysql)
856 parms.mysql= mysql;
857 parms.user= user;
858 parms.passwd= passwd;
859 parms.db= db;
860 },
861 TRUE,
862 r_my_bool,
863 /* Nothing */)
864}
865int STDCALL
866mysql_change_user_cont(my_bool *ret, MYSQL *mysql, int ready_status)
867{
868MK_ASYNC_CONT_BODY(
869 mysql,
870 TRUE,
871 r_my_bool)
872}
873
874/* Structure used to pass parameters from mysql_query_start(). */
875struct mysql_query_params {
876 MYSQL *mysql;
877 const char *q;
878};
879static void
880mysql_query_start_internal(void *d)
881{
882MK_ASYNC_INTERNAL_BODY(
883 mysql_query,
884 (parms->mysql, parms->q),
885 parms->mysql,
886 int,
887 r_int)
888}
889int STDCALL
890mysql_query_start(int *ret, MYSQL *mysql, const char *q)
891{
892MK_ASYNC_START_BODY(
893 mysql_query,
894 mysql,
895 {
896 WIN_SET_NONBLOCKING(mysql)
897 parms.mysql= mysql;
898 parms.q= q;
899 },
900 1,
901 r_int,
902 /* Nothing */)
903}
904int STDCALL
905mysql_query_cont(int *ret, MYSQL *mysql, int ready_status)
906{
907MK_ASYNC_CONT_BODY(
908 mysql,
909 1,
910 r_int)
911}
912
913/* Structure used to pass parameters from mysql_shutdown_start(). */
914struct mysql_shutdown_params {
915 MYSQL *mysql;
916 enum mysql_enum_shutdown_level shutdown_level;
917};
918static void
919mysql_shutdown_start_internal(void *d)
920{
921MK_ASYNC_INTERNAL_BODY(
922 mysql_shutdown,
923 (parms->mysql, parms->shutdown_level),
924 parms->mysql,
925 int,
926 r_int)
927}
928int STDCALL
929mysql_shutdown_start(int *ret, MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
930{
931MK_ASYNC_START_BODY(
932 mysql_shutdown,
933 mysql,
934 {
935 WIN_SET_NONBLOCKING(mysql)
936 parms.mysql= mysql;
937 parms.shutdown_level= shutdown_level;
938 },
939 1,
940 r_int,
941 /* Nothing */)
942}
943int STDCALL
944mysql_shutdown_cont(int *ret, MYSQL *mysql, int ready_status)
945{
946MK_ASYNC_CONT_BODY(
947 mysql,
948 1,
949 r_int)
950}
951
952/* Structure used to pass parameters from mysql_dump_debug_info_start(). */
953struct mysql_dump_debug_info_params {
954 MYSQL *mysql;
955};
956static void
957mysql_dump_debug_info_start_internal(void *d)
958{
959MK_ASYNC_INTERNAL_BODY(
960 mysql_dump_debug_info,
961 (parms->mysql),
962 parms->mysql,
963 int,
964 r_int)
965}
966int STDCALL
967mysql_dump_debug_info_start(int *ret, MYSQL *mysql)
968{
969MK_ASYNC_START_BODY(
970 mysql_dump_debug_info,
971 mysql,
972 {
973 WIN_SET_NONBLOCKING(mysql)
974 parms.mysql= mysql;
975 },
976 1,
977 r_int,
978 /* Nothing */)
979}
980int STDCALL
981mysql_dump_debug_info_cont(int *ret, MYSQL *mysql, int ready_status)
982{
983MK_ASYNC_CONT_BODY(
984 mysql,
985 1,
986 r_int)
987}
988
989/* Structure used to pass parameters from mysql_refresh_start(). */
990struct mysql_refresh_params {
991 MYSQL *mysql;
992 unsigned int refresh_options;
993};
994static void
995mysql_refresh_start_internal(void *d)
996{
997MK_ASYNC_INTERNAL_BODY(
998 mysql_refresh,
999 (parms->mysql, parms->refresh_options),
1000 parms->mysql,
1001 int,
1002 r_int)
1003}
1004int STDCALL
1005mysql_refresh_start(int *ret, MYSQL *mysql, unsigned int refresh_options)
1006{
1007MK_ASYNC_START_BODY(
1008 mysql_refresh,
1009 mysql,
1010 {
1011 WIN_SET_NONBLOCKING(mysql)
1012 parms.mysql= mysql;
1013 parms.refresh_options= refresh_options;
1014 },
1015 1,
1016 r_int,
1017 /* Nothing */)
1018}
1019int STDCALL
1020mysql_refresh_cont(int *ret, MYSQL *mysql, int ready_status)
1021{
1022MK_ASYNC_CONT_BODY(
1023 mysql,
1024 1,
1025 r_int)
1026}
1027
1028/* Structure used to pass parameters from mysql_kill_start(). */
1029struct mysql_kill_params {
1030 MYSQL *mysql;
1031 unsigned long pid;
1032};
1033static void
1034mysql_kill_start_internal(void *d)
1035{
1036MK_ASYNC_INTERNAL_BODY(
1037 mysql_kill,
1038 (parms->mysql, parms->pid),
1039 parms->mysql,
1040 int,
1041 r_int)
1042}
1043int STDCALL
1044mysql_kill_start(int *ret, MYSQL *mysql, unsigned long pid)
1045{
1046MK_ASYNC_START_BODY(
1047 mysql_kill,
1048 mysql,
1049 {
1050 WIN_SET_NONBLOCKING(mysql)
1051 parms.mysql= mysql;
1052 parms.pid= pid;
1053 },
1054 1,
1055 r_int,
1056 /* Nothing */)
1057}
1058int STDCALL
1059mysql_kill_cont(int *ret, MYSQL *mysql, int ready_status)
1060{
1061MK_ASYNC_CONT_BODY(
1062 mysql,
1063 1,
1064 r_int)
1065}
1066
1067/* Structure used to pass parameters from mysql_set_server_option_start(). */
1068struct mysql_set_server_option_params {
1069 MYSQL *mysql;
1070 enum enum_mysql_set_option option;
1071};
1072static void
1073mysql_set_server_option_start_internal(void *d)
1074{
1075MK_ASYNC_INTERNAL_BODY(
1076 mysql_set_server_option,
1077 (parms->mysql, parms->option),
1078 parms->mysql,
1079 int,
1080 r_int)
1081}
1082int STDCALL
1083mysql_set_server_option_start(int *ret, MYSQL *mysql,
1084 enum enum_mysql_set_option option)
1085{
1086MK_ASYNC_START_BODY(
1087 mysql_set_server_option,
1088 mysql,
1089 {
1090 WIN_SET_NONBLOCKING(mysql)
1091 parms.mysql= mysql;
1092 parms.option= option;
1093 },
1094 1,
1095 r_int,
1096 /* Nothing */)
1097}
1098int STDCALL
1099mysql_set_server_option_cont(int *ret, MYSQL *mysql, int ready_status)
1100{
1101MK_ASYNC_CONT_BODY(
1102 mysql,
1103 1,
1104 r_int)
1105}
1106
1107/* Structure used to pass parameters from mysql_ping_start(). */
1108struct mysql_ping_params {
1109 MYSQL *mysql;
1110};
1111static void
1112mysql_ping_start_internal(void *d)
1113{
1114MK_ASYNC_INTERNAL_BODY(
1115 mysql_ping,
1116 (parms->mysql),
1117 parms->mysql,
1118 int,
1119 r_int)
1120}
1121int STDCALL
1122mysql_ping_start(int *ret, MYSQL *mysql)
1123{
1124MK_ASYNC_START_BODY(
1125 mysql_ping,
1126 mysql,
1127 {
1128 WIN_SET_NONBLOCKING(mysql)
1129 parms.mysql= mysql;
1130 },
1131 1,
1132 r_int,
1133 /* Nothing */)
1134}
1135int STDCALL
1136mysql_ping_cont(int *ret, MYSQL *mysql, int ready_status)
1137{
1138MK_ASYNC_CONT_BODY(
1139 mysql,
1140 1,
1141 r_int)
1142}
1143
1144/* Structure used to pass parameters from mysql_stat_start(). */
1145struct mysql_stat_params {
1146 MYSQL *mysql;
1147};
1148static void
1149mysql_stat_start_internal(void *d)
1150{
1151MK_ASYNC_INTERNAL_BODY(
1152 mysql_stat,
1153 (parms->mysql),
1154 parms->mysql,
1155 const char *,
1156 r_const_ptr)
1157}
1158int STDCALL
1159mysql_stat_start(const char **ret, MYSQL *mysql)
1160{
1161MK_ASYNC_START_BODY(
1162 mysql_stat,
1163 mysql,
1164 {
1165 WIN_SET_NONBLOCKING(mysql)
1166 parms.mysql= mysql;
1167 },
1168 NULL,
1169 r_const_ptr,
1170 /* Nothing */)
1171}
1172int STDCALL
1173mysql_stat_cont(const char **ret, MYSQL *mysql, int ready_status)
1174{
1175MK_ASYNC_CONT_BODY(
1176 mysql,
1177 NULL,
1178 r_const_ptr)
1179}
1180
1181/* Structure used to pass parameters from mysql_list_dbs_start(). */
1182struct mysql_list_dbs_params {
1183 MYSQL *mysql;
1184 const char *wild;
1185};
1186static void
1187mysql_list_dbs_start_internal(void *d)
1188{
1189MK_ASYNC_INTERNAL_BODY(
1190 mysql_list_dbs,
1191 (parms->mysql, parms->wild),
1192 parms->mysql,
1193 MYSQL_RES *,
1194 r_ptr)
1195}
1196int STDCALL
1197mysql_list_dbs_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild)
1198{
1199MK_ASYNC_START_BODY(
1200 mysql_list_dbs,
1201 mysql,
1202 {
1203 WIN_SET_NONBLOCKING(mysql)
1204 parms.mysql= mysql;
1205 parms.wild= wild;
1206 },
1207 NULL,
1208 r_ptr,
1209 /* Nothing */)
1210}
1211int STDCALL
1212mysql_list_dbs_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
1213{
1214MK_ASYNC_CONT_BODY(
1215 mysql,
1216 NULL,
1217 r_ptr)
1218}
1219
1220/* Structure used to pass parameters from mysql_list_tables_start(). */
1221struct mysql_list_tables_params {
1222 MYSQL *mysql;
1223 const char *wild;
1224};
1225static void
1226mysql_list_tables_start_internal(void *d)
1227{
1228MK_ASYNC_INTERNAL_BODY(
1229 mysql_list_tables,
1230 (parms->mysql, parms->wild),
1231 parms->mysql,
1232 MYSQL_RES *,
1233 r_ptr)
1234}
1235int STDCALL
1236mysql_list_tables_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild)
1237{
1238MK_ASYNC_START_BODY(
1239 mysql_list_tables,
1240 mysql,
1241 {
1242 WIN_SET_NONBLOCKING(mysql)
1243 parms.mysql= mysql;
1244 parms.wild= wild;
1245 },
1246 NULL,
1247 r_ptr,
1248 /* Nothing */)
1249}
1250int STDCALL
1251mysql_list_tables_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
1252{
1253MK_ASYNC_CONT_BODY(
1254 mysql,
1255 NULL,
1256 r_ptr)
1257}
1258
1259/* Structure used to pass parameters from mysql_list_processes_start(). */
1260struct mysql_list_processes_params {
1261 MYSQL *mysql;
1262};
1263static void
1264mysql_list_processes_start_internal(void *d)
1265{
1266MK_ASYNC_INTERNAL_BODY(
1267 mysql_list_processes,
1268 (parms->mysql),
1269 parms->mysql,
1270 MYSQL_RES *,
1271 r_ptr)
1272}
1273int STDCALL
1274mysql_list_processes_start(MYSQL_RES **ret, MYSQL *mysql)
1275{
1276MK_ASYNC_START_BODY(
1277 mysql_list_processes,
1278 mysql,
1279 {
1280 WIN_SET_NONBLOCKING(mysql)
1281 parms.mysql= mysql;
1282 },
1283 NULL,
1284 r_ptr,
1285 /* Nothing */)
1286}
1287int STDCALL
1288mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
1289{
1290MK_ASYNC_CONT_BODY(
1291 mysql,
1292 NULL,
1293 r_ptr)
1294}
1295
1296/* Structure used to pass parameters from mysql_list_fields_start(). */
1297struct mysql_list_fields_params {
1298 MYSQL *mysql;
1299 const char *table;
1300 const char *wild;
1301};
1302static void
1303mysql_list_fields_start_internal(void *d)
1304{
1305MK_ASYNC_INTERNAL_BODY(
1306 mysql_list_fields,
1307 (parms->mysql, parms->table, parms->wild),
1308 parms->mysql,
1309 MYSQL_RES *,
1310 r_ptr)
1311}
1312int STDCALL
1313mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql, const char *table,
1314 const char *wild)
1315{
1316MK_ASYNC_START_BODY(
1317 mysql_list_fields,
1318 mysql,
1319 {
1320 WIN_SET_NONBLOCKING(mysql)
1321 parms.mysql= mysql;
1322 parms.table= table;
1323 parms.wild= wild;
1324 },
1325 NULL,
1326 r_ptr,
1327 /* Nothing */)
1328}
1329int STDCALL
1330mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
1331{
1332MK_ASYNC_CONT_BODY(
1333 mysql,
1334 NULL,
1335 r_ptr)
1336}
1337
1338/* Structure used to pass parameters from mysql_read_query_result_start(). */
1339struct mysql_read_query_result_params {
1340 MYSQL *mysql;
1341};
1342static void
1343mysql_read_query_result_start_internal(void *d)
1344{
1345MK_ASYNC_INTERNAL_BODY(
1346 mysql_read_query_result,
1347 (parms->mysql),
1348 parms->mysql,
1349 my_bool,
1350 r_my_bool)
1351}
1352int STDCALL
1353mysql_read_query_result_start(my_bool *ret, MYSQL *mysql)
1354{
1355MK_ASYNC_START_BODY(
1356 mysql_read_query_result,
1357 mysql,
1358 {
1359 WIN_SET_NONBLOCKING(mysql)
1360 parms.mysql= mysql;
1361 },
1362 TRUE,
1363 r_my_bool,
1364 /* Nothing */)
1365}
1366int STDCALL
1367mysql_read_query_result_cont(my_bool *ret, MYSQL *mysql, int ready_status)
1368{
1369MK_ASYNC_CONT_BODY(
1370 mysql,
1371 TRUE,
1372 r_my_bool)
1373}
1374
1375/* Structure used to pass parameters from mysql_stmt_prepare_start(). */
1376struct mysql_stmt_prepare_params {
1377 MYSQL_STMT *stmt;
1378 const char *query;
1379 unsigned long length;
1380};
1381static void
1382mysql_stmt_prepare_start_internal(void *d)
1383{
1384MK_ASYNC_INTERNAL_BODY(
1385 mysql_stmt_prepare,
1386 (parms->stmt, parms->query, parms->length),
1387 parms->stmt->mysql,
1388 int,
1389 r_int)
1390}
1391int STDCALL
1392mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt, const char *query,
1393 unsigned long length)
1394{
1395MK_ASYNC_START_BODY(
1396 mysql_stmt_prepare,
1397 stmt->mysql,
1398 {
1399 WIN_SET_NONBLOCKING(stmt->mysql)
1400 parms.stmt= stmt;
1401 parms.query= query;
1402 parms.length= length;
1403 },
1404 1,
1405 r_int,
1406 /* If stmt->mysql==NULL then we will not block so can call directly. */
1407 if (!stmt->mysql)
1408 {
1409 *ret= mysql_stmt_prepare(stmt, query, length);
1410 return 0;
1411 })
1412}
1413int STDCALL
1414mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1415{
1416MK_ASYNC_CONT_BODY(
1417 stmt->mysql,
1418 1,
1419 r_int)
1420}
1421
1422/* Structure used to pass parameters from mysql_stmt_execute_start(). */
1423struct mysql_stmt_execute_params {
1424 MYSQL_STMT *stmt;
1425};
1426static void
1427mysql_stmt_execute_start_internal(void *d)
1428{
1429MK_ASYNC_INTERNAL_BODY(
1430 mysql_stmt_execute,
1431 (parms->stmt),
1432 parms->stmt->mysql,
1433 int,
1434 r_int)
1435}
1436int STDCALL
1437mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt)
1438{
1439MK_ASYNC_START_BODY(
1440 mysql_stmt_execute,
1441 stmt->mysql,
1442 {
1443 WIN_SET_NONBLOCKING(stmt->mysql)
1444 parms.stmt= stmt;
1445 },
1446 1,
1447 r_int,
1448 /*
1449 If eg. mysql_change_user(), stmt->mysql will be NULL.
1450 In this case, we cannot block.
1451 */
1452 if (!stmt->mysql)
1453 {
1454 *ret= mysql_stmt_execute(stmt);
1455 return 0;
1456 })
1457}
1458int STDCALL
1459mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1460{
1461MK_ASYNC_CONT_BODY(
1462 stmt->mysql,
1463 1,
1464 r_int)
1465}
1466
1467/* Structure used to pass parameters from mysql_stmt_fetch_start(). */
1468struct mysql_stmt_fetch_params {
1469 MYSQL_STMT *stmt;
1470};
1471static void
1472mysql_stmt_fetch_start_internal(void *d)
1473{
1474MK_ASYNC_INTERNAL_BODY(
1475 mysql_stmt_fetch,
1476 (parms->stmt),
1477 parms->stmt->mysql,
1478 int,
1479 r_int)
1480}
1481int STDCALL
1482mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt)
1483{
1484MK_ASYNC_START_BODY(
1485 mysql_stmt_fetch,
1486 stmt->mysql,
1487 {
1488 WIN_SET_NONBLOCKING(stmt->mysql)
1489 parms.stmt= stmt;
1490 },
1491 1,
1492 r_int,
1493 /* If stmt->mysql==NULL then we will not block so can call directly. */
1494 if (!stmt->mysql)
1495 {
1496 *ret= mysql_stmt_fetch(stmt);
1497 return 0;
1498 })
1499}
1500int STDCALL
1501mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1502{
1503MK_ASYNC_CONT_BODY(
1504 stmt->mysql,
1505 1,
1506 r_int)
1507}
1508
1509/* Structure used to pass parameters from mysql_stmt_store_result_start(). */
1510struct mysql_stmt_store_result_params {
1511 MYSQL_STMT *stmt;
1512};
1513static void
1514mysql_stmt_store_result_start_internal(void *d)
1515{
1516MK_ASYNC_INTERNAL_BODY(
1517 mysql_stmt_store_result,
1518 (parms->stmt),
1519 parms->stmt->mysql,
1520 int,
1521 r_int)
1522}
1523int STDCALL
1524mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt)
1525{
1526MK_ASYNC_START_BODY(
1527 mysql_stmt_store_result,
1528 stmt->mysql,
1529 {
1530 WIN_SET_NONBLOCKING(stmt->mysql)
1531 parms.stmt= stmt;
1532 },
1533 1,
1534 r_int,
1535 /* If stmt->mysql==NULL then we will not block so can call directly. */
1536 if (!stmt->mysql)
1537 {
1538 *ret= mysql_stmt_store_result(stmt);
1539 return 0;
1540 })
1541}
1542int STDCALL
1543mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1544{
1545MK_ASYNC_CONT_BODY(
1546 stmt->mysql,
1547 1,
1548 r_int)
1549}
1550
1551/* Structure used to pass parameters from mysql_stmt_close_start(). */
1552struct mysql_stmt_close_params {
1553 MYSQL_STMT *stmt;
1554};
1555static void
1556mysql_stmt_close_start_internal(void *d)
1557{
1558MK_ASYNC_INTERNAL_BODY(
1559 mysql_stmt_close,
1560 (parms->stmt),
1561 parms->stmt->mysql,
1562 my_bool,
1563 r_my_bool)
1564}
1565int STDCALL
1566mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt)
1567{
1568MK_ASYNC_START_BODY(
1569 mysql_stmt_close,
1570 stmt->mysql,
1571 {
1572 WIN_SET_NONBLOCKING(stmt->mysql)
1573 parms.stmt= stmt;
1574 },
1575 TRUE,
1576 r_my_bool,
1577 /* If stmt->mysql==NULL then we will not block so can call directly. */
1578 if (!stmt->mysql)
1579 {
1580 *ret= mysql_stmt_close(stmt);
1581 return 0;
1582 })
1583}
1584int STDCALL
1585mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
1586{
1587MK_ASYNC_CONT_BODY(
1588 stmt->mysql,
1589 TRUE,
1590 r_my_bool)
1591}
1592
1593/* Structure used to pass parameters from mysql_stmt_reset_start(). */
1594struct mysql_stmt_reset_params {
1595 MYSQL_STMT *stmt;
1596};
1597static void
1598mysql_stmt_reset_start_internal(void *d)
1599{
1600MK_ASYNC_INTERNAL_BODY(
1601 mysql_stmt_reset,
1602 (parms->stmt),
1603 parms->stmt->mysql,
1604 my_bool,
1605 r_my_bool)
1606}
1607int STDCALL
1608mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT *stmt)
1609{
1610MK_ASYNC_START_BODY(
1611 mysql_stmt_reset,
1612 stmt->mysql,
1613 {
1614 WIN_SET_NONBLOCKING(stmt->mysql)
1615 parms.stmt= stmt;
1616 },
1617 TRUE,
1618 r_my_bool,
1619 /* If stmt->mysql==NULL then we will not block so can call directly. */
1620 if (!stmt->mysql)
1621 {
1622 *ret= mysql_stmt_reset(stmt);
1623 return 0;
1624 })
1625}
1626int STDCALL
1627mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
1628{
1629MK_ASYNC_CONT_BODY(
1630 stmt->mysql,
1631 TRUE,
1632 r_my_bool)
1633}
1634
1635/* Structure used to pass parameters from mysql_stmt_free_result_start(). */
1636struct mysql_stmt_free_result_params {
1637 MYSQL_STMT *stmt;
1638};
1639static void
1640mysql_stmt_free_result_start_internal(void *d)
1641{
1642MK_ASYNC_INTERNAL_BODY(
1643 mysql_stmt_free_result,
1644 (parms->stmt),
1645 parms->stmt->mysql,
1646 my_bool,
1647 r_my_bool)
1648}
1649int STDCALL
1650mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt)
1651{
1652MK_ASYNC_START_BODY(
1653 mysql_stmt_free_result,
1654 stmt->mysql,
1655 {
1656 WIN_SET_NONBLOCKING(stmt->mysql)
1657 parms.stmt= stmt;
1658 },
1659 TRUE,
1660 r_my_bool,
1661 /* If stmt->mysql==NULL then we will not block so can call directly. */
1662 if (!stmt->mysql)
1663 {
1664 *ret= mysql_stmt_free_result(stmt);
1665 return 0;
1666 })
1667}
1668int STDCALL
1669mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
1670{
1671MK_ASYNC_CONT_BODY(
1672 stmt->mysql,
1673 TRUE,
1674 r_my_bool)
1675}
1676
1677/* Structure used to pass parameters from mysql_stmt_send_long_data_start(). */
1678struct mysql_stmt_send_long_data_params {
1679 MYSQL_STMT *stmt;
1680 unsigned int param_number;
1681 const char *data;
1682 unsigned long length;
1683};
1684static void
1685mysql_stmt_send_long_data_start_internal(void *d)
1686{
1687MK_ASYNC_INTERNAL_BODY(
1688 mysql_stmt_send_long_data,
1689 (parms->stmt, parms->param_number, parms->data, parms->length),
1690 parms->stmt->mysql,
1691 my_bool,
1692 r_my_bool)
1693}
1694int STDCALL
1695mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt,
1696 unsigned int param_number,
1697 const char *data, unsigned long length)
1698{
1699MK_ASYNC_START_BODY(
1700 mysql_stmt_send_long_data,
1701 stmt->mysql,
1702 {
1703 WIN_SET_NONBLOCKING(stmt->mysql)
1704 parms.stmt= stmt;
1705 parms.param_number= param_number;
1706 parms.data= data;
1707 parms.length= length;
1708 },
1709 TRUE,
1710 r_my_bool,
1711 /* If stmt->mysql==NULL then we will not block so can call directly. */
1712 if (!stmt->mysql)
1713 {
1714 *ret= mysql_stmt_send_long_data(stmt, param_number, data, length);
1715 return 0;
1716 })
1717}
1718int STDCALL
1719mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
1720{
1721MK_ASYNC_CONT_BODY(
1722 stmt->mysql,
1723 TRUE,
1724 r_my_bool)
1725}
1726
1727/* Structure used to pass parameters from mysql_commit_start(). */
1728struct mysql_commit_params {
1729 MYSQL *mysql;
1730};
1731static void
1732mysql_commit_start_internal(void *d)
1733{
1734MK_ASYNC_INTERNAL_BODY(
1735 mysql_commit,
1736 (parms->mysql),
1737 parms->mysql,
1738 my_bool,
1739 r_my_bool)
1740}
1741int STDCALL
1742mysql_commit_start(my_bool *ret, MYSQL *mysql)
1743{
1744MK_ASYNC_START_BODY(
1745 mysql_commit,
1746 mysql,
1747 {
1748 WIN_SET_NONBLOCKING(mysql)
1749 parms.mysql= mysql;
1750 },
1751 TRUE,
1752 r_my_bool,
1753 /* Nothing */)
1754}
1755int STDCALL
1756mysql_commit_cont(my_bool *ret, MYSQL *mysql, int ready_status)
1757{
1758MK_ASYNC_CONT_BODY(
1759 mysql,
1760 TRUE,
1761 r_my_bool)
1762}
1763
1764/* Structure used to pass parameters from mysql_rollback_start(). */
1765struct mysql_rollback_params {
1766 MYSQL *mysql;
1767};
1768static void
1769mysql_rollback_start_internal(void *d)
1770{
1771MK_ASYNC_INTERNAL_BODY(
1772 mysql_rollback,
1773 (parms->mysql),
1774 parms->mysql,
1775 my_bool,
1776 r_my_bool)
1777}
1778int STDCALL
1779mysql_rollback_start(my_bool *ret, MYSQL *mysql)
1780{
1781MK_ASYNC_START_BODY(
1782 mysql_rollback,
1783 mysql,
1784 {
1785 WIN_SET_NONBLOCKING(mysql)
1786 parms.mysql= mysql;
1787 },
1788 TRUE,
1789 r_my_bool,
1790 /* Nothing */)
1791}
1792int STDCALL
1793mysql_rollback_cont(my_bool *ret, MYSQL *mysql, int ready_status)
1794{
1795MK_ASYNC_CONT_BODY(
1796 mysql,
1797 TRUE,
1798 r_my_bool)
1799}
1800
1801/* Structure used to pass parameters from mysql_autocommit_start(). */
1802struct mysql_autocommit_params {
1803 MYSQL *mysql;
1804 my_bool auto_mode;
1805};
1806static void
1807mysql_autocommit_start_internal(void *d)
1808{
1809MK_ASYNC_INTERNAL_BODY(
1810 mysql_autocommit,
1811 (parms->mysql, parms->auto_mode),
1812 parms->mysql,
1813 my_bool,
1814 r_my_bool)
1815}
1816int STDCALL
1817mysql_autocommit_start(my_bool *ret, MYSQL *mysql, my_bool auto_mode)
1818{
1819MK_ASYNC_START_BODY(
1820 mysql_autocommit,
1821 mysql,
1822 {
1823 WIN_SET_NONBLOCKING(mysql)
1824 parms.mysql= mysql;
1825 parms.auto_mode= auto_mode;
1826 },
1827 TRUE,
1828 r_my_bool,
1829 /* Nothing */)
1830}
1831int STDCALL
1832mysql_autocommit_cont(my_bool *ret, MYSQL *mysql, int ready_status)
1833{
1834MK_ASYNC_CONT_BODY(
1835 mysql,
1836 TRUE,
1837 r_my_bool)
1838}
1839
1840/* Structure used to pass parameters from mysql_next_result_start(). */
1841struct mysql_next_result_params {
1842 MYSQL *mysql;
1843};
1844static void
1845mysql_next_result_start_internal(void *d)
1846{
1847MK_ASYNC_INTERNAL_BODY(
1848 mysql_next_result,
1849 (parms->mysql),
1850 parms->mysql,
1851 int,
1852 r_int)
1853}
1854int STDCALL
1855mysql_next_result_start(int *ret, MYSQL *mysql)
1856{
1857MK_ASYNC_START_BODY(
1858 mysql_next_result,
1859 mysql,
1860 {
1861 WIN_SET_NONBLOCKING(mysql)
1862 parms.mysql= mysql;
1863 },
1864 1,
1865 r_int,
1866 /* Nothing */)
1867}
1868int STDCALL
1869mysql_next_result_cont(int *ret, MYSQL *mysql, int ready_status)
1870{
1871MK_ASYNC_CONT_BODY(
1872 mysql,
1873 1,
1874 r_int)
1875}
1876
1877/* Structure used to pass parameters from mysql_stmt_next_result_start(). */
1878struct mysql_stmt_next_result_params {
1879 MYSQL_STMT *stmt;
1880};
1881static void
1882mysql_stmt_next_result_start_internal(void *d)
1883{
1884MK_ASYNC_INTERNAL_BODY(
1885 mysql_stmt_next_result,
1886 (parms->stmt),
1887 parms->stmt->mysql,
1888 int,
1889 r_int)
1890}
1891int STDCALL
1892mysql_stmt_next_result_start(int *ret, MYSQL_STMT *stmt)
1893{
1894MK_ASYNC_START_BODY(
1895 mysql_stmt_next_result,
1896 stmt->mysql,
1897 {
1898 WIN_SET_NONBLOCKING(stmt->mysql)
1899 parms.stmt= stmt;
1900 },
1901 1,
1902 r_int,
1903 /* Nothing */)
1904}
1905int STDCALL
1906mysql_stmt_next_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1907{
1908MK_ASYNC_CONT_BODY(
1909 stmt->mysql,
1910 1,
1911 r_int)
1912}
1913#endif
1914
1915
1916/*
1917 The following functions are deprecated, and so have no non-blocking version:
1918
1919 mysql_connect
1920 mysql_create_db
1921 mysql_drop_db
1922*/
1923
1924/*
1925 The following functions can newer block, and so do not have special
1926 non-blocking versions:
1927
1928 mysql_num_rows()
1929 mysql_num_fields()
1930 mysql_eof()
1931 mysql_fetch_field_direct()
1932 mysql_fetch_fields()
1933 mysql_row_tell()
1934 mysql_field_tell()
1935 mysql_field_count()
1936 mysql_affected_rows()
1937 mysql_insert_id()
1938 mysql_errno()
1939 mysql_error()
1940 mysql_sqlstate()
1941 mysql_warning_count()
1942 mysql_info()
1943 mysql_thread_id()
1944 mysql_character_set_name()
1945 mysql_init()
1946 mysql_ssl_set()
1947 mysql_get_ssl_cipher()
1948 mysql_use_result()
1949 mysql_get_character_set_info()
1950 mysql_set_local_infile_handler()
1951 mysql_set_local_infile_default()
1952 mysql_get_server_info()
1953 mysql_get_server_name()
1954 mysql_get_client_info()
1955 mysql_get_client_version()
1956 mysql_get_host_info()
1957 mysql_get_server_version()
1958 mysql_get_proto_info()
1959 mysql_options()
1960 mysql_data_seek()
1961 mysql_row_seek()
1962 mysql_field_seek()
1963 mysql_fetch_lengths()
1964 mysql_fetch_field()
1965 mysql_escape_string()
1966 mysql_hex_string()
1967 mysql_real_escape_string()
1968 mysql_debug()
1969 myodbc_remove_escape()
1970 mysql_thread_safe()
1971 mysql_embedded()
1972 mariadb_connection()
1973 mysql_stmt_init()
1974 mysql_stmt_fetch_column()
1975 mysql_stmt_param_count()
1976 mysql_stmt_attr_set()
1977 mysql_stmt_attr_get()
1978 mysql_stmt_bind_param()
1979 mysql_stmt_bind_result()
1980 mysql_stmt_result_metadata()
1981 mysql_stmt_param_metadata()
1982 mysql_stmt_errno()
1983 mysql_stmt_error()
1984 mysql_stmt_sqlstate()
1985 mysql_stmt_row_seek()
1986 mysql_stmt_row_tell()
1987 mysql_stmt_data_seek()
1988 mysql_stmt_num_rows()
1989 mysql_stmt_affected_rows()
1990 mysql_stmt_insert_id()
1991 mysql_stmt_field_count()
1992 mysql_more_results()
1993 mysql_get_socket()
1994 mysql_get_timeout_value()
1995*/
1996