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