1 /* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
2    Copyright (c) 2008, 2020, MariaDB Corporation.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; if not, write to the Free Software
15    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335  USA */
16 
17 /**
18   @file
19 
20   Low level functions for storing data to be send to the MySQL client.
21   The actual communction is handled by the net_xxx functions in net_serv.cc
22 */
23 
24 #ifdef USE_PRAGMA_IMPLEMENTATION
25 #pragma implementation				// gcc: Class implementation
26 #endif
27 
28 #include "mariadb.h"
29 #include "sql_priv.h"
30 #include "protocol.h"
31 #include "sql_class.h"                          // THD
32 #include <stdarg.h>
33 
34 static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
35 /* Declared non-static only because of the embedded library. */
36 bool net_send_error_packet(THD *, uint, const char *, const char *);
37 /* Declared non-static only because of the embedded library. */
38 bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *,
39                  bool, bool);
40 /* Declared non-static only because of the embedded library. */
41 bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count);
42 #ifndef EMBEDDED_LIBRARY
43 static bool write_eof_packet(THD *, NET *, uint, uint);
44 #endif
45 
46 #ifndef EMBEDDED_LIBRARY
net_store_data(const uchar * from,size_t length)47 bool Protocol::net_store_data(const uchar *from, size_t length)
48 #else
49 bool Protocol_binary::net_store_data(const uchar *from, size_t length)
50 #endif
51 {
52   ulong 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->realloc(packet_length+9+length))
59     return 1;
60   uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length);
61   if (length)
62     memcpy(to,from,length);
63   packet->length((uint) (to+length-(uchar*) packet->ptr()));
64   return 0;
65 }
66 
67 
68 /*
69   net_store_data_cs() - 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_cs(const uchar * from,size_t length,CHARSET_INFO * from_cs,CHARSET_INFO * to_cs)81 bool Protocol::net_store_data_cs(const uchar *from, size_t length,
82                               CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
83 #else
84 bool Protocol_binary::net_store_data_cs(const uchar *from, size_t length,
85                               CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
86 #endif
87 {
88   uint dummy_errors;
89   /* Calculate maxumum possible result length */
90   size_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
91 
92   if (conv_length > 250)
93   {
94     /*
95       For strings with conv_length greater than 250 bytes
96       we don't know how many bytes we will need to store length: one or two,
97       because we don't know result length until conversion is done.
98       For example, when converting from utf8 (mbmaxlen=3) to latin1,
99       conv_length=300 means that the result length can vary between 100 to 300.
100       length=100 needs one byte, length=300 needs to bytes.
101 
102       Thus conversion directly to "packet" is not worthy.
103       Let's use "convert" as a temporary buffer.
104     */
105     return (convert->copy((const char*) from, length, from_cs,
106                           to_cs, &dummy_errors) ||
107             net_store_data((const uchar*) convert->ptr(), convert->length()));
108   }
109 
110   size_t packet_length= packet->length();
111   size_t new_length= packet_length + conv_length + 1;
112 
113   if (new_length > packet->alloced_length() && packet->realloc(new_length))
114     return 1;
115 
116   char *length_pos= (char*) packet->ptr() + packet_length;
117   char *to= length_pos + 1;
118 
119   to+= copy_and_convert(to, conv_length, to_cs,
120                         (const char*) from, length, from_cs, &dummy_errors);
121 
122   net_store_length((uchar*) length_pos, to - length_pos - 1);
123   packet->length((uint) (to - packet->ptr()));
124   return 0;
125 }
126 
127 
128 /**
129   Send a error string to client.
130 
131   Design note:
132 
133   net_printf_error and net_send_error are low-level functions
134   that shall be used only when a new connection is being
135   established or at server startup.
136 
137   For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
138   critical that every error that can be intercepted is issued in one
139   place only, my_message_sql.
140 
141   @param thd Thread handler
142   @param sql_errno The error code to send
143   @param err A pointer to the error message
144 
145   @return
146     @retval FALSE The message was sent to the client
147     @retval TRUE An error occurred and the message wasn't sent properly
148 */
149 
net_send_error(THD * thd,uint sql_errno,const char * err,const char * sqlstate)150 bool net_send_error(THD *thd, uint sql_errno, const char *err,
151                     const char* sqlstate)
152 {
153   bool error;
154   DBUG_ENTER("net_send_error");
155 
156   DBUG_ASSERT(!thd->spcont);
157   DBUG_ASSERT(sql_errno);
158   DBUG_ASSERT(err);
159 
160   DBUG_PRINT("enter",("sql_errno: %d  err: %s", sql_errno, err));
161 
162   if (sqlstate == NULL)
163     sqlstate= mysql_errno_to_sqlstate(sql_errno);
164 
165   /*
166     It's one case when we can push an error even though there
167     is an OK or EOF already.
168   */
169   thd->get_stmt_da()->set_overwrite_status(true);
170 
171   /* Abort multi-result sets */
172   thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
173 
174   error= net_send_error_packet(thd, sql_errno, err, sqlstate);
175 
176   thd->get_stmt_da()->set_overwrite_status(false);
177 
178   DBUG_RETURN(error);
179 }
180 
181 /**
182   Return ok to the client.
183 
184   The ok packet has the following structure:
185 
186   - 0               : Marker (1 byte)
187   - affected_rows	: Stored in 1-9 bytes
188   - id		: Stored in 1-9 bytes
189   - server_status	: Copy of thd->server_status;  Can be used by client
190   to check if we are inside an transaction.
191   New in 4.0 protocol
192   - warning_count	: Stored in 2 bytes; New in 4.1 protocol
193   - message		: Stored as packed length (1-9 bytes) + message.
194   Is not stored if no message.
195 
196   @param thd		   Thread handler
197   @param server_status     The server status
198   @param statement_warn_count  Total number of warnings
199   @param affected_rows	   Number of rows changed by statement
200   @param id		   Auto_increment id for first row (if used)
201   @param message	   Message to send to the client (Used by mysql_status)
202   @param is_eof            this called instead of old EOF packet
203 
204   @return
205     @retval FALSE The message was successfully sent
206     @retval TRUE An error occurred and the messages wasn't sent properly
207 
208 */
209 
210 #ifndef EMBEDDED_LIBRARY
211 bool
net_send_ok(THD * thd,uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong id,const char * message,bool is_eof,bool skip_flush)212 net_send_ok(THD *thd,
213             uint server_status, uint statement_warn_count,
214             ulonglong affected_rows, ulonglong id, const char *message,
215             bool is_eof,
216             bool skip_flush)
217 {
218   NET *net= &thd->net;
219   StringBuffer<MYSQL_ERRMSG_SIZE + 10> store;
220 
221   bool error= FALSE;
222   DBUG_ENTER("net_send_ok");
223 
224   if (! net->vio)	// hack for re-parsing queries
225   {
226     DBUG_PRINT("info", ("vio present: NO"));
227     DBUG_RETURN(FALSE);
228   }
229 
230   /*
231     OK send instead of EOF still require 0xFE header, but OK packet content.
232   */
233   if (is_eof)
234   {
235     DBUG_ASSERT(thd->client_capabilities & CLIENT_DEPRECATE_EOF);
236     store.q_append((char)254);
237   }
238   else
239     store.q_append('\0');
240 
241   /* affected rows */
242   store.q_net_store_length(affected_rows);
243 
244   /* last insert id */
245   store.q_net_store_length(id);
246 
247   /* if client has not session tracking capability, don't send state change flag*/
248   if (!(thd->client_capabilities & CLIENT_SESSION_TRACK)) {
249     server_status &= ~SERVER_SESSION_STATE_CHANGED;
250   }
251 
252   if (thd->client_capabilities & CLIENT_PROTOCOL_41)
253   {
254     DBUG_PRINT("info",
255 	       ("affected_rows: %lu  id: %lu  status: %u  warning_count: %u",
256 		(ulong) affected_rows,
257 		(ulong) id,
258 		(uint) (server_status & 0xffff),
259 		(uint) statement_warn_count));
260     store.q_append2b(server_status);
261 
262     /* We can only return up to 65535 warnings in two bytes */
263     uint tmp= MY_MIN(statement_warn_count, 65535);
264     store.q_append2b(tmp);
265   }
266   else if (net->return_status)			// For 4.0 protocol
267   {
268     store.q_append2b(server_status);
269   }
270   thd->get_stmt_da()->set_overwrite_status(true);
271 
272   if ((server_status & SERVER_SESSION_STATE_CHANGED) || (message && message[0]))
273   {
274     DBUG_ASSERT(safe_strlen(message) <= MYSQL_ERRMSG_SIZE);
275     store.q_net_store_data((uchar*) safe_str(message), safe_strlen(message));
276   }
277 
278   if (unlikely(server_status & SERVER_SESSION_STATE_CHANGED))
279   {
280     store.set_charset(thd->variables.collation_database);
281     thd->session_tracker.store(thd, &store);
282     thd->server_status&= ~SERVER_SESSION_STATE_CHANGED;
283   }
284 
285   DBUG_ASSERT(store.length() <= MAX_PACKET_LENGTH);
286 
287   error= my_net_write(net, (const unsigned char*)store.ptr(), store.length());
288   if (likely(!error) && (!skip_flush || is_eof))
289     error= net_flush(net);
290 
291   thd->get_stmt_da()->set_overwrite_status(false);
292   DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
293 
294   DBUG_RETURN(error);
295 }
296 
297 
298 static uchar eof_buff[1]= { (uchar) 254 };      /* Marker for end of fields */
299 
300 /**
301   Send eof (= end of result set) to the client.
302 
303   The eof packet has the following structure:
304 
305   - 254		: Marker (1 byte)
306   - warning_count	: Stored in 2 bytes; New in 4.1 protocol
307   - status_flag	: Stored in 2 bytes;
308   For flags like SERVER_MORE_RESULTS_EXISTS.
309 
310   Note that the warning count will not be sent if 'no_flush' is set as
311   we don't want to report the warning count until all data is sent to the
312   client.
313 
314   @param thd		Thread handler
315   @param server_status The server status
316   @param statement_warn_count Total number of warnings
317 
318   @return
319     @retval FALSE The message was successfully sent
320     @retval TRUE An error occurred and the message wasn't sent properly
321 */
322 
323 bool
net_send_eof(THD * thd,uint server_status,uint statement_warn_count)324 net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
325 {
326   NET *net= &thd->net;
327   bool error= FALSE;
328   DBUG_ENTER("net_send_eof");
329 
330   /*
331     Check if client understand new format packets (OK instead of EOF)
332 
333     Normally end of statement reply is signaled by OK packet, but in case
334     of binlog dump request an EOF packet is sent instead. Also, old clients
335     expect EOF packet instead of OK
336   */
337   if ((thd->client_capabilities & CLIENT_DEPRECATE_EOF) &&
338       (thd->get_command() != COM_BINLOG_DUMP ))
339   {
340     error= net_send_ok(thd, server_status, statement_warn_count, 0, 0, NULL,
341                        true, false);
342     DBUG_RETURN(error);
343   }
344 
345   /* Set to TRUE if no active vio, to work well in case of --init-file */
346   if (net->vio != 0)
347   {
348     thd->get_stmt_da()->set_overwrite_status(true);
349     error= write_eof_packet(thd, net, server_status, statement_warn_count);
350     if (likely(!error))
351       error= net_flush(net);
352     thd->get_stmt_da()->set_overwrite_status(false);
353     DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
354   }
355   DBUG_RETURN(error);
356 }
357 
358 
359 /**
360   Format EOF packet according to the current protocol and
361   write it to the network output buffer.
362 
363   @param thd The thread handler
364   @param net The network handler
365   @param server_status The server status
366   @param statement_warn_count The number of warnings
367 
368 
369   @return
370     @retval FALSE The message was sent successfully
371     @retval TRUE An error occurred and the messages wasn't sent properly
372 */
373 
write_eof_packet(THD * thd,NET * net,uint server_status,uint statement_warn_count)374 static bool write_eof_packet(THD *thd, NET *net,
375                              uint server_status,
376                              uint statement_warn_count)
377 {
378   bool error;
379   if (thd->client_capabilities & CLIENT_PROTOCOL_41)
380   {
381     uchar buff[5];
382     /*
383       Don't send warn count during SP execution, as the warn_list
384       is cleared between substatements, and mysqltest gets confused
385     */
386     uint tmp= MY_MIN(statement_warn_count, 65535);
387     buff[0]= 254;
388     int2store(buff+1, tmp);
389     /*
390       The following test should never be true, but it's better to do it
391       because if 'is_fatal_error' is set the server is not going to execute
392       other queries (see the if test in dispatch_command / COM_QUERY)
393     */
394     if (unlikely(thd->is_fatal_error))
395       server_status&= ~SERVER_MORE_RESULTS_EXISTS;
396     int2store(buff + 3, server_status);
397     error= my_net_write(net, buff, 5);
398   }
399   else
400     error= my_net_write(net, eof_buff, 1);
401 
402   return error;
403 }
404 
405 /**
406   @param thd Thread handler
407   @param sql_errno The error code to send
408   @param err A pointer to the error message
409 
410   @return
411    @retval FALSE The message was successfully sent
412    @retval TRUE  An error occurred and the messages wasn't sent properly
413 */
414 
net_send_error_packet(THD * thd,uint sql_errno,const char * err,const char * sqlstate)415 bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
416                            const char* sqlstate)
417 
418 {
419   NET *net= &thd->net;
420   uint length;
421   /*
422     buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512
423   */
424   uint error;
425   char converted_err[MYSQL_ERRMSG_SIZE];
426   char buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos;
427   my_bool ret;
428   uint8 save_compress;
429   DBUG_ENTER("send_error_packet");
430 
431   if (net->vio == 0)
432   {
433     if (thd->bootstrap)
434     {
435       /* In bootstrap it's ok to print on stderr */
436       fprintf(stderr,"ERROR: %d  %s\n",sql_errno,err);
437     }
438     DBUG_RETURN(FALSE);
439   }
440 
441   int2store(buff,sql_errno);
442   pos= buff+2;
443   if (thd->client_capabilities & CLIENT_PROTOCOL_41)
444   {
445     /* The first # is to make the protocol backward compatible */
446     buff[2]= '#';
447     pos= strmov(buff+3, sqlstate);
448   }
449 
450   convert_error_message(converted_err, sizeof(converted_err),
451                         thd->variables.character_set_results,
452                         err, strlen(err), system_charset_info, &error);
453   /* Converted error message is always null-terminated. */
454   length= (uint) (strmake(pos, converted_err, MYSQL_ERRMSG_SIZE - 1) - buff);
455 
456   /*
457     Ensure that errors are not compressed. This is to ensure we can
458     detect out of bands error messages in the client
459   */
460   if ((save_compress= net->compress))
461     net->compress= 2;
462 
463   /*
464     Sometimes, we send errors "out-of-band", e.g ER_CONNECTION_KILLED
465     on an idle connection. The current protocol "sequence number" is 0,
466     however some client drivers would however always   expect packets
467     coming from server to have seq_no > 0, due to missing awareness
468     of "out-of-band" operations. Make these clients happy.
469   */
470   if (!net->pkt_nr &&
471       (sql_errno == ER_CONNECTION_KILLED || sql_errno == ER_SERVER_SHUTDOWN ||
472        sql_errno == ER_QUERY_INTERRUPTED))
473   {
474     net->pkt_nr= 1;
475   }
476 
477   ret= net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) buff,
478                          length);
479   net->compress= save_compress;
480   DBUG_RETURN(ret);
481 }
482 
483 #endif /* EMBEDDED_LIBRARY */
484 
485 /**
486   Faster net_store_length when we know that length is less than 65536.
487   We keep a separate version for that range because it's widely used in
488   libmysql.
489 
490   uint is used as agrument type because of MySQL type conventions:
491   - uint for 0..65536
492   - ulong for 0..4294967296
493   - ulonglong for bigger numbers.
494 */
495 
net_store_length_fast(uchar * packet,size_t length)496 static uchar *net_store_length_fast(uchar *packet, size_t length)
497 {
498   DBUG_ASSERT(length < UINT_MAX16);
499   if (length < 251)
500   {
501     *packet=(uchar) length;
502     return packet+1;
503   }
504   *packet++=252;
505   int2store(packet,(uint) length);
506   return packet+2;
507 }
508 
509 /**
510   Send the status of the current statement execution over network.
511 
512   @param  thd   in fact, carries two parameters, NET for the transport and
513                 Diagnostics_area as the source of status information.
514 
515   In MySQL, there are two types of SQL statements: those that return
516   a result set and those that return status information only.
517 
518   If a statement returns a result set, it consists of 3 parts:
519   - result set meta-data
520   - variable number of result set rows (can be 0)
521   - followed and terminated by EOF or ERROR packet
522 
523   Once the  client has seen the meta-data information, it always
524   expects an EOF or ERROR to terminate the result set. If ERROR is
525   received, the result set rows are normally discarded (this is up
526   to the client implementation, libmysql at least does discard them).
527   EOF, on the contrary, means "successfully evaluated the entire
528   result set". Since we don't know how many rows belong to a result
529   set until it's evaluated, EOF/ERROR is the indicator of the end
530   of the row stream. Note, that we can not buffer result set rows
531   on the server -- there may be an arbitrary number of rows. But
532   we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
533   delay sending it till the very end of execution (here), to be able to
534   change EOF to an ERROR if commit failed or some other error occurred
535   during the last cleanup steps taken after execution.
536 
537   A statement that does not return a result set doesn't send result
538   set meta-data either. Instead it returns one of:
539   - OK packet
540   - ERROR packet.
541   Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
542   packet is "buffered" in the diagnostics area and sent to the client
543   in the end of statement.
544 
545   @note This method defines a template, but delegates actual
546   sending of data to virtual Protocol::send_{ok,eof,error}. This
547   allows for implementation of protocols that "intercept" ok/eof/error
548   messages, and store them in memory, etc, instead of sending to
549   the client.
550 
551   @pre  The diagnostics area is assigned or disabled. It can not be empty
552         -- we assume that every SQL statement or COM_* command
553         generates OK, ERROR, or EOF status.
554 
555   @post The status information is encoded to protocol format and sent to the
556         client.
557 
558   @return We conventionally return void, since the only type of error
559           that can happen here is a NET (transport) error, and that one
560           will become visible when we attempt to read from the NET the
561           next command.
562           Diagnostics_area::is_sent is set for debugging purposes only.
563 */
564 
end_statement()565 void Protocol::end_statement()
566 {
567   /* sanity check*/
568   DBUG_ASSERT_IF_WSREP(!(WSREP(thd) && thd->wsrep_conflict_state == REPLAYING));
569   DBUG_ENTER("Protocol::end_statement");
570   DBUG_ASSERT(! thd->get_stmt_da()->is_sent());
571   bool error= FALSE;
572 
573   /* Can not be true, but do not take chances in production. */
574   if (thd->get_stmt_da()->is_sent())
575     DBUG_VOID_RETURN;
576 
577   switch (thd->get_stmt_da()->status()) {
578   case Diagnostics_area::DA_ERROR:
579     /* The query failed, send error to log and abort bootstrap. */
580     error= send_error(thd->get_stmt_da()->sql_errno(),
581                       thd->get_stmt_da()->message(),
582                       thd->get_stmt_da()->get_sqlstate());
583     break;
584   case Diagnostics_area::DA_EOF:
585     error= send_eof(thd->server_status,
586                     thd->get_stmt_da()->statement_warn_count());
587     break;
588   case Diagnostics_area::DA_OK:
589   case Diagnostics_area::DA_OK_BULK:
590     error= send_ok(thd->server_status,
591                    thd->get_stmt_da()->statement_warn_count(),
592                    thd->get_stmt_da()->affected_rows(),
593                    thd->get_stmt_da()->last_insert_id(),
594                    thd->get_stmt_da()->message(),
595                    thd->get_stmt_da()->skip_flush());
596     break;
597   case Diagnostics_area::DA_DISABLED:
598     break;
599   case Diagnostics_area::DA_EMPTY:
600   default:
601     DBUG_ASSERT(0);
602     error= send_ok(thd->server_status, 0, 0, 0, NULL,
603                    thd->get_stmt_da()->skip_flush());
604     break;
605   }
606   if (likely(!error))
607     thd->get_stmt_da()->set_is_sent(true);
608   DBUG_VOID_RETURN;
609 }
610 
611 /**
612   A default implementation of "OK" packet response to the client.
613 
614   Currently this implementation is re-used by both network-oriented
615   protocols -- the binary and text one. They do not differ
616   in their OK packet format, which allows for a significant simplification
617   on client side.
618 */
619 
send_ok(uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong last_insert_id,const char * message,bool skip_flush)620 bool Protocol::send_ok(uint server_status, uint statement_warn_count,
621                        ulonglong affected_rows, ulonglong last_insert_id,
622                        const char *message, bool skip_flush)
623 {
624   DBUG_ENTER("Protocol::send_ok");
625   const bool retval=
626     net_send_ok(thd, server_status, statement_warn_count,
627                 affected_rows, last_insert_id, message, false, skip_flush);
628   DBUG_RETURN(retval);
629 }
630 
631 
632 /**
633   A default implementation of "EOF" packet response to the client.
634 
635   Binary and text protocol do not differ in their EOF packet format.
636 */
637 
send_eof(uint server_status,uint statement_warn_count)638 bool Protocol::send_eof(uint server_status, uint statement_warn_count)
639 {
640   DBUG_ENTER("Protocol::send_eof");
641   bool retval= net_send_eof(thd, server_status, statement_warn_count);
642   DBUG_RETURN(retval);
643 }
644 
645 
646 /**
647   A default implementation of "ERROR" packet response to the client.
648 
649   Binary and text protocol do not differ in ERROR packet format.
650 */
651 
send_error(uint sql_errno,const char * err_msg,const char * sql_state)652 bool Protocol::send_error(uint sql_errno, const char *err_msg,
653                           const char *sql_state)
654 {
655   DBUG_ENTER("Protocol::send_error");
656   const bool retval= net_send_error_packet(thd, sql_errno, err_msg, sql_state);
657   DBUG_RETURN(retval);
658 }
659 
660 
661 /**
662    Send a progress report to the client
663 
664    What we send is:
665    header (255,255,255,1)
666    stage, max_stage as on byte integers
667    percentage withing the stage as percentage*1000
668    (that is, ratio*100000) as a 3 byte integer
669    proc_info as a string
670 */
671 
672 const uchar progress_header[2]= {(uchar) 255, (uchar) 255 };
673 
net_send_progress_packet(THD * thd)674 void net_send_progress_packet(THD *thd)
675 {
676   uchar buff[200], *pos;
677   const char *proc_info= thd->proc_info ? thd->proc_info : "";
678   size_t length= strlen(proc_info);
679   ulonglong progress;
680   DBUG_ENTER("net_send_progress_packet");
681 
682   if (unlikely(!thd->net.vio))
683     DBUG_VOID_RETURN;                           // Socket is closed
684 
685   pos= buff;
686   /*
687     Store number of strings first. This allows us to later expand the
688     progress indicator if needed.
689   */
690   *pos++= (uchar) 1;                            // Number of strings
691   *pos++= (uchar) thd->progress.stage + 1;
692   /*
693     We have the MY_MAX() here to avoid problems if max_stage is not set,
694     which may happen during automatic repair of table
695   */
696   *pos++= (uchar) MY_MAX(thd->progress.max_stage, thd->progress.stage + 1);
697   progress= 0;
698   if (thd->progress.max_counter)
699     progress= 100000ULL * thd->progress.counter / thd->progress.max_counter;
700   int3store(pos, progress);                          // Between 0 & 100000
701   pos+= 3;
702   pos= net_store_data(pos, (const uchar*) proc_info,
703                       MY_MIN(length, sizeof(buff)-7));
704   net_write_command(&thd->net, (uchar) 255, progress_header,
705                     sizeof(progress_header), (uchar*) buff,
706                     (uint) (pos - buff));
707   DBUG_VOID_RETURN;
708 }
709 
710 
711 /****************************************************************************
712   Functions used by the protocol functions (like net_send_ok) to store
713   strings and numbers in the header result packet.
714 ****************************************************************************/
715 
716 /* The following will only be used for short strings < 65K */
717 
net_store_data(uchar * to,const uchar * from,size_t length)718 uchar *net_store_data(uchar *to, const uchar *from, size_t length)
719 {
720   to=net_store_length_fast(to,length);
721   if (length)
722     memcpy(to,from,length);
723   return to+length;
724 }
725 
net_store_data(uchar * to,int32 from)726 uchar *net_store_data(uchar *to,int32 from)
727 {
728   char buff[22];
729   uint length=(uint) (int10_to_str(from,buff,10)-buff);
730   to=net_store_length_fast(to,length);
731   memcpy(to,buff,length);
732   return to+length;
733 }
734 
net_store_data(uchar * to,longlong from)735 uchar *net_store_data(uchar *to,longlong from)
736 {
737   char buff[22];
738   uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
739   to=net_store_length_fast(to,length);
740   memcpy(to,buff,length);
741   return to+length;
742 }
743 
744 
745 /*****************************************************************************
746   Default Protocol functions
747 *****************************************************************************/
748 
init(THD * thd_arg)749 void Protocol::init(THD *thd_arg)
750 {
751   thd=thd_arg;
752   packet= &thd->packet;
753   convert= &thd->convert_buffer;
754 #ifndef DBUG_OFF
755   field_types= 0;
756 #endif
757 }
758 
759 /**
760   Finish the result set with EOF packet, as is expected by the client,
761   if there is an error evaluating the next row and a continue handler
762   for the error.
763 */
764 
end_partial_result_set(THD * thd_arg)765 void Protocol::end_partial_result_set(THD *thd_arg)
766 {
767   net_send_eof(thd_arg, thd_arg->server_status,
768                0 /* no warnings, we're inside SP */);
769 }
770 
771 
flush()772 bool Protocol::flush()
773 {
774 #ifndef EMBEDDED_LIBRARY
775   bool error;
776   thd->get_stmt_da()->set_overwrite_status(true);
777   error= net_flush(&thd->net);
778   thd->get_stmt_da()->set_overwrite_status(false);
779   return error;
780 #else
781   return 0;
782 #endif
783 }
784 
785 #ifndef EMBEDDED_LIBRARY
786 
787 /**
788   Send name and type of result to client.
789 
790   Sum fields has table name empty and field_name.
791 
792   @param THD		Thread data object
793   @param list	        List of items to send to client
794   @param flag	        Bit mask with the following functions:
795                         - 1 send number of rows
796                         - 2 send default values
797                         - 4 don't write eof packet
798 
799   @retval
800     0	ok
801   @retval
802     1	Error  (Note that in this case the error is not sent to the
803     client)
804 */
send_result_set_metadata(List<Item> * list,uint flags)805 bool Protocol::send_result_set_metadata(List<Item> *list, uint flags)
806 {
807   List_iterator_fast<Item> it(*list);
808   Item *item;
809   ValueBuffer<MAX_FIELD_WIDTH> tmp;
810   Protocol_text prot(thd);
811   String *local_packet= prot.storage_packet();
812   CHARSET_INFO *thd_charset= thd->variables.character_set_results;
813   DBUG_ENTER("Protocol::send_result_set_metadata");
814 
815   if (flags & SEND_NUM_ROWS)
816   {				// Packet with number of elements
817     uchar buff[MAX_INT_WIDTH];
818     uchar *pos= net_store_length(buff, list->elements);
819     DBUG_ASSERT(pos <= buff + sizeof(buff));
820     if (my_net_write(&thd->net, buff, (size_t) (pos-buff)))
821       DBUG_RETURN(1);
822   }
823 
824 #ifndef DBUG_OFF
825   field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
826 					      list->elements);
827   uint count= 0;
828 #endif
829 
830   /* We have to reallocate it here as a stored procedure may have reset it */
831   (void) local_packet->alloc(thd->variables.net_buffer_length);
832 
833   while ((item=it++))
834   {
835     char *pos;
836     CHARSET_INFO *cs= system_charset_info;
837     Send_field field;
838     item->make_send_field(thd, &field);
839 
840     /* limit number of decimals for float and double */
841     if (field.type == MYSQL_TYPE_FLOAT || field.type == MYSQL_TYPE_DOUBLE)
842       set_if_smaller(field.decimals, FLOATING_POINT_DECIMALS);
843 
844     /* Keep things compatible for old clients */
845     if (field.type == MYSQL_TYPE_VARCHAR)
846       field.type= MYSQL_TYPE_VAR_STRING;
847 
848     prot.prepare_for_resend();
849 
850     if (thd->client_capabilities & CLIENT_PROTOCOL_41)
851     {
852       if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
853 	  prot.store(field.db_name, (uint) strlen(field.db_name),
854 		     cs, thd_charset) ||
855 	  prot.store(field.table_name, (uint) strlen(field.table_name),
856 		     cs, thd_charset) ||
857 	  prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
858 		     cs, thd_charset) ||
859 	  prot.store(field.col_name.str, (uint) field.col_name.length,
860 		     cs, thd_charset) ||
861 	  prot.store(field.org_col_name.str, (uint) field.org_col_name.length,
862 		     cs, thd_charset) ||
863 	  local_packet->realloc(local_packet->length()+12))
864 	goto err;
865       /* Store fixed length fields */
866       pos= (char*) local_packet->ptr()+local_packet->length();
867       *pos++= 12;				// Length of packed fields
868       /* inject a NULL to test the client */
869       DBUG_EXECUTE_IF("poison_rs_fields", pos[-1]= (char) 0xfb;);
870       if (item->charset_for_protocol() == &my_charset_bin || thd_charset == NULL)
871       {
872         /* No conversion */
873         int2store(pos, item->charset_for_protocol()->number);
874         int4store(pos+2, field.length);
875       }
876       else
877       {
878         /* With conversion */
879         uint32 field_length, max_length;
880         int2store(pos, thd_charset->number);
881         /*
882           For TEXT/BLOB columns, field_length describes the maximum data
883           length in bytes. There is no limit to the number of characters
884           that a TEXT column can store, as long as the data fits into
885           the designated space.
886           For the rest of textual columns, field_length is evaluated as
887           char_count * mbmaxlen, where character count is taken from the
888           definition of the column. In other words, the maximum number
889           of characters here is limited by the column definition.
890 
891           When one has a LONG TEXT column with a single-byte
892           character set, and the connection character set is multi-byte, the
893           client may get fields longer than UINT_MAX32, due to
894           <character set column> -> <character set connection> conversion.
895           In that case column max length does not fit into the 4 bytes
896           reserved for it in the protocol.
897         */
898         max_length= (field.type >= MYSQL_TYPE_TINY_BLOB &&
899                      field.type <= MYSQL_TYPE_BLOB) ?
900                      field.length / item->collation.collation->mbminlen :
901                      field.length / item->collation.collation->mbmaxlen;
902         field_length= char_to_byte_length_safe(max_length,
903                                                thd_charset->mbmaxlen);
904         int4store(pos + 2, field_length);
905       }
906       pos[6]= field.type;
907       int2store(pos+7,field.flags);
908       pos[9]= (char) field.decimals;
909       pos[10]= 0;				// For the future
910       pos[11]= 0;				// For the future
911       pos+= 12;
912     }
913     else
914     {
915       if (prot.store(field.table_name, (uint) strlen(field.table_name),
916 		     cs, thd_charset) ||
917 	  prot.store(field.col_name.str, (uint) field.col_name.length,
918 		     cs, thd_charset) ||
919 	  local_packet->realloc(local_packet->length()+10))
920 	goto err;
921       pos= (char*) local_packet->ptr()+local_packet->length();
922       pos[0]=3;
923       int3store(pos+1,field.length);
924       pos[4]=1;
925       pos[5]=field.type;
926       pos[6]=3;
927       int2store(pos+7,field.flags);
928       pos[9]= (char) field.decimals;
929       pos+= 10;
930     }
931     local_packet->length((uint) (pos - local_packet->ptr()));
932     if (flags & SEND_DEFAULTS)
933       item->send(&prot, &tmp);			// Send default value
934     if (prot.write())
935       DBUG_RETURN(1);
936 #ifndef DBUG_OFF
937     field_types[count++]= field.type;
938 #endif
939   }
940 
941   if (flags & SEND_EOF)
942   {
943 
944     /* if it is new client do not send EOF packet */
945     if (!(thd->client_capabilities & CLIENT_DEPRECATE_EOF))
946     {
947       /*
948         Mark the end of meta-data result set, and store thd->server_status,
949         to show that there is no cursor.
950         Send no warning information, as it will be sent at statement end.
951       */
952       if (write_eof_packet(thd, &thd->net, thd->server_status,
953                            thd->get_stmt_da()->current_statement_warn_count()))
954         DBUG_RETURN(1);
955     }
956   }
957   DBUG_RETURN(prepare_for_send(list->elements));
958 
959 err:
960   my_message(ER_OUT_OF_RESOURCES, ER_THD(thd, ER_OUT_OF_RESOURCES),
961              MYF(0));	/* purecov: inspected */
962   DBUG_RETURN(1);				/* purecov: inspected */
963 }
964 
965 
write()966 bool Protocol::write()
967 {
968   DBUG_ENTER("Protocol::write");
969   DBUG_RETURN(my_net_write(&thd->net, (uchar*) packet->ptr(),
970                            packet->length()));
971 }
972 #endif /* EMBEDDED_LIBRARY */
973 
974 
975 /**
976   Send one result set row.
977 
978   @param row_items a collection of column values for that row
979 
980   @return Error status.
981     @retval TRUE  Error.
982     @retval FALSE Success.
983 */
984 
send_result_set_row(List<Item> * row_items)985 bool Protocol::send_result_set_row(List<Item> *row_items)
986 {
987   List_iterator_fast<Item> it(*row_items);
988 
989   DBUG_ENTER("Protocol::send_result_set_row");
990 
991   for (Item *item= it++; item; item= it++)
992   {
993     /*
994       ValueBuffer::m_string can be altered during Item::send().
995       It's important to declare value_buffer inside the loop,
996       to have ValueBuffer::m_string point to ValueBuffer::buffer
997       on every iteration.
998     */
999     ValueBuffer<MAX_FIELD_WIDTH> value_buffer;
1000     if (item->send(this, &value_buffer))
1001     {
1002       // If we're out of memory, reclaim some, to help us recover.
1003       this->free();
1004       DBUG_RETURN(TRUE);
1005     }
1006     /* Item::send() may generate an error. If so, abort the loop. */
1007     if (unlikely(thd->is_error()))
1008       DBUG_RETURN(TRUE);
1009   }
1010 
1011   DBUG_RETURN(FALSE);
1012 }
1013 
1014 
1015 /**
1016   Send \\0 end terminated string.
1017 
1018   @param from	NullS or \\0 terminated string
1019 
1020   @note
1021     In most cases one should use store(from, length) instead of this function
1022 
1023   @retval
1024     0		ok
1025   @retval
1026     1		error
1027 */
1028 
store(const char * from,CHARSET_INFO * cs)1029 bool Protocol::store(const char *from, CHARSET_INFO *cs)
1030 {
1031   if (!from)
1032     return store_null();
1033   size_t length= strlen(from);
1034   return store(from, length, cs);
1035 }
1036 
1037 
1038 /**
1039   Send a set of strings as one long string with ',' in between.
1040 */
1041 
store(I_List<i_string> * str_list)1042 bool Protocol::store(I_List<i_string>* str_list)
1043 {
1044   char buf[256];
1045   String tmp(buf, sizeof(buf), &my_charset_bin);
1046   uint32 len;
1047   I_List_iterator<i_string> it(*str_list);
1048   i_string* s;
1049 
1050   tmp.length(0);
1051   while ((s=it++))
1052   {
1053     tmp.append(s->ptr);
1054     tmp.append(',');
1055   }
1056   if ((len= tmp.length()))
1057     len--;					// Remove last ','
1058   return store((char*) tmp.ptr(), len,  tmp.charset());
1059 }
1060 
1061 /****************************************************************************
1062   Functions to handle the simple (default) protocol where everything is
1063   This protocol is the one that is used by default between the MySQL server
1064   and client when you are not using prepared statements.
1065 
1066   All data are sent as 'packed-string-length' followed by 'string-data'
1067 ****************************************************************************/
1068 
1069 #ifndef EMBEDDED_LIBRARY
prepare_for_resend()1070 void Protocol_text::prepare_for_resend()
1071 {
1072   packet->length(0);
1073 #ifndef DBUG_OFF
1074   field_pos= 0;
1075 #endif
1076 }
1077 
store_null()1078 bool Protocol_text::store_null()
1079 {
1080 #ifndef DBUG_OFF
1081   field_pos++;
1082 #endif
1083   char buff[1];
1084   buff[0]= (char)251;
1085   return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
1086 }
1087 #endif
1088 
1089 
1090 /**
1091   Auxilary function to convert string to the given character set
1092   and store in network buffer.
1093 */
1094 
store_string_aux(const char * from,size_t length,CHARSET_INFO * fromcs,CHARSET_INFO * tocs)1095 bool Protocol::store_string_aux(const char *from, size_t length,
1096                                 CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
1097 {
1098   /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
1099   if (tocs && !my_charset_same(fromcs, tocs) &&
1100       fromcs != &my_charset_bin &&
1101       tocs != &my_charset_bin)
1102   {
1103     /* Store with conversion */
1104     return net_store_data_cs((uchar*) from, length, fromcs, tocs);
1105   }
1106   /* Store without conversion */
1107   return net_store_data((uchar*) from, length);
1108 }
1109 
1110 
store(const char * from,size_t length,CHARSET_INFO * fromcs,CHARSET_INFO * tocs)1111 bool Protocol_text::store(const char *from, size_t length,
1112                           CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
1113 {
1114 #ifndef DBUG_OFF
1115   DBUG_ASSERT(field_types == 0 ||
1116 	      field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
1117               field_types[field_pos] == MYSQL_TYPE_BIT ||
1118               field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
1119 	      (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
1120 	       field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
1121   field_pos++;
1122 #endif
1123   return store_string_aux(from, length, fromcs, tocs);
1124 }
1125 
1126 
store(const char * from,size_t length,CHARSET_INFO * fromcs)1127 bool Protocol_text::store(const char *from, size_t length,
1128                           CHARSET_INFO *fromcs)
1129 {
1130   CHARSET_INFO *tocs= this->thd->variables.character_set_results;
1131 #ifndef DBUG_OFF
1132   DBUG_PRINT("info", ("Protocol_text::store field %u (%u): %.*s", field_pos,
1133                       field_count, (int) length, (length == 0 ? "" : from)));
1134   DBUG_ASSERT(field_types == 0 || field_pos < field_count);
1135   DBUG_ASSERT(field_types == 0 ||
1136 	      field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
1137               field_types[field_pos] == MYSQL_TYPE_BIT ||
1138               field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
1139               field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
1140 	      (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
1141 	       field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
1142   field_pos++;
1143 #endif
1144   return store_string_aux(from, length, fromcs, tocs);
1145 }
1146 
1147 
store_tiny(longlong from)1148 bool Protocol_text::store_tiny(longlong from)
1149 {
1150 #ifndef DBUG_OFF
1151   DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
1152   field_pos++;
1153 #endif
1154   char buff[22];
1155   return net_store_data((uchar*) buff,
1156 			(size_t) (int10_to_str((int) from, buff, -10) - buff));
1157 }
1158 
1159 
store_short(longlong from)1160 bool Protocol_text::store_short(longlong from)
1161 {
1162 #ifndef DBUG_OFF
1163   DBUG_ASSERT(field_types == 0 ||
1164 	      field_types[field_pos] == MYSQL_TYPE_YEAR ||
1165 	      field_types[field_pos] == MYSQL_TYPE_SHORT);
1166   field_pos++;
1167 #endif
1168   char buff[22];
1169   return net_store_data((uchar*) buff,
1170 			(size_t) (int10_to_str((int) from, buff, -10) -
1171                                   buff));
1172 }
1173 
1174 
store_long(longlong from)1175 bool Protocol_text::store_long(longlong from)
1176 {
1177 #ifndef DBUG_OFF
1178   DBUG_ASSERT(field_types == 0 ||
1179               field_types[field_pos] == MYSQL_TYPE_INT24 ||
1180               field_types[field_pos] == MYSQL_TYPE_LONG);
1181   field_pos++;
1182 #endif
1183   char buff[22];
1184   return net_store_data((uchar*) buff,
1185 			(size_t) (int10_to_str((long int)from, buff,
1186                                                (from <0)?-10:10)-buff));
1187 }
1188 
1189 
store_longlong(longlong from,bool unsigned_flag)1190 bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
1191 {
1192 #ifndef DBUG_OFF
1193   DBUG_ASSERT(field_types == 0 ||
1194 	      field_types[field_pos] == MYSQL_TYPE_LONGLONG);
1195   field_pos++;
1196 #endif
1197   char buff[22];
1198   return net_store_data((uchar*) buff,
1199 			(size_t) (longlong10_to_str(from,buff,
1200                                                     unsigned_flag ? 10 : -10)-
1201                                   buff));
1202 }
1203 
1204 
store_decimal(const my_decimal * d)1205 bool Protocol_text::store_decimal(const my_decimal *d)
1206 {
1207 #ifndef DBUG_OFF
1208   DBUG_ASSERT(field_types == 0 ||
1209               field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
1210   field_pos++;
1211 #endif
1212   char buff[DECIMAL_MAX_STR_LENGTH];
1213   String str(buff, sizeof(buff), &my_charset_bin);
1214   (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
1215   return net_store_data((uchar*) str.ptr(), str.length());
1216 }
1217 
1218 
store(float from,uint32 decimals,String * buffer)1219 bool Protocol_text::store(float from, uint32 decimals, String *buffer)
1220 {
1221 #ifndef DBUG_OFF
1222   DBUG_ASSERT(field_types == 0 ||
1223 	      field_types[field_pos] == MYSQL_TYPE_FLOAT);
1224   field_pos++;
1225 #endif
1226   Float(from).to_string(buffer, decimals);
1227   return net_store_data((uchar*) buffer->ptr(), buffer->length());
1228 }
1229 
1230 
store(double from,uint32 decimals,String * buffer)1231 bool Protocol_text::store(double from, uint32 decimals, String *buffer)
1232 {
1233 #ifndef DBUG_OFF
1234   DBUG_ASSERT(field_types == 0 ||
1235 	      field_types[field_pos] == MYSQL_TYPE_DOUBLE);
1236   field_pos++;
1237 #endif
1238   buffer->set_real(from, decimals, thd->charset());
1239   return net_store_data((uchar*) buffer->ptr(), buffer->length());
1240 }
1241 
1242 
store(Field * field)1243 bool Protocol_text::store(Field *field)
1244 {
1245   if (field->is_null())
1246     return store_null();
1247 #ifndef DBUG_OFF
1248   field_pos++;
1249 #endif
1250   char buff[MAX_FIELD_WIDTH];
1251   String str(buff,sizeof(buff), &my_charset_bin);
1252   CHARSET_INFO *tocs= this->thd->variables.character_set_results;
1253 #ifdef DBUG_ASSERT_EXISTS
1254   TABLE *table= field->table;
1255   MY_BITMAP *old_map= 0;
1256   if (table->file)
1257     old_map= dbug_tmp_use_all_columns(table, &table->read_set);
1258 #endif
1259 
1260   field->val_str(&str);
1261 #ifdef DBUG_ASSERT_EXISTS
1262   if (old_map)
1263     dbug_tmp_restore_column_map(&table->read_set, old_map);
1264 #endif
1265 
1266   return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
1267 }
1268 
1269 
store(MYSQL_TIME * tm,int decimals)1270 bool Protocol_text::store(MYSQL_TIME *tm, int decimals)
1271 {
1272 #ifndef DBUG_OFF
1273   DBUG_ASSERT(field_types == 0 ||
1274 	      field_types[field_pos] == MYSQL_TYPE_DATETIME ||
1275 	      field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
1276   field_pos++;
1277 #endif
1278   char buff[MAX_DATE_STRING_REP_LENGTH];
1279   uint length= my_datetime_to_str(tm, buff, decimals);
1280   return net_store_data((uchar*) buff, length);
1281 }
1282 
1283 
store_date(MYSQL_TIME * tm)1284 bool Protocol_text::store_date(MYSQL_TIME *tm)
1285 {
1286 #ifndef DBUG_OFF
1287   DBUG_ASSERT(field_types == 0 ||
1288 	      field_types[field_pos] == MYSQL_TYPE_DATE);
1289   field_pos++;
1290 #endif
1291   char buff[MAX_DATE_STRING_REP_LENGTH];
1292   size_t length= my_date_to_str(tm, buff);
1293   return net_store_data((uchar*) buff, length);
1294 }
1295 
1296 
store_time(MYSQL_TIME * tm,int decimals)1297 bool Protocol_text::store_time(MYSQL_TIME *tm, int decimals)
1298 {
1299 #ifndef DBUG_OFF
1300   DBUG_ASSERT(field_types == 0 ||
1301 	      field_types[field_pos] == MYSQL_TYPE_TIME);
1302   field_pos++;
1303 #endif
1304   char buff[MAX_DATE_STRING_REP_LENGTH];
1305   uint length= my_time_to_str(tm, buff, decimals);
1306   return net_store_data((uchar*) buff, length);
1307 }
1308 
1309 /**
1310   Assign OUT-parameters to user variables.
1311 
1312   @param sp_params  List of PS/SP parameters (both input and output).
1313 
1314   @return Error status.
1315     @retval FALSE Success.
1316     @retval TRUE  Error.
1317 */
1318 
send_out_parameters(List<Item_param> * sp_params)1319 bool Protocol_text::send_out_parameters(List<Item_param> *sp_params)
1320 {
1321   DBUG_ASSERT(sp_params->elements ==
1322               thd->lex->prepared_stmt_params.elements);
1323 
1324   List_iterator_fast<Item_param> item_param_it(*sp_params);
1325   List_iterator_fast<Item> param_it(thd->lex->prepared_stmt_params);
1326 
1327   while (true)
1328   {
1329     Item_param *item_param= item_param_it++;
1330     Item *param= param_it++;
1331     Settable_routine_parameter *sparam;
1332 
1333     if (!item_param || !param)
1334       break;
1335 
1336     if (!item_param->get_out_param_info())
1337       continue; // It's an IN-parameter.
1338 
1339     if (!(sparam= param->get_settable_routine_parameter()))
1340     {
1341       DBUG_ASSERT(0);
1342       continue;
1343     }
1344 
1345     DBUG_ASSERT(sparam->get_item_param() == NULL);
1346     sparam->set_value(thd, thd->spcont, reinterpret_cast<Item **>(&item_param));
1347   }
1348 
1349   return FALSE;
1350 }
1351 
1352 /****************************************************************************
1353   Functions to handle the binary protocol used with prepared statements
1354 
1355   Data format:
1356 
1357    [ok:1]                            reserved ok packet
1358    [null_field:(field_count+7+2)/8]  reserved to send null data. The size is
1359                                      calculated using:
1360                                      bit_fields= (field_count+7+2)/8;
1361                                      2 bits are reserved for identifying type
1362 				     of package.
1363    [[length]data]                    data field (the length applies only for
1364                                      string/binary/time/timestamp fields and
1365                                      rest of them are not sent as they have
1366                                      the default length that client understands
1367                                      based on the field type
1368    [..]..[[length]data]              data
1369 ****************************************************************************/
1370 
prepare_for_send(uint num_columns)1371 bool Protocol_binary::prepare_for_send(uint num_columns)
1372 {
1373   Protocol::prepare_for_send(num_columns);
1374   bit_fields= (field_count+9)/8;
1375   return packet->alloc(bit_fields+1);
1376 
1377   /* prepare_for_resend will be called after this one */
1378 }
1379 
1380 
prepare_for_resend()1381 void Protocol_binary::prepare_for_resend()
1382 {
1383   packet->length(bit_fields+1);
1384   bzero((uchar*) packet->ptr(), 1+bit_fields);
1385   field_pos=0;
1386 }
1387 
1388 
store(const char * from,size_t length,CHARSET_INFO * fromcs)1389 bool Protocol_binary::store(const char *from, size_t length,
1390                             CHARSET_INFO *fromcs)
1391 {
1392   CHARSET_INFO *tocs= thd->variables.character_set_results;
1393   field_pos++;
1394   return store_string_aux(from, length, fromcs, tocs);
1395 }
1396 
store(const char * from,size_t length,CHARSET_INFO * fromcs,CHARSET_INFO * tocs)1397 bool Protocol_binary::store(const char *from, size_t length,
1398                             CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
1399 {
1400   field_pos++;
1401   return store_string_aux(from, length, fromcs, tocs);
1402 }
1403 
store_null()1404 bool Protocol_binary::store_null()
1405 {
1406   uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));
1407   /* Room for this as it's allocated in prepare_for_send */
1408   char *to= (char*) packet->ptr()+offset;
1409   *to= (char) ((uchar) *to | (uchar) bit);
1410   field_pos++;
1411   return 0;
1412 }
1413 
1414 
store_tiny(longlong from)1415 bool Protocol_binary::store_tiny(longlong from)
1416 {
1417   char buff[1];
1418   field_pos++;
1419   buff[0]= (uchar) from;
1420   return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
1421 }
1422 
1423 
store_short(longlong from)1424 bool Protocol_binary::store_short(longlong from)
1425 {
1426   field_pos++;
1427   char *to= packet->prep_append(2, PACKET_BUFFER_EXTRA_ALLOC);
1428   if (!to)
1429     return 1;
1430   int2store(to, (int) from);
1431   return 0;
1432 }
1433 
1434 
store_long(longlong from)1435 bool Protocol_binary::store_long(longlong from)
1436 {
1437   field_pos++;
1438   char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
1439   if (!to)
1440     return 1;
1441   int4store(to, from);
1442   return 0;
1443 }
1444 
1445 
store_longlong(longlong from,bool unsigned_flag)1446 bool Protocol_binary::store_longlong(longlong from, bool unsigned_flag)
1447 {
1448   field_pos++;
1449   char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
1450   if (!to)
1451     return 1;
1452   int8store(to, from);
1453   return 0;
1454 }
1455 
store_decimal(const my_decimal * d)1456 bool Protocol_binary::store_decimal(const my_decimal *d)
1457 {
1458 #ifndef DBUG_OFF
1459   DBUG_ASSERT(field_types == 0 ||
1460               field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
1461   field_pos++;
1462 #endif
1463   char buff[DECIMAL_MAX_STR_LENGTH];
1464   String str(buff, sizeof(buff), &my_charset_bin);
1465   (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
1466   return store(str.ptr(), str.length(), str.charset());
1467 }
1468 
store(float from,uint32 decimals,String * buffer)1469 bool Protocol_binary::store(float from, uint32 decimals, String *buffer)
1470 {
1471   field_pos++;
1472   char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
1473   if (!to)
1474     return 1;
1475   float4store(to, from);
1476   return 0;
1477 }
1478 
1479 
store(double from,uint32 decimals,String * buffer)1480 bool Protocol_binary::store(double from, uint32 decimals, String *buffer)
1481 {
1482   field_pos++;
1483   char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
1484   if (!to)
1485     return 1;
1486   float8store(to, from);
1487   return 0;
1488 }
1489 
1490 
store(Field * field)1491 bool Protocol_binary::store(Field *field)
1492 {
1493   /*
1494     We should not increment field_pos here as send_binary() will call another
1495     protocol function to do this for us
1496   */
1497   if (field->is_null())
1498     return store_null();
1499   return field->send_binary(this);
1500 }
1501 
1502 
store(MYSQL_TIME * tm,int decimals)1503 bool Protocol_binary::store(MYSQL_TIME *tm, int decimals)
1504 {
1505   char buff[12],*pos;
1506   uint length;
1507   field_pos++;
1508   pos= buff+1;
1509 
1510   int2store(pos, tm->year);
1511   pos[2]= (uchar) tm->month;
1512   pos[3]= (uchar) tm->day;
1513   pos[4]= (uchar) tm->hour;
1514   pos[5]= (uchar) tm->minute;
1515   pos[6]= (uchar) tm->second;
1516   DBUG_ASSERT(decimals == AUTO_SEC_PART_DIGITS ||
1517               (decimals >= 0 && decimals <= TIME_SECOND_PART_DIGITS));
1518   if (decimals != AUTO_SEC_PART_DIGITS)
1519     my_time_trunc(tm, decimals);
1520   int4store(pos+7, tm->second_part);
1521   if (tm->second_part)
1522     length=11;
1523   else if (tm->hour || tm->minute || tm->second)
1524     length=7;
1525   else if (tm->year || tm->month || tm->day)
1526     length=4;
1527   else
1528     length=0;
1529   buff[0]=(char) length;			// Length is stored first
1530   return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
1531 }
1532 
store_date(MYSQL_TIME * tm)1533 bool Protocol_binary::store_date(MYSQL_TIME *tm)
1534 {
1535   tm->hour= tm->minute= tm->second=0;
1536   tm->second_part= 0;
1537   return Protocol_binary::store(tm, 0);
1538 }
1539 
1540 
store_time(MYSQL_TIME * tm,int decimals)1541 bool Protocol_binary::store_time(MYSQL_TIME *tm, int decimals)
1542 {
1543   char buff[13], *pos;
1544   uint length;
1545   field_pos++;
1546   pos= buff+1;
1547   pos[0]= tm->neg ? 1 : 0;
1548   if (tm->hour >= 24)
1549   {
1550     uint days= tm->hour/24;
1551     tm->hour-= days*24;
1552     tm->day+= days;
1553   }
1554   int4store(pos+1, tm->day);
1555   pos[5]= (uchar) tm->hour;
1556   pos[6]= (uchar) tm->minute;
1557   pos[7]= (uchar) tm->second;
1558   DBUG_ASSERT(decimals == AUTO_SEC_PART_DIGITS ||
1559               (decimals >= 0 && decimals <= TIME_SECOND_PART_DIGITS));
1560   if (decimals != AUTO_SEC_PART_DIGITS)
1561     my_time_trunc(tm, decimals);
1562   int4store(pos+8, tm->second_part);
1563   if (tm->second_part)
1564     length=12;
1565   else if (tm->hour || tm->minute || tm->second || tm->day)
1566     length=8;
1567   else
1568     length=0;
1569   buff[0]=(char) length;			// Length is stored first
1570   return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
1571 }
1572 
1573 /**
1574   Send a result set with OUT-parameter values by means of PS-protocol.
1575 
1576   @param sp_params  List of PS/SP parameters (both input and output).
1577 
1578   @return Error status.
1579     @retval FALSE Success.
1580     @retval TRUE  Error.
1581 */
1582 
send_out_parameters(List<Item_param> * sp_params)1583 bool Protocol_binary::send_out_parameters(List<Item_param> *sp_params)
1584 {
1585   bool ret;
1586   if (!(thd->client_capabilities & CLIENT_PS_MULTI_RESULTS))
1587   {
1588     /* The client does not support OUT-parameters. */
1589     return FALSE;
1590   }
1591 
1592   List<Item> out_param_lst;
1593 
1594   {
1595     List_iterator_fast<Item_param> item_param_it(*sp_params);
1596 
1597     while (true)
1598     {
1599       Item_param *item_param= item_param_it++;
1600 
1601       if (!item_param)
1602         break;
1603 
1604       if (!item_param->get_out_param_info())
1605         continue; // It's an IN-parameter.
1606 
1607       if (out_param_lst.push_back(item_param, thd->mem_root))
1608         return TRUE;
1609     }
1610   }
1611 
1612   if (!out_param_lst.elements)
1613     return FALSE;
1614 
1615   /*
1616     We have to set SERVER_PS_OUT_PARAMS in THD::server_status, because it
1617     is used in send_result_set_metadata().
1618   */
1619 
1620   thd->server_status|= SERVER_PS_OUT_PARAMS | SERVER_MORE_RESULTS_EXISTS;
1621 
1622   /* Send meta-data. */
1623   if (send_result_set_metadata(&out_param_lst, SEND_NUM_ROWS | SEND_EOF))
1624     return TRUE;
1625 
1626   /* Send data. */
1627 
1628   prepare_for_resend();
1629 
1630   if (send_result_set_row(&out_param_lst))
1631     return TRUE;
1632 
1633   if (write())
1634     return TRUE;
1635 
1636   ret= net_send_eof(thd, thd->server_status, 0);
1637 
1638   /*
1639     Reset server_status:
1640     - SERVER_MORE_RESULTS_EXISTS bit, because this is the last packet for sure.
1641     - Restore SERVER_PS_OUT_PARAMS status.
1642   */
1643   thd->server_status&= ~(SERVER_PS_OUT_PARAMS | SERVER_MORE_RESULTS_EXISTS);
1644 
1645   return ret ? FALSE : TRUE;
1646 }
1647