1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2010 Brian Aker
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; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
23
#include <drizzled/gettext.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>
24
23
#include <drizzled/error.h>
25
#include <drizzled/query_id.h>
24
#include <drizzled/sql_state.h>
25
#include <libdrizzleclient/pack.h>
26
#include <drizzled/protocol.h>
26
27
#include <drizzled/session.h>
27
#include <drizzled/internal/my_sys.h>
28
#include <drizzled/internal/m_string.h>
31
#include <boost/program_options.hpp>
32
#include <drizzled/module/option_map.h>
33
#include <drizzled/util/tokenize.h>
34
#include "drizzle_protocol.h"
36
namespace po= boost::program_options;
37
using namespace drizzled;
40
namespace drizzle_plugin
42
namespace drizzle_protocol
45
std::vector<std::string> ClientDrizzleProtocol::drizzle_admin_ip_addresses;
46
static port_constraint port;
47
static timeout_constraint connect_timeout;
48
static timeout_constraint read_timeout;
49
static timeout_constraint write_timeout;
50
static retry_constraint retry_count;
51
static buffer_constraint buffer_length;
53
static const uint32_t DRIZZLE_TCP_PORT= 4427;
55
ProtocolCounters *ListenDrizzleProtocol::drizzle_counters= new ProtocolCounters();
57
ListenDrizzleProtocol::~ListenDrizzleProtocol()
61
in_port_t ListenDrizzleProtocol::getPort(void) const
66
void ClientDrizzleProtocol::drizzle_compose_ip_addresses(vector<string> options)
68
for (vector<string>::iterator it= options.begin();
72
tokenize(*it, drizzle_admin_ip_addresses, ",", true);
76
bool ClientDrizzleProtocol::isAdminAllowed(void)
78
if (std::find(drizzle_admin_ip_addresses.begin(), drizzle_admin_ip_addresses.end(), session->user()->address()) != drizzle_admin_ip_addresses.end())
84
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
87
new_fd= acceptTcp(fd);
91
return new ClientDrizzleProtocol(new_fd, getCounters());
94
static int init(drizzled::module::Context &context)
96
const module::option_map &vm= context.getOptions();
98
ListenDrizzleProtocol *protocol=new ListenDrizzleProtocol("drizzle_protocol", vm["bind-address"].as<std::string>(), true);
99
protocol->addCountersToTable();
100
context.add(protocol);
101
context.registerVariable(new sys_var_constrained_value_readonly<in_port_t>("port", port));
102
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("connect_timeout", connect_timeout));
103
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("read_timeout", read_timeout));
104
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("write_timeout", write_timeout));
105
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("retry_count", retry_count));
106
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("buffer_length", buffer_length));
107
context.registerVariable(new sys_var_const_string_val("bind_address",
108
vm["bind-address"].as<std::string>()));
110
context.registerVariable(new sys_var_uint32_t_ptr("max-connections", &ListenDrizzleProtocol::drizzle_counters->max_connections));
116
static void init_options(drizzled::module::option_context &context)
119
po::value<port_constraint>(&port)->default_value(DRIZZLE_TCP_PORT),
120
N_("Port number to use for connection or 0 for default to with Drizzle/MySQL protocol."));
121
context("connect-timeout",
122
po::value<timeout_constraint>(&connect_timeout)->default_value(10),
123
N_("Connect Timeout."));
124
context("read-timeout",
125
po::value<timeout_constraint>(&read_timeout)->default_value(30),
126
N_("Read Timeout."));
127
context("write-timeout",
128
po::value<timeout_constraint>(&write_timeout)->default_value(60),
129
N_("Write Timeout."));
130
context("retry-count",
131
po::value<retry_constraint>(&retry_count)->default_value(10),
133
context("buffer-length",
134
po::value<buffer_constraint>(&buffer_length)->default_value(16384),
135
N_("Buffer length."));
136
context("bind-address",
137
po::value<std::string>()->default_value(""),
138
N_("Address to bind to."));
139
context("max-connections",
140
po::value<uint32_t>(&ListenDrizzleProtocol::drizzle_counters->max_connections)->default_value(1000),
141
N_("Maximum simultaneous connections."));
142
context("admin-ip-addresses",
143
po::value<vector<string> >()->composing()->notifier(&ClientDrizzleProtocol::drizzle_compose_ip_addresses),
144
N_("A restrictive IP address list for incoming admin connections."));
147
} /* namespace drizzle_protocol */
148
} /* namespace drizzle_plugin */
150
DRIZZLE_PLUGIN(drizzle_plugin::drizzle_protocol::init, NULL, drizzle_plugin::drizzle_protocol::init_options);
29
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
30
/* Declared non-static only because of the embedded library. */
31
static void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err);
32
static void write_eof_packet(Session *session, NET *net,
33
uint32_t server_status, uint32_t total_warn_count);
35
bool Protocol::net_store_data(const unsigned char *from, size_t length)
37
size_t packet_length= packet->length();
39
The +9 comes from that strings of length longer than 16M require
40
9 bytes to be stored (see drizzleclient_net_store_length).
42
if (packet_length+9+length > packet->alloced_length() &&
43
packet->realloc(packet_length+9+length))
45
unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet->ptr()+packet_length, length);
46
memcpy(to,from,length);
47
packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
55
net_store_data() - extended version with character set conversion.
57
It is optimized for short strings whose length after
58
conversion is garanteed to be less than 251, which accupies
59
exactly one byte to store length. It allows not to use
60
the "convert" member as a temporary buffer, conversion
61
is done directly to the "packet" member.
62
The limit 251 is good enough to optimize send_fields()
63
because column, table, database names fit into this limit.
66
bool Protocol::net_store_data(const unsigned char *from, size_t length,
67
const CHARSET_INFO * const from_cs,
68
const CHARSET_INFO * const to_cs)
70
uint32_t dummy_errors;
71
/* Calculate maxumum possible result length */
72
uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
73
if (conv_length > 250)
76
For strings with conv_length greater than 250 bytes
77
we don't know how many bytes we will need to store length: one or two,
78
because we don't know result length until conversion is done.
79
For example, when converting from utf8 (mbmaxlen=3) to latin1,
80
conv_length=300 means that the result length can vary between 100 to 300.
81
length=100 needs one byte, length=300 needs to bytes.
83
Thus conversion directly to "packet" is not worthy.
84
Let's use "convert" as a temporary buffer.
86
return (convert->copy((const char*) from, length, from_cs,
87
to_cs, &dummy_errors) ||
88
net_store_data((const unsigned char*) convert->ptr(), convert->length()));
91
size_t packet_length= packet->length();
92
size_t new_length= packet_length + conv_length + 1;
94
if (new_length > packet->alloced_length() && packet->realloc(new_length))
97
char *length_pos= (char*) packet->ptr() + packet_length;
98
char *to= length_pos + 1;
100
to+= copy_and_convert(to, conv_length, to_cs,
101
(const char*) from, length, from_cs, &dummy_errors);
103
drizzleclient_net_store_length((unsigned char*) length_pos, to - length_pos - 1);
104
packet->length((uint32_t) (to - packet->ptr()));
110
Send a error string to client.
113
net_printf_error and net_send_error are low-level functions
114
that shall be used only when a new connection is being
115
established or at server startup.
117
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
118
critical that every error that can be intercepted is issued in one
119
place only, my_message_sql.
121
void net_send_error(Session *session, uint32_t sql_errno, const char *err)
124
assert(err && err[0]);
127
It's one case when we can push an error even though there
128
is an OK or EOF already.
130
session->main_da.can_overwrite_status= true;
132
/* Abort multi-result sets */
133
session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
135
net_send_error_packet(session, sql_errno, err);
137
session->main_da.can_overwrite_status= false;
141
Return ok to the client.
143
The ok packet has the following structure:
145
- 0 : Marker (1 byte)
146
- affected_rows : Stored in 1-9 bytes
147
- id : Stored in 1-9 bytes
148
- server_status : Copy of session->server_status; Can be used by client
149
to check if we are inside an transaction.
151
- warning_count : Stored in 2 bytes; New in 4.1 protocol
152
- message : Stored as packed length (1-9 bytes) + message.
153
Is not stored if no message.
155
@param session Thread handler
156
@param affected_rows Number of rows changed by statement
157
@param id Auto_increment id for first row (if used)
158
@param message Message to send to the client (Used by mysql_status)
162
net_send_ok(Session *session,
163
uint32_t server_status, uint32_t total_warn_count,
164
ha_rows affected_rows, uint64_t id, const char *message)
166
NET *net= &session->net;
167
unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
169
if (! net->vio) // hack for re-parsing queries
174
buff[0]=0; // No fields
175
pos=drizzleclient_net_store_length(buff+1,affected_rows);
176
pos=drizzleclient_net_store_length(pos, id);
178
int2store(pos, server_status);
181
/* We can only return up to 65535 warnings in two bytes */
182
uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
186
session->main_da.can_overwrite_status= true;
188
if (message && message[0])
189
pos= net_store_data(pos, (unsigned char*) message, strlen(message));
190
drizzleclient_net_write(net, buff, (size_t) (pos-buff));
191
drizzleclient_net_flush(net);
193
session->main_da.can_overwrite_status= false;
197
Send eof (= end of result set) to the client.
199
The eof packet has the following structure:
201
- 254 (DRIZZLE_PROTOCOL_NO_MORE_DATA) : Marker (1 byte)
202
- warning_count : Stored in 2 bytes; New in 4.1 protocol
203
- status_flag : Stored in 2 bytes;
204
For flags like SERVER_MORE_RESULTS_EXISTS.
206
Note that the warning count will not be sent if 'no_flush' is set as
207
we don't want to report the warning count until all data is sent to the
210
@param session Thread handler
211
@param no_flush Set to 1 if there will be more data to the client,
212
like in send_fields().
216
net_send_eof(Session *session, uint32_t server_status, uint32_t total_warn_count)
218
NET *net= &session->net;
219
/* Set to true if no active vio, to work well in case of --init-file */
222
session->main_da.can_overwrite_status= true;
223
write_eof_packet(session, net, server_status, total_warn_count);
224
drizzleclient_net_flush(net);
225
session->main_da.can_overwrite_status= false;
231
Format EOF packet according to the current protocol and
232
write it to the network output buffer.
235
static void write_eof_packet(Session *session, NET *net,
236
uint32_t server_status,
237
uint32_t total_warn_count)
239
unsigned char buff[5];
241
Don't send warn count during SP execution, as the warn_list
242
is cleared between substatements, and mysqltest gets confused
244
uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
245
buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
246
int2store(buff+1, tmp);
248
The following test should never be true, but it's better to do it
249
because if 'is_fatal_error' is set the server is not going to execute
250
other queries (see the if test in dispatch_command / COM_QUERY)
252
if (session->is_fatal_error)
253
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
254
int2store(buff + 3, server_status);
255
drizzleclient_net_write(net, buff, 5);
258
void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err)
260
NET *net= &session->net;
263
buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
265
unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
272
int2store(buff,sql_errno);
275
/* The first # is to make the protocol backward compatible */
277
pos= (unsigned char*) strcpy((char*) buff+3, drizzleclient_errno_to_sqlstate(sql_errno));
278
pos+= strlen(drizzleclient_errno_to_sqlstate(sql_errno));
280
char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
281
tmp+= strlen((char*)pos);
283
length= (uint32_t)(tmp-(char*)buff);
286
drizzleclient_net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
292
Faster drizzleclient_net_store_length when we know that length is less than 65536.
293
We keep a separate version for that range because it's widely used in
296
uint32_t is used as agrument type because of MySQL type conventions:
297
- uint32_t for 0..65536
298
- ulong for 0..4294967296
299
- uint64_t for bigger numbers.
302
static unsigned char *drizzleclient_net_store_length_fast(unsigned char *packet, uint32_t length)
306
*packet=(unsigned char) length;
310
int2store(packet,(uint32_t) length);
316
Send the status of the current statement execution over network.
318
@param session in fact, carries two parameters, NET for the transport and
319
Diagnostics_area as the source of status information.
321
In MySQL, there are two types of SQL statements: those that return
322
a result set and those that return status information only.
324
If a statement returns a result set, it consists of 3 parts:
325
- result set meta-data
326
- variable number of result set rows (can be 0)
327
- followed and terminated by EOF or ERROR packet
329
Once the client has seen the meta-data information, it always
330
expects an EOF or ERROR to terminate the result set. If ERROR is
331
received, the result set rows are normally discarded (this is up
332
to the client implementation, libmysql at least does discard them).
333
EOF, on the contrary, means "successfully evaluated the entire
334
result set". Since we don't know how many rows belong to a result
335
set until it's evaluated, EOF/ERROR is the indicator of the end
336
of the row stream. Note, that we can not buffer result set rows
337
on the server -- there may be an arbitrary number of rows. But
338
we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
339
delay sending it till the very end of execution (here), to be able to
340
change EOF to an ERROR if commit failed or some other error occurred
341
during the last cleanup steps taken after execution.
343
A statement that does not return a result set doesn't send result
344
set meta-data either. Instead it returns one of:
347
Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
348
packet is "buffered" in the diagnostics area and sent to the client
349
in the end of statement.
351
@pre The diagnostics area is assigned or disabled. It can not be empty
352
-- we assume that every SQL statement or COM_* command
353
generates OK, ERROR, or EOF status.
355
@post The status information is encoded to protocol format and sent to the
358
@return We conventionally return void, since the only type of error
359
that can happen here is a NET (transport) error, and that one
360
will become visible when we attempt to read from the NET the
362
Diagnostics_area::is_sent is set for debugging purposes only.
365
void drizzleclient_net_end_statement(Session *session)
367
assert(! session->main_da.is_sent);
369
/* Can not be true, but do not take chances in production. */
370
if (session->main_da.is_sent)
373
switch (session->main_da.status()) {
374
case Diagnostics_area::DA_ERROR:
375
/* The query failed, send error to log and abort bootstrap. */
376
net_send_error(session,
377
session->main_da.sql_errno(),
378
session->main_da.message());
380
case Diagnostics_area::DA_EOF:
381
net_send_eof(session,
382
session->main_da.server_status(),
383
session->main_da.total_warn_count());
385
case Diagnostics_area::DA_OK:
387
session->main_da.server_status(),
388
session->main_da.total_warn_count(),
389
session->main_da.affected_rows(),
390
session->main_da.last_insert_id(),
391
session->main_da.message());
393
case Diagnostics_area::DA_DISABLED:
395
case Diagnostics_area::DA_EMPTY:
397
//TODO: Something is being masked here by commenting this out
399
net_send_ok(session, session->server_status, session->total_warn_count,
403
session->main_da.is_sent= true;
407
/****************************************************************************
408
Functions used by the protocol functions (like net_send_ok) to store
409
strings and numbers in the header result packet.
410
****************************************************************************/
412
/* The following will only be used for short strings < 65K */
414
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
416
to=drizzleclient_net_store_length_fast(to,length);
417
memcpy(to,from,length);
421
unsigned char *net_store_data(unsigned char *to,int32_t from)
424
uint32_t length=(uint32_t) (int10_to_str(from,buff,10)-buff);
425
to=drizzleclient_net_store_length_fast(to,length);
426
memcpy(to,buff,length);
430
unsigned char *net_store_data(unsigned char *to,int64_t from)
433
uint32_t length=(uint32_t) (int64_t10_to_str(from,buff,10)-buff);
434
to=drizzleclient_net_store_length_fast(to,length);
435
memcpy(to,buff,length);
440
/*****************************************************************************
441
Default Protocol functions
442
*****************************************************************************/
444
void Protocol::init(Session *session_arg)
447
packet= &session->packet;
448
convert= &session->convert_buffer;
452
bool Protocol::flush()
454
return drizzleclient_net_flush(&session->net);
459
Send name and type of result to client.
461
Sum fields has table name empty and field_name.
463
@param Session Thread data object
464
@param list List of items to send to client
465
@param flag Bit mask with the following functions:
466
- 1 send number of rows
467
- 2 send default values
468
- 4 don't write eof packet
473
1 Error (Note that in this case the error is not sent to the
476
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
478
List_iterator_fast<Item> it(*list);
480
unsigned char buff[80];
481
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
482
Protocol_text prot(session);
483
String *local_packet= prot.storage_packet();
484
const CHARSET_INFO * const session_charset= default_charset_info;
486
if (flags & SEND_NUM_ROWS)
487
{ // Packet with number of elements
488
unsigned char *pos= drizzleclient_net_store_length(buff, list->elements);
489
(void) drizzleclient_net_write(&session->net, buff, (size_t) (pos-buff));
495
const CHARSET_INFO * const cs= system_charset_info;
497
item->make_field(&field);
499
prot.prepare_for_resend();
502
if (prot.store(STRING_WITH_LEN("def"), cs, session_charset) ||
503
prot.store(field.db_name, (uint32_t) strlen(field.db_name),
504
cs, session_charset) ||
505
prot.store(field.table_name, (uint32_t) strlen(field.table_name),
506
cs, session_charset) ||
507
prot.store(field.org_table_name, (uint32_t) strlen(field.org_table_name),
508
cs, session_charset) ||
509
prot.store(field.col_name, (uint32_t) strlen(field.col_name),
510
cs, session_charset) ||
511
prot.store(field.org_col_name, (uint32_t) strlen(field.org_col_name),
512
cs, session_charset) ||
513
local_packet->realloc(local_packet->length()+12))
516
/* Store fixed length fields */
517
pos= (char*) local_packet->ptr()+local_packet->length();
518
*pos++= 12; // Length of packed fields
519
if (item->collation.collation == &my_charset_bin || session_charset == NULL)
522
int2store(pos, field.charsetnr);
523
int4store(pos+2, field.length);
527
/* With conversion */
528
uint32_t max_char_len;
529
int2store(pos, session_charset->number);
531
For TEXT/BLOB columns, field_length describes the maximum data
532
length in bytes. There is no limit to the number of characters
533
that a TEXT column can store, as long as the data fits into
534
the designated space.
535
For the rest of textual columns, field_length is evaluated as
536
char_count * mbmaxlen, where character count is taken from the
537
definition of the column. In other words, the maximum number
538
of characters here is limited by the column definition.
540
max_char_len= field.length / item->collation.collation->mbmaxlen;
541
int4store(pos+2, max_char_len * session_charset->mbmaxlen);
544
int2store(pos+7,field.flags);
545
pos[9]= (char) field.decimals;
546
pos[10]= 0; // For the future
547
pos[11]= 0; // For the future
550
local_packet->length((uint32_t) (pos - local_packet->ptr()));
551
if (flags & SEND_DEFAULTS)
552
item->send(&prot, &tmp); // Send default value
554
break; /* purecov: inspected */
557
if (flags & SEND_EOF)
560
Mark the end of meta-data result set, and store session->server_status,
561
to show that there is no cursor.
562
Send no warning information, as it will be sent at statement end.
564
write_eof_packet(session, &session->net, session->server_status, session->total_warn_count);
566
return(prepare_for_send(list));
569
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
570
MYF(0)); /* purecov: inspected */
571
return(1); /* purecov: inspected */
575
bool Protocol::write()
577
return(drizzleclient_net_write(&session->net, (unsigned char*) packet->ptr(),
583
Send \\0 end terminated string.
585
@param from NULL or \\0 terminated string
588
In most cases one should use store(from, length) instead of this function
596
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
600
uint32_t length= strlen(from);
601
return store(from, length, cs);
606
Send a set of strings as one long string with ',' in between.
609
bool Protocol::store(I_List<i_string>* str_list)
612
String tmp(buf, sizeof(buf), &my_charset_bin);
614
I_List_iterator<i_string> it(*str_list);
623
if ((len= tmp.length()))
624
len--; // Remove last ','
625
return store((char*) tmp.ptr(), len, tmp.charset());
629
bool Protocol::store(String *str)
631
return store((char*) str->ptr(), str->length(), str->charset());
634
void Protocol::free()
640
/****************************************************************************
641
Functions to handle the simple (default) protocol where everything is
642
This protocol is the one that is used by default between the MySQL server
643
and client when you are not using prepared statements.
645
All data are sent as 'packed-string-length' followed by 'string-data'
646
****************************************************************************/
648
void Protocol_text::prepare_for_resend()
653
bool Protocol_text::store_null()
657
return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
662
Auxilary function to convert string to the given character set
663
and store in network buffer.
666
bool Protocol::store_string_aux(const char *from, size_t length,
667
const CHARSET_INFO * const fromcs,
668
const CHARSET_INFO * const tocs)
670
/* 'tocs' is set 0 when client issues SET character_set_results=NULL */
671
if (tocs && !my_charset_same(fromcs, tocs) &&
672
fromcs != &my_charset_bin &&
673
tocs != &my_charset_bin)
675
/* Store with conversion */
676
return net_store_data((unsigned char*) from, length, fromcs, tocs);
678
/* Store without conversion */
679
return net_store_data((unsigned char*) from, length);
683
bool Protocol_text::store(const char *from, size_t length,
684
const CHARSET_INFO * const fromcs,
685
const CHARSET_INFO * const tocs)
687
return store_string_aux(from, length, fromcs, tocs);
691
bool Protocol_text::store(const char *from, size_t length,
692
const CHARSET_INFO * const fromcs)
694
const CHARSET_INFO * const tocs= default_charset_info;
695
return store_string_aux(from, length, fromcs, tocs);
699
bool Protocol_text::store_tiny(int64_t from)
702
return net_store_data((unsigned char*) buff,
703
(size_t) (int10_to_str((int) from, buff, -10) - buff));
707
bool Protocol_text::store_short(int64_t from)
710
return net_store_data((unsigned char*) buff,
711
(size_t) (int10_to_str((int) from, buff, -10) -
716
bool Protocol_text::store_long(int64_t from)
719
return net_store_data((unsigned char*) buff,
720
(size_t) (int10_to_str((long int)from, buff,
721
(from <0)?-10:10)-buff));
725
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
728
return net_store_data((unsigned char*) buff,
729
(size_t) (int64_t10_to_str(from,buff,
730
unsigned_flag ? 10 : -10)-
735
bool Protocol_text::store_decimal(const my_decimal *d)
737
char buff[DECIMAL_MAX_STR_LENGTH];
738
String str(buff, sizeof(buff), &my_charset_bin);
739
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
740
return net_store_data((unsigned char*) str.ptr(), str.length());
744
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
746
buffer->set_real((double) from, decimals, session->charset());
747
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
751
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
753
buffer->set_real(from, decimals, session->charset());
754
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
758
bool Protocol_text::store(Field *field)
760
if (field->is_null())
762
char buff[MAX_FIELD_WIDTH];
763
String str(buff,sizeof(buff), &my_charset_bin);
764
const CHARSET_INFO * const tocs= default_charset_info;
766
field->val_str(&str);
768
return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
774
Second_part format ("%06") needs to change when
775
we support 0-6 decimals for time.
778
bool Protocol_text::store(DRIZZLE_TIME *tm)
782
length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
790
length+= sprintf(buff+length, ".%06d",
791
(int)tm->second_part);
792
return net_store_data((unsigned char*) buff, length);
796
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
798
char buff[MAX_DATE_STRING_REP_LENGTH];
799
size_t length= my_date_to_str(tm, buff);
800
return net_store_data((unsigned char*) buff, length);
806
Second_part format ("%06") needs to change when
807
we support 0-6 decimals for time.
810
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
814
uint32_t day= (tm->year || tm->month) ? 0 : tm->day;
815
length= sprintf(buff, "%s%02ld:%02d:%02d",
817
(long) day*24L+(long) tm->hour,
821
length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
822
return net_store_data((unsigned char*) buff, length);