~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/protocol.cc

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2003 MySQL AB
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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 */
 
15
 
 
16
/**
 
17
  @file
 
18
 
 
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
 
21
*/
 
22
 
 
23
#ifdef USE_PRAGMA_IMPLEMENTATION
 
24
#pragma implementation                          // gcc: Class implementation
 
25
#endif
 
26
 
 
27
#include "mysql_priv.h"
 
28
#include <stdarg.h>
 
29
 
 
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);
 
37
 
 
38
bool Protocol::net_store_data(const uchar *from, size_t length)
 
39
{
 
40
  ulong packet_length=packet->length();
 
41
  /* 
 
42
     The +9 comes from that strings of length longer than 16M require
 
43
     9 bytes to be stored (see net_store_length).
 
44
  */
 
45
  if (packet_length+9+length > packet->alloced_length() &&
 
46
      packet->realloc(packet_length+9+length))
 
47
    return 1;
 
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()));
 
51
  return 0;
 
52
}
 
53
 
 
54
 
 
55
 
 
56
 
 
57
/*
 
58
  net_store_data() - extended version with character set conversion.
 
59
  
 
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.
 
67
*/
 
68
 
 
69
bool Protocol::net_store_data(const uchar *from, size_t length,
 
70
                              CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
 
71
{
 
72
  uint dummy_errors;
 
73
  /* Calculate maxumum possible result length */
 
74
  uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
 
75
  if (conv_length > 250)
 
76
  {
 
77
    /*
 
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.
 
84
      
 
85
      Thus conversion directly to "packet" is not worthy.
 
86
      Let's use "convert" as a temporary buffer.
 
87
    */
 
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()));
 
91
  }
 
92
 
 
93
  ulong packet_length= packet->length();
 
94
  ulong new_length= packet_length + conv_length + 1;
 
95
 
 
96
  if (new_length > packet->alloced_length() && packet->realloc(new_length))
 
97
    return 1;
 
98
 
 
99
  char *length_pos= (char*) packet->ptr() + packet_length;
 
100
  char *to= length_pos + 1;
 
101
 
 
102
  to+= copy_and_convert(to, conv_length, to_cs,
 
103
                        (const char*) from, length, from_cs, &dummy_errors);
 
104
 
 
105
  net_store_length((uchar*) length_pos, to - length_pos - 1);
 
106
  packet->length((uint) (to - packet->ptr()));
 
107
  return 0;
 
108
}
 
109
 
 
110
 
 
111
/**
 
112
  Send a error string to client.
 
113
 
 
114
  Design note:
 
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.
 
118
 
 
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.
 
122
*/
 
123
void net_send_error(THD *thd, uint sql_errno, const char *err)
 
124
{
 
125
  DBUG_ENTER("net_send_error");
 
126
 
 
127
  DBUG_ASSERT(sql_errno);
 
128
  DBUG_ASSERT(err && err[0]);
 
129
 
 
130
  DBUG_PRINT("enter",("sql_errno: %d  err: %s", sql_errno, err));
 
131
 
 
132
  /*
 
133
    It's one case when we can push an error even though there
 
134
    is an OK or EOF already.
 
135
  */
 
136
  thd->main_da.can_overwrite_status= TRUE;
 
137
 
 
138
  /* Abort multi-result sets */
 
139
  thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
140
 
 
141
  net_send_error_packet(thd, sql_errno, err);
 
142
 
 
143
  thd->main_da.can_overwrite_status= FALSE;
 
144
 
 
145
  DBUG_VOID_RETURN;
 
146
}
 
147
 
 
148
/**
 
149
  Return ok to the client.
 
150
 
 
151
  The ok packet has the following structure:
 
152
 
 
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.
 
158
  New in 4.0 protocol
 
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.
 
162
 
 
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)
 
167
*/
 
168
 
 
169
void
 
170
net_send_ok(THD *thd,
 
171
            uint server_status, uint total_warn_count,
 
172
            ha_rows affected_rows, ulonglong id, const char *message)
 
173
{
 
174
  NET *net= &thd->net;
 
175
  uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
 
176
  DBUG_ENTER("my_ok");
 
177
 
 
178
  if (! net->vio)       // hack for re-parsing queries
 
179
  {
 
180
    DBUG_PRINT("info", ("vio present: NO"));
 
181
    DBUG_VOID_RETURN;
 
182
  }
 
183
 
 
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)
 
