~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/protocol.cc

  • Committer: Monty Taylor
  • Date: 2008-08-01 22:33:44 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080801223344-vzhlflfmtijp1imv
First pass at gettexizing the error messages.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2010 Brian Aker
5
 
 *
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.
10
 
 *
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.
15
 
 *
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
19
 
 */
20
 
 
21
 
 
22
 
#include <config.h>
23
 
#include <drizzled/gettext.h>
24
 
#include <drizzled/error.h>
25
 
#include <drizzled/query_id.h>
26
 
#include <drizzled/session.h>
27
 
#include <drizzled/internal/my_sys.h>
28
 
#include <drizzled/internal/m_string.h>
29
 
#include <algorithm>
30
 
#include <iostream>
31
 
#include <boost/program_options.hpp>
32
 
#include <drizzled/module/option_map.h>
33
 
#include <drizzled/util/tokenize.h>
34
 
#include "drizzle_protocol.h"
35
 
 
36
 
namespace po= boost::program_options;
37
 
using namespace drizzled;
38
 
using namespace std;
39
 
 
40
 
namespace drizzle_plugin
41
 
{
42
 
namespace drizzle_protocol
43
 
{
44
 
 
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;
52
 
 
53
 
static const uint32_t DRIZZLE_TCP_PORT= 4427;
54
 
 
55
 
ProtocolCounters *ListenDrizzleProtocol::drizzle_counters= new ProtocolCounters();
56
 
 
57
 
ListenDrizzleProtocol::~ListenDrizzleProtocol()
58
 
{
59
 
}
60
 
 
61
 
in_port_t ListenDrizzleProtocol::getPort(void) const
62
 
{
63
 
  return port;
64
 
}
65
 
 
66
 
void ClientDrizzleProtocol::drizzle_compose_ip_addresses(vector<string> options)
67
 
{
68
 
  for (vector<string>::iterator it= options.begin();
69
 
       it != options.end();
70
 
       ++it)
71
 
  {
72
 
    tokenize(*it, drizzle_admin_ip_addresses, ",", true);
73
 
  }
74
 
}
75
 
 
76
 
bool ClientDrizzleProtocol::isAdminAllowed(void)
77
 
{
78
 
  if (std::find(drizzle_admin_ip_addresses.begin(), drizzle_admin_ip_addresses.end(), session->user()->address()) != drizzle_admin_ip_addresses.end())
79
 
    return true;
80
 
 
81
 
  return false;
82
 
}
83
 
 
84
 
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
85
 
{
86
 
  int new_fd;
87
 
  new_fd= acceptTcp(fd);
88
 
  if (new_fd == -1)
89
 
    return NULL;
90
 
 
91
 
  return new ClientDrizzleProtocol(new_fd, getCounters());
92
 
}
93
 
 
94
 
static int init(drizzled::module::Context &context)
95
 
{  
96
 
  const module::option_map &vm= context.getOptions();
97
 
 
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>()));
109
 
 
110
 
  context.registerVariable(new sys_var_uint32_t_ptr("max-connections", &ListenDrizzleProtocol::drizzle_counters->max_connections));
111
 
 
112
 
  return 0;
113
 
}
114
 
 
115
 
 
116
 
static void init_options(drizzled::module::option_context &context)
117
 
{
118
 
  context("port",
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),
132
 
          N_("Retry Count."));
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."));
145
 
}
146
 
 
147
 
} /* namespace drizzle_protocol */
148
 
} /* namespace drizzle_plugin */
149
 
 
150
 
DRIZZLE_PLUGIN(drizzle_plugin::drizzle_protocol::init, NULL, drizzle_plugin::drizzle_protocol::init_options);
 
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
#include <drizzled/drizzled_error_messages.h>
 
30
 
 
31
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
 
32
/* Declared non-static only because of the embedded library. */
 
33
static void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
 
34
static void write_eof_packet(THD *thd, NET *net,
 
35
                             uint server_status, uint total_warn_count);
 
36
 
 
37
bool Protocol::net_store_data(const uchar *from, size_t length)
 
38
{
 
39
  ulong packet_length=packet->length();
 
40
  /* 
 
41
     The +9 comes from that strings of length longer than 16M require
 
42
     9 bytes to be stored (see net_store_length).
 
43
  */
 
44
  if (packet_length+9+length > packet->alloced_length() &&
 
45
      packet->realloc(packet_length+9+length))
 
46
    return 1;
 
47
  uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length);
 
