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>
24
#include <drizzled/error.h>
25
#include <drizzled/query_id.h>
26
#include <drizzled/sql_state.h>
27
#include <drizzled/session.h>
28
#include "drizzled/internal/my_sys.h"
29
#include "drizzled/internal/m_string.h"
32
#include <boost/program_options.hpp>
33
#include <drizzled/module/option_map.h>
34
#include "drizzled/util/tokenize.h"
35
#include "drizzle_protocol.h"
36
#include "plugin/drizzle_protocol/status_table.h"
38
namespace po= boost::program_options;
39
using namespace drizzled;
42
namespace drizzle_plugin
44
namespace drizzle_protocol
47
std::vector<std::string> ClientDrizzleProtocol::drizzle_admin_ip_addresses;
48
static port_constraint port;
49
static timeout_constraint connect_timeout;
50
static timeout_constraint read_timeout;
51
static timeout_constraint write_timeout;
52
static retry_constraint retry_count;
53
static buffer_constraint buffer_length;
55
static const uint32_t DRIZZLE_TCP_PORT= 4427;
57
ProtocolCounters *ListenDrizzleProtocol::drizzle_counters= new ProtocolCounters();
59
ListenDrizzleProtocol::~ListenDrizzleProtocol()
63
in_port_t ListenDrizzleProtocol::getPort(void) const
68
void ClientDrizzleProtocol::drizzle_compose_ip_addresses(vector<string> options)
70
for (vector<string>::iterator it= options.begin();
74
tokenize(*it, drizzle_admin_ip_addresses, ",", true);
78
bool ClientDrizzleProtocol::isAdminAllowed(void)
80
if (std::find(drizzle_admin_ip_addresses.begin(), drizzle_admin_ip_addresses.end(), session->getSecurityContext().getIp()) != drizzle_admin_ip_addresses.end())
86
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
89
new_fd= acceptTcp(fd);
93
return new ClientDrizzleProtocol(new_fd, getCounters());
96
static int init(drizzled::module::Context &context)
98
const module::option_map &vm= context.getOptions();
100
context.add(new StatusTable);
101
context.add(new ListenDrizzleProtocol("drizzle_protocol", vm["bind-address"].as<std::string>(), true));
102
context.registerVariable(new sys_var_constrained_value_readonly<in_port_t>("port", port));
103
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("connect_timeout", connect_timeout));
104
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("read_timeout", read_timeout));
105
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("write_timeout", write_timeout));
106
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("retry_count", retry_count));
107
context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("buffer_length", buffer_length));
108
context.registerVariable(new sys_var_const_string_val("bind_address",
109
vm["bind-address"].as<std::string>()));
111
context.registerVariable(new sys_var_uint32_t_ptr("max-connections", &ListenDrizzleProtocol::drizzle_counters->max_connections));
117
static void init_options(drizzled::module::option_context &context)
120
po::value<port_constraint>(&port)->default_value(DRIZZLE_TCP_PORT),
121
N_("Port number to use for connection or 0 for default to with Drizzle/MySQL protocol."));
122
context("connect-timeout",
123
po::value<timeout_constraint>(&connect_timeout)->default_value(10),
124
N_("Connect Timeout."));
125
context("read-timeout",
126
po::value<timeout_constraint>(&read_timeout)->default_value(30),
127
N_("Read Timeout."));
128
context("write-timeout",
129
po::value<timeout_constraint>(&write_timeout)->default_value(60),
130
N_("Write Timeout."));
131
context("retry-count",
132
po::value<retry_constraint>(&retry_count)->default_value(10),
134
context("buffer-length",
135
po::value<buffer_constraint>(&buffer_length)->default_value(16384),
136
N_("Buffer length."));
137
context("bind-address",
138
po::value<std::string>()->default_value(""),
139
N_("Address to bind to."));
140
context("max-connections",
141
po::value<uint32_t>(&ListenDrizzleProtocol::drizzle_counters->max_connections)->default_value(1000),
142
N_("Maximum simultaneous connections."));
143
context("admin-ip-addresses",
144
po::value<vector<string> >()->composing()->notifier(&ClientDrizzleProtocol::drizzle_compose_ip_addresses),
145
N_("A restrictive IP address list for incoming admin connections."));
148
} /* namespace drizzle_protocol */
149
} /* namespace drizzle_plugin */
151
DRIZZLE_PLUGIN(drizzle_plugin::drizzle_protocol::init, NULL, drizzle_plugin::drizzle_protocol::init_options);
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>
25
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
26
/* Declared non-static only because of the embedded library. */
27
static void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
28
static void write_eof_packet(THD *thd, NET *net,
29
uint server_status, uint total_warn_count);
31
bool Protocol::net_store_data(const uchar *from, size_t length)
33
ulong packet_length=packet->length();
35
The +9 comes from that strings of length longer than 16M require
36
9 bytes to be stored (see net_store_length).
38
if (packet_length+9+length > packet->alloced_length() &&
39
packet->realloc(packet_length+9+length))
41
uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length);
42
memcpy(to,from,length);
43
packet->length((uint) (to+length-(uchar*) packet->ptr()));
51
net_store_data() - extended version with character set conversion.
53
It is optimized for short strings whose length after
54
conversion is garanteed to be less than 251, which accupies
55
exactly one byte to store length. It allows not to use
56
the "convert" member as a temporary buffer, conversion
57
is done directly to the "packet" member.
58
The limit 251 is good enough to optimize send_fields()
59
because column, table, database names fit into this limit.
62
bool Protocol::net_store_data(const uchar *from, size_t length,
63
const CHARSET_INFO * const from_cs,
64
const CHARSET_INFO * const to_cs)
67
/* Calculate maxumum possible result length */
68
uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
69
if (conv_length > 250)
72
For strings with conv_length greater than 250 bytes
73
we don't know how many bytes we will need to store length: one or two,
74
because we don't know result length until conversion is done.
75
For example, when converting from utf8 (mbmaxlen=3) to latin1,
76
conv_length=300 means that the result length can vary between 100 to 300.
77
length=100 needs one byte, length=300 needs to bytes.
79
Thus conversion directly to "packet" is not worthy.
80
Let's use "convert" as a temporary buffer.
82
return (convert->copy((const char*) from, length, from_cs,
83
to_cs, &dummy_errors) ||
84
net_store_data((const uchar*) convert->ptr(), convert->length()));
87
ulong packet_length= packet->length();
88
ulong new_length= packet_length + conv_length + 1;
90
if (new_length > packet->alloced_length() && packet->realloc(new_length))
93
char *length_pos= (char*) packet->ptr() + packet_length;
94
char *to= length_pos + 1;
96
to+= copy_and_convert(to, conv_length, to_cs,
97
(const char*) from, length, from_cs, &dummy_errors);
99
net_store_length((uchar*) length_pos, to - length_pos - 1);
100
packet->length((uint) (to - packet->ptr()));
106
Send a error string to client.
109
net_printf_error and net_send_error are low-level functions
110
that shall be used only when a new connection is being
111
established or at server startup.
113
For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
114
critical that every error that can be intercepted is issued in one
115
place only, my_message_sql.
117
void net_send_error(THD *thd, uint sql_errno, const char *err)
120
assert(err && err[0]);
123
It's one case when we can push an error even though there
124
is an OK or EOF already.
126
thd->main_da.can_overwrite_status= true;
128
/* Abort multi-result sets */
129
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
131
net_send_error_packet(thd, sql_errno, err);
133
thd->main_da.can_overwrite_status= false;
137
Return ok to the client.
139
The ok packet has the following structure:
141
- 0 : Marker (1 byte)
142
- affected_rows : Stored in 1-9 bytes
143
- id : Stored in 1-9 bytes
144
- server_status : Copy of thd->server_status; Can be used by client
145
to check if we are inside an transaction.
147
- warning_count : Stored in 2 bytes; New in 4.1 protocol
148
- message : Stored as packed length (1-9 bytes) + message.
149
Is not stored if no message.
151
@param thd Thread handler
152
@param affected_rows Number of rows changed by statement
153
@param id Auto_increment id for first row (if used)
154
@param message Message to send to the client (Used by mysql_status)
158
net_send_ok(THD *thd,
159
uint server_status, uint total_warn_count,
160
ha_rows affected_rows, uint64_t id, const char *message)
163
uchar buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
165
if (! net->vio) // hack for re-parsing queries
170
buff[0]=0; // No fields
171
pos=net_store_length(buff+1,affected_rows);
172
pos=net_store_length(pos, id);
174
int2store(pos, server_status);
177
/* We can only return up to 65535 warnings in two bytes */
178
uint tmp= min(total_warn_count, (uint)65535);
182
thd->main_da.can_overwrite_status= true;
184
if (message && message[0])
185
pos= net_store_data(pos, (uchar*) message, strlen(message));
186
VOID(my_net_write(net, buff, (size_t) (pos-buff)));
187
VOID(net_flush(net));
189
thd->main_da.can_overwrite_status= false;
193
Send eof (= end of result set) to the client.
195
The eof packet has the following structure:
197
- 254 (DRIZZLE_PROTOCOL_NO_MORE_DATA) : Marker (1 byte)
198
- warning_count : Stored in 2 bytes; New in 4.1 protocol
199
- status_flag : Stored in 2 bytes;
200
For flags like SERVER_MORE_RESULTS_EXISTS.
202
Note that the warning count will not be sent if 'no_flush' is set as
203
we don't want to report the warning count until all data is sent to the
206
@param thd Thread handler
207
@param no_flush Set to 1 if there will be more data to the client,
208
like in send_fields().
212
net_send_eof(THD *thd, uint server_status, uint total_warn_count)
215
/* Set to true if no active vio, to work well in case of --init-file */
218
thd->main_da.can_overwrite_status= true;
219
write_eof_packet(thd, net, server_status, total_warn_count);
220
VOID(net_flush(net));
221
thd->main_da.can_overwrite_status= false;
227
Format EOF packet according to the current protocol and
228
write it to the network output buffer.
231
static void write_eof_packet(THD *thd, NET *net,
233
uint total_warn_count)
237
Don't send warn count during SP execution, as the warn_list
238
is cleared between substatements, and mysqltest gets confused
240
uint tmp= min(total_warn_count, (uint)65535);
241
buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
242
int2store(buff+1, tmp);
244
The following test should never be true, but it's better to do it
245
because if 'is_fatal_error' is set the server is not going to execute
246
other queries (see the if test in dispatch_command / COM_QUERY)
248
if (thd->is_fatal_error)
249
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
250
int2store(buff + 3, server_status);
251
VOID(my_net_write(net, buff, 5));
254
void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
259
buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
261
uchar buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
268
int2store(buff,sql_errno);
271
/* The first # is to make the protocol backward compatible */
273
pos= (uchar*) stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
275
length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
279
VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
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
uint is used as agrument type because of MySQL type conventions:
292
- ulong for 0..4294967296
293
- uint64_t for bigger numbers.
296
static uchar *net_store_length_fast(uchar *packet, uint length)
300
*packet=(uchar) 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
uchar *net_store_data(uchar *to, const uchar *from, size_t length)
408
to=net_store_length_fast(to,length);
409
memcpy(to,from,length);
413
uchar *net_store_data(uchar *to,int32_t from)
416
uint length=(uint) (int10_to_str(from,buff,10)-buff);
417
to=net_store_length_fast(to,length);
418
memcpy(to,buff,length);
422
uchar *net_store_data(uchar *to,int64_t from)
425
uint 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);
462
Send name and type of result to client.
464
Sum fields has table name empty and field_name.
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:
469
- 1 send number of rows
470
- 2 send default values
471
- 4 don't write eof packet
476
1 Error (Note that in this case the error is not sent to the
479
bool Protocol::send_fields(List<Item> *list, uint flags)
481
List_iterator_fast<Item> it(*list);
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;
489
if (flags & SEND_NUM_ROWS)
490
{ // Packet with number of elements
491
uchar *pos= net_store_length(buff, list->elements);
492
(void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
498
const CHARSET_INFO * const cs= system_charset_info;
500
item->make_field(&field);
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))
519
/* Store fixed length fields */
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)
525
int2store(pos, field.charsetnr);
526
int4store(pos+2, field.length);
530
/* With conversion */
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);
547
int2store(pos+7,field.flags);
548
pos[9]= (char) field.decimals;
549
pos[10]= 0; // For the future
550
pos[11]= 0; // For the future
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 */
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));
572
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
573
MYF(0)); /* purecov: inspected */
574
return(1); /* purecov: inspected */
578
bool Protocol::write()
580
return(my_net_write(&thd->net, (uchar*) packet->ptr(),
586
Send \\0 end terminated string.
588
@param from NullS 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
uint 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((uchar*) from, length, fromcs, tocs);
670
/* Store without conversion */
671
return net_store_data((uchar*) 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((uchar*) 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((uchar*) 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((uchar*) 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((uchar*) 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((uchar*) 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((uchar*) 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((uchar*) buffer->ptr(), buffer->length());
750
bool Protocol_text::store(Field *field)
752
if (field->is_null())
754
char buff[MAX_FIELD_WIDTH];
755
String str(buff,sizeof(buff), &my_charset_bin);
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((uchar*) 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((uchar*) 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
uint 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((uchar*) buff, length);