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