48
  memcpy(to,from,length);
 
49
  packet->length((uint) (to+length-(uchar*) packet->ptr()));
 
50
  return 0;
 
51
}
 
52
 
 
53
 
 
54
 
 
55
 
 
56
/*
 
57
  net_store_data() - extended version with character set conversion.
 
58
  
 
59
  It is optimized for short strings whose length after
 
60
  conversion is garanteed to be less than 251, which accupies
 
61
  exactly one byte to store length. It allows not to use
 
62
  the "convert" member as a temporary buffer, conversion
 
63
  is done directly to the "packet" member.
 
64
  The limit 251 is good enough to optimize send_fields()
 
65
  because column, table, database names fit into this limit.
 
66
*/
 
67
 
 
68
bool Protocol::net_store_data(const uchar *from, size_t length,
 
69
                              CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
 
70
{
 
71
  uint dummy_errors;
 
72
  /* Calculate maxumum possible result length */
 
73
  uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
 
74
  if (conv_length > 250)
 
75
  {
 
76
    /*
 
77
      For strings with conv_length greater than 250 bytes
 
78
      we don't know how many bytes we will need to store length: one or two,
 
79
      because we don't know result length until conversion is done.
 
80
      For example, when converting from utf8 (mbmaxlen=3) to latin1,
 
81
      conv_length=300 means that the result length can vary between 100 to 300.
 
82
      length=100 needs one byte, length=300 needs to bytes.
 
83
      
 
84
      Thus conversion directly to "packet" is not worthy.
 
85
      Let's use "convert" as a temporary buffer.
 
86
    */
 
87
    return (convert->copy((const char*) from, length, from_cs,
 
88
                          to_cs, &dummy_errors) ||
 
89
            net_store_data((const uchar*) convert->ptr(), convert->length()));
 
90
  }
 
91
 
 
92
  ulong packet_length= packet->length();
 
93
  ulong new_length= packet_length + conv_length + 1;
 
94
 
 
95
  if (new_length > packet->alloced_length() && packet->realloc(new_length))
 
96
    return 1;
 
97
 
 
98
  char *length_pos= (char*) packet->ptr() + packet_length;
 
99
  char *to= length_pos + 1;
 
100
 
 
101
  to+= copy_and_convert(to, conv_length, to_cs,
 
102
                        (const char*) from, length, from_cs, &dummy_errors);
 
103
 
 
104
  net_store_length((uchar*) length_pos, to - length_pos - 1);
 
105
  packet->length((uint) (to - packet->ptr()));
 
106
  return 0;
 
107
}
 
108
 
 
109
 
 
110
/**
 
111
  Send a error string to client.
 
112
 
 
113
  Design note:
 
114
  net_printf_error and net_send_error are low-level functions
 
115
  that shall be used only when a new connection is being
 
116
  established or at server startup.
 
117
 
 
118
  For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
 
119
  critical that every error that can be intercepted is issued in one
 
120
  place only, my_message_sql.
 
121
*/
 
122
void net_send_error(THD *thd, uint sql_errno, const char *err)
 
123
{
 
124
  assert(sql_errno);
 
125
  assert(err && err[0]);
 
126
 
 
127
  /*
 
128
    It's one case when we can push an error even though there
 
129
    is an OK or EOF already.
 
130
  */
 
131
  thd->main_da.can_overwrite_status= true;
 
132
 
 
133
  /* Abort multi-result sets */
 
134
  thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
135
 
 
136
  net_send_error_packet(thd, sql_errno, err);
 
137
 
 
138
  thd->main_da.can_overwrite_status= false;
 
139
 
 
140
  return;
 
141
}
 
142
 
 
143
/**
 
144
  Return ok to the client.
 
145
 
 
146
  The ok packet has the following structure:
 
147
 
 
148
  - 0               : Marker (1 byte)
 
149
  - affected_rows       : Stored in 1-9 bytes
 
150
  - id          : Stored in 1-9 bytes
 
151
  - server_status       : Copy of thd->server_status;  Can be used by client
 
152
  to check if we are inside an transaction.
 
153
  New in 4.0 protocol
 
154
  - warning_count       : Stored in 2 bytes; New in 4.1 protocol
 
155
  - message             : Stored as packed length (1-9 bytes) + message.
 
156
  Is not stored if no message.
 
157
 
 
158
  @param thd               Thread handler
 
159
  @param affected_rows     Number of rows changed by statement
 
160
  @param id                Auto_increment id for first row (if used)
 
161
  @param message           Message to send to the client (Used by mysql_status)
 
162
*/
 
163
 
 
164
static void
 
165
net_send_ok(THD *thd,
 
166
            uint server_status, uint total_warn_count,
 
167
            ha_rows affected_rows, uint64_t id, const char *message)
 
168
{
 
169
  NET *net= &thd->net;
 
170
  uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
 
171
 
 
172
  if (! net->vio)       // hack for re-parsing queries
 
173
  {
 
174
    return;
 
175
  }
 
176
 
 
177
  buff[0]=0;                                    // No fields
 
178
  pos=net_store_length(buff+1,affected_rows);
 
179
  pos=net_store_length(pos, id);
 
180
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
181
  {
 
182
    int2store(pos, server_status);
 
183
    pos+=2;
 
184
 
 
185
    /* We can only return up to 65535 warnings in two bytes */
 
186
    uint tmp= min(total_warn_count, 65535);
 
187
    int2store(pos, tmp);
 
188
    pos+= 2;
 
189
  }
 
190
  else if (net->return_status)                  // For 4.0 protocol
 
191
  {
 
192
    int2store(pos, server_status);
 
193
    pos+=2;
 
194
  }
 
195
  thd->main_da.can_overwrite_status= true;
 
196
 
 
197
  if (message && message[0])
 
198
    pos= net_store_data(pos, (uchar*) message, strlen(message));
 
199
  VOID(my_net_write(net, buff, (size_t) (pos-buff)));
 
200
  VOID(net_flush(net));
 
201
 
 
202
  thd->main_da.can_overwrite_status= false;
 
203
 
 
204
  return;
 
205
}
 
206
 
 
207
static uchar eof_buff[1]= { (uchar) 254 };      /* Marker for end of fields */
 
208
 
 
209
/**
 
210
  Send eof (= end of result set) to the client.
 
211
 
 
212
  The eof packet has the following structure:
 
213
 
 
214
  - 254         : Marker (1 byte)
 
215
  - warning_count       : Stored in 2 bytes; New in 4.1 protocol
 
216
  - status_flag : Stored in 2 bytes;
 
217
  For flags like SERVER_MORE_RESULTS_EXISTS.
 
218
 
 
219
  Note that the warning count will not be sent if 'no_flush' is set as
 
220
  we don't want to report the warning count until all data is sent to the
 
221
  client.
 
222
 
 
223
  @param thd            Thread handler
 
224
  @param no_flush       Set to 1 if there will be more data to the client,
 
225
                    like in send_fields().
 
226
*/    
 
227
 
 
228
static void
 
229
net_send_eof(THD *thd, uint server_status, uint total_warn_count)
 
230
{
 
231
  NET *net= &thd->net;
 
232
  /* Set to true if no active vio, to work well in case of --init-file */
 
233
  if (net->vio != 0)
 
234
  {
 
235
    thd->main_da.can_overwrite_status= true;
 
236
    write_eof_packet(thd, net, server_status, total_warn_count);
 
237
    VOID(net_flush(net));
 
238
    thd->main_da.can_overwrite_status= false;
 
239
  }
 
240
  return;
 
241
}
 
242
 
 
243
 
 
244
/**
 
245
  Format EOF packet according to the current protocol and
 
246
  write it to the network output buffer.
 
247
*/
 
248
 
 
249
static void write_eof_packet(THD *thd, NET *net,
 
250
                             uint server_status,
 
251
                             uint total_warn_count)
 
252
{
 
253
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
254
  {
 
255
    uchar buff[5];
 
256
    /*
 
257
      Don't send warn count during SP execution, as the warn_list
 
258
      is cleared between substatements, and mysqltest gets confused
 
259
    */
 
260
    uint tmp= min(total_warn_count, 65535);
 
261
    buff[0]= 254;
 
262
    int2store(buff+1, tmp);
 
263
    /*
 
264
      The following test should never be true, but it's better to do it
 
265
      because if 'is_fatal_error' is set the server is not going to execute
 
266
      other queries (see the if test in dispatch_command / COM_QUERY)
 
267
    */
 
268
    if (thd->is_fatal_error)
 
269
      server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
270
    int2store(buff + 3, server_status);
 
271
    VOID(my_net_write(net, buff, 5));
 
272
  }
 
273
  else
 
274
    VOID(my_net_write(net, eof_buff, 1));
 
275
}
 
276
 
 
277
void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
 
278
{
 
279
  NET *net= &thd->net;
 
280
  uint length;
 
281
  /*
 
282
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512
 
283
  */
 
284
  uchar buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos;
 
285
 
 
286
  if (net->vio == 0)
 
287
  {
 
288
    return;
 
289
  }
 
290
 
 
291
  int2store(buff,sql_errno);
 
292
  pos= buff+2;
 
293
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
294
  {
 
295
    /* The first # is to make the protocol backward compatible */
 
296
    buff[2]= '#';
 
297
    pos= (uchar*) strmov((char*) buff+3, mysql_errno_to_sqlstate(sql_errno));
 
298
  }
 
299
  length= (uint) (strmake((char*) pos, err, MYSQL_ERRMSG_SIZE-1) -
 
300
                  (char*) buff);
 
301
  err= (char*) buff;
 
302
 
 
303
  VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
 
304
                         length));
 
