~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/protocol.cc

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

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/sql_state.h>
27
 
#include <drizzled/session.h>
28
 
#include "drizzled/internal/my_sys.h"
29
 
#include "drizzled/internal/m_string.h"
30
 
#include <algorithm>
31
 
#include <iostream>
32
 
#include <boost/program_options.hpp>
33
 
#include <drizzled/module/option_map.h>
34
 
#include "drizzled/util/tokenize.h"
35
 
#include "drizzle_protocol.h"
36
 
#include "plugin/drizzle_protocol/status_table.h"
37
 
 
38
 
namespace po= boost::program_options;
39
 
using namespace drizzled;
40
 
using namespace std;
41
 
 
42
 
namespace drizzle_plugin
43
 
{
44
 
namespace drizzle_protocol
45
 
{
46
 
 
47
 
std::vector<std::string> ClientDrizzleProtocol::drizzle_admin_ip_addresses;
48
 
static port_constraint port;
49
 
static timeout_constraint connect_timeout;
50
 
static timeout_constraint read_timeout;
51
 
static timeout_constraint write_timeout;
52
 
static retry_constraint retry_count;
53
 
static buffer_constraint buffer_length;
54
 
 
55
 
static const uint32_t DRIZZLE_TCP_PORT= 4427;
56
 
 
57
 
ProtocolCounters *ListenDrizzleProtocol::drizzle_counters= new ProtocolCounters();
58
 
 
59
 
ListenDrizzleProtocol::~ListenDrizzleProtocol()
60
 
{
61
 
}
62
 
 
63
 
in_port_t ListenDrizzleProtocol::getPort(void) const
64
 
{
65
 
  return port;
66
 
}
67
 
 
68
 
void ClientDrizzleProtocol::drizzle_compose_ip_addresses(vector<string> options)
69
 
{
70
 
  for (vector<string>::iterator it= options.begin();
71
 
       it != options.end();
72
 
       ++it)
73
 
  {
74
 
    tokenize(*it, drizzle_admin_ip_addresses, ",", true);
75
 
  }
76
 
}
77
 
 
78
 
bool ClientDrizzleProtocol::isAdminAllowed(void)
79
 
{
80
 
  if (std::find(drizzle_admin_ip_addresses.begin(), drizzle_admin_ip_addresses.end(), session->getSecurityContext().getIp()) != drizzle_admin_ip_addresses.end())
81
 
    return true;
82
 
  else
83
 
    return false;
84
 
}
85
 
 
86
 
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
87
 
{
88
 
  int new_fd;
89
 
  new_fd= acceptTcp(fd);
90
 
  if (new_fd == -1)
91
 
    return NULL;
92
 
 
93
 
  return new ClientDrizzleProtocol(new_fd, getCounters());
94
 
}
95
 
 
96
 
static int init(drizzled::module::Context &context)
97
 
{  
98
 
  const module::option_map &vm= context.getOptions();
99
 
 
100
 
  context.add(new StatusTable);
101
 
  context.add(new ListenDrizzleProtocol("drizzle_protocol", vm["bind-address"].as<std::string>(), true));
102
 
  context.registerVariable(new sys_var_constrained_value_readonly<in_port_t>("port", port));
103
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("connect_timeout", connect_timeout));
104
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("read_timeout", read_timeout));
105
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("write_timeout", write_timeout));
106
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("retry_count", retry_count));
107
 
  context.registerVariable(new sys_var_constrained_value_readonly<uint32_t>("buffer_length", buffer_length));
108
 
  context.registerVariable(new sys_var_const_string_val("bind_address",
109
 
                                                        vm["bind-address"].as<std::string>()));
110
 
 
111
 
  context.registerVariable(new sys_var_uint32_t_ptr("max-connections", &ListenDrizzleProtocol::drizzle_counters->max_connections));
112
 
 
113
 
  return 0;
114
 
}
115
 
 
116
 
 
117
 
static void init_options(drizzled::module::option_context &context)
118
 
