1 /* Copyright (c) 2000, 2021, Oracle and/or its affiliates.
2
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License, version 2.0,
5 as published by the Free Software Foundation.
6
7 This program is also distributed with certain software (including
8 but not limited to OpenSSL) that is licensed under separate terms,
9 as designated in a particular file or component or in included license
10 documentation. The authors of MySQL hereby grant you an additional
11 permission to link the program and your derivative works with the
12 separately licensed software that they have included with MySQL.
13
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License, version 2.0, for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
22
23 /**
24 @file
25
26 Low level functions for storing data to be send to the MySQL client.
27 The actual communication is handled by the net_xxx functions in net_serv.cc
28 */
29
30 #include "protocol_classic.h"
31 #include "sql_class.h" // THD
32 #include <stdarg.h>
33
34 using std::min;
35 using std::max;
36
37 static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
38 bool net_send_error_packet(THD *, uint, const char *, const char *);
39 bool net_send_error_packet(NET *, uint, const char *, const char *, bool,
40 ulong, const CHARSET_INFO*);
41 /* Declared non-static only because of the embedded library. */
42 bool net_send_ok(THD *, uint, uint, ulonglong, ulonglong, const char *, bool);
43 /* Declared non-static only because of the embedded library. */
44 bool net_send_eof(THD *thd, uint server_status, uint statement_warn_count);
45 #ifndef EMBEDDED_LIBRARY
46 static bool write_eof_packet(THD *, NET *, uint, uint);
47 #endif
48
49 #ifndef EMBEDDED_LIBRARY
net_store_data(const uchar * from,size_t length)50 bool Protocol_classic::net_store_data(const uchar *from, size_t length)
51 {
52 size_t 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->mem_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 #endif
66
67
68 /**
69 net_store_data() - extended version with character set conversion.
70
71 It is optimized for short strings whose length after
72 conversion is garanteed to be less than 251, which accupies
73 exactly one byte to store length. It allows not to use
74 the "convert" member as a temporary buffer, conversion
75 is done directly to the "packet" member.
76 The limit 251 is good enough to optimize send_result_set_metadata()
77 because column, table, database names fit into this limit.
78 */
79
80 #ifndef EMBEDDED_LIBRARY
net_store_data(const uchar * from,size_t length,const CHARSET_INFO * from_cs,const CHARSET_INFO * to_cs)81 bool Protocol_classic::net_store_data(const uchar *from, size_t length,
82 const CHARSET_INFO *from_cs,
83 const CHARSET_INFO *to_cs)
84 {
85 uint dummy_errors;
86 /* Calculate maxumum possible result length */
87 size_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
88 if (conv_length > 250)
89 {
90 /*
91 For strings with conv_length greater than 250 bytes
92 we don't know how many bytes we will need to store length: one or two,
93 because we don't know result length until conversion is done.
94 For example, when converting from utf8 (mbmaxlen=3) to latin1,
95 conv_length=300 means that the result length can vary between 100 to 300.
96 length=100 needs one byte, length=300 needs to bytes.
97
98 Thus conversion directly to "packet" is not worthy.
99 Let's use "convert" as a temporary buffer.
100 */
101 return (convert->copy((const char *) from, length, from_cs,
102 to_cs, &dummy_errors) ||
103 net_store_data((const uchar *) convert->ptr(), convert->length()));
104 }
105
106 size_t packet_length= packet->length();
107 size_t new_length= packet_length + conv_length + 1;
108
109 if (new_length > packet->alloced_length() && packet->mem_realloc(new_length))
110 return 1;
111
112 char *length_pos= (char *) packet->ptr() + packet_length;
113 char *to= length_pos + 1;
114
115 to+= copy_and_convert(to, conv_length, to_cs,
116 (const char *) from, length, from_cs, &dummy_errors);
117
118 net_store_length((uchar *) length_pos, to - length_pos - 1);
119 packet->length((uint) (to - packet->ptr()));
120 return 0;
121 }
122 #endif
123
124
125 /**
126 Send a error string to client.
127
128 Design note:
129
130 net_printf_error and net_send_error are low-level functions
131 that shall be used only when a new connection is being
132 established or at server startup.
133
134 For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
135 critical that every error that can be intercepted is issued in one
136 place only, my_message_sql.
137
138 @param thd Thread handler
139 @param sql_errno The error code to send
140 @param err A pointer to the error message
141
142 @return
143 @retval FALSE The message was sent to the client
144 @retval TRUE An error occurred and the message wasn't sent properly
145 */
146
net_send_error(THD * thd,uint sql_errno,const char * err)147 bool net_send_error(THD *thd, uint sql_errno, const char *err)
148 {
149 bool error;
150 DBUG_ENTER("net_send_error");
151
152 assert(!thd->sp_runtime_ctx);
153 assert(sql_errno);
154 assert(err);
155
156 DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
157
158 /*
159 It's one case when we can push an error even though there
160 is an OK or EOF already.
161 */
162 thd->get_stmt_da()->set_overwrite_status(true);
163
164 /* Abort multi-result sets */
165 thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
166
167 error= net_send_error_packet(thd, sql_errno, err,
168 mysql_errno_to_sqlstate(sql_errno));
169
170 thd->get_stmt_da()->set_overwrite_status(false);
171
172 DBUG_RETURN(error);
173 }
174
175
176 /**
177 Send a error string to client using net struct.
178 This is used initial connection handling code.
179
180 @param net Low-level net struct
181 @param sql_errno The error code to send
182 @param err A pointer to the error message
183
184 @return
185 @retval FALSE The message was sent to the client
186 @retval TRUE An error occurred and the message wasn't sent properly
187 */
188
189 #ifndef EMBEDDED_LIBRARY
net_send_error(NET * net,uint sql_errno,const char * err)190 bool net_send_error(NET *net, uint sql_errno, const char *err)
191 {
192 DBUG_ENTER("net_send_error");
193
194 assert(sql_errno && err);
195
196 DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
197
198 bool error=
199 net_send_error_packet(net, sql_errno, err,
200 mysql_errno_to_sqlstate(sql_errno), false, 0,
201 global_system_variables.character_set_results);
202
203 DBUG_RETURN(error);
204 }
205
206
207 /**
208 Return OK to the client.
209
210 The OK packet has the following structure:
211
212 Here 'n' denotes the length of state change information.
213
214 Bytes Name
215 ----- ----
216 1 [00] or [FE] the OK header
217 [FE] is used as header for result set rows
218 1-9 (lenenc-int) affected rows
219 1-9 (lenenc-int) last-insert-id
220
221 if capabilities & CLIENT_PROTOCOL_41 {
222 2 status_flags; Copy of thd->server_status; Can be used
223 by client to check if we are inside a transaction.
224 2 warnings (New in 4.1 protocol)
225 } elseif capabilities & CLIENT_TRANSACTIONS {
226 2 status_flags
227 }
228
229 if capabilities & CLIENT_ACCEPTS_SERVER_STATUS_CHANGE_INFO {
230 1-9(lenenc_str) info (message); Stored as length of the message string +
231 message.
232 if n > 0 {
233 1-9 (lenenc_int) total length of session state change
234 information to follow (= n)
235 n session state change information
236 }
237 }
238 else {
239 string[EOF] info (message); Stored as packed length (1-9 bytes) +
240 message. Is not stored if no message.
241 }
242
243 @param thd Thread handler
244 @param server_status The server status
245 @param statement_warn_count Total number of warnings
246 @param affected_rows Number of rows changed by statement
247 @param id Auto_increment id for first row (if used)
248 @param message Message to send to the client
249 (Used by mysql_status)
250 @param eof_indentifier when true [FE] will be set in OK header
251 else [00] will be used
252
253 @return
254 @retval FALSE The message was successfully sent
255 @retval TRUE An error occurred and the messages wasn't sent properly
256 */
257
258 bool
net_send_ok(THD * thd,uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong id,const char * message,bool eof_identifier)259 net_send_ok(THD *thd,
260 uint server_status, uint statement_warn_count,
261 ulonglong affected_rows, ulonglong id, const char *message,
262 bool eof_identifier)
263 {
264 Protocol *protocol= thd->get_protocol();
265 NET *net= thd->get_protocol_classic()->get_net();
266 uchar buff[MYSQL_ERRMSG_SIZE + 10];
267 uchar *pos, *start;
268
269 /*
270 To be used to manage the data storage in case session state change
271 information is present.
272 */
273 String store;
274 bool state_changed= false;
275
276 bool error= FALSE;
277 DBUG_ENTER("net_send_ok");
278
279 if (! net->vio) // hack for re-parsing queries
280 {
281 DBUG_PRINT("info", ("vio present: NO"));
282 DBUG_RETURN(FALSE);
283 }
284
285 start= buff;
286
287 /*
288 Use 0xFE packet header if eof_identifier is true
289 unless we are talking to old client
290 */
291 if (eof_identifier &&
292 (protocol->has_client_capability(CLIENT_DEPRECATE_EOF)))
293 buff[0]= 254;
294 else
295 buff[0]= 0;
296
297 /* affected rows */
298 pos= net_store_length(buff + 1, affected_rows);
299
300 /* last insert id */
301 pos= net_store_length(pos, id);
302
303 if (protocol->has_client_capability(CLIENT_SESSION_TRACK) &&
304 thd->session_tracker.enabled_any() &&
305 thd->session_tracker.changed_any())
306 {
307 server_status |= SERVER_SESSION_STATE_CHANGED;
308 state_changed= true;
309 }
310
311 if (protocol->has_client_capability(CLIENT_PROTOCOL_41))
312 {
313 DBUG_PRINT("info",
314 ("affected_rows: %lu id: %lu status: %u warning_count: %u",
315 (ulong) affected_rows,
316 (ulong) id,
317 (uint) (server_status & 0xffff),
318 (uint) statement_warn_count));
319 /* server status */
320 int2store(pos, server_status);
321 pos+= 2;
322
323 /* warning count: we can only return up to 65535 warnings in two bytes. */
324 uint tmp= min(statement_warn_count, 65535U);
325 int2store(pos, tmp);
326 pos+= 2;
327 }
328 else if (net->return_status) // For 4.0 protocol
329 {
330 int2store(pos, server_status);
331 pos+=2;
332 }
333
334 thd->get_stmt_da()->set_overwrite_status(true);
335
336 if (protocol->has_client_capability(CLIENT_SESSION_TRACK))
337 {
338 /* the info field */
339 if (state_changed || (message && message[0]))
340 pos= net_store_data(pos, (uchar*) message, message ? strlen(message) : 0);
341 /* session state change information */
342 if (unlikely(state_changed))
343 {
344 store.set_charset(thd->variables.collation_database);
345
346 /*
347 First append the fields collected so far. In case of malloc, memory
348 for message is also allocated here.
349 */
350 store.append((const char *)start, (pos - start), MYSQL_ERRMSG_SIZE);
351
352 /* .. and then the state change information. */
353 thd->session_tracker.store(thd, store);
354
355 start= (uchar *) store.ptr();
356 pos= start+store.length();
357 }
358 }
359 else if (message && message[0])
360 {
361 /* the info field, if there is a message to store */
362 pos= net_store_data(pos, (uchar*) message, strlen(message));
363 }
364
365 /* OK packet length will be restricted to 16777215 bytes */
366 if (((size_t) (pos - start)) > MAX_PACKET_LENGTH)
367 {
368 net->error= 1;
369 net->last_errno= ER_NET_OK_PACKET_TOO_LARGE;
370 my_error(ER_NET_OK_PACKET_TOO_LARGE, MYF(0));
371 DBUG_PRINT("info", ("OK packet too large"));
372 DBUG_RETURN(1);
373 }
374 error= my_net_write(net, start, (size_t) (pos - start));
375 if (!error)
376 error= net_flush(net);
377
378 thd->get_stmt_da()->set_overwrite_status(false);
379 DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
380
381 DBUG_RETURN(error);
382 }
383
384 static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
385
386
387 /**
388 Send eof (= end of result set) to the client.
389
390 The eof packet has the following structure:
391
392 - 254 : Marker (1 byte)
393 - warning_count : Stored in 2 bytes; New in 4.1 protocol
394 - status_flag : Stored in 2 bytes;
395 For flags like SERVER_MORE_RESULTS_EXISTS.
396
397 Note that the warning count will not be sent if 'no_flush' is set as
398 we don't want to report the warning count until all data is sent to the
399 client.
400
401 @param thd Thread handler
402 @param server_status The server status
403 @param statement_warn_count Total number of warnings
404
405 @return
406 @retval FALSE The message was successfully sent
407 @retval TRUE An error occurred and the message wasn't sent properly
408 */
409
410 bool
net_send_eof(THD * thd,uint server_status,uint statement_warn_count)411 net_send_eof(THD *thd, uint server_status, uint statement_warn_count)
412 {
413 NET *net= thd->get_protocol_classic()->get_net();
414 bool error= FALSE;
415 DBUG_ENTER("net_send_eof");
416 /* Set to TRUE if no active vio, to work well in case of --init-file */
417 if (net->vio != 0)
418 {
419 thd->get_stmt_da()->set_overwrite_status(true);
420 error= write_eof_packet(thd, net, server_status, statement_warn_count);
421 if (!error)
422 error= net_flush(net);
423 thd->get_stmt_da()->set_overwrite_status(false);
424 DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
425 }
426 DBUG_RETURN(error);
427 }
428
429
430 /**
431 Format EOF packet according to the current protocol and
432 write it to the network output buffer.
433
434 @param thd The thread handler
435 @param net The network handler
436 @param server_status The server status
437 @param statement_warn_count The number of warnings
438
439
440 @return
441 @retval FALSE The message was sent successfully
442 @retval TRUE An error occurred and the messages wasn't sent properly
443 */
444
write_eof_packet(THD * thd,NET * net,uint server_status,uint statement_warn_count)445 static bool write_eof_packet(THD *thd, NET *net,
446 uint server_status,
447 uint statement_warn_count)
448 {
449 bool error;
450 Protocol *protocol= thd->get_protocol();
451 if (protocol->has_client_capability(CLIENT_PROTOCOL_41))
452 {
453 uchar buff[5];
454 /*
455 Don't send warn count during SP execution, as the warn_list
456 is cleared between substatements, and mysqltest gets confused
457 */
458 uint tmp= min(statement_warn_count, 65535U);
459 buff[0]= 254;
460 int2store(buff+1, tmp);
461 /*
462 The following test should never be true, but it's better to do it
463 because if 'is_fatal_error' is set the server is not going to execute
464 other queries (see the if test in dispatch_command / COM_QUERY)
465 */
466 if (thd->is_fatal_error)
467 server_status&= ~SERVER_MORE_RESULTS_EXISTS;
468 int2store(buff + 3, server_status);
469 error= my_net_write(net, buff, 5);
470 }
471 else
472 error= my_net_write(net, eof_buff, 1);
473
474 return error;
475 }
476
477
478 /**
479 @param thd Thread handler
480 @param sql_errno The error code to send
481 @param err A pointer to the error message
482 @param sqlstate SQL state
483
484 @return
485 @retval FALSE The message was successfully sent
486 @retval TRUE An error occurred and the messages wasn't sent properly
487 */
488
net_send_error_packet(THD * thd,uint sql_errno,const char * err,const char * sqlstate)489 bool net_send_error_packet(THD *thd, uint sql_errno, const char *err,
490 const char* sqlstate)
491 {
492 return net_send_error_packet(thd->get_protocol_classic()->get_net(),
493 sql_errno, err, sqlstate, thd->bootstrap,
494 thd->get_protocol()->get_client_capabilities(),
495 thd->variables.character_set_results);
496 }
497
498
499 /**
500 @param net Low-level NET struct
501 @param sql_errno The error code to send
502 @param err A pointer to the error message
503 @param sqlstate SQL state
504 @param bootstrap Server is started in bootstrap mode
505 @param client_capabilities Client capabilities flag
506 @param character_set_results Char set info
507
508 @return
509 @retval FALSE The message was successfully sent
510 @retval TRUE An error occurred and the messages wasn't sent properly
511 */
512
net_send_error_packet(NET * net,uint sql_errno,const char * err,const char * sqlstate,bool bootstrap,ulong client_capabilities,const CHARSET_INFO * character_set_results)513 bool net_send_error_packet(NET* net, uint sql_errno, const char *err,
514 const char* sqlstate, bool bootstrap,
515 ulong client_capabilities,
516 const CHARSET_INFO* character_set_results)
517 {
518 uint length;
519 /*
520 buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512
521 */
522 uint error;
523 char converted_err[MYSQL_ERRMSG_SIZE];
524 char buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos;
525
526 DBUG_ENTER("net_send_error_packet");
527
528 if (net->vio == 0)
529 {
530 if (bootstrap)
531 {
532 /* In bootstrap it's ok to print on stderr */
533 my_message_local(ERROR_LEVEL, "%d %s", sql_errno, err);
534 }
535 DBUG_RETURN(FALSE);
536 }
537
538 int2store(buff,sql_errno);
539 pos= buff+2;
540 if (client_capabilities & CLIENT_PROTOCOL_41)
541 {
542 /* The first # is to make the protocol backward compatible */
543 buff[2]= '#';
544 pos= my_stpcpy(buff+3, sqlstate);
545 }
546
547 convert_error_message(converted_err, sizeof(converted_err),
548 character_set_results, err,
549 strlen(err), system_charset_info, &error);
550 /* Converted error message is always null-terminated. */
551 length= (uint) (strmake(pos, converted_err, MYSQL_ERRMSG_SIZE - 1) - buff);
552
553 DBUG_RETURN(net_write_command(net,(uchar) 255, (uchar *) "", 0,
554 (uchar *) buff, length));
555 }
556 #endif /* EMBEDDED_LIBRARY */
557
558
559 /**
560 Faster net_store_length when we know that length is less than 65536.
561 We keep a separate version for that range because it's widely used in
562 libmysql.
563
564 uint is used as agrument type because of MySQL type conventions:
565 - uint for 0..65536
566 - ulong for 0..4294967296
567 - ulonglong for bigger numbers.
568 */
569
net_store_length_fast(uchar * packet,size_t length)570 static uchar *net_store_length_fast(uchar *packet, size_t length)
571 {
572 if (length < 251)
573 {
574 *packet=(uchar) length;
575 return packet+1;
576 }
577 *packet++=252;
578 int2store(packet,(uint) length);
579 return packet+2;
580 }
581
582
583 /****************************************************************************
584 Functions used by the protocol functions (like net_send_ok) to store
585 strings and numbers in the header result packet.
586 ****************************************************************************/
587
588 /* The following will only be used for short strings < 65K */
589
net_store_data(uchar * to,const uchar * from,size_t length)590 uchar *net_store_data(uchar *to, const uchar *from, size_t length)
591 {
592 to=net_store_length_fast(to,length);
593 memcpy(to,from,length);
594 return to+length;
595 }
596
597
net_store_data(uchar * to,int32 from)598 uchar *net_store_data(uchar *to, int32 from)
599 {
600 char buff[20];
601 uint length= (uint)(int10_to_str(from, buff, 10) - buff);
602 to= net_store_length_fast(to, length);
603 memcpy(to, buff, length);
604 return to + length;
605 }
606
607
net_store_data(uchar * to,longlong from)608 uchar *net_store_data(uchar *to, longlong from)
609 {
610 char buff[22];
611 uint length= (uint)(longlong10_to_str(from, buff, 10) - buff);
612 to= net_store_length_fast(to, length);
613 memcpy(to, buff, length);
614 return to + length;
615 }
616
617
618 /*****************************************************************************
619 Protocol_classic functions
620 *****************************************************************************/
621
init(THD * thd_arg)622 void Protocol_classic::init(THD *thd_arg)
623 {
624 m_thd= thd_arg;
625 packet= &m_thd->packet;
626 convert= &m_thd->convert_buffer;
627 #ifndef NDEBUG
628 field_types= 0;
629 #endif
630 }
631
632
633 /**
634 A default implementation of "OK" packet response to the client.
635
636 Currently this implementation is re-used by both network-oriented
637 protocols -- the binary and text one. They do not differ
638 in their OK packet format, which allows for a significant simplification
639 on client side.
640 */
641
642 bool
send_ok(uint server_status,uint statement_warn_count,ulonglong affected_rows,ulonglong last_insert_id,const char * message)643 Protocol_classic::send_ok(uint server_status, uint statement_warn_count,
644 ulonglong affected_rows, ulonglong last_insert_id,
645 const char *message)
646 {
647 DBUG_ENTER("Protocol_classic::send_ok");
648 const bool retval=
649 net_send_ok(m_thd, server_status, statement_warn_count,
650 affected_rows, last_insert_id, message, false);
651 DBUG_RETURN(retval);
652 }
653
654
655 /**
656 A default implementation of "EOF" packet response to the client.
657
658 Binary and text protocol do not differ in their EOF packet format.
659 */
660
send_eof(uint server_status,uint statement_warn_count)661 bool Protocol_classic::send_eof(uint server_status, uint statement_warn_count)
662 {
663 DBUG_ENTER("Protocol_classic::send_eof");
664 bool retval;
665 /*
666 Normally end of statement reply is signaled by OK packet, but in case
667 of binlog dump request an EOF packet is sent instead. Also, old clients
668 expect EOF packet instead of OK
669 */
670 #ifndef EMBEDDED_LIBRARY
671 if (has_client_capability(CLIENT_DEPRECATE_EOF) &&
672 (m_thd->get_command() != COM_BINLOG_DUMP &&
673 m_thd->get_command() != COM_BINLOG_DUMP_GTID))
674 retval= net_send_ok(m_thd, server_status, statement_warn_count, 0, 0, NULL,
675 true);
676 else
677 #endif
678 retval= net_send_eof(m_thd, server_status, statement_warn_count);
679 DBUG_RETURN(retval);
680 }
681
682
683 /**
684 A default implementation of "ERROR" packet response to the client.
685
686 Binary and text protocol do not differ in ERROR packet format.
687 */
688
send_error(uint sql_errno,const char * err_msg,const char * sql_state)689 bool Protocol_classic::send_error(uint sql_errno, const char *err_msg,
690 const char *sql_state)
691 {
692 DBUG_ENTER("Protocol_classic::send_error");
693 const bool retval= net_send_error_packet(m_thd, sql_errno, err_msg, sql_state);
694 DBUG_RETURN(retval);
695 }
696
697
set_read_timeout(ulong read_timeout)698 void Protocol_classic::set_read_timeout(ulong read_timeout)
699 {
700 my_net_set_read_timeout(&m_thd->net, read_timeout);
701 }
702
703
set_write_timeout(ulong write_timeout)704 void Protocol_classic::set_write_timeout(ulong write_timeout)
705 {
706 my_net_set_write_timeout(&m_thd->net, write_timeout);
707 }
708
709
710 // NET interaction functions
init_net(Vio * vio)711 bool Protocol_classic::init_net(Vio *vio)
712 {
713 return my_net_init(&m_thd->net, vio);
714 }
715
claim_memory_ownership()716 void Protocol_classic::claim_memory_ownership()
717 {
718 net_claim_memory_ownership(&m_thd->net);
719 }
720
end_net()721 void Protocol_classic::end_net()
722 {
723 assert(m_thd->net.buff);
724 net_end(&m_thd->net);
725 m_thd->net.vio= NULL;
726 }
727
728
flush_net()729 bool Protocol_classic::flush_net()
730 {
731 return net_flush(&m_thd->net);
732 }
733
734
write(const uchar * ptr,size_t len)735 bool Protocol_classic::write(const uchar *ptr, size_t len)
736 {
737 return my_net_write(&m_thd->net, ptr, len);
738 }
739
740
get_error()741 uchar Protocol_classic::get_error()
742 {
743 return m_thd->net.error;
744 }
745
746
get_last_errno()747 uint Protocol_classic::get_last_errno()
748 {
749 return m_thd->net.last_errno;
750 }
751
752
set_last_errno(uint err)753 void Protocol_classic::set_last_errno(uint err)
754 {
755 m_thd->net.last_errno= err;
756 }
757
758
get_last_error()759 char *Protocol_classic::get_last_error()
760 {
761 return m_thd->net.last_error;
762 }
763
764
wipe_net()765 void Protocol_classic::wipe_net()
766 {
767 memset(&m_thd->net, 0, sizeof(m_thd->net));
768 }
769
770
set_max_packet_size(ulong max_packet_size)771 void Protocol_classic::set_max_packet_size(ulong max_packet_size)
772 {
773 m_thd->net.max_packet_size= max_packet_size;
774 }
775
776
get_net()777 NET *Protocol_classic::get_net()
778 {
779 return &m_thd->net;
780 }
781
782
get_vio()783 Vio *Protocol_classic::get_vio()
784 {
785 return m_thd->net.vio;
786 }
787
set_vio(Vio * vio)788 void Protocol_classic::set_vio(Vio *vio)
789 {
790 m_thd->net.vio= vio;
791 }
792
793
set_pkt_nr(uint pkt_nr)794 void Protocol_classic::set_pkt_nr(uint pkt_nr)
795 {
796 m_thd->net.pkt_nr= pkt_nr;
797 }
798
799
get_pkt_nr()800 uint Protocol_classic::get_pkt_nr()
801 {
802 return m_thd->net.pkt_nr;
803 }
804
805
get_packet()806 String *Protocol_classic::get_packet()
807 {
808 return &m_thd->packet;
809 }
810
811
read_packet()812 int Protocol_classic::read_packet()
813 {
814 int ret;
815 if ((packet_length= my_net_read(&m_thd->net)) &&
816 packet_length != packet_error)
817 {
818 assert(!m_thd->net.error);
819 bad_packet= false;
820 raw_packet= m_thd->net.read_pos;
821 return 0;
822 }
823 else if (m_thd->net.error == 3)
824 ret= 1;
825 else
826 ret= -1;
827 bad_packet= true;
828 return ret;
829 }
830
831
parse_packet(union COM_DATA * data,enum_server_command cmd)832 bool Protocol_classic::parse_packet(union COM_DATA *data,
833 enum_server_command cmd)
834 {
835 switch(cmd)
836 {
837 case COM_INIT_DB:
838 {
839 data->com_init_db.db_name= reinterpret_cast<const char*>(raw_packet);
840 data->com_init_db.length= packet_length;
841 break;
842 }
843 case COM_REFRESH:
844 {
845 if (packet_length < 1)
846 goto malformed;
847 data->com_refresh.options= raw_packet[0];
848 break;
849 }
850 case COM_SHUTDOWN:
851 {
852 data->com_shutdown.level= packet_length == 0 ?
853 SHUTDOWN_DEFAULT : (enum mysql_enum_shutdown_level) raw_packet[0];
854 break;
855 }
856 case COM_PROCESS_KILL:
857 {
858 if (packet_length < 4)
859 goto malformed;
860 data->com_kill.id= (ulong) uint4korr(raw_packet);
861 break;
862 }
863 case COM_SET_OPTION:
864 {
865 if (packet_length < 2)
866 goto malformed;
867 data->com_set_option.opt_command= uint2korr(raw_packet);
868 break;
869 }
870 case COM_STMT_EXECUTE:
871 {
872 if (packet_length < 9)
873 goto malformed;
874 data->com_stmt_execute.stmt_id= uint4korr(raw_packet);
875 data->com_stmt_execute.flags= (ulong) raw_packet[4];
876 /* stmt_id + 5 bytes of flags */
877 /*
878 FIXME: params have to be parsed into an array/structure
879 by protocol too
880 */
881 data->com_stmt_execute.params= raw_packet + 9;
882 data->com_stmt_execute.params_length= packet_length - 9;
883 break;
884 }
885 case COM_STMT_FETCH:
886 {
887 if (packet_length < 8)
888 goto malformed;
889 data->com_stmt_fetch.stmt_id= uint4korr(raw_packet);
890 data->com_stmt_fetch.num_rows= uint4korr(raw_packet + 4);
891 break;
892 }
893 case COM_STMT_SEND_LONG_DATA:
894 {
895 #ifndef EMBEDDED_LIBRARY
896 if (packet_length < MYSQL_LONG_DATA_HEADER)
897 goto malformed;
898 #endif
899 data->com_stmt_send_long_data.stmt_id= uint4korr(raw_packet);
900 data->com_stmt_send_long_data.param_number= uint2korr(raw_packet + 4);
901 data->com_stmt_send_long_data.longdata= raw_packet + 6;
902 data->com_stmt_send_long_data.length= packet_length - 6;
903 break;
904 }
905 case COM_STMT_PREPARE:
906 {
907 data->com_stmt_prepare.query= reinterpret_cast<const char*>(raw_packet);
908 data->com_stmt_prepare.length= packet_length;
909 break;
910 }
911 case COM_STMT_CLOSE:
912 {
913 if (packet_length < 4)
914 goto malformed;
915
916 data->com_stmt_close.stmt_id= uint4korr(raw_packet);
917 break;
918 }
919 case COM_STMT_RESET:
920 {
921 if (packet_length < 4)
922 goto malformed;
923
924 data->com_stmt_reset.stmt_id= uint4korr(raw_packet);
925 break;
926 }
927 case COM_QUERY:
928 {
929 data->com_query.query= reinterpret_cast<const char*>(raw_packet);
930 data->com_query.length= packet_length;
931 break;
932 }
933 case COM_FIELD_LIST:
934 {
935 /*
936 We have name + wildcard in packet, separated by endzero
937 */
938 data->com_field_list.table_name= raw_packet;
939 uint len= data->com_field_list.table_name_length=
940 strend((char *)raw_packet) - (char *)raw_packet;
941 if (len >= packet_length || len > NAME_LEN)
942 goto malformed;
943 data->com_field_list.query= raw_packet + len + 1;
944 data->com_field_list.query_length= packet_length - len;
945 break;
946 }
947 default:
948 break;
949 }
950
951 return false;
952
953 malformed:
954 my_error(ER_MALFORMED_PACKET, MYF(0));
955 bad_packet= true;
956 return true;
957 }
958
create_command(COM_DATA * com_data,enum_server_command cmd,uchar * pkt,size_t length)959 bool Protocol_classic::create_command(COM_DATA *com_data,
960 enum_server_command cmd,
961 uchar *pkt, size_t length)
962 {
963 raw_packet= pkt;
964 packet_length= length;
965
966 return parse_packet(com_data, cmd);
967 }
968
get_command(COM_DATA * com_data,enum_server_command * cmd)969 int Protocol_classic::get_command(COM_DATA *com_data, enum_server_command *cmd)
970 {
971 // read packet from the network
972 if(int rc= read_packet())
973 return rc;
974
975 /*
976 'packet_length' contains length of data, as it was stored in packet
977 header. In case of malformed header, my_net_read returns zero.
978 If packet_length is not zero, my_net_read ensures that the returned
979 number of bytes was actually read from network.
980 There is also an extra safety measure in my_net_read:
981 it sets packet[packet_length]= 0, but only for non-zero packets.
982 */
983 if (packet_length == 0) /* safety */
984 {
985 /* Initialize with COM_SLEEP packet */
986 raw_packet[0]= (uchar) COM_SLEEP;
987 packet_length= 1;
988 }
989 /* Do not rely on my_net_read, extra safety against programming errors. */
990 raw_packet[packet_length]= '\0'; /* safety */
991
992 *cmd= (enum enum_server_command) raw_packet[0];
993
994 if (*cmd >= COM_END)
995 *cmd= COM_END; // Wrong command
996
997 assert(packet_length);
998 // Skip 'command'
999 packet_length--;
1000 raw_packet++;
1001
1002 return parse_packet(com_data, *cmd);
1003 }
1004
get_rw_status()1005 uint Protocol_classic::get_rw_status()
1006 {
1007 return m_thd->net.reading_or_writing;
1008 }
1009
1010 /**
1011 Finish the result set with EOF packet, as is expected by the client,
1012 if there is an error evaluating the next row and a continue handler
1013 for the error.
1014 */
1015
end_partial_result_set()1016 void Protocol_classic::end_partial_result_set()
1017 {
1018 net_send_eof(m_thd, m_thd->server_status,
1019 0 /* no warnings, we're inside SP */);
1020 }
1021
1022
flush()1023 bool Protocol_classic::flush()
1024 {
1025 #ifndef EMBEDDED_LIBRARY
1026 bool error;
1027 m_thd->get_stmt_da()->set_overwrite_status(true);
1028 error= net_flush(&m_thd->net);
1029 m_thd->get_stmt_da()->set_overwrite_status(false);
1030 return error;
1031 #else
1032 return 0;
1033 #endif
1034 }
1035
1036
get_compression()1037 bool Protocol_classic::get_compression()
1038 {
1039 return m_thd->net.compress;
1040 }
1041
1042
1043 #ifndef EMBEDDED_LIBRARY
1044 bool
start_result_metadata(uint num_cols,uint flags,const CHARSET_INFO * cs)1045 Protocol_classic::start_result_metadata(uint num_cols, uint flags,
1046 const CHARSET_INFO *cs)
1047 {
1048 DBUG_ENTER("Protocol_classic::start_result_metadata");
1049 DBUG_PRINT("info", ("num_cols %u, flags %u", num_cols, flags));
1050 result_cs= (CHARSET_INFO *) cs;
1051 send_metadata= true;
1052 field_count= num_cols;
1053 sending_flags= flags;
1054 if (flags & Protocol::SEND_NUM_ROWS)
1055 {
1056 ulonglong tmp;
1057 uchar *pos = net_store_length((uchar *) &tmp, num_cols);
1058 my_net_write(&m_thd->net, (uchar *) &tmp, (size_t) (pos - ((uchar *) &tmp)));
1059 }
1060 #ifndef NDEBUG
1061 field_types= (enum_field_types*) m_thd->alloc(sizeof(field_types) * num_cols);
1062 count= 0;
1063 #endif
1064
1065 DBUG_RETURN(false);
1066 }
1067
1068
1069 bool
end_result_metadata()1070 Protocol_classic::end_result_metadata()
1071 {
1072 DBUG_ENTER("Protocol_classic::end_result_metadata");
1073 DBUG_PRINT("info", ("num_cols %u, flags %u", field_count, sending_flags));
1074 send_metadata= false;
1075 if (sending_flags & SEND_EOF)
1076 {
1077 /* if it is new client do not send EOF packet */
1078 if (!(has_client_capability(CLIENT_DEPRECATE_EOF)))
1079 {
1080 /*
1081 Mark the end of meta-data result set, and store m_thd->server_status,
1082 to show that there is no cursor.
1083 Send no warning information, as it will be sent at statement end.
1084 */
1085 if (write_eof_packet(m_thd, &m_thd->net, m_thd->server_status,
1086 m_thd->get_stmt_da()->current_statement_cond_count()))
1087 {
1088 DBUG_RETURN(true);
1089 }
1090 }
1091 }
1092 DBUG_RETURN(false);
1093 }
1094
1095
send_field_metadata(Send_field * field,const CHARSET_INFO * item_charset)1096 bool Protocol_classic::send_field_metadata(Send_field *field,
1097 const CHARSET_INFO *item_charset)
1098 {
1099 DBUG_ENTER("Protocol_classic::send_field_metadata");
1100 char *pos;
1101 const CHARSET_INFO *cs= system_charset_info;
1102 const CHARSET_INFO *thd_charset= m_thd->variables.character_set_results;
1103
1104 /* Keep things compatible for old clients */
1105 if (field->type == MYSQL_TYPE_VARCHAR)
1106 field->type= MYSQL_TYPE_VAR_STRING;
1107
1108 send_metadata= true;
1109 if (has_client_capability(CLIENT_PROTOCOL_41))
1110 {
1111 if (store(STRING_WITH_LEN("def"), cs) ||
1112 store(field->db_name, strlen(field->db_name), cs) ||
1113 store(field->table_name, strlen(field->table_name), cs) ||
1114 store(field->org_table_name, strlen(field->org_table_name), cs) ||
1115 store(field->col_name, strlen(field->col_name), cs) ||
1116 store(field->org_col_name, strlen(field->org_col_name), cs) ||
1117 packet->mem_realloc(packet->length() + 12))
1118 {
1119 send_metadata= false;
1120 return true;
1121 }
1122 /* Store fixed length fields */
1123 pos= (char *) packet->ptr() + packet->length();
1124 *pos++= 12; // Length of packed fields
1125 /* inject a NULL to test the client */
1126 DBUG_EXECUTE_IF("poison_rs_fields", pos[-1]= (char) 0xfb;);
1127 if (item_charset == &my_charset_bin || thd_charset == NULL)
1128 {
1129 /* No conversion */
1130 int2store(pos, item_charset->number);
1131 int4store(pos + 2, field->length);
1132 }
1133 else
1134 {
1135 /* With conversion */
1136 uint32 field_length, max_length;
1137 int2store(pos, thd_charset->number);
1138 /*
1139 For TEXT/BLOB columns, field_length describes the maximum data
1140 length in bytes. There is no limit to the number of characters
1141 that a TEXT column can store, as long as the data fits into
1142 the designated space.
1143 For the rest of textual columns, field_length is evaluated as
1144 char_count * mbmaxlen, where character count is taken from the
1145 definition of the column. In other words, the maximum number
1146 of characters here is limited by the column definition.
1147
1148 When one has a LONG TEXT column with a single-byte
1149 character set, and the connection character set is multi-byte, the
1150 client may get fields longer than UINT_MAX32, due to
1151 <character set column> -> <character set connection> conversion.
1152 In that case column max length does not fit into the 4 bytes
1153 reserved for it in the protocol.
1154 */
1155 max_length= (field->type >= MYSQL_TYPE_TINY_BLOB &&
1156 field->type <= MYSQL_TYPE_BLOB) ?
1157 field->length / item_charset->mbminlen :
1158 field->length / item_charset->mbmaxlen;
1159 field_length= char_to_byte_length_safe(max_length, thd_charset->mbmaxlen);
1160 int4store(pos + 2, field_length);
1161 }
1162 pos[6]= field->type;
1163 int2store(pos + 7, field->flags);
1164 pos[9]= (char) field->decimals;
1165 pos[10]= 0; // For the future
1166 pos[11]= 0; // For the future
1167 pos+= 12;
1168 }
1169 else
1170 {
1171 if (store(field->table_name, strlen(field->table_name), cs) ||
1172 store(field->col_name, strlen(field->col_name), cs) ||
1173 packet->mem_realloc(packet->length() + 10))
1174 {
1175 send_metadata= false;
1176 return true;
1177 }
1178 pos= (char *) packet->ptr() + packet->length();
1179 pos[0]= 3;
1180 int3store(pos + 1, field->length);
1181 pos[4]= 1;
1182 pos[5]= field->type;
1183 pos[6]= 3;
1184 int2store(pos + 7, field->flags);
1185 pos[9]= (char) field->decimals;
1186 pos+= 10;
1187 }
1188 packet->length((uint) (pos - packet->ptr()));
1189
1190 #ifndef NDEBUG
1191 // TODO: this should be protocol-dependent, as it records incorrect type
1192 // for binary protocol
1193 // Text protocol sends fields as varchar
1194 field_types[count++]= field->field ? MYSQL_TYPE_VAR_STRING : field->type;
1195 #endif
1196 DBUG_RETURN(false);
1197 }
1198
1199
end_row()1200 bool Protocol_classic::end_row()
1201 {
1202 DBUG_ENTER("Protocol_classic::end_row");
1203 if (m_thd->get_protocol()->connection_alive())
1204 DBUG_RETURN(my_net_write(&m_thd->net, (uchar *) packet->ptr(),
1205 packet->length()));
1206 DBUG_RETURN(0);
1207 }
1208 #endif /* EMBEDDED_LIBRARY */
1209
1210
1211 /**
1212 Send a set of strings as one long string with ',' in between.
1213 */
1214
store(Protocol * prot,I_List<i_string> * str_list)1215 bool store(Protocol *prot, I_List<i_string>* str_list)
1216 {
1217 char buf[256];
1218 String tmp(buf, sizeof(buf), &my_charset_bin);
1219 size_t len;
1220 I_List_iterator<i_string> it(*str_list);
1221 i_string* s;
1222
1223 tmp.length(0);
1224 while ((s=it++))
1225 {
1226 tmp.append(s->ptr);
1227 tmp.append(',');
1228 }
1229 if ((len= tmp.length()))
1230 len--; // Remove last ','
1231 return prot->store((char *) tmp.ptr(), len, tmp.charset());
1232 }
1233
1234 /****************************************************************************
1235 Functions to handle the simple (default) protocol where everything is
1236 This protocol is the one that is used by default between the MySQL server
1237 and client when you are not using prepared statements.
1238
1239 All data are sent as 'packed-string-length' followed by 'string-data'
1240 ****************************************************************************/
1241
1242 #ifndef EMBEDDED_LIBRARY
1243
connection_alive()1244 bool Protocol_classic::connection_alive()
1245 {
1246 return m_thd->net.vio != NULL;
1247 }
1248
start_row()1249 void Protocol_text::start_row()
1250 {
1251 #ifndef NDEBUG
1252 field_pos= 0;
1253 #endif
1254 packet->length(0);
1255 }
1256
1257
store_null()1258 bool Protocol_text::store_null()
1259 {
1260 #ifndef NDEBUG
1261 field_pos++;
1262 #endif
1263 char buff[1];
1264 buff[0]= (char)251;
1265 return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
1266 }
1267 #endif
1268
1269
1270 /**
1271 Auxilary function to convert string to the given character set
1272 and store in network buffer.
1273 */
1274
store_string_aux(const char * from,size_t length,const CHARSET_INFO * fromcs,const CHARSET_INFO * tocs)1275 bool Protocol_classic::store_string_aux(const char *from, size_t length,
1276 const CHARSET_INFO *fromcs,
1277 const CHARSET_INFO *tocs)
1278 {
1279 /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
1280 if (tocs && !my_charset_same(fromcs, tocs) &&
1281 fromcs != &my_charset_bin &&
1282 tocs != &my_charset_bin)
1283 {
1284 /* Store with conversion */
1285 return net_store_data((uchar *) from, length, fromcs, tocs);
1286 }
1287 /* Store without conversion */
1288 return net_store_data((uchar *) from, length);
1289 }
1290
1291
shutdown(bool server_shutdown)1292 int Protocol_classic::shutdown(bool server_shutdown)
1293 {
1294 return m_thd->net.vio ? vio_shutdown(m_thd->net.vio, SHUT_RDWR) : 0;
1295 }
1296
1297
store(const char * from,size_t length,const CHARSET_INFO * fromcs,const CHARSET_INFO * tocs)1298 bool Protocol_text::store(const char *from, size_t length,
1299 const CHARSET_INFO *fromcs,
1300 const CHARSET_INFO *tocs)
1301 {
1302 #ifndef NDEBUG
1303 // field_types check is needed because of the embedded protocol
1304 assert(send_metadata || field_types == 0 ||
1305 field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
1306 field_types[field_pos] == MYSQL_TYPE_BIT ||
1307 field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
1308 field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
1309 field_types[field_pos] == MYSQL_TYPE_JSON ||
1310 (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
1311 field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
1312 if(!send_metadata) field_pos++;
1313 #endif
1314 return store_string_aux(from, length, fromcs, tocs);
1315 }
1316
1317
store_tiny(longlong from)1318 bool Protocol_text::store_tiny(longlong from)
1319 {
1320 #ifndef NDEBUG
1321 // field_types check is needed because of the embedded protocol
1322 assert(send_metadata || field_types == 0 ||
1323 field_types[field_pos] == MYSQL_TYPE_TINY);
1324 field_pos++;
1325 #endif
1326 char buff[20];
1327 return net_store_data((uchar *) buff,
1328 (size_t) (int10_to_str((int) from, buff, -10) - buff));
1329 }
1330
1331
store_short(longlong from)1332 bool Protocol_text::store_short(longlong from)
1333 {
1334 #ifndef NDEBUG
1335 // field_types check is needed because of the embedded protocol
1336 assert(send_metadata || field_types == 0 ||
1337 field_types[field_pos] == MYSQL_TYPE_YEAR ||
1338 field_types[field_pos] == MYSQL_TYPE_SHORT);
1339 field_pos++;
1340 #endif
1341 char buff[20];
1342 return net_store_data((uchar *) buff,
1343 (size_t) (int10_to_str((int) from, buff, -10) - buff));
1344 }
1345
1346
store_long(longlong from)1347 bool Protocol_text::store_long(longlong from)
1348 {
1349 #ifndef NDEBUG
1350 // field_types check is needed because of the embedded protocol
1351 assert(send_metadata || field_types == 0 ||
1352 field_types[field_pos] == MYSQL_TYPE_INT24 ||
1353 field_types[field_pos] == MYSQL_TYPE_LONG);
1354 field_pos++;
1355 #endif
1356 char buff[20];
1357 return net_store_data((uchar *) buff,
1358 (size_t) (int10_to_str((long int)from, buff,
1359 (from < 0) ? -10 : 10) - buff));
1360 }
1361
1362
store_longlong(longlong from,bool unsigned_flag)1363 bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
1364 {
1365 #ifndef NDEBUG
1366 // field_types check is needed because of the embedded protocol
1367 assert(send_metadata || field_types == 0 ||
1368 field_types[field_pos] == MYSQL_TYPE_LONGLONG);
1369 field_pos++;
1370 #endif
1371 char buff[22];
1372 return net_store_data((uchar *) buff,
1373 (size_t) (longlong10_to_str(from, buff,
1374 unsigned_flag ? 10 : -10)-
1375 buff));
1376 }
1377
1378
store_decimal(const my_decimal * d,uint prec,uint dec)1379 bool Protocol_text::store_decimal(const my_decimal *d, uint prec, uint dec)
1380 {
1381 #ifndef NDEBUG
1382 // field_types check is needed because of the embedded protocol
1383 assert(send_metadata || field_types == 0 ||
1384 field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
1385 field_pos++;
1386 #endif
1387 char buff[DECIMAL_MAX_STR_LENGTH + 1];
1388 String str(buff, sizeof(buff), &my_charset_bin);
1389 (void) my_decimal2string(E_DEC_FATAL_ERROR, d, prec, dec, '0', &str);
1390 return net_store_data((uchar *) str.ptr(), str.length());
1391 }
1392
1393
store(float from,uint32 decimals,String * buffer)1394 bool Protocol_text::store(float from, uint32 decimals, String *buffer)
1395 {
1396 #ifndef NDEBUG
1397 // field_types check is needed because of the embedded protocol
1398 assert(send_metadata || field_types == 0 ||
1399 field_types[field_pos] == MYSQL_TYPE_FLOAT);
1400 field_pos++;
1401 #endif
1402 buffer->set_real((double) from, decimals, m_thd->charset());
1403 return net_store_data((uchar *) buffer->ptr(), buffer->length());
1404 }
1405
1406
store(double from,uint32 decimals,String * buffer)1407 bool Protocol_text::store(double from, uint32 decimals, String *buffer)
1408 {
1409 #ifndef NDEBUG
1410 // field_types check is needed because of the embedded protocol
1411 assert(send_metadata || field_types == 0 ||
1412 field_types[field_pos] == MYSQL_TYPE_DOUBLE);
1413 field_pos++;
1414 #endif
1415 buffer->set_real(from, decimals, m_thd->charset());
1416 return net_store_data((uchar *) buffer->ptr(), buffer->length());
1417 }
1418
1419
store(Proto_field * field)1420 bool Protocol_text::store(Proto_field *field)
1421 {
1422 return field->send_text(this);
1423 }
1424
1425
1426 /**
1427 @todo
1428 Second_part format ("%06") needs to change when
1429 we support 0-6 decimals for time.
1430 */
1431
store(MYSQL_TIME * tm,uint decimals)1432 bool Protocol_text::store(MYSQL_TIME *tm, uint decimals)
1433 {
1434 #ifndef NDEBUG
1435 // field_types check is needed because of the embedded protocol
1436 assert(send_metadata || field_types == 0 ||
1437 is_temporal_type_with_date_and_time(field_types[field_pos]));
1438 field_pos++;
1439 #endif
1440 char buff[MAX_DATE_STRING_REP_LENGTH];
1441 size_t length= my_datetime_to_str(tm, buff, decimals);
1442 return net_store_data((uchar *) buff, length);
1443 }
1444
1445
store_date(MYSQL_TIME * tm)1446 bool Protocol_text::store_date(MYSQL_TIME *tm)
1447 {
1448 #ifndef NDEBUG
1449 // field_types check is needed because of the embedded protocol
1450 assert(send_metadata || field_types == 0 ||
1451 field_types[field_pos] == MYSQL_TYPE_DATE);
1452 field_pos++;
1453 #endif
1454 char buff[MAX_DATE_STRING_REP_LENGTH];
1455 size_t length= my_date_to_str(tm, buff);
1456 return net_store_data((uchar *) buff, length);
1457 }
1458
1459
store_time(MYSQL_TIME * tm,uint decimals)1460 bool Protocol_text::store_time(MYSQL_TIME *tm, uint decimals)
1461 {
1462 #ifndef NDEBUG
1463 // field_types check is needed because of the embedded protocol
1464 assert(send_metadata || field_types == 0 ||
1465 field_types[field_pos] == MYSQL_TYPE_TIME);
1466 field_pos++;
1467 #endif
1468 char buff[MAX_DATE_STRING_REP_LENGTH];
1469 size_t length= my_time_to_str(tm, buff, decimals);
1470 return net_store_data((uchar *) buff, length);
1471 }
1472
1473
1474 /**
1475 Assign OUT-parameters to user variables.
1476
1477 @param sp_params List of PS/SP parameters (both input and output).
1478
1479 @return Error status.
1480 @retval FALSE Success.
1481 @retval TRUE Error.
1482 */
1483
send_out_parameters(List<Item_param> * sp_params)1484 bool Protocol_text::send_out_parameters(List<Item_param> *sp_params)
1485 {
1486 assert(sp_params->elements == m_thd->lex->prepared_stmt_params.elements);
1487
1488 List_iterator_fast<Item_param> item_param_it(*sp_params);
1489 List_iterator_fast<LEX_STRING> user_var_name_it(
1490 m_thd->lex->prepared_stmt_params);
1491
1492 while (true)
1493 {
1494 Item_param *item_param= item_param_it++;
1495 LEX_STRING *user_var_name= user_var_name_it++;
1496
1497 if (!item_param || !user_var_name)
1498 break;
1499
1500 if (!item_param->get_out_param_info())
1501 continue; // It's an IN-parameter.
1502
1503 Item_func_set_user_var *suv=
1504 new Item_func_set_user_var(*user_var_name, item_param, false);
1505 /*
1506 Item_func_set_user_var is not fixed after construction, call
1507 fix_fields().
1508 */
1509 if (suv->fix_fields(m_thd, NULL))
1510 return TRUE;
1511
1512 if (suv->check(FALSE))
1513 return TRUE;
1514
1515 if (suv->update())
1516 return TRUE;
1517 }
1518
1519 return FALSE;
1520 }
1521
1522
1523 /****************************************************************************
1524 Functions to handle the binary protocol used with prepared statements
1525
1526 Data format:
1527
1528 [ok:1] reserved ok packet
1529 [null_field:(field_count+7+2)/8] reserved to send null data. The size is
1530 calculated using:
1531 bit_fields= (field_count+7+2)/8;
1532 2 bits are reserved for identifying type
1533 of package.
1534 [[length]data] data field (the length applies only for
1535 string/binary/time/timestamp fields and
1536 rest of them are not sent as they have
1537 the default length that client understands
1538 based on the field type
1539 [..]..[[length]data] data
1540 ****************************************************************************/
start_result_metadata(uint num_cols,uint flags,const CHARSET_INFO * result_cs)1541 bool Protocol_binary::start_result_metadata(uint num_cols, uint flags,
1542 const CHARSET_INFO *result_cs)
1543 {
1544 bit_fields= (num_cols + 9) / 8;
1545 packet->alloc(bit_fields+1);
1546 return Protocol_classic::start_result_metadata(num_cols, flags, result_cs);
1547 }
1548
1549
1550 #ifndef EMBEDDED_LIBRARY
start_row()1551 void Protocol_binary::start_row()
1552 {
1553 if (send_metadata)
1554 return Protocol_text::start_row();
1555 packet->length(bit_fields+1);
1556 memset(const_cast<char*>(packet->ptr()), 0, 1+bit_fields);
1557 field_pos=0;
1558 }
1559 #endif
1560
1561
store(const char * from,size_t length,const CHARSET_INFO * fromcs,const CHARSET_INFO * tocs)1562 bool Protocol_binary::store(const char *from, size_t length,
1563 const CHARSET_INFO *fromcs,
1564 const CHARSET_INFO *tocs)
1565 {
1566 if(send_metadata)
1567 return Protocol_text::store(from, length, fromcs, tocs);
1568 #ifndef NDEBUG
1569 // field_types check is needed because of the embedded protocol
1570 assert(field_types == 0 ||
1571 field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
1572 field_types[field_pos] == MYSQL_TYPE_BIT ||
1573 field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
1574 field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
1575 field_types[field_pos] == MYSQL_TYPE_JSON ||
1576 (field_types[field_pos] >= MYSQL_TYPE_ENUM &&
1577 field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
1578 #endif
1579 field_pos++;
1580 return store_string_aux(from, length, fromcs, tocs);
1581 }
1582
1583
store_null()1584 bool Protocol_binary::store_null()
1585 {
1586 if(send_metadata)
1587 return Protocol_text::store_null();
1588 uint offset= (field_pos+2)/8+1, bit= (1 << ((field_pos+2) & 7));
1589 /* Room for this as it's allocated in prepare_for_send */
1590 char *to= (char *) packet->ptr()+offset;
1591 *to= (char) ((uchar) *to | (uchar) bit);
1592 field_pos++;
1593 return 0;
1594 }
1595
1596
store_tiny(longlong from)1597 bool Protocol_binary::store_tiny(longlong from)
1598 {
1599 if(send_metadata)
1600 return Protocol_text::store_tiny(from);
1601 char buff[1];
1602 #ifndef NDEBUG
1603 // field_types check is needed because of the embedded protocol
1604 assert(field_types == 0 ||
1605 field_types[field_pos] == MYSQL_TYPE_TINY ||
1606 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1607 #endif
1608 field_pos++;
1609 buff[0]= (uchar) from;
1610 return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
1611 }
1612
1613
store_short(longlong from)1614 bool Protocol_binary::store_short(longlong from)
1615 {
1616 if(send_metadata)
1617 return Protocol_text::store_short(from);
1618 #ifndef NDEBUG
1619 // field_types check is needed because of the embedded protocol
1620 assert(field_types == 0 ||
1621 field_types[field_pos] == MYSQL_TYPE_YEAR ||
1622 field_types[field_pos] == MYSQL_TYPE_SHORT ||
1623 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1624 #endif
1625 field_pos++;
1626 char *to= packet->prep_append(2, PACKET_BUFFER_EXTRA_ALLOC);
1627 if (!to)
1628 return 1;
1629 int2store(to, (int) from);
1630 return 0;
1631 }
1632
1633
store_long(longlong from)1634 bool Protocol_binary::store_long(longlong from)
1635 {
1636 if(send_metadata)
1637 return Protocol_text::store_long(from);
1638 #ifndef NDEBUG
1639 // field_types check is needed because of the embedded protocol
1640 assert(field_types == 0 ||
1641 field_types[field_pos] == MYSQL_TYPE_INT24 ||
1642 field_types[field_pos] == MYSQL_TYPE_LONG ||
1643 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1644 #endif
1645 field_pos++;
1646 char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
1647 if (!to)
1648 return 1;
1649 int4store(to, static_cast<uint32>(from));
1650 return 0;
1651 }
1652
1653
store_longlong(longlong from,bool unsigned_flag)1654 bool Protocol_binary::store_longlong(longlong from, bool unsigned_flag)
1655 {
1656 if(send_metadata)
1657 return Protocol_text::store_longlong(from, unsigned_flag);
1658 #ifndef NDEBUG
1659 // field_types check is needed because of the embedded protocol
1660 assert(field_types == 0 ||
1661 field_types[field_pos] == MYSQL_TYPE_LONGLONG ||
1662 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1663 #endif
1664 field_pos++;
1665 char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
1666 if (!to)
1667 return 1;
1668 int8store(to, from);
1669 return 0;
1670 }
1671
1672
store_decimal(const my_decimal * d,uint prec,uint dec)1673 bool Protocol_binary::store_decimal(const my_decimal *d, uint prec, uint dec)
1674 {
1675 if(send_metadata)
1676 return Protocol_text::store_decimal(d, prec, dec);
1677 #ifndef NDEBUG
1678 // field_types check is needed because of the embedded protocol
1679 assert(field_types == 0 ||
1680 field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
1681 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1682 // store() will increment the field_pos counter
1683 #endif
1684 char buff[DECIMAL_MAX_STR_LENGTH + 1];
1685 String str(buff, sizeof(buff), &my_charset_bin);
1686 (void) my_decimal2string(E_DEC_FATAL_ERROR, d, prec, dec, '0', &str);
1687 return store(str.ptr(), str.length(), str.charset(), result_cs);
1688 }
1689
1690
store(float from,uint32 decimals,String * buffer)1691 bool Protocol_binary::store(float from, uint32 decimals, String *buffer)
1692 {
1693 if(send_metadata)
1694 return Protocol_text::store(from, decimals, buffer);
1695 #ifndef NDEBUG
1696 // field_types check is needed because of the embedded protocol
1697 assert(field_types == 0 ||
1698 field_types[field_pos] == MYSQL_TYPE_FLOAT ||
1699 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1700 #endif
1701 field_pos++;
1702 char *to= packet->prep_append(4, PACKET_BUFFER_EXTRA_ALLOC);
1703 if (!to)
1704 return 1;
1705 float4store(to, from);
1706 return 0;
1707 }
1708
1709
store(double from,uint32 decimals,String * buffer)1710 bool Protocol_binary::store(double from, uint32 decimals, String *buffer)
1711 {
1712 if(send_metadata)
1713 return Protocol_text::store(from, decimals, buffer);
1714 #ifndef NDEBUG
1715 // field_types check is needed because of the embedded protocol
1716 assert(field_types == 0
1717 || field_types[field_pos] == MYSQL_TYPE_DOUBLE ||
1718 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1719 #endif
1720 field_pos++;
1721 char *to= packet->prep_append(8, PACKET_BUFFER_EXTRA_ALLOC);
1722 if (!to)
1723 return 1;
1724 float8store(to, from);
1725 return 0;
1726 }
1727
1728
store(Proto_field * field)1729 bool Protocol_binary::store(Proto_field *field)
1730 {
1731 if(send_metadata)
1732 return Protocol_text::store(field);
1733 return field->send_binary(this);
1734 }
1735
1736
store(MYSQL_TIME * tm,uint precision)1737 bool Protocol_binary::store(MYSQL_TIME *tm, uint precision)
1738 {
1739 if(send_metadata)
1740 return Protocol_text::store(tm, precision);
1741
1742 #ifndef NDEBUG
1743 // field_types check is needed because of the embedded protocol
1744 assert(field_types == 0 ||
1745 field_types[field_pos] == MYSQL_TYPE_DATE ||
1746 is_temporal_type_with_date_and_time(field_types[field_pos]) ||
1747 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1748 #endif
1749 char buff[12],*pos;
1750 size_t length;
1751 field_pos++;
1752 pos= buff+1;
1753
1754 int2store(pos, tm->year);
1755 pos[2]= (uchar) tm->month;
1756 pos[3]= (uchar) tm->day;
1757 pos[4]= (uchar) tm->hour;
1758 pos[5]= (uchar) tm->minute;
1759 pos[6]= (uchar) tm->second;
1760 int4store(pos+7, tm->second_part);
1761 if (tm->second_part)
1762 length=11;
1763 else if (tm->hour || tm->minute || tm->second)
1764 length=7;
1765 else if (tm->year || tm->month || tm->day)
1766 length=4;
1767 else
1768 length=0;
1769 buff[0]=(char) length; // Length is stored first
1770 return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
1771 }
1772
1773
store_date(MYSQL_TIME * tm)1774 bool Protocol_binary::store_date(MYSQL_TIME *tm)
1775 {
1776 if(send_metadata)
1777 return Protocol_text::store_date(tm);
1778 #ifndef NDEBUG
1779 // field_types check is needed because of the embedded protocol
1780 assert(field_types == 0 ||
1781 field_types[field_pos] == MYSQL_TYPE_DATE ||
1782 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1783 #endif
1784 tm->hour= tm->minute= tm->second=0;
1785 tm->second_part= 0;
1786 return Protocol_binary::store(tm, 0);
1787 }
1788
1789
store_time(MYSQL_TIME * tm,uint precision)1790 bool Protocol_binary::store_time(MYSQL_TIME *tm, uint precision)
1791 {
1792 if(send_metadata)
1793 return Protocol_text::store_time(tm, precision);
1794 char buff[13], *pos;
1795 size_t length;
1796 #ifndef NDEBUG
1797 // field_types check is needed because of the embedded protocol
1798 assert(field_types == 0 ||
1799 field_types[field_pos] == MYSQL_TYPE_TIME ||
1800 field_types[field_pos] == MYSQL_TYPE_VAR_STRING);
1801 #endif
1802 field_pos++;
1803 pos= buff+1;
1804 pos[0]= tm->neg ? 1 : 0;
1805 if (tm->hour >= 24)
1806 {
1807 /* Fix if we come from Item::send */
1808 uint days= tm->hour/24;
1809 tm->hour-= days*24;
1810 tm->day+= days;
1811 }
1812 int4store(pos+1, tm->day);
1813 pos[5]= (uchar) tm->hour;
1814 pos[6]= (uchar) tm->minute;
1815 pos[7]= (uchar) tm->second;
1816 int4store(pos+8, tm->second_part);
1817 if (tm->second_part)
1818 length=12;
1819 else if (tm->hour || tm->minute || tm->second || tm->day)
1820 length=8;
1821 else
1822 length=0;
1823 buff[0]=(char) length; // Length is stored first
1824 return packet->append(buff, length+1, PACKET_BUFFER_EXTRA_ALLOC);
1825 }
1826
1827
1828 /**
1829 Send a result set with OUT-parameter values by means of PS-protocol.
1830
1831 @param sp_params List of PS/SP parameters (both input and output).
1832
1833 @return Error status.
1834 @retval FALSE Success.
1835 @retval TRUE Error.
1836 */
1837
send_out_parameters(List<Item_param> * sp_params)1838 bool Protocol_binary::send_out_parameters(List<Item_param> *sp_params)
1839 {
1840 bool ret;
1841 if (!has_client_capability(CLIENT_PS_MULTI_RESULTS))
1842 {
1843 /* The client does not support OUT-parameters. */
1844 return FALSE;
1845 }
1846
1847 List<Item> out_param_lst;
1848
1849 {
1850 List_iterator_fast<Item_param> item_param_it(*sp_params);
1851
1852 while (true)
1853 {
1854 Item_param *item_param= item_param_it++;
1855
1856 if (!item_param)
1857 break;
1858
1859 if (!item_param->get_out_param_info())
1860 continue; // It's an IN-parameter.
1861
1862 if (out_param_lst.push_back(item_param))
1863 return TRUE;
1864 }
1865 }
1866
1867 if (!out_param_lst.elements)
1868 return FALSE;
1869
1870 /*
1871 We have to set SERVER_PS_OUT_PARAMS in THD::server_status, because it
1872 is used in send_result_metadata().
1873 */
1874
1875 m_thd->server_status|= SERVER_PS_OUT_PARAMS | SERVER_MORE_RESULTS_EXISTS;
1876
1877 /* Send meta-data. */
1878 if (m_thd->send_result_metadata(&out_param_lst,
1879 SEND_NUM_ROWS | SEND_EOF))
1880 return TRUE;
1881
1882 /* Send data. */
1883
1884 this->start_row();
1885
1886 if (m_thd->send_result_set_row(&out_param_lst))
1887 return TRUE;
1888
1889 if (this->end_row())
1890 return TRUE;
1891
1892 /* Restore THD::server_status. */
1893 m_thd->server_status&= ~SERVER_PS_OUT_PARAMS;
1894
1895 /*
1896 Reset SERVER_MORE_RESULTS_EXISTS bit, because for sure this is the last
1897 result set we are sending.
1898 */
1899
1900 m_thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
1901
1902 if (has_client_capability(CLIENT_DEPRECATE_EOF))
1903 ret= net_send_ok(m_thd,
1904 (m_thd->server_status | SERVER_PS_OUT_PARAMS |
1905 SERVER_MORE_RESULTS_EXISTS),
1906 m_thd->get_stmt_da()->current_statement_cond_count(),
1907 0, 0, NULL, true);
1908 else
1909 /* In case of old clients send EOF packet. */
1910 ret= net_send_eof(m_thd, m_thd->server_status, 0);
1911 return ret ? FALSE : TRUE;
1912 }
1913
1914
1915 /**
1916 @returns: the file descriptor of the socket.
1917 */
1918
get_socket()1919 my_socket Protocol_classic::get_socket()
1920 {
1921 return get_vio()->mysql_socket.fd;
1922 }
1923