1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
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, version 2.0,
5    as published by the Free Software Foundation.
6 
7    This program is also distributed with certain software (including
8    but not limited to OpenSSL) that is licensed under separate terms,
9    as designated in a particular file or component or in included license
10    documentation.  The authors of MySQL hereby grant you an additional
11    permission to link the program and your derivative works with the
12    separately licensed software that they have included with MySQL.
13 
14    This program is distributed in the hope that it will be useful,
15    but WITHOUT ANY WARRANTY; without even the implied warranty of
16    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17    GNU General Public License, version 2.0, for more details.
18 
19    You should have received a copy of the GNU General Public License
20    along with this program; if not, write to the Free Software
21    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA */
22 
23 /**
24 @file
25 
26 Low level functions for storing data to be send to the MySQL client.
27 The actual communication is handled by the net_xxx functions in net_serv.cc
28 */
29 
30 #include "protocol_classic.h"
31 #include "sql_class.h"                          // THD
32 #include <stdarg.h>
33 
34 using std::min;
35 using std::max;
36 
37 static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
38 bool net_send_error_packet(THD *, uint, const char *, const char *);
39 bool net_send_error_packet(NET *, uint, const char *, const char *, bool,
40                            ulong, const CHARSET_INFO*);
41 /* Declared non-static only because of the embedded library. */
42 bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, bool);
43 /* Declared non-static only because of the embedded library. */
44 bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count);
45 #ifndef EMBEDDED_LIBRARY
46 static bool write_eof_packet(THD *, NET *, uint, uint);
47 #endif
48 
49 #ifndef EMBEDDED_LIBRARY
net_store_data(const uchar * from,size_t length)50 bool Protocol_classic::net_store_data(const uchar *from, size_t length)
51 {
52   size_t packet_length=packet->length();
53   /*
54      The +9 comes from that strings of length longer than 16M require
55      9 bytes to be stored (see net_store_length).
56   */
57   if (packet_length+9+length > packet->alloced_length() &&
58       packet->mem_realloc(packet_length+9+length))
59     return 1;
60   uchar *to= net_store_length((uchar *) packet->ptr()+packet_length, length);
61   memcpy(to,from,length);
62   packet->length((uint) (to+length-(uchar *) packet->ptr()));
63   return 0;
64 }
65 #endif
66 
67 
68 /**
69   net_store_data() - extended version with character set conversion.
70 
71   It is optimized for short strings whose length after
72   conversion is garanteed to be less than 251, which accupies
73   exactly one byte to store length. It allows not to use
74   the "convert" member as a temporary buffer, conversion
75   is done directly to the "packet" member.
76   The limit 251 is good enough to optimize send_result_set_metadata()
77   because column, table, database names fit into this limit.
78 */
79 
80 #ifndef EMBEDDED_LIBRARY
net_store_data(const uchar * from,size_t length,const CHARSET_INFO * from_cs,const CHARSET_INFO * to_cs)81 bool Protocol_classic::net_store_data(const uchar *from, size_t length,
82                                       const CHARSET_INFO *from_cs,
83                                       const CHARSET_INFO *to_cs)
84 {
85   uint dummy_errors;
86   /* Calculate maxumum possible result length */
87   size_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
88   if (conv_length > 250)
89   {
90     /*
91       For strings with conv_length greater than 250 bytes
92       we don't know how many bytes we will need to store length: one or two,
93       because we don't know result length until conversion is done.
94       For example, when converting from utf8 (mbmaxlen=3) to latin1,
95       conv_length=300 means that the result length can vary between 100 to 300.
96       length=100 needs one byte, length=300 needs to bytes.
97 
98       Thus conversion directly to "packet" is not worthy.
99       Let's use "convert" as a temporary buffer.
100     */
101     return (convert->copy((const char *) from, length, from_cs,
102         to_cs, &dummy_errors) ||
103         net_store_data((const uchar *) convert->ptr(), convert->length()));
104   }
105 
106   size_t packet_length= packet->length();
107   size_t new_length= packet_length + conv_length + 1;
108 
109   if (new_length > packet->alloced_length() && packet->mem_realloc(new_length))
110     return 1;
111 
112   char *length_pos= (char *) packet->ptr() + packet_length;
113   char *to= length_pos + 1;
114 
115   to+= copy_and_convert(to, conv_length, to_cs,
116       (const char *) from, length, from_cs, &dummy_errors);
117 
118   net_store_length((uchar *) length_pos, to - length_pos - 1);
119   packet->length((uint) (to - packet->ptr()));
120   return 0;
121 }
122 #endif
123 
124 
125 /**
126   Send a error string to client.
127 
128   Design note:
129 
130   net_printf_error and net_send_error are low-level functions
131   that shall be used only when a new connection is being
132   established or at server startup.
133 
134   For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
135   critical that every error that can be intercepted is issued in one
136   place only, my_message_sql.
137 
138   @param thd Thread handler
139   @param sql_errno The error code to send
140   @param err A pointer to the error message
141 
142   @return
143     @retval FALSE The message was sent to the client
144     @retval TRUE An error occurred and the message wasn't sent properly
145 */
146 
net_send_error(THD * thd,uint sql_errno,const char * err)147 bool net_send_error(THD *thd, uint sql_errno, const char *err)
148 {
149   bool error;
150   DBUG_ENTER("net_send_error");
151 
152   assert(!thd->sp_runtime_ctx);
153   assert(sql_errno);
154   assert(err);
155 
156   DBUG_PRINT("enter",("sql_errno: %d  err: %s", sql_errno, err));
157 
158   /*
159     It's one case when we can push an error even though there
160     is an OK or EOF already.
161   */
162   thd->get_stmt_da()->set_overwrite_status(true);
163 
164   /* Abort multi-result sets */
165   thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
166 
167   error= net_send_error_packet(thd, sql_errno, err,
168     mysql_errno_to_sqlstate(sql_errno));
169 
170   thd->get_stmt_da()->set_overwrite_status(false);
171 
172   DBUG_RETURN(error);
173 }
174 
175 
176 /**
177   Send a error string to client using net struct.
178   This is used initial connection handling code.
179 
180   @param net        Low-level net struct
181   @param sql_errno  The error code to send
182   @param err        A pointer to the error message
183 
184   @return
185     @retval FALSE The message was sent to the client
186     @retval TRUE  An error occurred and the message wasn't sent properly
187 */
188 
189 #ifndef EMBEDDED_LIBRARY
net_send_error(NET * net,uint sql_errno,const char * err)190 bool net_send_error(NET *net, uint sql_errno, const char *err)
191 {
192   DBUG_ENTER("net_send_error");
193 
194   assert(sql_errno && err);
195 
196   DBUG_PRINT("enter",("sql_errno: %d  err: %s", sql_errno, err));
197 
198   bool error=
199     net_send_error_packet(net, sql_errno, err,
200                           mysql_errno_to_sqlstate(sql_errno), false, 0,
201                           global_system_variables.character_set_results);
202 
203   DBUG_RETURN(error);
204 }
205 
206 
207 /**
208   Return OK to the client.
209 
210   The OK packet has the following structure:
211 
212   Here 'n' denotes the length of state change information.
213 
214   Bytes                Name
215   -----                ----
216   1                    [00] or [FE] the OK header
217                        [FE] is used as header for result set rows
218   1-9 (lenenc-int)     affected rows
219   1-9 (lenenc-int)     last-insert-id
220 
221   if capabilities & CLIENT_PROTOCOL_41 {
222     2                  status_flags; Copy of thd->server_status; Can be used
223                        by client to check if we are inside a transaction.
224     2                  warnings (New in 4.1 protocol)
225   } elseif capabilities & CLIENT_TRANSACTIONS {
226     2                  status_flags
227   }
228 
229   if capabilities & CLIENT_ACCEPTS_SERVER_STATUS_CHANGE_INFO {
230     1-9(lenenc_str)    info (message); Stored as length of the message string +
231                        message.
232     if n > 0 {
233       1-9 (lenenc_int) total length of session state change
234                        information to follow (= n)
235       n                session state change information
236     }
237   }
238   else {
239     string[EOF]          info (message); Stored as packed length (1-9 bytes) +
240                          message. Is not stored if no message.
241   }
242 
243   @param thd                     Thread handler
244   @param server_status           The server status
245   @param statement_warn_count    Total number of warnings
246   @param affected_rows           Number of rows changed by statement
247   @param id                      Auto_increment id for first row (if used)
248   @param message                 Message to send to the client
249                                  (Used by mysql_status)
250   @param eof_indentifier         when true [FE] will be set in OK header
251                                  else [00] will be used
252 
253   @return
254     @retval FALSE The message was successfully sent
255     @retval TRUE An error occurred and the messages wasn't sent properly
256 */
257 
258 bool
net_send_ok(THD * thd,uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong id,const char * message,bool eof_identifier)259 net_send_ok(THD *thd,
260             uint server_status, uint statement_warn_count,
261             ulonglong affected_rows, ulonglong id, const char *message,
262             bool eof_identifier)
263 {
264   Protocol *protocol= thd->get_protocol();
265   NET *net= thd->get_protocol_classic()->get_net();
266   uchar buff[MYSQL_ERRMSG_SIZE + 10];
267   uchar *pos, *start;
268 
269   /*
270     To be used to manage the data storage in case session state change
271     information is present.
272   */
273   String store;
274   bool state_changed= false;
275 
276   bool error= FALSE;
277   DBUG_ENTER("net_send_ok");
278 
279   if (! net->vio)	// hack for re-parsing queries
280   {
281     DBUG_PRINT("info", ("vio present: NO"));
282     DBUG_RETURN(FALSE);
283   }
284 
285   start= buff;
286 
287   /*
288     Use 0xFE packet header if eof_identifier is true
289     unless we are talking to old client
290   */
291   if (eof_identifier &&
292       (protocol->has_client_capability(CLIENT_DEPRECATE_EOF)))
293     buff[0]= 254;
294   else
295     buff[0]= 0;
296 
297   /* affected rows */
298   pos= net_store_length(buff + 1, affected_rows);
299 
300   /* last insert id */
301   pos= net_store_length(pos, id);
302 
303   if (protocol->has_client_capability(CLIENT_SESSION_TRACK) &&
304       thd->session_tracker.enabled_any() &&
305       thd->session_tracker.changed_any())
306   {
307     server_status |= SERVER_SESSION_STATE_CHANGED;
308     state_changed= true;
309   }
310 
311   if (protocol->has_client_capability(CLIENT_PROTOCOL_41))
312   {
313     DBUG_PRINT("info",
314         ("affected_rows: %lu  id: %lu  status: %u  warning_count: %u",
315             (ulong) affected_rows,
316             (ulong) id,
317             (uint) (server_status & 0xffff),
318             (uint) statement_warn_count));
319     /* server status */
320     int2store(pos, server_status);
321     pos+= 2;
322 
323     /* warning count: we can only return up to 65535 warnings in two bytes. */
324     uint tmp= min(statement_warn_count, 65535U);
325     int2store(pos, tmp);
326     pos+= 2;
327   }
328   else if (net->return_status)			// For 4.0 protocol
329   {
330     int2store(pos, server_status);
331     pos+=2;
332   }
333 
334   thd->get_stmt_da()->set_overwrite_status(true);
335 
336   if (protocol->has_client_capability(CLIENT_SESSION_TRACK))
337   {
338     /* the info field */
339     if (state_changed || (message && message[0]))
340       pos= net_store_data(pos, (uchar*) message, message ? strlen(message) : 0);
341     /* session state change information */
342     if (unlikely(state_changed))
343     {
344       store.set_charset(thd->variables.collation_database);
345 
346       /*
347         First append the fields collected so far. In case of malloc, memory
348         for message is also allocated here.
349       */
350       store.append((const char *)start, (pos - start), MYSQL_ERRMSG_SIZE);
351 
352       /* .. and then the state change information. */
353       thd->session_tracker.store(thd, store);
354 
355       start= (uchar *) store.ptr();
356       pos= start+store.length();
357     }
358   }
359   else if (message && message[0])
360   {
361     /* the info field, if there is a message to store */
362     pos= net_store_data(pos, (uchar*) message, strlen(message));
363   }
364 
365   /* OK packet length will be restricted to 16777215 bytes */
366   if (((size_t) (pos - start)) > MAX_PACKET_LENGTH)
367   {
368     net->error= 1;
369     net->last_errno= ER_NET_OK_PACKET_TOO_LARGE;
370     my_error(ER_NET_OK_PACKET_TOO_LARGE, MYF(0));
371     DBUG_PRINT("info", ("OK packet too large"));
372     DBUG_RETURN(1);
373   }
374   error= my_net_write(net, start, (size_t) (pos - start));
375   if (!error)
376     error= net_flush(net);
377 
378   thd->get_stmt_da()->set_overwrite_status(false);
379   DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
380 
381   DBUG_RETURN(error);
382 }
383 
384 static uchar eof_buff[1]= { (uchar) 254 };      /* Marker for end of fields */
385 
386 
387 /**
388   Send eof (= end of result set) to the client.
389 
390   The eof packet has the following structure:
391 
392   - 254           : Marker (1 byte)
393   - warning_count : Stored in 2 bytes; New in 4.1 protocol
394   - status_flag   : Stored in 2 bytes;
395   For flags like SERVER_MORE_RESULTS_EXISTS.
396 
397   Note that the warning count will not be sent if 'no_flush' is set as
398   we don't want to report the warning count until all data is sent to the
399   client.
400 
401   @param thd                    Thread handler
402   @param server_status          The server status
403   @param statement_warn_count   Total number of warnings
404 
405   @return
406     @retval FALSE The message was successfully sent
407     @retval TRUE An error occurred and the message wasn't sent properly
408 */
409 
410 bool
net_send_eof(THD * thd,uint server_status,uint statement_warn_count)411 net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
412 {
413   NET *net= thd->get_protocol_classic()->get_net();
414   bool error= FALSE;
415   DBUG_ENTER("net_send_eof");
416   /* Set to TRUE if no active vio, to work well in case of --init-file */
417   if (net->vio != 0)
418   {
419     thd->get_stmt_da()->set_overwrite_status(true);
420     error= write_eof_packet(thd, net, server_status, statement_warn_count);
421     if (!error)
422       error= net_flush(net);
423     thd->get_stmt_da()->set_overwrite_status(false);
424     DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
425   }
426   DBUG_RETURN(error);
427 }
428 
429 
430 /**
431   Format EOF packet according to the current protocol and
432   write it to the network output buffer.
433 
434   @param thd The thread handler
435   @param net The network handler
436   @param server_status The server status
437   @param statement_warn_count The number of warnings
438 
439 
440   @return
441     @retval FALSE The message was sent successfully
442     @retval TRUE An error occurred and the messages wasn't sent properly
443 */
444 
write_eof_packet(THD * thd,NET * net,uint server_status,uint statement_warn_count)445 static bool write_eof_packet(THD *thd, NET *net,
446                              uint server_status,
447                              uint statement_warn_count)
448 {
449   bool error;
450   Protocol *protocol= thd->get_protocol();
451   if (protocol->has_client_capability(CLIENT_PROTOCOL_41))
452   {
453     uchar buff[5];
454     /*
455       Don't send warn count during SP execution, as the warn_list
456       is cleared between substatements, and mysqltest gets confused
457     */
458     uint tmp= min(statement_warn_count, 65535U);
459     buff[0]= 254;
460     int2store(buff+1, tmp);
461     /*
462       The following test should never be true, but it's better to do it
463       because if 'is_fatal_error' is set the server is not going to execute
464       other queries (see the if test in dispatch_command / COM_QUERY)
465     */
466     if (thd->is_fatal_error)
467       server_status&= ~SERVER_MORE_RESULTS_EXISTS;
468     int2store(buff + 3, server_status);
469     error= my_net_write(net, buff, 5);
470   }
471   else
472     error= my_net_write(net, eof_buff, 1);
473 
474   return error;
475 }
476 
477 
478 /**
479   @param thd          Thread handler
480   @param sql_errno    The error code to send
481   @param err          A pointer to the error message
482   @param sqlstate     SQL state
483 
484   @return
485    @retval FALSE The message was successfully sent
486    @retval TRUE  An error occurred and the messages wasn't sent properly
487 */
488 
net_send_error_packet(THD * thd,uint sql_errno,const char * err,const char * sqlstate)489 bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
490                            const char* sqlstate)
491 {
492   return net_send_error_packet(thd->get_protocol_classic()->get_net(),
493                                sql_errno, err, sqlstate, thd->bootstrap,
494                                thd->get_protocol()->get_client_capabilities(),
495                                thd->variables.character_set_results);
496 }
497 
498 
499 /**
500   @param net                    Low-level NET struct
501   @param sql_errno              The error code to send
502   @param err                    A pointer to the error message
503   @param sqlstate               SQL state
504   @param bootstrap              Server is started in bootstrap mode
505   @param client_capabilities    Client capabilities flag
506   @param character_set_results  Char set info
507 
508   @return
509    @retval FALSE The message was successfully sent
510    @retval TRUE  An error occurred and the messages wasn't sent properly
511 */
512 
net_send_error_packet(NET * net,uint sql_errno,const char * err,const char * sqlstate,bool bootstrap,ulong client_capabilities,const CHARSET_INFO * character_set_results)513 bool net_send_error_packet(NET* net, uint sql_errno, const char *err,
514                            const char* sqlstate, bool bootstrap,
515                            ulong client_capabilities,
516                            const CHARSET_INFO* character_set_results)
517 {
518   uint length;
519   /*
520     buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512
521   */
522   uint error;
523   char converted_err[MYSQL_ERRMSG_SIZE];
524   char buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos;
525 
526   DBUG_ENTER("net_send_error_packet");
527 
528   if (net->vio == 0)
529   {
530     if (bootstrap)
531     {
532       /* In bootstrap it's ok to print on stderr */
533       my_message_local(ERROR_LEVEL, "%d  %s", sql_errno, err);
534     }
535     DBUG_RETURN(FALSE);
536   }
537 
538   int2store(buff,sql_errno);
539   pos= buff+2;
540   if (client_capabilities & CLIENT_PROTOCOL_41)
541   {
542     /* The first # is to make the protocol backward compatible */
543     buff[2]= '#';
544     pos= my_stpcpy(buff+3, sqlstate);
545   }
546 
547   convert_error_message(converted_err, sizeof(converted_err),
548                         character_set_results, err,
549                         strlen(err), system_charset_info, &error);
550   /* Converted error message is always null-terminated. */
551   length= (uint) (strmake(pos, converted_err, MYSQL_ERRMSG_SIZE - 1) - buff);
552 
553   DBUG_RETURN(net_write_command(net,(uchar) 255, (uchar *) "", 0,
554               (uchar *) buff, length));
555 }
556 #endif /* EMBEDDED_LIBRARY */
557 
558 
559 /**
560   Faster net_store_length when we know that length is less than 65536.
561   We keep a separate version for that range because it's widely used in
562   libmysql.
563 
564   uint is used as agrument type because of MySQL type conventions:
565     - uint for 0..65536
566     - ulong for 0..4294967296
567     - ulonglong for bigger numbers.
568 */
569 
net_store_length_fast(uchar * packet,size_t length)570 static uchar *net_store_length_fast(uchar *packet, size_t length)
571 {
572   if (length < 251)
573   {
574     *packet=(uchar) length;
575     return packet+1;
576   }
577   *packet++=252;
578   int2store(packet,(uint) length);
579   return packet+2;
580 }
581 
582 
583 /****************************************************************************
584   Functions used by the protocol functions (like net_send_ok) to store
585   strings and numbers in the header result packet.
586 ****************************************************************************/
587 
588 /* The following will only be used for short strings < 65K */
589 
net_store_data(uchar * to,const uchar * from,size_t length)590 uchar *net_store_data(uchar *to, const uchar *from, size_t length)
591 {
592   to=net_store_length_fast(to,length);
593   memcpy(to,from,length);
594   return to+length;
595 }
596 
597 
net_store_data(uchar * to,int32 from)598 uchar *net_store_data(uchar *to, int32 from)
599 {
600   char buff[20];
601   uint length= (uint)(int10_to_str(from, buff, 10) - buff);
602   to= net_store_length_fast(to, length);
603   memcpy(to, buff, length);
604   return to + length;
605 }
606 
607 
net_store_data(uchar * to,longlong from)608 uchar *net_store_data(uchar *to, longlong from)
609 {
610   char buff[22];
611   uint length= (uint)(longlong10_to_str(from, buff, 10) - buff);
612   to= net_store_length_fast(to, length);
613   memcpy(to, buff, length);
614   return to + length;
615 }
616 
617 
618 /*****************************************************************************
619   Protocol_classic functions
620 *****************************************************************************/
621 
init(THD * thd_arg)622 void Protocol_classic::init(THD *thd_arg)
623 {
624   m_thd= thd_arg;
625   packet= &m_thd->packet;
626   convert= &m_thd->convert_buffer;
627 #ifndef NDEBUG
628   field_types= 0;
629 #endif
630 }
631 
632 
633 /**
634   A default implementation of "OK" packet response to the client.
635 
636   Currently this implementation is re-used by both network-oriented
637   protocols -- the binary and text one. They do not differ
638   in their OK packet format, which allows for a significant simplification
639   on client side.
640 */
641 
642 bool
send_ok(uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong last_insert_id,const char * message)643 Protocol_classic::send_ok(uint server_status, uint statement_warn_count,
644                           ulonglong affected_rows, ulonglong last_insert_id,
645                           const char *message)
646 {
647   DBUG_ENTER("Protocol_classic::send_ok");
648   const bool retval=
649     net_send_ok(m_thd, server_status, statement_warn_count,
650                 affected_rows, last_insert_id, message, false);
651   DBUG_RETURN(retval);
652 }
653 
654 
655 /**
656   A default implementation of "EOF" packet response to the client.
657 
658   Binary and text protocol do not differ in their EOF packet format.
659 */
660 
send_eof(uint server_status,uint statement_warn_count)661 bool Protocol_classic::send_eof(uint server_status, uint statement_warn_count)
662 {
663   DBUG_ENTER("Protocol_classic::send_eof");
664   bool retval;
665   /*
666     Normally end of statement reply is signaled by OK packet, but in case
667     of binlog dump request an EOF packet is sent instead. Also, old clients
668     expect EOF packet instead of OK
669   */
670 #ifndef EMBEDDED_LIBRARY
671   if (has_client_capability(CLIENT_DEPRECATE_EOF) &&
672       (m_thd->get_command() != COM_BINLOG_DUMP &&
673        m_thd->get_command() != COM_BINLOG_DUMP_GTID))
674     retval= net_send_ok(m_thd, server_status, statement_warn_count, 0, 0, NULL,
675                         true);
676   else
677 #endif
678     retval= net_send_eof(m_thd, server_status, statement_warn_count);
679   DBUG_RETURN(retval);
680 }
681 
682 
683 /**
684   A default implementation of "ERROR" packet response to the client.
685 
686   Binary and text protocol do not differ in ERROR packet format.
687 */
688 
send_error(uint sql_errno,const char * err_msg,const char * sql_state)689 bool Protocol_classic::send_error(uint sql_errno, const char *err_msg,
690                                   const char *sql_state)
691 {
692   DBUG_ENTER("Protocol_classic::send_error");
693   const bool retval= net_send_error_packet(m_thd, sql_errno, err_msg, sql_state);
694   DBUG_RETURN(retval);
695 }
696 
697 
set_read_timeout(ulong read_timeout)698 void Protocol_classic::set_read_timeout(ulong read_timeout)
699 {
700   my_net_set_read_timeout(&m_thd->net, read_timeout);
701 }
702 
703 
set_write_timeout(ulong write_timeout)704 void Protocol_classic::set_write_timeout(ulong write_timeout)
705 {
706   my_net_set_write_timeout(&m_thd->net, write_timeout);
707 }
708 
709 
710 // NET interaction functions
init_net(Vio * vio)711 bool Protocol_classic::init_net(Vio *vio)
712 {
713   return my_net_init(&m_thd->net, vio);
714 }
715 
claim_memory_ownership()716 void Protocol_classic::claim_memory_ownership()
717 {
718   net_claim_memory_ownership(&m_thd->net);
719 }
720 
end_net()721 void Protocol_classic::end_net()
722 {
723   assert(m_thd->net.buff);
724   net_end(&m_thd->net);
725   m_thd->net.vio= NULL;
726 }
727 
728 
flush_net()729 bool Protocol_classic::flush_net()
730 {
731   return net_flush(&m_thd->net);
732 }
733 
734 
write(const uchar * ptr,size_t len)735 bool Protocol_classic::write(const uchar *ptr, size_t len)
736 {
737   return my_net_write(&m_thd->net, ptr, len);
738 }
739 
740 
get_error()741 uchar Protocol_classic::get_error()
742 {
743   return m_thd->net.error;
744 }
745 
746 
get_last_errno()747 uint Protocol_classic::get_last_errno()
748 {
749   return m_thd->net.last_errno;
750 }
751 
752 
set_last_errno(uint err)753 void Protocol_classic::set_last_errno(uint err)
754 {
755   m_thd->net.last_errno= err;
756 }
757 
758 
get_last_error()759 char *Protocol_classic::get_last_error()
760 {
761   return m_thd->net.last_error;
762 }
763 
764 
wipe_net()765 void Protocol_classic::wipe_net()
766 {
767   memset(&m_thd->net, 0, sizeof(m_thd->net));
768 }
769 
770 
set_max_packet_size(ulong max_packet_size)771 void Protocol_classic::set_max_packet_size(ulong max_packet_size)
772 {
773   m_thd->net.max_packet_size= max_packet_size;
774 }
775 
776 
get_net()777 NET *Protocol_classic::get_net()
778 {
779   return &m_thd->net;
780 }
781 
782 
get_vio()783 Vio *Protocol_classic::get_vio()
784 {
785   return m_thd->net.vio;
786 }
787 
set_vio(Vio * vio)788 void Protocol_classic::set_vio(Vio *vio)
789 {
790   m_thd->net.vio= vio;
791 }
792 
793 
set_pkt_nr(uint pkt_nr)794 void Protocol_classic::set_pkt_nr(uint pkt_nr)
795 {
796   m_thd->net.pkt_nr= pkt_nr;
797 }
798 
799 
get_pkt_nr()800 uint Protocol_classic::get_pkt_nr()
801 {
802   return m_thd->net.pkt_nr;
803 }
804 
805 
get_packet()806 String *Protocol_classic::get_packet()
807 {
808   return &m_thd->packet;
809 }
810 
811 
read_packet()812 int Protocol_classic::read_packet()
813 {
814   int ret;
815   if ((packet_length= my_net_read(&m_thd->net)) &&
816       packet_length != packet_error)
817   {
818     assert(!m_thd->net.error);
819     bad_packet= false;
820     raw_packet= m_thd->net.read_pos;
821     return 0;
822   }
823   else if (m_thd->net.error == 3)
824     ret= 1;
825   else
826     ret= -1;
827   bad_packet= true;
828   return ret;
829 }
830 
831 
parse_packet(union COM_DATA * data,enum_server_command cmd)832 bool Protocol_classic::parse_packet(union COM_DATA *data,
833                                     enum_server_command cmd)
834 {
835   switch(cmd)
836   {
837   case COM_INIT_DB:
838   {
839     data->com_init_db.db_name= reinterpret_cast<const char*>(raw_packet);
840     data->com_init_db.length= packet_length;
841     break;
842   }
843   case COM_REFRESH:
844   {
845     if (packet_length < 1)
846       goto malformed;
847     data->com_refresh.options= raw_packet[0];
848     break;
849   }
850   case COM_SHUTDOWN:
851   {
852     data->com_shutdown.level= packet_length == 0 ?
853       SHUTDOWN_DEFAULT : (enum mysql_enum_shutdown_level) raw_packet[0];
854     break;
855   }
856   case COM_PROCESS_KILL:
857   {
858     if (packet_length < 4)
859       goto malformed;
860     data->com_kill.id= (ulong) uint4korr(raw_packet);
861     break;
862   }
863   case COM_SET_OPTION:
864   {
865     if (packet_length < 2)
866       goto malformed;
867     data->com_set_option.opt_command= uint2korr(raw_packet);
868     break;
869   }
870   case COM_STMT_EXECUTE:
871   {
872     if (packet_length < 9)
873       goto malformed;
874     data->com_stmt_execute.stmt_id= uint4korr(raw_packet);
875     data->com_stmt_execute.flags= (ulong) raw_packet[4];
876     /* stmt_id + 5 bytes of flags */
877     /*
878       FIXME: params have to be parsed into an array/structure
879       by protocol too
880     */
881     data->com_stmt_execute.params= raw_packet + 9;
882     data->com_stmt_execute.params_length= packet_length - 9;
883     break;
884   }
885   case COM_STMT_FETCH:
886   {
887     if (packet_length < 8)
888       goto malformed;
889     data->com_stmt_fetch.stmt_id= uint4korr(raw_packet);
890     data->com_stmt_fetch.num_rows= uint4korr(raw_packet + 4);
891     break;
892   }
893   case COM_STMT_SEND_LONG_DATA:
894   {
895 #ifndef EMBEDDED_LIBRARY
896     if (packet_length < MYSQL_LONG_DATA_HEADER)
897       goto malformed;
898 #endif
899     data->com_stmt_send_long_data.stmt_id= uint4korr(raw_packet);
900     data->com_stmt_send_long_data.param_number= uint2korr(raw_packet + 4);
901     data->com_stmt_send_long_data.longdata= raw_packet + 6;
902     data->com_stmt_send_long_data.length= packet_length - 6;
903     break;
904   }
905   case COM_STMT_PREPARE:
906   {
907     data->com_stmt_prepare.query= reinterpret_cast<const char*>(raw_packet);
908     data->com_stmt_prepare.length= packet_length;
909     break;
910   }
911   case COM_STMT_CLOSE:
912   {
913     if (packet_length < 4)
914       goto malformed;
915 
916     data->com_stmt_close.stmt_id= uint4korr(raw_packet);
917     break;
918   }
919   case COM_STMT_RESET:
920   {
921     if (packet_length < 4)
922       goto malformed;
923 
924     data->com_stmt_reset.stmt_id= uint4korr(raw_packet);
925     break;
926   }
927   case COM_QUERY:
928   {
929     data->com_query.query= reinterpret_cast<const char*>(raw_packet);
930     data->com_query.length= packet_length;
931     break;
932   }
933   case COM_FIELD_LIST:
934   {
935     /*
936       We have name + wildcard in packet, separated by endzero
937     */
938     data->com_field_list.table_name= raw_packet;
939     uint len= data->com_field_list.table_name_length=
940         strend((char *)raw_packet) - (char *)raw_packet;
941     if (len >= packet_length || len > NAME_LEN)
942       goto malformed;
943     data->com_field_list.query= raw_packet + len + 1;
944     data->com_field_list.query_length= packet_length - len;
945     break;
946   }
947   default:
948     break;
949   }
950 
951   return false;
952 
953   malformed:
954   my_error(ER_MALFORMED_PACKET, MYF(0));
955   bad_packet= true;
956   return true;
957 }
958 
create_command(COM_DATA * com_data,enum_server_command cmd,uchar * pkt,size_t length)959 bool Protocol_classic::create_command(COM_DATA *com_data,
960                                       enum_server_command cmd,
961                                       uchar *pkt, size_t length)
962 {
963   raw_packet= pkt;
964   packet_length= length;
965 
966   return parse_packet(com_data, cmd);
967 }
968 
get_command(COM_DATA * com_data,enum_server_command * cmd)969 int Protocol_classic::get_command(COM_DATA *com_data, enum_server_command *cmd)
970 {
971   // read packet from the network
972   if(int rc= read_packet())
973     return rc;
974 
975   /*
976     'packet_length' contains length of data, as it was stored in packet
977     header. In case of malformed header, my_net_read returns zero.
978     If packet_length is not zero, my_net_read ensures that the returned
979     number of bytes was actually read from network.
980     There is also an extra safety measure in my_net_read:
981     it sets packet[packet_length]= 0, but only for non-zero packets.
982   */
983   if (packet_length == 0)                       /* safety */
984   {
985     /* Initialize with COM_SLEEP packet */
986     raw_packet[0]= (uchar) COM_SLEEP;
987     packet_length= 1;
988   }
989   /* Do not rely on my_net_read, extra safety against programming errors. */
990   raw_packet[packet_length]= '\0';                  /* safety */
991 
992   *cmd= (enum enum_server_command) raw_packet[0];
993 
994   if (*cmd >= COM_END)
995     *cmd= COM_END;				// Wrong command
996 
997   assert(packet_length);
998   // Skip 'command'
999   packet_length--;
1000   raw_packet++;
1001 
1002   return parse_packet(com_data, *cmd);
1003 }
1004 
get_rw_status()1005 uint Protocol_classic::get_rw_status()
1006 {
1007   return m_thd->net.reading_or_writing;
1008 }
1009 
1010 /**
1011   Finish the result set with EOF packet, as is expected by the client,
1012   if there is an error evaluating the next row and a continue handler
1013   for the error.
1014 */
1015 
end_partial_result_set()1016 void Protocol_classic::end_partial_result_set()
1017 {
1018   net_send_eof(m_thd, m_thd->server_status,
1019                0 /* no warnings, we're inside SP */);
1020 }
1021 
1022 
flush()1023 bool Protocol_classic::flush()
1024 {
1025 #ifndef EMBEDDED_LIBRARY
1026   bool error;
1027   m_thd->get_stmt_da()->set_overwrite_status(true);
1028   error= net_flush(&m_thd->net);
1029   m_thd->get_stmt_da()->set_overwrite_status(false);
1030   return error;
1031 #else
1032   return 0;
1033 #endif
1034 }
1035 
1036 
get_compression()1037 bool Protocol_classic::get_compression()
1038 {
1039   return m_thd->net.compress;
1040 }
1041 
1042 
1043 #ifndef EMBEDDED_LIBRARY
1044 bool
start_result_metadata(uint num_cols,uint flags,const CHARSET_INFO * cs)1045 Protocol_classic::start_result_metadata(uint num_cols, uint flags,
1046                                         const CHARSET_INFO *cs)
1047 {
1048   DBUG_ENTER("Protocol_classic::start_result_metadata");
1049   DBUG_PRINT("info", ("num_cols %u, flags %u", num_cols, flags));
1050   result_cs= (CHARSET_INFO *) cs;
1051   send_metadata= true;
1052   field_count= num_cols;
1053   sending_flags= flags;
1054   if (flags & Protocol::SEND_NUM_ROWS)
1055   {
1056     ulonglong tmp;
1057     uchar *pos = net_store_length((uchar *) &tmp, num_cols);
1058     my_net_write(&m_thd->net, (uchar *) &tmp, (size_t) (pos - ((uchar *) &tmp)));
1059   }
1060 #ifndef NDEBUG
1061   field_types= (enum_field_types*) m_thd->alloc(sizeof(field_types) * num_cols);
1062   count= 0;
1063 #endif
1064 
1065   DBUG_RETURN(false);
1066 }
1067 
1068 
1069 bool
end_result_metadata()1070 Protocol_classic::end_result_metadata()
1071 {
1072   DBUG_ENTER("Protocol_classic::end_result_metadata");
1073   DBUG_PRINT("info", ("num_cols %u, flags %u", field_count, sending_flags));
1074   send_metadata= false;
1075   if (sending_flags & SEND_EOF)
1076   {
1077     /* if it is new client do not send EOF packet */
1078     if (!(has_client_capability(CLIENT_DEPRECATE_EOF)))
1079     {
1080       /*
1081         Mark the end of meta-data result set, and store m_thd->server_status,
1082         to show that there is no cursor.
1083         Send no warning information, as it will be sent at statement end.
1084       */
1085       if (write_eof_packet(m_thd, &m_thd->net, m_thd->server_status,
1086             m_thd->get_stmt_da()->current_statement_cond_count()))
1087       {
1088         DBUG_RETURN(true);
1089       }
1090     }
1091   }
1092   DBUG_RETURN(false);
1093 }
1094 
1095 
send_field_metadata(Send_field * field,const CHARSET_INFO * item_charset)1096 bool Protocol_classic::send_field_metadata(Send_field *field,
1097                                            const CHARSET_INFO *item_charset)
1098 {
1099   DBUG_ENTER("Protocol_classic::send_field_metadata");
1100   char *pos;
1101   const CHARSET_INFO *cs= system_charset_info;
1102   const CHARSET_INFO *thd_charset= m_thd->variables.character_set_results;
1103 
1104   /* Keep things compatible for old clients */
1105   if (field->type == MYSQL_TYPE_VARCHAR)
1106     field->type= MYSQL_TYPE_VAR_STRING;
1107 
1108   send_metadata= true;
1109   if (has_client_capability(CLIENT_PROTOCOL_41))
1110   {
1111     if (store(STRING_WITH_LEN("def"), cs) ||
1112         store(field->db_name, strlen(field->db_name), cs) ||
1113         store(field->table_name, strlen(field->table_name), cs) ||
1114         store(field->org_table_name, strlen(field->org_table_name), cs) ||
1115         store(field->col_name, strlen(field->col_name), cs) ||
1116         store(field->org_col_name, strlen(field->org_col_name), cs) ||
1117         packet->mem_realloc(packet->length() + 12))
1118     {
1119       send_metadata= false;
1120       return true;
1121     }
1122     /* Store fixed length fields */
1123     pos= (char *) packet->ptr() + packet->length();
1124     *pos++= 12;        // Length of packed fields
1125     /* inject a NULL to test the client */
1126     DBUG_EXECUTE_IF("poison_rs_fields", pos[-1]= (char) 0xfb;);
1127     if (item_charset == &my_charset_bin || thd_charset == NULL)
1128     {
1129       /* No conversion */
1130       int2store(pos, item_charset->number);
1131       int4store(pos + 2, field->length);
1132     }
1133     else
1134     {
1135       /* With conversion */
1136       uint32 field_length, max_length;
1137       int2store(pos, thd_charset->number);
1138       /*
1139         For TEXT/BLOB columns, field_length describes the maximum data
1140         length in bytes. There is no limit to the number of characters
1141         that a TEXT column can store, as long as the data fits into
1142         the designated space.
1143         For the rest of textual columns, field_length is evaluated as
1144         char_count * mbmaxlen, where character count is taken from the
1145         definition of the column. In other words, the maximum number
1146         of characters here is limited by the column definition.
1147 
1148         When one has a LONG TEXT column with a single-byte
1149         character set, and the connection character set is multi-byte, the
1150         client may get fields longer than UINT_MAX32, due to
1151         <character set column> -> <character set connection> conversion.
1152         In that case column max length does not fit into the 4 bytes
1153         reserved for it in the protocol.
1154       */
1155       max_length= (field->type >= MYSQL_TYPE_TINY_BLOB &&
1156                    field->type <= MYSQL_TYPE_BLOB) ?
1157                    field->length / item_charset->mbminlen :
1158                    field->length / item_charset->mbmaxlen;
1159       field_length= char_to_byte_length_safe(max_length, thd_charset->mbmaxlen);
1160       int4store(pos + 2, field_length);
1161     }
1162     pos[6]= field->type;
1163     int2store(pos + 7, field->flags);
1164     pos[9]= (char) field->decimals;
1165     pos[10]= 0;        // For the future
1166     pos[11]= 0;        // For the future
1167     pos+= 12;
1168   }
1169   else
1170   {
1171     if (store(field->table_name, strlen(field->table_name), cs) ||
1172         store(field->col_name, strlen(field->col_name), cs) ||
1173         packet->mem_realloc(packet->length() + 10))
1174     {
1175       send_metadata= false;
1176       return true;
1177     }
1178     pos= (char *) packet->ptr() + packet->length();
1179     pos[0]= 3;
1180     int3store(pos + 1, field->length);
1181     pos[4]= 1;
1182     pos[5]= field->type;
1183     pos[6]= 3;
1184     int2store(pos + 7, field->flags);
1185     pos[9]= (char) field->decimals;
1186     pos+= 10;
1187   }
1188   packet->length((uint) (pos - packet->ptr()));
1189 
1190 #ifndef NDEBUG
1191   // TODO: this should be protocol-dependent, as it records incorrect type
1192   // for binary protocol
1193   // Text protocol sends fields as varchar
1194   field_types[count++]= field->field ? MYSQL_TYPE_VAR_STRING : field->type;
1195 #endif
1196   DBUG_RETURN(false);
1197 }
1198 
1199 
end_row()1200 bool Protocol_classic::end_row()
1201 {
1202   DBUG_ENTER("Protocol_classic::end_row");
1203   if (m_thd->get_protocol()->connection_alive())
1204     DBUG_RETURN(my_net_write(&m_thd->net, (uchar *) packet->ptr(),
1205                              packet->length()));
1206   DBUG_RETURN(0);
1207 }
1208 #endif /* EMBEDDED_LIBRARY */
1209 
1210 
1211 /**
1212   Send a set of strings as one long string with ',' in between.
1213 */
1214 
store(Protocol * prot,I_List<i_string> * str_list)1215 bool store(Protocol *prot, I_List<i_string>* str_list)
1216 {
1217   char buf[256];
1218   String tmp(buf, sizeof(buf), &my_charset_bin);
1219   size_t len;
1220   I_List_iterator<i_string> it(*str_list);
1221   i_string* s;
1222 
1223   tmp.length(0);
1224   while ((s=it++))
1225   {
1226     tmp.append(s->ptr);
1227     tmp.append(',');
1228   }
1229   if ((len= tmp.length()))
1230     len--;                         // Remove last ','
1231   return prot->store((char *) tmp.ptr(), len,  tmp.charset());
1232 }
1233 
1234 /****************************************************************************
1235   Functions to handle the simple (default) protocol where everything is
1236   This protocol is the one that is used by default between the MySQL server
1237   and client when you are not using prepared statements.
1238 
1239   All data are sent as 'packed-string-length' followed by 'string-data'
1240 ****************************************************************************/
1241 
1242 #ifndef EMBEDDED_LIBRARY
1243 
connection_alive()1244 bool Protocol_classic::connection_alive()
1245 {
1246   return m_thd->net.vio != NULL;
1247 }
1248 
start_row()1249 void Protocol_text::start_row()
1250 {
1251 #ifndef NDEBUG
1252   field_pos= 0;
1253 #endif
1254   packet->length(0);
1255 }
1256 
1257 
store_null()1258 bool Protocol_text::store_null()
1259 {
1260 #ifndef NDEBUG
1261   field_pos++;
1262 #endif
1263   char buff[1];
1264   buff[0]= (char)251;
1265   return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
1266 }
1267 #endif
1268 
1269 
1270 /**
1271   Auxilary function to convert string to the given character set
1272   and store in network buffer.
1273 */
1274 
store_string_aux(const char * from,size_t length,const CHARSET_INFO * fromcs,const CHARSET_INFO * tocs)1275 bool Protocol_classic::store_string_aux(const char *from, size_t length,
1276                                         const CHARSET_INFO *fromcs,
1277                                         const CHARSET_INFO *tocs)
1278 {
1279   /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
1280   if (tocs && !my_charset_same(fromcs, tocs) &&
1281       fromcs != &my_charset_bin &&
1282       tocs != &my_charset_bin)
1283   {
1284     /* Store with conversion */
1285     return net_store_data((uchar *) from, length, fromcs, tocs);
1286   }
1287   /* Store without conversion */
1288   return net_store_data((uchar *) from, length);
1289 }
1290 
1291 
shutdown(bool server_shutdown)1292 int Protocol_classic::shutdown(bool server_shutdown)
1293 {
1294   return m_thd->net.vio ? vio_shutdown(m_thd->net.vio, SHUT_RDWR) : 0;
1295 }
1296 
1297 
store(const char * from,size_t length,const CHARSET_INFO * fromcs,const CHARSET_INFO * tocs)1298 bool Protocol_text::store(const char *from, size_t length,
1299                           const CHARSET_INFO *fromcs,
1300                           const CHARSET_INFO *tocs)
1301 {
1302 #ifndef NDEBUG
1303   // field_types check is needed because of the embedded protocol
1304   assert(send_metadata || field_types == 0 ||
1305          field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
1306          field_types[field_pos] == MYSQL_TYPE_BIT ||
1307          field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
1308          field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
1309          field_types[field_pos] == MYSQL_TYPE_JSON ||
1310          (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
1311           field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
1312   if(!send_metadata) field_pos++;
1313 #endif
1314   return store_string_aux(from, length, fromcs, tocs);
1315 }
1316 
1317 
store_tiny(longlong from)1318 bool Protocol_text::store_tiny(longlong from)
1319 {
1320 #ifndef NDEBUG
1321   // field_types check is needed because of the embedded protocol
1322   assert(send_metadata || field_types == 0 ||
1323          field_types[field_pos] == MYSQL_TYPE_TINY);
1324   field_pos++;
1325 #endif
1326   char buff[20];
1327   return net_store_data((uchar *) buff,
1328     (size_t) (int10_to_str((int) from, buff, -10) - buff));
1329 }
1330 
1331 
store_short(longlong from)1332 bool Protocol_text::store_short(longlong from)
1333 {
1334 #ifndef NDEBUG
1335   // field_types check is needed because of the embedded protocol
1336   assert(send_metadata || field_types == 0 ||
1337          field_types[field_pos] == MYSQL_TYPE_YEAR ||
1338          field_types[field_pos] == MYSQL_TYPE_SHORT);
1339   field_pos++;
1340 #endif
1341   char buff[20];
1342   return net_store_data((uchar *) buff,
1343     (size_t) (int10_to_str((int) from, buff, -10) - buff));
1344 }
1345 
1346 
store_long(longlong from)1347 bool Protocol_text::store_long(longlong from)
1348 {
1349 #ifndef NDEBUG
1350   // field_types check is needed because of the embedded protocol
1351   assert(send_metadata || field_types == 0 ||
1352          field_types[field_pos] == MYSQL_TYPE_INT24 ||
1353          field_types[field_pos] == MYSQL_TYPE_LONG);
1354   field_pos++;
1355 #endif
1356   char buff[20];
1357   return net_store_data((uchar *) buff,
1358     (size_t) (int10_to_str((long int)from, buff,
1359                            (from < 0) ? -10 : 10) - buff));
1360 }
1361 
1362 
store_longlong(longlong from,bool unsigned_flag)1363 bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
1364 {
1365 #ifndef NDEBUG
1366   // field_types check is needed because of the embedded protocol
1367   assert(send_metadata || field_types == 0 ||
1368          field_types[field_pos] == MYSQL_TYPE_LONGLONG);
1369   field_pos++;
1370 #endif
1371   char buff[22];
1372   return net_store_data((uchar *) buff,
1373     (size_t) (longlong10_to_str(from, buff,
1374                                 unsigned_flag ? 10 : -10)-
1375                                 buff));
1376 }
1377 
1378 
store_decimal(const my_decimal * d,uint prec,uint dec)1379 bool Protocol_text::store_decimal(const my_decimal *d, uint prec, uint dec)
1380 {
1381 #ifndef NDEBUG
1382   // field_types check is needed because of the embedded protocol
1383   assert(send_metadata || field_types == 0 ||
1384          field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
1385   field_pos++;
1386 #endif
1387   char buff[DECIMAL_MAX_STR_LENGTH + 1];
1388   String str(buff, sizeof(buff), &my_charset_bin);
1389   (void) my_decimal2string(E_DEC_FATAL_ERROR, d, prec, dec, '0', &str);
1390   return net_store_data((uchar *) str.ptr(), str.length());
1391 }
1392 
1393 
store(float from,uint32 decimals,String * buffer)1394 bool Protocol_text::store(float from, uint32 decimals, String *buffer)
1395 {
1396 #ifndef NDEBUG
1397   // field_types check is needed because of the embedded protocol
1398   assert(send_metadata || field_types == 0 ||
1399          field_types[field_pos] == MYSQL_TYPE_FLOAT);
1400   field_pos++;
1401 #endif
1402   buffer->set_real((double) from, decimals, m_thd->charset());
1403   return net_store_data((uchar *) buffer->ptr(), buffer->length());
1404 }
1405 
1406 
store(double from,uint32 decimals,String * buffer)1407 bool Protocol_text::store(double from, uint32 decimals, String *buffer)
1408 {
1409 #ifndef NDEBUG
1410   // field_types check is needed because of the embedded protocol
1411   assert(send_metadata || field_types == 0 ||
1412          field_types[field_pos] == MYSQL_TYPE_DOUBLE);
1413   field_pos++;
1414 #endif
1415   buffer->set_real(from, decimals, m_thd->charset());
1416   return net_store_data((uchar *) buffer->ptr(), buffer->length());
1417 }
1418 
1419 
store(Proto_field * field)1420 bool Protocol_text::store(Proto_field *field)
1421 {
1422   return field->send_text(this);
1423 }
1424 
1425 
1426 /**
1427   @todo
1428   Second_part format ("%06") needs to change when
1429   we support 0-6 decimals for time.
1430 */
1431 
store(MYSQL_TIME * tm,uint decimals)1432 bool Protocol_text::store(MYSQL_TIME *tm, uint decimals)
1433 {
1434 #ifndef NDEBUG
1435   // field_types check is needed because of the embedded protocol
1436   assert(send_metadata || field_types == 0 ||
1437          is_temporal_type_with_date_and_time(field_types[field_pos]));
1438   field_pos++;
1439 #endif
1440   char buff[MAX_DATE_STRING_REP_LENGTH];
1441   size_t length= my_datetime_to_str(tm, buff, decimals);
1442   return net_store_data((uchar *) buff, length);
1443 }
1444 
1445 
store_date(MYSQL_TIME * tm)1446 bool Protocol_text::store_date(MYSQL_TIME *tm)
1447 {
1448 #ifndef NDEBUG
1449   // field_types check is needed because of the embedded protocol
1450   assert(send_metadata || field_types == 0 ||
1451          field_types[field_pos] == MYSQL_TYPE_DATE);
1452   field_pos++;
1453 #endif
1454   char buff[MAX_DATE_STRING_REP_LENGTH];
1455   size_t length= my_date_to_str(tm, buff);
1456   return net_store_data((uchar *) buff, length);
1457 }
1458 
1459 
store_time(MYSQL_TIME * tm,uint decimals)1460 bool Protocol_text::store_time(MYSQL_TIME *tm, uint decimals)
1461 {
1462 #ifndef NDEBUG
1463   // field_types check is needed because of the embedded protocol
1464   assert(send_metadata || field_types == 0 ||
1465          field_types[field_pos] == MYSQL_TYPE_TIME);
1466   field_pos++;
1467 #endif
1468   char buff[MAX_DATE_STRING_REP_LENGTH];
1469   size_t length= my_time_to_str(tm, buff, decimals);
1470   return net_store_data((uchar *) buff, length);
1471 }
1472 
1473 
1474 /**
1475   Assign OUT-parameters to user variables.
1476 
1477   @param sp_params  List of PS/SP parameters (both input and output).
1478 
1479   @return Error status.
1480     @retval FALSE Success.
1481     @retval TRUE  Error.
1482 */
1483 
send_out_parameters(List<Item_param> * sp_params)1484 bool Protocol_text::send_out_parameters(List<Item_param> *sp_params)
1485 {
1486   assert(sp_params->elements == m_thd->lex->prepared_stmt_params.elements);
1487 
1488   List_iterator_fast<Item_param> item_param_it(*sp_params);
1489   List_iterator_fast<LEX_STRING> user_var_name_it(
1490     m_thd->lex->prepared_stmt_params);
1491 
1492   while (true)
1493   {
1494     Item_param *item_param= item_param_it++;
1495     LEX_STRING *user_var_name= user_var_name_it++;
1496 
1497     if (!item_param || !user_var_name)
1498       break;
1499 
1500     if (!item_param->get_out_param_info())
1501       continue; // It's an IN-parameter.
1502 
1503     Item_func_set_user_var *suv=
1504       new Item_func_set_user_var(*user_var_name, item_param, false);
1505     /*
1506       Item_func_set_user_var is not fixed after construction, call
1507       fix_fields().
1508     */
1509     if (suv->fix_fields(m_thd, NULL))
1510       return TRUE;
1511 
1512     if (suv->check(FALSE))
1513       return TRUE;
1514 
1515     if (suv->update())
1516       return TRUE;
1517   }
1518 
1519   return FALSE;
1520 }
1521 
1522 
1523 /****************************************************************************
1524   Functions to handle the binary protocol used with prepared statements
1525 
1526   Data format:
1527 
1528     [ok:1]                            reserved ok packet
1529     [null_field:(field_count+7+2)/8]  reserved to send null data. The size is
1530                                       calculated using:
1531                                       bit_fields= (field_count+7+2)/8;
1532                                       2 bits are reserved for identifying type
1533                                       of package.
1534     [[length]data]                    data field (the length applies only for
1535                                       string/binary/time/timestamp fields and
1536                                       rest of them are not sent as they have
1537                                       the default length that client understands
1538                                       based on the field type
1539     [..]..[[length]data]              data
1540 ****************************************************************************/
start_result_metadata(uint num_cols,uint flags,const CHARSET_INFO * result_cs)1541 bool Protocol_binary::start_result_metadata(uint num_cols, uint flags,
1542                                             const CHARSET_INFO *result_cs)
1543 {
1544   bit_fields= (num_cols + 9) / 8;
1545   packet->alloc(bit_fields+1);
1546   return Protocol_classic::start_result_metadata(num_cols, flags, result_cs);
1547 }
1548 
1549 
1550 #ifndef EMBEDDED_LIBRARY
start_row()1551 void Protocol_binary::start_row()
1552 {
1553   if (send_metadata)
1554     return Protocol_text::start_row();
1555   packet->length(bit_fields+1);
1556   memset(const_cast<char*>(packet->ptr()), 0, 1+bit_fields);
1557   field_pos=0;
1558 }
1559 #endif
1560 
1561 
store(const char * from,size_t length,const CHARSET_INFO * fromcs,const CHARSET_INFO * tocs)1562 bool Protocol_binary::store(const char *from, size_t length,
1563                             const CHARSET_INFO *fromcs,
1564                             const CHARSET_INFO *tocs)
1565 {
1566   if(send_metadata)
1567     return Protocol_text::store(from, length, fromcs, tocs);
1568 #ifndef NDEBUG
1569   // field_types check is needed because of the embedded protocol
1570   assert(field_types == 0 ||
1571          field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
1572          field_types[field_pos] == MYSQL_TYPE_BIT ||
1573          field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
1574          field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
1575          field_types[field_pos] == MYSQL_TYPE_JSON ||
1576          (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
1577           field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
1578 #endif
1579   field_pos++;
1580   return store_string_aux(from, length, fromcs, tocs);
1581 }
1582 
1583 
store_null()1584 bool Protocol_binary::store_null()
1585 {
1586   if(send_metadata)
1587     return Protocol_text::store_null();
1588   uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));
1589   /* Room for this as it's allocated in prepare_for_send */
1590   char *to= (char *) packet->ptr()+offset;
1591   *to= (char) ((uchar) *to | (uchar) bit);
1592   field_pos++;
1593   return 0;
1594 }
1595 
1596 
store_tiny(longlong from)1597 bool Protocol_binary::store_tiny(longlong from)
1598 {
1599   if(send_metadata)
1600     return Protocol_text::store_tiny(from);
1601   char buff[1];
1602 #ifndef NDEBUG
1603   // field_types check is needed because of the embedded protocol
1604   assert(field_types == 0 ||
1605          field_types[field_pos] == MYSQL_TYPE_TINY ||
1606          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1607 #endif
1608   field_pos++;
1609   buff[0]= (uchar) from;
1610   return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
1611 }
1612 
1613 
store_short(longlong from)1614 bool Protocol_binary::store_short(longlong from)
1615 {
1616   if(send_metadata)
1617     return Protocol_text::store_short(from);
1618 #ifndef NDEBUG
1619   // field_types check is needed because of the embedded protocol
1620   assert(field_types == 0 ||
1621          field_types[field_pos] == MYSQL_TYPE_YEAR ||
1622          field_types[field_pos] == MYSQL_TYPE_SHORT ||
1623          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1624 #endif
1625   field_pos++;
1626   char *to= packet->prep_append(2, PACKET_BUFFER_EXTRA_ALLOC);
1627   if (!to)
1628     return 1;
1629   int2store(to, (int) from);
1630   return 0;
1631 }
1632 
1633 
store_long(longlong from)1634 bool Protocol_binary::store_long(longlong from)
1635 {
1636   if(send_metadata)
1637     return Protocol_text::store_long(from);
1638 #ifndef NDEBUG
1639   // field_types check is needed because of the embedded protocol
1640   assert(field_types == 0 ||
1641          field_types[field_pos] == MYSQL_TYPE_INT24 ||
1642          field_types[field_pos] == MYSQL_TYPE_LONG ||
1643          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1644 #endif
1645   field_pos++;
1646   char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
1647   if (!to)
1648     return 1;
1649   int4store(to, static_cast<uint32>(from));
1650   return 0;
1651 }
1652 
1653 
store_longlong(longlong from,bool unsigned_flag)1654 bool Protocol_binary::store_longlong(longlong from, bool unsigned_flag)
1655 {
1656   if(send_metadata)
1657     return Protocol_text::store_longlong(from, unsigned_flag);
1658 #ifndef NDEBUG
1659   // field_types check is needed because of the embedded protocol
1660   assert(field_types == 0 ||
1661          field_types[field_pos] == MYSQL_TYPE_LONGLONG ||
1662          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1663 #endif
1664   field_pos++;
1665   char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
1666   if (!to)
1667     return 1;
1668   int8store(to, from);
1669   return 0;
1670 }
1671 
1672 
store_decimal(const my_decimal * d,uint prec,uint dec)1673 bool Protocol_binary::store_decimal(const my_decimal *d, uint prec, uint dec)
1674 {
1675   if(send_metadata)
1676     return Protocol_text::store_decimal(d, prec, dec);
1677 #ifndef NDEBUG
1678   // field_types check is needed because of the embedded protocol
1679   assert(field_types == 0 ||
1680          field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
1681          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1682   // store() will increment the field_pos counter
1683 #endif
1684   char buff[DECIMAL_MAX_STR_LENGTH + 1];
1685   String str(buff, sizeof(buff), &my_charset_bin);
1686   (void) my_decimal2string(E_DEC_FATAL_ERROR, d, prec, dec, '0', &str);
1687   return store(str.ptr(), str.length(), str.charset(), result_cs);
1688 }
1689 
1690 
store(float from,uint32 decimals,String * buffer)1691 bool Protocol_binary::store(float from, uint32 decimals, String *buffer)
1692 {
1693   if(send_metadata)
1694     return Protocol_text::store(from, decimals, buffer);
1695 #ifndef NDEBUG
1696   // field_types check is needed because of the embedded protocol
1697   assert(field_types == 0 ||
1698          field_types[field_pos] == MYSQL_TYPE_FLOAT ||
1699          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1700 #endif
1701   field_pos++;
1702   char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
1703   if (!to)
1704     return 1;
1705   float4store(to, from);
1706   return 0;
1707 }
1708 
1709 
store(double from,uint32 decimals,String * buffer)1710 bool Protocol_binary::store(double from, uint32 decimals, String *buffer)
1711 {
1712   if(send_metadata)
1713     return Protocol_text::store(from, decimals, buffer);
1714 #ifndef NDEBUG
1715   // field_types check is needed because of the embedded protocol
1716   assert(field_types == 0
1717          || field_types[field_pos] == MYSQL_TYPE_DOUBLE ||
1718          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1719 #endif
1720   field_pos++;
1721   char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
1722   if (!to)
1723     return 1;
1724   float8store(to, from);
1725   return 0;
1726 }
1727 
1728 
store(Proto_field * field)1729 bool Protocol_binary::store(Proto_field *field)
1730 {
1731   if(send_metadata)
1732     return Protocol_text::store(field);
1733   return field->send_binary(this);
1734 }
1735 
1736 
store(MYSQL_TIME * tm,uint precision)1737 bool Protocol_binary::store(MYSQL_TIME *tm, uint precision)
1738 {
1739   if(send_metadata)
1740     return Protocol_text::store(tm, precision);
1741 
1742 #ifndef NDEBUG
1743   // field_types check is needed because of the embedded protocol
1744   assert(field_types == 0 ||
1745          field_types[field_pos] == MYSQL_TYPE_DATE ||
1746          is_temporal_type_with_date_and_time(field_types[field_pos]) ||
1747          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1748 #endif
1749   char buff[12],*pos;
1750   size_t length;
1751   field_pos++;
1752   pos= buff+1;
1753 
1754   int2store(pos, tm->year);
1755   pos[2]= (uchar) tm->month;
1756   pos[3]= (uchar) tm->day;
1757   pos[4]= (uchar) tm->hour;
1758   pos[5]= (uchar) tm->minute;
1759   pos[6]= (uchar) tm->second;
1760   int4store(pos+7, tm->second_part);
1761   if (tm->second_part)
1762     length=11;
1763   else if (tm->hour || tm->minute || tm->second)
1764     length=7;
1765   else if (tm->year || tm->month || tm->day)
1766     length=4;
1767   else
1768     length=0;
1769   buff[0]=(char) length;			// Length is stored first
1770   return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
1771 }
1772 
1773 
store_date(MYSQL_TIME * tm)1774 bool Protocol_binary::store_date(MYSQL_TIME *tm)
1775 {
1776   if(send_metadata)
1777     return Protocol_text::store_date(tm);
1778 #ifndef NDEBUG
1779   // field_types check is needed because of the embedded protocol
1780   assert(field_types == 0 ||
1781          field_types[field_pos] == MYSQL_TYPE_DATE ||
1782          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1783 #endif
1784   tm->hour= tm->minute= tm->second=0;
1785   tm->second_part= 0;
1786   return Protocol_binary::store(tm, 0);
1787 }
1788 
1789 
store_time(MYSQL_TIME * tm,uint precision)1790 bool Protocol_binary::store_time(MYSQL_TIME *tm, uint precision)
1791 {
1792   if(send_metadata)
1793     return Protocol_text::store_time(tm, precision);
1794   char buff[13], *pos;
1795   size_t length;
1796 #ifndef NDEBUG
1797   // field_types check is needed because of the embedded protocol
1798   assert(field_types == 0 ||
1799          field_types[field_pos] == MYSQL_TYPE_TIME ||
1800          field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1801 #endif
1802   field_pos++;
1803   pos= buff+1;
1804   pos[0]= tm->neg ? 1 : 0;
1805   if (tm->hour >= 24)
1806   {
1807     /* Fix if we come from Item::send */
1808     uint days= tm->hour/24;
1809     tm->hour-= days*24;
1810     tm->day+= days;
1811   }
1812   int4store(pos+1, tm->day);
1813   pos[5]= (uchar) tm->hour;
1814   pos[6]= (uchar) tm->minute;
1815   pos[7]= (uchar) tm->second;
1816   int4store(pos+8, tm->second_part);
1817   if (tm->second_part)
1818     length=12;
1819   else if (tm->hour || tm->minute || tm->second || tm->day)
1820     length=8;
1821   else
1822     length=0;
1823   buff[0]=(char) length;			// Length is stored first
1824   return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
1825 }
1826 
1827 
1828 /**
1829   Send a result set with OUT-parameter values by means of PS-protocol.
1830 
1831   @param sp_params  List of PS/SP parameters (both input and output).
1832 
1833   @return Error status.
1834     @retval FALSE Success.
1835     @retval TRUE  Error.
1836 */
1837 
send_out_parameters(List<Item_param> * sp_params)1838 bool Protocol_binary::send_out_parameters(List<Item_param> *sp_params)
1839 {
1840   bool ret;
1841   if (!has_client_capability(CLIENT_PS_MULTI_RESULTS))
1842   {
1843     /* The client does not support OUT-parameters. */
1844     return FALSE;
1845   }
1846 
1847   List<Item> out_param_lst;
1848 
1849   {
1850     List_iterator_fast<Item_param> item_param_it(*sp_params);
1851 
1852     while (true)
1853     {
1854       Item_param *item_param= item_param_it++;
1855 
1856       if (!item_param)
1857         break;
1858 
1859       if (!item_param->get_out_param_info())
1860         continue; // It's an IN-parameter.
1861 
1862       if (out_param_lst.push_back(item_param))
1863         return TRUE;
1864     }
1865   }
1866 
1867   if (!out_param_lst.elements)
1868     return FALSE;
1869 
1870   /*
1871     We have to set SERVER_PS_OUT_PARAMS in THD::server_status, because it
1872     is used in send_result_metadata().
1873   */
1874 
1875   m_thd->server_status|= SERVER_PS_OUT_PARAMS | SERVER_MORE_RESULTS_EXISTS;
1876 
1877   /* Send meta-data. */
1878   if (m_thd->send_result_metadata(&out_param_lst,
1879                                   SEND_NUM_ROWS | SEND_EOF))
1880     return TRUE;
1881 
1882   /* Send data. */
1883 
1884   this->start_row();
1885 
1886   if (m_thd->send_result_set_row(&out_param_lst))
1887     return TRUE;
1888 
1889   if (this->end_row())
1890     return TRUE;
1891 
1892   /* Restore THD::server_status. */
1893   m_thd->server_status&= ~SERVER_PS_OUT_PARAMS;
1894 
1895   /*
1896     Reset SERVER_MORE_RESULTS_EXISTS bit, because for sure this is the last
1897     result set we are sending.
1898   */
1899 
1900   m_thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
1901 
1902   if (has_client_capability(CLIENT_DEPRECATE_EOF))
1903     ret= net_send_ok(m_thd,
1904                      (m_thd->server_status | SERVER_PS_OUT_PARAMS |
1905                        SERVER_MORE_RESULTS_EXISTS),
1906                      m_thd->get_stmt_da()->current_statement_cond_count(),
1907                      0, 0, NULL, true);
1908   else
1909     /* In case of old clients send EOF packet. */
1910     ret= net_send_eof(m_thd, m_thd->server_status, 0);
1911   return ret ? FALSE : TRUE;
1912 }
1913 
1914 
1915 /**
1916   @returns: the file descriptor of the socket.
1917 */
1918 
get_socket()1919 my_socket Protocol_classic::get_socket()
1920 {
1921   return get_vio()->mysql_socket.fd;
1922 }
1923