MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
protocol.cc
Go to the documentation of this file.
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 
23 #include "sql_priv.h"
24 #include "unireg.h" // REQUIRED: for other includes
25 #include "protocol.h"
26 #include "sql_class.h" // THD
27 #include <stdarg.h>
28 
29 using std::min;
30 using std::max;
31 
32 static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
33 /* Declared non-static only because of the embedded library. */
34 bool net_send_error_packet(THD *, uint, const char *, const char *);
35 /* Declared non-static only because of the embedded library. */
36 bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *);
37 /* Declared non-static only because of the embedded library. */
38 bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count);
39 #ifndef EMBEDDED_LIBRARY
40 static bool write_eof_packet(THD *, NET *, uint, uint);
41 #endif
42 
43 #ifndef EMBEDDED_LIBRARY
44 bool Protocol::net_store_data(const uchar *from, size_t length)
45 #else
46 bool Protocol_binary::net_store_data(const uchar *from, size_t length)
47 #endif
48 {
49  ulong packet_length=packet->length();
50  /*
51  The +9 comes from that strings of length longer than 16M require
52  9 bytes to be stored (see net_store_length).
53  */
54  if (packet_length+9+length > packet->alloced_length() &&
55  packet->realloc(packet_length+9+length))
56  return 1;
57  uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length);
58  memcpy(to,from,length);
59  packet->length((uint) (to+length-(uchar*) packet->ptr()));
60  return 0;
61 }
62 
63 
64 
65 
66 /*
67  net_store_data() - extended version with character set conversion.
68 
69  It is optimized for short strings whose length after
70  conversion is garanteed to be less than 251, which accupies
71  exactly one byte to store length. It allows not to use
72  the "convert" member as a temporary buffer, conversion
73  is done directly to the "packet" member.
74  The limit 251 is good enough to optimize send_result_set_metadata()
75  because column, table, database names fit into this limit.
76 */
77 
78 #ifndef EMBEDDED_LIBRARY
79 bool Protocol::net_store_data(const uchar *from, size_t length,
80  const CHARSET_INFO *from_cs,
81  const CHARSET_INFO *to_cs)
82 {
83  uint dummy_errors;
84  /* Calculate maxumum possible result length */
85  uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
86  if (conv_length > 250)
87  {
88  /*
89  For strings with conv_length greater than 250 bytes
90  we don't know how many bytes we will need to store length: one or two,
91  because we don't know result length until conversion is done.
92  For example, when converting from utf8 (mbmaxlen=3) to latin1,
93  conv_length=300 means that the result length can vary between 100 to 300.
94  length=100 needs one byte, length=300 needs to bytes.
95 
96  Thus conversion directly to "packet" is not worthy.
97  Let's use "convert" as a temporary buffer.
98  */
99  return (convert->copy((const char*) from, length, from_cs,
100  to_cs, &dummy_errors) ||
101  net_store_data((const uchar*) convert->ptr(), convert->length()));
102  }
103 
104  ulong packet_length= packet->length();
105  ulong new_length= packet_length + conv_length + 1;
106 
107  if (new_length > packet->alloced_length() && packet->realloc(new_length))
108  return 1;
109 
110  char *length_pos= (char*) packet->ptr() + packet_length;
111  char *to= length_pos + 1;
112 
113  to+= copy_and_convert(to, conv_length, to_cs,
114  (const char*) from, length, from_cs, &dummy_errors);
115 
116  net_store_length((uchar*) length_pos, to - length_pos - 1);
117  packet->length((uint) (to - packet->ptr()));
118  return 0;
119 }
120 #endif
121 
122 
145 bool net_send_error(THD *thd, uint sql_errno, const char *err,
146  const char* sqlstate)
147 {
148  bool error;
149  DBUG_ENTER("net_send_error");
150 
151  DBUG_ASSERT(!thd->sp_runtime_ctx);
152  DBUG_ASSERT(sql_errno);
153  DBUG_ASSERT(err);
154 
155  DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
156 
157  if (sqlstate == NULL)
158  sqlstate= mysql_errno_to_sqlstate(sql_errno);
159 
160  /*
161  It's one case when we can push an error even though there
162  is an OK or EOF already.
163  */
164  thd->get_stmt_da()->set_overwrite_status(true);
165 
166  /* Abort multi-result sets */
167  thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
168 
169  error= net_send_error_packet(thd, sql_errno, err, sqlstate);
170 
171  thd->get_stmt_da()->set_overwrite_status(false);
172 
173  DBUG_RETURN(error);
174 }
175 
204 #ifndef EMBEDDED_LIBRARY
205 bool
206 net_send_ok(THD *thd,
207  uint server_status, uint statement_warn_count,
208  ulonglong affected_rows, ulonglong id, const char *message)
209 {
210  NET *net= &thd->net;
211  uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
212  bool error= FALSE;
213  DBUG_ENTER("net_send_ok");
214 
215  if (! net->vio) // hack for re-parsing queries
216  {
217  DBUG_PRINT("info", ("vio present: NO"));
218  DBUG_RETURN(FALSE);
219  }
220 
221  buff[0]=0; // No fields
222  pos=net_store_length(buff+1,affected_rows);
223  pos=net_store_length(pos, id);
224  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
225  {
226  DBUG_PRINT("info",
227  ("affected_rows: %lu id: %lu status: %u warning_count: %u",
228  (ulong) affected_rows,
229  (ulong) id,
230  (uint) (server_status & 0xffff),
231  (uint) statement_warn_count));
232  int2store(pos, server_status);
233  pos+=2;
234 
235  /* We can only return up to 65535 warnings in two bytes */
236  uint tmp= min(statement_warn_count, 65535U);
237  int2store(pos, tmp);
238  pos+= 2;
239  }
240  else if (net->return_status) // For 4.0 protocol
241  {
242  int2store(pos, server_status);
243  pos+=2;
244  }
245  thd->get_stmt_da()->set_overwrite_status(true);
246 
247  if (message && message[0])
248  pos= net_store_data(pos, (uchar*) message, strlen(message));
249  error= my_net_write(net, buff, (size_t) (pos-buff));
250  if (!error)
251  error= net_flush(net);
252 
253 
254  thd->get_stmt_da()->set_overwrite_status(false);
255  DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
256 
257  DBUG_RETURN(error);
258 }
259 
260 static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
261 
285 bool
286 net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
287 {
288  NET *net= &thd->net;
289  bool error= FALSE;
290  DBUG_ENTER("net_send_eof");
291  /* Set to TRUE if no active vio, to work well in case of --init-file */
292  if (net->vio != 0)
293  {
294  thd->get_stmt_da()->set_overwrite_status(true);
295  error= write_eof_packet(thd, net, server_status, statement_warn_count);
296  if (!error)
297  error= net_flush(net);
298  thd->get_stmt_da()->set_overwrite_status(false);
299  DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
300  }
301  DBUG_RETURN(error);
302 }
303 
304 
320 static bool write_eof_packet(THD *thd, NET *net,
321  uint server_status,
322  uint statement_warn_count)
323 {
324  bool error;
325  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
326  {
327  uchar buff[5];
328  /*
329  Don't send warn count during SP execution, as the warn_list
330  is cleared between substatements, and mysqltest gets confused
331  */
332  uint tmp= min(statement_warn_count, 65535U);
333  buff[0]= 254;
334  int2store(buff+1, tmp);
335  /*
336  The following test should never be true, but it's better to do it
337  because if 'is_fatal_error' is set the server is not going to execute
338  other queries (see the if test in dispatch_command / COM_QUERY)
339  */
340  if (thd->is_fatal_error)
341  server_status&= ~SERVER_MORE_RESULTS_EXISTS;
342  int2store(buff + 3, server_status);
343  error= my_net_write(net, buff, 5);
344  }
345  else
346  error= my_net_write(net, eof_buff, 1);
347 
348  return error;
349 }
350 
361 bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
362  const char* sqlstate)
363 
364 {
365  NET *net= &thd->net;
366  uint length;
367  /*
368  buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512
369  */
370  uint error;
371  char converted_err[MYSQL_ERRMSG_SIZE];
372  char buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos;
373 
374  DBUG_ENTER("send_error_packet");
375 
376  if (net->vio == 0)
377  {
378  if (thd->bootstrap)
379  {
380  /* In bootstrap it's ok to print on stderr */
381  fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
382  }
383  DBUG_RETURN(FALSE);
384  }
385 
386  int2store(buff,sql_errno);
387  pos= buff+2;
388  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
389  {
390  /* The first # is to make the protocol backward compatible */
391  buff[2]= '#';
392  pos= strmov(buff+3, sqlstate);
393  }
394 
395  convert_error_message(converted_err, sizeof(converted_err),
396  thd->variables.character_set_results,
397  err, strlen(err), system_charset_info, &error);
398  /* Converted error message is always null-terminated. */
399  length= (uint) (strmake(pos, converted_err, MYSQL_ERRMSG_SIZE - 1) - buff);
400 
401  DBUG_RETURN(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) buff,
402  length));
403 }
404 
405 #endif /* EMBEDDED_LIBRARY */
406 
418 static uchar *net_store_length_fast(uchar *packet, uint length)
419 {
420  if (length < 251)
421  {
422  *packet=(uchar) length;
423  return packet+1;
424  }
425  *packet++=252;
426  int2store(packet,(uint) length);
427  return packet+2;
428 }
429 
487 {
488  DBUG_ENTER("Protocol::end_statement");
489  DBUG_ASSERT(! thd->get_stmt_da()->is_sent());
490  bool error= FALSE;
491 
492  /* Can not be true, but do not take chances in production. */
493  if (thd->get_stmt_da()->is_sent())
494  DBUG_VOID_RETURN;
495 
496  switch (thd->get_stmt_da()->status()) {
498  /* The query failed, send error to log and abort bootstrap. */
499  error= send_error(thd->get_stmt_da()->sql_errno(),
500  thd->get_stmt_da()->message(),
501  thd->get_stmt_da()->get_sqlstate());
502  break;
504  error= send_eof(thd->server_status,
505  thd->get_stmt_da()->statement_warn_count());
506  break;
508  error= send_ok(thd->server_status,
509  thd->get_stmt_da()->statement_warn_count(),
510  thd->get_stmt_da()->affected_rows(),
511  thd->get_stmt_da()->last_insert_id(),
512  thd->get_stmt_da()->message());
513  break;
515  break;
517  default:
518  DBUG_ASSERT(0);
519  error= send_ok(thd->server_status, 0, 0, 0, NULL);
520  break;
521  }
522  if (!error)
523  thd->get_stmt_da()->set_is_sent(true);
524  DBUG_VOID_RETURN;
525 }
526 
527 
537 bool Protocol::send_ok(uint server_status, uint statement_warn_count,
538  ulonglong affected_rows, ulonglong last_insert_id,
539  const char *message)
540 {
541  DBUG_ENTER("Protocol::send_ok");
542  const bool retval=
543  net_send_ok(thd, server_status, statement_warn_count,
544  affected_rows, last_insert_id, message);
545  DBUG_RETURN(retval);
546 }
547 
548 
555 bool Protocol::send_eof(uint server_status, uint statement_warn_count)
556 {
557  DBUG_ENTER("Protocol::send_eof");
558  const bool retval= net_send_eof(thd, server_status, statement_warn_count);
559  DBUG_RETURN(retval);
560 }
561 
562 
569 bool Protocol::send_error(uint sql_errno, const char *err_msg,
570  const char *sql_state)
571 {
572  DBUG_ENTER("Protocol::send_error");
573  const bool retval= net_send_error_packet(thd, sql_errno, err_msg, sql_state);
574  DBUG_RETURN(retval);
575 }
576 
577 
578 /****************************************************************************
579  Functions used by the protocol functions (like net_send_ok) to store
580  strings and numbers in the header result packet.
581 ****************************************************************************/
582 
583 /* The following will only be used for short strings < 65K */
584 
585 uchar *net_store_data(uchar *to, const uchar *from, size_t length)
586 {
587  to=net_store_length_fast(to,length);
588  memcpy(to,from,length);
589  return to+length;
590 }
591 
592 uchar *net_store_data(uchar *to,int32 from)
593 {
594  char buff[20];
595  uint length=(uint) (int10_to_str(from,buff,10)-buff);
596  to=net_store_length_fast(to,length);
597  memcpy(to,buff,length);
598  return to+length;
599 }
600 
601 uchar *net_store_data(uchar *to,longlong from)
602 {
603  char buff[22];
604  uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
605  to=net_store_length_fast(to,length);
606  memcpy(to,buff,length);
607  return to+length;
608 }
609 
610 
611 /*****************************************************************************
612  Default Protocol functions
613 *****************************************************************************/
614 
615 void Protocol::init(THD *thd_arg)
616 {
617  thd=thd_arg;
618  packet= &thd->packet;
619  convert= &thd->convert_buffer;
620 #ifndef DBUG_OFF
621  field_types= 0;
622 #endif
623 }
624 
632 {
633  net_send_eof(thd_arg, thd_arg->server_status, 0 /* no warnings, we're inside SP */);
634 }
635 
636 
637 bool Protocol::flush()
638 {
639 #ifndef EMBEDDED_LIBRARY
640  bool error;
641  thd->get_stmt_da()->set_overwrite_status(true);
642  error= net_flush(&thd->net);
643  thd->get_stmt_da()->set_overwrite_status(false);
644  return error;
645 #else
646  return 0;
647 #endif
648 }
649 
650 #ifndef EMBEDDED_LIBRARY
651 
671 {
672  List_iterator_fast<Item> it(*list);
673  Item *item;
674  uchar buff[MAX_FIELD_WIDTH];
675  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
676  Protocol_text prot(thd);
677  String *local_packet= prot.storage_packet();
678  const CHARSET_INFO *thd_charset= thd->variables.character_set_results;
679  DBUG_ENTER("send_result_set_metadata");
680 
681  if (flags & SEND_NUM_ROWS)
682  { // Packet with number of elements
683  uchar *pos= net_store_length(buff, list->elements);
684  if (my_net_write(&thd->net, buff, (size_t) (pos-buff)))
685  DBUG_RETURN(1);
686  }
687 
688 #ifndef DBUG_OFF
689  field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
690  list->elements);
691  uint count= 0;
692 #endif
693 
694  while ((item=it++))
695  {
696  char *pos;
697  const CHARSET_INFO *cs= system_charset_info;
698  Send_field field;
699  item->make_field(&field);
700 
701  /* Keep things compatible for old clients */
702  if (field.type == MYSQL_TYPE_VARCHAR)
703  field.type= MYSQL_TYPE_VAR_STRING;
704 
705  prot.prepare_for_resend();
706 
707  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
708  {
709  if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
710  prot.store(field.db_name, (uint) strlen(field.db_name),
711  cs, thd_charset) ||
712  prot.store(field.table_name, (uint) strlen(field.table_name),
713  cs, thd_charset) ||
714  prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
715  cs, thd_charset) ||
716  prot.store(field.col_name, (uint) strlen(field.col_name),
717  cs, thd_charset) ||
718  prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
719  cs, thd_charset) ||
720  local_packet->realloc(local_packet->length()+12))
721  goto err;
722  /* Store fixed length fields */
723  pos= (char*) local_packet->ptr()+local_packet->length();
724  *pos++= 12; // Length of packed fields
725  /* inject a NULL to test the client */
726  DBUG_EXECUTE_IF("poison_rs_fields", pos[-1]= 0xfb;);
727  if (item->charset_for_protocol() == &my_charset_bin || thd_charset == NULL)
728  {
729  /* No conversion */
730  int2store(pos, item->charset_for_protocol()->number);
731  int4store(pos+2, field.length);
732  }
733  else
734  {
735  /* With conversion */
736  uint32 field_length, max_length;
737  int2store(pos, thd_charset->number);
738  /*
739  For TEXT/BLOB columns, field_length describes the maximum data
740  length in bytes. There is no limit to the number of characters
741  that a TEXT column can store, as long as the data fits into
742  the designated space.
743  For the rest of textual columns, field_length is evaluated as
744  char_count * mbmaxlen, where character count is taken from the
745  definition of the column. In other words, the maximum number
746  of characters here is limited by the column definition.
747 
748  When one has a LONG TEXT column with a single-byte
749  character set, and the connection character set is multi-byte, the
750  client may get fields longer than UINT_MAX32, due to
751  <character set column> -> <character set connection> conversion.
752  In that case column max length does not fit into the 4 bytes
753  reserved for it in the protocol.
754  */
755  max_length= (field.type >= MYSQL_TYPE_TINY_BLOB &&
756  field.type <= MYSQL_TYPE_BLOB) ?
757  field.length / item->collation.collation->mbminlen :
758  field.length / item->collation.collation->mbmaxlen;
759  field_length= char_to_byte_length_safe(max_length,
760  thd_charset->mbmaxlen);
761  int4store(pos + 2, field_length);
762  }
763  pos[6]= field.type;
764  int2store(pos+7,field.flags);
765  pos[9]= (char) field.decimals;
766  pos[10]= 0; // For the future
767  pos[11]= 0; // For the future
768  pos+= 12;
769  }
770  else
771  {
772  if (prot.store(field.table_name, (uint) strlen(field.table_name),
773  cs, thd_charset) ||
774  prot.store(field.col_name, (uint) strlen(field.col_name),
775  cs, thd_charset) ||
776  local_packet->realloc(local_packet->length()+10))
777  goto err;
778  pos= (char*) local_packet->ptr()+local_packet->length();
779  pos[0]=3;
780  int3store(pos+1,field.length);
781  pos[4]=1;
782  pos[5]=field.type;
783  pos[6]=3;
784  int2store(pos+7,field.flags);
785  pos[9]= (char) field.decimals;
786  pos+= 10;
787  }
788  local_packet->length((uint) (pos - local_packet->ptr()));
789  if (flags & SEND_DEFAULTS)
790  item->send(&prot, &tmp); // Send default value
791  if (prot.write())
792  DBUG_RETURN(1);
793 #ifndef DBUG_OFF
794  field_types[count++]= field.type;
795 #endif
796  }
797 
798  if (flags & SEND_EOF)
799  {
800  /*
801  Mark the end of meta-data result set, and store thd->server_status,
802  to show that there is no cursor.
803  Send no warning information, as it will be sent at statement end.
804  */
805  if (write_eof_packet(thd, &thd->net, thd->server_status,
806  thd->get_stmt_da()->current_statement_warn_count()))
807  DBUG_RETURN(1);
808  }
809  DBUG_RETURN(prepare_for_send(list->elements));
810 
811 err:
812  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
813  MYF(0)); /* purecov: inspected */
814  DBUG_RETURN(1); /* purecov: inspected */
815 }
816 
817 
818 bool Protocol::write()
819 {
820  DBUG_ENTER("Protocol::write");
821  DBUG_RETURN(my_net_write(&thd->net, (uchar*) packet->ptr(),
822  packet->length()));
823 }
824 #endif /* EMBEDDED_LIBRARY */
825 
826 
838 {
839  char buffer[MAX_FIELD_WIDTH];
840  String str_buffer(buffer, sizeof (buffer), &my_charset_bin);
841  List_iterator_fast<Item> it(*row_items);
842 
843  DBUG_ENTER("Protocol::send_result_set_row");
844 
845  for (Item *item= it++; item; item= it++)
846  {
847  if (item->send(this, &str_buffer))
848  {
849  // If we're out of memory, reclaim some, to help us recover.
850  this->free();
851  DBUG_RETURN(TRUE);
852  }
853  /* Item::send() may generate an error. If so, abort the loop. */
854  if (thd->is_error())
855  DBUG_RETURN(TRUE);
856 
857  /*
858  Reset str_buffer to its original state, as it may have been altered in
859  Item::send().
860  */
861  str_buffer.set(buffer, sizeof(buffer), &my_charset_bin);
862  }
863 
864  DBUG_RETURN(FALSE);
865 }
866 
867 
882 bool Protocol::store(const char *from, const CHARSET_INFO *cs)
883 {
884  if (!from)
885  return store_null();
886  uint length= strlen(from);
887  return store(from, length, cs);
888 }
889 
890 
896 {
897  char buf[256];
898  String tmp(buf, sizeof(buf), &my_charset_bin);
899  uint32 len;
900  I_List_iterator<i_string> it(*str_list);
901  i_string* s;
902 
903  tmp.length(0);
904  while ((s=it++))
905  {
906  tmp.append(s->ptr);
907  tmp.append(',');
908  }
909  if ((len= tmp.length()))
910  len--; // Remove last ','
911  return store((char*) tmp.ptr(), len, tmp.charset());
912 }
913 
914 /****************************************************************************
915  Functions to handle the simple (default) protocol where everything is
916  This protocol is the one that is used by default between the MySQL server
917  and client when you are not using prepared statements.
918 
919  All data are sent as 'packed-string-length' followed by 'string-data'
920 ****************************************************************************/
921 
922 #ifndef EMBEDDED_LIBRARY
923 void Protocol_text::prepare_for_resend()
924 {
925  packet->length(0);
926 #ifndef DBUG_OFF
927  field_pos= 0;
928 #endif
929 }
930 
931 bool Protocol_text::store_null()
932 {
933 #ifndef DBUG_OFF
934  field_pos++;
935 #endif
936  char buff[1];
937  buff[0]= (char)251;
938  return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
939 }
940 #endif
941 
942 
948 bool Protocol::store_string_aux(const char *from, size_t length,
949  const CHARSET_INFO *fromcs,
950  const CHARSET_INFO *tocs)
951 {
952  /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
953  if (tocs && !my_charset_same(fromcs, tocs) &&
954  fromcs != &my_charset_bin &&
955  tocs != &my_charset_bin)
956  {
957  /* Store with conversion */
958  return net_store_data((uchar*) from, length, fromcs, tocs);
959  }
960  /* Store without conversion */
961  return net_store_data((uchar*) from, length);
962 }
963 
964 
965 bool Protocol_text::store(const char *from, size_t length,
966  const CHARSET_INFO *fromcs,
967  const CHARSET_INFO *tocs)
968 {
969 #ifndef DBUG_OFF
970  DBUG_ASSERT(field_types == 0 ||
971  field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
972  field_types[field_pos] == MYSQL_TYPE_BIT ||
973  field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
974  (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
975  field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
976  field_pos++;
977 #endif
978  return store_string_aux(from, length, fromcs, tocs);
979 }
980 
981 
982 bool Protocol_text::store(const char *from, size_t length,
983  const CHARSET_INFO *fromcs)
984 {
985  const CHARSET_INFO *tocs= this->thd->variables.character_set_results;
986 #ifndef DBUG_OFF
987  DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %.*s", field_pos,
988  field_count, (int) length, (length == 0 ? "" : from)));
989  DBUG_ASSERT(field_pos < field_count);
990  DBUG_ASSERT(field_types == 0 ||
991  field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
992  field_types[field_pos] == MYSQL_TYPE_BIT ||
993  field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
994  field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
995  (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
996  field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
997  field_pos++;
998 #endif
999  return store_string_aux(from, length, fromcs, tocs);
1000 }
1001 
1002 
1003 bool Protocol_text::store_tiny(longlong from)
1004 {
1005 #ifndef DBUG_OFF
1006  DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
1007  field_pos++;
1008 #endif
1009  char buff[20];
1010  return net_store_data((uchar*) buff,
1011  (size_t) (int10_to_str((int) from, buff, -10) - buff));
1012 }
1013 
1014 
1015 bool Protocol_text::store_short(longlong from)
1016 {
1017 #ifndef DBUG_OFF
1018  DBUG_ASSERT(field_types == 0 ||
1019  field_types[field_pos] == MYSQL_TYPE_YEAR ||
1020  field_types[field_pos] == MYSQL_TYPE_SHORT);
1021  field_pos++;
1022 #endif
1023  char buff[20];
1024  return net_store_data((uchar*) buff,
1025  (size_t) (int10_to_str((int) from, buff, -10) -
1026  buff));
1027 }
1028 
1029 
1030 bool Protocol_text::store_long(longlong from)
1031 {
1032 #ifndef DBUG_OFF
1033  DBUG_ASSERT(field_types == 0 ||
1034  field_types[field_pos] == MYSQL_TYPE_INT24 ||
1035  field_types[field_pos] == MYSQL_TYPE_LONG);
1036  field_pos++;
1037 #endif
1038  char buff[20];
1039  return net_store_data((uchar*) buff,
1040  (size_t) (int10_to_str((long int)from, buff,
1041  (from <0)?-10:10)-buff));
1042 }
1043 
1044 
1045 bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
1046 {
1047 #ifndef DBUG_OFF
1048  DBUG_ASSERT(field_types == 0 ||
1049  field_types[field_pos] == MYSQL_TYPE_LONGLONG);
1050  field_pos++;
1051 #endif
1052  char buff[22];
1053  return net_store_data((uchar*) buff,
1054  (size_t) (longlong10_to_str(from,buff,
1055  unsigned_flag ? 10 : -10)-
1056  buff));
1057 }
1058 
1059 
1060 bool Protocol_text::store_decimal(const my_decimal *d)
1061 {
1062 #ifndef DBUG_OFF
1063  DBUG_ASSERT(field_types == 0 ||
1064  field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
1065  field_pos++;
1066 #endif
1067  char buff[DECIMAL_MAX_STR_LENGTH + 1];
1068  String str(buff, sizeof(buff), &my_charset_bin);
1069  (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
1070  return net_store_data((uchar*) str.ptr(), str.length());
1071 }
1072 
1073 
1074 bool Protocol_text::store(float from, uint32 decimals, String *buffer)
1075 {
1076 #ifndef DBUG_OFF
1077  DBUG_ASSERT(field_types == 0 ||
1078  field_types[field_pos] == MYSQL_TYPE_FLOAT);
1079  field_pos++;
1080 #endif
1081  buffer->set_real((double) from, decimals, thd->charset());
1082  return net_store_data((uchar*) buffer->ptr(), buffer->length());
1083 }
1084 
1085 
1086 bool Protocol_text::store(double from, uint32 decimals, String *buffer)
1087 {
1088 #ifndef DBUG_OFF
1089  DBUG_ASSERT(field_types == 0 ||
1090  field_types[field_pos] == MYSQL_TYPE_DOUBLE);
1091  field_pos++;
1092 #endif
1093  buffer->set_real(from, decimals, thd->charset());
1094  return net_store_data((uchar*) buffer->ptr(), buffer->length());
1095 }
1096 
1097 
1098 bool Protocol_text::store(Field *field)
1099 {
1100  if (field->is_null())
1101  return store_null();
1102 #ifndef DBUG_OFF
1103  field_pos++;
1104 #endif
1105  char buff[MAX_FIELD_WIDTH];
1106  String str(buff,sizeof(buff), &my_charset_bin);
1107  const CHARSET_INFO *tocs= this->thd->variables.character_set_results;
1108 #ifndef DBUG_OFF
1109  TABLE *table= field->table;
1110  my_bitmap_map *old_map= 0;
1111  if (table->file)
1112  old_map= dbug_tmp_use_all_columns(table, table->read_set);
1113 #endif
1114 
1115  field->val_str(&str);
1116 #ifndef DBUG_OFF
1117  if (old_map)
1118  dbug_tmp_restore_column_map(table->read_set, old_map);
1119 #endif
1120 
1121  return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
1122 }
1123 
1124 
1131 bool Protocol_text::store(MYSQL_TIME *tm, uint decimals)
1132 {
1133 #ifndef DBUG_OFF
1134  DBUG_ASSERT(field_types == 0 ||
1135  is_temporal_type_with_date_and_time(field_types[field_pos]));
1136  field_pos++;
1137 #endif
1138  char buff[MAX_DATE_STRING_REP_LENGTH];
1139  uint length= my_datetime_to_str(tm, buff, decimals);
1140  return net_store_data((uchar*) buff, length);
1141 }
1142 
1143 
1144 bool Protocol_text::store_date(MYSQL_TIME *tm)
1145 {
1146 #ifndef DBUG_OFF
1147  DBUG_ASSERT(field_types == 0 ||
1148  field_types[field_pos] == MYSQL_TYPE_DATE);
1149  field_pos++;
1150 #endif
1151  char buff[MAX_DATE_STRING_REP_LENGTH];
1152  size_t length= my_date_to_str(tm, buff);
1153  return net_store_data((uchar*) buff, length);
1154 }
1155 
1156 
1157 bool Protocol_text::store_time(MYSQL_TIME *tm, uint decimals)
1158 {
1159 #ifndef DBUG_OFF
1160  DBUG_ASSERT(field_types == 0 ||
1161  field_types[field_pos] == MYSQL_TYPE_TIME);
1162  field_pos++;
1163 #endif
1164  char buff[MAX_DATE_STRING_REP_LENGTH];
1165  uint length= my_time_to_str(tm, buff, decimals);
1166  return net_store_data((uchar*) buff, length);
1167 }
1168 
1169 
1181 {
1182  DBUG_ASSERT(sp_params->elements ==
1183  thd->lex->prepared_stmt_params.elements);
1184 
1185  List_iterator_fast<Item_param> item_param_it(*sp_params);
1186  List_iterator_fast<LEX_STRING> user_var_name_it(thd->lex->prepared_stmt_params);
1187 
1188  while (true)
1189  {
1190  Item_param *item_param= item_param_it++;
1191  LEX_STRING *user_var_name= user_var_name_it++;
1192 
1193  if (!item_param || !user_var_name)
1194  break;
1195 
1196  if (!item_param->get_out_param_info())
1197  continue; // It's an IN-parameter.
1198 
1200  new Item_func_set_user_var(*user_var_name, item_param, false);
1201  /*
1202  Item_func_set_user_var is not fixed after construction, call
1203  fix_fields().
1204  */
1205  if (suv->fix_fields(thd, NULL))
1206  return TRUE;
1207 
1208  if (suv->check(FALSE))
1209  return TRUE;
1210 
1211  if (suv->update())
1212  return TRUE;
1213  }
1214 
1215  return FALSE;
1216 }
1217 
1218 /****************************************************************************
1219  Functions to handle the binary protocol used with prepared statements
1220 
1221  Data format:
1222 
1223  [ok:1] reserved ok packet
1224  [null_field:(field_count+7+2)/8] reserved to send null data. The size is
1225  calculated using:
1226  bit_fields= (field_count+7+2)/8;
1227  2 bits are reserved for identifying type
1228  of package.
1229  [[length]data] data field (the length applies only for
1230  string/binary/time/timestamp fields and
1231  rest of them are not sent as they have
1232  the default length that client understands
1233  based on the field type
1234  [..]..[[length]data] data
1235 ****************************************************************************/
1236 
1237 bool Protocol_binary::prepare_for_send(uint num_columns)
1238 {
1239  Protocol::prepare_for_send(num_columns);
1240  bit_fields= (field_count+9)/8;
1241  return packet->alloc(bit_fields+1);
1242 
1243  /* prepare_for_resend will be called after this one */
1244 }
1245 
1246 
1247 void Protocol_binary::prepare_for_resend()
1248 {
1249  packet->length(bit_fields+1);
1250  memset(const_cast<char*>(packet->ptr()), 0, 1+bit_fields);
1251  field_pos=0;
1252 }
1253 
1254 
1255 bool Protocol_binary::store(const char *from, size_t length,
1256  const CHARSET_INFO *fromcs)
1257 {
1258  const CHARSET_INFO *tocs= thd->variables.character_set_results;
1259  field_pos++;
1260  return store_string_aux(from, length, fromcs, tocs);
1261 }
1262 
1263 bool Protocol_binary::store(const char *from, size_t length,
1264  const CHARSET_INFO *fromcs,
1265  const CHARSET_INFO *tocs)
1266 {
1267  field_pos++;
1268  return store_string_aux(from, length, fromcs, tocs);
1269 }
1270 
1271 bool Protocol_binary::store_null()
1272 {
1273  uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));
1274  /* Room for this as it's allocated in prepare_for_send */
1275  char *to= (char*) packet->ptr()+offset;
1276  *to= (char) ((uchar) *to | (uchar) bit);
1277  field_pos++;
1278  return 0;
1279 }
1280 
1281 
1282 bool Protocol_binary::store_tiny(longlong from)
1283 {
1284  char buff[1];
1285  field_pos++;
1286  buff[0]= (uchar) from;
1287  return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
1288 }
1289 
1290 
1291 bool Protocol_binary::store_short(longlong from)
1292 {
1293  field_pos++;
1294  char *to= packet->prep_append(2, PACKET_BUFFER_EXTRA_ALLOC);
1295  if (!to)
1296  return 1;
1297  int2store(to, (int) from);
1298  return 0;
1299 }
1300 
1301 
1302 bool Protocol_binary::store_long(longlong from)
1303 {
1304  field_pos++;
1305  char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
1306  if (!to)
1307  return 1;
1308  int4store(to, from);
1309  return 0;
1310 }
1311 
1312 
1313 bool Protocol_binary::store_longlong(longlong from, bool unsigned_flag)
1314 {
1315  field_pos++;
1316  char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
1317  if (!to)
1318  return 1;
1319  int8store(to, from);
1320  return 0;
1321 }
1322 
1323 bool Protocol_binary::store_decimal(const my_decimal *d)
1324 {
1325 #ifndef DBUG_OFF
1326  DBUG_ASSERT(field_types == 0 ||
1327  field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
1328  field_pos++;
1329 #endif
1330  char buff[DECIMAL_MAX_STR_LENGTH + 1];
1331  String str(buff, sizeof(buff), &my_charset_bin);
1332  (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
1333  return store(str.ptr(), str.length(), str.charset());
1334 }
1335 
1336 bool Protocol_binary::store(float from, uint32 decimals, String *buffer)
1337 {
1338  field_pos++;
1339  char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
1340  if (!to)
1341  return 1;
1342  float4store(to, from);
1343  return 0;
1344 }
1345 
1346 
1347 bool Protocol_binary::store(double from, uint32 decimals, String *buffer)
1348 {
1349  field_pos++;
1350  char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
1351  if (!to)
1352  return 1;
1353  float8store(to, from);
1354  return 0;
1355 }
1356 
1357 
1358 bool Protocol_binary::store(Field *field)
1359 {
1360  /*
1361  We should not increment field_pos here as send_binary() will call another
1362  protocol function to do this for us
1363  */
1364  if (field->is_null())
1365  return store_null();
1366  return field->send_binary(this);
1367 }
1368 
1369 
1370 bool Protocol_binary::store(MYSQL_TIME *tm, uint precision)
1371 {
1372  char buff[12],*pos;
1373  uint length;
1374  field_pos++;
1375  pos= buff+1;
1376 
1377  int2store(pos, tm->year);
1378  pos[2]= (uchar) tm->month;
1379  pos[3]= (uchar) tm->day;
1380  pos[4]= (uchar) tm->hour;
1381  pos[5]= (uchar) tm->minute;
1382  pos[6]= (uchar) tm->second;
1383  int4store(pos+7, tm->second_part);
1384  if (tm->second_part)
1385  length=11;
1386  else if (tm->hour || tm->minute || tm->second)
1387  length=7;
1388  else if (tm->year || tm->month || tm->day)
1389  length=4;
1390  else
1391  length=0;
1392  buff[0]=(char) length; // Length is stored first
1393  return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
1394 }
1395 
1396 bool Protocol_binary::store_date(MYSQL_TIME *tm)
1397 {
1398  tm->hour= tm->minute= tm->second=0;
1399  tm->second_part= 0;
1400  return Protocol_binary::store(tm, 0);
1401 }
1402 
1403 
1404 bool Protocol_binary::store_time(MYSQL_TIME *tm, uint precision)
1405 {
1406  char buff[13], *pos;
1407  uint length;
1408  field_pos++;
1409  pos= buff+1;
1410  pos[0]= tm->neg ? 1 : 0;
1411  if (tm->hour >= 24)
1412  {
1413  /* Fix if we come from Item::send */
1414  uint days= tm->hour/24;
1415  tm->hour-= days*24;
1416  tm->day+= days;
1417  }
1418  int4store(pos+1, tm->day);
1419  pos[5]= (uchar) tm->hour;
1420  pos[6]= (uchar) tm->minute;
1421  pos[7]= (uchar) tm->second;
1422  int4store(pos+8, tm->second_part);
1423  if (tm->second_part)
1424  length=12;
1425  else if (tm->hour || tm->minute || tm->second || tm->day)
1426  length=8;
1427  else
1428  length=0;
1429  buff[0]=(char) length; // Length is stored first
1430  return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
1431 }
1432 
1444 {
1445  if (!(thd->client_capabilities & CLIENT_PS_MULTI_RESULTS))
1446  {
1447  /* The client does not support OUT-parameters. */
1448  return FALSE;
1449  }
1450 
1451  List<Item> out_param_lst;
1452 
1453  {
1454  List_iterator_fast<Item_param> item_param_it(*sp_params);
1455 
1456  while (true)
1457  {
1458  Item_param *item_param= item_param_it++;
1459 
1460  if (!item_param)
1461  break;
1462 
1463  if (!item_param->get_out_param_info())
1464  continue; // It's an IN-parameter.
1465 
1466  if (out_param_lst.push_back(item_param))
1467  return TRUE;
1468  }
1469  }
1470 
1471  if (!out_param_lst.elements)
1472  return FALSE;
1473 
1474  /*
1475  We have to set SERVER_PS_OUT_PARAMS in THD::server_status, because it
1476  is used in send_result_set_metadata().
1477  */
1478 
1479  thd->server_status|= SERVER_PS_OUT_PARAMS | SERVER_MORE_RESULTS_EXISTS;
1480 
1481  /* Send meta-data. */
1482  if (send_result_set_metadata(&out_param_lst, SEND_NUM_ROWS | SEND_EOF))
1483  return TRUE;
1484 
1485  /* Send data. */
1486 
1487  prepare_for_resend();
1488 
1489  if (send_result_set_row(&out_param_lst))
1490  return TRUE;
1491 
1492  if (write())
1493  return TRUE;
1494 
1495  /* Restore THD::server_status. */
1496  thd->server_status&= ~SERVER_PS_OUT_PARAMS;
1497 
1498  /*
1499  Reset SERVER_MORE_RESULTS_EXISTS bit, because this is the last packet
1500  for sure.
1501  */
1502  thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
1503 
1504  /* Send EOF-packet. */
1505  net_send_eof(thd, thd->server_status, 0);
1506 
1507  return FALSE;
1508 }