305
  return;
 
306
}
 
307
 
 
308
 
 
309
/**
 
310
  Faster net_store_length when we know that length is less than 65536.
 
311
  We keep a separate version for that range because it's widely used in
 
312
  libmysql.
 
313
 
 
314
  uint is used as agrument type because of MySQL type conventions:
 
315
  - uint for 0..65536
 
316
  - ulong for 0..4294967296
 
317
  - uint64_t for bigger numbers.
 
318
*/
 
319
 
 
320
static uchar *net_store_length_fast(uchar *packet, uint length)
 
321
{
 
322
  if (length < 251)
 
323
  {
 
324
    *packet=(uchar) length;
 
325
    return packet+1;
 
326
  }
 
327
  *packet++=252;
 
328
  int2store(packet,(uint) length);
 
329
  return packet+2;
 
330
}
 
331
 
 
332
/**
 
333
  Send the status of the current statement execution over network.
 
334
 
 
335
  @param  thd   in fact, carries two parameters, NET for the transport and
 
336
                Diagnostics_area as the source of status information.
 
337
 
 
338
  In MySQL, there are two types of SQL statements: those that return
 
339
  a result set and those that return status information only.
 
340
 
 
341
  If a statement returns a result set, it consists of 3 parts:
 
342
  - result set meta-data
 
343
  - variable number of result set rows (can be 0)
 
344
  - followed and terminated by EOF or ERROR packet
 
345
 
 
346
  Once the  client has seen the meta-data information, it always
 
347
  expects an EOF or ERROR to terminate the result set. If ERROR is
 
348
  received, the result set rows are normally discarded (this is up
 
349
  to the client implementation, libmysql at least does discard them).
 
350
  EOF, on the contrary, means "successfully evaluated the entire
 
351
  result set". Since we don't know how many rows belong to a result
 
352
  set until it's evaluated, EOF/ERROR is the indicator of the end
 
353
  of the row stream. Note, that we can not buffer result set rows
 
354
  on the server -- there may be an arbitrary number of rows. But
 
355
  we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
 
356
  delay sending it till the very end of execution (here), to be able to
 
357
  change EOF to an ERROR if commit failed or some other error occurred
 
358
  during the last cleanup steps taken after execution.
 
359
 
 
360
  A statement that does not return a result set doesn't send result
 
361
  set meta-data either. Instead it returns one of:
 
362
  - OK packet
 
363
  - ERROR packet.
 
364
  Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
 
365
  packet is "buffered" in the diagnostics area and sent to the client
 
366
  in the end of statement.
 
367
 
 
368
  @pre  The diagnostics area is assigned or disabled. It can not be empty
 
369
        -- we assume that every SQL statement or COM_* command
 
370
        generates OK, ERROR, or EOF status.
 
371
 
 
372
  @post The status information is encoded to protocol format and sent to the
 
373
        client.
 
374
 
 
375
  @return We conventionally return void, since the only type of error
 
376
          that can happen here is a NET (transport) error, and that one
 
377
          will become visible when we attempt to read from the NET the
 
378
          next command.
 
379
          Diagnostics_area::is_sent is set for debugging purposes only.
 
380
*/
 