188
  {
 
189
    DBUG_PRINT("info",
 
190
               ("affected_rows: %lu  id: %lu  status: %u  warning_count: %u",
 
191
                (ulong) affected_rows,          
 
192
                (ulong) id,
 
193
                (uint) (server_status & 0xffff),
 
194
                (uint) total_warn_count));
 
195
    int2store(pos, server_status);
 
196
    pos+=2;
 
197
 
 
198
    /* We can only return up to 65535 warnings in two bytes */
 
199
    uint tmp= min(total_warn_count, 65535);
 
200
    int2store(pos, tmp);
 
201
    pos+= 2;
 
202
  }
 
203
  else if (net->return_status)                  // For 4.0 protocol
 
204
  {
 
205
    int2store(pos, server_status);
 
206
    pos+=2;
 
207
  }
 
208
  thd->main_da.can_overwrite_status= TRUE;
 
209
 
 
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));
 
214
 
 
215
  thd->main_da.can_overwrite_status= FALSE;
 
216
  DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
 
217
 
 
218
  DBUG_VOID_RETURN;
 
219
}
 
220
 
 
221
static uchar eof_buff[1]= { (uchar) 254 };      /* Marker for end of fields */
 
222
 
 
223
/**
 
224
  Send eof (= end of result set) to the client.
 
225
 
 
226
  The eof packet has the following structure:
 
227
 
 
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.
 
232
 
 
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
 
235
  client.
 
236
 
 
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().
 
240
*/    
 
241
 
 
242
void
 
243
net_send_eof(THD *thd, uint server_status, uint total_warn_count)
 
244
{
 
245
  NET *net= &thd->net;
 
246
  DBUG_ENTER("net_send_eof");
 
247
  /* Set to TRUE if no active vio, to work well in case of --init-file */
 
248
  if (net->vio != 0)
 
249
  {
 
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"));
 
255
  }
 
256
  DBUG_VOID_RETURN;
 
257
}
 
258
 
 
259
 
 
260
/**
 
261
  Format EOF packet according to the current protocol and
 
262
  write it to the network output buffer.
 
263
*/
 
264
 
 
265
static void write_eof_packet(THD *thd, NET *net,
 
266
                             uint server_status,
 
267
                             uint total_warn_count)
 
268
{
 
269
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
270
  {
 
271
    uchar buff[5];
 
272
    /*
 
273
      Don't send warn count during SP execution, as the warn_list
 
274
      is cleared between substatements, and mysqltest gets confused
 
275
    */
 
276
    uint tmp= min(total_warn_count, 65535);
 
277
    buff[0]= 254;
 
278
    int2store(buff+1, tmp);
 
279
    /*
 
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)
 
283
    */
 
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));
 
288
  }
 
289
  else
 
290
    VOID(my_net_write(net, eof_buff, 1));
 
291
}
 
292
 
 
293
/**
 
294
  Please client to send scrambled_password in old format.
 
295
     
 
296
  @param thd thread handle
 
297
 
 
298
  @retval
 
299
    0  ok
 
300
  @retval
 
301
   !0  error
 
302
*/
 
303
 
 
304
bool send_old_password_request(THD *thd)
 
305
{
 
306
  NET *net= &thd->net;
 
307
  return my_net_write(net, eof_buff, 1) || net_flush(net);
 
308
}
 
309
 
 
310
 
 
311
void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
 
312
{
 
313
  NET *net= &thd->net;
 
314
  uint length;
 
315
  /*
 
316
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512
 
317
  */
 
318
  uchar buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos;
 
319
 
 
320
  DBUG_ENTER("send_error_packet");
 
321
 
 
322
  if (net->vio == 0)
 
323
  {
 
324
    if (thd->bootstrap)
 
325
    {
 
326
      /* In bootstrap it's ok to print on stderr */
 
327
      fprintf(stderr,"ERROR: %d  %s\n",sql_errno,err);
 
328
    }
 
329
    DBUG_VOID_RETURN;
 
330
  }
 
331
 
 
332
  int2store(buff,sql_errno);
 
333
  pos= buff+2;
 
334
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
335
  {
 
336
    /* The first # is to make the protocol backward compatible */
 
337
    buff[2]= '#';
 
338
    pos= (uchar*) strmov((char*) buff+3, mysql_errno_to_sqlstate(sql_errno));
 
339
  }
 
340
  length= (uint) (strmake((char*) pos, err, MYSQL_ERRMSG_SIZE-1) -
 
341
                  (char*) buff);
 
342
  err= (char*) buff;
 
343
 
 
344
  VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
 
345
                         length));
 
