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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
794 | mysql_close_slow_part_cont(MYSQL *sock, int ready_status) |
795 | { |
796 | MK_ASYNC_CONT_BODY_VOID_RETURN(sock) |
797 | } |
798 | int STDCALL |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 |
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 | |