mySQL 5.0.11 sources for tomato
[tomato.git] / release / src / router / mysql / libmysql / libmysql.c
blobf7eb19520b7108c06251a805a4aaa0e6418b7306
1 /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation.
7 There are special exceptions to the terms and conditions of the GPL as it
8 is applied to this software.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
19 #include <my_global.h>
20 #include <my_sys.h>
21 #include <my_time.h>
22 #include <mysys_err.h>
23 #include <m_string.h>
24 #include <m_ctype.h>
25 #include "mysql.h"
26 #include "mysql_version.h"
27 #include "mysqld_error.h"
28 #include "errmsg.h"
29 #include <violite.h>
30 #include <sys/stat.h>
31 #include <signal.h>
32 #include <time.h>
33 #ifdef HAVE_PWD_H
34 #include <pwd.h>
35 #endif
36 #if !defined(MSDOS) && !defined(__WIN__)
37 #include <sys/socket.h>
38 #include <netinet/in.h>
39 #include <arpa/inet.h>
40 #include <netdb.h>
41 #ifdef HAVE_SELECT_H
42 #include <select.h>
43 #endif
44 #ifdef HAVE_SYS_SELECT_H
45 #include <sys/select.h>
46 #endif
47 #endif /* !defined(MSDOS) && !defined(__WIN__) */
48 #ifdef HAVE_POLL
49 #include <sys/poll.h>
50 #endif
51 #ifdef HAVE_SYS_UN_H
52 #include <sys/un.h>
53 #endif
54 #if defined(THREAD) && !defined(__WIN__)
55 #include <my_pthread.h> /* because of signal() */
56 #endif
57 #ifndef INADDR_NONE
58 #define INADDR_NONE -1
59 #endif
61 #include <sql_common.h>
62 #include "client_settings.h"
64 #undef net_buffer_length
65 #undef max_allowed_packet
67 ulong net_buffer_length=8192;
68 ulong max_allowed_packet= 1024L*1024L*1024L;
71 #ifdef EMBEDDED_LIBRARY
72 #undef net_flush
73 my_bool net_flush(NET *net);
74 #endif
76 #if defined(MSDOS) || defined(__WIN__)
77 /* socket_errno is defined in my_global.h for all platforms */
78 #define perror(A)
79 #else
80 #include <errno.h>
81 #define SOCKET_ERROR -1
82 #endif /* __WIN__ */
85 If allowed through some configuration, then this needs to
86 be changed
88 #define MAX_LONG_DATA_LENGTH 8192
89 #define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
91 static void append_wild(char *to,char *end,const char *wild);
92 sig_handler my_pipe_sig_handler(int sig);
94 static my_bool mysql_client_init= 0;
95 static my_bool org_my_init_done= 0;
99 Initialize the MySQL client library
101 SYNOPSIS
102 mysql_server_init()
104 NOTES
105 Should be called before doing any other calls to the MySQL
106 client library to initialize thread specific variables etc.
107 It's called by mysql_init() to ensure that things will work for
108 old not threaded applications that doesn't call mysql_server_init()
109 directly.
111 RETURN
112 0 ok
113 1 could not initialize environment (out of memory or thread keys)
116 int STDCALL mysql_server_init(int argc __attribute__((unused)),
117 char **argv __attribute__((unused)),
118 char **groups __attribute__((unused)))
120 int result= 0;
121 if (!mysql_client_init)
123 mysql_client_init=1;
124 org_my_init_done=my_init_done;
125 if (my_init()) /* Will init threads */
126 return 1;
127 init_client_errs();
128 if (!mysql_port)
130 mysql_port = MYSQL_PORT;
131 #ifndef MSDOS
133 char *env;
134 struct servent *serv_ptr __attribute__((unused));
137 if builder specifically requested a default port, use that
138 (even if it coincides with our factory default).
139 only if they didn't do we check /etc/services (and, failing
140 on that, fall back to the factory default of 3306).
141 either default can be overridden by the environment variable
142 MYSQL_TCP_PORT, which in turn can be overridden with command
143 line options.
146 #if MYSQL_PORT_DEFAULT == 0
147 if ((serv_ptr = getservbyname("mysql", "tcp")))
148 mysql_port = (uint) ntohs((ushort) serv_ptr->s_port);
149 #endif
150 if ((env = getenv("MYSQL_TCP_PORT")))
151 mysql_port =(uint) atoi(env);
153 #endif
155 if (!mysql_unix_port)
157 char *env;
158 #ifdef __WIN__
159 mysql_unix_port = (char*) MYSQL_NAMEDPIPE;
160 #else
161 mysql_unix_port = (char*) MYSQL_UNIX_ADDR;
162 #endif
163 if ((env = getenv("MYSQL_UNIX_PORT")))
164 mysql_unix_port = env;
166 mysql_debug(NullS);
167 #if defined(SIGPIPE) && !defined(__WIN__) && !defined(__NETWARE__)
168 (void) signal(SIGPIPE, SIG_IGN);
169 #endif
170 #ifdef EMBEDDED_LIBRARY
171 if (argc > -1)
172 result= init_embedded_server(argc, argv, groups);
173 #endif
175 #ifdef THREAD
176 else
177 result= (int)my_thread_init(); /* Init if new thread */
178 #endif
179 return result;
184 Free all memory and resources used by the client library
186 NOTES
187 When calling this there should not be any other threads using
188 the library.
190 To make things simpler when used with windows dll's (which calls this
191 function automaticly), it's safe to call this function multiple times.
195 void STDCALL mysql_server_end()
197 if (!mysql_client_init)
198 return;
200 #ifdef EMBEDDED_LIBRARY
201 end_embedded_server();
202 #endif
203 finish_client_errs();
204 vio_end();
206 /* If library called my_init(), free memory allocated by it */
207 if (!org_my_init_done)
209 my_end(0);
211 else
213 free_charsets();
214 mysql_thread_end();
217 mysql_client_init= org_my_init_done= 0;
218 #ifdef EMBEDDED_SERVER
219 if (stderror_file)
221 fclose(stderror_file);
222 stderror_file= 0;
224 #endif
227 static MYSQL_PARAMETERS mysql_internal_parameters=
228 {&max_allowed_packet, &net_buffer_length, 0};
230 MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void)
232 return &mysql_internal_parameters;
235 my_bool STDCALL mysql_thread_init()
237 #ifdef THREAD
238 return my_thread_init();
239 #else
240 return 0;
241 #endif
244 void STDCALL mysql_thread_end()
246 #ifdef THREAD
247 my_thread_end();
248 #endif
252 Let the user specify that we don't want SIGPIPE; This doesn't however work
253 with threaded applications as we can have multiple read in progress.
255 static MYSQL* spawn_init(MYSQL* parent, const char* host,
256 unsigned int port,
257 const char* user,
258 const char* passwd);
263 Expand wildcard to a sql string
266 static void
267 append_wild(char *to, char *end, const char *wild)
269 end-=5; /* Some extra */
270 if (wild && wild[0])
272 to=strmov(to," like '");
273 while (*wild && to < end)
275 if (*wild == '\\' || *wild == '\'')
276 *to++='\\';
277 *to++= *wild++;
279 if (*wild) /* Too small buffer */
280 *to++='%'; /* Nicer this way */
281 to[0]='\'';
282 to[1]=0;
287 /**************************************************************************
288 Init debugging if MYSQL_DEBUG environment variable is found
289 **************************************************************************/
291 void STDCALL
292 mysql_debug(const char *debug __attribute__((unused)))
294 #ifndef DBUG_OFF
295 char *env;
296 if (debug)
298 DBUG_PUSH(debug);
300 else if ((env = getenv("MYSQL_DEBUG")))
302 DBUG_PUSH(env);
303 #if !defined(_WINVER) && !defined(WINVER)
304 puts("\n-------------------------------------------------------");
305 puts("MYSQL_DEBUG found. libmysql started with the following:");
306 puts(env);
307 puts("-------------------------------------------------------\n");
308 #else
310 char buff[80];
311 buff[sizeof(buff)-1]= 0;
312 strxnmov(buff,sizeof(buff)-1,"libmysql: ", env, NullS);
313 MessageBox((HWND) 0,"Debugging variable MYSQL_DEBUG used",buff,MB_OK);
315 #endif
317 #endif
321 /**************************************************************************
322 Close the server connection if we get a SIGPIPE
323 ARGSUSED
324 **************************************************************************/
326 sig_handler
327 my_pipe_sig_handler(int sig __attribute__((unused)))
329 DBUG_PRINT("info",("Hit by signal %d",sig));
330 #ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
331 (void) signal(SIGPIPE, my_pipe_sig_handler);
332 #endif
335 /* perform query on master */
336 my_bool STDCALL mysql_master_query(MYSQL *mysql, const char *q,
337 unsigned long length)
339 DBUG_ENTER("mysql_master_query");
340 if (mysql_master_send_query(mysql, q, length))
341 DBUG_RETURN(1);
342 DBUG_RETURN((*mysql->methods->read_query_result)(mysql));
345 my_bool STDCALL mysql_master_send_query(MYSQL *mysql, const char *q,
346 unsigned long length)
348 MYSQL *master = mysql->master;
349 DBUG_ENTER("mysql_master_send_query");
350 if (!master->net.vio && !mysql_real_connect(master,0,0,0,0,0,0,0))
351 DBUG_RETURN(1);
352 master->reconnect= 1;
353 mysql->last_used_con = master;
354 DBUG_RETURN(simple_command(master, COM_QUERY, (const uchar*) q, length, 1));
358 /* perform query on slave */
359 my_bool STDCALL mysql_slave_query(MYSQL *mysql, const char *q,
360 unsigned long length)
362 DBUG_ENTER("mysql_slave_query");
363 if (mysql_slave_send_query(mysql, q, length))
364 DBUG_RETURN(1);
365 DBUG_RETURN((*mysql->methods->read_query_result)(mysql));
369 my_bool STDCALL mysql_slave_send_query(MYSQL *mysql, const char *q,
370 unsigned long length)
372 MYSQL* last_used_slave, *slave_to_use = 0;
373 DBUG_ENTER("mysql_slave_send_query");
375 if ((last_used_slave = mysql->last_used_slave))
376 slave_to_use = last_used_slave->next_slave;
377 else
378 slave_to_use = mysql->next_slave;
380 Next_slave is always safe to use - we have a circular list of slaves
381 if there are no slaves, mysql->next_slave == mysql
383 mysql->last_used_con = mysql->last_used_slave = slave_to_use;
384 if (!slave_to_use->net.vio && !mysql_real_connect(slave_to_use, 0,0,0,
385 0,0,0,0))
386 DBUG_RETURN(1);
387 slave_to_use->reconnect= 1;
388 DBUG_RETURN(simple_command(slave_to_use, COM_QUERY, (const uchar*) q,
389 length, 1));
393 /* enable/disable parsing of all queries to decide
394 if they go on master or slave */
395 void STDCALL mysql_enable_rpl_parse(MYSQL* mysql)
397 mysql->options.rpl_parse = 1;
400 void STDCALL mysql_disable_rpl_parse(MYSQL* mysql)
402 mysql->options.rpl_parse = 0;
405 /* get the value of the parse flag */
406 int STDCALL mysql_rpl_parse_enabled(MYSQL* mysql)
408 return mysql->options.rpl_parse;
411 /* enable/disable reads from master */
412 void STDCALL mysql_enable_reads_from_master(MYSQL* mysql)
414 mysql->options.no_master_reads = 0;
417 void STDCALL mysql_disable_reads_from_master(MYSQL* mysql)
419 mysql->options.no_master_reads = 1;
422 /* get the value of the master read flag */
423 my_bool STDCALL mysql_reads_from_master_enabled(MYSQL* mysql)
425 return !(mysql->options.no_master_reads);
430 We may get an error while doing replication internals.
431 In this case, we add a special explanation to the original
432 error
435 static void expand_error(MYSQL* mysql, int error)
437 char tmp[MYSQL_ERRMSG_SIZE];
438 char *p;
439 uint err_length;
440 strmake(tmp, mysql->net.last_error, MYSQL_ERRMSG_SIZE-1);
441 p = strmake(mysql->net.last_error, ER(error), MYSQL_ERRMSG_SIZE-1);
442 err_length= (uint) (p - mysql->net.last_error);
443 strmake(p, tmp, MYSQL_ERRMSG_SIZE-1 - err_length);
444 mysql->net.last_errno = error;
448 This function assumes we have just called SHOW SLAVE STATUS and have
449 read the given result and row
452 static my_bool get_master(MYSQL* mysql, MYSQL_RES* res, MYSQL_ROW row)
454 MYSQL* master;
455 DBUG_ENTER("get_master");
456 if (mysql_num_fields(res) < 3)
457 DBUG_RETURN(1); /* safety */
459 /* use the same username and password as the original connection */
460 if (!(master = spawn_init(mysql, row[0], atoi(row[2]), 0, 0)))
461 DBUG_RETURN(1);
462 mysql->master = master;
463 DBUG_RETURN(0);
468 Assuming we already know that mysql points to a master connection,
469 retrieve all the slaves
472 static my_bool get_slaves_from_master(MYSQL* mysql)
474 MYSQL_RES* res = 0;
475 MYSQL_ROW row;
476 my_bool error = 1;
477 int has_auth_info;
478 int port_ind;
479 DBUG_ENTER("get_slaves_from_master");
481 if (!mysql->net.vio && !mysql_real_connect(mysql,0,0,0,0,0,0,0))
483 expand_error(mysql, CR_PROBE_MASTER_CONNECT);
484 DBUG_RETURN(1);
486 mysql->reconnect= 1;
488 if (mysql_query(mysql, "SHOW SLAVE HOSTS") ||
489 !(res = mysql_store_result(mysql)))
491 expand_error(mysql, CR_PROBE_SLAVE_HOSTS);
492 DBUG_RETURN(1);
495 switch (mysql_num_fields(res)) {
496 case 5:
497 has_auth_info = 0;
498 port_ind=2;
499 break;
500 case 7:
501 has_auth_info = 1;
502 port_ind=4;
503 break;
504 default:
505 goto err;
508 while ((row = mysql_fetch_row(res)))
510 MYSQL* slave;
511 const char* tmp_user, *tmp_pass;
513 if (has_auth_info)
515 tmp_user = row[2];
516 tmp_pass = row[3];
518 else
520 tmp_user = mysql->user;
521 tmp_pass = mysql->passwd;
524 if (!(slave = spawn_init(mysql, row[1], atoi(row[port_ind]),
525 tmp_user, tmp_pass)))
526 goto err;
528 /* Now add slave into the circular linked list */
529 slave->next_slave = mysql->next_slave;
530 mysql->next_slave = slave;
532 error = 0;
533 err:
534 if (res)
535 mysql_free_result(res);
536 DBUG_RETURN(error);
540 my_bool STDCALL mysql_rpl_probe(MYSQL* mysql)
542 MYSQL_RES *res= 0;
543 MYSQL_ROW row;
544 my_bool error= 1;
545 DBUG_ENTER("mysql_rpl_probe");
548 First determine the replication role of the server we connected to
549 the most reliable way to do this is to run SHOW SLAVE STATUS and see
550 if we have a non-empty master host. This is still not fool-proof -
551 it is not a sin to have a master that has a dormant slave thread with
552 a non-empty master host. However, it is more reliable to check
553 for empty master than whether the slave thread is actually running
555 if (mysql_query(mysql, "SHOW SLAVE STATUS") ||
556 !(res = mysql_store_result(mysql)))
558 expand_error(mysql, CR_PROBE_SLAVE_STATUS);
559 DBUG_RETURN(1);
562 row= mysql_fetch_row(res);
564 Check master host for emptiness/NULL
565 For MySQL 4.0 it's enough to check for row[0]
567 if (row && row[0] && *(row[0]))
569 /* this is a slave, ask it for the master */
570 if (get_master(mysql, res, row) || get_slaves_from_master(mysql))
571 goto err;
573 else
575 mysql->master = mysql;
576 if (get_slaves_from_master(mysql))
577 goto err;
580 error = 0;
581 err:
582 if (res)
583 mysql_free_result(res);
584 DBUG_RETURN(error);
589 Make a not so fool-proof decision on where the query should go, to
590 the master or the slave. Ideally the user should always make this
591 decision himself with mysql_master_query() or mysql_slave_query().
592 However, to be able to more easily port the old code, we support the
593 option of an educated guess - this should work for most applications,
594 however, it may make the wrong decision in some particular cases. If
595 that happens, the user would have to change the code to call
596 mysql_master_query() or mysql_slave_query() explicitly in the place
597 where we have made the wrong decision
600 enum mysql_rpl_type
601 STDCALL mysql_rpl_query_type(const char* q, int len)
603 const char *q_end= q + len;
604 for (; q < q_end; ++q)
606 char c;
607 if (my_isalpha(&my_charset_latin1, (c= *q)))
609 switch (my_tolower(&my_charset_latin1,c)) {
610 case 'i': /* insert */
611 case 'u': /* update or unlock tables */
612 case 'l': /* lock tables or load data infile */
613 case 'd': /* drop or delete */
614 case 'a': /* alter */
615 return MYSQL_RPL_MASTER;
616 case 'c': /* create or check */
617 return my_tolower(&my_charset_latin1,q[1]) == 'h' ? MYSQL_RPL_ADMIN :
618 MYSQL_RPL_MASTER;
619 case 's': /* select or show */
620 return my_tolower(&my_charset_latin1,q[1]) == 'h' ? MYSQL_RPL_ADMIN :
621 MYSQL_RPL_SLAVE;
622 case 'f': /* flush */
623 case 'r': /* repair */
624 case 'g': /* grant */
625 return MYSQL_RPL_ADMIN;
626 default:
627 return MYSQL_RPL_SLAVE;
631 return MYSQL_RPL_MASTER; /* By default, send to master */
635 /**************************************************************************
636 Connect to sql server
637 If host == 0 then use localhost
638 **************************************************************************/
640 #ifdef USE_OLD_FUNCTIONS
641 MYSQL * STDCALL
642 mysql_connect(MYSQL *mysql,const char *host,
643 const char *user, const char *passwd)
645 MYSQL *res;
646 mysql=mysql_init(mysql); /* Make it thread safe */
648 DBUG_ENTER("mysql_connect");
649 if (!(res=mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0)))
651 if (mysql->free_me)
652 my_free((uchar*) mysql,MYF(0));
654 mysql->reconnect= 1;
655 DBUG_RETURN(res);
658 #endif
661 /**************************************************************************
662 Change user and database
663 **************************************************************************/
665 int cli_read_change_user_result(MYSQL *mysql, char *buff, const char *passwd)
667 NET *net= &mysql->net;
668 ulong pkt_length;
670 pkt_length= cli_safe_read(mysql);
672 if (pkt_length == packet_error)
673 return 1;
675 if (pkt_length == 1 && net->read_pos[0] == 254 &&
676 mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
679 By sending this very specific reply server asks us to send scrambled
680 password in old format. The reply contains scramble_323.
682 scramble_323(buff, mysql->scramble, passwd);
683 if (my_net_write(net, (uchar*) buff, SCRAMBLE_LENGTH_323 + 1) ||
684 net_flush(net))
686 set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
687 return 1;
689 /* Read what server thinks about out new auth message report */
690 if (cli_safe_read(mysql) == packet_error)
691 return 1;
693 return 0;
696 my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
697 const char *passwd, const char *db)
699 char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
700 char *end= buff;
701 int rc;
702 CHARSET_INFO *saved_cs= mysql->charset;
704 DBUG_ENTER("mysql_change_user");
706 /* Get the connection-default character set. */
708 if (mysql_init_character_set(mysql))
710 mysql->charset= saved_cs;
711 DBUG_RETURN(TRUE);
714 /* Use an empty string instead of NULL. */
716 if (!user)
717 user="";
718 if (!passwd)
719 passwd="";
722 Store user into the buffer.
723 Advance position as strmake returns a pointer to the closing NUL.
725 end= strmake(end, user, USERNAME_LENGTH) + 1;
727 /* write scrambled password according to server capabilities */
728 if (passwd[0])
730 if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
732 *end++= SCRAMBLE_LENGTH;
733 scramble(end, mysql->scramble, passwd);
734 end+= SCRAMBLE_LENGTH;
736 else
738 scramble_323(end, mysql->scramble, passwd);
739 end+= SCRAMBLE_LENGTH_323 + 1;
742 else
743 *end++= '\0'; /* empty password */
744 /* Add database if needed */
745 end= strmake(end, db ? db : "", NAME_LEN) + 1;
747 /* Add character set number. */
749 if (mysql->server_capabilities & CLIENT_SECURE_CONNECTION)
751 int2store(end, (ushort) mysql->charset->number);
752 end+= 2;
755 /* Write authentication package */
756 simple_command(mysql,COM_CHANGE_USER, (uchar*) buff, (ulong) (end-buff), 1);
758 rc= (*mysql->methods->read_change_user_result)(mysql, buff, passwd);
761 The server will close all statements no matter was the attempt
762 to change user successful or not.
764 mysql_detach_stmt_list(&mysql->stmts, "mysql_change_user");
765 if (rc == 0)
767 /* Free old connect information */
768 my_free(mysql->user,MYF(MY_ALLOW_ZERO_PTR));
769 my_free(mysql->passwd,MYF(MY_ALLOW_ZERO_PTR));
770 my_free(mysql->db,MYF(MY_ALLOW_ZERO_PTR));
772 /* alloc new connect information */
773 mysql->user= my_strdup(user,MYF(MY_WME));
774 mysql->passwd=my_strdup(passwd,MYF(MY_WME));
775 mysql->db= db ? my_strdup(db,MYF(MY_WME)) : 0;
777 else
779 mysql->charset= saved_cs;
782 DBUG_RETURN(rc);
785 #if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
786 struct passwd *getpwuid(uid_t);
787 char* getlogin(void);
788 #endif
790 #if defined(__NETWARE__)
791 /* Default to value of USER on NetWare, if unset use "UNKNOWN_USER" */
792 void read_user_name(char *name)
794 char *str=getenv("USER");
795 strmake(name, str ? str : "UNKNOWN_USER", USERNAME_LENGTH);
798 #elif !defined(MSDOS) && ! defined(VMS) && !defined(__WIN__)
800 void read_user_name(char *name)
802 DBUG_ENTER("read_user_name");
803 if (geteuid() == 0)
804 (void) strmov(name,"root"); /* allow use of surun */
805 else
807 #ifdef HAVE_GETPWUID
808 struct passwd *skr;
809 const char *str;
810 if ((str=getlogin()) == NULL)
812 if ((skr=getpwuid(geteuid())) != NULL)
813 str=skr->pw_name;
814 else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
815 !(str=getenv("LOGIN")))
816 str="UNKNOWN_USER";
818 (void) strmake(name,str,USERNAME_LENGTH);
819 #elif HAVE_CUSERID
820 (void) cuserid(name);
821 #else
822 strmov(name,"UNKNOWN_USER");
823 #endif
825 DBUG_VOID_RETURN;
828 #else /* If MSDOS || VMS */
830 void read_user_name(char *name)
832 char *str=getenv("USER"); /* ODBC will send user variable */
833 strmake(name,str ? str : "ODBC", USERNAME_LENGTH);
836 #endif
838 my_bool handle_local_infile(MYSQL *mysql, const char *net_filename)
840 my_bool result= 1;
841 uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE);
842 NET *net= &mysql->net;
843 int readcount;
844 void *li_ptr; /* pass state to local_infile functions */
845 char *buf; /* buffer to be filled by local_infile_read */
846 struct st_mysql_options *options= &mysql->options;
847 DBUG_ENTER("handle_local_infile");
849 /* check that we've got valid callback functions */
850 if (!(options->local_infile_init &&
851 options->local_infile_read &&
852 options->local_infile_end &&
853 options->local_infile_error))
855 /* if any of the functions is invalid, set the default */
856 mysql_set_local_infile_default(mysql);
859 /* copy filename into local memory and allocate read buffer */
860 if (!(buf=my_malloc(packet_length, MYF(0))))
862 set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
863 DBUG_RETURN(1);
866 /* initialize local infile (open file, usually) */
867 if ((*options->local_infile_init)(&li_ptr, net_filename,
868 options->local_infile_userdata))
870 VOID(my_net_write(net,(const uchar*) "",0)); /* Server needs one packet */
871 net_flush(net);
872 strmov(net->sqlstate, unknown_sqlstate);
873 net->last_errno=
874 (*options->local_infile_error)(li_ptr,
875 net->last_error,
876 sizeof(net->last_error)-1);
877 goto err;
880 /* read blocks of data from local infile callback */
881 while ((readcount =
882 (*options->local_infile_read)(li_ptr, buf,
883 packet_length)) > 0)
885 if (my_net_write(net, (uchar*) buf, readcount))
887 DBUG_PRINT("error",
888 ("Lost connection to MySQL server during LOAD DATA of local file"));
889 set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
890 goto err;
894 /* Send empty packet to mark end of file */
895 if (my_net_write(net, (const uchar*) "", 0) || net_flush(net))
897 set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
898 goto err;
901 if (readcount < 0)
903 net->last_errno=
904 (*options->local_infile_error)(li_ptr,
905 net->last_error,
906 sizeof(net->last_error)-1);
907 goto err;
910 result=0; /* Ok */
912 err:
913 /* free up memory allocated with _init, usually */
914 (*options->local_infile_end)(li_ptr);
915 my_free(buf, MYF(0));
916 DBUG_RETURN(result);
920 /****************************************************************************
921 Default handlers for LOAD LOCAL INFILE
922 ****************************************************************************/
924 typedef struct st_default_local_infile
926 int fd;
927 int error_num;
928 const char *filename;
929 char error_msg[LOCAL_INFILE_ERROR_LEN];
930 } default_local_infile_data;
934 Open file for LOAD LOCAL INFILE
936 SYNOPSIS
937 default_local_infile_init()
938 ptr Store pointer to internal data here
939 filename File name to open. This may be in unix format !
942 NOTES
943 Even if this function returns an error, the load data interface
944 guarantees that default_local_infile_end() is called.
946 RETURN
947 0 ok
948 1 error
951 static int default_local_infile_init(void **ptr, const char *filename,
952 void *userdata __attribute__ ((unused)))
954 default_local_infile_data *data;
955 char tmp_name[FN_REFLEN];
957 if (!(*ptr= data= ((default_local_infile_data *)
958 my_malloc(sizeof(default_local_infile_data), MYF(0)))))
959 return 1; /* out of memory */
961 data->error_msg[0]= 0;
962 data->error_num= 0;
963 data->filename= filename;
965 fn_format(tmp_name, filename, "", "", MY_UNPACK_FILENAME);
966 if ((data->fd = my_open(tmp_name, O_RDONLY, MYF(0))) < 0)
968 data->error_num= my_errno;
969 my_snprintf(data->error_msg, sizeof(data->error_msg)-1,
970 EE(EE_FILENOTFOUND), tmp_name, data->error_num);
971 return 1;
973 return 0; /* ok */
978 Read data for LOAD LOCAL INFILE
980 SYNOPSIS
981 default_local_infile_read()
982 ptr Points to handle allocated by _init
983 buf Read data here
984 buf_len Ammount of data to read
986 RETURN
987 > 0 number of bytes read
988 == 0 End of data
989 < 0 Error
992 static int default_local_infile_read(void *ptr, char *buf, uint buf_len)
994 int count;
995 default_local_infile_data*data = (default_local_infile_data *) ptr;
997 if ((count= (int) my_read(data->fd, (uchar *) buf, buf_len, MYF(0))) < 0)
999 data->error_num= EE_READ; /* the errmsg for not entire file read */
1000 my_snprintf(data->error_msg, sizeof(data->error_msg)-1,
1001 EE(EE_READ),
1002 data->filename, my_errno);
1004 return count;
1009 Read data for LOAD LOCAL INFILE
1011 SYNOPSIS
1012 default_local_infile_end()
1013 ptr Points to handle allocated by _init
1014 May be NULL if _init failed!
1016 RETURN
1019 static void default_local_infile_end(void *ptr)
1021 default_local_infile_data *data= (default_local_infile_data *) ptr;
1022 if (data) /* If not error on open */
1024 if (data->fd >= 0)
1025 my_close(data->fd, MYF(MY_WME));
1026 my_free(ptr, MYF(MY_WME));
1032 Return error from LOAD LOCAL INFILE
1034 SYNOPSIS
1035 default_local_infile_end()
1036 ptr Points to handle allocated by _init
1037 May be NULL if _init failed!
1038 error_msg Store error text here
1039 error_msg_len Max lenght of error_msg
1041 RETURN
1042 error message number
1045 static int
1046 default_local_infile_error(void *ptr, char *error_msg, uint error_msg_len)
1048 default_local_infile_data *data = (default_local_infile_data *) ptr;
1049 if (data) /* If not error on open */
1051 strmake(error_msg, data->error_msg, error_msg_len);
1052 return data->error_num;
1054 /* This can only happen if we got error on malloc of handle */
1055 strmov(error_msg, ER(CR_OUT_OF_MEMORY));
1056 return CR_OUT_OF_MEMORY;
1060 void
1061 mysql_set_local_infile_handler(MYSQL *mysql,
1062 int (*local_infile_init)(void **, const char *,
1063 void *),
1064 int (*local_infile_read)(void *, char *, uint),
1065 void (*local_infile_end)(void *),
1066 int (*local_infile_error)(void *, char *, uint),
1067 void *userdata)
1069 mysql->options.local_infile_init= local_infile_init;
1070 mysql->options.local_infile_read= local_infile_read;
1071 mysql->options.local_infile_end= local_infile_end;
1072 mysql->options.local_infile_error= local_infile_error;
1073 mysql->options.local_infile_userdata = userdata;
1077 void mysql_set_local_infile_default(MYSQL *mysql)
1079 mysql->options.local_infile_init= default_local_infile_init;
1080 mysql->options.local_infile_read= default_local_infile_read;
1081 mysql->options.local_infile_end= default_local_infile_end;
1082 mysql->options.local_infile_error= default_local_infile_error;
1086 /**************************************************************************
1087 Do a query. If query returned rows, free old rows.
1088 Read data by mysql_store_result or by repeat call of mysql_fetch_row
1089 **************************************************************************/
1091 int STDCALL
1092 mysql_query(MYSQL *mysql, const char *query)
1094 return mysql_real_query(mysql,query, (uint) strlen(query));
1098 static MYSQL* spawn_init(MYSQL* parent, const char* host,
1099 unsigned int port, const char* user,
1100 const char* passwd)
1102 MYSQL* child;
1103 DBUG_ENTER("spawn_init");
1104 if (!(child= mysql_init(0)))
1105 DBUG_RETURN(0);
1107 child->options.user= my_strdup((user) ? user :
1108 (parent->user ? parent->user :
1109 parent->options.user), MYF(0));
1110 child->options.password= my_strdup((passwd) ? passwd :
1111 (parent->passwd ?
1112 parent->passwd :
1113 parent->options.password), MYF(0));
1114 child->options.port= port;
1115 child->options.host= my_strdup((host) ? host :
1116 (parent->host ?
1117 parent->host :
1118 parent->options.host), MYF(0));
1119 if (parent->db)
1120 child->options.db= my_strdup(parent->db, MYF(0));
1121 else if (parent->options.db)
1122 child->options.db= my_strdup(parent->options.db, MYF(0));
1125 rpl_pivot is set to 1 in mysql_init(); Reset it as we are not doing
1126 replication here
1128 child->rpl_pivot= 0;
1129 DBUG_RETURN(child);
1134 STDCALL mysql_set_master(MYSQL* mysql, const char* host,
1135 unsigned int port, const char* user,
1136 const char* passwd)
1138 if (mysql->master != mysql && !mysql->master->rpl_pivot)
1139 mysql_close(mysql->master);
1140 if (!(mysql->master = spawn_init(mysql, host, port, user, passwd)))
1141 return 1;
1142 return 0;
1147 STDCALL mysql_add_slave(MYSQL* mysql, const char* host,
1148 unsigned int port,
1149 const char* user,
1150 const char* passwd)
1152 MYSQL* slave;
1153 if (!(slave = spawn_init(mysql, host, port, user, passwd)))
1154 return 1;
1155 slave->next_slave = mysql->next_slave;
1156 mysql->next_slave = slave;
1157 return 0;
1160 /**************************************************************************
1161 Return next field of the query results
1162 **************************************************************************/
1164 MYSQL_FIELD * STDCALL
1165 mysql_fetch_field(MYSQL_RES *result)
1167 if (result->current_field >= result->field_count)
1168 return(NULL);
1169 return &result->fields[result->current_field++];
1173 /**************************************************************************
1174 Move to a specific row and column
1175 **************************************************************************/
1177 void STDCALL
1178 mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
1180 MYSQL_ROWS *tmp=0;
1181 DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
1182 if (result->data)
1183 for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
1184 result->current_row=0;
1185 result->data_cursor = tmp;
1189 /*************************************************************************
1190 put the row or field cursor one a position one got from mysql_row_tell()
1191 This doesn't restore any data. The next mysql_fetch_row or
1192 mysql_fetch_field will return the next row or field after the last used
1193 *************************************************************************/
1195 MYSQL_ROW_OFFSET STDCALL
1196 mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET row)
1198 MYSQL_ROW_OFFSET return_value=result->data_cursor;
1199 result->current_row= 0;
1200 result->data_cursor= row;
1201 return return_value;
1205 MYSQL_FIELD_OFFSET STDCALL
1206 mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset)
1208 MYSQL_FIELD_OFFSET return_value=result->current_field;
1209 result->current_field=field_offset;
1210 return return_value;
1214 /*****************************************************************************
1215 List all databases
1216 *****************************************************************************/
1218 MYSQL_RES * STDCALL
1219 mysql_list_dbs(MYSQL *mysql, const char *wild)
1221 char buff[255];
1222 DBUG_ENTER("mysql_list_dbs");
1224 append_wild(strmov(buff,"show databases"),buff+sizeof(buff),wild);
1225 if (mysql_query(mysql,buff))
1226 DBUG_RETURN(0);
1227 DBUG_RETURN (mysql_store_result(mysql));
1231 /*****************************************************************************
1232 List all tables in a database
1233 If wild is given then only the tables matching wild is returned
1234 *****************************************************************************/
1236 MYSQL_RES * STDCALL
1237 mysql_list_tables(MYSQL *mysql, const char *wild)
1239 char buff[255];
1240 DBUG_ENTER("mysql_list_tables");
1242 append_wild(strmov(buff,"show tables"),buff+sizeof(buff),wild);
1243 if (mysql_query(mysql,buff))
1244 DBUG_RETURN(0);
1245 DBUG_RETURN (mysql_store_result(mysql));
1249 MYSQL_FIELD *cli_list_fields(MYSQL *mysql)
1251 MYSQL_DATA *query;
1252 if (!(query= cli_read_rows(mysql,(MYSQL_FIELD*) 0,
1253 protocol_41(mysql) ? 8 : 6)))
1254 return NULL;
1256 mysql->field_count= (uint) query->rows;
1257 return unpack_fields(mysql, query,&mysql->field_alloc,
1258 mysql->field_count, 1, mysql->server_capabilities);
1262 /**************************************************************************
1263 List all fields in a table
1264 If wild is given then only the fields matching wild is returned
1265 Instead of this use query:
1266 show fields in 'table' like "wild"
1267 **************************************************************************/
1269 MYSQL_RES * STDCALL
1270 mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
1272 MYSQL_RES *result;
1273 MYSQL_FIELD *fields;
1274 char buff[258],*end;
1275 DBUG_ENTER("mysql_list_fields");
1276 DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : ""));
1278 end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
1279 free_old_query(mysql);
1280 if (simple_command(mysql, COM_FIELD_LIST, (uchar*) buff,
1281 (ulong) (end-buff), 1) ||
1282 !(fields= (*mysql->methods->list_fields)(mysql)))
1283 DBUG_RETURN(NULL);
1285 if (!(result = (MYSQL_RES *) my_malloc(sizeof(MYSQL_RES),
1286 MYF(MY_WME | MY_ZEROFILL))))
1287 DBUG_RETURN(NULL);
1289 result->methods= mysql->methods;
1290 result->field_alloc=mysql->field_alloc;
1291 mysql->fields=0;
1292 result->field_count = mysql->field_count;
1293 result->fields= fields;
1294 result->eof=1;
1295 DBUG_RETURN(result);
1298 /* List all running processes (threads) in server */
1300 MYSQL_RES * STDCALL
1301 mysql_list_processes(MYSQL *mysql)
1303 MYSQL_DATA *fields;
1304 uint field_count;
1305 uchar *pos;
1306 DBUG_ENTER("mysql_list_processes");
1308 LINT_INIT(fields);
1309 if (simple_command(mysql,COM_PROCESS_INFO,0,0,0))
1310 DBUG_RETURN(0);
1311 free_old_query(mysql);
1312 pos=(uchar*) mysql->net.read_pos;
1313 field_count=(uint) net_field_length(&pos);
1314 if (!(fields = (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*) 0,
1315 protocol_41(mysql) ? 7 : 5)))
1316 DBUG_RETURN(NULL);
1317 if (!(mysql->fields=unpack_fields(mysql, fields,&mysql->field_alloc,field_count,0,
1318 mysql->server_capabilities)))
1319 DBUG_RETURN(0);
1320 mysql->status=MYSQL_STATUS_GET_RESULT;
1321 mysql->field_count=field_count;
1322 DBUG_RETURN(mysql_store_result(mysql));
1326 #ifdef USE_OLD_FUNCTIONS
1327 int STDCALL
1328 mysql_create_db(MYSQL *mysql, const char *db)
1330 DBUG_ENTER("mysql_createdb");
1331 DBUG_PRINT("enter",("db: %s",db));
1332 DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (ulong) strlen(db),0));
1336 int STDCALL
1337 mysql_drop_db(MYSQL *mysql, const char *db)
1339 DBUG_ENTER("mysql_drop_db");
1340 DBUG_PRINT("enter",("db: %s",db));
1341 DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(ulong) strlen(db),0));
1343 #endif
1346 int STDCALL
1347 mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
1349 uchar level[1];
1350 DBUG_ENTER("mysql_shutdown");
1351 level[0]= (uchar) shutdown_level;
1352 DBUG_RETURN(simple_command(mysql, COM_SHUTDOWN, level, 1, 0));
1356 int STDCALL
1357 mysql_refresh(MYSQL *mysql,uint options)
1359 uchar bits[1];
1360 DBUG_ENTER("mysql_refresh");
1361 bits[0]= (uchar) options;
1362 DBUG_RETURN(simple_command(mysql, COM_REFRESH, bits, 1, 0));
1366 int STDCALL
1367 mysql_kill(MYSQL *mysql,ulong pid)
1369 uchar buff[4];
1370 DBUG_ENTER("mysql_kill");
1371 int4store(buff,pid);
1372 DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,sizeof(buff),0));
1376 int STDCALL
1377 mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option)
1379 uchar buff[2];
1380 DBUG_ENTER("mysql_set_server_option");
1381 int2store(buff, (uint) option);
1382 DBUG_RETURN(simple_command(mysql, COM_SET_OPTION, buff, sizeof(buff), 0));
1386 int STDCALL
1387 mysql_dump_debug_info(MYSQL *mysql)
1389 DBUG_ENTER("mysql_dump_debug_info");
1390 DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0));
1394 const char *cli_read_statistics(MYSQL *mysql)
1396 mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
1397 if (!mysql->net.read_pos[0])
1399 set_mysql_error(mysql, CR_WRONG_HOST_INFO, unknown_sqlstate);
1400 return mysql->net.last_error;
1402 return (char*) mysql->net.read_pos;
1406 const char * STDCALL
1407 mysql_stat(MYSQL *mysql)
1409 DBUG_ENTER("mysql_stat");
1410 if (simple_command(mysql,COM_STATISTICS,0,0,0))
1411 DBUG_RETURN(mysql->net.last_error);
1412 DBUG_RETURN((*mysql->methods->read_statistics)(mysql));
1416 int STDCALL
1417 mysql_ping(MYSQL *mysql)
1419 int res;
1420 DBUG_ENTER("mysql_ping");
1421 res= simple_command(mysql,COM_PING,0,0,0);
1422 if (res == CR_SERVER_LOST && mysql->reconnect)
1423 res= simple_command(mysql,COM_PING,0,0,0);
1424 DBUG_RETURN(res);
1428 const char * STDCALL
1429 mysql_get_server_info(MYSQL *mysql)
1431 return((char*) mysql->server_version);
1435 const char * STDCALL
1436 mysql_get_host_info(MYSQL *mysql)
1438 return(mysql->host_info);
1442 uint STDCALL
1443 mysql_get_proto_info(MYSQL *mysql)
1445 return (mysql->protocol_version);
1448 const char * STDCALL
1449 mysql_get_client_info(void)
1451 return (char*) MYSQL_SERVER_VERSION;
1454 ulong STDCALL mysql_get_client_version(void)
1456 return MYSQL_VERSION_ID;
1459 my_bool STDCALL mysql_eof(MYSQL_RES *res)
1461 return res->eof;
1464 MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr)
1466 return &(res)->fields[fieldnr];
1469 MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res)
1471 return (res)->fields;
1474 MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res)
1476 return res->data_cursor;
1479 MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res)
1481 return (res)->current_field;
1484 /* MYSQL */
1486 unsigned int STDCALL mysql_field_count(MYSQL *mysql)
1488 return mysql->last_used_con->field_count;
1491 my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
1493 return mysql->last_used_con->affected_rows;
1496 my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
1498 return mysql->last_used_con->insert_id;
1501 const char *STDCALL mysql_sqlstate(MYSQL *mysql)
1503 return mysql ? mysql->net.sqlstate : cant_connect_sqlstate;
1506 uint STDCALL mysql_warning_count(MYSQL *mysql)
1508 return mysql->warning_count;
1511 const char *STDCALL mysql_info(MYSQL *mysql)
1513 return mysql->info;
1516 ulong STDCALL mysql_thread_id(MYSQL *mysql)
1518 return (mysql)->thread_id;
1521 const char * STDCALL mysql_character_set_name(MYSQL *mysql)
1523 return mysql->charset->csname;
1526 void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *csinfo)
1528 csinfo->number = mysql->charset->number;
1529 csinfo->state = mysql->charset->state;
1530 csinfo->csname = mysql->charset->csname;
1531 csinfo->name = mysql->charset->name;
1532 csinfo->comment = mysql->charset->comment;
1533 csinfo->mbminlen = mysql->charset->mbminlen;
1534 csinfo->mbmaxlen = mysql->charset->mbmaxlen;
1536 if (mysql->options.charset_dir)
1537 csinfo->dir = mysql->options.charset_dir;
1538 else
1539 csinfo->dir = charsets_dir;
1542 uint STDCALL mysql_thread_safe(void)
1544 #ifdef THREAD
1545 return 1;
1546 #else
1547 return 0;
1548 #endif
1552 my_bool STDCALL mysql_embedded(void)
1554 #ifdef EMBEDDED_LIBRARY
1555 return 1;
1556 #else
1557 return 0;
1558 #endif
1561 /****************************************************************************
1562 Some support functions
1563 ****************************************************************************/
1566 Functions called my my_net_init() to set some application specific variables
1569 void my_net_local_init(NET *net)
1571 net->max_packet= (uint) net_buffer_length;
1572 my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
1573 my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
1574 net->retry_count= 1;
1575 net->max_packet_size= max(net_buffer_length, max_allowed_packet);
1579 This function is used to create HEX string that you
1580 can use in a SQL statement in of the either ways:
1581 INSERT INTO blob_column VALUES (0xAABBCC); (any MySQL version)
1582 INSERT INTO blob_column VALUES (X'AABBCC'); (4.1 and higher)
1584 The string in "from" is encoded to a HEX string.
1585 The result is placed in "to" and a terminating null byte is appended.
1587 The string pointed to by "from" must be "length" bytes long.
1588 You must allocate the "to" buffer to be at least length*2+1 bytes long.
1589 Each character needs two bytes, and you need room for the terminating
1590 null byte. When mysql_hex_string() returns, the contents of "to" will
1591 be a null-terminated string. The return value is the length of the
1592 encoded string, not including the terminating null character.
1594 The return value does not contain any leading 0x or a leading X' and
1595 trailing '. The caller must supply whichever of those is desired.
1598 ulong STDCALL
1599 mysql_hex_string(char *to, const char *from, ulong length)
1601 char *to0= to;
1602 const char *end;
1604 for (end= from + length; from < end; from++)
1606 *to++= _dig_vec_upper[((unsigned char) *from) >> 4];
1607 *to++= _dig_vec_upper[((unsigned char) *from) & 0x0F];
1609 *to= '\0';
1610 return (ulong) (to-to0);
1614 Add escape characters to a string (blob?) to make it suitable for a insert
1615 to should at least have place for length*2+1 chars
1616 Returns the length of the to string
1619 ulong STDCALL
1620 mysql_escape_string(char *to,const char *from,ulong length)
1622 return (uint) escape_string_for_mysql(default_charset_info, to, 0, from, length);
1625 ulong STDCALL
1626 mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
1627 ulong length)
1629 if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
1630 return (uint) escape_quotes_for_mysql(mysql->charset, to, 0, from, length);
1631 return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length);
1634 void STDCALL
1635 myodbc_remove_escape(MYSQL *mysql,char *name)
1637 char *to;
1638 #ifdef USE_MB
1639 my_bool use_mb_flag=use_mb(mysql->charset);
1640 char *UNINIT_VAR(end);
1641 if (use_mb_flag)
1642 for (end=name; *end ; end++) ;
1643 #endif
1645 for (to=name ; *name ; name++)
1647 #ifdef USE_MB
1648 int l;
1649 if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) )
1651 while (l--)
1652 *to++ = *name++;
1653 name--;
1654 continue;
1656 #endif
1657 if (*name == '\\' && name[1])
1658 name++;
1659 *to++= *name;
1661 *to=0;
1664 /********************************************************************
1665 Implementation of new client API for 4.1 version.
1667 mysql_stmt_* are real prototypes used by applications.
1669 To make API work in embedded library all functions performing
1670 real I/O are prefixed with 'cli_' (abbreviated from 'Call Level
1671 Interface'). This functions are invoked via pointers set in
1672 MYSQL::methods structure. Embedded counterparts, prefixed with
1673 'emb_' reside in libmysqld/lib_sql.cc.
1674 *********************************************************************/
1676 /******************* Declarations ***********************************/
1678 /* Default number of rows fetched per one COM_STMT_FETCH command. */
1680 #define DEFAULT_PREFETCH_ROWS (ulong) 1
1683 These functions are called by function pointer MYSQL_STMT::read_row_func.
1684 Each function corresponds to one of the read methods:
1685 - mysql_stmt_fetch without prior mysql_stmt_store_result,
1686 - mysql_stmt_fetch when result is stored,
1687 - mysql_stmt_fetch when there are no rows (always returns MYSQL_NO_DATA)
1690 static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row);
1691 static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row);
1692 static int stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row);
1693 static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row);
1694 static int stmt_read_row_no_result_set(MYSQL_STMT *stmt, unsigned char **row);
1697 This function is used in mysql_stmt_store_result if
1698 STMT_ATTR_UPDATE_MAX_LENGTH attribute is set.
1700 static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
1701 static my_bool setup_one_fetch_function(MYSQL_BIND *, MYSQL_FIELD *field);
1703 /* Auxilary function used to reset statement handle. */
1705 #define RESET_SERVER_SIDE 1
1706 #define RESET_LONG_DATA 2
1707 #define RESET_STORE_RESULT 4
1708 #define RESET_CLEAR_ERROR 8
1710 static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags);
1713 Maximum sizes of MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME
1714 values stored in network buffer.
1717 /* 1 (length) + 2 (year) + 1 (month) + 1 (day) */
1718 #define MAX_DATE_REP_LENGTH 5
1721 1 (length) + 1 (is negative) + 4 (day count) + 1 (hour)
1722 + 1 (minute) + 1 (seconds) + 4 (microseconds)
1724 #define MAX_TIME_REP_LENGTH 13
1727 1 (length) + 2 (year) + 1 (month) + 1 (day) +
1728 1 (hour) + 1 (minute) + 1 (second) + 4 (microseconds)
1730 #define MAX_DATETIME_REP_LENGTH 12
1732 #define MAX_DOUBLE_STRING_REP_LENGTH 331
1734 /* A macro to check truncation errors */
1736 #define IS_TRUNCATED(value, is_unsigned, min, max, umax) \
1737 ((is_unsigned) ? (((value) > (umax) || (value) < 0) ? 1 : 0) : \
1738 (((value) > (max) || (value) < (min)) ? 1 : 0))
1740 #define BIND_RESULT_DONE 1
1742 We report truncations only if at least one of MYSQL_BIND::error
1743 pointers is set. In this case stmt->bind_result_done |-ed with
1744 this flag.
1746 #define REPORT_DATA_TRUNCATION 2
1748 /**************** Misc utility functions ****************************/
1751 Reallocate the NET package to have at least length bytes available.
1753 SYNPOSIS
1754 my_realloc_str()
1755 net The NET structure to modify.
1756 length Ensure that net->buff has space for at least
1757 this number of bytes.
1759 RETURN VALUES
1760 0 Success.
1761 1 Error, i.e. out of memory or requested packet size is bigger
1762 than max_allowed_packet. The error code is stored in net->last_errno.
1765 static my_bool my_realloc_str(NET *net, ulong length)
1767 ulong buf_length= (ulong) (net->write_pos - net->buff);
1768 my_bool res=0;
1769 DBUG_ENTER("my_realloc_str");
1770 if (buf_length + length > net->max_packet)
1772 res= net_realloc(net, buf_length + length);
1773 if (res)
1775 strmov(net->sqlstate, unknown_sqlstate);
1776 strmov(net->last_error, ER(net->last_errno));
1778 net->write_pos= net->buff+ buf_length;
1780 DBUG_RETURN(res);
1784 static void stmt_clear_error(MYSQL_STMT *stmt)
1786 if (stmt->last_errno)
1788 stmt->last_errno= 0;
1789 stmt->last_error[0]= '\0';
1790 strmov(stmt->sqlstate, not_error_sqlstate);
1795 Set statement error code, sqlstate, and error message
1796 from given errcode and sqlstate.
1799 void set_stmt_error(MYSQL_STMT * stmt, int errcode,
1800 const char *sqlstate, const char *err)
1802 DBUG_ENTER("set_stmt_error");
1803 DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode)));
1804 DBUG_ASSERT(stmt != 0);
1806 if (err == 0)
1807 err= ER(errcode);
1809 stmt->last_errno= errcode;
1810 strmov(stmt->last_error, ER(errcode));
1811 strmov(stmt->sqlstate, sqlstate);
1813 DBUG_VOID_RETURN;
1818 Set statement error code, sqlstate, and error message from NET.
1820 @param stmt a statement handle. Copy the error here.
1821 @param net mysql->net. Source of the error.
1824 void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net)
1826 DBUG_ENTER("set_stmt_errmsg");
1827 DBUG_PRINT("enter", ("error: %d/%s '%s'",
1828 net->last_errno,
1829 net->sqlstate,
1830 net->last_error));
1831 DBUG_ASSERT(stmt != 0);
1833 stmt->last_errno= net->last_errno;
1834 if (net->last_error && net->last_error[0])
1835 strmov(stmt->last_error, net->last_error);
1836 strmov(stmt->sqlstate, net->sqlstate);
1838 DBUG_VOID_RETURN;
1842 Read and unpack server reply to COM_STMT_PREPARE command (sent from
1843 mysql_stmt_prepare).
1845 SYNOPSIS
1846 cli_read_prepare_result()
1847 mysql connection handle
1848 stmt statement handle
1850 RETURN VALUES
1851 0 ok
1852 1 error
1855 my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
1857 uchar *pos;
1858 uint field_count, param_count;
1859 ulong packet_length;
1860 MYSQL_DATA *fields_data;
1861 DBUG_ENTER("cli_read_prepare_result");
1863 mysql= mysql->last_used_con;
1864 if ((packet_length= cli_safe_read(mysql)) == packet_error)
1865 DBUG_RETURN(1);
1866 mysql->warning_count= 0;
1868 pos= (uchar*) mysql->net.read_pos;
1869 stmt->stmt_id= uint4korr(pos+1); pos+= 5;
1870 /* Number of columns in result set */
1871 field_count= uint2korr(pos); pos+= 2;
1872 /* Number of placeholders in the statement */
1873 param_count= uint2korr(pos); pos+= 2;
1874 if (packet_length >= 12)
1875 mysql->warning_count= uint2korr(pos+1);
1877 if (param_count != 0)
1879 MYSQL_DATA *param_data;
1881 /* skip parameters data: we don't support it yet */
1882 if (!(param_data= (*mysql->methods->read_rows)(mysql, (MYSQL_FIELD*)0, 7)))
1883 DBUG_RETURN(1);
1884 free_rows(param_data);
1887 if (field_count != 0)
1889 if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
1890 mysql->server_status|= SERVER_STATUS_IN_TRANS;
1892 if (!(fields_data= (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,7)))
1893 DBUG_RETURN(1);
1894 if (!(stmt->fields= unpack_fields(mysql, fields_data,&stmt->mem_root,
1895 field_count,0,
1896 mysql->server_capabilities)))
1897 DBUG_RETURN(1);
1899 stmt->field_count= field_count;
1900 stmt->param_count= (ulong) param_count;
1901 DBUG_PRINT("exit",("field_count: %u param_count: %u warning_count: %u",
1902 field_count, param_count, (uint) mysql->warning_count));
1904 DBUG_RETURN(0);
1909 Allocate memory and init prepared statement structure.
1911 SYNOPSIS
1912 mysql_stmt_init()
1913 mysql connection handle
1915 DESCRIPTION
1916 This is an entry point of the new API. Returned handle stands for
1917 a server-side prepared statement. Memory for this structure (~700
1918 bytes) is allocated using 'malloc'. Once created, the handle can be
1919 reused many times. Created statement handle is bound to connection
1920 handle provided to this call: its lifetime is limited by lifetime
1921 of connection.
1922 'mysql_stmt_init()' is a pure local call, server side structure is
1923 created only in mysql_stmt_prepare.
1924 Next steps you may want to make:
1925 - set a statement attribute (mysql_stmt_attr_set()),
1926 - prepare statement handle with a query (mysql_stmt_prepare()),
1927 - close statement handle and free its memory (mysql_stmt_close()),
1928 - reset statement with mysql_stmt_reset() (a no-op which will
1929 just return).
1930 Behaviour of the rest of API calls on this statement is not defined yet
1931 (though we're working on making each wrong call sequence return
1932 error).
1934 RETURN VALUE
1935 statement structure upon success and NULL if out of
1936 memory
1939 MYSQL_STMT * STDCALL
1940 mysql_stmt_init(MYSQL *mysql)
1942 MYSQL_STMT *stmt;
1943 DBUG_ENTER("mysql_stmt_init");
1945 if (!(stmt= (MYSQL_STMT *) my_malloc(sizeof(MYSQL_STMT),
1946 MYF(MY_WME | MY_ZEROFILL))))
1948 set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
1949 DBUG_RETURN(0);
1952 init_alloc_root(&stmt->mem_root, 2048, 2048);
1953 init_alloc_root(&stmt->result.alloc, 4096, 4096);
1954 stmt->result.alloc.min_malloc= sizeof(MYSQL_ROWS);
1955 mysql->stmts= list_add(mysql->stmts, &stmt->list);
1956 stmt->list.data= stmt;
1957 stmt->state= MYSQL_STMT_INIT_DONE;
1958 stmt->mysql= mysql;
1959 stmt->read_row_func= stmt_read_row_no_result_set;
1960 stmt->prefetch_rows= DEFAULT_PREFETCH_ROWS;
1961 strmov(stmt->sqlstate, not_error_sqlstate);
1962 /* The rest of statement members was bzeroed inside malloc */
1964 DBUG_RETURN(stmt);
1969 Prepare server side statement with query.
1971 SYNOPSIS
1972 mysql_stmt_prepare()
1973 stmt statement handle
1974 query statement to prepare
1975 length statement length
1977 DESCRIPTION
1978 Associate statement with statement handle. This is done both on
1979 client and server sides. At this point the server parses given query
1980 and creates an internal structure to represent it.
1981 Next steps you may want to make:
1982 - find out if this statement returns a result set by
1983 calling mysql_stmt_field_count(), and get result set metadata
1984 with mysql_stmt_result_metadata(),
1985 - if query contains placeholders, bind input parameters to placeholders
1986 using mysql_stmt_bind_param(),
1987 - otherwise proceed directly to mysql_stmt_execute().
1989 IMPLEMENTATION NOTES
1990 - if this is a re-prepare of the statement, first close previous data
1991 structure on the server and free old statement data
1992 - then send the query to server and get back number of placeholders,
1993 number of columns in result set (if any), and result set metadata.
1994 At the same time allocate memory for input and output parameters
1995 to have less checks in mysql_stmt_bind_{param, result}.
1997 RETURN VALUES
1998 0 success
1999 !0 error
2002 int STDCALL
2003 mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
2005 MYSQL *mysql= stmt->mysql;
2006 DBUG_ENTER("mysql_stmt_prepare");
2008 if (!mysql)
2010 /* mysql can be reset in mysql_close called from mysql_reconnect */
2011 set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
2012 DBUG_RETURN(1);
2016 Reset the last error in any case: that would clear the statement
2017 if the previous prepare failed.
2019 stmt->last_errno= 0;
2020 stmt->last_error[0]= '\0';
2022 if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
2024 /* This is second prepare with another statement */
2025 uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
2027 if (reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT))
2028 DBUG_RETURN(1);
2030 These members must be reset for API to
2031 function in case of error or misuse.
2033 stmt->bind_param_done= stmt->bind_result_done= FALSE;
2034 stmt->param_count= stmt->field_count= 0;
2035 free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
2037 int4store(buff, stmt->stmt_id);
2040 Close statement in server
2042 If there was a 'use' result from another statement, or from
2043 mysql_use_result it won't be freed in mysql_stmt_free_result and
2044 we should get 'Commands out of sync' here.
2046 stmt->state= MYSQL_STMT_INIT_DONE;
2047 if (stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))
2049 set_stmt_errmsg(stmt, &mysql->net);
2050 DBUG_RETURN(1);
2054 if (stmt_command(mysql, COM_STMT_PREPARE, (const uchar*) query, length, stmt))
2056 set_stmt_errmsg(stmt, &mysql->net);
2057 DBUG_RETURN(1);
2060 if ((*mysql->methods->read_prepare_result)(mysql, stmt))
2062 set_stmt_errmsg(stmt, &mysql->net);
2063 DBUG_RETURN(1);
2067 alloc_root will return valid address even in case when param_count
2068 and field_count are zero. Thus we should never rely on stmt->bind
2069 or stmt->params when checking for existence of placeholders or
2070 result set.
2072 if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
2073 sizeof(MYSQL_BIND)*
2074 (stmt->param_count +
2075 stmt->field_count))))
2077 set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
2078 DBUG_RETURN(1);
2080 stmt->bind= stmt->params + stmt->param_count;
2081 stmt->state= MYSQL_STMT_PREPARE_DONE;
2082 DBUG_PRINT("info", ("Parameter count: %u", stmt->param_count));
2083 DBUG_RETURN(0);
2087 Get result set metadata from reply to mysql_stmt_execute.
2088 This is used mainly for SHOW commands, as metadata for these
2089 commands is sent only with result set.
2090 To be removed when all commands will fully support prepared mode.
2093 static void alloc_stmt_fields(MYSQL_STMT *stmt)
2095 MYSQL_FIELD *fields, *field, *end;
2096 MEM_ROOT *alloc= &stmt->mem_root;
2097 MYSQL *mysql= stmt->mysql->last_used_con;
2099 stmt->field_count= mysql->field_count;
2102 Get the field information for non-select statements
2103 like SHOW and DESCRIBE commands
2105 if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(alloc,
2106 sizeof(MYSQL_FIELD) *
2107 stmt->field_count)) ||
2108 !(stmt->bind= (MYSQL_BIND *) alloc_root(alloc,
2109 sizeof(MYSQL_BIND) *
2110 stmt->field_count)))
2112 set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
2113 return;
2116 for (fields= mysql->fields, end= fields+stmt->field_count,
2117 field= stmt->fields;
2118 field && fields < end; fields++, field++)
2120 field->db = strdup_root(alloc,fields->db);
2121 field->table = strdup_root(alloc,fields->table);
2122 field->org_table= strdup_root(alloc,fields->org_table);
2123 field->name = strdup_root(alloc,fields->name);
2124 field->org_name = strdup_root(alloc,fields->org_name);
2125 field->charsetnr= fields->charsetnr;
2126 field->length = fields->length;
2127 field->type = fields->type;
2128 field->flags = fields->flags;
2129 field->decimals = fields->decimals;
2130 field->def = fields->def ? strdup_root(alloc,fields->def): 0;
2131 field->max_length= 0;
2137 Update result set columns metadata if it was sent again in
2138 reply to COM_STMT_EXECUTE.
2140 @note If the new field count is different from the original one,
2141 an error is set and no update is performed.
2144 static void update_stmt_fields(MYSQL_STMT *stmt)
2146 MYSQL_FIELD *field= stmt->mysql->fields;
2147 MYSQL_FIELD *field_end= field + stmt->field_count;
2148 MYSQL_FIELD *stmt_field= stmt->fields;
2149 MYSQL_BIND *my_bind= stmt->bind_result_done ? stmt->bind : 0;
2151 if (stmt->field_count != stmt->mysql->field_count)
2154 The tables used in the statement were altered,
2155 and the query now returns a different number of columns.
2156 There is no way to continue without reallocating the bind
2157 array:
2158 - if the number of columns increased, mysql_stmt_fetch()
2159 will write beyond allocated memory
2160 - if the number of columns decreased, some user-bound
2161 buffers will be left unassigned without user knowing
2162 that.
2164 set_stmt_error(stmt, CR_NEW_STMT_METADATA, unknown_sqlstate, NULL);
2165 return;
2168 for (; field < field_end; ++field, ++stmt_field)
2170 stmt_field->charsetnr= field->charsetnr;
2171 stmt_field->length = field->length;
2172 stmt_field->type = field->type;
2173 stmt_field->flags = field->flags;
2174 stmt_field->decimals = field->decimals;
2175 if (my_bind)
2177 /* Ignore return value: it should be 0 if bind_result succeeded. */
2178 (void) setup_one_fetch_function(my_bind++, stmt_field);
2184 Returns prepared statement metadata in the form of a result set.
2186 SYNOPSIS
2187 mysql_stmt_result_metadata()
2188 stmt statement handle
2190 DESCRIPTION
2191 This function should be used after mysql_stmt_execute().
2192 You can safely check that prepared statement has a result set by calling
2193 mysql_stmt_field_count(): if number of fields is not zero, you can call
2194 this function to get fields metadata.
2195 Next steps you may want to make:
2196 - find out number of columns in result set by calling
2197 mysql_num_fields(res) (the same value is returned by
2198 mysql_stmt_field_count())
2199 - fetch metadata for any column with mysql_fetch_field,
2200 mysql_fetch_field_direct, mysql_fetch_fields, mysql_field_seek.
2201 - free returned MYSQL_RES structure with mysql_free_result.
2202 - proceed to binding of output parameters.
2204 RETURN
2205 NULL statement contains no result set or out of memory.
2206 In the latter case you can retreive error message
2207 with mysql_stmt_error.
2208 MYSQL_RES a result set with no rows
2211 MYSQL_RES * STDCALL
2212 mysql_stmt_result_metadata(MYSQL_STMT *stmt)
2214 MYSQL_RES *result;
2215 DBUG_ENTER("mysql_stmt_result_metadata");
2218 stmt->fields is only defined if stmt->field_count is not null;
2219 stmt->field_count is initialized in prepare.
2221 if (!stmt->field_count)
2222 DBUG_RETURN(0);
2224 if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result),
2225 MYF(MY_WME | MY_ZEROFILL))))
2227 set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
2228 DBUG_RETURN(0);
2231 result->methods= stmt->mysql->methods;
2232 result->eof= 1; /* Marker for buffered */
2233 result->fields= stmt->fields;
2234 result->field_count= stmt->field_count;
2235 /* The rest of members of 'result' was bzeroed inside malloc */
2236 DBUG_RETURN(result);
2241 Returns parameter columns meta information in the form of
2242 result set.
2244 SYNOPSYS
2245 mysql_stmt_param_metadata()
2246 stmt statement handle
2248 DESCRIPTION
2249 This function can be called after you prepared the statement handle
2250 with mysql_stmt_prepare().
2251 XXX: not implemented yet.
2253 RETURN
2254 MYSQL_RES on success, 0 if there is no metadata.
2255 Currently this function always returns 0.
2258 MYSQL_RES * STDCALL
2259 mysql_stmt_param_metadata(MYSQL_STMT *stmt)
2261 DBUG_ENTER("mysql_stmt_param_metadata");
2263 if (!stmt->param_count)
2264 DBUG_RETURN(0);
2267 TODO: Fix this when server sends the information.
2268 Till then keep a dummy prototype.
2270 DBUG_RETURN(0);
2274 /* Store type of parameter in network buffer. */
2276 static void store_param_type(unsigned char **pos, MYSQL_BIND *param)
2278 uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
2279 int2store(*pos, typecode);
2280 *pos+= 2;
2285 Functions to store parameter data in network packet.
2287 SYNOPSIS
2288 store_param_xxx()
2289 net MySQL NET connection
2290 param MySQL bind param
2292 DESCRIPTION
2293 These funtions are invoked from mysql_stmt_execute() by
2294 MYSQL_BIND::store_param_func pointer. This pointer is set once per
2295 many executions in mysql_stmt_bind_param(). The caller must ensure
2296 that network buffer have enough capacity to store parameter
2297 (MYSQL_BIND::buffer_length contains needed number of bytes).
2300 static void store_param_tinyint(NET *net, MYSQL_BIND *param)
2302 *(net->write_pos++)= *(uchar *) param->buffer;
2305 static void store_param_short(NET *net, MYSQL_BIND *param)
2307 short value= *(short*) param->buffer;
2308 int2store(net->write_pos,value);
2309 net->write_pos+=2;
2312 static void store_param_int32(NET *net, MYSQL_BIND *param)
2314 int32 value= *(int32*) param->buffer;
2315 int4store(net->write_pos,value);
2316 net->write_pos+=4;
2319 static void store_param_int64(NET *net, MYSQL_BIND *param)
2321 longlong value= *(longlong*) param->buffer;
2322 int8store(net->write_pos,value);
2323 net->write_pos+= 8;
2326 static void store_param_float(NET *net, MYSQL_BIND *param)
2328 float value= *(float*) param->buffer;
2329 float4store(net->write_pos, value);
2330 net->write_pos+= 4;
2333 static void store_param_double(NET *net, MYSQL_BIND *param)
2335 double value= *(double*) param->buffer;
2336 float8store(net->write_pos, value);
2337 net->write_pos+= 8;
2340 static void store_param_time(NET *net, MYSQL_BIND *param)
2342 MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
2343 char buff[MAX_TIME_REP_LENGTH], *pos;
2344 uint length;
2346 pos= buff+1;
2347 pos[0]= tm->neg ? 1: 0;
2348 int4store(pos+1, tm->day);
2349 pos[5]= (uchar) tm->hour;
2350 pos[6]= (uchar) tm->minute;
2351 pos[7]= (uchar) tm->second;
2352 int4store(pos+8, tm->second_part);
2353 if (tm->second_part)
2354 length= 12;
2355 else if (tm->hour || tm->minute || tm->second || tm->day)
2356 length= 8;
2357 else
2358 length= 0;
2359 buff[0]= (char) length++;
2360 memcpy((char *)net->write_pos, buff, length);
2361 net->write_pos+= length;
2364 static void net_store_datetime(NET *net, MYSQL_TIME *tm)
2366 char buff[MAX_DATETIME_REP_LENGTH], *pos;
2367 uint length;
2369 pos= buff+1;
2371 int2store(pos, tm->year);
2372 pos[2]= (uchar) tm->month;
2373 pos[3]= (uchar) tm->day;
2374 pos[4]= (uchar) tm->hour;
2375 pos[5]= (uchar) tm->minute;
2376 pos[6]= (uchar) tm->second;
2377 int4store(pos+7, tm->second_part);
2378 if (tm->second_part)
2379 length= 11;
2380 else if (tm->hour || tm->minute || tm->second)
2381 length= 7;
2382 else if (tm->year || tm->month || tm->day)
2383 length= 4;
2384 else
2385 length= 0;
2386 buff[0]= (char) length++;
2387 memcpy((char *)net->write_pos, buff, length);
2388 net->write_pos+= length;
2391 static void store_param_date(NET *net, MYSQL_BIND *param)
2393 MYSQL_TIME tm= *((MYSQL_TIME *) param->buffer);
2394 tm.hour= tm.minute= tm.second= tm.second_part= 0;
2395 net_store_datetime(net, &tm);
2398 static void store_param_datetime(NET *net, MYSQL_BIND *param)
2400 MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
2401 net_store_datetime(net, tm);
2404 static void store_param_str(NET *net, MYSQL_BIND *param)
2406 /* param->length is always set in mysql_stmt_bind_param */
2407 ulong length= *param->length;
2408 uchar *to= net_store_length(net->write_pos, length);
2409 memcpy(to, param->buffer, length);
2410 net->write_pos= to+length;
2415 Mark if the parameter is NULL.
2417 SYNOPSIS
2418 store_param_null()
2419 net MySQL NET connection
2420 param MySQL bind param
2422 DESCRIPTION
2423 A data package starts with a string of bits where we set a bit
2424 if a parameter is NULL. Unlike bit string in result set row, here
2425 we don't have reserved bits for OK/error packet.
2428 static void store_param_null(NET *net, MYSQL_BIND *param)
2430 uint pos= param->param_number;
2431 net->buff[pos/8]|= (uchar) (1 << (pos & 7));
2436 Store one parameter in network packet: data is read from
2437 client buffer and saved in network packet by means of one
2438 of store_param_xxxx functions.
2441 static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
2443 NET *net= &stmt->mysql->net;
2444 DBUG_ENTER("store_param");
2445 DBUG_PRINT("enter",("type: %d buffer: 0x%lx length: %lu is_null: %d",
2446 param->buffer_type,
2447 (long) (param->buffer ? param->buffer : NullS),
2448 *param->length, *param->is_null));
2450 if (*param->is_null)
2451 store_param_null(net, param);
2452 else
2455 Param->length should ALWAYS point to the correct length for the type
2456 Either to the length pointer given by the user or param->buffer_length
2458 if ((my_realloc_str(net, *param->length)))
2460 set_stmt_errmsg(stmt, net);
2461 DBUG_RETURN(1);
2463 (*param->store_param_func)(net, param);
2465 DBUG_RETURN(0);
2470 Auxilary function to send COM_STMT_EXECUTE packet to server and read reply.
2471 Used from cli_stmt_execute, which is in turn used by mysql_stmt_execute.
2474 static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
2476 MYSQL *mysql= stmt->mysql;
2477 NET *net= &mysql->net;
2478 uchar buff[4 /* size of stmt id */ +
2479 5 /* execution flags */];
2480 my_bool res;
2481 DBUG_ENTER("execute");
2482 DBUG_DUMP("packet", (uchar *) packet, length);
2484 mysql->last_used_con= mysql;
2485 int4store(buff, stmt->stmt_id); /* Send stmt id to server */
2486 buff[4]= (char) stmt->flags;
2487 int4store(buff+5, 1); /* iteration count */
2489 res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
2490 (uchar*) packet, length, 1, stmt) ||
2491 (*mysql->methods->read_query_result)(mysql));
2492 stmt->affected_rows= mysql->affected_rows;
2493 stmt->server_status= mysql->server_status;
2494 stmt->insert_id= mysql->insert_id;
2495 if (res)
2498 Don't set stmt error if stmt->mysql is NULL, as the error in this case
2499 has already been set by mysql_prune_stmt_list().
2501 if (stmt->mysql)
2502 set_stmt_errmsg(stmt, net);
2503 DBUG_RETURN(1);
2505 else if (mysql->status == MYSQL_STATUS_GET_RESULT)
2506 stmt->mysql->status= MYSQL_STATUS_STATEMENT_GET_RESULT;
2507 DBUG_RETURN(0);
2511 int cli_stmt_execute(MYSQL_STMT *stmt)
2513 DBUG_ENTER("cli_stmt_execute");
2515 if (stmt->param_count)
2517 MYSQL *mysql= stmt->mysql;
2518 NET *net= &mysql->net;
2519 MYSQL_BIND *param, *param_end;
2520 char *param_data;
2521 ulong length;
2522 uint null_count;
2523 my_bool result;
2525 if (!stmt->bind_param_done)
2527 set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate, NULL);
2528 DBUG_RETURN(1);
2530 if (mysql->status != MYSQL_STATUS_READY ||
2531 mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
2533 set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
2534 DBUG_RETURN(1);
2537 net_clear(net, 1); /* Sets net->write_pos */
2538 /* Reserve place for null-marker bytes */
2539 null_count= (stmt->param_count+7) /8;
2540 if (my_realloc_str(net, null_count + 1))
2542 set_stmt_errmsg(stmt, net);
2543 DBUG_RETURN(1);
2545 bzero((char*) net->write_pos, null_count);
2546 net->write_pos+= null_count;
2547 param_end= stmt->params + stmt->param_count;
2549 /* In case if buffers (type) altered, indicate to server */
2550 *(net->write_pos)++= (uchar) stmt->send_types_to_server;
2551 if (stmt->send_types_to_server)
2553 if (my_realloc_str(net, 2 * stmt->param_count))
2555 set_stmt_errmsg(stmt, net);
2556 DBUG_RETURN(1);
2559 Store types of parameters in first in first package
2560 that is sent to the server.
2562 for (param= stmt->params; param < param_end ; param++)
2563 store_param_type(&net->write_pos, param);
2566 for (param= stmt->params; param < param_end; param++)
2568 /* check if mysql_stmt_send_long_data() was used */
2569 if (param->long_data_used)
2570 param->long_data_used= 0; /* Clear for next execute call */
2571 else if (store_param(stmt, param))
2572 DBUG_RETURN(1);
2574 length= (ulong) (net->write_pos - net->buff);
2575 /* TODO: Look into avoding the following memdup */
2576 if (!(param_data= my_memdup(net->buff, length, MYF(0))))
2578 set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
2579 DBUG_RETURN(1);
2581 result= execute(stmt, param_data, length);
2582 stmt->send_types_to_server=0;
2583 my_free(param_data, MYF(MY_WME));
2584 DBUG_RETURN(result);
2586 DBUG_RETURN((int) execute(stmt,0,0));
2590 Read one row from buffered result set. Result set is created by prior
2591 call to mysql_stmt_store_result().
2592 SYNOPSIS
2593 stmt_read_row_buffered()
2595 RETURN VALUE
2596 0 - success; *row is set to valid row pointer (row data
2597 is stored in result set buffer)
2598 MYSQL_NO_DATA - end of result set. *row is set to NULL
2601 static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
2603 if (stmt->data_cursor)
2605 *row= (uchar *) stmt->data_cursor->data;
2606 stmt->data_cursor= stmt->data_cursor->next;
2607 return 0;
2609 *row= 0;
2610 return MYSQL_NO_DATA;
2614 Read one row from network: unbuffered non-cursor fetch.
2615 If last row was read, or error occured, erase this statement
2616 from record pointing to object unbuffered fetch is performed from.
2618 SYNOPSIS
2619 stmt_read_row_unbuffered()
2620 stmt statement handle
2621 row pointer to write pointer to row data;
2623 RETURN VALUE
2624 0 - success; *row contains valid address of a row;
2625 row data is stored in network buffer
2626 1 - error; error code is written to
2627 stmt->last_{errno,error}; *row is not changed
2628 MYSQL_NO_DATA - end of file was read from network;
2629 *row is set to NULL
2632 static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
2634 int rc= 1;
2635 MYSQL *mysql= stmt->mysql;
2637 This function won't be called if stmt->field_count is zero
2638 or execution wasn't done: this is ensured by mysql_stmt_execute.
2640 if (!mysql)
2642 set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
2643 return 1;
2645 if (mysql->status != MYSQL_STATUS_STATEMENT_GET_RESULT)
2647 set_stmt_error(stmt, stmt->unbuffered_fetch_cancelled ?
2648 CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
2649 unknown_sqlstate, NULL);
2650 goto error;
2652 if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) row))
2654 set_stmt_errmsg(stmt, &mysql->net);
2656 If there was an error, there are no more pending rows:
2657 reset statement status to not hang up in following
2658 mysql_stmt_close (it will try to flush result set before
2659 closing the statement).
2661 mysql->status= MYSQL_STATUS_READY;
2662 goto error;
2664 if (!*row)
2666 mysql->status= MYSQL_STATUS_READY;
2667 rc= MYSQL_NO_DATA;
2668 goto error;
2670 return 0;
2671 error:
2672 if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
2673 mysql->unbuffered_fetch_owner= 0;
2674 return rc;
2679 Fetch statement row using server side cursor.
2681 SYNOPSIS
2682 stmt_read_row_from_cursor()
2684 RETURN VALUE
2685 0 success
2686 1 error
2687 MYSQL_NO_DATA end of data
2690 static int
2691 stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
2693 if (stmt->data_cursor)
2694 return stmt_read_row_buffered(stmt, row);
2695 if (stmt->server_status & SERVER_STATUS_LAST_ROW_SENT)
2696 stmt->server_status &= ~SERVER_STATUS_LAST_ROW_SENT;
2697 else
2699 MYSQL *mysql= stmt->mysql;
2700 NET *net= &mysql->net;
2701 MYSQL_DATA *result= &stmt->result;
2702 uchar buff[4 /* statement id */ +
2703 4 /* number of rows to fetch */];
2705 free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
2706 result->data= NULL;
2707 result->rows= 0;
2708 /* Send row request to the server */
2709 int4store(buff, stmt->stmt_id);
2710 int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
2711 if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
2712 buff, sizeof(buff), (uchar*) 0, 0,
2713 1, stmt))
2716 Don't set stmt error if stmt->mysql is NULL, as the error in this case
2717 has already been set by mysql_prune_stmt_list().
2719 if (stmt->mysql)
2720 set_stmt_errmsg(stmt, net);
2721 return 1;
2723 if ((*mysql->methods->read_rows_from_cursor)(stmt))
2724 return 1;
2725 stmt->server_status= mysql->server_status;
2727 stmt->data_cursor= result->data;
2728 return stmt_read_row_buffered(stmt, row);
2730 *row= 0;
2731 return MYSQL_NO_DATA;
2736 Default read row function to not SIGSEGV in client in
2737 case of wrong sequence of API calls.
2740 static int
2741 stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)),
2742 unsigned char **row __attribute__((unused)))
2744 return MYSQL_NO_DATA;
2747 static int
2748 stmt_read_row_no_result_set(MYSQL_STMT *stmt __attribute__((unused)),
2749 unsigned char **row __attribute__((unused)))
2751 set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate, NULL);
2752 return 1;
2757 Get/set statement attributes
2759 SYNOPSIS
2760 mysql_stmt_attr_get()
2761 mysql_stmt_attr_set()
2763 attr_type statement attribute
2764 value casted to const void * pointer to value.
2766 RETURN VALUE
2767 0 success
2768 !0 wrong attribute type
2771 my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
2772 enum enum_stmt_attr_type attr_type,
2773 const void *value)
2775 switch (attr_type) {
2776 case STMT_ATTR_UPDATE_MAX_LENGTH:
2777 stmt->update_max_length= value ? *(const my_bool*) value : 0;
2778 break;
2779 case STMT_ATTR_CURSOR_TYPE:
2781 ulong cursor_type;
2782 cursor_type= value ? *(ulong*) value : 0UL;
2783 if (cursor_type > (ulong) CURSOR_TYPE_READ_ONLY)
2784 goto err_not_implemented;
2785 stmt->flags= cursor_type;
2786 break;
2788 case STMT_ATTR_PREFETCH_ROWS:
2790 ulong prefetch_rows= value ? *(ulong*) value : DEFAULT_PREFETCH_ROWS;
2791 if (value == 0)
2792 return TRUE;
2793 stmt->prefetch_rows= prefetch_rows;
2794 break;
2796 default:
2797 goto err_not_implemented;
2799 return FALSE;
2800 err_not_implemented:
2801 set_stmt_error(stmt, CR_NOT_IMPLEMENTED, unknown_sqlstate, NULL);
2802 return TRUE;
2806 my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
2807 enum enum_stmt_attr_type attr_type,
2808 void *value)
2810 switch (attr_type) {
2811 case STMT_ATTR_UPDATE_MAX_LENGTH:
2812 *(my_bool*) value= stmt->update_max_length;
2813 break;
2814 case STMT_ATTR_CURSOR_TYPE:
2815 *(ulong*) value= stmt->flags;
2816 break;
2817 case STMT_ATTR_PREFETCH_ROWS:
2818 *(ulong*) value= stmt->prefetch_rows;
2819 break;
2820 default:
2821 return TRUE;
2823 return FALSE;
2828 Update statement result set metadata from with the new field
2829 information sent during statement execute.
2831 @pre mysql->field_count is not zero
2833 @retval TRUE if error: out of memory or the new
2834 result set has a different number of columns
2835 @retval FALSE success
2838 static void reinit_result_set_metadata(MYSQL_STMT *stmt)
2840 /* Server has sent result set metadata */
2841 if (stmt->field_count == 0)
2844 This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
2845 prepared statements can't send result set metadata for these queries
2846 on prepare stage. Read it now.
2848 alloc_stmt_fields(stmt);
2850 else
2853 Update result set metadata if it for some reason changed between
2854 prepare and execute, i.e.:
2855 - in case of 'SELECT ?' we don't know column type unless data was
2856 supplied to mysql_stmt_execute, so updated column type is sent
2857 now.
2858 - if data dictionary changed between prepare and execute, for
2859 example a table used in the query was altered.
2860 Note, that now (4.1.3) we always send metadata in reply to
2861 COM_STMT_EXECUTE (even if it is not necessary), so either this or
2862 previous branch always works.
2863 TODO: send metadata only when it's really necessary and add a warning
2864 'Metadata changed' when it's sent twice.
2866 update_stmt_fields(stmt);
2872 Send placeholders data to server (if there are placeholders)
2873 and execute prepared statement.
2875 SYNOPSIS
2876 mysql_stmt_execute()
2877 stmt statement handle. The handle must be created
2878 with mysql_stmt_init() and prepared with
2879 mysql_stmt_prepare(). If there are placeholders
2880 in the statement they must be bound to local
2881 variables with mysql_stmt_bind_param().
2883 DESCRIPTION
2884 This function will automatically flush pending result
2885 set (if there is one), send parameters data to the server
2886 and read result of statement execution.
2887 If previous result set was cached with mysql_stmt_store_result()
2888 it will also be freed in the beginning of this call.
2889 The server can return 3 types of responses to this command:
2890 - error, can be retrieved with mysql_stmt_error()
2891 - ok, no result set pending. In this case we just update
2892 stmt->insert_id and stmt->affected_rows.
2893 - the query returns a result set: there could be 0 .. N
2894 rows in it. In this case the server can also send updated
2895 result set metadata.
2897 Next steps you may want to make:
2898 - find out if there is result set with mysql_stmt_field_count().
2899 If there is one:
2900 - optionally, cache entire result set on client to unblock
2901 connection with mysql_stmt_store_result()
2902 - bind client variables to result set columns and start read rows
2903 with mysql_stmt_fetch().
2904 - reset statement with mysql_stmt_reset() or close it with
2905 mysql_stmt_close()
2906 Otherwise:
2907 - find out last insert id and number of affected rows with
2908 mysql_stmt_insert_id(), mysql_stmt_affected_rows()
2910 RETURN
2911 0 success
2912 1 error, message can be retrieved with mysql_stmt_error().
2915 int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
2917 MYSQL *mysql= stmt->mysql;
2918 DBUG_ENTER("mysql_stmt_execute");
2920 if (!mysql)
2922 /* Error is already set in mysql_detatch_stmt_list */
2923 DBUG_RETURN(1);
2926 if (reset_stmt_handle(stmt, RESET_STORE_RESULT | RESET_CLEAR_ERROR))
2927 DBUG_RETURN(1);
2929 No need to check for stmt->state: if the statement wasn't
2930 prepared we'll get 'unknown statement handler' error from server.
2932 if (mysql->methods->stmt_execute(stmt))
2933 DBUG_RETURN(1);
2934 stmt->state= MYSQL_STMT_EXECUTE_DONE;
2935 if (mysql->field_count)
2937 reinit_result_set_metadata(stmt);
2938 if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
2940 mysql->status= MYSQL_STATUS_READY;
2941 stmt->read_row_func= stmt_read_row_from_cursor;
2943 else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
2946 This is a single-row result set, a result set with no rows, EXPLAIN,
2947 SHOW VARIABLES, or some other command which either a) bypasses the
2948 cursors framework in the server and writes rows directly to the
2949 network or b) is more efficient if all (few) result set rows are
2950 precached on client and server's resources are freed.
2952 mysql_stmt_store_result(stmt);
2954 else
2956 stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
2957 stmt->unbuffered_fetch_cancelled= FALSE;
2958 stmt->read_row_func= stmt_read_row_unbuffered;
2961 DBUG_RETURN(test(stmt->last_errno));
2966 Return total parameters count in the statement
2969 ulong STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt)
2971 DBUG_ENTER("mysql_stmt_param_count");
2972 DBUG_RETURN(stmt->param_count);
2976 Return total affected rows from the last statement
2979 my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
2981 return stmt->affected_rows;
2986 Returns the number of result columns for the most recent query
2987 run on this statement.
2990 unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
2992 return stmt->field_count;
2996 Return last inserted id for auto_increment columns.
2998 SYNOPSIS
2999 mysql_stmt_insert_id()
3000 stmt statement handle
3002 DESCRIPTION
3003 Current implementation of this call has a caveat: stmt->insert_id is
3004 unconditionally updated from mysql->insert_id in the end of each
3005 mysql_stmt_execute(). This works OK if mysql->insert_id contains new
3006 value (sent in reply to mysql_stmt_execute()), otherwise stmt->insert_id
3007 value gets undefined, as it's updated from some arbitrary value saved in
3008 connection structure during some other call.
3011 my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
3013 return stmt->insert_id;
3017 static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */
3018 static my_bool int_is_null_false= 0;
3022 Set up input data buffers for a statement.
3024 SYNOPSIS
3025 mysql_stmt_bind_param()
3026 stmt statement handle
3027 The statement must be prepared with mysql_stmt_prepare().
3028 my_bind Array of mysql_stmt_param_count() bind parameters.
3029 This function doesn't check that size of this argument
3030 is >= mysql_stmt_field_count(): it's user's responsibility.
3032 DESCRIPTION
3033 Use this call after mysql_stmt_prepare() to bind user variables to
3034 placeholders.
3035 Each element of bind array stands for a placeholder. Placeholders
3036 are counted from 0. For example statement
3037 'INSERT INTO t (a, b) VALUES (?, ?)'
3038 contains two placeholders, and for such statement you should supply
3039 bind array of two elements (MYSQL_BIND bind[2]).
3041 By properly initializing bind array you can bind virtually any
3042 C language type to statement's placeholders:
3043 First, it's strongly recommended to always zero-initialize entire
3044 bind structure before setting its members. This will both shorten
3045 your application code and make it robust to future extensions of
3046 MYSQL_BIND structure.
3047 Then you need to assign typecode of your application buffer to
3048 MYSQL_BIND::buffer_type. The following typecodes with their
3049 correspondence to C language types are supported:
3050 MYSQL_TYPE_TINY for 8-bit integer variables. Normally it's
3051 'signed char' and 'unsigned char';
3052 MYSQL_TYPE_SHORT for 16-bit signed and unsigned variables. This
3053 is usually 'short' and 'unsigned short';
3054 MYSQL_TYPE_LONG for 32-bit signed and unsigned variables. It
3055 corresponds to 'int' and 'unsigned int' on
3056 vast majority of platforms. On IA-32 and some
3057 other 32-bit systems you can also use 'long'
3058 here;
3059 MYSQL_TYPE_LONGLONG 64-bit signed or unsigned integer. Stands for
3060 '[unsigned] long long' on most platforms;
3061 MYSQL_TYPE_FLOAT 32-bit floating point type, 'float' on most
3062 systems;
3063 MYSQL_TYPE_DOUBLE 64-bit floating point type, 'double' on most
3064 systems;
3065 MYSQL_TYPE_TIME broken-down time stored in MYSQL_TIME
3066 structure
3067 MYSQL_TYPE_DATE date stored in MYSQL_TIME structure
3068 MYSQL_TYPE_DATETIME datetime stored in MYSQL_TIME structure See
3069 more on how to use these types for sending
3070 dates and times below;
3071 MYSQL_TYPE_STRING character string, assumed to be in
3072 character-set-client. If character set of
3073 client is not equal to character set of
3074 column, value for this placeholder will be
3075 converted to destination character set before
3076 insert.
3077 MYSQL_TYPE_BLOB sequence of bytes. This sequence is assumed to
3078 be in binary character set (which is the same
3079 as no particular character set), and is never
3080 converted to any other character set. See also
3081 notes about supplying string/blob length
3082 below.
3083 MYSQL_TYPE_NULL special typecode for binding nulls.
3084 These C/C++ types are not supported yet by the API: long double,
3085 bool.
3087 As you can see from the list above, it's responsibility of
3088 application programmer to ensure that chosen typecode properly
3089 corresponds to host language type. For example on all platforms
3090 where we build MySQL packages (as of MySQL 4.1.4) int is a 32-bit
3091 type. So for int you can always assume that proper typecode is
3092 MYSQL_TYPE_LONG (however queer it sounds, the name is legacy of the
3093 old MySQL API). In contrary sizeof(long) can be 4 or 8 8-bit bytes,
3094 depending on platform.
3096 TODO: provide client typedefs for each integer and floating point
3097 typecode, i. e. int8, uint8, float32, etc.
3099 Once typecode was set, it's necessary to assign MYSQL_BIND::buffer
3100 to point to the buffer of given type. Finally, additional actions
3101 may be taken for some types or use cases:
3103 Binding integer types.
3104 For integer types you might also need to set MYSQL_BIND::is_unsigned
3105 member. Set it to TRUE when binding unsigned char, unsigned short,
3106 unsigned int, unsigned long, unsigned long long.
3108 Binding floating point types.
3109 For floating point types you just need to set
3110 MYSQL_BIND::buffer_type and MYSQL_BIND::buffer. The rest of the
3111 members should be zero-initialized.
3113 Binding NULLs.
3114 You might have a column always NULL, never NULL, or sometimes
3115 NULL. For an always NULL column set MYSQL_BIND::buffer_type to
3116 MYSQL_TYPE_NULL. The rest of the members just need to be
3117 zero-initialized. For never NULL columns set
3118 MYSQL_BIND::is_null to 0, or this has already been done if you
3119 zero-initialized the entire structure. If you set
3120 MYSQL_TYPE::is_null to point to an application buffer of type
3121 'my_bool', then this buffer will be checked on each execution:
3122 this way you can set the buffer to TRUE, or any non-0 value for
3123 NULLs, and to FALSE or 0 for not NULL data.
3125 Binding text strings and sequences of bytes.
3126 For strings, in addition to MYSQL_BIND::buffer_type and
3127 MYSQL_BIND::buffer you need to set MYSQL_BIND::length or
3128 MYSQL_BIND::buffer_length. If 'length' is set, 'buffer_length'
3129 is ignored. 'buffer_length' member should be used when size of
3130 string doesn't change between executions. If you want to vary
3131 buffer length for each value, set 'length' to point to an
3132 application buffer of type 'unsigned long' and set this long to
3133 length of the string before each mysql_stmt_execute().
3135 Binding dates and times.
3136 For binding dates and times prepared statements API provides
3137 clients with MYSQL_TIME structure. A pointer to instance of this
3138 structure should be assigned to MYSQL_BIND::buffer whenever
3139 MYSQL_TYPE_TIME, MYSQL_TYPE_DATE, MYSQL_TYPE_DATETIME typecodes
3140 are used. When typecode is MYSQL_TYPE_TIME, only members
3141 'hour', 'minute', 'second' and 'neg' (is time offset negative)
3142 are used. These members only will be sent to the server.
3143 MYSQL_TYPE_DATE implies use of 'year', 'month', 'day', 'neg'.
3144 MYSQL_TYPE_DATETIME utilizes both parts of MYSQL_TIME structure.
3145 You don't have to set MYSQL_TIME::time_type member: it's not
3146 used when sending data to the server, typecode information is
3147 enough. 'second_part' member can hold microsecond precision of
3148 time value, but now it's only supported on protocol level: you
3149 can't store microsecond in a column, or use in temporal
3150 calculations. However, if you send a time value with microsecond
3151 part for 'SELECT ?', statement, you'll get it back unchanged
3152 from the server.
3154 Data conversion.
3155 If conversion from host language type to data representation,
3156 corresponding to SQL type, is required it's done on the server.
3157 Data truncation is possible when conversion is lossy. For
3158 example, if you supply MYSQL_TYPE_DATETIME value out of valid
3159 SQL type TIMESTAMP range, the same conversion will be applied as
3160 if this value would have been sent as string in the old
3161 protocol. TODO: document how the server will behave in case of
3162 truncation/data loss.
3164 After variables were bound, you can repeatedly set/change their
3165 values and mysql_stmt_execute() the statement.
3167 See also: mysql_stmt_send_long_data() for sending long text/blob
3168 data in pieces, examples in tests/mysql_client_test.c.
3169 Next steps you might want to make:
3170 - execute statement with mysql_stmt_execute(),
3171 - reset statement using mysql_stmt_reset() or reprepare it with
3172 another query using mysql_stmt_prepare()
3173 - close statement with mysql_stmt_close().
3175 IMPLEMENTATION
3176 The function copies given bind array to internal storage of the
3177 statement, and sets up typecode-specific handlers to perform
3178 serialization of bound data. This means that although you don't need
3179 to call this routine after each assignment to bind buffers, you
3180 need to call it each time you change parameter typecodes, or other
3181 members of MYSQL_BIND array.
3182 This is a pure local call. Data types of client buffers are sent
3183 along with buffers' data at first execution of the statement.
3185 RETURN
3186 0 success
3187 1 error, can be retrieved with mysql_stmt_error.
3190 my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *my_bind)
3192 uint count=0;
3193 MYSQL_BIND *param, *end;
3194 DBUG_ENTER("mysql_stmt_bind_param");
3196 if (!stmt->param_count)
3198 if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
3200 set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate, NULL);
3201 DBUG_RETURN(1);
3203 DBUG_RETURN(0);
3206 /* Allocated on prepare */
3207 memcpy((char*) stmt->params, (char*) my_bind,
3208 sizeof(MYSQL_BIND) * stmt->param_count);
3210 for (param= stmt->params, end= param+stmt->param_count;
3211 param < end ;
3212 param++)
3214 param->param_number= count++;
3215 param->long_data_used= 0;
3217 /* If param->is_null is not set, then the value can never be NULL */
3218 if (!param->is_null)
3219 param->is_null= &int_is_null_false;
3221 /* Setup data copy functions for the different supported types */
3222 switch (param->buffer_type) {
3223 case MYSQL_TYPE_NULL:
3224 param->is_null= &int_is_null_true;
3225 break;
3226 case MYSQL_TYPE_TINY:
3227 /* Force param->length as this is fixed for this type */
3228 param->length= &param->buffer_length;
3229 param->buffer_length= 1;
3230 param->store_param_func= store_param_tinyint;
3231 break;
3232 case MYSQL_TYPE_SHORT:
3233 param->length= &param->buffer_length;
3234 param->buffer_length= 2;
3235 param->store_param_func= store_param_short;
3236 break;
3237 case MYSQL_TYPE_LONG:
3238 param->length= &param->buffer_length;
3239 param->buffer_length= 4;
3240 param->store_param_func= store_param_int32;
3241 break;
3242 case MYSQL_TYPE_LONGLONG:
3243 param->length= &param->buffer_length;
3244 param->buffer_length= 8;
3245 param->store_param_func= store_param_int64;
3246 break;
3247 case MYSQL_TYPE_FLOAT:
3248 param->length= &param->buffer_length;
3249 param->buffer_length= 4;
3250 param->store_param_func= store_param_float;
3251 break;
3252 case MYSQL_TYPE_DOUBLE:
3253 param->length= &param->buffer_length;
3254 param->buffer_length= 8;
3255 param->store_param_func= store_param_double;
3256 break;
3257 case MYSQL_TYPE_TIME:
3258 param->store_param_func= store_param_time;
3259 param->buffer_length= MAX_TIME_REP_LENGTH;
3260 break;
3261 case MYSQL_TYPE_DATE:
3262 param->store_param_func= store_param_date;
3263 param->buffer_length= MAX_DATE_REP_LENGTH;
3264 break;
3265 case MYSQL_TYPE_DATETIME:
3266 case MYSQL_TYPE_TIMESTAMP:
3267 param->store_param_func= store_param_datetime;
3268 param->buffer_length= MAX_DATETIME_REP_LENGTH;
3269 break;
3270 case MYSQL_TYPE_TINY_BLOB:
3271 case MYSQL_TYPE_MEDIUM_BLOB:
3272 case MYSQL_TYPE_LONG_BLOB:
3273 case MYSQL_TYPE_BLOB:
3274 case MYSQL_TYPE_VARCHAR:
3275 case MYSQL_TYPE_VAR_STRING:
3276 case MYSQL_TYPE_STRING:
3277 case MYSQL_TYPE_DECIMAL:
3278 case MYSQL_TYPE_NEWDECIMAL:
3279 param->store_param_func= store_param_str;
3281 For variable length types user must set either length or
3282 buffer_length.
3284 break;
3285 default:
3286 strmov(stmt->sqlstate, unknown_sqlstate);
3287 sprintf(stmt->last_error,
3288 ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
3289 param->buffer_type, count);
3290 DBUG_RETURN(1);
3293 If param->length is not given, change it to point to buffer_length.
3294 This way we can always use *param->length to get the length of data
3296 if (!param->length)
3297 param->length= &param->buffer_length;
3299 /* We have to send/resend type information to MySQL */
3300 stmt->send_types_to_server= TRUE;
3301 stmt->bind_param_done= TRUE;
3302 DBUG_RETURN(0);
3306 /********************************************************************
3307 Long data implementation
3308 *********************************************************************/
3311 Send long data in pieces to the server
3313 SYNOPSIS
3314 mysql_stmt_send_long_data()
3315 stmt Statement handler
3316 param_number Parameter number (0 - N-1)
3317 data Data to send to server
3318 length Length of data to send (may be 0)
3320 DESCRIPTION
3321 This call can be used repeatedly to send long data in pieces
3322 for any string/binary placeholder. Data supplied for
3323 a placeholder is saved at server side till execute, and then
3324 used instead of value from MYSQL_BIND object. More precisely,
3325 if long data for a parameter was supplied, MYSQL_BIND object
3326 corresponding to this parameter is not sent to server. In the
3327 end of execution long data states of placeholders are reset,
3328 so next time values of such placeholders will be taken again
3329 from MYSQL_BIND array.
3330 The server does not reply to this call: if there was an error
3331 in data handling (which now only can happen if server run out
3332 of memory) it would be returned in reply to
3333 mysql_stmt_execute().
3334 You should choose type of long data carefully if you care
3335 about character set conversions performed by server when the
3336 statement is executed. No conversion is performed at all for
3337 MYSQL_TYPE_BLOB and other binary typecodes. For
3338 MYSQL_TYPE_STRING and the rest of text placeholders data is
3339 converted from client character set to character set of
3340 connection. If these character sets are different, this
3341 conversion may require additional memory at server, equal to
3342 total size of supplied pieces.
3344 RETURN VALUES
3345 0 ok
3346 1 error
3349 my_bool STDCALL
3350 mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
3351 const char *data, ulong length)
3353 MYSQL_BIND *param;
3354 DBUG_ENTER("mysql_stmt_send_long_data");
3355 DBUG_ASSERT(stmt != 0);
3356 DBUG_PRINT("enter",("param no: %d data: 0x%lx, length : %ld",
3357 param_number, (long) data, length));
3360 We only need to check for stmt->param_count, if it's not null
3361 prepare was done.
3363 if (param_number >= stmt->param_count)
3365 set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL);
3366 DBUG_RETURN(1);
3369 param= stmt->params+param_number;
3370 if (!IS_LONGDATA(param->buffer_type))
3372 /* Long data handling should be used only for string/binary types */
3373 strmov(stmt->sqlstate, unknown_sqlstate);
3374 sprintf(stmt->last_error, ER(stmt->last_errno= CR_INVALID_BUFFER_USE),
3375 param->param_number);
3376 DBUG_RETURN(1);
3380 Send long data packet if there is data or we're sending long data
3381 for the first time.
3383 if (length || param->long_data_used == 0)
3385 MYSQL *mysql= stmt->mysql;
3386 /* Packet header: stmt id (4 bytes), param no (2 bytes) */
3387 uchar buff[MYSQL_LONG_DATA_HEADER];
3389 int4store(buff, stmt->stmt_id);
3390 int2store(buff + 4, param_number);
3391 param->long_data_used= 1;
3394 Note that we don't get any ok packet from the server in this case
3395 This is intentional to save bandwidth.
3397 if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA,
3398 buff, sizeof(buff), (uchar*) data,
3399 length, 1, stmt))
3402 Don't set stmt error if stmt->mysql is NULL, as the error in this case
3403 has already been set by mysql_prune_stmt_list().
3405 if (stmt->mysql)
3406 set_stmt_errmsg(stmt, &mysql->net);
3407 DBUG_RETURN(1);
3410 DBUG_RETURN(0);
3414 /********************************************************************
3415 Fetch and conversion of result set rows (binary protocol).
3416 *********************************************************************/
3419 Read date, (time, datetime) value from network buffer and store it
3420 in MYSQL_TIME structure.
3422 SYNOPSIS
3423 read_binary_{date,time,datetime}()
3424 tm MYSQL_TIME structure to fill
3425 pos pointer to current position in network buffer.
3426 These functions increase pos to point to the beginning of the
3427 next column.
3429 Auxiliary functions to read time (date, datetime) values from network
3430 buffer and store in MYSQL_TIME structure. Jointly used by conversion
3431 and no-conversion fetching.
3434 static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
3436 /* net_field_length will set pos to the first byte of data */
3437 uint length= net_field_length(pos);
3439 if (length)
3441 uchar *to= *pos;
3442 tm->neg= to[0];
3444 tm->day= (ulong) sint4korr(to+1);
3445 tm->hour= (uint) to[5];
3446 tm->minute= (uint) to[6];
3447 tm->second= (uint) to[7];
3448 tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
3449 tm->year= tm->month= 0;
3450 if (tm->day)
3452 /* Convert days to hours at once */
3453 tm->hour+= tm->day*24;
3454 tm->day= 0;
3456 tm->time_type= MYSQL_TIMESTAMP_TIME;
3458 *pos+= length;
3460 else
3461 set_zero_time(tm, MYSQL_TIMESTAMP_TIME);
3464 static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
3466 uint length= net_field_length(pos);
3468 if (length)
3470 uchar *to= *pos;
3472 tm->neg= 0;
3473 tm->year= (uint) sint2korr(to);
3474 tm->month= (uint) to[2];
3475 tm->day= (uint) to[3];
3477 if (length > 4)
3479 tm->hour= (uint) to[4];
3480 tm->minute= (uint) to[5];
3481 tm->second= (uint) to[6];
3483 else
3484 tm->hour= tm->minute= tm->second= 0;
3485 tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
3486 tm->time_type= MYSQL_TIMESTAMP_DATETIME;
3488 *pos+= length;
3490 else
3491 set_zero_time(tm, MYSQL_TIMESTAMP_DATETIME);
3494 static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
3496 uint length= net_field_length(pos);
3498 if (length)
3500 uchar *to= *pos;
3501 tm->year = (uint) sint2korr(to);
3502 tm->month= (uint) to[2];
3503 tm->day= (uint) to[3];
3505 tm->hour= tm->minute= tm->second= 0;
3506 tm->second_part= 0;
3507 tm->neg= 0;
3508 tm->time_type= MYSQL_TIMESTAMP_DATE;
3510 *pos+= length;
3512 else
3513 set_zero_time(tm, MYSQL_TIMESTAMP_DATE);
3518 Convert string to supplied buffer of any type.
3520 SYNOPSIS
3521 fetch_string_with_conversion()
3522 param output buffer descriptor
3523 value column data
3524 length data length
3527 static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
3528 uint length)
3530 char *buffer= (char *)param->buffer;
3531 int err= 0;
3532 char *endptr= value + length;
3535 This function should support all target buffer types: the rest
3536 of conversion functions can delegate conversion to it.
3538 switch (param->buffer_type) {
3539 case MYSQL_TYPE_NULL: /* do nothing */
3540 break;
3541 case MYSQL_TYPE_TINY:
3543 longlong data= my_strtoll10(value, &endptr, &err);
3544 *param->error= (IS_TRUNCATED(data, param->is_unsigned,
3545 INT_MIN8, INT_MAX8, UINT_MAX8) || err > 0);
3546 *buffer= (uchar) data;
3547 break;
3549 case MYSQL_TYPE_SHORT:
3551 longlong data= my_strtoll10(value, &endptr, &err);
3552 *param->error= (IS_TRUNCATED(data, param->is_unsigned,
3553 INT_MIN16, INT_MAX16, UINT_MAX16) || err > 0);
3554 shortstore(buffer, (short) data);
3555 break;
3557 case MYSQL_TYPE_LONG:
3559 longlong data= my_strtoll10(value, &endptr, &err);
3560 *param->error= (IS_TRUNCATED(data, param->is_unsigned,
3561 INT_MIN32, INT_MAX32, UINT_MAX32) || err > 0);
3562 longstore(buffer, (int32) data);
3563 break;
3565 case MYSQL_TYPE_LONGLONG:
3567 longlong data= my_strtoll10(value, &endptr, &err);
3568 *param->error= param->is_unsigned ? err != 0 :
3569 (err > 0 || (err == 0 && data < 0));
3570 longlongstore(buffer, data);
3571 break;
3573 case MYSQL_TYPE_FLOAT:
3575 double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
3576 float fdata= (float) data;
3577 *param->error= (fdata != data) | test(err);
3578 floatstore(buffer, fdata);
3579 break;
3581 case MYSQL_TYPE_DOUBLE:
3583 double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
3584 *param->error= test(err);
3585 doublestore(buffer, data);
3586 break;
3588 case MYSQL_TYPE_TIME:
3590 MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
3591 str_to_time(value, length, tm, &err);
3592 *param->error= test(err);
3593 break;
3595 case MYSQL_TYPE_DATE:
3596 case MYSQL_TYPE_DATETIME:
3597 case MYSQL_TYPE_TIMESTAMP:
3599 MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
3600 (void) str_to_datetime(value, length, tm, TIME_FUZZY_DATE, &err);
3601 *param->error= test(err) && (param->buffer_type == MYSQL_TYPE_DATE &&
3602 tm->time_type != MYSQL_TIMESTAMP_DATE);
3603 break;
3605 case MYSQL_TYPE_TINY_BLOB:
3606 case MYSQL_TYPE_MEDIUM_BLOB:
3607 case MYSQL_TYPE_LONG_BLOB:
3608 case MYSQL_TYPE_BLOB:
3609 case MYSQL_TYPE_DECIMAL:
3610 case MYSQL_TYPE_NEWDECIMAL:
3611 default:
3614 Copy column data to the buffer taking into account offset,
3615 data length and buffer length.
3617 char *start= value + param->offset;
3618 char *end= value + length;
3619 ulong copy_length;
3620 if (start < end)
3622 copy_length= end - start;
3623 /* We've got some data beyond offset: copy up to buffer_length bytes */
3624 if (param->buffer_length)
3625 memcpy(buffer, start, min(copy_length, param->buffer_length));
3627 else
3628 copy_length= 0;
3629 if (copy_length < param->buffer_length)
3630 buffer[copy_length]= '\0';
3631 *param->error= copy_length > param->buffer_length;
3633 param->length will always contain length of entire column;
3634 number of copied bytes may be way different:
3636 *param->length= length;
3637 break;
3644 Convert integer value to client buffer of any type.
3646 SYNOPSIS
3647 fetch_long_with_conversion()
3648 param output buffer descriptor
3649 field column metadata
3650 value column data
3653 static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3654 longlong value, my_bool is_unsigned)
3656 char *buffer= (char *)param->buffer;
3658 switch (param->buffer_type) {
3659 case MYSQL_TYPE_NULL: /* do nothing */
3660 break;
3661 case MYSQL_TYPE_TINY:
3662 *param->error= IS_TRUNCATED(value, param->is_unsigned,
3663 INT_MIN8, INT_MAX8, UINT_MAX8);
3664 *(uchar *)param->buffer= (uchar) value;
3665 break;
3666 case MYSQL_TYPE_SHORT:
3667 *param->error= IS_TRUNCATED(value, param->is_unsigned,
3668 INT_MIN16, INT_MAX16, UINT_MAX16);
3669 shortstore(buffer, (short) value);
3670 break;
3671 case MYSQL_TYPE_LONG:
3672 *param->error= IS_TRUNCATED(value, param->is_unsigned,
3673 INT_MIN32, INT_MAX32, UINT_MAX32);
3674 longstore(buffer, (int32) value);
3675 break;
3676 case MYSQL_TYPE_LONGLONG:
3677 longlongstore(buffer, value);
3678 *param->error= param->is_unsigned != is_unsigned && value < 0;
3679 break;
3680 case MYSQL_TYPE_FLOAT:
3683 We need to mark the local variable volatile to
3684 workaround Intel FPU executive precision feature.
3685 (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
3687 volatile float data;
3688 if (is_unsigned)
3690 data= (float) ulonglong2double(value);
3691 *param->error= ((ulonglong) value) != ((ulonglong) data);
3693 else
3695 data= (float)value;
3696 *param->error= value != ((longlong) data);
3698 floatstore(buffer, data);
3699 break;
3701 case MYSQL_TYPE_DOUBLE:
3703 volatile double data;
3704 if (is_unsigned)
3706 data= ulonglong2double(value);
3707 *param->error= ((ulonglong) value) != ((ulonglong) data);
3709 else
3711 data= (double)value;
3712 *param->error= value != ((longlong) data);
3714 doublestore(buffer, data);
3715 break;
3717 case MYSQL_TYPE_TIME:
3718 case MYSQL_TYPE_DATE:
3719 case MYSQL_TYPE_TIMESTAMP:
3720 case MYSQL_TYPE_DATETIME:
3722 int error;
3723 value= number_to_datetime(value, (MYSQL_TIME *) buffer, TIME_FUZZY_DATE,
3724 &error);
3725 *param->error= test(error);
3726 break;
3728 default:
3730 uchar buff[22]; /* Enough for longlong */
3731 uchar *end= (uchar*) longlong10_to_str(value, (char*) buff,
3732 is_unsigned ? 10: -10);
3733 /* Resort to string conversion which supports all typecodes */
3734 uint length= (uint) (end-buff);
3736 if (field->flags & ZEROFILL_FLAG && length < field->length &&
3737 field->length < 21)
3739 bmove_upp(buff+field->length,buff+length, length);
3740 bfill(buff, field->length - length,'0');
3741 length= field->length;
3743 fetch_string_with_conversion(param, (char*) buff, length);
3744 break;
3750 Convert double/float column to supplied buffer of any type.
3752 SYNOPSIS
3753 fetch_float_with_conversion()
3754 param output buffer descriptor
3755 field column metadata
3756 value column data
3757 width default number of significant digits used when converting
3758 float/double to string
3761 static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3762 double value, int width)
3764 char *buffer= (char *)param->buffer;
3765 double val64 = (value < 0 ? -floor(-value) : floor(value));
3767 switch (param->buffer_type) {
3768 case MYSQL_TYPE_NULL: /* do nothing */
3769 break;
3770 case MYSQL_TYPE_TINY:
3772 We need to _store_ data in the buffer before the truncation check to
3773 workaround Intel FPU executive precision feature.
3774 (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
3775 Sic: AFAIU it does not guarantee to work.
3777 if (param->is_unsigned)
3778 *buffer= (uint8) value;
3779 else
3780 *buffer= (int8) value;
3781 *param->error= val64 != (param->is_unsigned ? (double)((uint8) *buffer) :
3782 (double)((int8) *buffer));
3783 break;
3784 case MYSQL_TYPE_SHORT:
3785 if (param->is_unsigned)
3787 ushort data= (ushort) value;
3788 shortstore(buffer, data);
3790 else
3792 short data= (short) value;
3793 shortstore(buffer, data);
3795 *param->error= val64 != (param->is_unsigned ? (double) (*(ushort*) buffer):
3796 (double) (*(short*) buffer));
3797 break;
3798 case MYSQL_TYPE_LONG:
3799 if (param->is_unsigned)
3801 uint32 data= (uint32) value;
3802 longstore(buffer, data);
3804 else
3806 int32 data= (int32) value;
3807 longstore(buffer, data);
3809 *param->error= val64 != (param->is_unsigned ? (double) (*(uint32*) buffer):
3810 (double) (*(int32*) buffer));
3811 break;
3812 case MYSQL_TYPE_LONGLONG:
3813 if (param->is_unsigned)
3815 ulonglong data= (ulonglong) value;
3816 longlongstore(buffer, data);
3818 else
3820 longlong data= (longlong) value;
3821 longlongstore(buffer, data);
3823 *param->error= val64 != (param->is_unsigned ?
3824 ulonglong2double(*(ulonglong*) buffer) :
3825 (double) (*(longlong*) buffer));
3826 break;
3827 case MYSQL_TYPE_FLOAT:
3829 float data= (float) value;
3830 floatstore(buffer, data);
3831 *param->error= (*(float*) buffer) != value;
3832 break;
3834 case MYSQL_TYPE_DOUBLE:
3836 doublestore(buffer, value);
3837 break;
3839 default:
3842 Resort to fetch_string_with_conversion: this should handle
3843 floating point -> string conversion nicely, honor all typecodes
3844 and param->offset possibly set in mysql_stmt_fetch_column
3846 char buff[MAX_DOUBLE_STRING_REP_LENGTH];
3847 char *end;
3848 /* TODO: move this to a header shared between client and server. */
3849 #define NOT_FIXED_DEC 31
3850 if (field->decimals >= NOT_FIXED_DEC)
3851 #undef NOT_FIXED_DEC
3854 DBL_DIG below is to ensure that the server and client has the same
3855 precisions. This will ensure that on the same machine you get the
3856 same value as a string independent of the protocol you use.
3858 sprintf(buff, "%-*.*g", (int) min(sizeof(buff)-1,
3859 param->buffer_length),
3860 min(DBL_DIG, width), value);
3861 end= strcend(buff, ' ');
3862 *end= 0;
3864 else
3866 sprintf(buff, "%.*f", (int) field->decimals, value);
3867 end= strend(buff);
3871 size_t length= end - buff;
3872 if (field->flags & ZEROFILL_FLAG && length < field->length &&
3873 field->length < MAX_DOUBLE_STRING_REP_LENGTH - 1)
3875 bmove_upp((uchar*) buff + field->length, (uchar*) buff + length,
3876 length);
3877 bfill((char*) buff, field->length - length, '0');
3878 length= field->length;
3880 fetch_string_with_conversion(param, buff, length);
3883 break;
3890 Fetch time/date/datetime to supplied buffer of any type
3892 SYNOPSIS
3893 param output buffer descriptor
3894 time column data
3897 static void fetch_datetime_with_conversion(MYSQL_BIND *param,
3898 MYSQL_FIELD *field,
3899 MYSQL_TIME *my_time)
3901 switch (param->buffer_type) {
3902 case MYSQL_TYPE_NULL: /* do nothing */
3903 break;
3904 case MYSQL_TYPE_DATE:
3905 *(MYSQL_TIME *)(param->buffer)= *my_time;
3906 *param->error= my_time->time_type != MYSQL_TIMESTAMP_DATE;
3907 break;
3908 case MYSQL_TYPE_TIME:
3909 *(MYSQL_TIME *)(param->buffer)= *my_time;
3910 *param->error= my_time->time_type != MYSQL_TIMESTAMP_TIME;
3911 break;
3912 case MYSQL_TYPE_DATETIME:
3913 case MYSQL_TYPE_TIMESTAMP:
3914 *(MYSQL_TIME *)(param->buffer)= *my_time;
3915 /* No error: time and date are compatible with datetime */
3916 break;
3917 case MYSQL_TYPE_YEAR:
3918 shortstore(param->buffer, my_time->year);
3919 *param->error= 1;
3920 break;
3921 case MYSQL_TYPE_FLOAT:
3922 case MYSQL_TYPE_DOUBLE:
3924 ulonglong value= TIME_to_ulonglong(my_time);
3925 fetch_float_with_conversion(param, field,
3926 ulonglong2double(value), DBL_DIG);
3927 break;
3929 case MYSQL_TYPE_TINY:
3930 case MYSQL_TYPE_SHORT:
3931 case MYSQL_TYPE_INT24:
3932 case MYSQL_TYPE_LONG:
3933 case MYSQL_TYPE_LONGLONG:
3935 longlong value= (longlong) TIME_to_ulonglong(my_time);
3936 fetch_long_with_conversion(param, field, value, TRUE);
3937 break;
3939 default:
3942 Convert time value to string and delegate the rest to
3943 fetch_string_with_conversion:
3945 char buff[MAX_DATE_STRING_REP_LENGTH];
3946 uint length= my_TIME_to_str(my_time, buff);
3947 /* Resort to string conversion */
3948 fetch_string_with_conversion(param, (char *)buff, length);
3949 break;
3956 Fetch and convert result set column to output buffer.
3958 SYNOPSIS
3959 fetch_result_with_conversion()
3960 param output buffer descriptor
3961 field column metadata
3962 row points to a column of result set tuple in binary format
3964 DESCRIPTION
3965 This is a fallback implementation of column fetch used
3966 if column and output buffer types do not match.
3967 Increases tuple pointer to point at the next column within the
3968 tuple.
3971 static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3972 uchar **row)
3974 enum enum_field_types field_type= field->type;
3975 uint field_is_unsigned= field->flags & UNSIGNED_FLAG;
3977 switch (field_type) {
3978 case MYSQL_TYPE_TINY:
3980 uchar value= **row;
3981 /* sic: we need to cast to 'signed char' as 'char' may be unsigned */
3982 longlong data= field_is_unsigned ? (longlong) value :
3983 (longlong) (signed char) value;
3984 fetch_long_with_conversion(param, field, data, 0);
3985 *row+= 1;
3986 break;
3988 case MYSQL_TYPE_SHORT:
3989 case MYSQL_TYPE_YEAR:
3991 short value= sint2korr(*row);
3992 longlong data= field_is_unsigned ? (longlong) (unsigned short) value :
3993 (longlong) value;
3994 fetch_long_with_conversion(param, field, data, 0);
3995 *row+= 2;
3996 break;
3998 case MYSQL_TYPE_INT24: /* mediumint is sent as 4 bytes int */
3999 case MYSQL_TYPE_LONG:
4001 int32 value= sint4korr(*row);
4002 longlong data= field_is_unsigned ? (longlong) (uint32) value :
4003 (longlong) value;
4004 fetch_long_with_conversion(param, field, data, 0);
4005 *row+= 4;
4006 break;
4008 case MYSQL_TYPE_LONGLONG:
4010 longlong value= (longlong)sint8korr(*row);
4011 fetch_long_with_conversion(param, field, value,
4012 field->flags & UNSIGNED_FLAG);
4013 *row+= 8;
4014 break;
4016 case MYSQL_TYPE_FLOAT:
4018 float value;
4019 float4get(value,*row);
4020 fetch_float_with_conversion(param, field, value, FLT_DIG);
4021 *row+= 4;
4022 break;
4024 case MYSQL_TYPE_DOUBLE:
4026 double value;
4027 float8get(value,*row);
4028 fetch_float_with_conversion(param, field, value, DBL_DIG);
4029 *row+= 8;
4030 break;
4032 case MYSQL_TYPE_DATE:
4034 MYSQL_TIME tm;
4036 read_binary_date(&tm, row);
4037 fetch_datetime_with_conversion(param, field, &tm);
4038 break;
4040 case MYSQL_TYPE_TIME:
4042 MYSQL_TIME tm;
4044 read_binary_time(&tm, row);
4045 fetch_datetime_with_conversion(param, field, &tm);
4046 break;
4048 case MYSQL_TYPE_DATETIME:
4049 case MYSQL_TYPE_TIMESTAMP:
4051 MYSQL_TIME tm;
4053 read_binary_datetime(&tm, row);
4054 fetch_datetime_with_conversion(param, field, &tm);
4055 break;
4057 default:
4059 ulong length= net_field_length(row);
4060 fetch_string_with_conversion(param, (char*) *row, length);
4061 *row+= length;
4062 break;
4069 Functions to fetch data to application buffers without conversion.
4071 All functions have the following characteristics:
4073 SYNOPSIS
4074 fetch_result_xxx()
4075 param MySQL bind param
4076 pos Row value
4078 DESCRIPTION
4079 These are no-conversion functions, used in binary protocol to store
4080 rows in application buffers. A function used only if type of binary data
4081 is compatible with type of application buffer.
4083 RETURN
4084 none
4087 static void fetch_result_tinyint(MYSQL_BIND *param, MYSQL_FIELD *field,
4088 uchar **row)
4090 my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
4091 uchar data= **row;
4092 *(uchar *)param->buffer= data;
4093 *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX8;
4094 (*row)++;
4097 static void fetch_result_short(MYSQL_BIND *param, MYSQL_FIELD *field,
4098 uchar **row)
4100 my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
4101 ushort data= (ushort) sint2korr(*row);
4102 shortstore(param->buffer, data);
4103 *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX16;
4104 *row+= 2;
4107 static void fetch_result_int32(MYSQL_BIND *param,
4108 MYSQL_FIELD *field __attribute__((unused)),
4109 uchar **row)
4111 my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
4112 uint32 data= (uint32) sint4korr(*row);
4113 longstore(param->buffer, data);
4114 *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX32;
4115 *row+= 4;
4118 static void fetch_result_int64(MYSQL_BIND *param,
4119 MYSQL_FIELD *field __attribute__((unused)),
4120 uchar **row)
4122 my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
4123 ulonglong data= (ulonglong) sint8korr(*row);
4124 *param->error= param->is_unsigned != field_is_unsigned && data > LONGLONG_MAX;
4125 longlongstore(param->buffer, data);
4126 *row+= 8;
4129 static void fetch_result_float(MYSQL_BIND *param,
4130 MYSQL_FIELD *field __attribute__((unused)),
4131 uchar **row)
4133 float value;
4134 float4get(value,*row);
4135 floatstore(param->buffer, value);
4136 *row+= 4;
4139 static void fetch_result_double(MYSQL_BIND *param,
4140 MYSQL_FIELD *field __attribute__((unused)),
4141 uchar **row)
4143 double value;
4144 float8get(value,*row);
4145 doublestore(param->buffer, value);
4146 *row+= 8;
4149 static void fetch_result_time(MYSQL_BIND *param,
4150 MYSQL_FIELD *field __attribute__((unused)),
4151 uchar **row)
4153 MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
4154 read_binary_time(tm, row);
4157 static void fetch_result_date(MYSQL_BIND *param,
4158 MYSQL_FIELD *field __attribute__((unused)),
4159 uchar **row)
4161 MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
4162 read_binary_date(tm, row);
4165 static void fetch_result_datetime(MYSQL_BIND *param,
4166 MYSQL_FIELD *field __attribute__((unused)),
4167 uchar **row)
4169 MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
4170 read_binary_datetime(tm, row);
4173 static void fetch_result_bin(MYSQL_BIND *param,
4174 MYSQL_FIELD *field __attribute__((unused)),
4175 uchar **row)
4177 ulong length= net_field_length(row);
4178 ulong copy_length= min(length, param->buffer_length);
4179 memcpy(param->buffer, (char *)*row, copy_length);
4180 *param->length= length;
4181 *param->error= copy_length < length;
4182 *row+= length;
4185 static void fetch_result_str(MYSQL_BIND *param,
4186 MYSQL_FIELD *field __attribute__((unused)),
4187 uchar **row)
4189 ulong length= net_field_length(row);
4190 ulong copy_length= min(length, param->buffer_length);
4191 memcpy(param->buffer, (char *)*row, copy_length);
4192 /* Add an end null if there is room in the buffer */
4193 if (copy_length != param->buffer_length)
4194 ((uchar *)param->buffer)[copy_length]= '\0';
4195 *param->length= length; /* return total length */
4196 *param->error= copy_length < length;
4197 *row+= length;
4202 functions to calculate max lengths for strings during
4203 mysql_stmt_store_result()
4206 static void skip_result_fixed(MYSQL_BIND *param,
4207 MYSQL_FIELD *field __attribute__((unused)),
4208 uchar **row)
4211 (*row)+= param->pack_length;
4215 static void skip_result_with_length(MYSQL_BIND *param __attribute__((unused)),
4216 MYSQL_FIELD *field __attribute__((unused)),
4217 uchar **row)
4220 ulong length= net_field_length(row);
4221 (*row)+= length;
4225 static void skip_result_string(MYSQL_BIND *param __attribute__((unused)),
4226 MYSQL_FIELD *field,
4227 uchar **row)
4230 ulong length= net_field_length(row);
4231 (*row)+= length;
4232 if (field->max_length < length)
4233 field->max_length= length;
4238 Check that two field types are binary compatible i. e.
4239 have equal representation in the binary protocol and
4240 require client-side buffers of the same type.
4242 SYNOPSIS
4243 is_binary_compatible()
4244 type1 parameter type supplied by user
4245 type2 field type, obtained from result set metadata
4247 RETURN
4248 TRUE or FALSE
4251 static my_bool is_binary_compatible(enum enum_field_types type1,
4252 enum enum_field_types type2)
4254 static const enum enum_field_types
4255 range1[]= { MYSQL_TYPE_SHORT, MYSQL_TYPE_YEAR, MYSQL_TYPE_NULL },
4256 range2[]= { MYSQL_TYPE_INT24, MYSQL_TYPE_LONG, MYSQL_TYPE_NULL },
4257 range3[]= { MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_NULL },
4258 range4[]= { MYSQL_TYPE_ENUM, MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB,
4259 MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
4260 MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY,
4261 MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NULL };
4262 static const enum enum_field_types
4263 *range_list[]= { range1, range2, range3, range4 },
4264 **range_list_end= range_list + sizeof(range_list)/sizeof(*range_list);
4265 const enum enum_field_types **range, *type;
4267 if (type1 == type2)
4268 return TRUE;
4269 for (range= range_list; range != range_list_end; ++range)
4271 /* check that both type1 and type2 are in the same range */
4272 my_bool type1_found= FALSE, type2_found= FALSE;
4273 for (type= *range; *type != MYSQL_TYPE_NULL; type++)
4275 type1_found|= type1 == *type;
4276 type2_found|= type2 == *type;
4278 if (type1_found || type2_found)
4279 return type1_found && type2_found;
4281 return FALSE;
4286 Setup a fetch function for one column of a result set.
4288 SYNOPSIS
4289 setup_one_fetch_function()
4290 param output buffer descriptor
4291 field column descriptor
4293 DESCRIPTION
4294 When user binds result set buffers or when result set
4295 metadata is changed, we need to setup fetch (and possibly
4296 conversion) functions for all columns of the result set.
4297 In addition to that here we set up skip_result function, used
4298 to update result set metadata in case when
4299 STMT_ATTR_UPDATE_MAX_LENGTH attribute is set.
4300 Notice that while fetch_result is chosen depending on both
4301 field->type and param->type, skip_result depends on field->type
4302 only.
4304 RETURN
4305 TRUE fetch function for this typecode was not found (typecode
4306 is not supported by the client library)
4307 FALSE success
4310 static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
4312 DBUG_ENTER("setup_one_fetch_function");
4314 /* Setup data copy functions for the different supported types */
4315 switch (param->buffer_type) {
4316 case MYSQL_TYPE_NULL: /* for dummy binds */
4318 It's not binary compatible with anything the server can return:
4319 no need to setup fetch_result, as it'll be reset anyway
4321 *param->length= 0;
4322 break;
4323 case MYSQL_TYPE_TINY:
4324 param->fetch_result= fetch_result_tinyint;
4325 *param->length= 1;
4326 break;
4327 case MYSQL_TYPE_SHORT:
4328 case MYSQL_TYPE_YEAR:
4329 param->fetch_result= fetch_result_short;
4330 *param->length= 2;
4331 break;
4332 case MYSQL_TYPE_INT24:
4333 case MYSQL_TYPE_LONG:
4334 param->fetch_result= fetch_result_int32;
4335 *param->length= 4;
4336 break;
4337 case MYSQL_TYPE_LONGLONG:
4338 param->fetch_result= fetch_result_int64;
4339 *param->length= 8;
4340 break;
4341 case MYSQL_TYPE_FLOAT:
4342 param->fetch_result= fetch_result_float;
4343 *param->length= 4;
4344 break;
4345 case MYSQL_TYPE_DOUBLE:
4346 param->fetch_result= fetch_result_double;
4347 *param->length= 8;
4348 break;
4349 case MYSQL_TYPE_TIME:
4350 param->fetch_result= fetch_result_time;
4351 *param->length= sizeof(MYSQL_TIME);
4352 break;
4353 case MYSQL_TYPE_DATE:
4354 param->fetch_result= fetch_result_date;
4355 *param->length= sizeof(MYSQL_TIME);
4356 break;
4357 case MYSQL_TYPE_DATETIME:
4358 case MYSQL_TYPE_TIMESTAMP:
4359 param->fetch_result= fetch_result_datetime;
4360 *param->length= sizeof(MYSQL_TIME);
4361 break;
4362 case MYSQL_TYPE_TINY_BLOB:
4363 case MYSQL_TYPE_MEDIUM_BLOB:
4364 case MYSQL_TYPE_LONG_BLOB:
4365 case MYSQL_TYPE_BLOB:
4366 case MYSQL_TYPE_BIT:
4367 DBUG_ASSERT(param->buffer_length != 0);
4368 param->fetch_result= fetch_result_bin;
4369 break;
4370 case MYSQL_TYPE_VAR_STRING:
4371 case MYSQL_TYPE_STRING:
4372 case MYSQL_TYPE_DECIMAL:
4373 case MYSQL_TYPE_NEWDECIMAL:
4374 case MYSQL_TYPE_NEWDATE:
4375 DBUG_ASSERT(param->buffer_length != 0);
4376 param->fetch_result= fetch_result_str;
4377 break;
4378 default:
4379 DBUG_PRINT("error", ("Unknown param->buffer_type: %u",
4380 (uint) param->buffer_type));
4381 DBUG_RETURN(TRUE);
4383 if (! is_binary_compatible(param->buffer_type, field->type))
4384 param->fetch_result= fetch_result_with_conversion;
4386 /* Setup skip_result functions (to calculate max_length) */
4387 param->skip_result= skip_result_fixed;
4388 switch (field->type) {
4389 case MYSQL_TYPE_NULL: /* for dummy binds */
4390 param->pack_length= 0;
4391 field->max_length= 0;
4392 break;
4393 case MYSQL_TYPE_TINY:
4394 param->pack_length= 1;
4395 field->max_length= 4; /* as in '-127' */
4396 break;
4397 case MYSQL_TYPE_YEAR:
4398 case MYSQL_TYPE_SHORT:
4399 param->pack_length= 2;
4400 field->max_length= 6; /* as in '-32767' */
4401 break;
4402 case MYSQL_TYPE_INT24:
4403 field->max_length= 9; /* as in '16777216' or in '-8388607' */
4404 param->pack_length= 4;
4405 break;
4406 case MYSQL_TYPE_LONG:
4407 field->max_length= 11; /* '-2147483647' */
4408 param->pack_length= 4;
4409 break;
4410 case MYSQL_TYPE_LONGLONG:
4411 field->max_length= 21; /* '18446744073709551616' */
4412 param->pack_length= 8;
4413 break;
4414 case MYSQL_TYPE_FLOAT:
4415 param->pack_length= 4;
4416 field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
4417 break;
4418 case MYSQL_TYPE_DOUBLE:
4419 param->pack_length= 8;
4420 field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
4421 break;
4422 case MYSQL_TYPE_TIME:
4423 field->max_length= 15; /* 19:23:48.123456 */
4424 param->skip_result= skip_result_with_length;
4425 break;
4426 case MYSQL_TYPE_DATE:
4427 field->max_length= 10; /* 2003-11-11 */
4428 param->skip_result= skip_result_with_length;
4429 break;
4430 case MYSQL_TYPE_DATETIME:
4431 case MYSQL_TYPE_TIMESTAMP:
4432 param->skip_result= skip_result_with_length;
4433 field->max_length= MAX_DATE_STRING_REP_LENGTH;
4434 break;
4435 case MYSQL_TYPE_DECIMAL:
4436 case MYSQL_TYPE_NEWDECIMAL:
4437 case MYSQL_TYPE_ENUM:
4438 case MYSQL_TYPE_SET:
4439 case MYSQL_TYPE_GEOMETRY:
4440 case MYSQL_TYPE_TINY_BLOB:
4441 case MYSQL_TYPE_MEDIUM_BLOB:
4442 case MYSQL_TYPE_LONG_BLOB:
4443 case MYSQL_TYPE_BLOB:
4444 case MYSQL_TYPE_VAR_STRING:
4445 case MYSQL_TYPE_STRING:
4446 case MYSQL_TYPE_BIT:
4447 case MYSQL_TYPE_NEWDATE:
4448 param->skip_result= skip_result_string;
4449 break;
4450 default:
4451 DBUG_PRINT("error", ("Unknown field->type: %u", (uint) field->type));
4452 DBUG_RETURN(TRUE);
4454 DBUG_RETURN(FALSE);
4459 Setup the bind buffers for resultset processing
4462 my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *my_bind)
4464 MYSQL_BIND *param, *end;
4465 MYSQL_FIELD *field;
4466 ulong bind_count= stmt->field_count;
4467 uint param_count= 0;
4468 DBUG_ENTER("mysql_stmt_bind_result");
4469 DBUG_PRINT("enter",("field_count: %lu", bind_count));
4471 if (!bind_count)
4473 int errorcode= (int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE ?
4474 CR_NO_PREPARE_STMT : CR_NO_STMT_METADATA;
4475 set_stmt_error(stmt, errorcode, unknown_sqlstate, NULL);
4476 DBUG_RETURN(1);
4480 We only need to check that stmt->field_count - if it is not null
4481 stmt->bind was initialized in mysql_stmt_prepare
4482 stmt->bind overlaps with bind if mysql_stmt_bind_param
4483 is called from mysql_stmt_store_result.
4486 if (stmt->bind != my_bind)
4487 memcpy((char*) stmt->bind, (char*) my_bind,
4488 sizeof(MYSQL_BIND) * bind_count);
4490 for (param= stmt->bind, end= param + bind_count, field= stmt->fields ;
4491 param < end ;
4492 param++, field++)
4494 DBUG_PRINT("info",("buffer_type: %u field_type: %u",
4495 (uint) param->buffer_type, (uint) field->type));
4497 Set param->is_null to point to a dummy variable if it's not set.
4498 This is to make the execute code easier
4500 if (!param->is_null)
4501 param->is_null= &param->is_null_value;
4503 if (!param->length)
4504 param->length= &param->length_value;
4506 if (!param->error)
4507 param->error= &param->error_value;
4509 param->param_number= param_count++;
4510 param->offset= 0;
4512 if (setup_one_fetch_function(param, field))
4514 strmov(stmt->sqlstate, unknown_sqlstate);
4515 sprintf(stmt->last_error,
4516 ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
4517 field->type, param_count);
4518 DBUG_RETURN(1);
4521 stmt->bind_result_done= BIND_RESULT_DONE;
4522 if (stmt->mysql->options.report_data_truncation)
4523 stmt->bind_result_done|= REPORT_DATA_TRUNCATION;
4525 DBUG_RETURN(0);
4530 Fetch row data to bind buffers
4533 static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
4535 MYSQL_BIND *my_bind, *end;
4536 MYSQL_FIELD *field;
4537 uchar *null_ptr, bit;
4538 int truncation_count= 0;
4540 Precondition: if stmt->field_count is zero or row is NULL, read_row_*
4541 function must return no data.
4543 DBUG_ASSERT(stmt->field_count);
4544 DBUG_ASSERT(row);
4546 if (!stmt->bind_result_done)
4548 /* If output parameters were not bound we should just return success */
4549 return 0;
4552 null_ptr= row;
4553 row+= (stmt->field_count+9)/8; /* skip null bits */
4554 bit= 4; /* first 2 bits are reserved */
4556 /* Copy complete row to application buffers */
4557 for (my_bind= stmt->bind, end= my_bind + stmt->field_count,
4558 field= stmt->fields ;
4559 my_bind < end ;
4560 my_bind++, field++)
4562 *my_bind->error= 0;
4563 if (*null_ptr & bit)
4566 We should set both row_ptr and is_null to be able to see
4567 nulls in mysql_stmt_fetch_column. This is because is_null may point
4568 to user data which can be overwritten between mysql_stmt_fetch and
4569 mysql_stmt_fetch_column, and in this case nullness of column will be
4570 lost. See mysql_stmt_fetch_column for details.
4572 my_bind->row_ptr= NULL;
4573 *my_bind->is_null= 1;
4575 else
4577 *my_bind->is_null= 0;
4578 my_bind->row_ptr= row;
4579 (*my_bind->fetch_result)(my_bind, field, &row);
4580 truncation_count+= *my_bind->error;
4582 if (!((bit<<=1) & 255))
4584 bit= 1; /* To next uchar */
4585 null_ptr++;
4588 if (truncation_count && (stmt->bind_result_done & REPORT_DATA_TRUNCATION))
4589 return MYSQL_DATA_TRUNCATED;
4590 return 0;
4594 int cli_unbuffered_fetch(MYSQL *mysql, char **row)
4596 if (packet_error == cli_safe_read(mysql))
4597 return 1;
4599 *row= ((mysql->net.read_pos[0] == 254) ? NULL :
4600 (char*) (mysql->net.read_pos+1));
4601 return 0;
4606 Fetch and return row data to bound buffers, if any
4609 int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
4611 int rc;
4612 uchar *row;
4613 DBUG_ENTER("mysql_stmt_fetch");
4615 if ((rc= (*stmt->read_row_func)(stmt, &row)) ||
4616 ((rc= stmt_fetch_row(stmt, row)) && rc != MYSQL_DATA_TRUNCATED))
4618 stmt->state= MYSQL_STMT_PREPARE_DONE; /* XXX: this is buggy */
4619 stmt->read_row_func= (rc == MYSQL_NO_DATA) ?
4620 stmt_read_row_no_data : stmt_read_row_no_result_set;
4622 else
4624 /* This is to know in mysql_stmt_fetch_column that data was fetched */
4625 stmt->state= MYSQL_STMT_FETCH_DONE;
4627 DBUG_RETURN(rc);
4632 Fetch data for one specified column data
4634 SYNOPSIS
4635 mysql_stmt_fetch_column()
4636 stmt Prepared statement handler
4637 my_bind Where data should be placed. Should be filled in as
4638 when calling mysql_stmt_bind_result()
4639 column Column to fetch (first column is 0)
4640 ulong offset Offset in result data (to fetch blob in pieces)
4641 This is normally 0
4642 RETURN
4643 0 ok
4644 1 error
4647 int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *my_bind,
4648 uint column, ulong offset)
4650 MYSQL_BIND *param= stmt->bind+column;
4651 DBUG_ENTER("mysql_stmt_fetch_column");
4653 if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE)
4655 set_stmt_error(stmt, CR_NO_DATA, unknown_sqlstate, NULL);
4656 DBUG_RETURN(1);
4658 if (column >= stmt->field_count)
4660 set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL);
4661 DBUG_RETURN(1);
4664 if (!my_bind->error)
4665 my_bind->error= &my_bind->error_value;
4666 *my_bind->error= 0;
4667 if (param->row_ptr)
4669 MYSQL_FIELD *field= stmt->fields+column;
4670 uchar *row= param->row_ptr;
4671 my_bind->offset= offset;
4672 if (my_bind->is_null)
4673 *my_bind->is_null= 0;
4674 if (my_bind->length) /* Set the length if non char/binary types */
4675 *my_bind->length= *param->length;
4676 else
4677 my_bind->length= &param->length_value; /* Needed for fetch_result() */
4678 fetch_result_with_conversion(my_bind, field, &row);
4680 else
4682 if (my_bind->is_null)
4683 *my_bind->is_null= 1;
4685 DBUG_RETURN(0);
4690 Read all rows of data from server (binary format)
4693 int cli_read_binary_rows(MYSQL_STMT *stmt)
4695 ulong pkt_len;
4696 uchar *cp;
4697 MYSQL *mysql= stmt->mysql;
4698 MYSQL_DATA *result= &stmt->result;
4699 MYSQL_ROWS *cur, **prev_ptr= &result->data;
4700 NET *net;
4702 DBUG_ENTER("cli_read_binary_rows");
4704 if (!mysql)
4706 set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
4707 DBUG_RETURN(1);
4710 net = &mysql->net;
4711 mysql= mysql->last_used_con;
4713 while ((pkt_len= cli_safe_read(mysql)) != packet_error)
4715 cp= net->read_pos;
4716 if (cp[0] != 254 || pkt_len >= 8)
4718 if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
4719 sizeof(MYSQL_ROWS) + pkt_len - 1)))
4721 set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
4722 goto err;
4724 cur->data= (MYSQL_ROW) (cur+1);
4725 *prev_ptr= cur;
4726 prev_ptr= &cur->next;
4727 memcpy((char *) cur->data, (char *) cp+1, pkt_len-1);
4728 cur->length= pkt_len; /* To allow us to do sanity checks */
4729 result->rows++;
4731 else
4733 /* end of data */
4734 *prev_ptr= 0;
4735 mysql->warning_count= uint2korr(cp+1);
4736 mysql->server_status= uint2korr(cp+3);
4737 DBUG_PRINT("info",("status: %u warning_count: %u",
4738 mysql->server_status, mysql->warning_count));
4739 DBUG_RETURN(0);
4742 set_stmt_errmsg(stmt, net);
4744 err:
4745 DBUG_RETURN(1);
4750 Update meta data for statement
4752 SYNOPSIS
4753 stmt_update_metadata()
4754 stmt Statement handler
4755 row Binary data
4757 NOTES
4758 Only updates MYSQL_FIELD->max_length for strings
4761 static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data)
4763 MYSQL_BIND *my_bind, *end;
4764 MYSQL_FIELD *field;
4765 uchar *null_ptr, bit;
4766 uchar *row= (uchar*) data->data;
4767 #ifndef DBUG_OFF
4768 uchar *row_end= row + data->length;
4769 #endif
4771 null_ptr= row;
4772 row+= (stmt->field_count+9)/8; /* skip null bits */
4773 bit= 4; /* first 2 bits are reserved */
4775 /* Go through all fields and calculate metadata */
4776 for (my_bind= stmt->bind, end= my_bind + stmt->field_count, field= stmt->fields ;
4777 my_bind < end ;
4778 my_bind++, field++)
4780 if (!(*null_ptr & bit))
4781 (*my_bind->skip_result)(my_bind, field, &row);
4782 DBUG_ASSERT(row <= row_end);
4783 if (!((bit<<=1) & 255))
4785 bit= 1; /* To next uchar */
4786 null_ptr++;
4793 Store or buffer the binary results to stmt
4796 int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
4798 MYSQL *mysql= stmt->mysql;
4799 MYSQL_DATA *result= &stmt->result;
4800 DBUG_ENTER("mysql_stmt_store_result");
4802 if (!mysql)
4804 /* mysql can be reset in mysql_close called from mysql_reconnect */
4805 set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
4806 DBUG_RETURN(1);
4809 mysql= mysql->last_used_con;
4811 if (!stmt->field_count)
4812 DBUG_RETURN(0);
4814 if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE)
4816 set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
4817 DBUG_RETURN(1);
4820 if (stmt->last_errno)
4822 /* An attempt to use an invalid statement handle. */
4823 DBUG_RETURN(1);
4826 if (mysql->status == MYSQL_STATUS_READY &&
4827 stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
4830 Server side cursor exist, tell server to start sending the rows
4832 NET *net= &mysql->net;
4833 uchar buff[4 /* statement id */ +
4834 4 /* number of rows to fetch */];
4836 /* Send row request to the server */
4837 int4store(buff, stmt->stmt_id);
4838 int4store(buff + 4, (int)~0); /* number of rows to fetch */
4839 if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
4840 (uchar*) 0, 0, 1, stmt))
4843 Don't set stmt error if stmt->mysql is NULL, as the error in this case
4844 has already been set by mysql_prune_stmt_list().
4846 if (stmt->mysql)
4847 set_stmt_errmsg(stmt, net);
4848 DBUG_RETURN(1);
4851 else if (mysql->status != MYSQL_STATUS_STATEMENT_GET_RESULT)
4853 set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
4854 DBUG_RETURN(1);
4857 if (stmt->update_max_length && !stmt->bind_result_done)
4860 We must initalize the bind structure to be able to calculate
4861 max_length
4863 MYSQL_BIND *my_bind, *end;
4864 MYSQL_FIELD *field;
4865 bzero((char*) stmt->bind, sizeof(*stmt->bind)* stmt->field_count);
4867 for (my_bind= stmt->bind, end= my_bind + stmt->field_count,
4868 field= stmt->fields;
4869 my_bind < end ;
4870 my_bind++, field++)
4872 my_bind->buffer_type= MYSQL_TYPE_NULL;
4873 my_bind->buffer_length=1;
4876 if (mysql_stmt_bind_result(stmt, stmt->bind))
4877 DBUG_RETURN(1);
4878 stmt->bind_result_done= 0; /* No normal bind done */
4881 if ((*mysql->methods->read_binary_rows)(stmt))
4883 free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
4884 result->data= NULL;
4885 result->rows= 0;
4886 mysql->status= MYSQL_STATUS_READY;
4887 DBUG_RETURN(1);
4890 /* Assert that if there was a cursor, all rows have been fetched */
4891 DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY ||
4892 (mysql->server_status & SERVER_STATUS_LAST_ROW_SENT));
4894 if (stmt->update_max_length)
4896 MYSQL_ROWS *cur= result->data;
4897 for(; cur; cur=cur->next)
4898 stmt_update_metadata(stmt, cur);
4901 stmt->data_cursor= result->data;
4902 mysql->affected_rows= stmt->affected_rows= result->rows;
4903 stmt->read_row_func= stmt_read_row_buffered;
4904 mysql->unbuffered_fetch_owner= 0; /* set in stmt_execute */
4905 mysql->status= MYSQL_STATUS_READY; /* server is ready */
4906 DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_stmt_fetch() */
4911 Seek to desired row in the statement result set
4914 MYSQL_ROW_OFFSET STDCALL
4915 mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
4917 MYSQL_ROW_OFFSET offset= stmt->data_cursor;
4918 DBUG_ENTER("mysql_stmt_row_seek");
4920 stmt->data_cursor= row;
4921 DBUG_RETURN(offset);
4926 Return the current statement row cursor position
4929 MYSQL_ROW_OFFSET STDCALL
4930 mysql_stmt_row_tell(MYSQL_STMT *stmt)
4932 DBUG_ENTER("mysql_stmt_row_tell");
4934 DBUG_RETURN(stmt->data_cursor);
4939 Move the stmt result set data cursor to specified row
4942 void STDCALL
4943 mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
4945 MYSQL_ROWS *tmp= stmt->result.data;
4946 DBUG_ENTER("mysql_stmt_data_seek");
4947 DBUG_PRINT("enter",("row id to seek: %ld",(long) row));
4949 for (; tmp && row; --row, tmp= tmp->next)
4951 stmt->data_cursor= tmp;
4952 if (!row && tmp)
4954 /* Rewind the counter */
4955 stmt->read_row_func= stmt_read_row_buffered;
4956 stmt->state= MYSQL_STMT_EXECUTE_DONE;
4958 DBUG_VOID_RETURN;
4963 Return total rows the current statement result set
4966 my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
4968 DBUG_ENTER("mysql_stmt_num_rows");
4970 DBUG_RETURN(stmt->result.rows);
4975 Free the client side memory buffers, reset long data state
4976 on client if necessary, and reset the server side statement if
4977 this has been requested.
4980 static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
4982 /* If statement hasn't been prepared there is nothing to reset */
4983 if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
4985 MYSQL *mysql= stmt->mysql;
4986 MYSQL_DATA *result= &stmt->result;
4989 Reset stored result set if so was requested or it's a part
4990 of cursor fetch.
4992 if (flags & RESET_STORE_RESULT)
4994 /* Result buffered */
4995 free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
4996 result->data= NULL;
4997 result->rows= 0;
4998 stmt->data_cursor= NULL;
5000 if (flags & RESET_LONG_DATA)
5002 MYSQL_BIND *param= stmt->params, *param_end= param + stmt->param_count;
5003 /* Clear long_data_used flags */
5004 for (; param < param_end; param++)
5005 param->long_data_used= 0;
5007 stmt->read_row_func= stmt_read_row_no_result_set;
5008 if (mysql)
5010 if ((int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
5012 if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
5013 mysql->unbuffered_fetch_owner= 0;
5014 if (stmt->field_count && mysql->status != MYSQL_STATUS_READY)
5016 /* There is a result set and it belongs to this statement */
5017 (*mysql->methods->flush_use_result)(mysql);
5018 if (mysql->unbuffered_fetch_owner)
5019 *mysql->unbuffered_fetch_owner= TRUE;
5020 mysql->status= MYSQL_STATUS_READY;
5023 if (flags & RESET_SERVER_SIDE)
5026 Reset the server side statement and close the server side
5027 cursor if it exists.
5029 uchar buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
5030 int4store(buff, stmt->stmt_id);
5031 if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff,
5032 sizeof(buff), 0, 0, 0, stmt))
5034 set_stmt_errmsg(stmt, &mysql->net);
5035 stmt->state= MYSQL_STMT_INIT_DONE;
5036 return 1;
5040 if (flags & RESET_CLEAR_ERROR)
5041 stmt_clear_error(stmt);
5042 stmt->state= MYSQL_STMT_PREPARE_DONE;
5044 return 0;
5047 my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
5049 DBUG_ENTER("mysql_stmt_free_result");
5051 /* Free the client side and close the server side cursor if there is one */
5052 DBUG_RETURN(reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT |
5053 RESET_CLEAR_ERROR));
5056 /********************************************************************
5057 statement error handling and close
5058 *********************************************************************/
5061 Close the statement handle by freeing all alloced resources
5063 SYNOPSIS
5064 mysql_stmt_close()
5065 stmt Statement handle
5067 RETURN VALUES
5068 0 ok
5069 1 error
5072 my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
5074 MYSQL *mysql= stmt->mysql;
5075 int rc= 0;
5076 DBUG_ENTER("mysql_stmt_close");
5078 free_root(&stmt->result.alloc, MYF(0));
5079 free_root(&stmt->mem_root, MYF(0));
5081 if (mysql)
5083 mysql->stmts= list_delete(mysql->stmts, &stmt->list);
5085 Clear NET error state: if the following commands come through
5086 successfully, connection will still be usable for other commands.
5088 net_clear_error(&mysql->net);
5089 if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
5091 uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
5093 if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
5094 mysql->unbuffered_fetch_owner= 0;
5095 if (mysql->status != MYSQL_STATUS_READY)
5098 Flush result set of the connection. If it does not belong
5099 to this statement, set a warning.
5101 (*mysql->methods->flush_use_result)(mysql);
5102 if (mysql->unbuffered_fetch_owner)
5103 *mysql->unbuffered_fetch_owner= TRUE;
5104 mysql->status= MYSQL_STATUS_READY;
5106 int4store(buff, stmt->stmt_id);
5107 if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)))
5109 set_stmt_errmsg(stmt, &mysql->net);
5114 my_free((uchar*) stmt, MYF(MY_WME));
5116 DBUG_RETURN(test(rc));
5120 Reset the statement buffers in server
5123 my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
5125 DBUG_ENTER("mysql_stmt_reset");
5126 DBUG_ASSERT(stmt != 0);
5127 if (!stmt->mysql)
5129 /* mysql can be reset in mysql_close called from mysql_reconnect */
5130 set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
5131 DBUG_RETURN(1);
5133 /* Reset the client and server sides of the prepared statement */
5134 DBUG_RETURN(reset_stmt_handle(stmt,
5135 RESET_SERVER_SIDE | RESET_LONG_DATA |
5136 RESET_CLEAR_ERROR));
5140 Return statement error code
5143 uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt)
5145 DBUG_ENTER("mysql_stmt_errno");
5146 DBUG_RETURN(stmt->last_errno);
5149 const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt)
5151 DBUG_ENTER("mysql_stmt_sqlstate");
5152 DBUG_RETURN(stmt->sqlstate);
5156 Return statement error message
5159 const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt)
5161 DBUG_ENTER("mysql_stmt_error");
5162 DBUG_RETURN(stmt->last_error);
5166 /********************************************************************
5167 Transactional APIs
5168 *********************************************************************/
5171 Commit the current transaction
5174 my_bool STDCALL mysql_commit(MYSQL * mysql)
5176 DBUG_ENTER("mysql_commit");
5177 DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6));
5181 Rollback the current transaction
5184 my_bool STDCALL mysql_rollback(MYSQL * mysql)
5186 DBUG_ENTER("mysql_rollback");
5187 DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8));
5192 Set autocommit to either true or false
5195 my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
5197 DBUG_ENTER("mysql_autocommit");
5198 DBUG_PRINT("enter", ("mode : %d", auto_mode));
5200 DBUG_RETURN((my_bool) mysql_real_query(mysql, auto_mode ?
5201 "set autocommit=1":"set autocommit=0",
5202 16));
5206 /********************************************************************
5207 Multi query execution + SPs APIs
5208 *********************************************************************/
5211 Returns true/false to indicate whether any more query results exist
5212 to be read using mysql_next_result()
5215 my_bool STDCALL mysql_more_results(MYSQL *mysql)
5217 my_bool res;
5218 DBUG_ENTER("mysql_more_results");
5220 res= ((mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS) ?
5221 1: 0);
5222 DBUG_PRINT("exit",("More results exists ? %d", res));
5223 DBUG_RETURN(res);
5228 Reads and returns the next query results
5230 int STDCALL mysql_next_result(MYSQL *mysql)
5232 DBUG_ENTER("mysql_next_result");
5234 if (mysql->status != MYSQL_STATUS_READY)
5236 set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
5237 DBUG_RETURN(1);
5240 net_clear_error(&mysql->net);
5241 mysql->affected_rows= ~(my_ulonglong) 0;
5243 if (mysql->last_used_con->server_status & SERVER_MORE_RESULTS_EXISTS)
5244 DBUG_RETURN((*mysql->methods->next_result)(mysql));
5246 DBUG_RETURN(-1); /* No more results */
5250 MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql)
5252 return (*mysql->methods->use_result)(mysql);
5255 my_bool STDCALL mysql_read_query_result(MYSQL *mysql)
5257 return (*mysql->methods->read_query_result)(mysql);