381
 
 
382
void net_end_statement(THD *thd)
 
383
{
 
384
  assert(! thd->main_da.is_sent);
 
385
 
 
386
  /* Can not be true, but do not take chances in production. */
 
387
  if (thd->main_da.is_sent)
 
388
    return;
 
389
 
 
390
  switch (thd->main_da.status()) {
 
391
  case Diagnostics_area::DA_ERROR:
 
392
    /* The query failed, send error to log and abort bootstrap. */
 
393
    net_send_error(thd,
 
394
                   thd->main_da.sql_errno(),
 
395
                   thd->main_da.message());
 
396
    break;
 
397
  case Diagnostics_area::DA_EOF:
 
398
    net_send_eof(thd,
 
399
                 thd->main_da.server_status(),
 
400
                 thd->main_da.total_warn_count());
 
401
    break;
 
402
  case Diagnostics_area::DA_OK:
 
403
    net_send_ok(thd,
 
404
                thd->main_da.server_status(),
 
405
                thd->main_da.total_warn_count(),
 
406
                thd->main_da.affected_rows(),
 
407
                thd->main_da.last_insert_id(),
 
408
                thd->main_da.message());
 
409
    break;
 
410
  case Diagnostics_area::DA_DISABLED:
 
411
    break;
 
412
  case Diagnostics_area::DA_EMPTY:
 
413
  default:
 
414
    assert(0);
 
415
    net_send_ok(thd, thd->server_status, thd->total_warn_count,
 
416
                0, 0, NULL);
 
417
    break;
 
418
  }
 
419
  thd->main_da.is_sent= true;
 
420
}
 
