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
21
#include <drizzled/gettext.h>
22
#include <drizzled/error.h>
23
#include <drizzled/query_id.h>
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 */
19
Low level functions for storing data to be send to the MySQL client.
20
The actual communction is handled by the net_xxx functions in net_serv.cc
22
#include <drizzled/server_includes.h>
23
#include <drizzled/drizzled_error_messages.h>
24
24
#include <drizzled/sql_state.h>
25
#include <drizzled/session.h>
26
#include "drizzled/internal/my_sys.h"
27
#include "drizzled/internal/m_string.h"
30
#include <boost/program_options.hpp>
31
#include <drizzled/module/option_map.h>
34
#include "drizzle_protocol.h"
36
#include "table_function.h"
38
#define PROTOCOL_VERSION 10
40
namespace po= boost::program_options;
41
using namespace drizzled;
44
namespace drizzle_protocol
48
static const uint32_t DRIZZLE_TCP_PORT= 4427;
49
26
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
51
static uint32_t connect_timeout;
52
static uint32_t read_timeout;
53
static uint32_t write_timeout;
54
static uint32_t retry_count;
55
static uint32_t buffer_length;
56
static char* bind_address= NULL;
58
static plugin::TableFunction* drizzle_status_table_function_ptr= NULL;
60
ListenDrizzleProtocol::~ListenDrizzleProtocol()
62
/* This is strdup'd from the options */
66
const char* ListenDrizzleProtocol::getHost(void) const
71
in_port_t ListenDrizzleProtocol::getPort(void) const
77
port= DRIZZLE_TCP_PORT;
79
if ((env = getenv("DRIZZLE_TCP_PORT")))
80
port= (uint32_t) atoi(env);
85
return (in_port_t) port;
88
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
91
new_fd= acceptTcp(fd);
95
return new (nothrow) ClientDrizzleProtocol(new_fd, using_mysql41_protocol);
98
drizzled::atomic<uint64_t> ClientDrizzleProtocol::connectionCount;
99
drizzled::atomic<uint64_t> ClientDrizzleProtocol::failedConnections;
100
drizzled::atomic<uint64_t> ClientDrizzleProtocol::connected;
102
ClientDrizzleProtocol::ClientDrizzleProtocol(int fd, bool using_mysql41_protocol_arg):
103
using_mysql41_protocol(using_mysql41_protocol_arg)
110
if (drizzleclient_net_init_sock(&net, fd, 0, buffer_length))
113
drizzleclient_net_set_read_timeout(&net, read_timeout);
114
drizzleclient_net_set_write_timeout(&net, write_timeout);
115
net.retry_count=retry_count;
118
ClientDrizzleProtocol::~ClientDrizzleProtocol()
121
drizzleclient_vio_close(net.vio);
124
int ClientDrizzleProtocol::getFileDescriptor(void)
126
return drizzleclient_net_get_sd(&net);
129
bool ClientDrizzleProtocol::isConnected()
134
bool ClientDrizzleProtocol::isReading(void)
136
return net.reading_or_writing == 1;
139
bool ClientDrizzleProtocol::isWriting(void)
141
return net.reading_or_writing == 2;
144
bool ClientDrizzleProtocol::flush()
148
bool ret= drizzleclient_net_write(&net, (unsigned char*) packet.ptr(),
154
void ClientDrizzleProtocol::close(void)
158
drizzleclient_net_close(&net);
159
drizzleclient_net_end(&net);
160
connected.decrement();
164
bool ClientDrizzleProtocol::authenticate()
166
bool connection_is_valid;
168
connectionCount.increment();
169
connected.increment();
171
/* Use "connect_timeout" value during connection phase */
172
drizzleclient_net_set_read_timeout(&net, connect_timeout);
173
drizzleclient_net_set_write_timeout(&net, connect_timeout);
175
connection_is_valid= checkConnection();
177
if (connection_is_valid)
181
sendError(session->main_da.sql_errno(), session->main_da.message());
182
failedConnections.increment();
186
/* Connect completed, set read/write timeouts back to default */
187
drizzleclient_net_set_read_timeout(&net, read_timeout);
188
drizzleclient_net_set_write_timeout(&net, write_timeout);
192
bool ClientDrizzleProtocol::readCommand(char **l_packet, uint32_t *packet_length)
195
This thread will do a blocking read from the client which
196
will be interrupted when the next command is received from
197
the client, the connection is closed or "net_wait_timeout"
198
number of seconds has passed
201
/* We can do this much more efficiently with poll timeouts or watcher thread,
202
disabling for now, which means net_wait_timeout == read_timeout. */
203
drizzleclient_net_set_read_timeout(&net,
204
session->variables.net_wait_timeout);
209
*packet_length= drizzleclient_net_read(&net);
210
if (*packet_length == packet_error)
212
/* Check if we can continue without closing the connection */
214
if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
215
my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
216
if (session->main_da.status() == Diagnostics_area::DA_ERROR)
217
sendError(session->main_da.sql_errno(), session->main_da.message());
222
return false; // We have to close it.
229
*l_packet= (char*) net.read_pos;
232
'packet_length' contains length of data, as it was stored in packet
233
header. In case of malformed header, drizzleclient_net_read returns zero.
234
If packet_length is not zero, drizzleclient_net_read ensures that the returned
235
number of bytes was actually read from network.
236
There is also an extra safety measure in drizzleclient_net_read:
237
it sets packet[packet_length]= 0, but only for non-zero packets.
240
if (*packet_length == 0) /* safety */
242
/* Initialize with COM_SLEEP packet */
243
(*l_packet)[0]= (unsigned char) COM_SLEEP;
246
else if (using_mysql41_protocol)
248
/* Map from MySQL commands to Drizzle commands. */
249
switch ((int)(*l_packet)[0])
253
case 2: /* INIT_DB */
257
case 8: /* SHUTDOWN */
258
(*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
262
(*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
267
/* Just drop connection for MySQL commands we don't support. */
268
(*l_packet)[0]= (unsigned char) COM_QUIT;
274
/* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
275
(*l_packet)[*packet_length]= '\0'; /* safety */
278
/* See comment above. */
279
/* Restore read timeout value */
280
drizzleclient_net_set_read_timeout(&net,
281
session->variables.net_read_timeout);
27
/* Declared non-static only because of the embedded library. */
28
static void net_send_error_packet(THD *thd, uint32_t sql_errno, const char *err);
29
static void write_eof_packet(THD *thd, NET *net,
30
uint32_t server_status, uint32_t total_warn_count);
32
bool Protocol::net_store_data(const unsigned char *from, size_t length)
34
ulong packet_length=packet->length();
36
The +9 comes from that strings of length longer than 16M require
37
9 bytes to be stored (see net_store_length).
39
if (packet_length+9+length > packet->alloced_length() &&
40
packet->realloc(packet_length+9+length))
42
unsigned char *to= net_store_length((unsigned char*) packet->ptr()+packet_length, length);
43
memcpy(to,from,length);
44
packet->length((uint) (to+length-(unsigned char*) packet->ptr()));
52
net_store_data() - extended version with character set conversion.
54
It is optimized for short strings whose length after
55
conversion is garanteed to be less than 251, which accupies
56
exactly one byte to store length. It allows not to use
57
the "convert" member as a temporary buffer, conversion
58
is done directly to the "packet" member.
59
The limit 251 is good enough to optimize send_fields()
60
because column, table, database names fit into this limit.
63
bool Protocol::net_store_data(const unsigned char *from, size_t length,
64
const CHARSET_INFO * const from_cs,
65
const CHARSET_INFO * const to_cs)
67
uint32_t dummy_errors;
68
/* Calculate maxumum possible result length */
69
uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
70
if (conv_length > 250)
73
For strings with conv_length greater than 250 bytes
74
we don't know how many bytes we will need to store length: one or two,
75
because we don't know result length until conversion is done.
76
For example, when converting from utf8 (mbmaxlen=3) to latin1,
77
conv_length=300 means that the result length can vary between 100 to 300.
78
length=100 needs one byte, length=300 needs to bytes.
80
Thus conversion directly to "packet" is not worthy.
81
Let's use "convert" as a temporary buffer.
83
return (convert->copy((const char*) from, length, from_cs,
84
to_cs, &dummy_errors) ||
85
net_store_data((const unsigned char*) convert->ptr(), convert->length()));
88
ulong packet_length= packet->length();
89
ulong new_length= packet_length + conv_length + 1;
91
if (new_length > packet->alloced_length() && packet->realloc(new_length))
94
char *length_pos= (char*) packet->ptr() + packet_length;
95
char *to= length_pos + 1;
97
to+= copy_and_convert(to, conv_length, to_cs,
98
(const char*) from, length, from_cs, &dummy_errors);
100
net_store_length((unsigned char*) length_pos, to - length_pos - 1);
101
packet->length((uint) (to - packet->ptr()));
107
Send a error string to client.
110
net_printf_error and net_send_error are low-level functions
111
that shall be used only when a new connection is being
112
established or at server startup.
114
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
115
critical that every error that can be intercepted is issued in one
116
place only, my_message_sql.
118
void net_send_error(THD *thd, uint32_t sql_errno, const char *err)
121
assert(err && err[0]);
124
It's one case when we can push an error even though there
125
is an OK or EOF already.
127
thd->main_da.can_overwrite_status= true;
129
/* Abort multi-result sets */
130
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
132
net_send_error_packet(thd, sql_errno, err);
134
thd->main_da.can_overwrite_status= false;
423
269
int2store(buff,sql_errno);
426
/* The first # is to make the client backward compatible */
272
/* The first # is to make the protocol backward compatible */
428
pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
429
pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
274
pos= (unsigned char*) my_stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
431
char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
432
tmp+= strlen((char*)pos);
434
length= (uint32_t)(tmp-(char*)buff);
276
length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
435
278
err= (char*) buff;
437
drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
439
session->main_da.can_overwrite_status= false;
280
net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
286
Faster net_store_length when we know that length is less than 65536.
287
We keep a separate version for that range because it's widely used in
290
uint32_t is used as agrument type because of MySQL type conventions:
291
- uint32_t for 0..65536
292
- ulong for 0..4294967296
293
- uint64_t for bigger numbers.
296
static unsigned char *net_store_length_fast(unsigned char *packet, uint32_t length)
300
*packet=(unsigned char) length;
304
int2store(packet,(uint) length);
309
Send the status of the current statement execution over network.
311
@param thd in fact, carries two parameters, NET for the transport and
312
Diagnostics_area as the source of status information.
314
In MySQL, there are two types of SQL statements: those that return
315
a result set and those that return status information only.
317
If a statement returns a result set, it consists of 3 parts:
318
- result set meta-data
319
- variable number of result set rows (can be 0)
320
- followed and terminated by EOF or ERROR packet
322
Once the client has seen the meta-data information, it always
323
expects an EOF or ERROR to terminate the result set. If ERROR is
324
received, the result set rows are normally discarded (this is up
325
to the client implementation, libmysql at least does discard them).
326
EOF, on the contrary, means "successfully evaluated the entire
327
result set". Since we don't know how many rows belong to a result
328
set until it's evaluated, EOF/ERROR is the indicator of the end
329
of the row stream. Note, that we can not buffer result set rows
330
on the server -- there may be an arbitrary number of rows. But
331
we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
332
delay sending it till the very end of execution (here), to be able to
333
change EOF to an ERROR if commit failed or some other error occurred
334
during the last cleanup steps taken after execution.
336
A statement that does not return a result set doesn't send result
337
set meta-data either. Instead it returns one of:
340
Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
341
packet is "buffered" in the diagnostics area and sent to the client
342
in the end of statement.
344
@pre The diagnostics area is assigned or disabled. It can not be empty
345
-- we assume that every SQL statement or COM_* command
346
generates OK, ERROR, or EOF status.
348
@post The status information is encoded to protocol format and sent to the
351
@return We conventionally return void, since the only type of error
352
that can happen here is a NET (transport) error, and that one
353
will become visible when we attempt to read from the NET the
355
Diagnostics_area::is_sent is set for debugging purposes only.
358
void net_end_statement(THD *thd)
360
assert(! thd->main_da.is_sent);
362
/* Can not be true, but do not take chances in production. */
363
if (thd->main_da.is_sent)
366
switch (thd->main_da.status()) {
367
case Diagnostics_area::DA_ERROR:
368
/* The query failed, send error to log and abort bootstrap. */
370
thd->main_da.sql_errno(),
371
thd->main_da.message());
373
case Diagnostics_area::DA_EOF:
375
thd->main_da.server_status(),
376
thd->main_da.total_warn_count());
378
case Diagnostics_area::DA_OK:
380
thd->main_da.server_status(),
381
thd->main_da.total_warn_count(),
382
thd->main_da.affected_rows(),
383
thd->main_da.last_insert_id(),
384
thd->main_da.message());
386
case Diagnostics_area::DA_DISABLED:
388
case Diagnostics_area::DA_EMPTY:
391
net_send_ok(thd, thd->server_status, thd->total_warn_count,
395
thd->main_da.is_sent= true;
399
/****************************************************************************
400
Functions used by the protocol functions (like net_send_ok) to store
401
strings and numbers in the header result packet.
402
****************************************************************************/
404
/* The following will only be used for short strings < 65K */
406
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
408
to=net_store_length_fast(to,length);
409
memcpy(to,from,length);
413
unsigned char *net_store_data(unsigned char *to,int32_t from)
416
uint32_t length=(uint) (int10_to_str(from,buff,10)-buff);
417
to=net_store_length_fast(to,length);
418
memcpy(to,buff,length);
422
unsigned char *net_store_data(unsigned char *to,int64_t from)
425
uint32_t length=(uint) (int64_t10_to_str(from,buff,10)-buff);
426
to=net_store_length_fast(to,length);
427
memcpy(to,buff,length);
432
/*****************************************************************************
433
Default Protocol functions
434
*****************************************************************************/
436
void Protocol::init(THD *thd_arg)
439
packet= &thd->packet;
440
convert= &thd->convert_buffer;
444
Finish the result set with EOF packet, as is expected by the client,
445
if there is an error evaluating the next row and a continue handler
449
void Protocol::end_partial_result_set(THD *thd)
451
net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
455
bool Protocol::flush()
457
return net_flush(&thd->net);
443
462
Send name and type of result to client.
445
464
Sum fields has table name empty and field_name.
447
@param Session Thread data object
448
@param list List of items to send to client
449
@param flag Bit mask with the following functions:
466
@param THD Thread data object
467
@param list List of items to send to client
468
@param flag Bit mask with the following functions:
450
469
- 1 send number of rows
451
470
- 2 send default values
452
471
- 4 don't write eof packet
457
1 Error (Note that in this case the error is not sent to the
476
1 Error (Note that in this case the error is not sent to the
460
bool ClientDrizzleProtocol::sendFields(List<Item> *list)
479
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
462
481
List_iterator_fast<Item> it(*list);
464
483
unsigned char buff[80];
465
484
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
485
Protocol_text prot(thd);
486
String *local_packet= prot.storage_packet();
487
const CHARSET_INFO * const thd_charset= thd->variables.character_set_results;
467
unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
468
(void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
489
if (flags & SEND_NUM_ROWS)
490
{ // Packet with number of elements
491
unsigned char *pos= net_store_length(buff, list->elements);
492
(void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
470
495
while ((item=it++))
498
const CHARSET_INFO * const cs= system_charset_info;
474
500
item->make_field(&field);
478
if (store(STRING_WITH_LEN("def")) ||
479
store(field.db_name) ||
480
store(field.table_name) ||
481
store(field.org_table_name) ||
482
store(field.col_name) ||
483
store(field.org_col_name) ||
484
packet.realloc(packet.length()+12))
502
prot.prepare_for_resend();
505
if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
506
prot.store(field.db_name, (uint) strlen(field.db_name),
508
prot.store(field.table_name, (uint) strlen(field.table_name),
510
prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
512
prot.store(field.col_name, (uint) strlen(field.col_name),
514
prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
516
local_packet->realloc(local_packet->length()+12))
487
519
/* Store fixed length fields */
488
pos= (char*) packet.ptr()+packet.length();
489
*pos++= 12; // Length of packed fields
491
int2store(pos, field.charsetnr);
492
int4store(pos+2, field.length);
494
if (using_mysql41_protocol)
520
pos= (char*) local_packet->ptr()+local_packet->length();
521
*pos++= 12; // Length of packed fields
522
if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
496
/* Switch to MySQL field numbering. */
499
case DRIZZLE_TYPE_LONG:
503
case DRIZZLE_TYPE_DOUBLE:
507
case DRIZZLE_TYPE_NULL:
511
case DRIZZLE_TYPE_TIMESTAMP:
515
case DRIZZLE_TYPE_LONGLONG:
519
case DRIZZLE_TYPE_DATETIME:
523
case DRIZZLE_TYPE_DATE:
527
case DRIZZLE_TYPE_VARCHAR:
531
case DRIZZLE_TYPE_DECIMAL:
535
case DRIZZLE_TYPE_ENUM:
539
case DRIZZLE_TYPE_BLOB:
525
int2store(pos, field.charsetnr);
526
int4store(pos+2, field.length);
546
/* Add one to compensate for tinyint removal from enum. */
547
pos[6]= field.type + 1;
530
/* With conversion */
531
uint32_t max_char_len;
532
int2store(pos, thd_charset->number);
534
For TEXT/BLOB columns, field_length describes the maximum data
535
length in bytes. There is no limit to the number of characters
536
that a TEXT column can store, as long as the data fits into
537
the designated space.
538
For the rest of textual columns, field_length is evaluated as
539
char_count * mbmaxlen, where character count is taken from the
540
definition of the column. In other words, the maximum number
541
of characters here is limited by the column definition.
543
max_char_len= field.length / item->collation.collation->mbmaxlen;
544
int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
550
547
int2store(pos+7,field.flags);
551
548
pos[9]= (char) field.decimals;
552
pos[10]= 0; // For the future
553
pos[11]= 0; // For the future
549
pos[10]= 0; // For the future
550
pos[11]= 0; // For the future
556
packet.length((uint32_t) (pos - packet.ptr()));
553
local_packet->length((uint) (pos - local_packet->ptr()));
554
if (flags & SEND_DEFAULTS)
555
item->send(&prot, &tmp); // Send default value
557
break; /* purecov: inspected */
562
Mark the end of meta-data result set, and store session->server_status,
563
to show that there is no cursor.
564
Send no warning information, as it will be sent at statement end.
566
writeEOFPacket(session->server_status, session->total_warn_count);
560
if (flags & SEND_EOF)
563
Mark the end of meta-data result set, and store thd->server_status,
564
to show that there is no cursor.
565
Send no warning information, as it will be sent at statement end.
567
write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
569
return(prepare_for_send(list));
570
572
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
575
bool ClientDrizzleProtocol::store(Field *from)
573
MYF(0)); /* purecov: inspected */
574
return(1); /* purecov: inspected */
578
bool Protocol::write()
580
return(my_net_write(&thd->net, (unsigned char*) packet->ptr(),
586
Send \\0 end terminated string.
588
@param from NULL or \\0 terminated string
591
In most cases one should use store(from, length) instead of this function
599
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
603
uint32_t length= strlen(from);
604
return store(from, length, cs);
609
Send a set of strings as one long string with ',' in between.
612
bool Protocol::store(I_List<i_string>* str_list)
615
String tmp(buf, sizeof(buf), &my_charset_bin);
617
I_List_iterator<i_string> it(*str_list);
626
if ((len= tmp.length()))
627
len--; // Remove last ','
628
return store((char*) tmp.ptr(), len, tmp.charset());
632
/****************************************************************************
633
Functions to handle the simple (default) protocol where everything is
634
This protocol is the one that is used by default between the MySQL server
635
and client when you are not using prepared statements.
637
All data are sent as 'packed-string-length' followed by 'string-data'
638
****************************************************************************/
640
void Protocol_text::prepare_for_resend()
645
bool Protocol_text::store_null()
649
return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
654
Auxilary function to convert string to the given character set
655
and store in network buffer.
658
bool Protocol::store_string_aux(const char *from, size_t length,
659
const CHARSET_INFO * const fromcs,
660
const CHARSET_INFO * const tocs)
662
/* 'tocs' is set 0 when client issues SET character_set_results=NULL */
663
if (tocs && !my_charset_same(fromcs, tocs) &&
664
fromcs != &my_charset_bin &&
665
tocs != &my_charset_bin)
667
/* Store with conversion */
668
return net_store_data((unsigned char*) from, length, fromcs, tocs);
670
/* Store without conversion */
671
return net_store_data((unsigned char*) from, length);
675
bool Protocol_text::store(const char *from, size_t length,
676
const CHARSET_INFO * const fromcs,
677
const CHARSET_INFO * const tocs)
679
return store_string_aux(from, length, fromcs, tocs);
683
bool Protocol_text::store(const char *from, size_t length,
684
const CHARSET_INFO * const fromcs)
686
const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
687
return store_string_aux(from, length, fromcs, tocs);
691
bool Protocol_text::store_tiny(int64_t from)
694
return net_store_data((unsigned char*) buff,
695
(size_t) (int10_to_str((int) from, buff, -10) - buff));
699
bool Protocol_text::store_short(int64_t from)
702
return net_store_data((unsigned char*) buff,
703
(size_t) (int10_to_str((int) from, buff, -10) -
708
bool Protocol_text::store_long(int64_t from)
711
return net_store_data((unsigned char*) buff,
712
(size_t) (int10_to_str((long int)from, buff,
713
(from <0)?-10:10)-buff));
717
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
720
return net_store_data((unsigned char*) buff,
721
(size_t) (int64_t10_to_str(from,buff,
722
unsigned_flag ? 10 : -10)-
727
bool Protocol_text::store_decimal(const my_decimal *d)
729
char buff[DECIMAL_MAX_STR_LENGTH];
730
String str(buff, sizeof(buff), &my_charset_bin);
731
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
732
return net_store_data((unsigned char*) str.ptr(), str.length());
736
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
738
buffer->set_real((double) from, decimals, thd->charset());
739
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
743
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
745
buffer->set_real(from, decimals, thd->charset());
746
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
750
bool Protocol_text::store(Field *field)
752
if (field->is_null())
579
754
char buff[MAX_FIELD_WIDTH];
580
755
String str(buff,sizeof(buff), &my_charset_bin);
584
return netStoreData((const unsigned char *)str.ptr(), str.length());
587
bool ClientDrizzleProtocol::store(void)
591
return packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
594
bool ClientDrizzleProtocol::store(int32_t from)
597
return netStoreData((unsigned char*) buff,
598
(size_t) (internal::int10_to_str(from, buff, -10) - buff));
601
bool ClientDrizzleProtocol::store(uint32_t from)
604
return netStoreData((unsigned char*) buff,
605
(size_t) (internal::int10_to_str(from, buff, 10) - buff));
608
bool ClientDrizzleProtocol::store(int64_t from)
611
return netStoreData((unsigned char*) buff,
612
(size_t) (internal::int64_t10_to_str(from, buff, -10) - buff));
615
bool ClientDrizzleProtocol::store(uint64_t from)
618
return netStoreData((unsigned char*) buff,
619
(size_t) (internal::int64_t10_to_str(from, buff, 10) - buff));
622
bool ClientDrizzleProtocol::store(double from, uint32_t decimals, String *buffer)
624
buffer->set_real(from, decimals, session->charset());
625
return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
628
bool ClientDrizzleProtocol::store(const char *from, size_t length)
630
return netStoreData((const unsigned char *)from, length);
633
bool ClientDrizzleProtocol::wasAborted(void)
635
return net.error && net.vio != 0;
638
bool ClientDrizzleProtocol::haveMoreData(void)
640
return drizzleclient_net_more_data(&net);
643
bool ClientDrizzleProtocol::haveError(void)
645
return net.error || net.vio == 0;
648
bool ClientDrizzleProtocol::checkConnection(void)
658
if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
660
my_error(ER_BAD_HOST_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
664
session->getSecurityContext().setIp(ip);
666
drizzleclient_net_keepalive(&net, true);
668
uint32_t server_capabilites;
670
/* buff[] needs to big enough to hold the server_version variable */
671
char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
673
server_capabilites= CLIENT_BASIC_FLAGS;
675
if (using_mysql41_protocol)
676
server_capabilites|= CLIENT_PROTOCOL_MYSQL41;
679
server_capabilites|= CLIENT_COMPRESS;
680
#endif /* HAVE_COMPRESS */
682
end= buff + strlen(PANDORA_RELEASE_VERSION);
683
if ((end - buff) >= SERVER_VERSION_LENGTH)
684
end= buff + (SERVER_VERSION_LENGTH - 1);
685
memcpy(buff, PANDORA_RELEASE_VERSION, end - buff);
689
int4store((unsigned char*) end, session->variables.pseudo_thread_id);
692
/* We don't use scramble anymore. */
693
memset(end, 'X', SCRAMBLE_LENGTH_323);
694
end+= SCRAMBLE_LENGTH_323;
695
*end++= 0; /* an empty byte for some reason */
697
int2store(end, server_capabilites);
698
/* write server characteristics: up to 16 bytes allowed */
699
end[2]=(char) default_charset_info->number;
700
int2store(end+3, session->server_status);
701
memset(end+5, 0, 13);
704
/* Write scramble tail. */
705
memset(end, 'X', SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
706
end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
707
*end++= 0; /* an empty byte for some reason */
709
/* At this point we write connection message and read reply */
710
if (drizzleclient_net_write_command(&net
711
, (unsigned char) PROTOCOL_VERSION
712
, (unsigned char*) ""
714
, (unsigned char*) buff
715
, (size_t) (end-buff))
716
|| (pkt_len= drizzleclient_net_read(&net)) == packet_error
717
|| pkt_len < MIN_HANDSHAKE_SIZE)
719
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
723
if (packet.alloc(buffer_length))
724
return false; /* The error is set by alloc(). */
726
client_capabilities= uint2korr(net.read_pos);
729
client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
730
session->max_client_packet_length= uint4korr(net.read_pos + 4);
731
end= (char*) net.read_pos + 32;
734
Disable those bits which are not supported by the server.
735
This is a precautionary measure, if the client lies. See Bug#27944.
737
client_capabilities&= server_capabilites;
739
if (end >= (char*) net.read_pos + pkt_len + 2)
741
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
745
net.return_status= &session->server_status;
748
char *passwd= strchr(user, '\0')+1;
749
uint32_t user_len= passwd - user - 1;
753
Old clients send null-terminated string as password; new clients send
754
the size (1 byte) + string (not null-terminated). Hence in case of empty
755
password both send '\0'.
757
This strlen() can't be easily deleted without changing client.
759
Cast *passwd to an unsigned char, so that it doesn't extend the sign for
760
*passwd > 127 and become 2**32-127+ after casting to uint.
762
uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
763
(unsigned char)(*passwd++) : strlen(passwd);
764
l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
766
/* strlen() can't be easily deleted without changing client */
767
uint32_t db_len= l_db ? strlen(l_db) : 0;
769
if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
771
my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
775
/* If username starts and ends in "'", chop them off */
776
if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
783
session->getSecurityContext().setUser(user);
785
return session->checkUser(passwd, passwd_len, l_db);
788
bool ClientDrizzleProtocol::netStoreData(const unsigned char *from, size_t length)
790
size_t packet_length= packet.length();
792
The +9 comes from that strings of length longer than 16M require
793
9 bytes to be stored (see drizzleclient_net_store_length).
795
if (packet_length+9+length > packet.alloced_length() &&
796
packet.realloc(packet_length+9+length))
798
unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet.ptr()+packet_length, length);
799
memcpy(to,from,length);
800
packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
805
Format EOF packet according to the current client and
806
write it to the network output buffer.
809
void ClientDrizzleProtocol::writeEOFPacket(uint32_t server_status,
810
uint32_t total_warn_count)
812
unsigned char buff[5];
814
Don't send warn count during SP execution, as the warn_list
815
is cleared between substatements, and mysqltest gets confused
817
uint32_t tmp= min(total_warn_count, (uint32_t)65535);
818
buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
819
int2store(buff+1, tmp);
821
The following test should never be true, but it's better to do it
822
because if 'is_fatal_error' is set the server is not going to execute
823
other queries (see the if test in dispatch_command / COM_QUERY)
825
if (session->is_fatal_error)
826
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
827
int2store(buff + 3, server_status);
828
drizzleclient_net_write(&net, buff, 5);
831
static int init(module::Context &context)
833
drizzle_status_table_function_ptr= new DrizzleProtocolStatus;
835
context.add(drizzle_status_table_function_ptr);
837
const module::option_map &vm= context.getOptions();
838
if (vm.count("port"))
842
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of port\n"));
847
if (vm.count("connect-timeout"))
849
if (connect_timeout < 1 || connect_timeout > 300)
851
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for connect_timeout\n"));
856
if (vm.count("read-timeout"))
858
if (read_timeout < 1 || read_timeout > 300)
860
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for read_timeout\n"));
865
if (vm.count("write-timeout"))
867
if (write_timeout < 1 || write_timeout > 300)
869
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for write_timeout\n"));
874
if (vm.count("retry-count"))
876
if (retry_count < 1 || retry_count > 100)
878
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for retry_count\n"));
883
if (vm.count("buffer-length"))
885
if (buffer_length < 1024 || buffer_length > 1024*1024)
887
errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for buffer_length\n"));
892
if (vm.count("bind-address"))
894
bind_address= strdup(vm["bind-address"].as<string>().c_str());
902
context.add(new ListenDrizzleProtocol("drizzle_protocol", false));
906
static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
907
N_("Port number to use for connection or 0 for "
908
"default to, in order of "
909
"preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
910
"built-in default (4427)."),
911
NULL, NULL, 0, 0, 65535, 0);
912
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
913
PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
914
NULL, NULL, 10, 1, 300, 0);
915
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
916
N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
917
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
918
N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
919
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
920
N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
921
static DRIZZLE_SYSVAR_UINT(buffer_length, buffer_length, PLUGIN_VAR_RQCMDARG,
922
N_("Buffer length."), NULL, NULL, 16384, 1024,
924
static DRIZZLE_SYSVAR_STR(bind_address, bind_address, PLUGIN_VAR_READONLY,
925
N_("Address to bind to."), NULL, NULL, NULL);
927
static void init_options(drizzled::module::option_context &context)
930
po::value<uint32_t>(&port)->default_value(0),
931
N_("Port number to use for connection or 0 for "
932
"default to, in order of "
933
"preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
934
"built-in default (4427)."));
935
context("connect-timeout",
936
po::value<uint32_t>(&connect_timeout)->default_value(10),
937
N_("Connect Timeout."));
938
context("read-timeout",
939
po::value<uint32_t>(&read_timeout)->default_value(30),
940
N_("Read Timeout."));
941
context("write-timeout",
942
po::value<uint32_t>(&write_timeout)->default_value(60),
943
N_("Write Timeout."));
944
context("retry-count",
945
po::value<uint32_t>(&retry_count)->default_value(10),
947
context("buffer-length",
948
po::value<uint32_t>(&buffer_length)->default_value(16384),
949
N_("Buffer length."));
950
context("bind-address",
952
N_("Address to bind to."));
955
static drizzle_sys_var* sys_variables[]= {
956
DRIZZLE_SYSVAR(port),
957
DRIZZLE_SYSVAR(connect_timeout),
958
DRIZZLE_SYSVAR(read_timeout),
959
DRIZZLE_SYSVAR(write_timeout),
960
DRIZZLE_SYSVAR(retry_count),
961
DRIZZLE_SYSVAR(buffer_length),
962
DRIZZLE_SYSVAR(bind_address),
966
static int drizzle_protocol_connection_count_func(drizzle_show_var *var, char *buff)
968
var->type= SHOW_LONGLONG;
970
*((uint64_t *)buff)= ClientDrizzleProtocol::connectionCount;
974
static int drizzle_protocol_connected_count_func(drizzle_show_var *var, char *buff)
976
var->type= SHOW_LONGLONG;
978
*((uint64_t *)buff)= ClientDrizzleProtocol::connected;
982
static int drizzle_protocol_failed_count_func(drizzle_show_var *var, char *buff)
984
var->type= SHOW_LONGLONG;
986
*((uint64_t *)buff)= ClientDrizzleProtocol::failedConnections;
990
static st_show_var_func_container drizzle_protocol_connection_count=
991
{ &drizzle_protocol_connection_count_func };
993
static st_show_var_func_container drizzle_protocol_connected_count=
994
{ &drizzle_protocol_connected_count_func };
996
static st_show_var_func_container drizzle_protocol_failed_count=
997
{ &drizzle_protocol_failed_count_func };
999
static drizzle_show_var drizzle_protocol_status_variables[]= {
1001
(char*) &drizzle_protocol_connection_count, SHOW_FUNC},
1003
(char*) &drizzle_protocol_connected_count, SHOW_FUNC},
1004
{"Failed_connections",
1005
(char*) &drizzle_protocol_failed_count, SHOW_FUNC},
1006
{NULL, NULL, SHOW_LONGLONG}
1009
DrizzleProtocolStatus::Generator::Generator(drizzled::Field **fields) :
1010
plugin::TableFunction::Generator(fields)
1012
status_var_ptr= drizzle_protocol_status_variables;
1015
bool DrizzleProtocolStatus::Generator::populate()
1017
MY_ALIGNED_BYTE_ARRAY(buff_data, SHOW_VAR_FUNC_BUFF_SIZE, int64_t);
1018
char * const buff= (char *) &buff_data;
1019
drizzle_show_var tmp;
1021
if (status_var_ptr->name)
1023
std::ostringstream oss;
1024
string return_value;
1028
push(status_var_ptr->name);
1030
if (status_var_ptr->type == SHOW_FUNC)
1032
((mysql_show_var_func)((st_show_var_func_container *)status_var_ptr->value)->func)(&tmp, buff);
1038
value= status_var_ptr->value;
1039
type= status_var_ptr->type;
1045
oss << *(uint64_t*) value;
1046
return_value= oss.str();
1051
if (return_value.length())
1063
} /* namespace drizzle_protocol */
1065
DRIZZLE_PLUGIN(drizzle_protocol::init, drizzle_protocol::sys_variables, drizzle_protocol::init_options);
756
const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
758
field->val_str(&str);
760
return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
766
Second_part format ("%06") needs to change when
767
we support 0-6 decimals for time.
770
bool Protocol_text::store(DRIZZLE_TIME *tm)
774
length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
782
length+= sprintf(buff+length, ".%06d",
783
(int)tm->second_part);
784
return net_store_data((unsigned char*) buff, length);
788
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
790
char buff[MAX_DATE_STRING_REP_LENGTH];
791
size_t length= my_date_to_str(tm, buff);
792
return net_store_data((unsigned char*) buff, length);
798
Second_part format ("%06") needs to change when
799
we support 0-6 decimals for time.
802
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
806
uint32_t day= (tm->year || tm->month) ? 0 : tm->day;
807
length= sprintf(buff, "%s%02ld:%02d:%02d",
809
(long) day*24L+(long) tm->hour,
813
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
814
return net_store_data((unsigned char*) buff, length);