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