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