346
  DBUG_VOID_RETURN;
 
347
}
 
348
 
 
349
 
 
350
/**
 
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
 
353
  libmysql.
 
354
 
 
355
  uint is used as agrument type because of MySQL type conventions:
 
356
  - uint for 0..65536
 
357
  - ulong for 0..4294967296
 
358
  - ulonglong for bigger numbers.
 
359
*/
 
360
 
 
361
static uchar *net_store_length_fast(uchar *packet, uint length)
 
362
{
 
363
  if (length < 251)
 
364
  {
 
365
    *packet=(uchar) length;
 
366
    return packet+1;
 
367
  }
 
368
  *packet++=252;
 
369
  int2store(packet,(uint) length);
 
370
  return packet+2;
 
371
}
 
372
 
 
373
/**
 
374
  Send the status of the current statement execution over network.
 
375
 
 
376
  @param  thd   in fact, carries two parameters, NET for the transport and
 
377
                Diagnostics_area as the source of status information.
 
378
 
 
379
  In MySQL, there are two types of SQL statements: those that return
 
380
  a result set and those that return status information only.
 
381
 
 
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
 
386
 
 
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.
 
400
 
 
401
  A statement that does not return a result set doesn't send result
 
402
  set meta-data either. Instead it returns one of:
 
403
  - OK packet
 
404
  - ERROR packet.
 
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.
 
408
 
 
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.
 
412
 
 
413
  @post The status information is encoded to protocol format and sent to the
 
414
        client.
 
415
 
 
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
 
419
          next command.
 
420
          Diagnostics_area::is_sent is set for debugging purposes only.
 
421
*/
 
422
 
 
423
void net_end_statement(THD *thd)
 
424
{
 
425
  DBUG_ASSERT(! thd->main_da.is_sent);
 
426
 
 
427
  /* Can not be true, but do not take chances in production. */
 
428
  if (thd->main_da.is_sent)
 
429
    return;
 
430
 
 
431
  switch (thd->main_da.status()) {
 
432
  case Diagnostics_area::DA_ERROR:
 
433
    /* The query failed, send error to log and abort bootstrap. */
 
434
    net_send_error(thd,
 
435
                   thd->main_da.sql_errno(),
 
436
                   thd->main_da.message());
 
437
    break;
 
438
  case Diagnostics_area::DA_EOF:
 
439
    net_send_eof(thd,
 
440
                 thd->main_da.server_status(),
 
441
                 thd->main_da.total_warn_count());
 
442
    break;
 
443
  case Diagnostics_area::DA_OK:
 
444
    net_send_ok(thd,
 
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());
 
450
    break;
 
451
  case Diagnostics_area::DA_DISABLED:
 
452
    break;
 
453
  case Diagnostics_area::DA_EMPTY:
 
454
  default:
 
455
    DBUG_ASSERT(0);
 
456
    net_send_ok(thd, thd->server_status, thd->total_warn_count,
 
457
                0, 0, NULL);
 
458
    break;
 
459
  }
 
460
  thd->main_da.is_sent= TRUE;
 
461
}
 
462
 
 
463
 
 
464
/****************************************************************************
 
465
  Functions used by the protocol functions (like net_send_ok) to store
 
466
  strings and numbers in the header result packet.
 
467
****************************************************************************/
 
468
 
 
469
/* The following will only be used for short strings < 65K */
 
470
 
 
471
uchar *net_store_data(uchar *to, const uchar *from, size_t length)
 
472
{
 
473
  to=net_store_length_fast(to,length);
 
474
  memcpy(to,from,length);
 
475
  return to+length;
 
476
}
 
477
 
 
478
uchar *net_store_data(uchar *to,int32 from)
 