421
 
 
422
 
 
423
/****************************************************************************
 
424
  Functions used by the protocol functions (like net_send_ok) to store
 
425
  strings and numbers in the header result packet.
 
426
****************************************************************************/
 
427
 
 
428
/* The following will only be used for short strings < 65K */
 
429
 
 
430
uchar *net_store_data(uchar *to, const uchar *from, size_t length)
 
431
{
 
432
  to=net_store_length_fast(to,length);
 
433
  memcpy(to,from,length);
 
434
  return to+length;
 
435
}
 
436
 
 
437
uchar *net_store_data(uchar *to,int32_t from)
 
438
{
 
439
  char buff[20];
 
440
  uint length=(uint) (int10_to_str(from,buff,10)-buff);
 
441
  to=net_store_length_fast(to,length);
 
442
  memcpy(to,buff,length);
 
443
  return to+length;
 
444
}
 
445
 
 
446
uchar *net_store_data(uchar *to,int64_t from)
 
447
{
 
448
  char buff[22];
 
449
  uint length=(uint) (int64_t10_to_str(from,buff,10)-buff);
 
450
  to=net_store_length_fast(to,length);
 
451
  memcpy(to,buff,length);
 
452
  return to+length;
 
453
}
 
454
 
 
455
 
 
456
/*****************************************************************************
 
457
  Default Protocol functions
 
458
*****************************************************************************/
 
459
 
 
460
void Protocol::init(THD *thd_arg)
 
461
{
 
462
  thd=thd_arg;
 
463
  packet= &thd->packet;
 
464
  convert= &thd->convert_buffer;
 
465
}
 
466
 
 
467
/**
 
468
  Finish the result set with EOF packet, as is expected by the client,
 
469
  if there is an error evaluating the next row and a continue handler
 
470
  for the error.
 
471
*/
 
472
 
 
473
void Protocol::end_partial_result_set(THD *thd)
 
474
{
 
475
  net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
 
476
}
 
477
 
 
478
 
 
479
bool Protocol::flush()
 
480
{
 
481
  return net_flush(&thd->net);
 
482
}
 
483
 
 
484
 
 
485
/**
 
486
  Send name and type of result to client.
 
487
 
 
488
  Sum fields has table name empty and field_name.
 
489
 
 
490
  @param THD            Thread data object
 
491
  @param list           List of items to send to client
 
492
  @param flag           Bit mask with the following functions:
 
493
                        - 1 send number of rows
 
494
                        - 2 send default values
 
495
                        - 4 don't write eof packet
 
496
 
 
497
  @retval
 
498
    0   ok
 
499
  @retval
 
500
    1   Error  (Note that in this case the error is not sent to the
 
501
    client)
 
502
*/
 