{
119
 
  context("port",
120
 
          po::value<port_constraint>(&port)->default_value(DRIZZLE_TCP_PORT),
121
 
          N_("Port number to use for connection or 0 for default to with Drizzle/MySQL protocol."));
122
 
  context("connect-timeout",
123
 
          po::value<timeout_constraint>(&connect_timeout)->default_value(10),
124
 
          N_("Connect Timeout."));
125
 
  context("read-timeout",
126
 
          po::value<timeout_constraint>(&read_timeout)->default_value(30),
127
 
          N_("Read Timeout."));
128
 
  context("write-timeout",
129
 
          po::value<timeout_constraint>(&write_timeout)->default_value(60),
130
 
          N_("Write Timeout."));
131
 
  context("retry-count",
132
 
          po::value<retry_constraint>(&retry_count)->default_value(10),
133
 
          N_("Retry Count."));
134
 
  context("buffer-length",
135
 
          po::value<buffer_constraint>(&buffer_length)->default_value(16384),
136
 
          N_("Buffer length."));
137
 
  context("bind-address",
138
 
          po::value<std::string>()->default_value(""),
139
 
          N_("Address to bind to."));
140
 
  context("max-connections",
141
 
          po::value<uint32_t>(&ListenDrizzleProtocol::drizzle_counters->max_connections)->default_value(1000),
142
 
          N_("Maximum simultaneous connections."));
143
 
  context("admin-ip-addresses",
144
 
          po::value<vector<string> >()->composing()->notifier(&ClientDrizzleProtocol::drizzle_compose_ip_addresses),
145
 
          N_("A restrictive IP address list for incoming admin connections."));
146
 
}
147
 
 
148
 
} /* namespace drizzle_protocol */
149
 
} /* namespace drizzle_plugin */
150
 
 
151
 
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= min(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
  VOID(my_net_write(net, buff, (size_t) (pos-buff)));
 
187
  VOID(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
    VOID(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= min(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
  VOID(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*) 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
  VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
 
280
                         length));
 
281
  return;
 
282
}
 
283
 
 
284
 
 
285
/**
 
286
  Faster net_store_length when we know that length is less than 65536.
 
287
  We keep a separate version for that range because it's widely used in
 
288
  libmysql.
 
289
 
 
290
  uint is used as agrument type because of MySQL type conventions:
 
291
  - uint for 0..65536
 
292
  - ulong for 0..4294967296
 
293
  - uint64_t for bigger numbers.
 
294
*/
 
295
 
 
296
static uchar *net_store_length_fast(uchar *packet, uint length)
 
297
{
 
298
  if (length < 251)
 
299
  {
 
300
    *packet=(uchar) length;
 
301
    return packet+1;
 
302
  }
 
303
  *packet++=252;
 
304
  int2store(packet,(uint) length);
 
305
  return packet+2;
 
306
}
 
307
 
 
308
/**
 
309
  Send the status of the current statement execution over network.
 
310
 
 
311
  @param  thd   in fact, carries two parameters, NET for the transport and
 
312
                Diagnostics_area as the source of status information.
 
313
 
 
314
  In MySQL, there are two types of SQL statements: those that return
 
315
  a result set and those that return status information only.
 
316
 
 
317
  If a statement returns a result set, it consists of 3 parts:
 
318
  - result set meta-data
 
319
  - variable number of result set rows (can be 0)
 
320
  - followed and terminated by EOF or ERROR packet
 
321
 
 
322
  Once the  client has seen the meta-data information, it always
 
323
  expects an EOF or ERROR to terminate the result set. If ERROR is
 
324
  received, the result set rows are normally discarded (this is up
 
325
  to the client implementation, libmysql at least does discard them).
 
326
  EOF, on the contrary, means "successfully evaluated the entire
 
327
  result set". Since we don't know how many rows belong to a result
 
328
  set until it's evaluated, EOF/ERROR is the indicator of the end
 
329
  of the row stream. Note, that we can not buffer result set rows
 
330
  on the server -- there may be an arbitrary number of rows. But
 
331
  we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
 
332
  delay sending it till the very end of execution (here), to be able to
 
333
  change EOF to an ERROR if commit failed or some other error occurred
 
334
  during the last cleanup steps taken after execution.
 
335
 
 
336
  A statement that does not return a result set doesn't send result
 
337
  set meta-data either. Instead it returns one of:
 
338
  - OK packet
 
339
  - ERROR packet.
 
340
  Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
 
341
  packet is "buffered" in the diagnostics area and sent to the client
 
342
  in the end of statement.
 
343
 
 
344
  @pre  The diagnostics area is assigned or disabled. It can not be empty
 
345
        -- we assume that every SQL statement or COM_* command
 
346
        generates OK, ERROR, or EOF status.
 
347
 
 
348
  @post The status information is encoded to protocol format and sent to the
 
349
        client.
 
350
 
 
351
  @return We conventionally return void, since the only type of error
 
352
          that can happen here is a NET (transport) error, and that one
 
353
          will become visible when we attempt to read from the NET the
 
354
          next command.
 
355
          Diagnostics_area::is_sent is set for debugging purposes only.
 
356
*/
 
357
 
 
358
void net_end_statement(THD *thd)
 
359
{
 
360
  assert(! thd->main_da.is_sent);
 
361
 
 
362
  /* Can not be true, but do not take chances in production. */
 
363
  if (thd->main_da.is_sent)
 
364
    return;
 
365
 
 
366
  switch (thd->main_da.status()) {
 
367
  case Diagnostics_area::DA_ERROR:
 
368
    /* The query failed, send error to log and abort bootstrap. */
 
369
    net_send_error(thd,
 
370
                   thd->main_da.sql_errno(),
 
371
                   thd->main_da.message());
 
372
    break;
 
373
  case Diagnostics_area::DA_EOF:
 
374
    net_send_eof(thd,
 
375
                 thd->main_da.server_status(),
 
376
                 thd->main_da.total_warn_count());
 
377
    break;
 
378
  case Diagnostics_area::DA_OK:
 
379
    net_send_ok(thd,
 
380
                thd->main_da.server_status(),
 
381
                thd->main_da.total_warn_count(),
 
382
                thd->main_da.affected_rows(),
 
383
                thd->main_da.last_insert_id(),
 
384
                thd->main_da.message());
 
385
    break;
 
386
  case Diagnostics_area::DA_DISABLED:
 
387
    break;
 
388
  case Diagnostics_area::DA_EMPTY:
 
389
  default:
 
390
    assert(0);
 
391
    net_send_ok(thd, thd->server_status, thd->total_warn_count,
 
392
                0, 0, NULL);
 
393
    break;
 
394
  }
 
395
  thd->main_da.is_sent= true;
 
396
}
 
397
 
 
398
 
 
399
/****************************************************************************
 
400
  Functions used by the protocol functions (like net_send_ok) to store
 
401
  strings and numbers in the header result packet.
 
402
****************************************************************************/
 
403
 
 
404
/* The following will only be used for short strings < 65K */
 
405
 
 
406
uchar *net_store_data(uchar *to, const uchar *from, size_t length)
 
407
{
 
408
  to=net_store_length_fast(to,length);
 
409
  memcpy(to,from,length);
 
410
  return to+length;
 
411
}
 
412
 
 
413
uchar *net_store_data(uchar *to,int32_t from)
 
414
{
 
415
  char buff[20];
 
416
  uint length=(uint) (int10_to_str(from,buff,10)-buff);
 
417
  to=net_store_length_fast(to,length);
 
418
  memcpy(to,buff,length);
 
419
  return to+length;
 
420
}
 
421
 
 
422
uchar *net_store_data(uchar *to,int64_t from)
 
423
{
 
424
  char buff[22];
 
425
  uint length=(uint) (int64_t10_to_str(from,buff,10)-buff);
 
426
  to=net_store_length_fast(to,length);
 
427
  memcpy(to,buff,length);
 
428
  return to+length;
 
429
}
 
430
 
 
431
 
 
432
/*****************************************************************************
 
433
  Default Protocol functions
 
434
*****************************************************************************/
 
435
 
 
436
void Protocol::init(THD *thd_arg)
 
437
{
 
438
  thd=thd_arg;
 
439
  packet= &thd->packet;
 
440
  convert= &thd->convert_buffer;
 
441
}
 
442
 
 
443
/**
 
444
  Finish the result set with EOF packet, as is expected by the client,
 
445
  if there is an error evaluating the next row and a continue handler
 
446
  for the error.
 
447
*/
 
448
 
 
449
void Protocol::end_partial_result_set(THD *thd)
 
450
{
 
451
  net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
 
452
}
 
453
 
 
454
 
 
455
bool Protocol::flush()
 
456
{
 
457
  return net_flush(&thd->net);
 
458
}
 
459
 
 
460
 
 
461
/**
 
462
  Send name and type of result to client.
 
463
 
 
464
  Sum fields has table name empty and field_name.
 
465
 
 
466
  @param THD            Thread data object
 
467
  @param list           List of items to send to client
 
468
  @param flag           Bit mask with the following functions:
 
469
                        - 1 send number of rows
 
470
                        - 2 send default values
 
471
                        - 4 don't write eof packet
 
472
 
 
473
  @retval
 
474
    0   ok
 
475
  @retval
 
476
    1   Error  (Note that in this case the error is not sent to the
 
477
    client)
 
478
*/
 
479
bool Protocol::send_fields(List<Item> *list, uint flags)
 
480
{
 
481
  List_iterator_fast<Item> it(*list);
 
482
  Item *item;
 
483
  uchar buff[80];
 
484
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
 
485
  Protocol_text prot(thd);
 
486
  String *local_packet= prot.storage_packet();
 
487
  const CHARSET_INFO * const thd_charset= thd->variables.character_set_results;
 
488
 
 
489
  if (flags & SEND_NUM_ROWS)
 
490
  {                             // Packet with number of elements
 
491
    uchar *pos= net_store_length(buff, list->elements);
 
492
    (void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
 
493
  }
 
494
 
 
495
  while ((item=it++))
 
496
  {
 
497
    char *pos;
 
498
    const CHARSET_INFO * const cs= system_charset_info;
 
499
    Send_field field;
 
500
    item->make_field(&field);
 
501
 
 
502
    prot.prepare_for_resend();
 
503
 
 
504
 
 
505
    if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
 
506
        prot.store(field.db_name, (uint) strlen(field.db_name),
 
507
                   cs, thd_charset) ||
 
508
        prot.store(field.table_name, (uint) strlen(field.table_name),
 
509
                   cs, thd_charset) ||
 
510
        prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
 
511
                   cs, thd_charset) ||
 
512
        prot.store(field.col_name, (uint) strlen(field.col_name),
 
513
                   cs, thd_charset) ||
 
514
        prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
 
515
                   cs, thd_charset) ||
 
516
        local_packet->realloc(local_packet->length()+12))
 
517
      goto err;
 
518
 
 
519
    /* Store fixed length fields */
 
520
    pos= (char*) local_packet->ptr()+local_packet->length();
 
521
    *pos++= 12;                         // Length of packed fields
 
522
    if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
 
523
    {
 
524
      /* No conversion */
 
525
      int2store(pos, field.charsetnr);
 
526
      int4store(pos+2, field.length);
 
527
    }
 
528
    else
 
529
    {
 
530
      /* With conversion */
 
531
      uint max_char_len;
 
532
      int2store(pos, thd_charset->number);
 
533
      /*
 
534
        For TEXT/BLOB columns, field_length describes the maximum data
 
535
        length in bytes. There is no limit to the number of characters
 
536
        that a TEXT column can store, as long as the data fits into
 
537
        the designated space.
 
538
        For the rest of textual columns, field_length is evaluated as
 
539
        char_count * mbmaxlen, where character count is taken from the
 
540
        definition of the column. In other words, the maximum number
 
541
        of characters here is limited by the column definition.
 
542
      */
 
543
      max_char_len= field.length / item->collation.collation->mbmaxlen;
 
544
      int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
 
545
    }
 
546
    pos[6]= field.type;
 
547
    int2store(pos+7,field.flags);
 
548
    pos[9]= (char) field.decimals;
 
549
    pos[10]= 0;                         // For the future
 
550
    pos[11]= 0;                         // For the future
 
551
    pos+= 12;
 
552
 
 
553
    local_packet->length((uint) (pos - local_packet->ptr()));
 
554
    if (flags & SEND_DEFAULTS)
 
555
      item->send(&prot, &tmp);                  // Send default value
 
556
    if (prot.write())
 
557
      break;                                    /* purecov: inspected */
 
558
  }
 
