~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/protocol.cc

  • Committer: Monty
  • Date: 2008-10-02 05:41:33 UTC
  • mfrom: (398.1.10 codestyle)
  • Revision ID: mordred@scylla.inaugust.com-20081002054133-tyxv5bmqpazfaqqi
Merged up to 408 of stdint-includes-fix.

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