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"
30
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
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;
149
Return ok to the client.
151
The ok packet has the following structure:
153
- 0 : Marker (1 byte)
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
157
to check if we are inside an transaction.
159
- warning_count : Stored in 2 bytes; New in 4.1 protocol
160
- message : Stored as packed length (1-9 bytes) + message.
161
Is not stored if no message.
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)
170
net_send_ok(THD *thd,
171
uint server_status, uint total_warn_count,
172
ha_rows affected_rows, ulonglong id, const char *message)
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;
210
if (message && message[0])
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 */
224
Send eof (= end of result set) to the client.
226
The eof packet has the following structure:
228
- 254 : Marker (1 byte)
229
- warning_count : Stored in 2 bytes; New in 4.1 protocol
230
- status_flag : Stored in 2 bytes;
231
For flags like SERVER_MORE_RESULTS_EXISTS.
233
Note that the warning count will not be sent if 'no_flush' is set as
234
we don't want to report the warning count until all data is sent to the
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);
332
int2store(buff,sql_errno);
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) -
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);
530
Send name and type of result to client.
532
Sum fields has table name empty and field_name.
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:
537
- 1 send number of rows
538
- 2 send default values
539
- 4 don't write eof packet
544
1 Error (Note that in this case the error is not sent to the
547
bool Protocol::send_fields(List<Item> *list, uint flags)
549
List_iterator_fast<Item> it(*list);
552
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
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) *
573
CHARSET_INFO *cs= system_charset_info;
575
item->make_field(&field);
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)
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
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;
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));
692
my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
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_DECIMAL ||
807
field_types[field_pos] == MYSQL_TYPE_BIT ||
808
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
809
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
810
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
813
return store_string_aux(from, length, fromcs, tocs);
817
bool Protocol_text::store(const char *from, size_t length,
818
CHARSET_INFO *fromcs)
820
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
822
DBUG_ASSERT(field_types == 0 ||
823
field_types[field_pos] == MYSQL_TYPE_DECIMAL ||
824
field_types[field_pos] == MYSQL_TYPE_BIT ||
825
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
826
field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
827
(field_types[field_pos] >= MYSQL_TYPE_ENUM &&
828
field_types[field_pos] <= MYSQL_TYPE_GEOMETRY));
831
return store_string_aux(from, length, fromcs, tocs);
835
bool Protocol_text::store_tiny(longlong from)
838
DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
842
return net_store_data((uchar*) buff,
843
(size_t) (int10_to_str((int) from, buff, -10) - buff));
847
bool Protocol_text::store_short(longlong from)
850
DBUG_ASSERT(field_types == 0 ||
851
field_types[field_pos] == MYSQL_TYPE_YEAR ||
852
field_types[field_pos] == MYSQL_TYPE_SHORT);
856
return net_store_data((uchar*) buff,
857
(size_t) (int10_to_str((int) from, buff, -10) -
862
bool Protocol_text::store_long(longlong from)
865
DBUG_ASSERT(field_types == 0 ||
866
field_types[field_pos] == MYSQL_TYPE_INT24 ||
867
field_types[field_pos] == MYSQL_TYPE_LONG);
871
return net_store_data((uchar*) buff,
872
(size_t) (int10_to_str((long int)from, buff,
873
(from <0)?-10:10)-buff));
877
bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
880
DBUG_ASSERT(field_types == 0 ||
881
field_types[field_pos] == MYSQL_TYPE_LONGLONG);
885
return net_store_data((uchar*) buff,
886
(size_t) (longlong10_to_str(from,buff,
887
unsigned_flag ? 10 : -10)-
892
bool Protocol_text::store_decimal(const my_decimal *d)
895
DBUG_ASSERT(field_types == 0 ||
896
field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
899
char buff[DECIMAL_MAX_STR_LENGTH];
900
String str(buff, sizeof(buff), &my_charset_bin);
901
(void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
902
return net_store_data((uchar*) str.ptr(), str.length());
906
bool Protocol_text::store(float from, uint32 decimals, String *buffer)
909
DBUG_ASSERT(field_types == 0 ||
910
field_types[field_pos] == MYSQL_TYPE_FLOAT);
913
buffer->set_real((double) from, decimals, thd->charset());
914
return net_store_data((uchar*) buffer->ptr(), buffer->length());
918
bool Protocol_text::store(double from, uint32 decimals, String *buffer)
921
DBUG_ASSERT(field_types == 0 ||
922
field_types[field_pos] == MYSQL_TYPE_DOUBLE);
925
buffer->set_real(from, decimals, thd->charset());
926
return net_store_data((uchar*) buffer->ptr(), buffer->length());
930
bool Protocol_text::store(Field *field)
932
if (field->is_null())
937
char buff[MAX_FIELD_WIDTH];
938
String str(buff,sizeof(buff), &my_charset_bin);
939
CHARSET_INFO *tocs= this->thd->variables.character_set_results;
941
TABLE *table= field->table;
942
my_bitmap_map *old_map= 0;
944
old_map= dbug_tmp_use_all_columns(table, table->read_set);
947
field->val_str(&str);
950
dbug_tmp_restore_column_map(table->read_set, old_map);
953
return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
959
Second_part format ("%06") needs to change when
960
we support 0-6 decimals for time.
963
bool Protocol_text::store(MYSQL_TIME *tm)
966
DBUG_ASSERT(field_types == 0 ||
967
field_types[field_pos] == MYSQL_TYPE_DATETIME ||
968
field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
973
length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
981
length+= my_sprintf(buff+length,(buff+length, ".%06d",
982
(int)tm->second_part));
983
return net_store_data((uchar*) buff, length);
987
bool Protocol_text::store_date(MYSQL_TIME *tm)
990
DBUG_ASSERT(field_types == 0 ||
991
field_types[field_pos] == MYSQL_TYPE_DATE);
994
char buff[MAX_DATE_STRING_REP_LENGTH];
995
size_t length= my_date_to_str(tm, buff);
996
return net_store_data((uchar*) buff, length);
1002
Second_part format ("%06") needs to change when
1003
we support 0-6 decimals for time.
1006
bool Protocol_text::store_time(MYSQL_TIME *tm)
1009
DBUG_ASSERT(field_types == 0 ||
1010
field_types[field_pos] == MYSQL_TYPE_TIME);
1015
uint day= (tm->year || tm->month) ? 0 : tm->day;
1016
length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
1018
(long) day*24L+(long) tm->hour,
1021
if (tm->second_part)
1022
length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
1023
return net_store_data((uchar*) buff, length);