MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
libmysql.c
1 /* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
2 
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; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #include <my_global.h>
17 #include <my_sys.h>
18 #include <my_time.h>
19 #include <mysys_err.h>
20 #include <m_string.h>
21 #include <m_ctype.h>
22 #include "mysql.h"
23 #include "mysql_version.h"
24 #include "mysqld_error.h"
25 #include "errmsg.h"
26 #include <violite.h>
27 #include <sys/stat.h>
28 #include <signal.h>
29 #include <time.h>
30 #ifdef HAVE_PWD_H
31 #include <pwd.h>
32 #endif
33 #if !defined(__WIN__)
34 #ifdef HAVE_SELECT_H
35 #include <select.h>
36 #endif
37 #ifdef HAVE_SYS_SELECT_H
38 #include <sys/select.h>
39 #endif
40 #endif /* !defined(__WIN__) */
41 #ifdef HAVE_POLL
42 #include <sys/poll.h>
43 #endif
44 #ifdef HAVE_SYS_UN_H
45 #include <sys/un.h>
46 #endif
47 #if !defined(__WIN__)
48 #include <my_pthread.h> /* because of signal() */
49 #endif
50 #ifndef INADDR_NONE
51 #define INADDR_NONE -1
52 #endif
53 
54 #include <sql_common.h>
55 #include "client_settings.h"
56 
57 #undef net_buffer_length
58 #undef max_allowed_packet
59 
60 ulong net_buffer_length=8192;
61 ulong max_allowed_packet= 1024L*1024L*1024L;
62 
63 
64 #ifdef EMBEDDED_LIBRARY
65 #undef net_flush
66 my_bool net_flush(NET *net);
67 #endif
68 
69 #if defined(__WIN__)
70 /* socket_errno is defined in my_global.h for all platforms */
71 #define perror(A)
72 #else
73 #include <errno.h>
74 #define SOCKET_ERROR -1
75 #endif /* __WIN__ */
76 
77 /*
78  If allowed through some configuration, then this needs to
79  be changed
80 */
81 #define MAX_LONG_DATA_LENGTH 8192
82 #define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
83 
84 static void append_wild(char *to,char *end,const char *wild);
85 sig_handler my_pipe_sig_handler(int sig);
86 
87 static my_bool mysql_client_init= 0;
88 static my_bool org_my_init_done= 0;
89 
91 {
92  MEM_ROOT fields_mem_root;
94 
95 
96 /*
97  Initialize the MySQL client library
98 
99  SYNOPSIS
100  mysql_server_init()
101 
102  NOTES
103  Should be called before doing any other calls to the MySQL
104  client library to initialize thread specific variables etc.
105  It's called by mysql_init() to ensure that things will work for
106  old not threaded applications that doesn't call mysql_server_init()
107  directly.
108 
109  RETURN
110  0 ok
111  1 could not initialize environment (out of memory or thread keys)
112 */
113 
114 int STDCALL mysql_server_init(int argc __attribute__((unused)),
115  char **argv __attribute__((unused)),
116  char **groups __attribute__((unused)))
117 {
118  int result= 0;
119  if (!mysql_client_init)
120  {
121  mysql_client_init=1;
122  org_my_init_done=my_init_done;
123  if (my_init()) /* Will init threads */
124  return 1;
125  init_client_errs();
127  return 1;
128  if (!mysql_port)
129  {
130  char *env;
131  struct servent *serv_ptr __attribute__((unused));
132 
133  mysql_port = MYSQL_PORT;
134 
135  /*
136  if builder specifically requested a default port, use that
137  (even if it coincides with our factory default).
138  only if they didn't do we check /etc/services (and, failing
139  on that, fall back to the factory default of 3306).
140  either default can be overridden by the environment variable
141  MYSQL_TCP_PORT, which in turn can be overridden with command
142  line options.
143  */
144 
145 #if MYSQL_PORT_DEFAULT == 0
146  if ((serv_ptr= getservbyname("mysql", "tcp")))
147  mysql_port= (uint) ntohs((ushort) serv_ptr->s_port);
148 #endif
149  if ((env= getenv("MYSQL_TCP_PORT")))
150  mysql_port=(uint) atoi(env);
151  }
152 
153  if (!mysql_unix_port)
154  {
155  char *env;
156 #ifdef __WIN__
157  mysql_unix_port = (char*) MYSQL_NAMEDPIPE;
158 #else
159  mysql_unix_port = (char*) MYSQL_UNIX_ADDR;
160 #endif
161  if ((env = getenv("MYSQL_UNIX_PORT")))
162  mysql_unix_port = env;
163  }
164  mysql_debug(NullS);
165 #if defined(SIGPIPE) && !defined(__WIN__)
166  (void) signal(SIGPIPE, SIG_IGN);
167 #endif
168 #ifdef EMBEDDED_LIBRARY
169  if (argc > -1)
170  result= init_embedded_server(argc, argv, groups);
171 #endif
172  }
173  else
174  result= (int)my_thread_init(); /* Init if new thread */
175  return result;
176 }
177 
178 
179 /*
180  Free all memory and resources used by the client library
181 
182  NOTES
183  When calling this there should not be any other threads using
184  the library.
185 
186  To make things simpler when used with windows dll's (which calls this
187  function automaticly), it's safe to call this function multiple times.
188 */
189 
190 
191 void STDCALL mysql_server_end()
192 {
193  if (!mysql_client_init)
194  return;
195 
197 
198 #ifdef EMBEDDED_LIBRARY
199  end_embedded_server();
200 #endif
201  finish_client_errs();
202  vio_end();
203 
204  /* If library called my_init(), free memory allocated by it */
205  if (!org_my_init_done)
206  {
207  my_end(0);
208  }
209  else
210  {
211  free_charsets();
212  mysql_thread_end();
213  }
214 
215  mysql_client_init= org_my_init_done= 0;
216 }
217 
218 static MYSQL_PARAMETERS mysql_internal_parameters=
219 {&max_allowed_packet, &net_buffer_length, 0};
220 
221 MYSQL_PARAMETERS *STDCALL mysql_get_parameters(void)
222 {
223  return &mysql_internal_parameters;
224 }
225 
226 my_bool STDCALL mysql_thread_init()
227 {
228  return my_thread_init();
229 }
230 
231 void STDCALL mysql_thread_end()
232 {
233  my_thread_end();
234 }
235 
236 
237 /*
238  Expand wildcard to a sql string
239 */
240 
241 static void
242 append_wild(char *to, char *end, const char *wild)
243 {
244  end-=5; /* Some extra */
245  if (wild && wild[0])
246  {
247  to=strmov(to," like '");
248  while (*wild && to < end)
249  {
250  if (*wild == '\\' || *wild == '\'')
251  *to++='\\';
252  *to++= *wild++;
253  }
254  if (*wild) /* Too small buffer */
255  *to++='%'; /* Nicer this way */
256  to[0]='\'';
257  to[1]=0;
258  }
259 }
260 
261 
262 /**************************************************************************
263  Init debugging if MYSQL_DEBUG environment variable is found
264 **************************************************************************/
265 
266 void STDCALL
267 mysql_debug(const char *debug __attribute__((unused)))
268 {
269 #ifndef DBUG_OFF
270  char *env;
271  if (debug)
272  {
273  DBUG_PUSH(debug);
274  }
275  else if ((env = getenv("MYSQL_DEBUG")))
276  {
277  DBUG_PUSH(env);
278 #if !defined(_WINVER) && !defined(WINVER)
279  puts("\n-------------------------------------------------------");
280  puts("MYSQL_DEBUG found. libmysql started with the following:");
281  puts(env);
282  puts("-------------------------------------------------------\n");
283 #else
284  {
285  char buff[80];
286  buff[sizeof(buff)-1]= 0;
287  strxnmov(buff,sizeof(buff)-1,"libmysql: ", env, NullS);
288  MessageBox((HWND) 0,"Debugging variable MYSQL_DEBUG used",buff,MB_OK);
289  }
290 #endif
291  }
292 #endif
293 }
294 
295 
296 /**************************************************************************
297  Ignore SIGPIPE handler
298  ARGSUSED
299 **************************************************************************/
300 
301 sig_handler
302 my_pipe_sig_handler(int sig __attribute__((unused)))
303 {
304  DBUG_PRINT("info",("Hit by signal %d",sig));
305 #ifdef SIGNAL_HANDLER_RESET_ON_DELIVERY
306  (void) signal(SIGPIPE, my_pipe_sig_handler);
307 #endif
308 }
309 
310 
311 /**************************************************************************
312  Connect to sql server
313  If host == 0 then use localhost
314 **************************************************************************/
315 
316 #ifdef USE_OLD_FUNCTIONS
317 MYSQL * STDCALL
318 mysql_connect(MYSQL *mysql,const char *host,
319  const char *user, const char *passwd)
320 {
321  MYSQL *res;
322  mysql=mysql_init(mysql); /* Make it thread safe */
323  {
324  DBUG_ENTER("mysql_connect");
325  if (!(res=mysql_real_connect(mysql,host,user,passwd,NullS,0,NullS,0)))
326  {
327  if (mysql->free_me)
328  my_free(mysql);
329  }
330  mysql->reconnect= 1;
331  DBUG_RETURN(res);
332  }
333 }
334 #endif
335 
336 
337 /**************************************************************************
338  Change user and database
339 **************************************************************************/
340 
341 my_bool STDCALL mysql_change_user(MYSQL *mysql, const char *user,
342  const char *passwd, const char *db)
343 {
344  int rc;
345  CHARSET_INFO *saved_cs= mysql->charset;
346  char *saved_user= mysql->user;
347  char *saved_passwd= mysql->passwd;
348  char *saved_db= mysql->db;
349 
350  DBUG_ENTER("mysql_change_user");
351 
352  /* Get the connection-default character set. */
353 
354  if (mysql_init_character_set(mysql))
355  {
356  mysql->charset= saved_cs;
357  DBUG_RETURN(TRUE);
358  }
359 
360  /* Use an empty string instead of NULL. */
361 
362  mysql->user= (char*)(user ? user : "");
363  mysql->passwd= (char*)(passwd ? passwd : "");
364  mysql->db= 0;
365 
366  rc= run_plugin_auth(mysql, 0, 0, 0, db);
367 
368  /*
369  The server will close all statements no matter was the attempt
370  to change user successful or not.
371  */
372  mysql_detach_stmt_list(&mysql->stmts, "mysql_change_user");
373  if (rc == 0)
374  {
375  /* Free old connect information */
376  my_free(saved_user);
377  my_free(saved_passwd);
378  my_free(saved_db);
379 
380  /* alloc new connect information */
381  mysql->user= my_strdup(mysql->user, MYF(MY_WME));
382  mysql->passwd= my_strdup(mysql->passwd, MYF(MY_WME));
383  mysql->db= db ? my_strdup(db, MYF(MY_WME)) : 0;
384  }
385  else
386  {
387  mysql->charset= saved_cs;
388  mysql->user= saved_user;
389  mysql->passwd= saved_passwd;
390  mysql->db= saved_db;
391  }
392 
393  DBUG_RETURN(rc);
394 }
395 
396 #if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
397 struct passwd *getpwuid(uid_t);
398 char* getlogin(void);
399 #endif
400 
401 #if !defined(__WIN__)
402 
403 void read_user_name(char *name)
404 {
405  DBUG_ENTER("read_user_name");
406  if (geteuid() == 0)
407  (void) strmov(name,"root"); /* allow use of surun */
408  else
409  {
410 #ifdef HAVE_GETPWUID
411  struct passwd *skr;
412  const char *str;
413  if ((str=getlogin()) == NULL)
414  {
415  if ((skr=getpwuid(geteuid())) != NULL)
416  str=skr->pw_name;
417  else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
418  !(str=getenv("LOGIN")))
419  str="UNKNOWN_USER";
420  }
421  (void) strmake(name,str,USERNAME_LENGTH);
422 #elif HAVE_CUSERID
423  (void) cuserid(name);
424 #else
425  strmov(name,"UNKNOWN_USER");
426 #endif
427  }
428  DBUG_VOID_RETURN;
429 }
430 
431 #else /* If Windows */
432 
433 void read_user_name(char *name)
434 {
435  char *str=getenv("USER"); /* ODBC will send user variable */
436  strmake(name,str ? str : "ODBC", USERNAME_LENGTH);
437 }
438 
439 #endif
440 
441 my_bool handle_local_infile(MYSQL *mysql, const char *net_filename)
442 {
443  my_bool result= 1;
444  uint packet_length=MY_ALIGN(mysql->net.max_packet-16,IO_SIZE);
445  NET *net= &mysql->net;
446  int readcount;
447  void *li_ptr; /* pass state to local_infile functions */
448  char *buf; /* buffer to be filled by local_infile_read */
449  struct st_mysql_options *options= &mysql->options;
450  DBUG_ENTER("handle_local_infile");
451 
452  /* check that we've got valid callback functions */
453  if (!(options->local_infile_init &&
454  options->local_infile_read &&
455  options->local_infile_end &&
456  options->local_infile_error))
457  {
458  /* if any of the functions is invalid, set the default */
459  mysql_set_local_infile_default(mysql);
460  }
461 
462  /* copy filename into local memory and allocate read buffer */
463  if (!(buf=my_malloc(packet_length, MYF(0))))
464  {
465  set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
466  DBUG_RETURN(1);
467  }
468 
469  /* initialize local infile (open file, usually) */
470  if ((*options->local_infile_init)(&li_ptr, net_filename,
471  options->local_infile_userdata))
472  {
473  (void) my_net_write(net,(const uchar*) "",0); /* Server needs one packet */
474  net_flush(net);
475  strmov(net->sqlstate, unknown_sqlstate);
476  net->last_errno=
477  (*options->local_infile_error)(li_ptr,
478  net->last_error,
479  sizeof(net->last_error)-1);
480  goto err;
481  }
482 
483  /* read blocks of data from local infile callback */
484  while ((readcount =
485  (*options->local_infile_read)(li_ptr, buf,
486  packet_length)) > 0)
487  {
488  if (my_net_write(net, (uchar*) buf, readcount))
489  {
490  DBUG_PRINT("error",
491  ("Lost connection to MySQL server during LOAD DATA of local file"));
492  set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
493  goto err;
494  }
495  }
496 
497  /* Send empty packet to mark end of file */
498  if (my_net_write(net, (const uchar*) "", 0) || net_flush(net))
499  {
500  set_mysql_error(mysql, CR_SERVER_LOST, unknown_sqlstate);
501  goto err;
502  }
503 
504  if (readcount < 0)
505  {
506  net->last_errno=
507  (*options->local_infile_error)(li_ptr,
508  net->last_error,
509  sizeof(net->last_error)-1);
510  goto err;
511  }
512 
513  result=0; /* Ok */
514 
515 err:
516  /* free up memory allocated with _init, usually */
517  (*options->local_infile_end)(li_ptr);
518  my_free(buf);
519  DBUG_RETURN(result);
520 }
521 
522 
523 /****************************************************************************
524  Default handlers for LOAD LOCAL INFILE
525 ****************************************************************************/
526 
528 {
529  int fd;
530  int error_num;
531  const char *filename;
532  char error_msg[LOCAL_INFILE_ERROR_LEN];
534 
535 
536 /*
537  Open file for LOAD LOCAL INFILE
538 
539  SYNOPSIS
540  default_local_infile_init()
541  ptr Store pointer to internal data here
542  filename File name to open. This may be in unix format !
543 
544 
545  NOTES
546  Even if this function returns an error, the load data interface
547  guarantees that default_local_infile_end() is called.
548 
549  RETURN
550  0 ok
551  1 error
552 */
553 
554 static int default_local_infile_init(void **ptr, const char *filename,
555  void *userdata __attribute__ ((unused)))
556 {
558  char tmp_name[FN_REFLEN];
559 
560  if (!(*ptr= data= ((default_local_infile_data *)
561  my_malloc(sizeof(default_local_infile_data), MYF(0)))))
562  return 1; /* out of memory */
563 
564  data->error_msg[0]= 0;
565  data->error_num= 0;
566  data->filename= filename;
567 
568  fn_format(tmp_name, filename, "", "", MY_UNPACK_FILENAME);
569  if ((data->fd = my_open(tmp_name, O_RDONLY, MYF(0))) < 0)
570  {
571  char errbuf[MYSYS_STRERROR_SIZE];
572  data->error_num= my_errno;
573  my_snprintf(data->error_msg, sizeof(data->error_msg)-1,
574  EE(EE_FILENOTFOUND), tmp_name, data->error_num,
575  my_strerror(errbuf, sizeof(errbuf), data->error_num));
576  return 1;
577  }
578  return 0; /* ok */
579 }
580 
581 
582 /*
583  Read data for LOAD LOCAL INFILE
584 
585  SYNOPSIS
586  default_local_infile_read()
587  ptr Points to handle allocated by _init
588  buf Read data here
589  buf_len Ammount of data to read
590 
591  RETURN
592  > 0 number of bytes read
593  == 0 End of data
594  < 0 Error
595 */
596 
597 static int default_local_infile_read(void *ptr, char *buf, uint buf_len)
598 {
599  int count;
601 
602  if ((count= (int) my_read(data->fd, (uchar *) buf, buf_len, MYF(0))) < 0)
603  {
604  char errbuf[MYSYS_STRERROR_SIZE];
605  data->error_num= EE_READ; /* the errmsg for not entire file read */
606  my_snprintf(data->error_msg, sizeof(data->error_msg)-1,
607  EE(EE_READ), data->filename,
608  my_errno, my_strerror(errbuf, sizeof(errbuf), my_errno));
609  }
610  return count;
611 }
612 
613 
614 /*
615  Read data for LOAD LOCAL INFILE
616 
617  SYNOPSIS
618  default_local_infile_end()
619  ptr Points to handle allocated by _init
620  May be NULL if _init failed!
621 
622  RETURN
623 */
624 
625 static void default_local_infile_end(void *ptr)
626 {
628  if (data) /* If not error on open */
629  {
630  if (data->fd >= 0)
631  my_close(data->fd, MYF(MY_WME));
632  my_free(ptr);
633  }
634 }
635 
636 
637 /*
638  Return error from LOAD LOCAL INFILE
639 
640  SYNOPSIS
641  default_local_infile_end()
642  ptr Points to handle allocated by _init
643  May be NULL if _init failed!
644  error_msg Store error text here
645  error_msg_len Max lenght of error_msg
646 
647  RETURN
648  error message number
649 */
650 
651 static int
652 default_local_infile_error(void *ptr, char *error_msg, uint error_msg_len)
653 {
655  if (data) /* If not error on open */
656  {
657  strmake(error_msg, data->error_msg, error_msg_len);
658  return data->error_num;
659  }
660  /* This can only happen if we got error on malloc of handle */
661  strmov(error_msg, ER(CR_OUT_OF_MEMORY));
662  return CR_OUT_OF_MEMORY;
663 }
664 
665 
666 void
667 mysql_set_local_infile_handler(MYSQL *mysql,
668  int (*local_infile_init)(void **, const char *,
669  void *),
670  int (*local_infile_read)(void *, char *, uint),
671  void (*local_infile_end)(void *),
672  int (*local_infile_error)(void *, char *, uint),
673  void *userdata)
674 {
675  mysql->options.local_infile_init= local_infile_init;
676  mysql->options.local_infile_read= local_infile_read;
677  mysql->options.local_infile_end= local_infile_end;
678  mysql->options.local_infile_error= local_infile_error;
679  mysql->options.local_infile_userdata = userdata;
680 }
681 
682 
683 void mysql_set_local_infile_default(MYSQL *mysql)
684 {
685  mysql->options.local_infile_init= default_local_infile_init;
686  mysql->options.local_infile_read= default_local_infile_read;
687  mysql->options.local_infile_end= default_local_infile_end;
688  mysql->options.local_infile_error= default_local_infile_error;
689 }
690 
691 
692 /**************************************************************************
693  Do a query. If query returned rows, free old rows.
694  Read data by mysql_store_result or by repeat call of mysql_fetch_row
695 **************************************************************************/
696 
697 int STDCALL
698 mysql_query(MYSQL *mysql, const char *query)
699 {
700  return mysql_real_query(mysql,query, (uint) strlen(query));
701 }
702 
703 
704 /**************************************************************************
705  Return next field of the query results
706 **************************************************************************/
707 
708 MYSQL_FIELD * STDCALL
709 mysql_fetch_field(MYSQL_RES *result)
710 {
711  if (result->current_field >= result->field_count)
712  return(NULL);
713  return &result->fields[result->current_field++];
714 }
715 
716 
717 /**************************************************************************
718  Move to a specific row and column
719 **************************************************************************/
720 
721 void STDCALL
722 mysql_data_seek(MYSQL_RES *result, my_ulonglong row)
723 {
724  MYSQL_ROWS *tmp=0;
725  DBUG_PRINT("info",("mysql_data_seek(%ld)",(long) row));
726  if (result->data)
727  for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
728  result->current_row=0;
729  result->data_cursor = tmp;
730 }
731 
732 
733 /*************************************************************************
734  put the row or field cursor one a position one got from mysql_row_tell()
735  This doesn't restore any data. The next mysql_fetch_row or
736  mysql_fetch_field will return the next row or field after the last used
737 *************************************************************************/
738 
739 MYSQL_ROW_OFFSET STDCALL
740 mysql_row_seek(MYSQL_RES *result, MYSQL_ROW_OFFSET row)
741 {
742  MYSQL_ROW_OFFSET return_value=result->data_cursor;
743  result->current_row= 0;
744  result->data_cursor= row;
745  return return_value;
746 }
747 
748 
749 MYSQL_FIELD_OFFSET STDCALL
750 mysql_field_seek(MYSQL_RES *result, MYSQL_FIELD_OFFSET field_offset)
751 {
752  MYSQL_FIELD_OFFSET return_value=result->current_field;
753  result->current_field=field_offset;
754  return return_value;
755 }
756 
757 
758 /*****************************************************************************
759  List all databases
760 *****************************************************************************/
761 
762 MYSQL_RES * STDCALL
763 mysql_list_dbs(MYSQL *mysql, const char *wild)
764 {
765  char buff[255];
766  DBUG_ENTER("mysql_list_dbs");
767 
768  append_wild(strmov(buff,"show databases"),buff+sizeof(buff),wild);
769  if (mysql_query(mysql,buff))
770  DBUG_RETURN(0);
771  DBUG_RETURN (mysql_store_result(mysql));
772 }
773 
774 
775 /*****************************************************************************
776  List all tables in a database
777  If wild is given then only the tables matching wild is returned
778 *****************************************************************************/
779 
780 MYSQL_RES * STDCALL
781 mysql_list_tables(MYSQL *mysql, const char *wild)
782 {
783  char buff[255];
784  DBUG_ENTER("mysql_list_tables");
785 
786  append_wild(strmov(buff,"show tables"),buff+sizeof(buff),wild);
787  if (mysql_query(mysql,buff))
788  DBUG_RETURN(0);
789  DBUG_RETURN (mysql_store_result(mysql));
790 }
791 
792 
793 MYSQL_FIELD *cli_list_fields(MYSQL *mysql)
794 {
795  MYSQL_DATA *query;
796  if (!(query= cli_read_rows(mysql,(MYSQL_FIELD*) 0,
797  protocol_41(mysql) ? 8 : 6)))
798  return NULL;
799 
800  mysql->field_count= (uint) query->rows;
801  return unpack_fields(mysql, query,&mysql->field_alloc,
802  mysql->field_count, 1, mysql->server_capabilities);
803 }
804 
805 
806 /**************************************************************************
807  List all fields in a table
808  If wild is given then only the fields matching wild is returned
809  Instead of this use query:
810  show fields in 'table' like "wild"
811 **************************************************************************/
812 
813 MYSQL_RES * STDCALL
814 mysql_list_fields(MYSQL *mysql, const char *table, const char *wild)
815 {
816  MYSQL_RES *result;
817  MYSQL_FIELD *fields;
818  char buff[258],*end;
819  DBUG_ENTER("mysql_list_fields");
820  DBUG_PRINT("enter",("table: '%s' wild: '%s'",table,wild ? wild : ""));
821 
822  end=strmake(strmake(buff, table,128)+1,wild ? wild : "",128);
823  free_old_query(mysql);
824  if (simple_command(mysql, COM_FIELD_LIST, (uchar*) buff,
825  (ulong) (end-buff), 1) ||
826  !(fields= (*mysql->methods->list_fields)(mysql)))
827  DBUG_RETURN(NULL);
828 
829  if (!(result = (MYSQL_RES *) my_malloc(sizeof(MYSQL_RES),
830  MYF(MY_WME | MY_ZEROFILL))))
831  DBUG_RETURN(NULL);
832 
833  result->methods= mysql->methods;
834  result->field_alloc=mysql->field_alloc;
835  mysql->fields=0;
836  result->field_count = mysql->field_count;
837  result->fields= fields;
838  result->eof=1;
839  DBUG_RETURN(result);
840 }
841 
842 /* List all running processes (threads) in server */
843 
844 MYSQL_RES * STDCALL
845 mysql_list_processes(MYSQL *mysql)
846 {
847  MYSQL_DATA *fields;
848  uint field_count;
849  uchar *pos;
850  DBUG_ENTER("mysql_list_processes");
851 
852  LINT_INIT(fields);
853  if (simple_command(mysql,COM_PROCESS_INFO,0,0,0))
854  DBUG_RETURN(0);
855  free_old_query(mysql);
856  pos=(uchar*) mysql->net.read_pos;
857  field_count=(uint) net_field_length(&pos);
858  if (!(fields = (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*) 0,
859  protocol_41(mysql) ? 7 : 5)))
860  DBUG_RETURN(NULL);
861  if (!(mysql->fields=unpack_fields(mysql, fields,&mysql->field_alloc,field_count,0,
862  mysql->server_capabilities)))
863  DBUG_RETURN(0);
864  mysql->status=MYSQL_STATUS_GET_RESULT;
865  mysql->field_count=field_count;
866  DBUG_RETURN(mysql_store_result(mysql));
867 }
868 
869 
870 #ifdef USE_OLD_FUNCTIONS
871 int STDCALL
872 mysql_create_db(MYSQL *mysql, const char *db)
873 {
874  DBUG_ENTER("mysql_createdb");
875  DBUG_PRINT("enter",("db: %s",db));
876  DBUG_RETURN(simple_command(mysql,COM_CREATE_DB,db, (ulong) strlen(db),0));
877 }
878 
879 
880 int STDCALL
881 mysql_drop_db(MYSQL *mysql, const char *db)
882 {
883  DBUG_ENTER("mysql_drop_db");
884  DBUG_PRINT("enter",("db: %s",db));
885  DBUG_RETURN(simple_command(mysql,COM_DROP_DB,db,(ulong) strlen(db),0));
886 }
887 #endif
888 
889 
890 int STDCALL
891 mysql_shutdown(MYSQL *mysql, enum mysql_enum_shutdown_level shutdown_level)
892 {
893  uchar level[1];
894  DBUG_ENTER("mysql_shutdown");
895  level[0]= (uchar) shutdown_level;
896  DBUG_RETURN(simple_command(mysql, COM_SHUTDOWN, level, 1, 0));
897 }
898 
899 
900 int STDCALL
901 mysql_refresh(MYSQL *mysql,uint options)
902 {
903  uchar bits[1];
904  DBUG_ENTER("mysql_refresh");
905  bits[0]= (uchar) options;
906  DBUG_RETURN(simple_command(mysql, COM_REFRESH, bits, 1, 0));
907 }
908 
909 
910 int STDCALL
911 mysql_kill(MYSQL *mysql,ulong pid)
912 {
913  uchar buff[4];
914  DBUG_ENTER("mysql_kill");
915  /*
916  Sanity check: if ulong is 64-bits, user can submit a PID here that
917  overflows our 32-bit parameter to the somewhat obsolete COM_PROCESS_KILL.
918  If this is the case, we'll flag an error here.
919  The SQL statement KILL CONNECTION is the safer option here.
920  There is an analog of this failsafe in the server as we might see old
921  libmysql connection to a new server as well as the other way around.
922  */
923  if (pid & (~0xfffffffful))
924  DBUG_RETURN(CR_INVALID_CONN_HANDLE);
925  int4store(buff,pid);
926  DBUG_RETURN(simple_command(mysql,COM_PROCESS_KILL,buff,sizeof(buff),0));
927 }
928 
929 
930 int STDCALL
931 mysql_set_server_option(MYSQL *mysql, enum enum_mysql_set_option option)
932 {
933  uchar buff[2];
934  DBUG_ENTER("mysql_set_server_option");
935  int2store(buff, (uint) option);
936  DBUG_RETURN(simple_command(mysql, COM_SET_OPTION, buff, sizeof(buff), 0));
937 }
938 
939 
940 int STDCALL
941 mysql_dump_debug_info(MYSQL *mysql)
942 {
943  DBUG_ENTER("mysql_dump_debug_info");
944  DBUG_RETURN(simple_command(mysql,COM_DEBUG,0,0,0));
945 }
946 
947 
948 const char *cli_read_statistics(MYSQL *mysql)
949 {
950  mysql->net.read_pos[mysql->packet_length]=0; /* End of stat string */
951  if (!mysql->net.read_pos[0])
952  {
953  set_mysql_error(mysql, CR_WRONG_HOST_INFO, unknown_sqlstate);
954  return mysql->net.last_error;
955  }
956  return (char*) mysql->net.read_pos;
957 }
958 
959 
960 const char * STDCALL
961 mysql_stat(MYSQL *mysql)
962 {
963  DBUG_ENTER("mysql_stat");
964  if (simple_command(mysql,COM_STATISTICS,0,0,0))
965  DBUG_RETURN(mysql->net.last_error);
966  DBUG_RETURN((*mysql->methods->read_statistics)(mysql));
967 }
968 
969 
970 int STDCALL
971 mysql_ping(MYSQL *mysql)
972 {
973  int res;
974  DBUG_ENTER("mysql_ping");
975  res= simple_command(mysql,COM_PING,0,0,0);
976  if (res == CR_SERVER_LOST && mysql->reconnect)
977  res= simple_command(mysql,COM_PING,0,0,0);
978  DBUG_RETURN(res);
979 }
980 
981 
982 const char * STDCALL
983 mysql_get_server_info(MYSQL *mysql)
984 {
985  return((char*) mysql->server_version);
986 }
987 
988 
989 const char * STDCALL
990 mysql_get_host_info(MYSQL *mysql)
991 {
992  return(mysql->host_info);
993 }
994 
995 
996 uint STDCALL
997 mysql_get_proto_info(MYSQL *mysql)
998 {
999  return (mysql->protocol_version);
1000 }
1001 
1002 const char * STDCALL
1003 mysql_get_client_info(void)
1004 {
1005  return (char*) MYSQL_SERVER_VERSION;
1006 }
1007 
1008 ulong STDCALL mysql_get_client_version(void)
1009 {
1010  return MYSQL_VERSION_ID;
1011 }
1012 
1013 my_bool STDCALL mysql_eof(MYSQL_RES *res)
1014 {
1015  return res->eof;
1016 }
1017 
1018 MYSQL_FIELD * STDCALL mysql_fetch_field_direct(MYSQL_RES *res,uint fieldnr)
1019 {
1020  return &(res)->fields[fieldnr];
1021 }
1022 
1023 MYSQL_FIELD * STDCALL mysql_fetch_fields(MYSQL_RES *res)
1024 {
1025  return (res)->fields;
1026 }
1027 
1028 MYSQL_ROW_OFFSET STDCALL mysql_row_tell(MYSQL_RES *res)
1029 {
1030  return res->data_cursor;
1031 }
1032 
1033 MYSQL_FIELD_OFFSET STDCALL mysql_field_tell(MYSQL_RES *res)
1034 {
1035  return (res)->current_field;
1036 }
1037 
1038 /* MYSQL */
1039 
1040 unsigned int STDCALL mysql_field_count(MYSQL *mysql)
1041 {
1042  return mysql->field_count;
1043 }
1044 
1045 my_ulonglong STDCALL mysql_affected_rows(MYSQL *mysql)
1046 {
1047  return mysql->affected_rows;
1048 }
1049 
1050 my_ulonglong STDCALL mysql_insert_id(MYSQL *mysql)
1051 {
1052  return mysql->insert_id;
1053 }
1054 
1055 const char *STDCALL mysql_sqlstate(MYSQL *mysql)
1056 {
1057  return mysql ? mysql->net.sqlstate : cant_connect_sqlstate;
1058 }
1059 
1060 uint STDCALL mysql_warning_count(MYSQL *mysql)
1061 {
1062  return mysql->warning_count;
1063 }
1064 
1065 const char *STDCALL mysql_info(MYSQL *mysql)
1066 {
1067  return mysql->info;
1068 }
1069 
1070 ulong STDCALL mysql_thread_id(MYSQL *mysql)
1071 {
1072  /*
1073  ulong may be 64-bit, but we currently only transmit 32-bit.
1074  mysql_thread_id() is usually used in conjunction with mysql_kill()
1075  which is similarly limited (and obsolete).
1076  SELECTION CONNECTION_ID() / KILL CONNECTION avoid this issue.
1077  */
1078  return (mysql)->thread_id;
1079 }
1080 
1081 const char * STDCALL mysql_character_set_name(MYSQL *mysql)
1082 {
1083  return mysql->charset->csname;
1084 }
1085 
1086 void STDCALL mysql_get_character_set_info(MYSQL *mysql, MY_CHARSET_INFO *csinfo)
1087 {
1088  csinfo->number = mysql->charset->number;
1089  csinfo->state = mysql->charset->state;
1090  csinfo->csname = mysql->charset->csname;
1091  csinfo->name = mysql->charset->name;
1092  csinfo->comment = mysql->charset->comment;
1093  csinfo->mbminlen = mysql->charset->mbminlen;
1094  csinfo->mbmaxlen = mysql->charset->mbmaxlen;
1095 
1096  if (mysql->options.charset_dir)
1097  csinfo->dir = mysql->options.charset_dir;
1098  else
1099  csinfo->dir = charsets_dir;
1100 }
1101 
1102 uint STDCALL mysql_thread_safe(void)
1103 {
1104  return 1;
1105 }
1106 
1107 
1108 my_bool STDCALL mysql_embedded(void)
1109 {
1110 #ifdef EMBEDDED_LIBRARY
1111  return 1;
1112 #else
1113  return 0;
1114 #endif
1115 }
1116 
1117 /****************************************************************************
1118  Some support functions
1119 ****************************************************************************/
1120 
1121 /*
1122  Functions called my my_net_init() to set some application specific variables
1123 */
1124 
1125 void my_net_local_init(NET *net)
1126 {
1127  net->max_packet= (uint) net_buffer_length;
1128  my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
1129  my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
1130  net->retry_count= 1;
1131  net->max_packet_size= MY_MAX(net_buffer_length, max_allowed_packet);
1132 }
1133 
1134 /*
1135  This function is used to create HEX string that you
1136  can use in a SQL statement in of the either ways:
1137  INSERT INTO blob_column VALUES (0xAABBCC); (any MySQL version)
1138  INSERT INTO blob_column VALUES (X'AABBCC'); (4.1 and higher)
1139 
1140  The string in "from" is encoded to a HEX string.
1141  The result is placed in "to" and a terminating null byte is appended.
1142 
1143  The string pointed to by "from" must be "length" bytes long.
1144  You must allocate the "to" buffer to be at least length*2+1 bytes long.
1145  Each character needs two bytes, and you need room for the terminating
1146  null byte. When mysql_hex_string() returns, the contents of "to" will
1147  be a null-terminated string. The return value is the length of the
1148  encoded string, not including the terminating null character.
1149 
1150  The return value does not contain any leading 0x or a leading X' and
1151  trailing '. The caller must supply whichever of those is desired.
1152 */
1153 
1154 ulong STDCALL
1155 mysql_hex_string(char *to, const char *from, ulong length)
1156 {
1157  char *to0= to;
1158  const char *end;
1159 
1160  for (end= from + length; from < end; from++)
1161  {
1162  *to++= _dig_vec_upper[((unsigned char) *from) >> 4];
1163  *to++= _dig_vec_upper[((unsigned char) *from) & 0x0F];
1164  }
1165  *to= '\0';
1166  return (ulong) (to-to0);
1167 }
1168 
1169 /*
1170  Add escape characters to a string (blob?) to make it suitable for a insert
1171  to should at least have place for length*2+1 chars
1172  Returns the length of the to string
1173 */
1174 
1175 ulong STDCALL
1176 mysql_escape_string(char *to,const char *from,ulong length)
1177 {
1178  return (uint) escape_string_for_mysql(default_charset_info, to, 0, from, length);
1179 }
1180 
1181 ulong STDCALL
1182 mysql_real_escape_string(MYSQL *mysql, char *to,const char *from,
1183  ulong length)
1184 {
1185  if (mysql->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
1186  return (uint) escape_quotes_for_mysql(mysql->charset, to, 0, from, length);
1187  return (uint) escape_string_for_mysql(mysql->charset, to, 0, from, length);
1188 }
1189 
1190 void STDCALL
1191 myodbc_remove_escape(MYSQL *mysql,char *name)
1192 {
1193  char *to;
1194 #ifdef USE_MB
1195  my_bool use_mb_flag=use_mb(mysql->charset);
1196  char *UNINIT_VAR(end);
1197  if (use_mb_flag)
1198  for (end=name; *end ; end++) ;
1199 #endif
1200 
1201  for (to=name ; *name ; name++)
1202  {
1203 #ifdef USE_MB
1204  int l;
1205  if (use_mb_flag && (l = my_ismbchar( mysql->charset, name , end ) ) )
1206  {
1207  while (l--)
1208  *to++ = *name++;
1209  name--;
1210  continue;
1211  }
1212 #endif
1213  if (*name == '\\' && name[1])
1214  name++;
1215  *to++= *name;
1216  }
1217  *to=0;
1218 }
1219 
1220 /********************************************************************
1221  Implementation of new client API for 4.1 version.
1222 
1223  mysql_stmt_* are real prototypes used by applications.
1224 
1225  To make API work in embedded library all functions performing
1226  real I/O are prefixed with 'cli_' (abbreviated from 'Call Level
1227  Interface'). This functions are invoked via pointers set in
1228  MYSQL::methods structure. Embedded counterparts, prefixed with
1229  'emb_' reside in libmysqld/lib_sql.cc.
1230 *********************************************************************/
1231 
1232 /******************* Declarations ***********************************/
1233 
1234 /* Default number of rows fetched per one COM_STMT_FETCH command. */
1235 
1236 #define DEFAULT_PREFETCH_ROWS (ulong) 1
1237 
1238 /*
1239  These functions are called by function pointer MYSQL_STMT::read_row_func.
1240  Each function corresponds to one of the read methods:
1241  - mysql_stmt_fetch without prior mysql_stmt_store_result,
1242  - mysql_stmt_fetch when result is stored,
1243  - mysql_stmt_fetch when there are no rows (always returns MYSQL_NO_DATA)
1244 */
1245 
1246 static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row);
1247 static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row);
1248 static int stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row);
1249 static int stmt_read_row_no_data(MYSQL_STMT *stmt, unsigned char **row);
1250 static int stmt_read_row_no_result_set(MYSQL_STMT *stmt, unsigned char **row);
1251 
1252 /*
1253  This function is used in mysql_stmt_store_result if
1254  STMT_ATTR_UPDATE_MAX_LENGTH attribute is set.
1255 */
1256 static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data);
1257 static my_bool setup_one_fetch_function(MYSQL_BIND *, MYSQL_FIELD *field);
1258 
1259 /* Auxilary function used to reset statement handle. */
1260 
1261 #define RESET_SERVER_SIDE 1
1262 #define RESET_LONG_DATA 2
1263 #define RESET_STORE_RESULT 4
1264 #define RESET_CLEAR_ERROR 8
1265 
1266 static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags);
1267 
1268 /*
1269  Maximum sizes of MYSQL_TYPE_DATE, MYSQL_TYPE_TIME, MYSQL_TYPE_DATETIME
1270  values stored in network buffer.
1271 */
1272 
1273 /* 1 (length) + 2 (year) + 1 (month) + 1 (day) */
1274 #define MAX_DATE_REP_LENGTH 5
1275 
1276 /*
1277  1 (length) + 1 (is negative) + 4 (day count) + 1 (hour)
1278  + 1 (minute) + 1 (seconds) + 4 (microseconds)
1279 */
1280 #define MAX_TIME_REP_LENGTH 13
1281 
1282 /*
1283  1 (length) + 2 (year) + 1 (month) + 1 (day) +
1284  1 (hour) + 1 (minute) + 1 (second) + 4 (microseconds)
1285 */
1286 #define MAX_DATETIME_REP_LENGTH 12
1287 
1288 #define MAX_DOUBLE_STRING_REP_LENGTH 331
1289 
1290 /* A macro to check truncation errors */
1291 
1292 #define IS_TRUNCATED(value, is_unsigned, min, max, umax) \
1293  ((is_unsigned) ? (((value) > (umax) || (value) < 0) ? 1 : 0) : \
1294  (((value) > (max) || (value) < (min)) ? 1 : 0))
1295 
1296 #define BIND_RESULT_DONE 1
1297 /*
1298  We report truncations only if at least one of MYSQL_BIND::error
1299  pointers is set. In this case stmt->bind_result_done |-ed with
1300  this flag.
1301 */
1302 #define REPORT_DATA_TRUNCATION 2
1303 
1304 /**************** Misc utility functions ****************************/
1305 
1306 /*
1307  Reallocate the NET package to have at least length bytes available.
1308 
1309  SYNPOSIS
1310  my_realloc_str()
1311  net The NET structure to modify.
1312  length Ensure that net->buff has space for at least
1313  this number of bytes.
1314 
1315  RETURN VALUES
1316  0 Success.
1317  1 Error, i.e. out of memory or requested packet size is bigger
1318  than max_allowed_packet. The error code is stored in net->last_errno.
1319 */
1320 
1321 static my_bool my_realloc_str(NET *net, ulong length)
1322 {
1323  ulong buf_length= (ulong) (net->write_pos - net->buff);
1324  my_bool res=0;
1325  DBUG_ENTER("my_realloc_str");
1326  if (buf_length + length > net->max_packet)
1327  {
1328  res= net_realloc(net, buf_length + length);
1329  if (res)
1330  {
1331  strmov(net->sqlstate, unknown_sqlstate);
1332  strmov(net->last_error, ER(net->last_errno));
1333  }
1334  net->write_pos= net->buff+ buf_length;
1335  }
1336  DBUG_RETURN(res);
1337 }
1338 
1339 
1340 static void stmt_clear_error(MYSQL_STMT *stmt)
1341 {
1342  if (stmt->last_errno)
1343  {
1344  stmt->last_errno= 0;
1345  stmt->last_error[0]= '\0';
1346  strmov(stmt->sqlstate, not_error_sqlstate);
1347  }
1348 }
1349 
1355 void set_stmt_error(MYSQL_STMT * stmt, int errcode,
1356  const char *sqlstate, const char *err)
1357 {
1358  DBUG_ENTER("set_stmt_error");
1359  DBUG_PRINT("enter", ("error: %d '%s'", errcode, ER(errcode)));
1360  DBUG_ASSERT(stmt != 0);
1361 
1362  if (err == 0)
1363  err= ER(errcode);
1364 
1365  stmt->last_errno= errcode;
1366  strmov(stmt->last_error, ER(errcode));
1367  strmov(stmt->sqlstate, sqlstate);
1368 
1369  DBUG_VOID_RETURN;
1370 }
1371 
1372 
1380 void set_stmt_errmsg(MYSQL_STMT *stmt, NET *net)
1381 {
1382  DBUG_ENTER("set_stmt_errmsg");
1383  DBUG_PRINT("enter", ("error: %d/%s '%s'",
1384  net->last_errno,
1385  net->sqlstate,
1386  net->last_error));
1387  DBUG_ASSERT(stmt != 0);
1388 
1389  stmt->last_errno= net->last_errno;
1390  if (net->last_error && net->last_error[0])
1391  strmov(stmt->last_error, net->last_error);
1392  strmov(stmt->sqlstate, net->sqlstate);
1393 
1394  DBUG_VOID_RETURN;
1395 }
1396 
1397 /*
1398  Read and unpack server reply to COM_STMT_PREPARE command (sent from
1399  mysql_stmt_prepare).
1400 
1401  SYNOPSIS
1402  cli_read_prepare_result()
1403  mysql connection handle
1404  stmt statement handle
1405 
1406  RETURN VALUES
1407  0 ok
1408  1 error
1409 */
1410 
1411 my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
1412 {
1413  uchar *pos;
1414  uint field_count, param_count;
1415  ulong packet_length;
1416  MYSQL_DATA *fields_data;
1417  DBUG_ENTER("cli_read_prepare_result");
1418 
1419  if ((packet_length= cli_safe_read(mysql)) == packet_error)
1420  DBUG_RETURN(1);
1421  mysql->warning_count= 0;
1422 
1423  pos= (uchar*) mysql->net.read_pos;
1424  stmt->stmt_id= uint4korr(pos+1); pos+= 5;
1425  /* Number of columns in result set */
1426  field_count= uint2korr(pos); pos+= 2;
1427  /* Number of placeholders in the statement */
1428  param_count= uint2korr(pos); pos+= 2;
1429  if (packet_length >= 12)
1430  mysql->warning_count= uint2korr(pos+1);
1431 
1432  if (param_count != 0)
1433  {
1434  MYSQL_DATA *param_data;
1435 
1436  /* skip parameters data: we don't support it yet */
1437  if (!(param_data= (*mysql->methods->read_rows)(mysql, (MYSQL_FIELD*)0, 7)))
1438  DBUG_RETURN(1);
1439  free_rows(param_data);
1440  }
1441 
1442  if (field_count != 0)
1443  {
1444  if (!(mysql->server_status & SERVER_STATUS_AUTOCOMMIT))
1445  mysql->server_status|= SERVER_STATUS_IN_TRANS;
1446 
1447  if (!(fields_data= (*mysql->methods->read_rows)(mysql,(MYSQL_FIELD*)0,7)))
1448  DBUG_RETURN(1);
1449  if (!(stmt->fields= unpack_fields(mysql, fields_data,&stmt->mem_root,
1450  field_count,0,
1451  mysql->server_capabilities)))
1452  DBUG_RETURN(1);
1453  }
1454  stmt->field_count= field_count;
1455  stmt->param_count= (ulong) param_count;
1456  DBUG_PRINT("exit",("field_count: %u param_count: %u warning_count: %u",
1457  field_count, param_count, (uint) mysql->warning_count));
1458 
1459  DBUG_RETURN(0);
1460 }
1461 
1462 
1463 /*
1464  Allocate memory and init prepared statement structure.
1465 
1466  SYNOPSIS
1467  mysql_stmt_init()
1468  mysql connection handle
1469 
1470  DESCRIPTION
1471  This is an entry point of the new API. Returned handle stands for
1472  a server-side prepared statement. Memory for this structure (~700
1473  bytes) is allocated using 'malloc'. Once created, the handle can be
1474  reused many times. Created statement handle is bound to connection
1475  handle provided to this call: its lifetime is limited by lifetime
1476  of connection.
1477  'mysql_stmt_init()' is a pure local call, server side structure is
1478  created only in mysql_stmt_prepare.
1479  Next steps you may want to make:
1480  - set a statement attribute (mysql_stmt_attr_set()),
1481  - prepare statement handle with a query (mysql_stmt_prepare()),
1482  - close statement handle and free its memory (mysql_stmt_close()),
1483  - reset statement with mysql_stmt_reset() (a no-op which will
1484  just return).
1485  Behaviour of the rest of API calls on this statement is not defined yet
1486  (though we're working on making each wrong call sequence return
1487  error).
1488 
1489  RETURN VALUE
1490  statement structure upon success and NULL if out of
1491  memory
1492 */
1493 
1494 MYSQL_STMT * STDCALL
1495 mysql_stmt_init(MYSQL *mysql)
1496 {
1497  MYSQL_STMT *stmt;
1498  DBUG_ENTER("mysql_stmt_init");
1499 
1500  if (!(stmt=
1501  (MYSQL_STMT *) my_malloc(sizeof (MYSQL_STMT),
1502  MYF(MY_WME | MY_ZEROFILL))) ||
1503  !(stmt->extension=
1504  (MYSQL_STMT_EXT *) my_malloc(sizeof (MYSQL_STMT_EXT),
1505  MYF(MY_WME | MY_ZEROFILL))))
1506  {
1507  set_mysql_error(mysql, CR_OUT_OF_MEMORY, unknown_sqlstate);
1508  my_free(stmt);
1509  DBUG_RETURN(NULL);
1510  }
1511 
1512  init_alloc_root(&stmt->mem_root, 2048, 2048);
1513  init_alloc_root(&stmt->result.alloc, 4096, 4096);
1514  stmt->result.alloc.min_malloc= sizeof(MYSQL_ROWS);
1515  mysql->stmts= list_add(mysql->stmts, &stmt->list);
1516  stmt->list.data= stmt;
1517  stmt->state= MYSQL_STMT_INIT_DONE;
1518  stmt->mysql= mysql;
1519  stmt->read_row_func= stmt_read_row_no_result_set;
1520  stmt->prefetch_rows= DEFAULT_PREFETCH_ROWS;
1521  strmov(stmt->sqlstate, not_error_sqlstate);
1522  /* The rest of statement members was zeroed inside malloc */
1523 
1524  init_alloc_root(&stmt->extension->fields_mem_root, 2048, 0);
1525 
1526  DBUG_RETURN(stmt);
1527 }
1528 
1529 
1530 /*
1531  Prepare server side statement with query.
1532 
1533  SYNOPSIS
1534  mysql_stmt_prepare()
1535  stmt statement handle
1536  query statement to prepare
1537  length statement length
1538 
1539  DESCRIPTION
1540  Associate statement with statement handle. This is done both on
1541  client and server sides. At this point the server parses given query
1542  and creates an internal structure to represent it.
1543  Next steps you may want to make:
1544  - find out if this statement returns a result set by
1545  calling mysql_stmt_field_count(), and get result set metadata
1546  with mysql_stmt_result_metadata(),
1547  - if query contains placeholders, bind input parameters to placeholders
1548  using mysql_stmt_bind_param(),
1549  - otherwise proceed directly to mysql_stmt_execute().
1550 
1551  IMPLEMENTATION NOTES
1552  - if this is a re-prepare of the statement, first close previous data
1553  structure on the server and free old statement data
1554  - then send the query to server and get back number of placeholders,
1555  number of columns in result set (if any), and result set metadata.
1556  At the same time allocate memory for input and output parameters
1557  to have less checks in mysql_stmt_bind_{param, result}.
1558 
1559  RETURN VALUES
1560  0 success
1561  !0 error
1562 */
1563 
1564 int STDCALL
1565 mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query, ulong length)
1566 {
1567  MYSQL *mysql= stmt->mysql;
1568  DBUG_ENTER("mysql_stmt_prepare");
1569 
1570  if (!mysql)
1571  {
1572  /* mysql can be reset in mysql_close called from mysql_reconnect */
1573  set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
1574  DBUG_RETURN(1);
1575  }
1576 
1577  /*
1578  Reset the last error in any case: that would clear the statement
1579  if the previous prepare failed.
1580  */
1581  stmt->last_errno= 0;
1582  stmt->last_error[0]= '\0';
1583 
1584  if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
1585  {
1586  /* This is second prepare with another statement */
1587  uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
1588 
1589  if (reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT))
1590  DBUG_RETURN(1);
1591  /*
1592  These members must be reset for API to
1593  function in case of error or misuse.
1594  */
1595  stmt->bind_param_done= stmt->bind_result_done= FALSE;
1596  stmt->param_count= stmt->field_count= 0;
1597  free_root(&stmt->mem_root, MYF(MY_KEEP_PREALLOC));
1598  free_root(&stmt->extension->fields_mem_root, MYF(0));
1599 
1600  int4store(buff, stmt->stmt_id);
1601 
1602  /*
1603  Close statement in server
1604 
1605  If there was a 'use' result from another statement, or from
1606  mysql_use_result it won't be freed in mysql_stmt_free_result and
1607  we should get 'Commands out of sync' here.
1608  */
1609  stmt->state= MYSQL_STMT_INIT_DONE;
1610  if (stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt))
1611  {
1612  set_stmt_errmsg(stmt, &mysql->net);
1613  DBUG_RETURN(1);
1614  }
1615  }
1616 
1617  if (stmt_command(mysql, COM_STMT_PREPARE, (const uchar*) query, length, stmt))
1618  {
1619  set_stmt_errmsg(stmt, &mysql->net);
1620  DBUG_RETURN(1);
1621  }
1622 
1623  if ((*mysql->methods->read_prepare_result)(mysql, stmt))
1624  {
1625  set_stmt_errmsg(stmt, &mysql->net);
1626  DBUG_RETURN(1);
1627  }
1628 
1629  /*
1630  alloc_root will return valid address even in case when param_count
1631  and field_count are zero. Thus we should never rely on stmt->bind
1632  or stmt->params when checking for existence of placeholders or
1633  result set.
1634  */
1635  if (!(stmt->params= (MYSQL_BIND *) alloc_root(&stmt->mem_root,
1636  sizeof(MYSQL_BIND)*
1637  (stmt->param_count +
1638  stmt->field_count))))
1639  {
1640  set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
1641  DBUG_RETURN(1);
1642  }
1643  stmt->bind= stmt->params + stmt->param_count;
1644  stmt->state= MYSQL_STMT_PREPARE_DONE;
1645  DBUG_PRINT("info", ("Parameter count: %u", stmt->param_count));
1646  DBUG_RETURN(0);
1647 }
1648 
1649 /*
1650  Get result set metadata from reply to mysql_stmt_execute.
1651  This is used mainly for SHOW commands, as metadata for these
1652  commands is sent only with result set.
1653  To be removed when all commands will fully support prepared mode.
1654 */
1655 
1656 static void alloc_stmt_fields(MYSQL_STMT *stmt)
1657 {
1658  MYSQL_FIELD *fields, *field, *end;
1659  MEM_ROOT *fields_mem_root= &stmt->extension->fields_mem_root;
1660  MYSQL *mysql= stmt->mysql;
1661 
1662  DBUG_ASSERT(stmt->field_count);
1663 
1664  free_root(fields_mem_root, MYF(0));
1665 
1666  /*
1667  Get the field information for non-select statements
1668  like SHOW and DESCRIBE commands
1669  */
1670  if (!(stmt->fields= (MYSQL_FIELD *) alloc_root(fields_mem_root,
1671  sizeof(MYSQL_FIELD) *
1672  stmt->field_count)) ||
1673  !(stmt->bind= (MYSQL_BIND *) alloc_root(fields_mem_root,
1674  sizeof(MYSQL_BIND) *
1675  stmt->field_count)))
1676  {
1677  set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
1678  return;
1679  }
1680 
1681  for (fields= mysql->fields, end= fields+stmt->field_count,
1682  field= stmt->fields;
1683  field && fields < end; fields++, field++)
1684  {
1685  *field= *fields; /* To copy all numeric parts. */
1686  field->catalog= strmake_root(fields_mem_root,
1687  fields->catalog,
1688  fields->catalog_length);
1689  field->db= strmake_root(fields_mem_root,
1690  fields->db,
1691  fields->db_length);
1692  field->table= strmake_root(fields_mem_root,
1693  fields->table,
1694  fields->table_length);
1695  field->org_table= strmake_root(fields_mem_root,
1696  fields->org_table,
1697  fields->org_table_length);
1698  field->name= strmake_root(fields_mem_root,
1699  fields->name,
1700  fields->name_length);
1701  field->org_name= strmake_root(fields_mem_root,
1702  fields->org_name,
1703  fields->org_name_length);
1704  if (fields->def)
1705  {
1706  field->def= strmake_root(fields_mem_root,
1707  fields->def,
1708  fields->def_length);
1709  field->def_length= fields->def_length;
1710  }
1711  else
1712  {
1713  field->def= NULL;
1714  field->def_length= 0;
1715  }
1716  field->extension= 0; /* Avoid dangling links. */
1717  field->max_length= 0; /* max_length is set in mysql_stmt_store_result() */
1718  }
1719 }
1720 
1721 
1730 static void update_stmt_fields(MYSQL_STMT *stmt)
1731 {
1732  MYSQL_FIELD *field= stmt->mysql->fields;
1733  MYSQL_FIELD *field_end= field + stmt->field_count;
1734  MYSQL_FIELD *stmt_field= stmt->fields;
1735  MYSQL_BIND *my_bind= stmt->bind_result_done ? stmt->bind : 0;
1736 
1737  if (stmt->field_count != stmt->mysql->field_count)
1738  {
1739  /*
1740  The tables used in the statement were altered,
1741  and the query now returns a different number of columns.
1742  There is no way to continue without reallocating the bind
1743  array:
1744  - if the number of columns increased, mysql_stmt_fetch()
1745  will write beyond allocated memory
1746  - if the number of columns decreased, some user-bound
1747  buffers will be left unassigned without user knowing
1748  that.
1749  */
1750  set_stmt_error(stmt, CR_NEW_STMT_METADATA, unknown_sqlstate, NULL);
1751  return;
1752  }
1753 
1754  for (; field < field_end; ++field, ++stmt_field)
1755  {
1756  stmt_field->charsetnr= field->charsetnr;
1757  stmt_field->length = field->length;
1758  stmt_field->type = field->type;
1759  stmt_field->flags = field->flags;
1760  stmt_field->decimals = field->decimals;
1761  if (my_bind)
1762  {
1763  /* Ignore return value: it should be 0 if bind_result succeeded. */
1764  (void) setup_one_fetch_function(my_bind++, stmt_field);
1765  }
1766  }
1767 }
1768 
1769 /*
1770  Returns prepared statement metadata in the form of a result set.
1771 
1772  SYNOPSIS
1773  mysql_stmt_result_metadata()
1774  stmt statement handle
1775 
1776  DESCRIPTION
1777  This function should be used after mysql_stmt_execute().
1778  You can safely check that prepared statement has a result set by calling
1779  mysql_stmt_field_count(): if number of fields is not zero, you can call
1780  this function to get fields metadata.
1781  Next steps you may want to make:
1782  - find out number of columns in result set by calling
1783  mysql_num_fields(res) (the same value is returned by
1784  mysql_stmt_field_count())
1785  - fetch metadata for any column with mysql_fetch_field,
1786  mysql_fetch_field_direct, mysql_fetch_fields, mysql_field_seek.
1787  - free returned MYSQL_RES structure with mysql_free_result.
1788  - proceed to binding of output parameters.
1789 
1790  RETURN
1791  NULL statement contains no result set or out of memory.
1792  In the latter case you can retreive error message
1793  with mysql_stmt_error.
1794  MYSQL_RES a result set with no rows
1795 */
1796 
1797 MYSQL_RES * STDCALL
1798 mysql_stmt_result_metadata(MYSQL_STMT *stmt)
1799 {
1800  MYSQL_RES *result;
1801  DBUG_ENTER("mysql_stmt_result_metadata");
1802 
1803  /*
1804  stmt->fields is only defined if stmt->field_count is not null;
1805  stmt->field_count is initialized in prepare.
1806  */
1807  if (!stmt->field_count)
1808  DBUG_RETURN(0);
1809 
1810  if (!(result=(MYSQL_RES*) my_malloc(sizeof(*result),
1811  MYF(MY_WME | MY_ZEROFILL))))
1812  {
1813  set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
1814  DBUG_RETURN(0);
1815  }
1816 
1817  result->methods= stmt->mysql->methods;
1818  result->eof= 1; /* Marker for buffered */
1819  result->fields= stmt->fields;
1820  result->field_count= stmt->field_count;
1821  /* The rest of members of 'result' was zeroed inside malloc */
1822  DBUG_RETURN(result);
1823 }
1824 
1825 
1826 /*
1827  Returns parameter columns meta information in the form of
1828  result set.
1829 
1830  SYNOPSYS
1831  mysql_stmt_param_metadata()
1832  stmt statement handle
1833 
1834  DESCRIPTION
1835  This function can be called after you prepared the statement handle
1836  with mysql_stmt_prepare().
1837  XXX: not implemented yet.
1838 
1839  RETURN
1840  MYSQL_RES on success, 0 if there is no metadata.
1841  Currently this function always returns 0.
1842 */
1843 
1844 MYSQL_RES * STDCALL
1845 mysql_stmt_param_metadata(MYSQL_STMT *stmt)
1846 {
1847  DBUG_ENTER("mysql_stmt_param_metadata");
1848 
1849  if (!stmt->param_count)
1850  DBUG_RETURN(0);
1851 
1852  /*
1853  TODO: Fix this when server sends the information.
1854  Till then keep a dummy prototype.
1855  */
1856  DBUG_RETURN(0);
1857 }
1858 
1859 
1860 /* Store type of parameter in network buffer. */
1861 
1862 static void store_param_type(unsigned char **pos, MYSQL_BIND *param)
1863 {
1864  uint typecode= param->buffer_type | (param->is_unsigned ? 32768 : 0);
1865  int2store(*pos, typecode);
1866  *pos+= 2;
1867 }
1868 
1869 
1870 /*
1871  Functions to store parameter data in network packet.
1872 
1873  SYNOPSIS
1874  store_param_xxx()
1875  net MySQL NET connection
1876  param MySQL bind param
1877 
1878  DESCRIPTION
1879  These funtions are invoked from mysql_stmt_execute() by
1880  MYSQL_BIND::store_param_func pointer. This pointer is set once per
1881  many executions in mysql_stmt_bind_param(). The caller must ensure
1882  that network buffer have enough capacity to store parameter
1883  (MYSQL_BIND::buffer_length contains needed number of bytes).
1884 */
1885 
1886 static void store_param_tinyint(NET *net, MYSQL_BIND *param)
1887 {
1888  *(net->write_pos++)= *(uchar *) param->buffer;
1889 }
1890 
1891 static void store_param_short(NET *net, MYSQL_BIND *param)
1892 {
1893  short value= *(short*) param->buffer;
1894  int2store(net->write_pos,value);
1895  net->write_pos+=2;
1896 }
1897 
1898 static void store_param_int32(NET *net, MYSQL_BIND *param)
1899 {
1900  int32 value= *(int32*) param->buffer;
1901  int4store(net->write_pos,value);
1902  net->write_pos+=4;
1903 }
1904 
1905 static void store_param_int64(NET *net, MYSQL_BIND *param)
1906 {
1907  longlong value= *(longlong*) param->buffer;
1908  int8store(net->write_pos,value);
1909  net->write_pos+= 8;
1910 }
1911 
1912 static void store_param_float(NET *net, MYSQL_BIND *param)
1913 {
1914  float value= *(float*) param->buffer;
1915  float4store(net->write_pos, value);
1916  net->write_pos+= 4;
1917 }
1918 
1919 static void store_param_double(NET *net, MYSQL_BIND *param)
1920 {
1921  double value= *(double*) param->buffer;
1922  float8store(net->write_pos, value);
1923  net->write_pos+= 8;
1924 }
1925 
1926 static void store_param_time(NET *net, MYSQL_BIND *param)
1927 {
1928  MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
1929  char buff[MAX_TIME_REP_LENGTH], *pos;
1930  uint length;
1931 
1932  pos= buff+1;
1933  pos[0]= tm->neg ? 1: 0;
1934  int4store(pos+1, tm->day);
1935  pos[5]= (uchar) tm->hour;
1936  pos[6]= (uchar) tm->minute;
1937  pos[7]= (uchar) tm->second;
1938  int4store(pos+8, tm->second_part);
1939  if (tm->second_part)
1940  length= 12;
1941  else if (tm->hour || tm->minute || tm->second || tm->day)
1942  length= 8;
1943  else
1944  length= 0;
1945  buff[0]= (char) length++;
1946  memcpy((char *)net->write_pos, buff, length);
1947  net->write_pos+= length;
1948 }
1949 
1950 static void net_store_datetime(NET *net, MYSQL_TIME *tm)
1951 {
1952  char buff[MAX_DATETIME_REP_LENGTH], *pos;
1953  uint length;
1954 
1955  pos= buff+1;
1956 
1957  int2store(pos, tm->year);
1958  pos[2]= (uchar) tm->month;
1959  pos[3]= (uchar) tm->day;
1960  pos[4]= (uchar) tm->hour;
1961  pos[5]= (uchar) tm->minute;
1962  pos[6]= (uchar) tm->second;
1963  int4store(pos+7, tm->second_part);
1964  if (tm->second_part)
1965  length= 11;
1966  else if (tm->hour || tm->minute || tm->second)
1967  length= 7;
1968  else if (tm->year || tm->month || tm->day)
1969  length= 4;
1970  else
1971  length= 0;
1972  buff[0]= (char) length++;
1973  memcpy((char *)net->write_pos, buff, length);
1974  net->write_pos+= length;
1975 }
1976 
1977 static void store_param_date(NET *net, MYSQL_BIND *param)
1978 {
1979  MYSQL_TIME tm= *((MYSQL_TIME *) param->buffer);
1980  tm.hour= tm.minute= tm.second= tm.second_part= 0;
1981  net_store_datetime(net, &tm);
1982 }
1983 
1984 static void store_param_datetime(NET *net, MYSQL_BIND *param)
1985 {
1986  MYSQL_TIME *tm= (MYSQL_TIME *) param->buffer;
1987  net_store_datetime(net, tm);
1988 }
1989 
1990 static void store_param_str(NET *net, MYSQL_BIND *param)
1991 {
1992  /* param->length is always set in mysql_stmt_bind_param */
1993  ulong length= *param->length;
1994  uchar *to= net_store_length(net->write_pos, length);
1995  memcpy(to, param->buffer, length);
1996  net->write_pos= to+length;
1997 }
1998 
1999 
2000 /*
2001  Mark if the parameter is NULL.
2002 
2003  SYNOPSIS
2004  store_param_null()
2005  net MySQL NET connection
2006  param MySQL bind param
2007 
2008  DESCRIPTION
2009  A data package starts with a string of bits where we set a bit
2010  if a parameter is NULL. Unlike bit string in result set row, here
2011  we don't have reserved bits for OK/error packet.
2012 */
2013 
2014 static void store_param_null(NET *net, MYSQL_BIND *param)
2015 {
2016  uint pos= param->param_number;
2017  net->buff[pos/8]|= (uchar) (1 << (pos & 7));
2018 }
2019 
2020 
2021 /*
2022  Store one parameter in network packet: data is read from
2023  client buffer and saved in network packet by means of one
2024  of store_param_xxxx functions.
2025 */
2026 
2027 static my_bool store_param(MYSQL_STMT *stmt, MYSQL_BIND *param)
2028 {
2029  NET *net= &stmt->mysql->net;
2030  DBUG_ENTER("store_param");
2031  DBUG_PRINT("enter",("type: %d buffer: 0x%lx length: %lu is_null: %d",
2032  param->buffer_type,
2033  (long) (param->buffer ? param->buffer : NullS),
2034  *param->length, *param->is_null));
2035 
2036  if (*param->is_null)
2037  store_param_null(net, param);
2038  else
2039  {
2040  /*
2041  Param->length should ALWAYS point to the correct length for the type
2042  Either to the length pointer given by the user or param->buffer_length
2043  */
2044  if ((my_realloc_str(net, *param->length)))
2045  {
2046  set_stmt_errmsg(stmt, net);
2047  DBUG_RETURN(1);
2048  }
2049  (*param->store_param_func)(net, param);
2050  }
2051  DBUG_RETURN(0);
2052 }
2053 
2054 
2055 /*
2056  Auxilary function to send COM_STMT_EXECUTE packet to server and read reply.
2057  Used from cli_stmt_execute, which is in turn used by mysql_stmt_execute.
2058 */
2059 
2060 static my_bool execute(MYSQL_STMT *stmt, char *packet, ulong length)
2061 {
2062  MYSQL *mysql= stmt->mysql;
2063  NET *net= &mysql->net;
2064  uchar buff[4 /* size of stmt id */ +
2065  5 /* execution flags */];
2066  my_bool res;
2067  DBUG_ENTER("execute");
2068  DBUG_DUMP("packet", (uchar *) packet, length);
2069 
2070  int4store(buff, stmt->stmt_id); /* Send stmt id to server */
2071  buff[4]= (char) stmt->flags;
2072  int4store(buff+5, 1); /* iteration count */
2073 
2074  res= test(cli_advanced_command(mysql, COM_STMT_EXECUTE, buff, sizeof(buff),
2075  (uchar*) packet, length, 1, stmt) ||
2076  (*mysql->methods->read_query_result)(mysql));
2077  stmt->affected_rows= mysql->affected_rows;
2078  stmt->server_status= mysql->server_status;
2079  stmt->insert_id= mysql->insert_id;
2080  if (res)
2081  {
2082  /*
2083  Don't set stmt error if stmt->mysql is NULL, as the error in this case
2084  has already been set by mysql_prune_stmt_list().
2085  */
2086  if (stmt->mysql)
2087  set_stmt_errmsg(stmt, net);
2088  DBUG_RETURN(1);
2089  }
2090  else if (mysql->status == MYSQL_STATUS_GET_RESULT)
2091  stmt->mysql->status= MYSQL_STATUS_STATEMENT_GET_RESULT;
2092  DBUG_RETURN(0);
2093 }
2094 
2095 
2096 int cli_stmt_execute(MYSQL_STMT *stmt)
2097 {
2098  DBUG_ENTER("cli_stmt_execute");
2099 
2100  if (stmt->param_count)
2101  {
2102  MYSQL *mysql= stmt->mysql;
2103  NET *net= &mysql->net;
2104  MYSQL_BIND *param, *param_end;
2105  char *param_data;
2106  ulong length;
2107  uint null_count;
2108  my_bool result;
2109 
2110  if (!stmt->bind_param_done)
2111  {
2112  set_stmt_error(stmt, CR_PARAMS_NOT_BOUND, unknown_sqlstate, NULL);
2113  DBUG_RETURN(1);
2114  }
2115  if (mysql->status != MYSQL_STATUS_READY ||
2116  mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
2117  {
2118  set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
2119  DBUG_RETURN(1);
2120  }
2121 
2122  if (net->vio)
2123  net_clear(net, 1); /* Sets net->write_pos */
2124  else
2125  {
2126  set_stmt_errmsg(stmt, net);
2127  DBUG_RETURN(1);
2128  }
2129 
2130  /* Reserve place for null-marker bytes */
2131  null_count= (stmt->param_count+7) /8;
2132  if (my_realloc_str(net, null_count + 1))
2133  {
2134  set_stmt_errmsg(stmt, net);
2135  DBUG_RETURN(1);
2136  }
2137  memset(net->write_pos, 0, null_count);
2138  net->write_pos+= null_count;
2139  param_end= stmt->params + stmt->param_count;
2140 
2141  /* In case if buffers (type) altered, indicate to server */
2142  *(net->write_pos)++= (uchar) stmt->send_types_to_server;
2143  if (stmt->send_types_to_server)
2144  {
2145  if (my_realloc_str(net, 2 * stmt->param_count))
2146  {
2147  set_stmt_errmsg(stmt, net);
2148  DBUG_RETURN(1);
2149  }
2150  /*
2151  Store types of parameters in first in first package
2152  that is sent to the server.
2153  */
2154  for (param= stmt->params; param < param_end ; param++)
2155  store_param_type(&net->write_pos, param);
2156  }
2157 
2158  for (param= stmt->params; param < param_end; param++)
2159  {
2160  /* check if mysql_stmt_send_long_data() was used */
2161  if (param->long_data_used)
2162  param->long_data_used= 0; /* Clear for next execute call */
2163  else if (store_param(stmt, param))
2164  DBUG_RETURN(1);
2165  }
2166  length= (ulong) (net->write_pos - net->buff);
2167  /* TODO: Look into avoding the following memdup */
2168  if (!(param_data= my_memdup(net->buff, length, MYF(0))))
2169  {
2170  set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
2171  DBUG_RETURN(1);
2172  }
2173  result= execute(stmt, param_data, length);
2174  stmt->send_types_to_server=0;
2175  my_free(param_data);
2176  DBUG_RETURN(result);
2177  }
2178  DBUG_RETURN((int) execute(stmt,0,0));
2179 }
2180 
2181 /*
2182  Read one row from buffered result set. Result set is created by prior
2183  call to mysql_stmt_store_result().
2184  SYNOPSIS
2185  stmt_read_row_buffered()
2186 
2187  RETURN VALUE
2188  0 - success; *row is set to valid row pointer (row data
2189  is stored in result set buffer)
2190  MYSQL_NO_DATA - end of result set. *row is set to NULL
2191 */
2192 
2193 static int stmt_read_row_buffered(MYSQL_STMT *stmt, unsigned char **row)
2194 {
2195  if (stmt->data_cursor)
2196  {
2197  *row= (uchar *) stmt->data_cursor->data;
2198  stmt->data_cursor= stmt->data_cursor->next;
2199  return 0;
2200  }
2201  *row= 0;
2202  return MYSQL_NO_DATA;
2203 }
2204 
2205 /*
2206  Read one row from network: unbuffered non-cursor fetch.
2207  If last row was read, or error occured, erase this statement
2208  from record pointing to object unbuffered fetch is performed from.
2209 
2210  SYNOPSIS
2211  stmt_read_row_unbuffered()
2212  stmt statement handle
2213  row pointer to write pointer to row data;
2214 
2215  RETURN VALUE
2216  0 - success; *row contains valid address of a row;
2217  row data is stored in network buffer
2218  1 - error; error code is written to
2219  stmt->last_{errno,error}; *row is not changed
2220  MYSQL_NO_DATA - end of file was read from network;
2221  *row is set to NULL
2222 */
2223 
2224 static int stmt_read_row_unbuffered(MYSQL_STMT *stmt, unsigned char **row)
2225 {
2226  int rc= 1;
2227  MYSQL *mysql= stmt->mysql;
2228  /*
2229  This function won't be called if stmt->field_count is zero
2230  or execution wasn't done: this is ensured by mysql_stmt_execute.
2231  */
2232  if (!mysql)
2233  {
2234  set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
2235  return 1;
2236  }
2237  if (mysql->status != MYSQL_STATUS_STATEMENT_GET_RESULT)
2238  {
2239  set_stmt_error(stmt, stmt->unbuffered_fetch_cancelled ?
2240  CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
2241  unknown_sqlstate, NULL);
2242  goto error;
2243  }
2244  if ((*mysql->methods->unbuffered_fetch)(mysql, (char**) row))
2245  {
2246  set_stmt_errmsg(stmt, &mysql->net);
2247  /*
2248  If there was an error, there are no more pending rows:
2249  reset statement status to not hang up in following
2250  mysql_stmt_close (it will try to flush result set before
2251  closing the statement).
2252  */
2253  mysql->status= MYSQL_STATUS_READY;
2254  goto error;
2255  }
2256  if (!*row)
2257  {
2258  mysql->status= MYSQL_STATUS_READY;
2259  rc= MYSQL_NO_DATA;
2260  goto error;
2261  }
2262  return 0;
2263 error:
2264  if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
2265  mysql->unbuffered_fetch_owner= 0;
2266  return rc;
2267 }
2268 
2269 
2270 /*
2271  Fetch statement row using server side cursor.
2272 
2273  SYNOPSIS
2274  stmt_read_row_from_cursor()
2275 
2276  RETURN VALUE
2277  0 success
2278  1 error
2279  MYSQL_NO_DATA end of data
2280 */
2281 
2282 static int
2283 stmt_read_row_from_cursor(MYSQL_STMT *stmt, unsigned char **row)
2284 {
2285  if (stmt->data_cursor)
2286  return stmt_read_row_buffered(stmt, row);
2287  if (stmt->server_status & SERVER_STATUS_LAST_ROW_SENT)
2288  stmt->server_status &= ~SERVER_STATUS_LAST_ROW_SENT;
2289  else
2290  {
2291  MYSQL *mysql= stmt->mysql;
2292  NET *net= &mysql->net;
2293  MYSQL_DATA *result= &stmt->result;
2294  uchar buff[4 /* statement id */ +
2295  4 /* number of rows to fetch */];
2296 
2297  free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
2298  result->data= NULL;
2299  result->rows= 0;
2300  /* Send row request to the server */
2301  int4store(buff, stmt->stmt_id);
2302  int4store(buff + 4, stmt->prefetch_rows); /* number of rows to fetch */
2303  if ((*mysql->methods->advanced_command)(mysql, COM_STMT_FETCH,
2304  buff, sizeof(buff), (uchar*) 0, 0,
2305  1, stmt))
2306  {
2307  /*
2308  Don't set stmt error if stmt->mysql is NULL, as the error in this case
2309  has already been set by mysql_prune_stmt_list().
2310  */
2311  if (stmt->mysql)
2312  set_stmt_errmsg(stmt, net);
2313  return 1;
2314  }
2315  if ((*mysql->methods->read_rows_from_cursor)(stmt))
2316  return 1;
2317  stmt->server_status= mysql->server_status;
2318 
2319  stmt->data_cursor= result->data;
2320  return stmt_read_row_buffered(stmt, row);
2321  }
2322  *row= 0;
2323  return MYSQL_NO_DATA;
2324 }
2325 
2326 
2327 /*
2328  Default read row function to not SIGSEGV in client in
2329  case of wrong sequence of API calls.
2330 */
2331 
2332 static int
2333 stmt_read_row_no_data(MYSQL_STMT *stmt __attribute__((unused)),
2334  unsigned char **row __attribute__((unused)))
2335 {
2336  return MYSQL_NO_DATA;
2337 }
2338 
2339 static int
2340 stmt_read_row_no_result_set(MYSQL_STMT *stmt __attribute__((unused)),
2341  unsigned char **row __attribute__((unused)))
2342 {
2343  set_stmt_error(stmt, CR_NO_RESULT_SET, unknown_sqlstate, NULL);
2344  return 1;
2345 }
2346 
2347 
2348 /*
2349  Get/set statement attributes
2350 
2351  SYNOPSIS
2352  mysql_stmt_attr_get()
2353  mysql_stmt_attr_set()
2354 
2355  attr_type statement attribute
2356  value casted to const void * pointer to value.
2357 
2358  RETURN VALUE
2359  0 success
2360  !0 wrong attribute type
2361 */
2362 
2363 my_bool STDCALL mysql_stmt_attr_set(MYSQL_STMT *stmt,
2364  enum enum_stmt_attr_type attr_type,
2365  const void *value)
2366 {
2367  switch (attr_type) {
2368  case STMT_ATTR_UPDATE_MAX_LENGTH:
2369  stmt->update_max_length= value ? *(const my_bool*) value : 0;
2370  break;
2371  case STMT_ATTR_CURSOR_TYPE:
2372  {
2373  ulong cursor_type;
2374  cursor_type= value ? *(ulong*) value : 0UL;
2375  if (cursor_type > (ulong) CURSOR_TYPE_READ_ONLY)
2376  goto err_not_implemented;
2377  stmt->flags= cursor_type;
2378  break;
2379  }
2380  case STMT_ATTR_PREFETCH_ROWS:
2381  {
2382  ulong prefetch_rows= value ? *(ulong*) value : DEFAULT_PREFETCH_ROWS;
2383  if (value == 0)
2384  return TRUE;
2385  stmt->prefetch_rows= prefetch_rows;
2386  break;
2387  }
2388  default:
2389  goto err_not_implemented;
2390  }
2391  return FALSE;
2392 err_not_implemented:
2393  set_stmt_error(stmt, CR_NOT_IMPLEMENTED, unknown_sqlstate, NULL);
2394  return TRUE;
2395 }
2396 
2397 
2398 my_bool STDCALL mysql_stmt_attr_get(MYSQL_STMT *stmt,
2399  enum enum_stmt_attr_type attr_type,
2400  void *value)
2401 {
2402  switch (attr_type) {
2403  case STMT_ATTR_UPDATE_MAX_LENGTH:
2404  *(my_bool*) value= stmt->update_max_length;
2405  break;
2406  case STMT_ATTR_CURSOR_TYPE:
2407  *(ulong*) value= stmt->flags;
2408  break;
2409  case STMT_ATTR_PREFETCH_ROWS:
2410  *(ulong*) value= stmt->prefetch_rows;
2411  break;
2412  default:
2413  return TRUE;
2414  }
2415  return FALSE;
2416 }
2417 
2418 
2430 static void reinit_result_set_metadata(MYSQL_STMT *stmt)
2431 {
2432  /* Server has sent result set metadata */
2433  if (stmt->field_count == 0)
2434  {
2435  /*
2436  This is 'SHOW'/'EXPLAIN'-like query. Current implementation of
2437  prepared statements can't send result set metadata for these queries
2438  on prepare stage. Read it now.
2439  */
2440 
2441  stmt->field_count= stmt->mysql->field_count;
2442 
2443  alloc_stmt_fields(stmt);
2444  }
2445  else
2446  {
2447  /*
2448  Update result set metadata if it for some reason changed between
2449  prepare and execute, i.e.:
2450  - in case of 'SELECT ?' we don't know column type unless data was
2451  supplied to mysql_stmt_execute, so updated column type is sent
2452  now.
2453  - if data dictionary changed between prepare and execute, for
2454  example a table used in the query was altered.
2455  Note, that now (4.1.3) we always send metadata in reply to
2456  COM_STMT_EXECUTE (even if it is not necessary), so either this or
2457  previous branch always works.
2458  TODO: send metadata only when it's really necessary and add a warning
2459  'Metadata changed' when it's sent twice.
2460  */
2461  update_stmt_fields(stmt);
2462  }
2463 }
2464 
2465 
2466 static void prepare_to_fetch_result(MYSQL_STMT *stmt)
2467 {
2468  if (stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
2469  {
2470  stmt->mysql->status= MYSQL_STATUS_READY;
2471  stmt->read_row_func= stmt_read_row_from_cursor;
2472  }
2473  else if (stmt->flags & CURSOR_TYPE_READ_ONLY)
2474  {
2475  /*
2476  This is a single-row result set, a result set with no rows, EXPLAIN,
2477  SHOW VARIABLES, or some other command which either a) bypasses the
2478  cursors framework in the server and writes rows directly to the
2479  network or b) is more efficient if all (few) result set rows are
2480  precached on client and server's resources are freed.
2481  */
2482  mysql_stmt_store_result(stmt);
2483  }
2484  else
2485  {
2486  stmt->mysql->unbuffered_fetch_owner= &stmt->unbuffered_fetch_cancelled;
2487  stmt->unbuffered_fetch_cancelled= FALSE;
2488  stmt->read_row_func= stmt_read_row_unbuffered;
2489  }
2490 }
2491 
2492 
2493 /*
2494  Send placeholders data to server (if there are placeholders)
2495  and execute prepared statement.
2496 
2497  SYNOPSIS
2498  mysql_stmt_execute()
2499  stmt statement handle. The handle must be created
2500  with mysql_stmt_init() and prepared with
2501  mysql_stmt_prepare(). If there are placeholders
2502  in the statement they must be bound to local
2503  variables with mysql_stmt_bind_param().
2504 
2505  DESCRIPTION
2506  This function will automatically flush pending result
2507  set (if there is one), send parameters data to the server
2508  and read result of statement execution.
2509  If previous result set was cached with mysql_stmt_store_result()
2510  it will also be freed in the beginning of this call.
2511  The server can return 3 types of responses to this command:
2512  - error, can be retrieved with mysql_stmt_error()
2513  - ok, no result set pending. In this case we just update
2514  stmt->insert_id and stmt->affected_rows.
2515  - the query returns a result set: there could be 0 .. N
2516  rows in it. In this case the server can also send updated
2517  result set metadata.
2518 
2519  Next steps you may want to make:
2520  - find out if there is result set with mysql_stmt_field_count().
2521  If there is one:
2522  - optionally, cache entire result set on client to unblock
2523  connection with mysql_stmt_store_result()
2524  - bind client variables to result set columns and start read rows
2525  with mysql_stmt_fetch().
2526  - reset statement with mysql_stmt_reset() or close it with
2527  mysql_stmt_close()
2528  Otherwise:
2529  - find out last insert id and number of affected rows with
2530  mysql_stmt_insert_id(), mysql_stmt_affected_rows()
2531 
2532  RETURN
2533  0 success
2534  1 error, message can be retrieved with mysql_stmt_error().
2535 */
2536 
2537 int STDCALL mysql_stmt_execute(MYSQL_STMT *stmt)
2538 {
2539  MYSQL *mysql= stmt->mysql;
2540  DBUG_ENTER("mysql_stmt_execute");
2541 
2542  if (!mysql)
2543  {
2544  /* Error is already set in mysql_detatch_stmt_list */
2545  DBUG_RETURN(1);
2546  }
2547 
2548  if (reset_stmt_handle(stmt, RESET_STORE_RESULT | RESET_CLEAR_ERROR))
2549  DBUG_RETURN(1);
2550  /*
2551  No need to check for stmt->state: if the statement wasn't
2552  prepared we'll get 'unknown statement handler' error from server.
2553  */
2554  if (mysql->methods->stmt_execute(stmt))
2555  DBUG_RETURN(1);
2556  stmt->state= MYSQL_STMT_EXECUTE_DONE;
2557  if (mysql->field_count)
2558  {
2559  reinit_result_set_metadata(stmt);
2560  prepare_to_fetch_result(stmt);
2561  }
2562  DBUG_RETURN(test(stmt->last_errno));
2563 }
2564 
2565 
2566 /*
2567  Return total parameters count in the statement
2568 */
2569 
2570 ulong STDCALL mysql_stmt_param_count(MYSQL_STMT * stmt)
2571 {
2572  DBUG_ENTER("mysql_stmt_param_count");
2573  DBUG_RETURN(stmt->param_count);
2574 }
2575 
2576 /*
2577  Return total affected rows from the last statement
2578 */
2579 
2580 my_ulonglong STDCALL mysql_stmt_affected_rows(MYSQL_STMT *stmt)
2581 {
2582  return stmt->affected_rows;
2583 }
2584 
2585 
2586 /*
2587  Returns the number of result columns for the most recent query
2588  run on this statement.
2589 */
2590 
2591 unsigned int STDCALL mysql_stmt_field_count(MYSQL_STMT *stmt)
2592 {
2593  return stmt->field_count;
2594 }
2595 
2596 /*
2597  Return last inserted id for auto_increment columns.
2598 
2599  SYNOPSIS
2600  mysql_stmt_insert_id()
2601  stmt statement handle
2602 
2603  DESCRIPTION
2604  Current implementation of this call has a caveat: stmt->insert_id is
2605  unconditionally updated from mysql->insert_id in the end of each
2606  mysql_stmt_execute(). This works OK if mysql->insert_id contains new
2607  value (sent in reply to mysql_stmt_execute()), otherwise stmt->insert_id
2608  value gets undefined, as it's updated from some arbitrary value saved in
2609  connection structure during some other call.
2610 */
2611 
2612 my_ulonglong STDCALL mysql_stmt_insert_id(MYSQL_STMT *stmt)
2613 {
2614  return stmt->insert_id;
2615 }
2616 
2617 
2618 static my_bool int_is_null_true= 1; /* Used for MYSQL_TYPE_NULL */
2619 static my_bool int_is_null_false= 0;
2620 
2621 
2622 /*
2623  Set up input data buffers for a statement.
2624 
2625  SYNOPSIS
2626  mysql_stmt_bind_param()
2627  stmt statement handle
2628  The statement must be prepared with mysql_stmt_prepare().
2629  my_bind Array of mysql_stmt_param_count() bind parameters.
2630  This function doesn't check that size of this argument
2631  is >= mysql_stmt_field_count(): it's user's responsibility.
2632 
2633  DESCRIPTION
2634  Use this call after mysql_stmt_prepare() to bind user variables to
2635  placeholders.
2636  Each element of bind array stands for a placeholder. Placeholders
2637  are counted from 0. For example statement
2638  'INSERT INTO t (a, b) VALUES (?, ?)'
2639  contains two placeholders, and for such statement you should supply
2640  bind array of two elements (MYSQL_BIND bind[2]).
2641 
2642  By properly initializing bind array you can bind virtually any
2643  C language type to statement's placeholders:
2644  First, it's strongly recommended to always zero-initialize entire
2645  bind structure before setting its members. This will both shorten
2646  your application code and make it robust to future extensions of
2647  MYSQL_BIND structure.
2648  Then you need to assign typecode of your application buffer to
2649  MYSQL_BIND::buffer_type. The following typecodes with their
2650  correspondence to C language types are supported:
2651  MYSQL_TYPE_TINY for 8-bit integer variables. Normally it's
2652  'signed char' and 'unsigned char';
2653  MYSQL_TYPE_SHORT for 16-bit signed and unsigned variables. This
2654  is usually 'short' and 'unsigned short';
2655  MYSQL_TYPE_LONG for 32-bit signed and unsigned variables. It
2656  corresponds to 'int' and 'unsigned int' on
2657  vast majority of platforms. On IA-32 and some
2658  other 32-bit systems you can also use 'long'
2659  here;
2660  MYSQL_TYPE_LONGLONG 64-bit signed or unsigned integer. Stands for
2661  '[unsigned] long long' on most platforms;
2662  MYSQL_TYPE_FLOAT 32-bit floating point type, 'float' on most
2663  systems;
2664  MYSQL_TYPE_DOUBLE 64-bit floating point type, 'double' on most
2665  systems;
2666  MYSQL_TYPE_TIME broken-down time stored in MYSQL_TIME
2667  structure
2668  MYSQL_TYPE_DATE date stored in MYSQL_TIME structure
2669  MYSQL_TYPE_DATETIME datetime stored in MYSQL_TIME structure See
2670  more on how to use these types for sending
2671  dates and times below;
2672  MYSQL_TYPE_STRING character string, assumed to be in
2673  character-set-client. If character set of
2674  client is not equal to character set of
2675  column, value for this placeholder will be
2676  converted to destination character set before
2677  insert.
2678  MYSQL_TYPE_BLOB sequence of bytes. This sequence is assumed to
2679  be in binary character set (which is the same
2680  as no particular character set), and is never
2681  converted to any other character set. See also
2682  notes about supplying string/blob length
2683  below.
2684  MYSQL_TYPE_NULL special typecode for binding nulls.
2685  These C/C++ types are not supported yet by the API: long double,
2686  bool.
2687 
2688  As you can see from the list above, it's responsibility of
2689  application programmer to ensure that chosen typecode properly
2690  corresponds to host language type. For example on all platforms
2691  where we build MySQL packages (as of MySQL 4.1.4) int is a 32-bit
2692  type. So for int you can always assume that proper typecode is
2693  MYSQL_TYPE_LONG (however queer it sounds, the name is legacy of the
2694  old MySQL API). In contrary sizeof(long) can be 4 or 8 8-bit bytes,
2695  depending on platform.
2696 
2697  TODO: provide client typedefs for each integer and floating point
2698  typecode, i. e. int8, uint8, float32, etc.
2699 
2700  Once typecode was set, it's necessary to assign MYSQL_BIND::buffer
2701  to point to the buffer of given type. Finally, additional actions
2702  may be taken for some types or use cases:
2703 
2704  Binding integer types.
2705  For integer types you might also need to set MYSQL_BIND::is_unsigned
2706  member. Set it to TRUE when binding unsigned char, unsigned short,
2707  unsigned int, unsigned long, unsigned long long.
2708 
2709  Binding floating point types.
2710  For floating point types you just need to set
2711  MYSQL_BIND::buffer_type and MYSQL_BIND::buffer. The rest of the
2712  members should be zero-initialized.
2713 
2714  Binding NULLs.
2715  You might have a column always NULL, never NULL, or sometimes
2716  NULL. For an always NULL column set MYSQL_BIND::buffer_type to
2717  MYSQL_TYPE_NULL. The rest of the members just need to be
2718  zero-initialized. For never NULL columns set
2719  MYSQL_BIND::is_null to 0, or this has already been done if you
2720  zero-initialized the entire structure. If you set
2721  MYSQL_TYPE::is_null to point to an application buffer of type
2722  'my_bool', then this buffer will be checked on each execution:
2723  this way you can set the buffer to TRUE, or any non-0 value for
2724  NULLs, and to FALSE or 0 for not NULL data.
2725 
2726  Binding text strings and sequences of bytes.
2727  For strings, in addition to MYSQL_BIND::buffer_type and
2728  MYSQL_BIND::buffer you need to set MYSQL_BIND::length or
2729  MYSQL_BIND::buffer_length. If 'length' is set, 'buffer_length'
2730  is ignored. 'buffer_length' member should be used when size of
2731  string doesn't change between executions. If you want to vary
2732  buffer length for each value, set 'length' to point to an
2733  application buffer of type 'unsigned long' and set this long to
2734  length of the string before each mysql_stmt_execute().
2735 
2736  Binding dates and times.
2737  For binding dates and times prepared statements API provides
2738  clients with MYSQL_TIME structure. A pointer to instance of this
2739  structure should be assigned to MYSQL_BIND::buffer whenever
2740  MYSQL_TYPE_TIME, MYSQL_TYPE_DATE, MYSQL_TYPE_DATETIME typecodes
2741  are used. When typecode is MYSQL_TYPE_TIME, only members
2742  'hour', 'minute', 'second' and 'neg' (is time offset negative)
2743  are used. These members only will be sent to the server.
2744  MYSQL_TYPE_DATE implies use of 'year', 'month', 'day', 'neg'.
2745  MYSQL_TYPE_DATETIME utilizes both parts of MYSQL_TIME structure.
2746  You don't have to set MYSQL_TIME::time_type member: it's not
2747  used when sending data to the server, typecode information is
2748  enough. 'second_part' member can hold microsecond precision of
2749  time value, but now it's only supported on protocol level: you
2750  can't store microsecond in a column, or use in temporal
2751  calculations. However, if you send a time value with microsecond
2752  part for 'SELECT ?', statement, you'll get it back unchanged
2753  from the server.
2754 
2755  Data conversion.
2756  If conversion from host language type to data representation,
2757  corresponding to SQL type, is required it's done on the server.
2758  Data truncation is possible when conversion is lossy. For
2759  example, if you supply MYSQL_TYPE_DATETIME value out of valid
2760  SQL type TIMESTAMP range, the same conversion will be applied as
2761  if this value would have been sent as string in the old
2762  protocol. TODO: document how the server will behave in case of
2763  truncation/data loss.
2764 
2765  After variables were bound, you can repeatedly set/change their
2766  values and mysql_stmt_execute() the statement.
2767 
2768  See also: mysql_stmt_send_long_data() for sending long text/blob
2769  data in pieces, examples in tests/mysql_client_test.c.
2770  Next steps you might want to make:
2771  - execute statement with mysql_stmt_execute(),
2772  - reset statement using mysql_stmt_reset() or reprepare it with
2773  another query using mysql_stmt_prepare()
2774  - close statement with mysql_stmt_close().
2775 
2776  IMPLEMENTATION
2777  The function copies given bind array to internal storage of the
2778  statement, and sets up typecode-specific handlers to perform
2779  serialization of bound data. This means that although you don't need
2780  to call this routine after each assignment to bind buffers, you
2781  need to call it each time you change parameter typecodes, or other
2782  members of MYSQL_BIND array.
2783  This is a pure local call. Data types of client buffers are sent
2784  along with buffers' data at first execution of the statement.
2785 
2786  RETURN
2787  0 success
2788  1 error, can be retrieved with mysql_stmt_error.
2789 */
2790 
2791 my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *my_bind)
2792 {
2793  uint count=0;
2794  MYSQL_BIND *param, *end;
2795  DBUG_ENTER("mysql_stmt_bind_param");
2796 
2797  if (!stmt->param_count)
2798  {
2799  if ((int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE)
2800  {
2801  set_stmt_error(stmt, CR_NO_PREPARE_STMT, unknown_sqlstate, NULL);
2802  DBUG_RETURN(1);
2803  }
2804  DBUG_RETURN(0);
2805  }
2806 
2807  /* Allocated on prepare */
2808  memcpy((char*) stmt->params, (char*) my_bind,
2809  sizeof(MYSQL_BIND) * stmt->param_count);
2810 
2811  for (param= stmt->params, end= param+stmt->param_count;
2812  param < end ;
2813  param++)
2814  {
2815  param->param_number= count++;
2816  param->long_data_used= 0;
2817 
2818  /* If param->is_null is not set, then the value can never be NULL */
2819  if (!param->is_null)
2820  param->is_null= &int_is_null_false;
2821 
2822  /* Setup data copy functions for the different supported types */
2823  switch (param->buffer_type) {
2824  case MYSQL_TYPE_NULL:
2825  param->is_null= &int_is_null_true;
2826  break;
2827  case MYSQL_TYPE_TINY:
2828  /* Force param->length as this is fixed for this type */
2829  param->length= &param->buffer_length;
2830  param->buffer_length= 1;
2831  param->store_param_func= store_param_tinyint;
2832  break;
2833  case MYSQL_TYPE_SHORT:
2834  param->length= &param->buffer_length;
2835  param->buffer_length= 2;
2836  param->store_param_func= store_param_short;
2837  break;
2838  case MYSQL_TYPE_LONG:
2839  param->length= &param->buffer_length;
2840  param->buffer_length= 4;
2841  param->store_param_func= store_param_int32;
2842  break;
2843  case MYSQL_TYPE_LONGLONG:
2844  param->length= &param->buffer_length;
2845  param->buffer_length= 8;
2846  param->store_param_func= store_param_int64;
2847  break;
2848  case MYSQL_TYPE_FLOAT:
2849  param->length= &param->buffer_length;
2850  param->buffer_length= 4;
2851  param->store_param_func= store_param_float;
2852  break;
2853  case MYSQL_TYPE_DOUBLE:
2854  param->length= &param->buffer_length;
2855  param->buffer_length= 8;
2856  param->store_param_func= store_param_double;
2857  break;
2858  case MYSQL_TYPE_TIME:
2859  param->store_param_func= store_param_time;
2860  param->buffer_length= MAX_TIME_REP_LENGTH;
2861  break;
2862  case MYSQL_TYPE_DATE:
2863  param->store_param_func= store_param_date;
2864  param->buffer_length= MAX_DATE_REP_LENGTH;
2865  break;
2866  case MYSQL_TYPE_DATETIME:
2867  case MYSQL_TYPE_TIMESTAMP:
2868  param->store_param_func= store_param_datetime;
2869  param->buffer_length= MAX_DATETIME_REP_LENGTH;
2870  break;
2871  case MYSQL_TYPE_TINY_BLOB:
2872  case MYSQL_TYPE_MEDIUM_BLOB:
2873  case MYSQL_TYPE_LONG_BLOB:
2874  case MYSQL_TYPE_BLOB:
2875  case MYSQL_TYPE_VARCHAR:
2876  case MYSQL_TYPE_VAR_STRING:
2877  case MYSQL_TYPE_STRING:
2878  case MYSQL_TYPE_DECIMAL:
2879  case MYSQL_TYPE_NEWDECIMAL:
2880  param->store_param_func= store_param_str;
2881  /*
2882  For variable length types user must set either length or
2883  buffer_length.
2884  */
2885  break;
2886  default:
2887  strmov(stmt->sqlstate, unknown_sqlstate);
2888  sprintf(stmt->last_error,
2889  ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
2890  param->buffer_type, count);
2891  DBUG_RETURN(1);
2892  }
2893  /*
2894  If param->length is not given, change it to point to buffer_length.
2895  This way we can always use *param->length to get the length of data
2896  */
2897  if (!param->length)
2898  param->length= &param->buffer_length;
2899  }
2900  /* We have to send/resend type information to MySQL */
2901  stmt->send_types_to_server= TRUE;
2902  stmt->bind_param_done= TRUE;
2903  DBUG_RETURN(0);
2904 }
2905 
2906 
2907 /********************************************************************
2908  Long data implementation
2909 *********************************************************************/
2910 
2911 /*
2912  Send long data in pieces to the server
2913 
2914  SYNOPSIS
2915  mysql_stmt_send_long_data()
2916  stmt Statement handler
2917  param_number Parameter number (0 - N-1)
2918  data Data to send to server
2919  length Length of data to send (may be 0)
2920 
2921  DESCRIPTION
2922  This call can be used repeatedly to send long data in pieces
2923  for any string/binary placeholder. Data supplied for
2924  a placeholder is saved at server side till execute, and then
2925  used instead of value from MYSQL_BIND object. More precisely,
2926  if long data for a parameter was supplied, MYSQL_BIND object
2927  corresponding to this parameter is not sent to server. In the
2928  end of execution long data states of placeholders are reset,
2929  so next time values of such placeholders will be taken again
2930  from MYSQL_BIND array.
2931  The server does not reply to this call: if there was an error
2932  in data handling (which now only can happen if server run out
2933  of memory) it would be returned in reply to
2934  mysql_stmt_execute().
2935  You should choose type of long data carefully if you care
2936  about character set conversions performed by server when the
2937  statement is executed. No conversion is performed at all for
2938  MYSQL_TYPE_BLOB and other binary typecodes. For
2939  MYSQL_TYPE_STRING and the rest of text placeholders data is
2940  converted from client character set to character set of
2941  connection. If these character sets are different, this
2942  conversion may require additional memory at server, equal to
2943  total size of supplied pieces.
2944 
2945  RETURN VALUES
2946  0 ok
2947  1 error
2948 */
2949 
2950 my_bool STDCALL
2951 mysql_stmt_send_long_data(MYSQL_STMT *stmt, uint param_number,
2952  const char *data, ulong length)
2953 {
2954  MYSQL_BIND *param;
2955  DBUG_ENTER("mysql_stmt_send_long_data");
2956  DBUG_ASSERT(stmt != 0);
2957  DBUG_PRINT("enter",("param no: %d data: 0x%lx, length : %ld",
2958  param_number, (long) data, length));
2959 
2960  /*
2961  We only need to check for stmt->param_count, if it's not null
2962  prepare was done.
2963  */
2964  if (param_number >= stmt->param_count)
2965  {
2966  set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL);
2967  DBUG_RETURN(1);
2968  }
2969 
2970  param= stmt->params+param_number;
2971  if (!IS_LONGDATA(param->buffer_type))
2972  {
2973  /* Long data handling should be used only for string/binary types */
2974  strmov(stmt->sqlstate, unknown_sqlstate);
2975  sprintf(stmt->last_error, ER(stmt->last_errno= CR_INVALID_BUFFER_USE),
2976  param->param_number);
2977  DBUG_RETURN(1);
2978  }
2979 
2980  /*
2981  Send long data packet if there is data or we're sending long data
2982  for the first time.
2983  */
2984  if (length || param->long_data_used == 0)
2985  {
2986  MYSQL *mysql= stmt->mysql;
2987  /* Packet header: stmt id (4 bytes), param no (2 bytes) */
2988  uchar buff[MYSQL_LONG_DATA_HEADER];
2989 
2990  int4store(buff, stmt->stmt_id);
2991  int2store(buff + 4, param_number);
2992  param->long_data_used= 1;
2993 
2994  /*
2995  Note that we don't get any ok packet from the server in this case
2996  This is intentional to save bandwidth.
2997  */
2998  if ((*mysql->methods->advanced_command)(mysql, COM_STMT_SEND_LONG_DATA,
2999  buff, sizeof(buff), (uchar*) data,
3000  length, 1, stmt))
3001  {
3002  /*
3003  Don't set stmt error if stmt->mysql is NULL, as the error in this case
3004  has already been set by mysql_prune_stmt_list().
3005  */
3006  if (stmt->mysql)
3007  set_stmt_errmsg(stmt, &mysql->net);
3008  DBUG_RETURN(1);
3009  }
3010  }
3011  DBUG_RETURN(0);
3012 }
3013 
3014 
3015 /********************************************************************
3016  Fetch and conversion of result set rows (binary protocol).
3017 *********************************************************************/
3018 
3019 /*
3020  Read date, (time, datetime) value from network buffer and store it
3021  in MYSQL_TIME structure.
3022 
3023  SYNOPSIS
3024  read_binary_{date,time,datetime}()
3025  tm MYSQL_TIME structure to fill
3026  pos pointer to current position in network buffer.
3027  These functions increase pos to point to the beginning of the
3028  next column.
3029 
3030  Auxiliary functions to read time (date, datetime) values from network
3031  buffer and store in MYSQL_TIME structure. Jointly used by conversion
3032  and no-conversion fetching.
3033 */
3034 
3035 static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
3036 {
3037  /* net_field_length will set pos to the first byte of data */
3038  uint length= net_field_length(pos);
3039 
3040  if (length)
3041  {
3042  uchar *to= *pos;
3043  tm->neg= to[0];
3044 
3045  tm->day= (ulong) sint4korr(to+1);
3046  tm->hour= (uint) to[5];
3047  tm->minute= (uint) to[6];
3048  tm->second= (uint) to[7];
3049  tm->second_part= (length > 8) ? (ulong) sint4korr(to+8) : 0;
3050  tm->year= tm->month= 0;
3051  if (tm->day)
3052  {
3053  /* Convert days to hours at once */
3054  tm->hour+= tm->day*24;
3055  tm->day= 0;
3056  }
3057  tm->time_type= MYSQL_TIMESTAMP_TIME;
3058 
3059  *pos+= length;
3060  }
3061  else
3062  set_zero_time(tm, MYSQL_TIMESTAMP_TIME);
3063 }
3064 
3065 static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
3066 {
3067  uint length= net_field_length(pos);
3068 
3069  if (length)
3070  {
3071  uchar *to= *pos;
3072 
3073  tm->neg= 0;
3074  tm->year= (uint) sint2korr(to);
3075  tm->month= (uint) to[2];
3076  tm->day= (uint) to[3];
3077 
3078  if (length > 4)
3079  {
3080  tm->hour= (uint) to[4];
3081  tm->minute= (uint) to[5];
3082  tm->second= (uint) to[6];
3083  }
3084  else
3085  tm->hour= tm->minute= tm->second= 0;
3086  tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
3087  tm->time_type= MYSQL_TIMESTAMP_DATETIME;
3088 
3089  *pos+= length;
3090  }
3091  else
3092  set_zero_time(tm, MYSQL_TIMESTAMP_DATETIME);
3093 }
3094 
3095 static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
3096 {
3097  uint length= net_field_length(pos);
3098 
3099  if (length)
3100  {
3101  uchar *to= *pos;
3102  tm->year = (uint) sint2korr(to);
3103  tm->month= (uint) to[2];
3104  tm->day= (uint) to[3];
3105 
3106  tm->hour= tm->minute= tm->second= 0;
3107  tm->second_part= 0;
3108  tm->neg= 0;
3109  tm->time_type= MYSQL_TIMESTAMP_DATE;
3110 
3111  *pos+= length;
3112  }
3113  else
3114  set_zero_time(tm, MYSQL_TIMESTAMP_DATE);
3115 }
3116 
3117 
3118 /*
3119  Convert string to supplied buffer of any type.
3120 
3121  SYNOPSIS
3122  fetch_string_with_conversion()
3123  param output buffer descriptor
3124  value column data
3125  length data length
3126 */
3127 
3128 static void fetch_string_with_conversion(MYSQL_BIND *param, char *value,
3129  uint length)
3130 {
3131  char *buffer= (char *)param->buffer;
3132  char *endptr= value + length;
3133 
3134  /*
3135  This function should support all target buffer types: the rest
3136  of conversion functions can delegate conversion to it.
3137  */
3138  switch (param->buffer_type) {
3139  case MYSQL_TYPE_NULL: /* do nothing */
3140  break;
3141  case MYSQL_TYPE_TINY:
3142  {
3143  int err;
3144  longlong data= my_strtoll10(value, &endptr, &err);
3145  *param->error= (IS_TRUNCATED(data, param->is_unsigned,
3146  INT_MIN8, INT_MAX8, UINT_MAX8) || err > 0);
3147  *buffer= (uchar) data;
3148  break;
3149  }
3150  case MYSQL_TYPE_SHORT:
3151  {
3152  int err;
3153  longlong data= my_strtoll10(value, &endptr, &err);
3154  *param->error= (IS_TRUNCATED(data, param->is_unsigned,
3155  INT_MIN16, INT_MAX16, UINT_MAX16) || err > 0);
3156  shortstore(buffer, (short) data);
3157  break;
3158  }
3159  case MYSQL_TYPE_LONG:
3160  {
3161  int err;
3162  longlong data= my_strtoll10(value, &endptr, &err);
3163  *param->error= (IS_TRUNCATED(data, param->is_unsigned,
3164  INT_MIN32, INT_MAX32, UINT_MAX32) || err > 0);
3165  longstore(buffer, (int32) data);
3166  break;
3167  }
3168  case MYSQL_TYPE_LONGLONG:
3169  {
3170  int err;
3171  longlong data= my_strtoll10(value, &endptr, &err);
3172  *param->error= param->is_unsigned ? err != 0 :
3173  (err > 0 || (err == 0 && data < 0));
3174  longlongstore(buffer, data);
3175  break;
3176  }
3177  case MYSQL_TYPE_FLOAT:
3178  {
3179  int err;
3180  double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
3181  float fdata= (float) data;
3182  *param->error= (fdata != data) | test(err);
3183  floatstore(buffer, fdata);
3184  break;
3185  }
3186  case MYSQL_TYPE_DOUBLE:
3187  {
3188  int err;
3189  double data= my_strntod(&my_charset_latin1, value, length, &endptr, &err);
3190  *param->error= test(err);
3191  doublestore(buffer, data);
3192  break;
3193  }
3194  case MYSQL_TYPE_TIME:
3195  {
3196  MYSQL_TIME_STATUS status;
3197  MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
3198  str_to_time(value, length, tm, &status);
3199  *param->error= test(status.warnings);
3200  break;
3201  }
3202  case MYSQL_TYPE_DATE:
3203  case MYSQL_TYPE_DATETIME:
3204  case MYSQL_TYPE_TIMESTAMP:
3205  {
3206  MYSQL_TIME_STATUS status;
3207  MYSQL_TIME *tm= (MYSQL_TIME *)buffer;
3208  (void) str_to_datetime(value, length, tm, TIME_FUZZY_DATE, &status);
3209  *param->error= test(status.warnings) &&
3210  (param->buffer_type == MYSQL_TYPE_DATE &&
3211  tm->time_type != MYSQL_TIMESTAMP_DATE);
3212  break;
3213  }
3214  case MYSQL_TYPE_TINY_BLOB:
3215  case MYSQL_TYPE_MEDIUM_BLOB:
3216  case MYSQL_TYPE_LONG_BLOB:
3217  case MYSQL_TYPE_BLOB:
3218  case MYSQL_TYPE_DECIMAL:
3219  case MYSQL_TYPE_NEWDECIMAL:
3220  default:
3221  {
3222  /*
3223  Copy column data to the buffer taking into account offset,
3224  data length and buffer length.
3225  */
3226  char *start= value + param->offset;
3227  char *end= value + length;
3228  ulong copy_length;
3229  if (start < end)
3230  {
3231  copy_length= end - start;
3232  /* We've got some data beyond offset: copy up to buffer_length bytes */
3233  if (param->buffer_length)
3234  memcpy(buffer, start, MY_MIN(copy_length, param->buffer_length));
3235  }
3236  else
3237  copy_length= 0;
3238  if (copy_length < param->buffer_length)
3239  buffer[copy_length]= '\0';
3240  *param->error= copy_length > param->buffer_length;
3241  /*
3242  param->length will always contain length of entire column;
3243  number of copied bytes may be way different:
3244  */
3245  *param->length= length;
3246  break;
3247  }
3248  }
3249 }
3250 
3251 
3252 /*
3253  Convert integer value to client buffer of any type.
3254 
3255  SYNOPSIS
3256  fetch_long_with_conversion()
3257  param output buffer descriptor
3258  field column metadata
3259  value column data
3260 */
3261 
3262 static void fetch_long_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3263  longlong value, my_bool is_unsigned)
3264 {
3265  char *buffer= (char *)param->buffer;
3266 
3267  switch (param->buffer_type) {
3268  case MYSQL_TYPE_NULL: /* do nothing */
3269  break;
3270  case MYSQL_TYPE_TINY:
3271  *param->error= IS_TRUNCATED(value, param->is_unsigned,
3272  INT_MIN8, INT_MAX8, UINT_MAX8);
3273  *(uchar *)param->buffer= (uchar) value;
3274  break;
3275  case MYSQL_TYPE_SHORT:
3276  *param->error= IS_TRUNCATED(value, param->is_unsigned,
3277  INT_MIN16, INT_MAX16, UINT_MAX16);
3278  shortstore(buffer, (short) value);
3279  break;
3280  case MYSQL_TYPE_LONG:
3281  *param->error= IS_TRUNCATED(value, param->is_unsigned,
3282  INT_MIN32, INT_MAX32, UINT_MAX32);
3283  longstore(buffer, (int32) value);
3284  break;
3285  case MYSQL_TYPE_LONGLONG:
3286  longlongstore(buffer, value);
3287  *param->error= param->is_unsigned != is_unsigned && value < 0;
3288  break;
3289  case MYSQL_TYPE_FLOAT:
3290  {
3291  /*
3292  We need to mark the local variable volatile to
3293  workaround Intel FPU executive precision feature.
3294  (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
3295  */
3296  volatile float data;
3297  if (is_unsigned)
3298  {
3299  data= (float) ulonglong2double(value);
3300  *param->error= ((ulonglong) value) != ((ulonglong) data);
3301  }
3302  else
3303  {
3304  data= (float)value;
3305  *param->error= value != ((longlong) data);
3306  }
3307  floatstore(buffer, data);
3308  break;
3309  }
3310  case MYSQL_TYPE_DOUBLE:
3311  {
3312  volatile double data;
3313  if (is_unsigned)
3314  {
3315  data= ulonglong2double(value);
3316  *param->error= ((ulonglong) value) != ((ulonglong) data);
3317  }
3318  else
3319  {
3320  data= (double)value;
3321  *param->error= value != ((longlong) data);
3322  }
3323  doublestore(buffer, data);
3324  break;
3325  }
3326  case MYSQL_TYPE_TIME:
3327  case MYSQL_TYPE_DATE:
3328  case MYSQL_TYPE_TIMESTAMP:
3329  case MYSQL_TYPE_DATETIME:
3330  {
3331  int error;
3332  value= number_to_datetime(value, (MYSQL_TIME *) buffer, TIME_FUZZY_DATE,
3333  &error);
3334  *param->error= test(error);
3335  break;
3336  }
3337  default:
3338  {
3339  uchar buff[22]; /* Enough for longlong */
3340  uchar *end= (uchar*) longlong10_to_str(value, (char*) buff,
3341  is_unsigned ? 10: -10);
3342  /* Resort to string conversion which supports all typecodes */
3343  uint length= (uint) (end-buff);
3344 
3345  if (field->flags & ZEROFILL_FLAG && length < field->length &&
3346  field->length < 21)
3347  {
3348  bmove_upp(buff+field->length,buff+length, length);
3349  memset(buff, '0', field->length - length);
3350  length= field->length;
3351  }
3352  fetch_string_with_conversion(param, (char*) buff, length);
3353  break;
3354  }
3355  }
3356 }
3357 
3358 /*
3359  Convert double/float column to supplied buffer of any type.
3360 
3361  SYNOPSIS
3362  fetch_float_with_conversion()
3363  param output buffer descriptor
3364  field column metadata
3365  value column data
3366  type either MY_GCVT_ARG_FLOAT or MY_GCVT_ARG_DOUBLE.
3367  Affects the maximum number of significant digits
3368  returned by my_gcvt().
3369 */
3370 
3371 static void fetch_float_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3372  double value, my_gcvt_arg_type type)
3373 {
3374  char *buffer= (char *)param->buffer;
3375  double val64 = (value < 0 ? -floor(-value) : floor(value));
3376 
3377  switch (param->buffer_type) {
3378  case MYSQL_TYPE_NULL: /* do nothing */
3379  break;
3380  case MYSQL_TYPE_TINY:
3381  /*
3382  We need to _store_ data in the buffer before the truncation check to
3383  workaround Intel FPU executive precision feature.
3384  (See http://gcc.gnu.org/bugzilla/show_bug.cgi?id=323 for details)
3385  Sic: AFAIU it does not guarantee to work.
3386  */
3387  if (param->is_unsigned)
3388  *buffer= (uint8) value;
3389  else
3390  *buffer= (int8) value;
3391  *param->error= val64 != (param->is_unsigned ? (double)((uint8) *buffer) :
3392  (double)((int8) *buffer));
3393  break;
3394  case MYSQL_TYPE_SHORT:
3395  if (param->is_unsigned)
3396  {
3397  ushort data= (ushort) value;
3398  shortstore(buffer, data);
3399  }
3400  else
3401  {
3402  short data= (short) value;
3403  shortstore(buffer, data);
3404  }
3405  *param->error= val64 != (param->is_unsigned ? (double) (*(ushort*) buffer):
3406  (double) (*(short*) buffer));
3407  break;
3408  case MYSQL_TYPE_LONG:
3409  if (param->is_unsigned)
3410  {
3411  uint32 data= (uint32) value;
3412  longstore(buffer, data);
3413  }
3414  else
3415  {
3416  int32 data= (int32) value;
3417  longstore(buffer, data);
3418  }
3419  *param->error= val64 != (param->is_unsigned ? (double) (*(uint32*) buffer):
3420  (double) (*(int32*) buffer));
3421  break;
3422  case MYSQL_TYPE_LONGLONG:
3423  if (param->is_unsigned)
3424  {
3425  ulonglong data= (ulonglong) value;
3426  longlongstore(buffer, data);
3427  }
3428  else
3429  {
3430  longlong data= (longlong) value;
3431  longlongstore(buffer, data);
3432  }
3433  *param->error= val64 != (param->is_unsigned ?
3434  ulonglong2double(*(ulonglong*) buffer) :
3435  (double) (*(longlong*) buffer));
3436  break;
3437  case MYSQL_TYPE_FLOAT:
3438  {
3439  float data= (float) value;
3440  floatstore(buffer, data);
3441  *param->error= (*(float*) buffer) != value;
3442  break;
3443  }
3444  case MYSQL_TYPE_DOUBLE:
3445  {
3446  doublestore(buffer, value);
3447  break;
3448  }
3449  default:
3450  {
3451  /*
3452  Resort to fetch_string_with_conversion: this should handle
3453  floating point -> string conversion nicely, honor all typecodes
3454  and param->offset possibly set in mysql_stmt_fetch_column
3455  */
3456  char buff[FLOATING_POINT_BUFFER];
3457  size_t len;
3458  if (field->decimals >= NOT_FIXED_DEC)
3459  len= my_gcvt(value, type,
3460  (int) MY_MIN(sizeof(buff)-1, param->buffer_length),
3461  buff, NULL);
3462  else
3463  len= my_fcvt(value, (int) field->decimals, buff, NULL);
3464 
3465  if (field->flags & ZEROFILL_FLAG && len < field->length &&
3466  field->length < MAX_DOUBLE_STRING_REP_LENGTH - 1)
3467  {
3468  bmove_upp((uchar*) buff + field->length, (uchar*) buff + len,
3469  len);
3470  memset(buff, '0', field->length - len);
3471  len= field->length;
3472  }
3473  fetch_string_with_conversion(param, buff, len);
3474 
3475  break;
3476  }
3477  }
3478 }
3479 
3480 
3481 /*
3482  Fetch time/date/datetime to supplied buffer of any type
3483 
3484  SYNOPSIS
3485  param output buffer descriptor
3486  time column data
3487 */
3488 
3489 static void fetch_datetime_with_conversion(MYSQL_BIND *param,
3490  MYSQL_FIELD *field,
3491  MYSQL_TIME *my_time)
3492 {
3493  switch (param->buffer_type) {
3494  case MYSQL_TYPE_NULL: /* do nothing */
3495  break;
3496  case MYSQL_TYPE_DATE:
3497  *(MYSQL_TIME *)(param->buffer)= *my_time;
3498  *param->error= my_time->time_type != MYSQL_TIMESTAMP_DATE;
3499  break;
3500  case MYSQL_TYPE_TIME:
3501  *(MYSQL_TIME *)(param->buffer)= *my_time;
3502  *param->error= my_time->time_type != MYSQL_TIMESTAMP_TIME;
3503  break;
3504  case MYSQL_TYPE_DATETIME:
3505  case MYSQL_TYPE_TIMESTAMP:
3506  *(MYSQL_TIME *)(param->buffer)= *my_time;
3507  /* No error: time and date are compatible with datetime */
3508  break;
3509  case MYSQL_TYPE_YEAR:
3510  shortstore(param->buffer, my_time->year);
3511  *param->error= 1;
3512  break;
3513  case MYSQL_TYPE_FLOAT:
3514  case MYSQL_TYPE_DOUBLE:
3515  {
3516  ulonglong value= TIME_to_ulonglong(my_time);
3517  fetch_float_with_conversion(param, field,
3518  ulonglong2double(value), MY_GCVT_ARG_DOUBLE);
3519  break;
3520  }
3521  case MYSQL_TYPE_TINY:
3522  case MYSQL_TYPE_SHORT:
3523  case MYSQL_TYPE_INT24:
3524  case MYSQL_TYPE_LONG:
3525  case MYSQL_TYPE_LONGLONG:
3526  {
3527  longlong value= (longlong) TIME_to_ulonglong(my_time);
3528  fetch_long_with_conversion(param, field, value, TRUE);
3529  break;
3530  }
3531  default:
3532  {
3533  /*
3534  Convert time value to string and delegate the rest to
3535  fetch_string_with_conversion:
3536  */
3537  char buff[MAX_DATE_STRING_REP_LENGTH];
3538  uint length= my_TIME_to_str(my_time, buff, field->decimals);
3539  /* Resort to string conversion */
3540  fetch_string_with_conversion(param, (char *)buff, length);
3541  break;
3542  }
3543  }
3544 }
3545 
3546 
3547 /*
3548  Fetch and convert result set column to output buffer.
3549 
3550  SYNOPSIS
3551  fetch_result_with_conversion()
3552  param output buffer descriptor
3553  field column metadata
3554  row points to a column of result set tuple in binary format
3555 
3556  DESCRIPTION
3557  This is a fallback implementation of column fetch used
3558  if column and output buffer types do not match.
3559  Increases tuple pointer to point at the next column within the
3560  tuple.
3561 */
3562 
3563 static void fetch_result_with_conversion(MYSQL_BIND *param, MYSQL_FIELD *field,
3564  uchar **row)
3565 {
3566  enum enum_field_types field_type= field->type;
3567  uint field_is_unsigned= field->flags & UNSIGNED_FLAG;
3568 
3569  switch (field_type) {
3570  case MYSQL_TYPE_TINY:
3571  {
3572  uchar value= **row;
3573  /* sic: we need to cast to 'signed char' as 'char' may be unsigned */
3574  longlong data= field_is_unsigned ? (longlong) value :
3575  (longlong) (signed char) value;
3576  fetch_long_with_conversion(param, field, data, 0);
3577  *row+= 1;
3578  break;
3579  }
3580  case MYSQL_TYPE_SHORT:
3581  case MYSQL_TYPE_YEAR:
3582  {
3583  short value= sint2korr(*row);
3584  longlong data= field_is_unsigned ? (longlong) (unsigned short) value :
3585  (longlong) value;
3586  fetch_long_with_conversion(param, field, data, 0);
3587  *row+= 2;
3588  break;
3589  }
3590  case MYSQL_TYPE_INT24: /* mediumint is sent as 4 bytes int */
3591  case MYSQL_TYPE_LONG:
3592  {
3593  int32 value= sint4korr(*row);
3594  longlong data= field_is_unsigned ? (longlong) (uint32) value :
3595  (longlong) value;
3596  fetch_long_with_conversion(param, field, data, 0);
3597  *row+= 4;
3598  break;
3599  }
3600  case MYSQL_TYPE_LONGLONG:
3601  {
3602  longlong value= (longlong)sint8korr(*row);
3603  fetch_long_with_conversion(param, field, value,
3604  field->flags & UNSIGNED_FLAG);
3605  *row+= 8;
3606  break;
3607  }
3608  case MYSQL_TYPE_FLOAT:
3609  {
3610  float value;
3611  float4get(value,*row);
3612  fetch_float_with_conversion(param, field, value, MY_GCVT_ARG_FLOAT);
3613  *row+= 4;
3614  break;
3615  }
3616  case MYSQL_TYPE_DOUBLE:
3617  {
3618  double value;
3619  float8get(value,*row);
3620  fetch_float_with_conversion(param, field, value, MY_GCVT_ARG_DOUBLE);
3621  *row+= 8;
3622  break;
3623  }
3624  case MYSQL_TYPE_DATE:
3625  {
3626  MYSQL_TIME tm;
3627 
3628  read_binary_date(&tm, row);
3629  fetch_datetime_with_conversion(param, field, &tm);
3630  break;
3631  }
3632  case MYSQL_TYPE_TIME:
3633  {
3634  MYSQL_TIME tm;
3635 
3636  read_binary_time(&tm, row);
3637  fetch_datetime_with_conversion(param, field, &tm);
3638  break;
3639  }
3640  case MYSQL_TYPE_DATETIME:
3641  case MYSQL_TYPE_TIMESTAMP:
3642  {
3643  MYSQL_TIME tm;
3644 
3645  read_binary_datetime(&tm, row);
3646  fetch_datetime_with_conversion(param, field, &tm);
3647  break;
3648  }
3649  default:
3650  {
3651  ulong length= net_field_length(row);
3652  fetch_string_with_conversion(param, (char*) *row, length);
3653  *row+= length;
3654  break;
3655  }
3656  }
3657 }
3658 
3659 
3660 /*
3661  Functions to fetch data to application buffers without conversion.
3662 
3663  All functions have the following characteristics:
3664 
3665  SYNOPSIS
3666  fetch_result_xxx()
3667  param MySQL bind param
3668  pos Row value
3669 
3670  DESCRIPTION
3671  These are no-conversion functions, used in binary protocol to store
3672  rows in application buffers. A function used only if type of binary data
3673  is compatible with type of application buffer.
3674 
3675  RETURN
3676  none
3677 */
3678 
3679 static void fetch_result_tinyint(MYSQL_BIND *param, MYSQL_FIELD *field,
3680  uchar **row)
3681 {
3682  my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
3683  uchar data= **row;
3684  *(uchar *)param->buffer= data;
3685  *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX8;
3686  (*row)++;
3687 }
3688 
3689 static void fetch_result_short(MYSQL_BIND *param, MYSQL_FIELD *field,
3690  uchar **row)
3691 {
3692  my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
3693  ushort data= (ushort) sint2korr(*row);
3694  shortstore(param->buffer, data);
3695  *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX16;
3696  *row+= 2;
3697 }
3698 
3699 static void fetch_result_int32(MYSQL_BIND *param,
3700  MYSQL_FIELD *field __attribute__((unused)),
3701  uchar **row)
3702 {
3703  my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
3704  uint32 data= (uint32) sint4korr(*row);
3705  longstore(param->buffer, data);
3706  *param->error= param->is_unsigned != field_is_unsigned && data > INT_MAX32;
3707  *row+= 4;
3708 }
3709 
3710 static void fetch_result_int64(MYSQL_BIND *param,
3711  MYSQL_FIELD *field __attribute__((unused)),
3712  uchar **row)
3713 {
3714  my_bool field_is_unsigned= test(field->flags & UNSIGNED_FLAG);
3715  ulonglong data= (ulonglong) sint8korr(*row);
3716  *param->error= param->is_unsigned != field_is_unsigned && data > LONGLONG_MAX;
3717  longlongstore(param->buffer, data);
3718  *row+= 8;
3719 }
3720 
3721 static void fetch_result_float(MYSQL_BIND *param,
3722  MYSQL_FIELD *field __attribute__((unused)),
3723  uchar **row)
3724 {
3725  float value;
3726  float4get(value,*row);
3727  floatstore(param->buffer, value);
3728  *row+= 4;
3729 }
3730 
3731 static void fetch_result_double(MYSQL_BIND *param,
3732  MYSQL_FIELD *field __attribute__((unused)),
3733  uchar **row)
3734 {
3735  double value;
3736  float8get(value,*row);
3737  doublestore(param->buffer, value);
3738  *row+= 8;
3739 }
3740 
3741 static void fetch_result_time(MYSQL_BIND *param,
3742  MYSQL_FIELD *field __attribute__((unused)),
3743  uchar **row)
3744 {
3745  MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
3746  read_binary_time(tm, row);
3747 }
3748 
3749 static void fetch_result_date(MYSQL_BIND *param,
3750  MYSQL_FIELD *field __attribute__((unused)),
3751  uchar **row)
3752 {
3753  MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
3754  read_binary_date(tm, row);
3755 }
3756 
3757 static void fetch_result_datetime(MYSQL_BIND *param,
3758  MYSQL_FIELD *field __attribute__((unused)),
3759  uchar **row)
3760 {
3761  MYSQL_TIME *tm= (MYSQL_TIME *)param->buffer;
3762  read_binary_datetime(tm, row);
3763 }
3764 
3765 static void fetch_result_bin(MYSQL_BIND *param,
3766  MYSQL_FIELD *field __attribute__((unused)),
3767  uchar **row)
3768 {
3769  ulong length= net_field_length(row);
3770  ulong copy_length= MY_MIN(length, param->buffer_length);
3771  memcpy(param->buffer, (char *)*row, copy_length);
3772  *param->length= length;
3773  *param->error= copy_length < length;
3774  *row+= length;
3775 }
3776 
3777 static void fetch_result_str(MYSQL_BIND *param,
3778  MYSQL_FIELD *field __attribute__((unused)),
3779  uchar **row)
3780 {
3781  ulong length= net_field_length(row);
3782  ulong copy_length= MY_MIN(length, param->buffer_length);
3783  memcpy(param->buffer, (char *)*row, copy_length);
3784  /* Add an end null if there is room in the buffer */
3785  if (copy_length != param->buffer_length)
3786  ((uchar *)param->buffer)[copy_length]= '\0';
3787  *param->length= length; /* return total length */
3788  *param->error= copy_length < length;
3789  *row+= length;
3790 }
3791 
3792 
3793 /*
3794  functions to calculate max lengths for strings during
3795  mysql_stmt_store_result()
3796 */
3797 
3798 static void skip_result_fixed(MYSQL_BIND *param,
3799  MYSQL_FIELD *field __attribute__((unused)),
3800  uchar **row)
3801 
3802 {
3803  (*row)+= param->pack_length;
3804 }
3805 
3806 
3807 static void skip_result_with_length(MYSQL_BIND *param __attribute__((unused)),
3808  MYSQL_FIELD *field __attribute__((unused)),
3809  uchar **row)
3810 
3811 {
3812  ulong length= net_field_length(row);
3813  (*row)+= length;
3814 }
3815 
3816 
3817 static void skip_result_string(MYSQL_BIND *param __attribute__((unused)),
3818  MYSQL_FIELD *field,
3819  uchar **row)
3820 
3821 {
3822  ulong length= net_field_length(row);
3823  (*row)+= length;
3824  if (field->max_length < length)
3825  field->max_length= length;
3826 }
3827 
3828 
3829 /*
3830  Check that two field types are binary compatible i. e.
3831  have equal representation in the binary protocol and
3832  require client-side buffers of the same type.
3833 
3834  SYNOPSIS
3835  is_binary_compatible()
3836  type1 parameter type supplied by user
3837  type2 field type, obtained from result set metadata
3838 
3839  RETURN
3840  TRUE or FALSE
3841 */
3842 
3843 static my_bool is_binary_compatible(enum enum_field_types type1,
3844  enum enum_field_types type2)
3845 {
3846  static const enum enum_field_types
3847  range1[]= { MYSQL_TYPE_SHORT, MYSQL_TYPE_YEAR, MYSQL_TYPE_NULL },
3848  range2[]= { MYSQL_TYPE_INT24, MYSQL_TYPE_LONG, MYSQL_TYPE_NULL },
3849  range3[]= { MYSQL_TYPE_DATETIME, MYSQL_TYPE_TIMESTAMP, MYSQL_TYPE_NULL },
3850  range4[]= { MYSQL_TYPE_ENUM, MYSQL_TYPE_SET, MYSQL_TYPE_TINY_BLOB,
3851  MYSQL_TYPE_MEDIUM_BLOB, MYSQL_TYPE_LONG_BLOB, MYSQL_TYPE_BLOB,
3852  MYSQL_TYPE_VAR_STRING, MYSQL_TYPE_STRING, MYSQL_TYPE_GEOMETRY,
3853  MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NULL };
3854  static const enum enum_field_types
3855  *range_list[]= { range1, range2, range3, range4 },
3856  **range_list_end= range_list + sizeof(range_list)/sizeof(*range_list);
3857  const enum enum_field_types **range, *type;
3858 
3859  if (type1 == type2)
3860  return TRUE;
3861  for (range= range_list; range != range_list_end; ++range)
3862  {
3863  /* check that both type1 and type2 are in the same range */
3864  my_bool type1_found= FALSE, type2_found= FALSE;
3865  for (type= *range; *type != MYSQL_TYPE_NULL; type++)
3866  {
3867  type1_found|= type1 == *type;
3868  type2_found|= type2 == *type;
3869  }
3870  if (type1_found || type2_found)
3871  return type1_found && type2_found;
3872  }
3873  return FALSE;
3874 }
3875 
3876 
3877 /*
3878  Setup a fetch function for one column of a result set.
3879 
3880  SYNOPSIS
3881  setup_one_fetch_function()
3882  param output buffer descriptor
3883  field column descriptor
3884 
3885  DESCRIPTION
3886  When user binds result set buffers or when result set
3887  metadata is changed, we need to setup fetch (and possibly
3888  conversion) functions for all columns of the result set.
3889  In addition to that here we set up skip_result function, used
3890  to update result set metadata in case when
3891  STMT_ATTR_UPDATE_MAX_LENGTH attribute is set.
3892  Notice that while fetch_result is chosen depending on both
3893  field->type and param->type, skip_result depends on field->type
3894  only.
3895 
3896  RETURN
3897  TRUE fetch function for this typecode was not found (typecode
3898  is not supported by the client library)
3899  FALSE success
3900 */
3901 
3902 static my_bool setup_one_fetch_function(MYSQL_BIND *param, MYSQL_FIELD *field)
3903 {
3904  DBUG_ENTER("setup_one_fetch_function");
3905 
3906  /* Setup data copy functions for the different supported types */
3907  switch (param->buffer_type) {
3908  case MYSQL_TYPE_NULL: /* for dummy binds */
3909  /*
3910  It's not binary compatible with anything the server can return:
3911  no need to setup fetch_result, as it'll be reset anyway
3912  */
3913  *param->length= 0;
3914  break;
3915  case MYSQL_TYPE_TINY:
3916  param->fetch_result= fetch_result_tinyint;
3917  *param->length= 1;
3918  break;
3919  case MYSQL_TYPE_SHORT:
3920  case MYSQL_TYPE_YEAR:
3921  param->fetch_result= fetch_result_short;
3922  *param->length= 2;
3923  break;
3924  case MYSQL_TYPE_INT24:
3925  case MYSQL_TYPE_LONG:
3926  param->fetch_result= fetch_result_int32;
3927  *param->length= 4;
3928  break;
3929  case MYSQL_TYPE_LONGLONG:
3930  param->fetch_result= fetch_result_int64;
3931  *param->length= 8;
3932  break;
3933  case MYSQL_TYPE_FLOAT:
3934  param->fetch_result= fetch_result_float;
3935  *param->length= 4;
3936  break;
3937  case MYSQL_TYPE_DOUBLE:
3938  param->fetch_result= fetch_result_double;
3939  *param->length= 8;
3940  break;
3941  case MYSQL_TYPE_TIME:
3942  param->fetch_result= fetch_result_time;
3943  *param->length= sizeof(MYSQL_TIME);
3944  break;
3945  case MYSQL_TYPE_DATE:
3946  param->fetch_result= fetch_result_date;
3947  *param->length= sizeof(MYSQL_TIME);
3948  break;
3949  case MYSQL_TYPE_DATETIME:
3950  case MYSQL_TYPE_TIMESTAMP:
3951  param->fetch_result= fetch_result_datetime;
3952  *param->length= sizeof(MYSQL_TIME);
3953  break;
3954  case MYSQL_TYPE_TINY_BLOB:
3955  case MYSQL_TYPE_MEDIUM_BLOB:
3956  case MYSQL_TYPE_LONG_BLOB:
3957  case MYSQL_TYPE_BLOB:
3958  case MYSQL_TYPE_BIT:
3959  DBUG_ASSERT(param->buffer_length != 0);
3960  param->fetch_result= fetch_result_bin;
3961  break;
3962  case MYSQL_TYPE_VAR_STRING:
3963  case MYSQL_TYPE_STRING:
3964  case MYSQL_TYPE_DECIMAL:
3965  case MYSQL_TYPE_NEWDECIMAL:
3966  case MYSQL_TYPE_NEWDATE:
3967  DBUG_ASSERT(param->buffer_length != 0);
3968  param->fetch_result= fetch_result_str;
3969  break;
3970  default:
3971  DBUG_PRINT("error", ("Unknown param->buffer_type: %u",
3972  (uint) param->buffer_type));
3973  DBUG_RETURN(TRUE);
3974  }
3975  if (! is_binary_compatible(param->buffer_type, field->type))
3976  param->fetch_result= fetch_result_with_conversion;
3977 
3978  /* Setup skip_result functions (to calculate max_length) */
3979  param->skip_result= skip_result_fixed;
3980  switch (field->type) {
3981  case MYSQL_TYPE_NULL: /* for dummy binds */
3982  param->pack_length= 0;
3983  field->max_length= 0;
3984  break;
3985  case MYSQL_TYPE_TINY:
3986  param->pack_length= 1;
3987  field->max_length= 4; /* as in '-127' */
3988  break;
3989  case MYSQL_TYPE_YEAR:
3990  case MYSQL_TYPE_SHORT:
3991  param->pack_length= 2;
3992  field->max_length= 6; /* as in '-32767' */
3993  break;
3994  case MYSQL_TYPE_INT24:
3995  field->max_length= 9; /* as in '16777216' or in '-8388607' */
3996  param->pack_length= 4;
3997  break;
3998  case MYSQL_TYPE_LONG:
3999  field->max_length= 11; /* '-2147483647' */
4000  param->pack_length= 4;
4001  break;
4002  case MYSQL_TYPE_LONGLONG:
4003  field->max_length= 21; /* '18446744073709551616' */
4004  param->pack_length= 8;
4005  break;
4006  case MYSQL_TYPE_FLOAT:
4007  param->pack_length= 4;
4008  field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
4009  break;
4010  case MYSQL_TYPE_DOUBLE:
4011  param->pack_length= 8;
4012  field->max_length= MAX_DOUBLE_STRING_REP_LENGTH;
4013  break;
4014  case MYSQL_TYPE_TIME:
4015  field->max_length= 17; /* -819:23:48.123456 */
4016  param->skip_result= skip_result_with_length;
4017  break;
4018  case MYSQL_TYPE_DATE:
4019  field->max_length= 10; /* 2003-11-11 */
4020  param->skip_result= skip_result_with_length;
4021  break;
4022  case MYSQL_TYPE_DATETIME:
4023  case MYSQL_TYPE_TIMESTAMP:
4024  param->skip_result= skip_result_with_length;
4025  field->max_length= MAX_DATE_STRING_REP_LENGTH;
4026  break;
4027  case MYSQL_TYPE_DECIMAL:
4028  case MYSQL_TYPE_NEWDECIMAL:
4029  case MYSQL_TYPE_ENUM:
4030  case MYSQL_TYPE_SET:
4031  case MYSQL_TYPE_GEOMETRY:
4032  case MYSQL_TYPE_TINY_BLOB:
4033  case MYSQL_TYPE_MEDIUM_BLOB:
4034  case MYSQL_TYPE_LONG_BLOB:
4035  case MYSQL_TYPE_BLOB:
4036  case MYSQL_TYPE_VAR_STRING:
4037  case MYSQL_TYPE_STRING:
4038  case MYSQL_TYPE_BIT:
4039  case MYSQL_TYPE_NEWDATE:
4040  param->skip_result= skip_result_string;
4041  break;
4042  default:
4043  DBUG_PRINT("error", ("Unknown field->type: %u", (uint) field->type));
4044  DBUG_RETURN(TRUE);
4045  }
4046  DBUG_RETURN(FALSE);
4047 }
4048 
4049 
4050 /*
4051  Setup the bind buffers for resultset processing
4052 */
4053 
4054 my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *my_bind)
4055 {
4056  MYSQL_BIND *param, *end;
4057  MYSQL_FIELD *field;
4058  ulong bind_count= stmt->field_count;
4059  uint param_count= 0;
4060  DBUG_ENTER("mysql_stmt_bind_result");
4061  DBUG_PRINT("enter",("field_count: %lu", bind_count));
4062 
4063  if (!bind_count)
4064  {
4065  int errorcode= (int) stmt->state < (int) MYSQL_STMT_PREPARE_DONE ?
4066  CR_NO_PREPARE_STMT : CR_NO_STMT_METADATA;
4067  set_stmt_error(stmt, errorcode, unknown_sqlstate, NULL);
4068  DBUG_RETURN(1);
4069  }
4070 
4071  /*
4072  We only need to check that stmt->field_count - if it is not null
4073  stmt->bind was initialized in mysql_stmt_prepare
4074  stmt->bind overlaps with bind if mysql_stmt_bind_param
4075  is called from mysql_stmt_store_result.
4076  BEWARE of buffer overwrite ...
4077  */
4078 
4079  if (stmt->bind != my_bind)
4080  memcpy((char*) stmt->bind, (char*) my_bind,
4081  sizeof(MYSQL_BIND) * bind_count);
4082 
4083  for (param= stmt->bind, end= param + bind_count, field= stmt->fields ;
4084  param < end ;
4085  param++, field++)
4086  {
4087  DBUG_PRINT("info",("buffer_type: %u field_type: %u",
4088  (uint) param->buffer_type, (uint) field->type));
4089  /*
4090  Set param->is_null to point to a dummy variable if it's not set.
4091  This is to make the execute code easier
4092  */
4093  if (!param->is_null)
4094  param->is_null= &param->is_null_value;
4095 
4096  if (!param->length)
4097  param->length= &param->length_value;
4098 
4099  if (!param->error)
4100  param->error= &param->error_value;
4101 
4102  param->param_number= param_count++;
4103  param->offset= 0;
4104 
4105  if (setup_one_fetch_function(param, field))
4106  {
4107  strmov(stmt->sqlstate, unknown_sqlstate);
4108  sprintf(stmt->last_error,
4109  ER(stmt->last_errno= CR_UNSUPPORTED_PARAM_TYPE),
4110  field->type, param_count);
4111  DBUG_RETURN(1);
4112  }
4113  }
4114  stmt->bind_result_done= BIND_RESULT_DONE;
4115  if (stmt->mysql->options.report_data_truncation)
4116  stmt->bind_result_done|= REPORT_DATA_TRUNCATION;
4117 
4118  DBUG_RETURN(0);
4119 }
4120 
4121 
4122 /*
4123  Fetch row data to bind buffers
4124 */
4125 
4126 static int stmt_fetch_row(MYSQL_STMT *stmt, uchar *row)
4127 {
4128  MYSQL_BIND *my_bind, *end;
4129  MYSQL_FIELD *field;
4130  uchar *null_ptr, bit;
4131  int truncation_count= 0;
4132  /*
4133  Precondition: if stmt->field_count is zero or row is NULL, read_row_*
4134  function must return no data.
4135  */
4136  DBUG_ASSERT(stmt->field_count);
4137  DBUG_ASSERT(row);
4138 
4139  if (!stmt->bind_result_done)
4140  {
4141  /* If output parameters were not bound we should just return success */
4142  return 0;
4143  }
4144 
4145  null_ptr= row;
4146  row+= (stmt->field_count+9)/8; /* skip null bits */
4147  bit= 4; /* first 2 bits are reserved */
4148 
4149  /* Copy complete row to application buffers */
4150  for (my_bind= stmt->bind, end= my_bind + stmt->field_count,
4151  field= stmt->fields ;
4152  my_bind < end ;
4153  my_bind++, field++)
4154  {
4155  *my_bind->error= 0;
4156  if (*null_ptr & bit)
4157  {
4158  /*
4159  We should set both row_ptr and is_null to be able to see
4160  nulls in mysql_stmt_fetch_column. This is because is_null may point
4161  to user data which can be overwritten between mysql_stmt_fetch and
4162  mysql_stmt_fetch_column, and in this case nullness of column will be
4163  lost. See mysql_stmt_fetch_column for details.
4164  */
4165  my_bind->row_ptr= NULL;
4166  *my_bind->is_null= 1;
4167  }
4168  else
4169  {
4170  *my_bind->is_null= 0;
4171  my_bind->row_ptr= row;
4172  (*my_bind->fetch_result)(my_bind, field, &row);
4173  truncation_count+= *my_bind->error;
4174  }
4175  if (!((bit<<=1) & 255))
4176  {
4177  bit= 1; /* To next uchar */
4178  null_ptr++;
4179  }
4180  }
4181  if (truncation_count && (stmt->bind_result_done & REPORT_DATA_TRUNCATION))
4182  return MYSQL_DATA_TRUNCATED;
4183  return 0;
4184 }
4185 
4186 
4187 int cli_unbuffered_fetch(MYSQL *mysql, char **row)
4188 {
4189  if (packet_error == cli_safe_read(mysql))
4190  return 1;
4191 
4192  *row= ((mysql->net.read_pos[0] == 254) ? NULL :
4193  (char*) (mysql->net.read_pos+1));
4194  return 0;
4195 }
4196 
4197 
4198 /*
4199  Fetch and return row data to bound buffers, if any
4200 */
4201 
4202 int STDCALL mysql_stmt_fetch(MYSQL_STMT *stmt)
4203 {
4204  int rc;
4205  uchar *row;
4206  DBUG_ENTER("mysql_stmt_fetch");
4207 
4208  if ((rc= (*stmt->read_row_func)(stmt, &row)) ||
4209  ((rc= stmt_fetch_row(stmt, row)) && rc != MYSQL_DATA_TRUNCATED))
4210  {
4211  stmt->state= MYSQL_STMT_PREPARE_DONE; /* XXX: this is buggy */
4212  stmt->read_row_func= (rc == MYSQL_NO_DATA) ?
4213  stmt_read_row_no_data : stmt_read_row_no_result_set;
4214  }
4215  else
4216  {
4217  /* This is to know in mysql_stmt_fetch_column that data was fetched */
4218  stmt->state= MYSQL_STMT_FETCH_DONE;
4219  }
4220  DBUG_RETURN(rc);
4221 }
4222 
4223 
4224 /*
4225  Fetch data for one specified column data
4226 
4227  SYNOPSIS
4228  mysql_stmt_fetch_column()
4229  stmt Prepared statement handler
4230  my_bind Where data should be placed. Should be filled in as
4231  when calling mysql_stmt_bind_result()
4232  column Column to fetch (first column is 0)
4233  ulong offset Offset in result data (to fetch blob in pieces)
4234  This is normally 0
4235  RETURN
4236  0 ok
4237  1 error
4238 */
4239 
4240 int STDCALL mysql_stmt_fetch_column(MYSQL_STMT *stmt, MYSQL_BIND *my_bind,
4241  uint column, ulong offset)
4242 {
4243  MYSQL_BIND *param= stmt->bind+column;
4244  DBUG_ENTER("mysql_stmt_fetch_column");
4245 
4246  if ((int) stmt->state < (int) MYSQL_STMT_FETCH_DONE)
4247  {
4248  set_stmt_error(stmt, CR_NO_DATA, unknown_sqlstate, NULL);
4249  DBUG_RETURN(1);
4250  }
4251  if (column >= stmt->field_count)
4252  {
4253  set_stmt_error(stmt, CR_INVALID_PARAMETER_NO, unknown_sqlstate, NULL);
4254  DBUG_RETURN(1);
4255  }
4256 
4257  if (!my_bind->error)
4258  my_bind->error= &my_bind->error_value;
4259  *my_bind->error= 0;
4260  if (param->row_ptr)
4261  {
4262  MYSQL_FIELD *field= stmt->fields+column;
4263  uchar *row= param->row_ptr;
4264  my_bind->offset= offset;
4265  if (my_bind->is_null)
4266  *my_bind->is_null= 0;
4267  if (my_bind->length) /* Set the length if non char/binary types */
4268  *my_bind->length= *param->length;
4269  else
4270  my_bind->length= &param->length_value; /* Needed for fetch_result() */
4271  fetch_result_with_conversion(my_bind, field, &row);
4272  }
4273  else
4274  {
4275  if (my_bind->is_null)
4276  *my_bind->is_null= 1;
4277  }
4278  DBUG_RETURN(0);
4279 }
4280 
4281 
4282 /*
4283  Read all rows of data from server (binary format)
4284 */
4285 
4286 int cli_read_binary_rows(MYSQL_STMT *stmt)
4287 {
4288  ulong pkt_len;
4289  uchar *cp;
4290  MYSQL *mysql= stmt->mysql;
4291  MYSQL_DATA *result= &stmt->result;
4292  MYSQL_ROWS *cur, **prev_ptr= &result->data;
4293  NET *net;
4294 
4295  DBUG_ENTER("cli_read_binary_rows");
4296 
4297  if (!mysql)
4298  {
4299  set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
4300  DBUG_RETURN(1);
4301  }
4302 
4303  net = &mysql->net;
4304 
4305  while ((pkt_len= cli_safe_read(mysql)) != packet_error)
4306  {
4307  cp= net->read_pos;
4308  if (cp[0] != 254 || pkt_len >= 8)
4309  {
4310  if (!(cur= (MYSQL_ROWS*) alloc_root(&result->alloc,
4311  sizeof(MYSQL_ROWS) + pkt_len - 1)))
4312  {
4313  set_stmt_error(stmt, CR_OUT_OF_MEMORY, unknown_sqlstate, NULL);
4314  goto err;
4315  }
4316  cur->data= (MYSQL_ROW) (cur+1);
4317  *prev_ptr= cur;
4318  prev_ptr= &cur->next;
4319  memcpy((char *) cur->data, (char *) cp+1, pkt_len-1);
4320  cur->length= pkt_len; /* To allow us to do sanity checks */
4321  result->rows++;
4322  }
4323  else
4324  {
4325  /* end of data */
4326  *prev_ptr= 0;
4327  mysql->warning_count= uint2korr(cp+1);
4328  mysql->server_status= uint2korr(cp+3);
4329  DBUG_PRINT("info",("status: %u warning_count: %u",
4330  mysql->server_status, mysql->warning_count));
4331  DBUG_RETURN(0);
4332  }
4333  }
4334  set_stmt_errmsg(stmt, net);
4335 
4336 err:
4337  DBUG_RETURN(1);
4338 }
4339 
4340 
4341 /*
4342  Update meta data for statement
4343 
4344  SYNOPSIS
4345  stmt_update_metadata()
4346  stmt Statement handler
4347  row Binary data
4348 
4349  NOTES
4350  Only updates MYSQL_FIELD->max_length for strings
4351 */
4352 
4353 static void stmt_update_metadata(MYSQL_STMT *stmt, MYSQL_ROWS *data)
4354 {
4355  MYSQL_BIND *my_bind, *end;
4356  MYSQL_FIELD *field;
4357  uchar *null_ptr, bit;
4358  uchar *row= (uchar*) data->data;
4359 #ifndef DBUG_OFF
4360  uchar *row_end= row + data->length;
4361 #endif
4362 
4363  null_ptr= row;
4364  row+= (stmt->field_count+9)/8; /* skip null bits */
4365  bit= 4; /* first 2 bits are reserved */
4366 
4367  /* Go through all fields and calculate metadata */
4368  for (my_bind= stmt->bind, end= my_bind + stmt->field_count, field= stmt->fields ;
4369  my_bind < end ;
4370  my_bind++, field++)
4371  {
4372  if (!(*null_ptr & bit))
4373  (*my_bind->skip_result)(my_bind, field, &row);
4374  DBUG_ASSERT(row <= row_end);
4375  if (!((bit<<=1) & 255))
4376  {
4377  bit= 1; /* To next uchar */
4378  null_ptr++;
4379  }
4380  }
4381 }
4382 
4383 
4384 /*
4385  Store or buffer the binary results to stmt
4386 */
4387 
4388 int STDCALL mysql_stmt_store_result(MYSQL_STMT *stmt)
4389 {
4390  MYSQL *mysql= stmt->mysql;
4391  MYSQL_DATA *result= &stmt->result;
4392  DBUG_ENTER("mysql_stmt_store_result");
4393 
4394  if (!mysql)
4395  {
4396  /* mysql can be reset in mysql_close called from mysql_reconnect */
4397  set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
4398  DBUG_RETURN(1);
4399  }
4400 
4401  if (!stmt->field_count)
4402  DBUG_RETURN(0);
4403 
4404  if ((int) stmt->state < (int) MYSQL_STMT_EXECUTE_DONE)
4405  {
4406  set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
4407  DBUG_RETURN(1);
4408  }
4409 
4410  if (stmt->last_errno)
4411  {
4412  /* An attempt to use an invalid statement handle. */
4413  DBUG_RETURN(1);
4414  }
4415 
4416  if (mysql->status == MYSQL_STATUS_READY &&
4417  stmt->server_status & SERVER_STATUS_CURSOR_EXISTS)
4418  {
4419  /*
4420  Server side cursor exist, tell server to start sending the rows
4421  */
4422  NET *net= &mysql->net;
4423  uchar buff[4 /* statement id */ +
4424  4 /* number of rows to fetch */];
4425 
4426  /* Send row request to the server */
4427  int4store(buff, stmt->stmt_id);
4428  int4store(buff + 4, (int)~0); /* number of rows to fetch */
4429  if (cli_advanced_command(mysql, COM_STMT_FETCH, buff, sizeof(buff),
4430  (uchar*) 0, 0, 1, stmt))
4431  {
4432  /*
4433  Don't set stmt error if stmt->mysql is NULL, as the error in this case
4434  has already been set by mysql_prune_stmt_list().
4435  */
4436  if (stmt->mysql)
4437  set_stmt_errmsg(stmt, net);
4438  DBUG_RETURN(1);
4439  }
4440  }
4441  else if (mysql->status != MYSQL_STATUS_STATEMENT_GET_RESULT)
4442  {
4443  set_stmt_error(stmt, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate, NULL);
4444  DBUG_RETURN(1);
4445  }
4446 
4447  if (stmt->update_max_length && !stmt->bind_result_done)
4448  {
4449  /*
4450  We must initalize the bind structure to be able to calculate
4451  max_length
4452  */
4453  MYSQL_BIND *my_bind, *end;
4454  MYSQL_FIELD *field;
4455  memset(stmt->bind, 0, sizeof(*stmt->bind) * stmt->field_count);
4456 
4457  for (my_bind= stmt->bind, end= my_bind + stmt->field_count,
4458  field= stmt->fields;
4459  my_bind < end ;
4460  my_bind++, field++)
4461  {
4462  my_bind->buffer_type= MYSQL_TYPE_NULL;
4463  my_bind->buffer_length=1;
4464  }
4465 
4466  if (mysql_stmt_bind_result(stmt, stmt->bind))
4467  DBUG_RETURN(1);
4468  stmt->bind_result_done= 0; /* No normal bind done */
4469  }
4470 
4471  if ((*mysql->methods->read_binary_rows)(stmt))
4472  {
4473  free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
4474  result->data= NULL;
4475  result->rows= 0;
4476  mysql->status= MYSQL_STATUS_READY;
4477  DBUG_RETURN(1);
4478  }
4479 
4480  /* Assert that if there was a cursor, all rows have been fetched */
4481  DBUG_ASSERT(mysql->status != MYSQL_STATUS_READY ||
4482  (mysql->server_status & SERVER_STATUS_LAST_ROW_SENT));
4483 
4484  if (stmt->update_max_length)
4485  {
4486  MYSQL_ROWS *cur= result->data;
4487  for(; cur; cur=cur->next)
4488  stmt_update_metadata(stmt, cur);
4489  }
4490 
4491  stmt->data_cursor= result->data;
4492  mysql->affected_rows= stmt->affected_rows= result->rows;
4493  stmt->read_row_func= stmt_read_row_buffered;
4494  mysql->unbuffered_fetch_owner= 0; /* set in stmt_execute */
4495  mysql->status= MYSQL_STATUS_READY; /* server is ready */
4496  DBUG_RETURN(0); /* Data buffered, must be fetched with mysql_stmt_fetch() */
4497 }
4498 
4499 
4500 /*
4501  Seek to desired row in the statement result set
4502 */
4503 
4504 MYSQL_ROW_OFFSET STDCALL
4505 mysql_stmt_row_seek(MYSQL_STMT *stmt, MYSQL_ROW_OFFSET row)
4506 {
4507  MYSQL_ROW_OFFSET offset= stmt->data_cursor;
4508  DBUG_ENTER("mysql_stmt_row_seek");
4509 
4510  stmt->data_cursor= row;
4511  DBUG_RETURN(offset);
4512 }
4513 
4514 
4515 /*
4516  Return the current statement row cursor position
4517 */
4518 
4519 MYSQL_ROW_OFFSET STDCALL
4520 mysql_stmt_row_tell(MYSQL_STMT *stmt)
4521 {
4522  DBUG_ENTER("mysql_stmt_row_tell");
4523 
4524  DBUG_RETURN(stmt->data_cursor);
4525 }
4526 
4527 
4528 /*
4529  Move the stmt result set data cursor to specified row
4530 */
4531 
4532 void STDCALL
4533 mysql_stmt_data_seek(MYSQL_STMT *stmt, my_ulonglong row)
4534 {
4535  MYSQL_ROWS *tmp= stmt->result.data;
4536  DBUG_ENTER("mysql_stmt_data_seek");
4537  DBUG_PRINT("enter",("row id to seek: %ld",(long) row));
4538 
4539  for (; tmp && row; --row, tmp= tmp->next)
4540  ;
4541  stmt->data_cursor= tmp;
4542  if (!row && tmp)
4543  {
4544  /* Rewind the counter */
4545  stmt->read_row_func= stmt_read_row_buffered;
4546  stmt->state= MYSQL_STMT_EXECUTE_DONE;
4547  }
4548  DBUG_VOID_RETURN;
4549 }
4550 
4551 
4552 /*
4553  Return total rows the current statement result set
4554 */
4555 
4556 my_ulonglong STDCALL mysql_stmt_num_rows(MYSQL_STMT *stmt)
4557 {
4558  DBUG_ENTER("mysql_stmt_num_rows");
4559 
4560  DBUG_RETURN(stmt->result.rows);
4561 }
4562 
4563 
4564 /*
4565  Free the client side memory buffers, reset long data state
4566  on client if necessary, and reset the server side statement if
4567  this has been requested.
4568 */
4569 
4570 static my_bool reset_stmt_handle(MYSQL_STMT *stmt, uint flags)
4571 {
4572  /* If statement hasn't been prepared there is nothing to reset */
4573  if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
4574  {
4575  MYSQL *mysql= stmt->mysql;
4576  MYSQL_DATA *result= &stmt->result;
4577 
4578  /*
4579  Reset stored result set if so was requested or it's a part
4580  of cursor fetch.
4581  */
4582  if (flags & RESET_STORE_RESULT)
4583  {
4584  /* Result buffered */
4585  free_root(&result->alloc, MYF(MY_KEEP_PREALLOC));
4586  result->data= NULL;
4587  result->rows= 0;
4588  stmt->data_cursor= NULL;
4589  }
4590  if (flags & RESET_LONG_DATA)
4591  {
4592  MYSQL_BIND *param= stmt->params, *param_end= param + stmt->param_count;
4593  /* Clear long_data_used flags */
4594  for (; param < param_end; param++)
4595  param->long_data_used= 0;
4596  }
4597  stmt->read_row_func= stmt_read_row_no_result_set;
4598  if (mysql)
4599  {
4600  if ((int) stmt->state > (int) MYSQL_STMT_PREPARE_DONE)
4601  {
4602  if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
4603  mysql->unbuffered_fetch_owner= 0;
4604  if (stmt->field_count && mysql->status != MYSQL_STATUS_READY)
4605  {
4606  /* There is a result set and it belongs to this statement */
4607  (*mysql->methods->flush_use_result)(mysql, FALSE);
4608  if (mysql->unbuffered_fetch_owner)
4609  *mysql->unbuffered_fetch_owner= TRUE;
4610  mysql->status= MYSQL_STATUS_READY;
4611  }
4612  }
4613  if (flags & RESET_SERVER_SIDE)
4614  {
4615  /*
4616  Reset the server side statement and close the server side
4617  cursor if it exists.
4618  */
4619  uchar buff[MYSQL_STMT_HEADER]; /* packet header: 4 bytes for stmt id */
4620  int4store(buff, stmt->stmt_id);
4621  if ((*mysql->methods->advanced_command)(mysql, COM_STMT_RESET, buff,
4622  sizeof(buff), 0, 0, 0, stmt))
4623  {
4624  set_stmt_errmsg(stmt, &mysql->net);
4625  stmt->state= MYSQL_STMT_INIT_DONE;
4626  return 1;
4627  }
4628  }
4629  }
4630  if (flags & RESET_CLEAR_ERROR)
4631  stmt_clear_error(stmt);
4632  stmt->state= MYSQL_STMT_PREPARE_DONE;
4633  }
4634  return 0;
4635 }
4636 
4637 my_bool STDCALL mysql_stmt_free_result(MYSQL_STMT *stmt)
4638 {
4639  DBUG_ENTER("mysql_stmt_free_result");
4640 
4641  /* Free the client side and close the server side cursor if there is one */
4642  DBUG_RETURN(reset_stmt_handle(stmt, RESET_LONG_DATA | RESET_STORE_RESULT |
4643  RESET_CLEAR_ERROR));
4644 }
4645 
4646 /********************************************************************
4647  statement error handling and close
4648 *********************************************************************/
4649 
4650 /*
4651  Close the statement handle by freeing all alloced resources
4652 
4653  SYNOPSIS
4654  mysql_stmt_close()
4655  stmt Statement handle
4656 
4657  RETURN VALUES
4658  0 ok
4659  1 error
4660 */
4661 
4662 my_bool STDCALL mysql_stmt_close(MYSQL_STMT *stmt)
4663 {
4664  MYSQL *mysql= stmt->mysql;
4665  int rc= 0;
4666  DBUG_ENTER("mysql_stmt_close");
4667 
4668  free_root(&stmt->result.alloc, MYF(0));
4669  free_root(&stmt->mem_root, MYF(0));
4670  free_root(&stmt->extension->fields_mem_root, MYF(0));
4671 
4672  if (mysql)
4673  {
4674  mysql->stmts= list_delete(mysql->stmts, &stmt->list);
4675  /*
4676  Clear NET error state: if the following commands come through
4677  successfully, connection will still be usable for other commands.
4678  */
4679  net_clear_error(&mysql->net);
4680  if ((int) stmt->state > (int) MYSQL_STMT_INIT_DONE)
4681  {
4682  uchar buff[MYSQL_STMT_HEADER]; /* 4 bytes - stmt id */
4683 
4684  if (mysql->unbuffered_fetch_owner == &stmt->unbuffered_fetch_cancelled)
4685  mysql->unbuffered_fetch_owner= 0;
4686  if (mysql->status != MYSQL_STATUS_READY)
4687  {
4688  /*
4689  Flush result set of the connection. If it does not belong
4690  to this statement, set a warning.
4691  */
4692  (*mysql->methods->flush_use_result)(mysql, TRUE);
4693  if (mysql->unbuffered_fetch_owner)
4694  *mysql->unbuffered_fetch_owner= TRUE;
4695  mysql->status= MYSQL_STATUS_READY;
4696  }
4697  int4store(buff, stmt->stmt_id);
4698  if ((rc= stmt_command(mysql, COM_STMT_CLOSE, buff, 4, stmt)))
4699  {
4700  set_stmt_errmsg(stmt, &mysql->net);
4701  }
4702  }
4703  }
4704 
4705  my_free(stmt->extension);
4706  my_free(stmt);
4707 
4708  DBUG_RETURN(test(rc));
4709 }
4710 
4711 /*
4712  Reset the statement buffers in server
4713 */
4714 
4715 my_bool STDCALL mysql_stmt_reset(MYSQL_STMT *stmt)
4716 {
4717  DBUG_ENTER("mysql_stmt_reset");
4718  DBUG_ASSERT(stmt != 0);
4719  if (!stmt->mysql)
4720  {
4721  /* mysql can be reset in mysql_close called from mysql_reconnect */
4722  set_stmt_error(stmt, CR_SERVER_LOST, unknown_sqlstate, NULL);
4723  DBUG_RETURN(1);
4724  }
4725  /* Reset the client and server sides of the prepared statement */
4726  DBUG_RETURN(reset_stmt_handle(stmt,
4727  RESET_SERVER_SIDE | RESET_LONG_DATA |
4728  RESET_CLEAR_ERROR));
4729 }
4730 
4731 /*
4732  Return statement error code
4733 */
4734 
4735 uint STDCALL mysql_stmt_errno(MYSQL_STMT * stmt)
4736 {
4737  DBUG_ENTER("mysql_stmt_errno");
4738  DBUG_RETURN(stmt->last_errno);
4739 }
4740 
4741 const char *STDCALL mysql_stmt_sqlstate(MYSQL_STMT * stmt)
4742 {
4743  DBUG_ENTER("mysql_stmt_sqlstate");
4744  DBUG_RETURN(stmt->sqlstate);
4745 }
4746 
4747 /*
4748  Return statement error message
4749 */
4750 
4751 const char *STDCALL mysql_stmt_error(MYSQL_STMT * stmt)
4752 {
4753  DBUG_ENTER("mysql_stmt_error");
4754  DBUG_RETURN(stmt->last_error);
4755 }
4756 
4757 
4758 /********************************************************************
4759  Transactional APIs
4760 *********************************************************************/
4761 
4762 /*
4763  Commit the current transaction
4764 */
4765 
4766 my_bool STDCALL mysql_commit(MYSQL * mysql)
4767 {
4768  DBUG_ENTER("mysql_commit");
4769  DBUG_RETURN((my_bool) mysql_real_query(mysql, "commit", 6));
4770 }
4771 
4772 /*
4773  Rollback the current transaction
4774 */
4775 
4776 my_bool STDCALL mysql_rollback(MYSQL * mysql)
4777 {
4778  DBUG_ENTER("mysql_rollback");
4779  DBUG_RETURN((my_bool) mysql_real_query(mysql, "rollback", 8));
4780 }
4781 
4782 
4783 /*
4784  Set autocommit to either true or false
4785 */
4786 
4787 my_bool STDCALL mysql_autocommit(MYSQL * mysql, my_bool auto_mode)
4788 {
4789  DBUG_ENTER("mysql_autocommit");
4790  DBUG_PRINT("enter", ("mode : %d", auto_mode));
4791 
4792  DBUG_RETURN((my_bool) mysql_real_query(mysql, auto_mode ?
4793  "set autocommit=1":"set autocommit=0",
4794  16));
4795 }
4796 
4797 
4798 /********************************************************************
4799  Multi query execution + SPs APIs
4800 *********************************************************************/
4801 
4802 /*
4803  Returns true/false to indicate whether any more query results exist
4804  to be read using mysql_next_result()
4805 */
4806 
4807 my_bool STDCALL mysql_more_results(MYSQL *mysql)
4808 {
4809  my_bool res;
4810  DBUG_ENTER("mysql_more_results");
4811 
4812  res= ((mysql->server_status & SERVER_MORE_RESULTS_EXISTS) ? 1: 0);
4813  DBUG_PRINT("exit",("More results exists ? %d", res));
4814  DBUG_RETURN(res);
4815 }
4816 
4817 
4818 /*
4819  Reads and returns the next query results
4820 */
4821 int STDCALL mysql_next_result(MYSQL *mysql)
4822 {
4823  DBUG_ENTER("mysql_next_result");
4824 
4825  if (mysql->status != MYSQL_STATUS_READY)
4826  {
4827  set_mysql_error(mysql, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
4828  DBUG_RETURN(1);
4829  }
4830 
4831  net_clear_error(&mysql->net);
4832  mysql->affected_rows= ~(my_ulonglong) 0;
4833 
4834  if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
4835  DBUG_RETURN((*mysql->methods->next_result)(mysql));
4836 
4837  DBUG_RETURN(-1); /* No more results */
4838 }
4839 
4840 
4841 int STDCALL mysql_stmt_next_result(MYSQL_STMT *stmt)
4842 {
4843  MYSQL *mysql= stmt->mysql;
4844  int rc;
4845  DBUG_ENTER("mysql_stmt_next_result");
4846 
4847  if (!mysql)
4848  DBUG_RETURN(1);
4849 
4850  if (stmt->last_errno)
4851  DBUG_RETURN(stmt->last_errno);
4852 
4853  if (mysql->server_status & SERVER_MORE_RESULTS_EXISTS)
4854  {
4855  if (reset_stmt_handle(stmt, RESET_STORE_RESULT))
4856  DBUG_RETURN(1);
4857  }
4858 
4859  rc= mysql_next_result(mysql);
4860 
4861  if (rc)
4862  {
4863  set_stmt_errmsg(stmt, &mysql->net);
4864  DBUG_RETURN(rc);
4865  }
4866 
4867  if (mysql->status == MYSQL_STATUS_GET_RESULT)
4868  mysql->status= MYSQL_STATUS_STATEMENT_GET_RESULT;
4869 
4870  stmt->state= MYSQL_STMT_EXECUTE_DONE;
4871  stmt->bind_result_done= FALSE;
4872  stmt->field_count= mysql->field_count;
4873 
4874  if (mysql->field_count)
4875  {
4876  alloc_stmt_fields(stmt);
4877  prepare_to_fetch_result(stmt);
4878  }
4879 
4880  DBUG_RETURN(0);
4881 }
4882 
4883 
4884 MYSQL_RES * STDCALL mysql_use_result(MYSQL *mysql)
4885 {
4886  return (*mysql->methods->use_result)(mysql);
4887 }
4888 
4889 my_bool STDCALL mysql_read_query_result(MYSQL *mysql)
4890 {
4891  return (*mysql->methods->read_query_result)(mysql);
4892 }
4893