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