503
bool Protocol::send_fields(List<Item> *list, uint flags)
 
504
{
 
505
  List_iterator_fast<Item> it(*list);
 
506
  Item *item;
 
507
  uchar buff[80];
 
508
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
 
509
  Protocol_text prot(thd);
 
510
  String *local_packet= prot.storage_packet();
 
511
  CHARSET_INFO *thd_charset= thd->variables.character_set_results;
 
512
 
 
513
  if (flags & SEND_NUM_ROWS)
 
514
  {                             // Packet with number of elements
 
515
    uchar *pos= net_store_length(buff, list->elements);
 
516
    (void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
 
517
  }
 
518
 
 
519
  while ((item=it++))
 
520
  {
 
521
    char *pos;
 
522
    CHARSET_INFO *cs= system_charset_info;
 
523
    Send_field field;
 
524
    item->make_field(&field);
 
525
 
 
526
    prot.prepare_for_resend();
 
527
 
 
528
    if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
529
    {
 
530
      if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
 
531
          prot.store(field.db_name, (uint) strlen(field.db_name),
 
532
                     cs, thd_charset) ||
 
533
          prot.store(field.table_name, (uint) strlen(field.table_name),
 
534
                     cs, thd_charset) ||
 
535
          prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
 
536
                     cs, thd_charset) ||
 
537
          prot.store(field.col_name, (uint) strlen(field.col_name),
 
538
                     cs, thd_charset) ||
 
539
          prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
 
540
                     cs, thd_charset) ||
 
541
          local_packet->realloc(local_packet->length()+12))
 
542
        goto err;
 
543
      /* Store fixed length fields */
 
544
      pos= (char*) local_packet->ptr()+local_packet->length();
 
545
      *pos++= 12;                               // Length of packed fields
 
546
      if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
 
547
      {
 
548
        /* No conversion */
 
549
        int2store(pos, field.charsetnr);
 
550
        int4store(pos+2, field.length);
 
551
      }
 
552
      else
 
553
      {
 
554
        /* With conversion */
 
555
        uint max_char_len;
 
556
        int2store(pos, thd_charset->number);
 
557
        /*
 
558
          For TEXT/BLOB columns, field_length describes the maximum data
 
559
          length in bytes. There is no limit to the number of characters
 
560
          that a TEXT column can store, as long as the data fits into
 
561
          the designated space.
 
562
          For the rest of textual columns, field_length is evaluated as
 
563
          char_count * mbmaxlen, where character count is taken from the
 
564
          definition of the column. In other words, the maximum number
 
565
          of characters here is limited by the column definition.
 
566
        */
 
567
        max_char_len= field.length / item->collation.collation->mbmaxlen;
 
568
        int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
 
569
      }
 
570
      pos[6]= field.type;
 
571
      int2store(pos+7,field.flags);
 
572
      pos[9]= (char) field.decimals;
 
573
      pos[10]= 0;                               // For the future
 
574
      pos[11]= 0;                               // For the future
 
575
      pos+= 12;
 
576
    }
 
577
    else
 
578
    {
 
579
      if (prot.store(field.table_name, (uint) strlen(field.table_name),
 
580
                     cs, thd_charset) ||
 
581
          prot.store(field.col_name, (uint) strlen(field.col_name),
 
582
                     cs, thd_charset) ||
 
583
          local_packet->realloc(local_packet->length()+10))
 
584
        goto err;
 
585
      pos= (char*) local_packet->ptr()+local_packet->length();
 
586
 
 
587
        pos[0]=3;
 
588
        int3store(pos+1,field.length);
 
589
        pos[4]=1;
 
590
        pos[5]=field.type;
 
591
        pos[6]=3;
 
592
        int2store(pos+7,field.flags);
 
593
        pos[9]= (char) field.decimals;
 
594
        pos+= 10;
 
595
    }
 
596
    local_packet->length((uint) (pos - local_packet->ptr()));
 
597
    if (flags & SEND_DEFAULTS)
 
598
      item->send(&prot, &tmp);                  // Send default value
 
599
    if (prot.write())
 
600
      break;                                    /* purecov: inspected */
 
601
  }
 
602
 
 
603
  if (flags & SEND_EOF)
 