559
 
 
560
  if (flags & SEND_EOF)
 
561
  {
 
562
    /*
 
563
      Mark the end of meta-data result set, and store thd->server_status,
 
564
      to show that there is no cursor.
 
565
      Send no warning information, as it will be sent at statement end.
 
566
    */
 
567
    write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
 
568
  }
 
569
  return(prepare_for_send(list));
 
570
 
 
571
err:
 
572
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
 
573
             MYF(0));   /* purecov: inspected */
 
574
  return(1);                            /* purecov: inspected */
 
575
}
 
576
 
 
577
 
 
578
bool Protocol::write()
 
579
{
 
580
  return(my_net_write(&thd->net, (uchar*) packet->ptr(),
 
581
                           packet->length()));
 
582
}
 
583
 
 
584
 
 
585
/**
 
586
  Send \\0 end terminated string.
 
587
 
 
588
  @param from   NullS or \\0 terminated string
 
589
 
 
590
  @note
 
591
    In most cases one should use store(from, length) instead of this function
 
592
 
 
593
  @retval
 
594
    0           ok
 
595
  @retval
 
596
    1           error
 
597
*/
 
598
 
 
599
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
 
600
{
 
601
  if (!from)
 
602
    return store_null();
 
603
  uint length= strlen(from);
 
604
  return store(from, length, cs);
 
605
}
 