479
{
 
480
  char buff[20];
 
481
  uint length=(uint) (int10_to_str(from,buff,10)-buff);
 
482
  to=net_store_length_fast(to,length);
 
483
  memcpy(to,buff,length);
 
484
  return to+length;
 
485
}
 
486
 
 
487
uchar *net_store_data(uchar *to,longlong from)
 
488
{
 
489
  char buff[22];
 
490
  uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
 
491
  to=net_store_length_fast(to,length);
 
492
  memcpy(to,buff,length);
 
493
  return to+length;
 
494
}
 
495
 
 
496
 
 
497
/*****************************************************************************
 
498
  Default Protocol functions
 
499
*****************************************************************************/
 
500
 
 
501
void Protocol::init(THD *thd_arg)
 
502
{
 
503
  thd=thd_arg;
 
504
  packet= &thd->packet;
 
505
  convert= &thd->convert_buffer;
 
506
#ifndef DBUG_OFF
 
507
  field_types= 0;
 
508
#endif
 
509
}
 
510
 
 
511
/**
 
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
 
514
  for the error.
 
515
*/
 
516
 
 
517
void Protocol::end_partial_result_set(THD *thd)
 
518
{
 
519
  net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
 
520
}
 
521
 
 
522
 
 
523
bool Protocol::flush()
 
524
{
 
525
  return net_flush(&thd->net);
 
526
}
 
527
 
 
528
 
 
529
/**
 
530
  Send name and type of result to client.
 
531
 
 
532
  Sum fields has table name empty and field_name.
 
533
 
 
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
 
540
 
 
541
  @retval
 
542
    0   ok
 
543
  @retval
 
544
    1   Error  (Note that in this case the error is not sent to the
 
545
    client)
 
546
*/
 
547
bool Protocol::send_fields(List<Item> *list, uint flags)
 
548
{
 
549
  List_iterator_fast<Item> it(*list);
 
550
  Item *item;
 
551
  uchar buff[80];
 
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");
 
557
 
 
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));
 
562
  }
 
563
 
 
564
#ifndef DBUG_OFF
 
565
  field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
 
566
                                              list->elements);
 
567
  uint count= 0;
 
568
#endif
 
569
 
 
570
  while ((item=it++))
 
571
  {
 
572
    char *pos;
 
573
    CHARSET_INFO *cs= system_charset_info;
 
574
    Send_field field;
 
575
    item->make_field(&field);
 
576
 
 
577
    /* Keep things compatible for old clients */
 
578
    if (field.type == MYSQL_TYPE_VARCHAR)
 
579
      field.type= MYSQL_TYPE_VAR_STRING;
 
580
 
 
581
    prot.prepare_for_resend();
 
582
 
 
583
    if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
584
    {
 
585
      if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
 
586
          prot.store(field.db_name, (uint) strlen(field.db_name),
 
587
                     cs, thd_charset) ||
 
588
          prot.store(field.table_name, (uint) strlen(field.table_name),
 
589
                     cs, thd_charset) ||
 
590
          prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
 
591
                     cs, thd_charset) ||
 
592
          prot.store(field.col_name, (uint) strlen(field.col_name),
 
593
                     cs, thd_charset) ||
 
594
          prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
 
595
                     cs, thd_charset) ||
 
596
          local_packet->realloc(local_packet->length()+12))
 
597
        goto err;
 
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)
 
602
      {
 
603
        /* No conversion */
 
604
        int2store(pos, field.charsetnr);
 
605
        int4store(pos+2, field.length);
 
606
      }
 
607
      else
 
608
      {
 
609
        /* With conversion */
 
610
        uint max_char_len;
 
611
        int2store(pos, thd_charset->number);
 
612
        /*
 
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.
 
621
        */
 
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);
 
627
      }
 
628
      pos[6]= field.type;
 
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
 
633
      pos+= 12;
 
634
    }
 
635
    else
 
