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
46 void
my_context_install_suspend_resume_hook(struct mysql_async_context * b,void (* hook)(my_bool,void *),void * user_data)47 my_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. */
57 int
my_connect_async(struct mysql_async_context * b,my_socket fd,const struct sockaddr * name,uint namelen,int vio_timeout)58 my_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
130 ssize_t
my_recv_async(struct mysql_async_context * b,my_socket fd,unsigned char * buf,size_t size,int timeout)131 my_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
158 ssize_t
my_send_async(struct mysql_async_context * b,my_socket fd,const unsigned char * buf,size_t size,int timeout)159 my_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
186 my_bool
my_io_wait_async(struct mysql_async_context * b,enum enum_vio_io_event event,int timeout)187 my_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
218 static my_bool
my_ssl_async_check_result(int res,struct mysql_async_context * b,SSL * ssl)219 my_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
240 int
my_ssl_read_async(struct mysql_async_context * b,SSL * ssl,void * buf,int size)241 my_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
254 int
my_ssl_write_async(struct mysql_async_context * b,SSL * ssl,const void * buf,int size)255 my_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 */
274 unsigned int STDCALL
mysql_get_timeout_value(const MYSQL * mysql)275 mysql_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
286 unsigned int STDCALL
mysql_get_timeout_value_ms(const MYSQL * mysql)287 mysql_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(). */
420 struct 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 };
430 static void
mysql_real_connect_start_internal(void * d)431 mysql_real_connect_start_internal(void *d)
432 {
433 MK_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 }
441 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)442 mysql_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 {
447 MK_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 }
468 int STDCALL
mysql_real_connect_cont(MYSQL ** ret,MYSQL * mysql,int ready_status)469 mysql_real_connect_cont(MYSQL **ret, MYSQL *mysql, int ready_status)
470 {
471 MK_ASYNC_CONT_BODY(
472 mysql,
473 NULL,
474 r_ptr)
475 }
476
477 /* Structure used to pass parameters from mysql_real_query_start(). */
478 struct mysql_real_query_params {
479 MYSQL *mysql;
480 const char *stmt_str;
481 unsigned long length;
482 };
483 static void
mysql_real_query_start_internal(void * d)484 mysql_real_query_start_internal(void *d)
485 {
486 MK_ASYNC_INTERNAL_BODY(
487 mysql_real_query,
488 (parms->mysql, parms->stmt_str, parms->length),
489 parms->mysql,
490 int,
491 r_int)
492 }
493 int STDCALL
mysql_real_query_start(int * ret,MYSQL * mysql,const char * stmt_str,unsigned long length)494 mysql_real_query_start(int *ret, MYSQL *mysql, const char *stmt_str, unsigned long length)
495 {
496 MK_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 }
509 int STDCALL
mysql_real_query_cont(int * ret,MYSQL * mysql,int ready_status)510 mysql_real_query_cont(int *ret, MYSQL *mysql, int ready_status)
511 {
512 MK_ASYNC_CONT_BODY(
513 mysql,
514 1,
515 r_int)
516 }
517
518 /* Structure used to pass parameters from mysql_fetch_row_start(). */
519 struct mysql_fetch_row_params {
520 MYSQL_RES *result;
521 };
522 static void
mysql_fetch_row_start_internal(void * d)523 mysql_fetch_row_start_internal(void *d)
524 {
525 MK_ASYNC_INTERNAL_BODY(
526 mysql_fetch_row,
527 (parms->result),
528 parms->result->handle,
529 MYSQL_ROW,
530 r_ptr)
531 }
532 int STDCALL
mysql_fetch_row_start(MYSQL_ROW * ret,MYSQL_RES * result)533 mysql_fetch_row_start(MYSQL_ROW *ret, MYSQL_RES *result)
534 {
535 MK_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 }
556 int STDCALL
mysql_fetch_row_cont(MYSQL_ROW * ret,MYSQL_RES * result,int ready_status)557 mysql_fetch_row_cont(MYSQL_ROW *ret, MYSQL_RES *result, int ready_status)
558 {
559 MK_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(). */
566 struct mysql_set_character_set_params {
567 MYSQL *mysql;
568 const char *csname;
569 };
570 static void
mysql_set_character_set_start_internal(void * d)571 mysql_set_character_set_start_internal(void *d)
572 {
573 MK_ASYNC_INTERNAL_BODY(
574 mysql_set_character_set,
575 (parms->mysql, parms->csname),
576 parms->mysql,
577 int,
578 r_int)
579 }
580 int STDCALL
mysql_set_character_set_start(int * ret,MYSQL * mysql,const char * csname)581 mysql_set_character_set_start(int *ret, MYSQL *mysql, const char *csname)
582 {
583 MK_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 }
595 int STDCALL
mysql_set_character_set_cont(int * ret,MYSQL * mysql,int ready_status)596 mysql_set_character_set_cont(int *ret, MYSQL *mysql, int ready_status)
597 {
598 MK_ASYNC_CONT_BODY(
599 mysql,
600 1,
601 r_int)
602 }
603
604 /* Structure used to pass parameters from mysql_sekect_db_start(). */
605 struct mysql_select_db_params {
606 MYSQL *mysql;
607 const char *db;
608 };
609 static void
mysql_select_db_start_internal(void * d)610 mysql_select_db_start_internal(void *d)
611 {
612 MK_ASYNC_INTERNAL_BODY(
613 mysql_select_db,
614 (parms->mysql, parms->db),
615 parms->mysql,
616 int,
617 r_int)
618 }
619 int STDCALL
mysql_select_db_start(int * ret,MYSQL * mysql,const char * db)620 mysql_select_db_start(int *ret, MYSQL *mysql, const char *db)
621 {
622 MK_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 }
634 int STDCALL
mysql_select_db_cont(int * ret,MYSQL * mysql,int ready_status)635 mysql_select_db_cont(int *ret, MYSQL *mysql, int ready_status)
636 {
637 MK_ASYNC_CONT_BODY(
638 mysql,
639 1,
640 r_int)
641 }
642
643 /* Structure used to pass parameters from mysql_send_query_start(). */
644 struct mysql_send_query_params {
645 MYSQL *mysql;
646 const char *q;
647 unsigned long length;
648 };
649 static void
mysql_send_query_start_internal(void * d)650 mysql_send_query_start_internal(void *d)
651 {
652 MK_ASYNC_INTERNAL_BODY(
653 mysql_send_query,
654 (parms->mysql, parms->q, parms->length),
655 parms->mysql,
656 int,
657 r_int)
658 }
659 int STDCALL
mysql_send_query_start(int * ret,MYSQL * mysql,const char * q,unsigned long length)660 mysql_send_query_start(int *ret, MYSQL *mysql, const char *q, unsigned long length)
661 {
662 MK_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 }
675 int STDCALL
mysql_send_query_cont(int * ret,MYSQL * mysql,int ready_status)676 mysql_send_query_cont(int *ret, MYSQL *mysql, int ready_status)
677 {
678 MK_ASYNC_CONT_BODY(
679 mysql,
680 1,
681 r_int)
682 }
683
684 /* Structure used to pass parameters from mysql_store_result_start(). */
685 struct mysql_store_result_params {
686 MYSQL *mysql;
687 };
688 static void
mysql_store_result_start_internal(void * d)689 mysql_store_result_start_internal(void *d)
690 {
691 MK_ASYNC_INTERNAL_BODY(
692 mysql_store_result,
693 (parms->mysql),
694 parms->mysql,
695 MYSQL_RES *,
696 r_ptr)
697 }
698 int STDCALL
mysql_store_result_start(MYSQL_RES ** ret,MYSQL * mysql)699 mysql_store_result_start(MYSQL_RES **ret, MYSQL *mysql)
700 {
701 MK_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 }
712 int STDCALL
mysql_store_result_cont(MYSQL_RES ** ret,MYSQL * mysql,int ready_status)713 mysql_store_result_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
714 {
715 MK_ASYNC_CONT_BODY(
716 mysql,
717 NULL,
718 r_ptr)
719 }
720
721 /* Structure used to pass parameters from mysql_free_result_start(). */
722 struct mysql_free_result_params {
723 MYSQL_RES *result;
724 };
725 static void
mysql_free_result_start_internal(void * d)726 mysql_free_result_start_internal(void *d)
727 {
728 MK_ASYNC_INTERNAL_BODY_VOID_RETURN(
729 mysql_free_result,
730 (parms->result),
731 parms->result->handle)
732 }
733 int STDCALL
mysql_free_result_start(MYSQL_RES * result)734 mysql_free_result_start(MYSQL_RES *result)
735 {
736 MK_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 }
756 int STDCALL
mysql_free_result_cont(MYSQL_RES * result,int ready_status)757 mysql_free_result_cont(MYSQL_RES *result, int ready_status)
758 {
759 MK_ASYNC_CONT_BODY_VOID_RETURN(result->handle)
760 }
761
762 /* Structure used to pass parameters from mysql_close_slow_part_start(). */
763 struct 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 */
773 static void
mysql_close_slow_part_start_internal(void * d)774 mysql_close_slow_part_start_internal(void *d)
775 {
776 MK_ASYNC_INTERNAL_BODY_VOID_RETURN(
777 mysql_close_slow_part,
778 (parms->sock),
779 parms->sock)
780 }
781 int STDCALL
mysql_close_slow_part_start(MYSQL * sock)782 mysql_close_slow_part_start(MYSQL *sock)
783 {
784 MK_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 }
793 int STDCALL
mysql_close_slow_part_cont(MYSQL * sock,int ready_status)794 mysql_close_slow_part_cont(MYSQL *sock, int ready_status)
795 {
796 MK_ASYNC_CONT_BODY_VOID_RETURN(sock)
797 }
798 int STDCALL
mysql_close_start(MYSQL * sock)799 mysql_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 }
814 int STDCALL
mysql_close_cont(MYSQL * sock,int ready_status)815 mysql_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(). */
832 struct mysql_change_user_params {
833 MYSQL *mysql;
834 const char *user;
835 const char *passwd;
836 const char *db;
837 };
838 static void
mysql_change_user_start_internal(void * d)839 mysql_change_user_start_internal(void *d)
840 {
841 MK_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 }
848 int STDCALL
mysql_change_user_start(my_bool * ret,MYSQL * mysql,const char * user,const char * passwd,const char * db)849 mysql_change_user_start(my_bool *ret, MYSQL *mysql, const char *user, const char *passwd, const char *db)
850 {
851 MK_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 }
865 int STDCALL
mysql_change_user_cont(my_bool * ret,MYSQL * mysql,int ready_status)866 mysql_change_user_cont(my_bool *ret, MYSQL *mysql, int ready_status)
867 {
868 MK_ASYNC_CONT_BODY(
869 mysql,
870 TRUE,
871 r_my_bool)
872 }
873
874 /* Structure used to pass parameters from mysql_query_start(). */
875 struct mysql_query_params {
876 MYSQL *mysql;
877 const char *q;
878 };
879 static void
mysql_query_start_internal(void * d)880 mysql_query_start_internal(void *d)
881 {
882 MK_ASYNC_INTERNAL_BODY(
883 mysql_query,
884 (parms->mysql, parms->q),
885 parms->mysql,
886 int,
887 r_int)
888 }
889 int STDCALL
mysql_query_start(int * ret,MYSQL * mysql,const char * q)890 mysql_query_start(int *ret, MYSQL *mysql, const char *q)
891 {
892 MK_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 }
904 int STDCALL
mysql_query_cont(int * ret,MYSQL * mysql,int ready_status)905 mysql_query_cont(int *ret, MYSQL *mysql, int ready_status)
906 {
907 MK_ASYNC_CONT_BODY(
908 mysql,
909 1,
910 r_int)
911 }
912
913 /* Structure used to pass parameters from mysql_shutdown_start(). */
914 struct mysql_shutdown_params {
915 MYSQL *mysql;
916 enum mysql_enum_shutdown_level shutdown_level;
917 };
918 static void
mysql_shutdown_start_internal(void * d)919 mysql_shutdown_start_internal(void *d)
920 {
921 MK_ASYNC_INTERNAL_BODY(
922 mysql_shutdown,
923 (parms->mysql, parms->shutdown_level),
924 parms->mysql,
925 int,
926 r_int)
927 }
928 int STDCALL
mysql_shutdown_start(int * ret,MYSQL * mysql,enum mysql_enum_shutdown_level shutdown_level)929 mysql_shutdown_start(int *ret, MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
930 {
931 MK_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 }
943 int STDCALL
mysql_shutdown_cont(int * ret,MYSQL * mysql,int ready_status)944 mysql_shutdown_cont(int *ret, MYSQL *mysql, int ready_status)
945 {
946 MK_ASYNC_CONT_BODY(
947 mysql,
948 1,
949 r_int)
950 }
951
952 /* Structure used to pass parameters from mysql_dump_debug_info_start(). */
953 struct mysql_dump_debug_info_params {
954 MYSQL *mysql;
955 };
956 static void
mysql_dump_debug_info_start_internal(void * d)957 mysql_dump_debug_info_start_internal(void *d)
958 {
959 MK_ASYNC_INTERNAL_BODY(
960 mysql_dump_debug_info,
961 (parms->mysql),
962 parms->mysql,
963 int,
964 r_int)
965 }
966 int STDCALL
mysql_dump_debug_info_start(int * ret,MYSQL * mysql)967 mysql_dump_debug_info_start(int *ret, MYSQL *mysql)
968 {
969 MK_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 }
980 int STDCALL
mysql_dump_debug_info_cont(int * ret,MYSQL * mysql,int ready_status)981 mysql_dump_debug_info_cont(int *ret, MYSQL *mysql, int ready_status)
982 {
983 MK_ASYNC_CONT_BODY(
984 mysql,
985 1,
986 r_int)
987 }
988
989 /* Structure used to pass parameters from mysql_refresh_start(). */
990 struct mysql_refresh_params {
991 MYSQL *mysql;
992 unsigned int refresh_options;
993 };
994 static void
mysql_refresh_start_internal(void * d)995 mysql_refresh_start_internal(void *d)
996 {
997 MK_ASYNC_INTERNAL_BODY(
998 mysql_refresh,
999 (parms->mysql, parms->refresh_options),
1000 parms->mysql,
1001 int,
1002 r_int)
1003 }
1004 int STDCALL
mysql_refresh_start(int * ret,MYSQL * mysql,unsigned int refresh_options)1005 mysql_refresh_start(int *ret, MYSQL *mysql, unsigned int refresh_options)
1006 {
1007 MK_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 }
1019 int STDCALL
mysql_refresh_cont(int * ret,MYSQL * mysql,int ready_status)1020 mysql_refresh_cont(int *ret, MYSQL *mysql, int ready_status)
1021 {
1022 MK_ASYNC_CONT_BODY(
1023 mysql,
1024 1,
1025 r_int)
1026 }
1027
1028 /* Structure used to pass parameters from mysql_kill_start(). */
1029 struct mysql_kill_params {
1030 MYSQL *mysql;
1031 unsigned long pid;
1032 };
1033 static void
mysql_kill_start_internal(void * d)1034 mysql_kill_start_internal(void *d)
1035 {
1036 MK_ASYNC_INTERNAL_BODY(
1037 mysql_kill,
1038 (parms->mysql, parms->pid),
1039 parms->mysql,
1040 int,
1041 r_int)
1042 }
1043 int STDCALL
mysql_kill_start(int * ret,MYSQL * mysql,unsigned long pid)1044 mysql_kill_start(int *ret, MYSQL *mysql, unsigned long pid)
1045 {
1046 MK_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 }
1058 int STDCALL
mysql_kill_cont(int * ret,MYSQL * mysql,int ready_status)1059 mysql_kill_cont(int *ret, MYSQL *mysql, int ready_status)
1060 {
1061 MK_ASYNC_CONT_BODY(
1062 mysql,
1063 1,
1064 r_int)
1065 }
1066
1067 /* Structure used to pass parameters from mysql_set_server_option_start(). */
1068 struct mysql_set_server_option_params {
1069 MYSQL *mysql;
1070 enum enum_mysql_set_option option;
1071 };
1072 static void
mysql_set_server_option_start_internal(void * d)1073 mysql_set_server_option_start_internal(void *d)
1074 {
1075 MK_ASYNC_INTERNAL_BODY(
1076 mysql_set_server_option,
1077 (parms->mysql, parms->option),
1078 parms->mysql,
1079 int,
1080 r_int)
1081 }
1082 int STDCALL
mysql_set_server_option_start(int * ret,MYSQL * mysql,enum enum_mysql_set_option option)1083 mysql_set_server_option_start(int *ret, MYSQL *mysql,
1084 enum enum_mysql_set_option option)
1085 {
1086 MK_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 }
1098 int STDCALL
mysql_set_server_option_cont(int * ret,MYSQL * mysql,int ready_status)1099 mysql_set_server_option_cont(int *ret, MYSQL *mysql, int ready_status)
1100 {
1101 MK_ASYNC_CONT_BODY(
1102 mysql,
1103 1,
1104 r_int)
1105 }
1106
1107 /* Structure used to pass parameters from mysql_ping_start(). */
1108 struct mysql_ping_params {
1109 MYSQL *mysql;
1110 };
1111 static void
mysql_ping_start_internal(void * d)1112 mysql_ping_start_internal(void *d)
1113 {
1114 MK_ASYNC_INTERNAL_BODY(
1115 mysql_ping,
1116 (parms->mysql),
1117 parms->mysql,
1118 int,
1119 r_int)
1120 }
1121 int STDCALL
mysql_ping_start(int * ret,MYSQL * mysql)1122 mysql_ping_start(int *ret, MYSQL *mysql)
1123 {
1124 MK_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 }
1135 int STDCALL
mysql_ping_cont(int * ret,MYSQL * mysql,int ready_status)1136 mysql_ping_cont(int *ret, MYSQL *mysql, int ready_status)
1137 {
1138 MK_ASYNC_CONT_BODY(
1139 mysql,
1140 1,
1141 r_int)
1142 }
1143
1144 /* Structure used to pass parameters from mysql_stat_start(). */
1145 struct mysql_stat_params {
1146 MYSQL *mysql;
1147 };
1148 static void
mysql_stat_start_internal(void * d)1149 mysql_stat_start_internal(void *d)
1150 {
1151 MK_ASYNC_INTERNAL_BODY(
1152 mysql_stat,
1153 (parms->mysql),
1154 parms->mysql,
1155 const char *,
1156 r_const_ptr)
1157 }
1158 int STDCALL
mysql_stat_start(const char ** ret,MYSQL * mysql)1159 mysql_stat_start(const char **ret, MYSQL *mysql)
1160 {
1161 MK_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 }
1172 int STDCALL
mysql_stat_cont(const char ** ret,MYSQL * mysql,int ready_status)1173 mysql_stat_cont(const char **ret, MYSQL *mysql, int ready_status)
1174 {
1175 MK_ASYNC_CONT_BODY(
1176 mysql,
1177 NULL,
1178 r_const_ptr)
1179 }
1180
1181 /* Structure used to pass parameters from mysql_list_dbs_start(). */
1182 struct mysql_list_dbs_params {
1183 MYSQL *mysql;
1184 const char *wild;
1185 };
1186 static void
mysql_list_dbs_start_internal(void * d)1187 mysql_list_dbs_start_internal(void *d)
1188 {
1189 MK_ASYNC_INTERNAL_BODY(
1190 mysql_list_dbs,
1191 (parms->mysql, parms->wild),
1192 parms->mysql,
1193 MYSQL_RES *,
1194 r_ptr)
1195 }
1196 int STDCALL
mysql_list_dbs_start(MYSQL_RES ** ret,MYSQL * mysql,const char * wild)1197 mysql_list_dbs_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild)
1198 {
1199 MK_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 }
1211 int STDCALL
mysql_list_dbs_cont(MYSQL_RES ** ret,MYSQL * mysql,int ready_status)1212 mysql_list_dbs_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
1213 {
1214 MK_ASYNC_CONT_BODY(
1215 mysql,
1216 NULL,
1217 r_ptr)
1218 }
1219
1220 /* Structure used to pass parameters from mysql_list_tables_start(). */
1221 struct mysql_list_tables_params {
1222 MYSQL *mysql;
1223 const char *wild;
1224 };
1225 static void
mysql_list_tables_start_internal(void * d)1226 mysql_list_tables_start_internal(void *d)
1227 {
1228 MK_ASYNC_INTERNAL_BODY(
1229 mysql_list_tables,
1230 (parms->mysql, parms->wild),
1231 parms->mysql,
1232 MYSQL_RES *,
1233 r_ptr)
1234 }
1235 int STDCALL
mysql_list_tables_start(MYSQL_RES ** ret,MYSQL * mysql,const char * wild)1236 mysql_list_tables_start(MYSQL_RES **ret, MYSQL *mysql, const char *wild)
1237 {
1238 MK_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 }
1250 int STDCALL
mysql_list_tables_cont(MYSQL_RES ** ret,MYSQL * mysql,int ready_status)1251 mysql_list_tables_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
1252 {
1253 MK_ASYNC_CONT_BODY(
1254 mysql,
1255 NULL,
1256 r_ptr)
1257 }
1258
1259 /* Structure used to pass parameters from mysql_list_processes_start(). */
1260 struct mysql_list_processes_params {
1261 MYSQL *mysql;
1262 };
1263 static void
mysql_list_processes_start_internal(void * d)1264 mysql_list_processes_start_internal(void *d)
1265 {
1266 MK_ASYNC_INTERNAL_BODY(
1267 mysql_list_processes,
1268 (parms->mysql),
1269 parms->mysql,
1270 MYSQL_RES *,
1271 r_ptr)
1272 }
1273 int STDCALL
mysql_list_processes_start(MYSQL_RES ** ret,MYSQL * mysql)1274 mysql_list_processes_start(MYSQL_RES **ret, MYSQL *mysql)
1275 {
1276 MK_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 }
1287 int STDCALL
mysql_list_processes_cont(MYSQL_RES ** ret,MYSQL * mysql,int ready_status)1288 mysql_list_processes_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
1289 {
1290 MK_ASYNC_CONT_BODY(
1291 mysql,
1292 NULL,
1293 r_ptr)
1294 }
1295
1296 /* Structure used to pass parameters from mysql_list_fields_start(). */
1297 struct mysql_list_fields_params {
1298 MYSQL *mysql;
1299 const char *table;
1300 const char *wild;
1301 };
1302 static void
mysql_list_fields_start_internal(void * d)1303 mysql_list_fields_start_internal(void *d)
1304 {
1305 MK_ASYNC_INTERNAL_BODY(
1306 mysql_list_fields,
1307 (parms->mysql, parms->table, parms->wild),
1308 parms->mysql,
1309 MYSQL_RES *,
1310 r_ptr)
1311 }
1312 int STDCALL
mysql_list_fields_start(MYSQL_RES ** ret,MYSQL * mysql,const char * table,const char * wild)1313 mysql_list_fields_start(MYSQL_RES **ret, MYSQL *mysql, const char *table,
1314 const char *wild)
1315 {
1316 MK_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 }
1329 int STDCALL
mysql_list_fields_cont(MYSQL_RES ** ret,MYSQL * mysql,int ready_status)1330 mysql_list_fields_cont(MYSQL_RES **ret, MYSQL *mysql, int ready_status)
1331 {
1332 MK_ASYNC_CONT_BODY(
1333 mysql,
1334 NULL,
1335 r_ptr)
1336 }
1337
1338 /* Structure used to pass parameters from mysql_read_query_result_start(). */
1339 struct mysql_read_query_result_params {
1340 MYSQL *mysql;
1341 };
1342 static void
mysql_read_query_result_start_internal(void * d)1343 mysql_read_query_result_start_internal(void *d)
1344 {
1345 MK_ASYNC_INTERNAL_BODY(
1346 mysql_read_query_result,
1347 (parms->mysql),
1348 parms->mysql,
1349 my_bool,
1350 r_my_bool)
1351 }
1352 int STDCALL
mysql_read_query_result_start(my_bool * ret,MYSQL * mysql)1353 mysql_read_query_result_start(my_bool *ret, MYSQL *mysql)
1354 {
1355 MK_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 }
1366 int STDCALL
mysql_read_query_result_cont(my_bool * ret,MYSQL * mysql,int ready_status)1367 mysql_read_query_result_cont(my_bool *ret, MYSQL *mysql, int ready_status)
1368 {
1369 MK_ASYNC_CONT_BODY(
1370 mysql,
1371 TRUE,
1372 r_my_bool)
1373 }
1374
1375 /* Structure used to pass parameters from mysql_stmt_prepare_start(). */
1376 struct mysql_stmt_prepare_params {
1377 MYSQL_STMT *stmt;
1378 const char *query;
1379 unsigned long length;
1380 };
1381 static void
mysql_stmt_prepare_start_internal(void * d)1382 mysql_stmt_prepare_start_internal(void *d)
1383 {
1384 MK_ASYNC_INTERNAL_BODY(
1385 mysql_stmt_prepare,
1386 (parms->stmt, parms->query, parms->length),
1387 parms->stmt->mysql,
1388 int,
1389 r_int)
1390 }
1391 int STDCALL
mysql_stmt_prepare_start(int * ret,MYSQL_STMT * stmt,const char * query,unsigned long length)1392 mysql_stmt_prepare_start(int *ret, MYSQL_STMT *stmt, const char *query,
1393 unsigned long length)
1394 {
1395 MK_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 }
1413 int STDCALL
mysql_stmt_prepare_cont(int * ret,MYSQL_STMT * stmt,int ready_status)1414 mysql_stmt_prepare_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1415 {
1416 MK_ASYNC_CONT_BODY(
1417 stmt->mysql,
1418 1,
1419 r_int)
1420 }
1421
1422 /* Structure used to pass parameters from mysql_stmt_execute_start(). */
1423 struct mysql_stmt_execute_params {
1424 MYSQL_STMT *stmt;
1425 };
1426 static void
mysql_stmt_execute_start_internal(void * d)1427 mysql_stmt_execute_start_internal(void *d)
1428 {
1429 MK_ASYNC_INTERNAL_BODY(
1430 mysql_stmt_execute,
1431 (parms->stmt),
1432 parms->stmt->mysql,
1433 int,
1434 r_int)
1435 }
1436 int STDCALL
mysql_stmt_execute_start(int * ret,MYSQL_STMT * stmt)1437 mysql_stmt_execute_start(int *ret, MYSQL_STMT *stmt)
1438 {
1439 MK_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 }
1458 int STDCALL
mysql_stmt_execute_cont(int * ret,MYSQL_STMT * stmt,int ready_status)1459 mysql_stmt_execute_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1460 {
1461 MK_ASYNC_CONT_BODY(
1462 stmt->mysql,
1463 1,
1464 r_int)
1465 }
1466
1467 /* Structure used to pass parameters from mysql_stmt_fetch_start(). */
1468 struct mysql_stmt_fetch_params {
1469 MYSQL_STMT *stmt;
1470 };
1471 static void
mysql_stmt_fetch_start_internal(void * d)1472 mysql_stmt_fetch_start_internal(void *d)
1473 {
1474 MK_ASYNC_INTERNAL_BODY(
1475 mysql_stmt_fetch,
1476 (parms->stmt),
1477 parms->stmt->mysql,
1478 int,
1479 r_int)
1480 }
1481 int STDCALL
mysql_stmt_fetch_start(int * ret,MYSQL_STMT * stmt)1482 mysql_stmt_fetch_start(int *ret, MYSQL_STMT *stmt)
1483 {
1484 MK_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 }
1500 int STDCALL
mysql_stmt_fetch_cont(int * ret,MYSQL_STMT * stmt,int ready_status)1501 mysql_stmt_fetch_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1502 {
1503 MK_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(). */
1510 struct mysql_stmt_store_result_params {
1511 MYSQL_STMT *stmt;
1512 };
1513 static void
mysql_stmt_store_result_start_internal(void * d)1514 mysql_stmt_store_result_start_internal(void *d)
1515 {
1516 MK_ASYNC_INTERNAL_BODY(
1517 mysql_stmt_store_result,
1518 (parms->stmt),
1519 parms->stmt->mysql,
1520 int,
1521 r_int)
1522 }
1523 int STDCALL
mysql_stmt_store_result_start(int * ret,MYSQL_STMT * stmt)1524 mysql_stmt_store_result_start(int *ret, MYSQL_STMT *stmt)
1525 {
1526 MK_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 }
1542 int STDCALL
mysql_stmt_store_result_cont(int * ret,MYSQL_STMT * stmt,int ready_status)1543 mysql_stmt_store_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1544 {
1545 MK_ASYNC_CONT_BODY(
1546 stmt->mysql,
1547 1,
1548 r_int)
1549 }
1550
1551 /* Structure used to pass parameters from mysql_stmt_close_start(). */
1552 struct mysql_stmt_close_params {
1553 MYSQL_STMT *stmt;
1554 };
1555 static void
mysql_stmt_close_start_internal(void * d)1556 mysql_stmt_close_start_internal(void *d)
1557 {
1558 MK_ASYNC_INTERNAL_BODY(
1559 mysql_stmt_close,
1560 (parms->stmt),
1561 parms->stmt->mysql,
1562 my_bool,
1563 r_my_bool)
1564 }
1565 int STDCALL
mysql_stmt_close_start(my_bool * ret,MYSQL_STMT * stmt)1566 mysql_stmt_close_start(my_bool *ret, MYSQL_STMT *stmt)
1567 {
1568 MK_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 }
1584 int STDCALL
mysql_stmt_close_cont(my_bool * ret,MYSQL_STMT * stmt,int ready_status)1585 mysql_stmt_close_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
1586 {
1587 MK_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(). */
1594 struct mysql_stmt_reset_params {
1595 MYSQL_STMT *stmt;
1596 };
1597 static void
mysql_stmt_reset_start_internal(void * d)1598 mysql_stmt_reset_start_internal(void *d)
1599 {
1600 MK_ASYNC_INTERNAL_BODY(
1601 mysql_stmt_reset,
1602 (parms->stmt),
1603 parms->stmt->mysql,
1604 my_bool,
1605 r_my_bool)
1606 }
1607 int STDCALL
mysql_stmt_reset_start(my_bool * ret,MYSQL_STMT * stmt)1608 mysql_stmt_reset_start(my_bool *ret, MYSQL_STMT *stmt)
1609 {
1610 MK_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 }
1626 int STDCALL
mysql_stmt_reset_cont(my_bool * ret,MYSQL_STMT * stmt,int ready_status)1627 mysql_stmt_reset_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
1628 {
1629 MK_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(). */
1636 struct mysql_stmt_free_result_params {
1637 MYSQL_STMT *stmt;
1638 };
1639 static void
mysql_stmt_free_result_start_internal(void * d)1640 mysql_stmt_free_result_start_internal(void *d)
1641 {
1642 MK_ASYNC_INTERNAL_BODY(
1643 mysql_stmt_free_result,
1644 (parms->stmt),
1645 parms->stmt->mysql,
1646 my_bool,
1647 r_my_bool)
1648 }
1649 int STDCALL
mysql_stmt_free_result_start(my_bool * ret,MYSQL_STMT * stmt)1650 mysql_stmt_free_result_start(my_bool *ret, MYSQL_STMT *stmt)
1651 {
1652 MK_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 }
1668 int STDCALL
mysql_stmt_free_result_cont(my_bool * ret,MYSQL_STMT * stmt,int ready_status)1669 mysql_stmt_free_result_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
1670 {
1671 MK_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(). */
1678 struct mysql_stmt_send_long_data_params {
1679 MYSQL_STMT *stmt;
1680 unsigned int param_number;
1681 const char *data;
1682 unsigned long length;
1683 };
1684 static void
mysql_stmt_send_long_data_start_internal(void * d)1685 mysql_stmt_send_long_data_start_internal(void *d)
1686 {
1687 MK_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 }
1694 int STDCALL
mysql_stmt_send_long_data_start(my_bool * ret,MYSQL_STMT * stmt,unsigned int param_number,const char * data,unsigned long length)1695 mysql_stmt_send_long_data_start(my_bool *ret, MYSQL_STMT *stmt,
1696 unsigned int param_number,
1697 const char *data, unsigned long length)
1698 {
1699 MK_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 }
1718 int STDCALL
mysql_stmt_send_long_data_cont(my_bool * ret,MYSQL_STMT * stmt,int ready_status)1719 mysql_stmt_send_long_data_cont(my_bool *ret, MYSQL_STMT *stmt, int ready_status)
1720 {
1721 MK_ASYNC_CONT_BODY(
1722 stmt->mysql,
1723 TRUE,
1724 r_my_bool)
1725 }
1726
1727 /* Structure used to pass parameters from mysql_commit_start(). */
1728 struct mysql_commit_params {
1729 MYSQL *mysql;
1730 };
1731 static void
mysql_commit_start_internal(void * d)1732 mysql_commit_start_internal(void *d)
1733 {
1734 MK_ASYNC_INTERNAL_BODY(
1735 mysql_commit,
1736 (parms->mysql),
1737 parms->mysql,
1738 my_bool,
1739 r_my_bool)
1740 }
1741 int STDCALL
mysql_commit_start(my_bool * ret,MYSQL * mysql)1742 mysql_commit_start(my_bool *ret, MYSQL *mysql)
1743 {
1744 MK_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 }
1755 int STDCALL
mysql_commit_cont(my_bool * ret,MYSQL * mysql,int ready_status)1756 mysql_commit_cont(my_bool *ret, MYSQL *mysql, int ready_status)
1757 {
1758 MK_ASYNC_CONT_BODY(
1759 mysql,
1760 TRUE,
1761 r_my_bool)
1762 }
1763
1764 /* Structure used to pass parameters from mysql_rollback_start(). */
1765 struct mysql_rollback_params {
1766 MYSQL *mysql;
1767 };
1768 static void
mysql_rollback_start_internal(void * d)1769 mysql_rollback_start_internal(void *d)
1770 {
1771 MK_ASYNC_INTERNAL_BODY(
1772 mysql_rollback,
1773 (parms->mysql),
1774 parms->mysql,
1775 my_bool,
1776 r_my_bool)
1777 }
1778 int STDCALL
mysql_rollback_start(my_bool * ret,MYSQL * mysql)1779 mysql_rollback_start(my_bool *ret, MYSQL *mysql)
1780 {
1781 MK_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 }
1792 int STDCALL
mysql_rollback_cont(my_bool * ret,MYSQL * mysql,int ready_status)1793 mysql_rollback_cont(my_bool *ret, MYSQL *mysql, int ready_status)
1794 {
1795 MK_ASYNC_CONT_BODY(
1796 mysql,
1797 TRUE,
1798 r_my_bool)
1799 }
1800
1801 /* Structure used to pass parameters from mysql_autocommit_start(). */
1802 struct mysql_autocommit_params {
1803 MYSQL *mysql;
1804 my_bool auto_mode;
1805 };
1806 static void
mysql_autocommit_start_internal(void * d)1807 mysql_autocommit_start_internal(void *d)
1808 {
1809 MK_ASYNC_INTERNAL_BODY(
1810 mysql_autocommit,
1811 (parms->mysql, parms->auto_mode),
1812 parms->mysql,
1813 my_bool,
1814 r_my_bool)
1815 }
1816 int STDCALL
mysql_autocommit_start(my_bool * ret,MYSQL * mysql,my_bool auto_mode)1817 mysql_autocommit_start(my_bool *ret, MYSQL *mysql, my_bool auto_mode)
1818 {
1819 MK_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 }
1831 int STDCALL
mysql_autocommit_cont(my_bool * ret,MYSQL * mysql,int ready_status)1832 mysql_autocommit_cont(my_bool *ret, MYSQL *mysql, int ready_status)
1833 {
1834 MK_ASYNC_CONT_BODY(
1835 mysql,
1836 TRUE,
1837 r_my_bool)
1838 }
1839
1840 /* Structure used to pass parameters from mysql_next_result_start(). */
1841 struct mysql_next_result_params {
1842 MYSQL *mysql;
1843 };
1844 static void
mysql_next_result_start_internal(void * d)1845 mysql_next_result_start_internal(void *d)
1846 {
1847 MK_ASYNC_INTERNAL_BODY(
1848 mysql_next_result,
1849 (parms->mysql),
1850 parms->mysql,
1851 int,
1852 r_int)
1853 }
1854 int STDCALL
mysql_next_result_start(int * ret,MYSQL * mysql)1855 mysql_next_result_start(int *ret, MYSQL *mysql)
1856 {
1857 MK_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 }
1868 int STDCALL
mysql_next_result_cont(int * ret,MYSQL * mysql,int ready_status)1869 mysql_next_result_cont(int *ret, MYSQL *mysql, int ready_status)
1870 {
1871 MK_ASYNC_CONT_BODY(
1872 mysql,
1873 1,
1874 r_int)
1875 }
1876
1877 /* Structure used to pass parameters from mysql_stmt_next_result_start(). */
1878 struct mysql_stmt_next_result_params {
1879 MYSQL_STMT *stmt;
1880 };
1881 static void
mysql_stmt_next_result_start_internal(void * d)1882 mysql_stmt_next_result_start_internal(void *d)
1883 {
1884 MK_ASYNC_INTERNAL_BODY(
1885 mysql_stmt_next_result,
1886 (parms->stmt),
1887 parms->stmt->mysql,
1888 int,
1889 r_int)
1890 }
1891 int STDCALL
mysql_stmt_next_result_start(int * ret,MYSQL_STMT * stmt)1892 mysql_stmt_next_result_start(int *ret, MYSQL_STMT *stmt)
1893 {
1894 MK_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 }
1905 int STDCALL
mysql_stmt_next_result_cont(int * ret,MYSQL_STMT * stmt,int ready_status)1906 mysql_stmt_next_result_cont(int *ret, MYSQL_STMT *stmt, int ready_status)
1907 {
1908 MK_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