606
 
 
607
 
 
608
/**
 
609
  Send a set of strings as one long string with ',' in between.
 
610
*/
 
611
 
 
612
bool Protocol::store(I_List<i_string>* str_list)
 
613
{
 
614
  char buf[256];
 
615
  String tmp(buf, sizeof(buf), &my_charset_bin);
 
616
  uint32_t len;
 
617
  I_List_iterator<i_string> it(*str_list);
 
618
  i_string* s;
 
619
 
 
620
  tmp.length(0);
 
621
  while ((s=it++))
 
622
  {
 
623
    tmp.append(s->ptr);
 
624
    tmp.append(',');
 
625
  }
 
626
  if ((len= tmp.length()))
 
627
    len--;                                      // Remove last ','
 
628
  return store((char*) tmp.ptr(), len,  tmp.charset());
 
629
}
 
630
 
 
631
 
 
632
/****************************************************************************
 
633
  Functions to handle the simple (default) protocol where everything is
 
634
  This protocol is the one that is used by default between the MySQL server
 
635
  and client when you are not using prepared statements.
 
636
 
 
637
  All data are sent as 'packed-string-length' followed by 'string-data'
 
638
****************************************************************************/
 
639
 
 
640
void Protocol_text::prepare_for_resend()
 
641
{
 
642
  packet->length(0);
 
643
}
 