636
    {
 
637
      if (prot.store(field.table_name, (uint) strlen(field.table_name),
 
638
                     cs, thd_charset) ||
 
639
          prot.store(field.col_name, (uint) strlen(field.col_name),
 
640
                     cs, thd_charset) ||
 
641
          local_packet->realloc(local_packet->length()+10))
 
642
        goto err;
 
643
      pos= (char*) local_packet->ptr()+local_packet->length();
 
644
 
 
645
#ifdef TO_BE_DELETED_IN_6
 
646
      if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
 
647
      {
 
648
        pos[0]=3;
 
649
        int3store(pos+1,field.length);
 
650
        pos[4]=1;
 
651
        pos[5]=field.type;
 
652
        pos[6]=2;
 
653
        pos[7]= (char) field.flags;
 
654
        pos[8]= (char) field.decimals;
 
655
        pos+= 9;
 
656
      }
 
657
      else
 
658
#endif
 
659
      {
 
660
        pos[0]=3;
 
661
        int3store(pos+1,field.length);
 
662
        pos[4]=1;
 
663
        pos[5]=field.type;
 
664
        pos[6]=3;
 
665
        int2store(pos+7,field.flags);
 
666
        pos[9]= (char) field.decimals;
 
667
        pos+= 10;
 
668
      }
 
669
    }
 
670
    local_packet->length((uint) (pos - local_packet->ptr()));
 
671
    if (flags & SEND_DEFAULTS)
 
672
      item->send(&prot, &tmp);                  // Send default value
 
673
    if (prot.write())
 
674
      break;                                    /* purecov: inspected */
 
675
#ifndef DBUG_OFF
 
676
    field_types[count++]= field.type;
 
677
#endif
 
678
  }
 
679
 
 
680
  if (flags & SEND_EOF)
 
681
  {
 
682
    /*
 
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.
 
686
    */
 
687
    write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
 
688
  }
 
689
  DBUG_RETURN(prepare_for_send(list));
 
690
 
 
691
err:
 
692
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
 
693
             MYF(0));   /* purecov: inspected */
 
694
  DBUG_RETURN(1);                               /* purecov: inspected */
 
695
}
 
696
 
 
697
 
 
698
bool Protocol::write()
 
699
{
 
700
  DBUG_ENTER("Protocol::write");
 
701
  DBUG_RETURN(my_net_write(&thd->net, (uchar*) packet->ptr(),
 
702
                           packet->length()));
 
703
}
 
704
 
 
705
 
 
706
/**
 
707
  Send \\0 end terminated string.
 
708
 
 
709
  @param from   NullS or \\0 terminated string
 
710
 
 
711
  @note
 
712
    In most cases one should use store(from, length) instead of this function
 
713
 
 
714
  @retval
 
715
    0           ok
 
716
  @retval
 
717
    1           error
 
718
*/
 
719
 
 
720
bool Protocol::store(const char *from, CHARSET_INFO *cs)
 
721
{
 
722
  if (!from)
 
723
    return store_null();
 
724
  uint length= strlen(from);
 
725
  return store(from, length, cs);
 
726
}
 
727
 
 
728
 
 
729
/**
 
730
  Send a set of strings as one long string with ',' in between.
 
731
*/
 
732
 
 
733
bool Protocol::store(I_List<i_string>* str_list)
 
734
{
 
735
  char buf[256];
 
736
  String tmp(buf, sizeof(buf), &my_charset_bin);
 
737
  uint32 len;
 
738
  I_List_iterator<i_string> it(*str_list);
 
739
  i_string* s;
 
740
 
 
741
  tmp.length(0);
 
742
  while ((s=it++))
 
743
  {
 
744
    tmp.append(s->ptr);
 
745
    tmp.append(',');
 
746
  }
 
747
  if ((len= tmp.length()))
 
748
    len--;                                      // Remove last ','
 
749
  return store((char*) tmp.ptr(), len,  tmp.charset());
 
750
}
 
751
 
 
752
 
 
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.
 
757
 
 
758
  All data are sent as 'packed-string-length' followed by 'string-data'
 
759
****************************************************************************/
 
760
 
 
761
void Protocol_text::prepare_for_resend()
 
762
{
 
763
  packet->length(0);
 
764
#ifndef DBUG_OFF
 
765
  field_pos= 0;
 
766
#endif
 
767
}
 
768
 
 
769
bool Protocol_text::store_null()
 