604
  {
 
605
    /*
 
606
      Mark the end of meta-data result set, and store thd->server_status,
 
607
      to show that there is no cursor.
 
608
      Send no warning information, as it will be sent at statement end.
 
609
    */
 
610
    write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
 
611
  }
 
612
  return(prepare_for_send(list));
 
613
 
 
614
err:
 
615
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
 
616
             MYF(0));   /* purecov: inspected */
 
617
  return(1);                            /* purecov: inspected */
 
618
}
 
619
 
 
620
 
 
621
bool Protocol::write()
 
622
{
 
623
  return(my_net_write(&thd->net, (uchar*) packet->ptr(),
 
624
                           packet->length()));
 
625
}
 
626
 
 
627
 
 
628
/**
 
629
  Send \\0 end terminated string.
 
630
 
 
631
  @param from   NullS or \\0 terminated string
 
632
 
 
633
  @note
 
634
    In most cases one should use store(from, length) instead of this function
 
635
 
 
636
  @retval
 
637
    0           ok
 
638
  @retval
 
639
    1           error
 
640
*/
 
641
 
 
642
bool Protocol::store(const char *from, CHARSET_INFO *cs)
 
643
{
 
644
  if (!from)
 
645
    return store_null();
 
646
  uint length= strlen(from);
 
647
  return store(from, length, cs);
 
648
}
 
649
 
 
650
 
 
651
/**
 
652
  Send a set of strings as one long string with ',' in between.
 
653
*/
 
654
 
 
655
bool Protocol::store(I_List<i_string>* str_list)
 
656
{
 
657
  char buf[256];
 
658
  String tmp(buf, sizeof(buf), &my_charset_bin);
 
659
  uint32_t len;
 
660
  I_List_iterator<i_string> it(*str_list);
 
661
  i_string* s;
 
662
 
 
663
  tmp.length(0);
 
664
  while ((s=it++))
 
665
  {
 
666
    tmp.append(s->ptr);
 
667
    tmp.append(',');
 
668
  }
 
669
  if ((len= tmp.length()))
 
670
    len--;                                      // Remove last ','
 
671
  return store((char*) tmp.ptr(), len,  tmp.charset());
 
672
}
 
673
 
 
674
 
 
675
/****************************************************************************
 
676
  Functions to handle the simple (default) protocol where everything is
 
677
  This protocol is the one that is used by default between the MySQL server
 
678
  and client when you are not using prepared statements.
 
679
 
 
680
  All data are sent as 'packed-string-length' followed by 'string-data'
 
681
****************************************************************************/
 
682
 
 
683
void Protocol_text::prepare_for_resend()
 
684
{
 
685
  packet->length(0);
 
686
}
 
687
 
 
688
bool Protocol_text::store_null()
 
689
{
 
690
  char buff[1];
 
691
  buff[0]= (char)251;
 
692
  return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
 
693
}
 
694
 
 
695
 
 
696
/**
 
697
  Auxilary function to convert string to the given character set
 
698
  and store in network buffer.
 
699
*/
 