644
 
 
645
bool Protocol_text::store_null()
 
646
{
 
647
  char buff[1];
 
648
  buff[0]= (char)251;
 
649
  return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
 
650
}
 
651
 
 
652
 
 
653
/**
 
654
  Auxilary function to convert string to the given character set
 
655
  and store in network buffer.
 
656
*/
 
657
 
 
658
bool Protocol::store_string_aux(const char *from, size_t length,
 
659
                                const CHARSET_INFO * const fromcs,
 
660
                                                                const CHARSET_INFO * const tocs)
 
661
{
 
662
  /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
 
663
  if (tocs && !my_charset_same(fromcs, tocs) &&
 
664
      fromcs != &my_charset_bin &&
 
665
      tocs != &my_charset_bin)
 
666
  {
 
667
    /* Store with conversion */
 
668
    return net_store_data((uchar*) from, length, fromcs, tocs);
 
669
  }
 
670
  /* Store without conversion */
 
671
  return net_store_data((uchar*) from, length);
 
672
}
 
673
 
 
674
 
 
675
bool Protocol_text::store(const char *from, size_t length,
 
676
                          const CHARSET_INFO * const fromcs,
 
677
                                                  const CHARSET_INFO * const tocs)
 
678
{
 
679
  return store_string_aux(from, length, fromcs, tocs);
 
680
}
 
681
 
 
682
 
 
683
bool Protocol_text::store(const char *from, size_t length,
 
684
                          const CHARSET_INFO * const fromcs)
 
685
{
 
686
  const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
 
687
  return store_string_aux(from, length, fromcs, tocs);
 
688
}
 
689
 
 
690
 
 
691
bool Protocol_text::store_tiny(int64_t from)
 