770
{
 
771
#ifndef DBUG_OFF
 
772
  field_pos++;
 
773
#endif
 
774
  char buff[1];
 
775
  buff[0]= (char)251;
 
776
  return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
 
777
}
 
778
 
 
779
 
 
780
/**
 
781
  Auxilary function to convert string to the given character set
 
782
  and store in network buffer.
 
783
*/
 
784
 
 
785
bool Protocol::store_string_aux(const char *from, size_t length,
 
786
                                CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
 
787
{
 
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)
 
792
  {
 
793
    /* Store with conversion */
 
794
    return net_store_data((uchar*) from, length, fromcs, tocs);
 
795
  }
 
796
  /* Store without conversion */
 
797
  return net_store_data((uchar*) from, length);
 
798
}
 
799
 
 
800
 
 
801
bool Protocol_text::store(const char *from, size_t length,
 
802
                          CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
 
803
{
 
804
#ifndef DBUG_OFF
 
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));
 
811
  field_pos++;
 
812
#endif
 
813
  return store_string_aux(from, length, fromcs, tocs);
 
814
}
 
815
 
 
816
 
 
817
bool Protocol_text::store(const char *from, size_t length,
 
818
                          CHARSET_INFO *fromcs)
 
819
{
 
820
  CHARSET_INFO *tocs= this->thd->variables.character_set_results;
 
821
#ifndef DBUG_OFF
 
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));
 
829
  field_pos++;
 
830
#endif
 
831
  return store_string_aux(from, length, fromcs, tocs);
 
832
}
 
833
 
 
834
 
 
835
bool Protocol_text::store_tiny(longlong from)
 
836
{
 
837
#ifndef DBUG_OFF
 
838
  DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
 
839
  field_pos++;
 
840
#endif
 
841
  char buff[20];
 
842
  return net_store_data((uchar*) buff,
 
843
                        (size_t) (int10_to_str((int) from, buff, -10) - buff));
 
844
}
 
845
 
 
846
 
 
847
bool Protocol_text::store_short(longlong from)
 
848
{
 
849
#ifndef DBUG_OFF
 
850
  DBUG_ASSERT(field_types == 0 ||
 
851
              field_types[field_pos] == MYSQL_TYPE_YEAR ||
 
852
              field_types[field_pos] == MYSQL_TYPE_SHORT);
 
853
  field_pos++;
 
854
#endif
 
855
  char buff[20];
 
856
  return net_store_data((uchar*) buff,
 
857
                        (size_t) (int10_to_str((int) from, buff, -10) -
 
858
                                  buff));
 
859
}
 
860
 
 
861
 
 
862
bool Protocol_text::store_long(longlong from)
 
863
{
 
864
#ifndef DBUG_OFF
 
865
  DBUG_ASSERT(field_types == 0 ||
 
866
              field_types[field_pos] == MYSQL_TYPE_INT24 ||
 
867
              field_types[field_pos] == MYSQL_TYPE_LONG);
 
868
  field_pos++;
 
869
#endif
 
870
  char buff[20];
 
871
  return net_store_data((uchar*) buff,
 
872
                        (size_t) (int10_to_str((long int)from, buff,
 
873
                                               (from <0)?-10:10)-buff));
 
874
}
 
875
 
 
876
 
 
877
bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
 
878
{
 
879
#ifndef DBUG_OFF
 
880
  DBUG_ASSERT(field_types == 0 ||
 
881
              field_types[field_pos] == MYSQL_TYPE_LONGLONG);
 
882
  field_pos++;
 
883
#endif
 
884
  char buff[22];
 
885
  return net_store_data((uchar*) buff,
 
886
                        (size_t) (longlong10_to_str(from,buff,
 
887
                                                    unsigned_flag ? 10 : -10)-
 
888
                                  buff));
 
889
}
 
890
 
 
891
 
 
892
bool Protocol_text::store_decimal(const my_decimal *d)
 
893
{
 
894
#ifndef DBUG_OFF
 
895
  DBUG_ASSERT(field_types == 0 ||
 
896
              field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
 
897
  field_pos++;
 
898
#endif
 
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());
 
903
}
 
904
 
 
905
 
 
906
bool Protocol_text::store(float from, uint32 decimals, String *buffer)
 
