1
/* Copyright (C) 2000-2003 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
19
23
Low level functions for storing data to be send to the MySQL client.
20
24
The actual communction is handled by the net_xxx functions in net_serv.cc
22
27
#include <drizzled/server_includes.h>
23
28
#include <drizzled/error.h>
24
29
#include <drizzled/sql_state.h>
25
#include <libdrizzleclient/pack.h>
26
#include <libdrizzleclient/errmsg.h>
27
30
#include <drizzled/protocol.h>
28
31
#include <drizzled/session.h>
29
32
#include <drizzled/data_home.h>
35
#include "oldlibdrizzle.h"
32
38
Function called by drizzleclient_net_init() to set some check variables
36
void drizzleclient_net_local_init(NET *net)
38
net->max_packet= (uint32_t) global_system_variables.net_buffer_length;
40
drizzleclient_net_set_read_timeout(net,
41
(uint32_t)global_system_variables.net_read_timeout);
42
drizzleclient_net_set_write_timeout(net,
43
(uint32_t)global_system_variables.net_write_timeout);
45
net->retry_count= (uint32_t) global_system_variables.net_retry_count;
46
net->max_packet_size= cmax(global_system_variables.net_buffer_length,
47
global_system_variables.max_allowed_packet);
51
41
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
53
43
static void write_eof_packet(Session *session, NET *net,
54
44
uint32_t server_status, uint32_t total_warn_count);
56
bool Protocol::io_ok()
46
bool ProtocolOldLibdrizzle::isConnected()
58
48
return net.vio != 0;
61
void Protocol::set_read_timeout(uint32_t timeout)
51
void ProtocolOldLibdrizzle::setReadTimeout(uint32_t timeout)
63
53
drizzleclient_net_set_read_timeout(&net, timeout);
66
void Protocol::set_write_timeout(uint32_t timeout)
56
void ProtocolOldLibdrizzle::setWriteTimeout(uint32_t timeout)
68
58
drizzleclient_net_set_write_timeout(&net, timeout);
71
void Protocol::set_retry_count(uint32_t count)
61
void ProtocolOldLibdrizzle::setRetryCount(uint32_t count)
73
63
net.retry_count=count;
76
void Protocol::set_error(char error)
66
void ProtocolOldLibdrizzle::setError(char error)
81
bool Protocol::have_error(void)
71
bool ProtocolOldLibdrizzle::haveError(void)
83
73
return net.error || net.vio == 0;
86
bool Protocol::was_aborted(void)
76
bool ProtocolOldLibdrizzle::wasAborted(void)
88
78
return net.error && net.vio != 0;
91
bool Protocol::have_more_data(void)
81
bool ProtocolOldLibdrizzle::haveMoreData(void)
93
83
return drizzleclient_net_more_data(&net);
96
bool Protocol::have_compression(void)
101
void Protocol::enable_compression(void)
86
void ProtocolOldLibdrizzle::enableCompression(void)
103
88
net.compress= true;
106
bool Protocol::is_reading(void)
91
bool ProtocolOldLibdrizzle::isReading(void)
108
93
return net.reading_or_writing == 1;
111
bool Protocol::is_writing(void)
96
bool ProtocolOldLibdrizzle::isWriting(void)
113
98
return net.reading_or_writing == 2;
117
* To disable results we set net.vio to 0.
120
void Protocol::disable_results(void)
126
void Protocol::enable_results(void)
132
bool Protocol::net_store_data(const unsigned char *from, size_t length)
101
bool ProtocolOldLibdrizzle::netStoreData(const unsigned char *from, size_t length)
134
103
size_t packet_length= packet->length();
209
176
The ok packet has the following structure:
211
178
- 0 : Marker (1 byte)
212
- affected_rows : Stored in 1-9 bytes
213
- id : Stored in 1-9 bytes
214
- server_status : Copy of session->server_status; Can be used by client
179
- affected_rows : Stored in 1-9 bytes
180
- id : Stored in 1-9 bytes
181
- server_status : Copy of session->server_status; Can be used by client
215
182
to check if we are inside an transaction.
216
183
New in 4.0 protocol
217
- warning_count : Stored in 2 bytes; New in 4.1 protocol
218
- message : Stored as packed length (1-9 bytes) + message.
184
- warning_count : Stored in 2 bytes; New in 4.1 protocol
185
- message : Stored as packed length (1-9 bytes) + message.
219
186
Is not stored if no message.
221
@param session Thread handler
222
@param affected_rows Number of rows changed by statement
223
@param id Auto_increment id for first row (if used)
224
@param message Message to send to the client (Used by mysql_status)
188
@param session Thread handler
189
@param affected_rows Number of rows changed by statement
190
@param id Auto_increment id for first row (if used)
191
@param message Message to send to the client (Used by mysql_status)
228
net_send_ok(Session *session, NET *net,
229
uint32_t server_status, uint32_t total_warn_count,
230
ha_rows affected_rows, uint64_t id, const char *message)
194
void ProtocolOldLibdrizzle::sendOK()
232
196
unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
197
const char *message= NULL;
234
if (!net->vio) // hack for re-parsing queries
200
if (!net.vio) // hack for re-parsing queries
239
buff[0]=0; // No fields
240
pos=drizzleclient_net_store_length(buff+1,affected_rows);
241
pos=drizzleclient_net_store_length(pos, id);
243
int2store(pos, server_status);
205
buff[0]=0; // No fields
206
if (session->main_da.status() == Diagnostics_area::DA_OK)
208
pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
209
pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
210
int2store(pos, session->main_da.server_status());
212
tmp= cmin(session->main_da.total_warn_count(), (uint32_t)65535);
213
message= session->main_da.message();
217
pos=drizzleclient_net_store_length(buff+1,0);
218
pos=drizzleclient_net_store_length(pos, 0);
219
int2store(pos, session->server_status);
221
tmp= cmin(session->total_warn_count, (uint32_t)65535);
246
224
/* We can only return up to 65535 warnings in two bytes */
247
uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
248
225
int2store(pos, tmp);
269
246
The eof packet has the following structure:
271
- 254 (DRIZZLE_PROTOCOL_NO_MORE_DATA) : Marker (1 byte)
272
- warning_count : Stored in 2 bytes; New in 4.1 protocol
273
- status_flag : Stored in 2 bytes;
248
- 254 (DRIZZLE_PROTOCOL_NO_MORE_DATA) : Marker (1 byte)
249
- warning_count : Stored in 2 bytes; New in 4.1 protocol
250
- status_flag : Stored in 2 bytes;
274
251
For flags like SERVER_MORE_RESULTS_EXISTS.
276
253
Note that the warning count will not be sent if 'no_flush' is set as
277
254
we don't want to report the warning count until all data is sent to the
280
@param session Thread handler
281
@param no_flush Set to 1 if there will be more data to the client,
282
like in send_fields().
286
net_send_eof(Session *session, NET *net, uint32_t server_status, uint32_t total_warn_count)
258
void ProtocolOldLibdrizzle::sendEOF()
288
260
/* Set to true if no active vio, to work well in case of --init-file */
291
263
session->main_da.can_overwrite_status= true;
292
write_eof_packet(session, net, server_status, total_warn_count);
293
drizzleclient_net_flush(net);
264
write_eof_packet(session, &net, session->main_da.server_status(),
265
session->main_da.total_warn_count());
266
drizzleclient_net_flush(&net);
294
267
session->main_da.can_overwrite_status= false;
352
345
err= (char*) buff;
354
347
drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
359
Send a error string to client.
362
net_printf_error and net_send_error are low-level functions
363
that shall be used only when a new connection is being
364
established or at server startup.
366
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
367
critical that every error that can be intercepted is issued in one
368
place only, my_message_sql.
370
void Protocol_text::send_error(uint32_t sql_errno, const char *err)
373
assert(err && err[0]);
376
It's one case when we can push an error even though there
377
is an OK or EOF already.
379
session->main_da.can_overwrite_status= true;
381
/* Abort multi-result sets */
382
session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
384
send_error_packet(sql_errno, err);
386
349
session->main_da.can_overwrite_status= false;
391
Send the status of the current statement execution over network.
393
@param session in fact, carries two parameters, NET for the transport and
394
Diagnostics_area as the source of status information.
396
In MySQL, there are two types of SQL statements: those that return
397
a result set and those that return status information only.
399
If a statement returns a result set, it consists of 3 parts:
400
- result set meta-data
401
- variable number of result set rows (can be 0)
402
- followed and terminated by EOF or ERROR packet
404
Once the client has seen the meta-data information, it always
405
expects an EOF or ERROR to terminate the result set. If ERROR is
406
received, the result set rows are normally discarded (this is up
407
to the client implementation, libmysql at least does discard them).
408
EOF, on the contrary, means "successfully evaluated the entire
409
result set". Since we don't know how many rows belong to a result
410
set until it's evaluated, EOF/ERROR is the indicator of the end
411
of the row stream. Note, that we can not buffer result set rows
412
on the server -- there may be an arbitrary number of rows. But
413
we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
414
delay sending it till the very end of execution (here), to be able to
415
change EOF to an ERROR if commit failed or some other error occurred
416
during the last cleanup steps taken after execution.
418
A statement that does not return a result set doesn't send result
419
set meta-data either. Instead it returns one of:
422
Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
423
packet is "buffered" in the diagnostics area and sent to the client
424
in the end of statement.
426
@pre The diagnostics area is assigned or disabled. It can not be empty
427
-- we assume that every SQL statement or COM_* command
428
generates OK, ERROR, or EOF status.
430
@post The status information is encoded to protocol format and sent to the
433
@return We conventionally return void, since the only type of error
434
that can happen here is a NET (transport) error, and that one
435
will become visible when we attempt to read from the NET the
437
Diagnostics_area::is_sent is set for debugging purposes only.
440
void Protocol::end_statement()
353
ProtocolOldLibdrizzle::ProtocolOldLibdrizzle()
442
assert(! session->main_da.is_sent);
444
/* Can not be true, but do not take chances in production. */
445
if (session->main_da.is_sent)
448
switch (session->main_da.status()) {
449
case Diagnostics_area::DA_ERROR:
450
/* The query failed, send error to log and abort bootstrap. */
451
send_error(session->main_da.sql_errno(),
452
session->main_da.message());
454
case Diagnostics_area::DA_EOF:
455
net_send_eof(session, &net,
456
session->main_da.server_status(),
457
session->main_da.total_warn_count());
459
case Diagnostics_area::DA_OK:
460
net_send_ok(session, &net,
461
session->main_da.server_status(),
462
session->main_da.total_warn_count(),
463
session->main_da.affected_rows(),
464
session->main_da.last_insert_id(),
465
session->main_da.message());
467
case Diagnostics_area::DA_DISABLED:
469
case Diagnostics_area::DA_EMPTY:
471
//TODO: Something is being masked here by commenting this out
473
net_send_ok(session, &net, session->server_status, session->total_warn_count,
477
session->main_da.is_sent= true;
481
/*****************************************************************************
482
Default Protocol functions
483
*****************************************************************************/
485
void Protocol::init(Session *session_arg)
359
void ProtocolOldLibdrizzle::setSession(Session *session_arg)
361
session= session_arg;
488
362
packet= &session->packet;
489
363
convert= &session->convert_buffer;
494
bool Protocol::flush()
496
return drizzleclient_net_flush(&net);
537
402
Send_field field;
538
403
item->make_field(&field);
540
prepare_for_resend();
543
if (store(STRING_WITH_LEN("def"), cs, session_charset) ||
544
store(field.db_name, (uint32_t) strlen(field.db_name),
545
cs, session_charset) ||
546
store(field.table_name, (uint32_t) strlen(field.table_name),
547
cs, session_charset) ||
548
store(field.org_table_name, (uint32_t) strlen(field.org_table_name),
549
cs, session_charset) ||
550
store(field.col_name, (uint32_t) strlen(field.col_name),
551
cs, session_charset) ||
552
store(field.org_col_name, (uint32_t) strlen(field.org_col_name),
553
cs, session_charset) ||
554
local_packet->realloc(local_packet->length()+12))
407
if (store(STRING_WITH_LEN("def"), cs) ||
408
store(field.db_name, cs) ||
409
store(field.table_name, cs) ||
410
store(field.org_table_name, cs) ||
411
store(field.col_name, cs) ||
412
store(field.org_col_name, cs) ||
413
packet->realloc(packet->length()+12))
557
416
/* Store fixed length fields */
558
pos= (char*) local_packet->ptr()+local_packet->length();
559
*pos++= 12; // Length of packed fields
560
if (item->collation.collation == &my_charset_bin || session_charset == NULL)
417
pos= (char*) packet->ptr()+packet->length();
418
*pos++= 12; // Length of packed fields
419
if (item->collation.collation == &my_charset_bin)
562
421
/* No conversion */
563
422
int2store(pos, field.charsetnr);
605
464
write_eof_packet(session, &net, session->server_status, session->total_warn_count);
607
return(prepare_for_send(list));
467
field_count= list->elements;
610
471
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
611
MYF(0)); /* purecov: inspected */
612
return(1); /* purecov: inspected */
472
MYF(0)); /* purecov: inspected */
473
return 1; /* purecov: inspected */
616
bool Protocol::write()
477
bool ProtocolOldLibdrizzle::write()
618
479
return(drizzleclient_net_write(&net, (unsigned char*) packet->ptr(),
619
480
packet->length()));
624
Send \\0 end terminated string.
626
@param from NULL or \\0 terminated string
629
In most cases one should use store(from, length) instead of this function
637
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
641
uint32_t length= strlen(from);
642
return store(from, length, cs);
647
Send a set of strings as one long string with ',' in between.
650
bool Protocol::store(I_List<i_string>* str_list)
653
String tmp(buf, sizeof(buf), &my_charset_bin);
655
I_List_iterator<i_string> it(*str_list);
664
if ((len= tmp.length()))
665
len--; // Remove last ','
666
return store((char*) tmp.ptr(), len, tmp.charset());
670
bool Protocol::store(String *str)
672
return store((char*) str->ptr(), str->length(), str->charset());
675
void Protocol::free()
483
void ProtocolOldLibdrizzle::free()
681
/****************************************************************************
682
Functions to handle the simple (default) protocol where everything is
683
This protocol is the one that is used by default between the MySQL server
684
and client when you are not using prepared statements.
686
All data are sent as 'packed-string-length' followed by 'string-data'
687
****************************************************************************/
689
void Protocol_text::init_random(uint64_t seed1, uint64_t seed2)
489
void ProtocolOldLibdrizzle::setRandom(uint64_t seed1, uint64_t seed2)
691
drizzleclient_randominit(&_rand, seed1, seed2);
491
drizzleclient_randominit(&rand, seed1, seed2);
694
bool Protocol_text::init_file_descriptor(int fd)
494
bool ProtocolOldLibdrizzle::setFileDescriptor(int fd)
696
496
if (drizzleclient_net_init_sock(&net, fd, 0))
701
int Protocol_text::file_descriptor(void)
501
int ProtocolOldLibdrizzle::fileDescriptor(void)
703
503
return drizzleclient_net_get_sd(&net);
706
bool Protocol_text::authenticate()
506
bool ProtocolOldLibdrizzle::authenticate()
708
508
bool connection_is_valid;
829
629
tocs != &my_charset_bin)
831
631
/* Store with conversion */
832
return net_store_data((unsigned char*) from, length, fromcs, tocs);
632
return netStoreData((unsigned char*) from, length, fromcs, tocs);
834
634
/* Store without conversion */
835
return net_store_data((unsigned char*) from, length);
839
bool Protocol_text::store(const char *from, size_t length,
840
const CHARSET_INFO * const fromcs,
841
const CHARSET_INFO * const tocs)
843
return store_string_aux(from, length, fromcs, tocs);
847
bool Protocol_text::store(const char *from, size_t length,
635
return netStoreData((unsigned char*) from, length);
639
bool ProtocolOldLibdrizzle::store(const char *from, size_t length,
848
640
const CHARSET_INFO * const fromcs)
850
642
const CHARSET_INFO * const tocs= default_charset_info;
851
return store_string_aux(from, length, fromcs, tocs);
855
bool Protocol_text::store_tiny(int64_t from)
858
return net_store_data((unsigned char*) buff,
859
(size_t) (int10_to_str((int) from, buff, -10) - buff));
863
bool Protocol_text::store_short(int64_t from)
866
return net_store_data((unsigned char*) buff,
867
(size_t) (int10_to_str((int) from, buff, -10) -
872
bool Protocol_text::store_long(int64_t from)
875
return net_store_data((unsigned char*) buff,
876
(size_t) (int10_to_str((long int)from, buff,
877
(from <0)?-10:10)-buff));
881
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
643
return storeString(from, length, fromcs, tocs);
647
bool ProtocolOldLibdrizzle::store(int32_t from)
650
return netStoreData((unsigned char*) buff,
651
(size_t) (int10_to_str(from, buff, -10) - buff));
654
bool ProtocolOldLibdrizzle::store(uint32_t from)
657
return netStoreData((unsigned char*) buff,
658
(size_t) (int10_to_str(from, buff, 10) - buff));
661
bool ProtocolOldLibdrizzle::store(int64_t from)
884
return net_store_data((unsigned char*) buff,
885
(size_t) (int64_t10_to_str(from,buff,
886
unsigned_flag ? 10 : -10)-
891
bool Protocol_text::store_decimal(const my_decimal *d)
893
char buff[DECIMAL_MAX_STR_LENGTH];
894
String str(buff, sizeof(buff), &my_charset_bin);
895
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
896
return net_store_data((unsigned char*) str.ptr(), str.length());
900
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
902
buffer->set_real((double) from, decimals, session->charset());
903
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
907
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
664
return netStoreData((unsigned char*) buff,
665
(size_t) (int64_t10_to_str(from, buff, -10) - buff));
668
bool ProtocolOldLibdrizzle::store(uint64_t from)
671
return netStoreData((unsigned char*) buff,
672
(size_t) (int64_t10_to_str(from, buff, 10) - buff));
676
bool ProtocolOldLibdrizzle::store(double from, uint32_t decimals, String *buffer)
909
678
buffer->set_real(from, decimals, session->charset());
910
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
679
return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
914
bool Protocol_text::store(Field *field)
683
bool ProtocolOldLibdrizzle::store(Field *from)
916
if (field->is_null())
918
687
char buff[MAX_FIELD_WIDTH];
919
688
String str(buff,sizeof(buff), &my_charset_bin);
920
689
const CHARSET_INFO * const tocs= default_charset_info;
922
field->val_str(&str);
924
return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
930
Second_part format ("%06") needs to change when
931
we support 0-6 decimals for time.
934
bool Protocol_text::store(DRIZZLE_TIME *tm)
938
length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
946
length+= sprintf(buff+length, ".%06d",
947
(int)tm->second_part);
948
return net_store_data((unsigned char*) buff, length);
952
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
954
char buff[MAX_DATE_STRING_REP_LENGTH];
955
size_t length= my_date_to_str(tm, buff);
956
return net_store_data((unsigned char*) buff, length);
962
Second_part format ("%06") needs to change when
963
we support 0-6 decimals for time.
966
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
970
uint32_t day= (tm->year || tm->month) ? 0 : tm->day;
971
length= sprintf(buff, "%s%02ld:%02d:%02d",
973
(long) day*24L+(long) tm->hour,
977
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
978
return net_store_data((unsigned char*) buff, length);
981
bool Protocol_text::_check_connection(void)
693
return storeString(str.ptr(), str.length(), str.charset(), tocs);
699
Second_part format ("%06") needs to change when
700
we support 0-6 decimals for time.
703
bool ProtocolOldLibdrizzle::store(const DRIZZLE_TIME *tm)
709
switch (tm->time_type)
711
case DRIZZLE_TIMESTAMP_DATETIME:
712
length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
720
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
723
case DRIZZLE_TIMESTAMP_DATE:
724
length= sprintf(buff, "%04d-%02d-%02d",
730
case DRIZZLE_TIMESTAMP_TIME:
731
day= (tm->year || tm->month) ? 0 : tm->day;
732
length= sprintf(buff, "%s%02ld:%02d:%02d", tm->neg ? "-" : "",
733
(long) day*24L+(long) tm->hour, (int) tm->minute,
736
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
739
case DRIZZLE_TIMESTAMP_NONE:
740
case DRIZZLE_TIMESTAMP_ERROR:
746
return netStoreData((unsigned char*) buff, length);
749
bool ProtocolOldLibdrizzle::checkConnection(void)
983
751
uint32_t pkt_len= 0;