700
 
 
701
bool Protocol::store_string_aux(const char *from, size_t length,
 
702
                                CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
 
703
{
 
704
  /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
 
705
  if (tocs && !my_charset_same(fromcs, tocs) &&
 
706
      fromcs != &my_charset_bin &&
 
707
      tocs != &my_charset_bin)
 
708
  {
 
709
    /* Store with conversion */
 
710
    return net_store_data((uchar*) from, length, fromcs, tocs);
 
711
  }
 
712
  /* Store without conversion */
 
713
  return net_store_data((uchar*) from, length);
 
714
}
 
715
 
 
716
 
 
717
bool Protocol_text::store(const char *from, size_t length,
 
718
                          CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
 
719
{
 
720
  return store_string_aux(from, length, fromcs, tocs);
 
721
}
 
722
 
 
723
 
 
724
bool Protocol_text::store(const char *from, size_t length,
 
725
                          CHARSET_INFO *fromcs)
 
726
{
 
727
  CHARSET_INFO *tocs= this->thd->variables.character_set_results;
 
728
  return store_string_aux(from, length, fromcs, tocs);
 
729
}
 
730
 
 
731
 
 
732
bool Protocol_text::store_tiny(int64_t from)
 
733
{
 
734
  char buff[20];
 
735
  return net_store_data((uchar*) buff,
 
736
                        (size_t) (int10_to_str((int) from, buff, -10) - buff));
 
737
}
 
738
 
 
739
 
 
740
bool Protocol_text::store_short(int64_t from)
 
741
{
 
742
  char buff[20];
 
743
  return net_store_data((uchar*) buff,
 
744
                        (size_t) (int10_to_str((int) from, buff, -10) -
 
745
                                  buff));
 
746
}
 
747
 
 
748
 
 
749
bool Protocol_text::store_long(int64_t from)
 
750
{
 
751
  char buff[20];
 
752
  return net_store_data((uchar*) buff,
 
753
                        (size_t) (int10_to_str((long int)from, buff,
 
754
                                               (from <0)?-10:10)-buff));
 
755
}
 
756
 
 
757
 
 
758
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
 
759
{
 
760
  char buff[22];
 
761
  return net_store_data((uchar*) buff,
 
762
                        (size_t) (int64_t10_to_str(from,buff,
 
763
                                                    unsigned_flag ? 10 : -10)-
 
764
                                  buff));
 
765
}
 
766
 
 
767
 
 
768
bool Protocol_text::store_decimal(const my_decimal *d)
 
769
{
 
770
  char buff[DECIMAL_MAX_STR_LENGTH];
 
771
  String str(buff, sizeof(buff), &my_charset_bin);
 
772
  (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
 
773
  return net_store_data((uchar*) str.ptr(), str.length());
 
774
}
 
775
 
 
776
 
 
777
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
 
778
{
 
779
  buffer->set_real((double) from, decimals, thd->charset());
 
780
  return net_store_data((uchar*) buffer->ptr(), buffer->length());
 
781
}
 
782
 
 
783
 
 
784
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
 
785
{
 
786
  buffer->set_real(from, decimals, thd->charset());
 
787
  return net_store_data((uchar*) buffer->ptr(), buffer->length());
 
788
}
 
789
 
 
790
 
 
791
bool Protocol_text::store(Field *field)
 
792
{
 
793
  if (field->is_null())
 
794
    return store_null();
 
795
  char buff[MAX_FIELD_WIDTH];
 
796
  String str(buff,sizeof(buff), &my_charset_bin);
 
797
  CHARSET_INFO *tocs= this->thd->variables.character_set_results;
 
798
 
 
799
  field->val_str(&str);
 
800
 
 
801
  return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
 
802
}
 
803
 
 
804
 
 
805
/**
 
806
  @todo
 
807
    Second_part format ("%06") needs to change when 
 
808
    we support 0-6 decimals for time.
 
809
*/
 
810
 
 
811
bool Protocol_text::store(DRIZZLE_TIME *tm)
 
812
{
 
813
  char buff[40];
 
814
  uint length;
 
815
  length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
 
816
                           (int) tm->year,
 
817
                           (int) tm->month,
 
818
                           (int) tm->day,
 
819
                           (int) tm->hour,
 
820
                           (int) tm->minute,
 
821
                           (int) tm->second);
 
822
  if (tm->second_part)
 
823
    length+= sprintf(buff+length, ".%06d",
 
824
                                     (int)tm->second_part);
 
825
  return net_store_data((uchar*) buff, length);
 
826
}
 
827
 
 
828
 
 
829
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
 
830
{
 
831
  char buff[MAX_DATE_STRING_REP_LENGTH];
 
832
  size_t length= my_date_to_str(tm, buff);
 
833
  return net_store_data((uchar*) buff, length);
 
834
}
 
835
 
 
836
 
 
837
/**
 
838
  @todo 
 
839
    Second_part format ("%06") needs to change when 
 
840
    we support 0-6 decimals for time.
 
841
*/
 
842
 
 
843
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
 
844
{
 
845
  char buff[40];
 
846
  uint length;
 
847
  uint day= (tm->year || tm->month) ? 0 : tm->day;
 
848
  length= sprintf(buff, "%s%02ld:%02d:%02d",
 
849
                           tm->neg ? "-" : "",
 
850
                           (long) day*24L+(long) tm->hour,
 
851
                           (int) tm->minute,
 
852
                           (int) tm->second);
 
853
  if (tm->second_part)
 
854
    length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
 
855
  return net_store_data((uchar*) buff, length);
 
856
}
 
857