907
{
 
908
#ifndef DBUG_OFF
 
909
  DBUG_ASSERT(field_types == 0 ||
 
910
              field_types[field_pos] == MYSQL_TYPE_FLOAT);
 
911
  field_pos++;
 
912
#endif
 
913
  buffer->set_real((double) from, decimals, thd->charset());
 
914
  return net_store_data((uchar*) buffer->ptr(), buffer->length());
 
915
}
 
916
 
 
917
 
 
918
bool Protocol_text::store(double from, uint32 decimals, String *buffer)
 
919
{
 
920
#ifndef DBUG_OFF
 
921
  DBUG_ASSERT(field_types == 0 ||
 
922
              field_types[field_pos] == MYSQL_TYPE_DOUBLE);
 
923
  field_pos++;
 
924
#endif
 
925
  buffer->set_real(from, decimals, thd->charset());
 
926
  return net_store_data((uchar*) buffer->ptr(), buffer->length());
 
927
}
 
928
 
 
929
 
 
930
bool Protocol_text::store(Field *field)
 
931
{
 
932
  if (field->is_null())
 
933
    return store_null();
 
934
#ifndef DBUG_OFF
 
935
  field_pos++;
 
936
#endif
 
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;
 
940
#ifndef DBUG_OFF
 
941
  TABLE *table= field->table;
 
942
  my_bitmap_map *old_map= 0;
 
943
  if (table->file)
 
944
    old_map= dbug_tmp_use_all_columns(table, table->read_set);
 
945
#endif
 
946
 
 
947
  field->val_str(&str);
 
948
#ifndef DBUG_OFF
 
949
  if (old_map)
 
950
    dbug_tmp_restore_column_map(table->read_set, old_map);
 
951
#endif
 
952
 
 
953
  return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
 
954
}
 
955
 
 
956
 
 
957
/**
 
958
  @todo
 
959
    Second_part format ("%06") needs to change when 
 
960
    we support 0-6 decimals for time.
 
961
*/
 
962
 
 
963
bool Protocol_text::store(MYSQL_TIME *tm)
 
964
{
 
965
#ifndef DBUG_OFF
 
966
  DBUG_ASSERT(field_types == 0 ||
 
967
              field_types[field_pos] == MYSQL_TYPE_DATETIME ||
 
968
              field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
 
969
  field_pos++;
 
970
#endif
 
971
  char buff[40];
 
972
  uint length;
 
973
  length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
 
974
                           (int) tm->year,
 
975
                           (int) tm->month,
 
976
                           (int) tm->day,
 
977
                           (int) tm->hour,
 
978
                           (int) tm->minute,
 
979
                           (int) tm->second));
 
980
  if (tm->second_part)
 
981
    length+= my_sprintf(buff+length,(buff+length, ".%06d",
 
982
                                     (int)tm->second_part));
 
983
  return net_store_data((uchar*) buff, length);
 
984
}
 
985
 
 
986
 
 
987
bool Protocol_text::store_date(MYSQL_TIME *tm)
 
988
{
 
989
#ifndef DBUG_OFF
 
990
  DBUG_ASSERT(field_types == 0 ||
 
991
              field_types[field_pos] == MYSQL_TYPE_DATE);
 
992
  field_pos++;
 
993
#endif
 
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);
 
997
}
 
998
 
 
999
 
 
1000
/**
 
1001
  @todo 
 
1002
    Second_part format ("%06") needs to change when 
 
1003
    we support 0-6 decimals for time.
 
1004
*/
 
1005
 
 
1006
bool Protocol_text::store_time(MYSQL_TIME *tm)
 
1007
{
 
1008
#ifndef DBUG_OFF
 
1009
  DBUG_ASSERT(field_types == 0 ||
 
1010
              field_types[field_pos] == MYSQL_TYPE_TIME);
 
1011
  field_pos++;
 
1012
#endif
 
1013
  char buff[40];
 
1014
  uint length;
 
1015
  uint day= (tm->year || tm->month) ? 0 : tm->day;
 
1016
  length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
 
1017
                           tm->neg ? "-" : "",
 
1018
                           (long) day*24L+(long) tm->hour,
 
1019
                           (int) tm->minute,
 
1020
                           (int) tm->second));
 
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);
 
1024
}
 
1025