692
{
 
693
  char buff[20];
 
694
  return net_store_data((uchar*) buff,
 
695
                        (size_t) (int10_to_str((int) from, buff, -10) - buff));
 
696
}
 
697
 
 
698
 
 
699
bool Protocol_text::store_short(int64_t from)
 
700
{
 
701
  char buff[20];
 
702
  return net_store_data((uchar*) buff,
 
703
                        (size_t) (int10_to_str((int) from, buff, -10) -
 
704
                                  buff));
 
705
}
 
706
 
 
707
 
 
708
bool Protocol_text::store_long(int64_t from)
 
709
{
 
710
  char buff[20];
 
711
  return net_store_data((uchar*) buff,
 
712
                        (size_t) (int10_to_str((long int)from, buff,
 
713
                                               (from <0)?-10:10)-buff));
 
714
}
 
715
 
 
716
 
 
717
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
 
718
{
 
719
  char buff[22];
 
720
  return net_store_data((uchar*) buff,
 
721
                        (size_t) (int64_t10_to_str(from,buff,
 
722
                                                    unsigned_flag ? 10 : -10)-
 
723
                                  buff));
 
724
}
 
725
 
 
726
 
 
727
bool Protocol_text::store_decimal(const my_decimal *d)
 
728
{
 
729
  char buff[DECIMAL_MAX_STR_LENGTH];
 
730
  String str(buff, sizeof(buff), &my_charset_bin);
 
731
  (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
 
732
  return net_store_data((uchar*) str.ptr(), str.length());
 
733
}
 
734
 
 
735
 
 
736
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
 
737
{
 
738
  buffer->set_real((double) from, decimals, thd->charset());
 
739
  return net_store_data((uchar*) buffer->ptr(), buffer->length());
 
740
}
 
741
 
 
742
 
 
743
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
 
744
{
 
745
  buffer->set_real(from, decimals, thd->charset());
 
746
  return net_store_data((uchar*) buffer->ptr(), buffer->length());
 
747
}
 
748
 
 
749
 
 
750
bool Protocol_text::store(Field *field)
 
751
{
 
752
  if (field->is_null())
 
753
    return store_null();
 
754
  char buff[MAX_FIELD_WIDTH];
 
755
  String str(buff,sizeof(buff), &my_charset_bin);
 
756
  const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
 
757
 
 
758
  field->val_str(&str);
 
759
 
 
760
  return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
 
761
}
 
762
 
 
763
 
 
764
/**
 
765
  @todo
 
766
    Second_part format ("%06") needs to change when 
 
767
    we support 0-6 decimals for time.
 
768
*/
 
769
 
 
770
bool Protocol_text::store(DRIZZLE_TIME *tm)
 
771
{
 
772
  char buff[40];
 
773
  uint length;
 
774
  length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
 
775
                           (int) tm->year,
 
776
                           (int) tm->month,
 
777
                           (int) tm->day,
 
778
                           (int) tm->hour,
 
779
                           (int) tm->minute,
 
780
                           (int) tm->second);
 
781
  if (tm->second_part)
 
782
    length+= sprintf(buff+length, ".%06d",
 
783
                                     (int)tm->second_part);
 
784
  return net_store_data((uchar*) buff, length);
 
785
}
 
786
 
 
787
 
 
788
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
 
789
{
 
790
  char buff[MAX_DATE_STRING_REP_LENGTH];
 
791
  size_t length= my_date_to_str(tm, buff);
 
792
  return net_store_data((uchar*) buff, length);
 
793
}
 
794
 
 
795
 
 
796
/**
 
797
  @todo 
 
798
    Second_part format ("%06") needs to change when 
 
799
    we support 0-6 decimals for time.
 
800
*/
 
801
 
 
802
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
 
803
{
 
804
  char buff[40];
 
805
  uint length;
 
806
  uint day= (tm->year || tm->month) ? 0 : tm->day;
 
807
  length= sprintf(buff, "%s%02ld:%02d:%02d",
 
808
                           tm->neg ? "-" : "",
 
809
                           (long) day*24L+(long) tm->hour,
 
810
                           (int) tm->minute,
 
811
                           (int) tm->second);
 
812
  if (tm->second_part)
 
813
    length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
 
814
  return net_store_data((uchar*) buff, length);
 
815
}
 
816