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>
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;
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
23
#ifdef USE_PRAGMA_IMPLEMENTATION
24
#pragma implementation // gcc: Class implementation
27
#include "mysql_priv.h"
49
30
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);
31
/* Declared non-static only because of the embedded library. */
32
void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
33
void net_send_ok(THD *, uint, uint, ha_rows, ulonglong, const char *);
34
void net_send_eof(THD *thd, uint server_status, uint total_warn_count);
35
static void write_eof_packet(THD *thd, NET *net,
36
uint server_status, uint total_warn_count);
38
bool Protocol::net_store_data(const uchar *from, size_t length)
40
ulong packet_length=packet->length();
42
The +9 comes from that strings of length longer than 16M require
43
9 bytes to be stored (see net_store_length).
45
if (packet_length+9+length > packet->alloced_length() &&
46
packet->realloc(packet_length+9+length))
48
uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length);
49
memcpy(to,from,length);
50
packet->length((uint) (to+length-(uchar*) packet->ptr()));
58
net_store_data() - extended version with character set conversion.
60
It is optimized for short strings whose length after
61
conversion is garanteed to be less than 251, which accupies
62
exactly one byte to store length. It allows not to use
63
the "convert" member as a temporary buffer, conversion
64
is done directly to the "packet" member.
65
The limit 251 is good enough to optimize send_fields()
66
because column, table, database names fit into this limit.
69
bool Protocol::net_store_data(const uchar *from, size_t length,
70
CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
73
/* Calculate maxumum possible result length */
74
uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
75
if (conv_length > 250)
78
For strings with conv_length greater than 250 bytes
79
we don't know how many bytes we will need to store length: one or two,
80
because we don't know result length until conversion is done.
81
For example, when converting from utf8 (mbmaxlen=3) to latin1,
82
conv_length=300 means that the result length can vary between 100 to 300.
83
length=100 needs one byte, length=300 needs to bytes.
85
Thus conversion directly to "packet" is not worthy.
86
Let's use "convert" as a temporary buffer.
88
return (convert->copy((const char*) from, length, from_cs,
89
to_cs, &dummy_errors) ||
90
net_store_data((const uchar*) convert->ptr(), convert->length()));
93
ulong packet_length= packet->length();
94
ulong new_length= packet_length + conv_length + 1;
96
if (new_length > packet->alloced_length() && packet->realloc(new_length))
99
char *length_pos= (char*) packet->ptr() + packet_length;
100
char *to= length_pos + 1;
102
to+= copy_and_convert(to, conv_length, to_cs,
103
(const char*) from, length, from_cs, &dummy_errors);
105
net_store_length((uchar*) length_pos, to - length_pos - 1);
106
packet->length((uint) (to - packet->ptr()));
112
Send a error string to client.
115
net_printf_error and net_send_error are low-level functions
116
that shall be used only when a new connection is being
117
established or at server startup.
119
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
120
critical that every error that can be intercepted is issued in one
121
place only, my_message_sql.
123
void net_send_error(THD *thd, uint sql_errno, const char *err)
125
DBUG_ENTER("net_send_error");
127
DBUG_ASSERT(sql_errno);
128
DBUG_ASSERT(err && err[0]);
130
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno, err));
133
It's one case when we can push an error even though there
134
is an OK or EOF already.
136
thd->main_da.can_overwrite_status= TRUE;
138
/* Abort multi-result sets */
139
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
141
net_send_error_packet(thd, sql_errno, err);
143
thd->main_da.can_overwrite_status= FALSE;
290
151
The ok packet has the following structure:
292
153
- 0 : Marker (1 byte)
293
- affected_rows : Stored in 1-9 bytes
294
- id : Stored in 1-9 bytes
295
- server_status : Copy of session->server_status; Can be used by client
154
- affected_rows : Stored in 1-9 bytes
155
- id : Stored in 1-9 bytes
156
- server_status : Copy of thd->server_status; Can be used by client
296
157
to check if we are inside an transaction.
298
- warning_count : Stored in 2 bytes; New in 4.1 client
299
- message : Stored as packed length (1-9 bytes) + message.
159
- warning_count : Stored in 2 bytes; New in 4.1 protocol
160
- message : Stored as packed length (1-9 bytes) + message.
300
161
Is not stored if no message.
302
@param session Thread handler
303
@param affected_rows Number of rows changed by statement
304
@param id Auto_increment id for first row (if used)
305
@param message Message to send to the client (Used by mysql_status)
163
@param thd Thread handler
164
@param affected_rows Number of rows changed by statement
165
@param id Auto_increment id for first row (if used)
166
@param message Message to send to the client (Used by mysql_status)
308
void ClientDrizzleProtocol::sendOK()
170
net_send_ok(THD *thd,
171
uint server_status, uint total_warn_count,
172
ha_rows affected_rows, ulonglong id, const char *message)
310
unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
311
const char *message= NULL;
314
if (!net.vio) // hack for re-parsing queries
319
buff[0]=0; // No fields
320
if (session->main_da.status() == Diagnostics_area::DA_OK)
322
if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da.found_rows())
323
pos=drizzleclient_net_store_length(buff+1,session->main_da.found_rows());
325
pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
326
pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
327
int2store(pos, session->main_da.server_status());
329
tmp= min(session->main_da.total_warn_count(), (uint32_t)65535);
330
message= session->main_da.message();
334
pos=drizzleclient_net_store_length(buff+1,0);
335
pos=drizzleclient_net_store_length(pos, 0);
336
int2store(pos, session->server_status);
338
tmp= min(session->total_warn_count, (uint32_t)65535);
341
/* We can only return up to 65535 warnings in two bytes */
345
session->main_da.can_overwrite_status= true;
175
uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
178
if (! net->vio) // hack for re-parsing queries
180
DBUG_PRINT("info", ("vio present: NO"));
184
buff[0]=0; // No fields
185
pos=net_store_length(buff+1,affected_rows);
186
pos=net_store_length(pos, id);
187
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
190
("affected_rows: %lu id: %lu status: %u warning_count: %u",
191
(ulong) affected_rows,
193
(uint) (server_status & 0xffff),
194
(uint) total_warn_count));
195
int2store(pos, server_status);
198
/* We can only return up to 65535 warnings in two bytes */
199
uint tmp= min(total_warn_count, 65535);
203
else if (net->return_status) // For 4.0 protocol
205
int2store(pos, server_status);
208
thd->main_da.can_overwrite_status= TRUE;
347
210
if (message && message[0])
349
size_t length= strlen(message);
350
pos=drizzleclient_net_store_length(pos,length);
351
memcpy(pos,(unsigned char*) message,length);
354
drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
355
drizzleclient_net_flush(&net);
357
session->main_da.can_overwrite_status= false;
211
pos= net_store_data(pos, (uchar*) message, strlen(message));
212
VOID(my_net_write(net, buff, (size_t) (pos-buff)));
213
VOID(net_flush(net));
215
thd->main_da.can_overwrite_status= FALSE;
216
DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
221
static uchar eof_buff[1]= { (uchar) 254 }; /* Marker for end of fields */
361
224
Send eof (= end of result set) to the client.
363
226
The eof packet has the following structure:
365
- 254 (DRIZZLE_PROTOCOL_NO_MORE_DATA) : Marker (1 byte)
366
- warning_count : Stored in 2 bytes; New in 4.1 client
367
- status_flag : Stored in 2 bytes;
228
- 254 : Marker (1 byte)
229
- warning_count : Stored in 2 bytes; New in 4.1 protocol
230
- status_flag : Stored in 2 bytes;
368
231
For flags like SERVER_MORE_RESULTS_EXISTS.
370
233
Note that the warning count will not be sent if 'no_flush' is set as
371
234
we don't want to report the warning count until all data is sent to the
375
void ClientDrizzleProtocol::sendEOF()
377
/* Set to true if no active vio, to work well in case of --init-file */
380
session->main_da.can_overwrite_status= true;
381
writeEOFPacket(session->main_da.server_status(),
382
session->main_da.total_warn_count());
383
drizzleclient_net_flush(&net);
384
session->main_da.can_overwrite_status= false;
386
packet.shrink(buffer_length);
390
void ClientDrizzleProtocol::sendError(uint32_t sql_errno, const char *err)
394
buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
396
unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
399
assert(err && err[0]);
402
It's one case when we can push an error even though there
403
is an OK or EOF already.
405
session->main_da.can_overwrite_status= true;
407
/* Abort multi-result sets */
408
session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
411
Send a error string to client.
413
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
414
critical that every error that can be intercepted is issued in one
415
place only, my_message_sql.
237
@param thd Thread handler
238
@param no_flush Set to 1 if there will be more data to the client,
239
like in send_fields().
243
net_send_eof(THD *thd, uint server_status, uint total_warn_count)
246
DBUG_ENTER("net_send_eof");
247
/* Set to TRUE if no active vio, to work well in case of --init-file */
250
thd->main_da.can_overwrite_status= TRUE;
251
write_eof_packet(thd, net, server_status, total_warn_count);
252
VOID(net_flush(net));
253
thd->main_da.can_overwrite_status= FALSE;
254
DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
261
Format EOF packet according to the current protocol and
262
write it to the network output buffer.
265
static void write_eof_packet(THD *thd, NET *net,
267
uint total_warn_count)
269
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
273
Don't send warn count during SP execution, as the warn_list
274
is cleared between substatements, and mysqltest gets confused
276
uint tmp= min(total_warn_count, 65535);
278
int2store(buff+1, tmp);
280
The following test should never be true, but it's better to do it
281
because if 'is_fatal_error' is set the server is not going to execute
282
other queries (see the if test in dispatch_command / COM_QUERY)
284
if (thd->is_fatal_error)
285
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
286
int2store(buff + 3, server_status);
287
VOID(my_net_write(net, buff, 5));
290
VOID(my_net_write(net, eof_buff, 1));
294
Please client to send scrambled_password in old format.
296
@param thd thread handle
304
bool send_old_password_request(THD *thd)
307
return my_net_write(net, eof_buff, 1) || net_flush(net);
311
void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
316
buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512
318
uchar buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos;
320
DBUG_ENTER("send_error_packet");
326
/* In bootstrap it's ok to print on stderr */
327
fprintf(stderr,"ERROR: %d %s\n",sql_errno,err);
423
332
int2store(buff,sql_errno);
426
/* The first # is to make the client 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));
431
char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
432
tmp+= strlen((char*)pos);
434
length= (uint32_t)(tmp-(char*)buff);
334
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
336
/* The first # is to make the protocol backward compatible */
338
pos= (uchar*) strmov((char*) buff+3, mysql_errno_to_sqlstate(sql_errno));
340
length= (uint) (strmake((char*) pos, err, MYSQL_ERRMSG_SIZE-1) -
435
342
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;
344
VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
351
Faster net_store_length when we know that length is less than 65536.
352
We keep a separate version for that range because it's widely used in
355
uint is used as agrument type because of MySQL type conventions:
357
- ulong for 0..4294967296
358
- ulonglong for bigger numbers.
361
static uchar *net_store_length_fast(uchar *packet, uint length)
365
*packet=(uchar) length;
369
int2store(packet,(uint) length);
374
Send the status of the current statement execution over network.
376
@param thd in fact, carries two parameters, NET for the transport and
377
Diagnostics_area as the source of status information.
379
In MySQL, there are two types of SQL statements: those that return
380
a result set and those that return status information only.
382
If a statement returns a result set, it consists of 3 parts:
383
- result set meta-data
384
- variable number of result set rows (can be 0)
385
- followed and terminated by EOF or ERROR packet
387
Once the client has seen the meta-data information, it always
388
expects an EOF or ERROR to terminate the result set. If ERROR is
389
received, the result set rows are normally discarded (this is up
390
to the client implementation, libmysql at least does discard them).
391
EOF, on the contrary, means "successfully evaluated the entire
392
result set". Since we don't know how many rows belong to a result
393
set until it's evaluated, EOF/ERROR is the indicator of the end
394
of the row stream. Note, that we can not buffer result set rows
395
on the server -- there may be an arbitrary number of rows. But
396
we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
397
delay sending it till the very end of execution (here), to be able to
398
change EOF to an ERROR if commit failed or some other error occurred
399
during the last cleanup steps taken after execution.
401
A statement that does not return a result set doesn't send result
402
set meta-data either. Instead it returns one of:
405
Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
406
packet is "buffered" in the diagnostics area and sent to the client
407
in the end of statement.
409
@pre The diagnostics area is assigned or disabled. It can not be empty
410
-- we assume that every SQL statement or COM_* command
411
generates OK, ERROR, or EOF status.
413
@post The status information is encoded to protocol format and sent to the
416
@return We conventionally return void, since the only type of error
417
that can happen here is a NET (transport) error, and that one
418
will become visible when we attempt to read from the NET the
420
Diagnostics_area::is_sent is set for debugging purposes only.
423
void net_end_statement(THD *thd)
425
DBUG_ASSERT(! thd->main_da.is_sent);
427
/* Can not be true, but do not take chances in production. */
428
if (thd->main_da.is_sent)
431
switch (thd->main_da.status()) {
432
case Diagnostics_area::DA_ERROR:
433
/* The query failed, send error to log and abort bootstrap. */
435
thd->main_da.sql_errno(),
436
thd->main_da.message());
438
case Diagnostics_area::DA_EOF:
440
thd->main_da.server_status(),
441
thd->main_da.total_warn_count());
443
case Diagnostics_area::DA_OK:
445
thd->main_da.server_status(),
446
thd->main_da.total_warn_count(),
447
thd->main_da.affected_rows(),
448
thd->main_da.last_insert_id(),
449
thd->main_da.message());
451
case Diagnostics_area::DA_DISABLED:
453
case Diagnostics_area::DA_EMPTY:
456
net_send_ok(thd, thd->server_status, thd->total_warn_count,
460
thd->main_da.is_sent= TRUE;
464
/****************************************************************************
465
Functions used by the protocol functions (like net_send_ok) to store
466
strings and numbers in the header result packet.
467
****************************************************************************/
469
/* The following will only be used for short strings < 65K */
471
uchar *net_store_data(uchar *to, const uchar *from, size_t length)
473
to=net_store_length_fast(to,length);
474
memcpy(to,from,length);
478
uchar *net_store_data(uchar *to,int32 from)
481
uint length=(uint) (int10_to_str(from,buff,10)-buff);
482
to=net_store_length_fast(to,length);
483
memcpy(to,buff,length);
487
uchar *net_store_data(uchar *to,longlong from)
490
uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
491
to=net_store_length_fast(to,length);
492
memcpy(to,buff,length);
497
/*****************************************************************************
498
Default Protocol functions
499
*****************************************************************************/
501
void Protocol::init(THD *thd_arg)
504
packet= &thd->packet;
505
convert= &thd->convert_buffer;
512
Finish the result set with EOF packet, as is expected by the client,
513
if there is an error evaluating the next row and a continue handler
517
void Protocol::end_partial_result_set(THD *thd)
519
net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
523
bool Protocol::flush()
525
return net_flush(&thd->net);
443
530
Send name and type of result to client.
445
532
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:
534
@param THD Thread data object
535
@param list List of items to send to client
536
@param flag Bit mask with the following functions:
450
537
- 1 send number of rows
451
538
- 2 send default values
452
539
- 4 don't write eof packet
457
1 Error (Note that in this case the error is not sent to the
544
1 Error (Note that in this case the error is not sent to the
460
bool ClientDrizzleProtocol::sendFields(List<Item> *list)
547
bool Protocol::send_fields(List<Item> *list, uint flags)
462
549
List_iterator_fast<Item> it(*list);
464
unsigned char buff[80];
465
552
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
467
unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
468
(void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
553
Protocol_text prot(thd);
554
String *local_packet= prot.storage_packet();
555
CHARSET_INFO *thd_charset= thd->variables.character_set_results;
556
DBUG_ENTER("send_fields");
558
if (flags & SEND_NUM_ROWS)
559
{ // Packet with number of elements
560
uchar *pos= net_store_length(buff, list->elements);
561
(void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
565
field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
470
570
while ((item=it++))
573
CHARSET_INFO *cs= system_charset_info;
474
575
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))
487
/* 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)
577
/* Keep things compatible for old clients */
578
if (field.type == MYSQL_TYPE_VARCHAR)
579
field.type= MYSQL_TYPE_VAR_STRING;
581
prot.prepare_for_resend();
583
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
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:
585
if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
586
prot.store(field.db_name, (uint) strlen(field.db_name),
588
prot.store(field.table_name, (uint) strlen(field.table_name),
590
prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
592
prot.store(field.col_name, (uint) strlen(field.col_name),
594
prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
596
local_packet->realloc(local_packet->length()+12))
598
/* Store fixed length fields */
599
pos= (char*) local_packet->ptr()+local_packet->length();
600
*pos++= 12; // Length of packed fields
601
if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
604
int2store(pos, field.charsetnr);
605
int4store(pos+2, field.length);
609
/* With conversion */
611
int2store(pos, thd_charset->number);
613
For TEXT/BLOB columns, field_length describes the maximum data
614
length in bytes. There is no limit to the number of characters
615
that a TEXT column can store, as long as the data fits into
616
the designated space.
617
For the rest of textual columns, field_length is evaluated as
618
char_count * mbmaxlen, where character count is taken from the
619
definition of the column. In other words, the maximum number
620
of characters here is limited by the column definition.
622
max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
623
field.type <= (int) MYSQL_TYPE_BLOB) ?
624
field.length / item->collation.collation->mbminlen :
625
field.length / item->collation.collation->mbmaxlen;
626
int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
629
int2store(pos+7,field.flags);
630
pos[9]= (char) field.decimals;
631
pos[10]= 0; // For the future
632
pos[11]= 0; // For the future
546
/* Add one to compensate for tinyint removal from enum. */
547
pos[6]= field.type + 1;
637
if (prot.store(field.table_name, (uint) strlen(field.table_name),
639
prot.store(field.col_name, (uint) strlen(field.col_name),
641
local_packet->realloc(local_packet->length()+10))
643
pos= (char*) local_packet->ptr()+local_packet->length();
645
#ifdef TO_BE_DELETED_IN_6
646
if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
649
int3store(pos+1,field.length);
653
pos[7]= (char) field.flags;
654
pos[8]= (char) field.decimals;
661
int3store(pos+1,field.length);
665
int2store(pos+7,field.flags);
666
pos[9]= (char) field.decimals;
550
int2store(pos+7,field.flags);
551
pos[9]= (char) field.decimals;
552
pos[10]= 0; // For the future
553
pos[11]= 0; // For the future
556
packet.length((uint32_t) (pos - packet.ptr()));
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);
670
local_packet->length((uint) (pos - local_packet->ptr()));
671
if (flags & SEND_DEFAULTS)
672
item->send(&prot, &tmp); // Send default value
674
break; /* purecov: inspected */
676
field_types[count++]= field.type;
680
if (flags & SEND_EOF)
683
Mark the end of meta-data result set, and store thd->server_status,
684
to show that there is no cursor.
685
Send no warning information, as it will be sent at statement end.
687
write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
689
DBUG_RETURN(prepare_for_send(list));
570
692
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
575
bool ClientDrizzleProtocol::store(Field *from)
693
MYF(0)); /* purecov: inspected */
694
DBUG_RETURN(1); /* purecov: inspected */
698
bool Protocol::write()
700
DBUG_ENTER("Protocol::write");
701
DBUG_RETURN(my_net_write(&thd->net, (uchar*) packet->ptr(),
707
Send \\0 end terminated string.
709
@param from NullS or \\0 terminated string
712
In most cases one should use store(from, length) instead of this function
720
bool Protocol::store(const char *from, CHARSET_INFO *cs)
724
uint length= strlen(from);
725
return store(from, length, cs);
730
Send a set of strings as one long string with ',' in between.
733
bool Protocol::store(I_List<i_string>* str_list)
736
String tmp(buf, sizeof(buf), &my_charset_bin);
738
I_List_iterator<i_string> it(*str_list);
747
if ((len= tmp.length()))
748
len--; // Remove last ','
749
return store((char*) tmp.ptr(), len, tmp.charset());
753
/****************************************************************************
754
Functions to handle the simple (default) protocol where everything is
755
This protocol is the one that is used by default between the MySQL server
756
and client when you are not using prepared statements.
758
All data are sent as 'packed-string-length' followed by 'string-data'
759
****************************************************************************/
761
void Protocol_text::prepare_for_resend()
769
bool Protocol_text::store_null()
776
return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
781
Auxilary function to convert string to the given character set
782
and store in network buffer.
785
bool Protocol::store_string_aux(const char *from, size_t length,
786
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
788
/* 'tocs' is set 0 when client issues SET character_set_results=NULL */
789
if (tocs && !my_charset_same(fromcs, tocs) &&
790
fromcs != &my_charset_bin &&
791
tocs != &my_charset_bin)
793
/* Store with conversion */
794
return net_store_data((uchar*) from, length, fromcs, tocs);
796
/* Store without conversion */
797
return net_store_data((uchar*) from, length);
801
bool Protocol_text::store(const char *from, size_t length,
802
CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
805
DBUG_ASSERT(field_types == 0 ||
806
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
807
(field_types[field_pos] >= MYSQL_TYPE_ENUM && field_types[field_pos] <= MYSQL_TYPE_STRING));
810
return store_string_aux(from, length, fromcs, tocs);
814
bool Protocol_text::store(const char *from, size_t length,
815
CHARSET_INFO *fromcs)
817
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
819
DBUG_ASSERT(field_types == 0 ||
820
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
821
field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
822
(field_types[field_pos] >= MYSQL_TYPE_ENUM && field_types[field_pos] <= MYSQL_TYPE_STRING));
825
return store_string_aux(from, length, fromcs, tocs);
829
bool Protocol_text::store_tiny(longlong from)
832
DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
836
return net_store_data((uchar*) buff,
837
(size_t) (int10_to_str((int) from, buff, -10) - buff));
841
bool Protocol_text::store_short(longlong from)
844
DBUG_ASSERT(field_types == 0 ||
845
field_types[field_pos] == MYSQL_TYPE_YEAR ||
846
field_types[field_pos] == MYSQL_TYPE_SHORT);
850
return net_store_data((uchar*) buff,
851
(size_t) (int10_to_str((int) from, buff, -10) -
856
bool Protocol_text::store_long(longlong from)
859
DBUG_ASSERT(field_types == 0 ||
860
field_types[field_pos] == MYSQL_TYPE_LONG);
864
return net_store_data((uchar*) buff,
865
(size_t) (int10_to_str((long int)from, buff,
866
(from <0)?-10:10)-buff));
870
bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
873
DBUG_ASSERT(field_types == 0 ||
874
field_types[field_pos] == MYSQL_TYPE_LONGLONG);
878
return net_store_data((uchar*) buff,
879
(size_t) (longlong10_to_str(from,buff,
880
unsigned_flag ? 10 : -10)-
885
bool Protocol_text::store_decimal(const my_decimal *d)
888
DBUG_ASSERT(field_types == 0 ||
889
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
892
char buff[DECIMAL_MAX_STR_LENGTH];
893
String str(buff, sizeof(buff), &my_charset_bin);
894
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
895
return net_store_data((uchar*) str.ptr(), str.length());
899
bool Protocol_text::store(float from, uint32 decimals, String *buffer)
902
DBUG_ASSERT(field_types == 0 ||
903
field_types[field_pos] == MYSQL_TYPE_FLOAT);
906
buffer->set_real((double) from, decimals, thd->charset());
907
return net_store_data((uchar*) buffer->ptr(), buffer->length());
911
bool Protocol_text::store(double from, uint32 decimals, String *buffer)
914
DBUG_ASSERT(field_types == 0 ||
915
field_types[field_pos] == MYSQL_TYPE_DOUBLE);
918
buffer->set_real(from, decimals, thd->charset());
919
return net_store_data((uchar*) buffer->ptr(), buffer->length());
923
bool Protocol_text::store(Field *field)
925
if (field->is_null())
579
930
char buff[MAX_FIELD_WIDTH];
580
931
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);
932
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
934
TABLE *table= field->table;
935
my_bitmap_map *old_map= 0;
937
old_map= dbug_tmp_use_all_columns(table, table->read_set);
940
field->val_str(&str);
943
dbug_tmp_restore_column_map(table->read_set, old_map);
946
return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
952
Second_part format ("%06") needs to change when
953
we support 0-6 decimals for time.
956
bool Protocol_text::store(MYSQL_TIME *tm)
959
DBUG_ASSERT(field_types == 0 ||
960
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
961
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
966
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
974
length+= my_sprintf(buff+length,(buff+length, ".%06d",
975
(int)tm->second_part));
976
return net_store_data((uchar*) buff, length);
980
bool Protocol_text::store_date(MYSQL_TIME *tm)
983
DBUG_ASSERT(field_types == 0 ||
984
field_types[field_pos] == MYSQL_TYPE_DATE);
987
char buff[MAX_DATE_STRING_REP_LENGTH];
988
size_t length= my_date_to_str(tm, buff);
989
return net_store_data((uchar*) buff, length);
995
Second_part format ("%06") needs to change when
996
we support 0-6 decimals for time.
999
bool Protocol_text::store_time(MYSQL_TIME *tm)
1002
DBUG_ASSERT(field_types == 0 ||
1003
field_types[field_pos] == MYSQL_TYPE_TIME);
1008
uint day= (tm->year || tm->month) ? 0 : tm->day;
1009
length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
1011
(long) day*24L+(long) tm->hour,
1014
if (tm->second_part)
1015
length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
1016
return net_store_data((uchar*) buff, length);