~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/protocol.cc

code clean move Item_func_num1 and Item_func_connection_id to functions directory

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) 2008 Sun Microsystems
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; version 2 of the License.
9
 
 *
10
 
 * This program is distributed in the hope that it will be useful,
11
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 * GNU General Public License for more details.
14
 
 *
15
 
 * You should have received a copy of the GNU General Public License
16
 
 * along with this program; if not, write to the Free Software
17
 
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18
 
 */
19
 
 
20
 
#include "config.h"
21
 
#include <drizzled/gettext.h>
22
 
#include <drizzled/error.h>
23
 
#include <drizzled/query_id.h>
 
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
24
#include <drizzled/sql_state.h>
25
 
#include <drizzled/session.h>
26
 
#include "drizzled/internal/my_sys.h"
27
 
#include "drizzled/internal/m_string.h"
28
 
#include <algorithm>
29
 
#include <iostream>
30
 
#include <boost/program_options.hpp>
31
 
#include <drizzled/module/option_map.h>
32
 
#include "pack.h"
33
 
#include "errmsg.h"
34
 
#include "drizzle_protocol.h"
35
 
#include "options.h"
36
 
#include "table_function.h"
37
 
 
38
 
#define PROTOCOL_VERSION 10
39
 
 
40
 
namespace po= boost::program_options;
41
 
using namespace drizzled;
42
 
using namespace std;
43
 
 
44
 
namespace drizzle_protocol
45
 
{
46
 
 
47
 
 
48
 
static const uint32_t DRIZZLE_TCP_PORT= 4427;
 
25
 
49
26
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
50
 
static uint32_t port;
51
 
static uint32_t connect_timeout;
52
 
static uint32_t read_timeout;
53
 
static uint32_t write_timeout;
54
 
static uint32_t retry_count;
55
 
static uint32_t buffer_length;
56
 
static char* bind_address= NULL;
57
 
 
58
 
static plugin::TableFunction* drizzle_status_table_function_ptr= NULL;
59
 
 
60
 
ListenDrizzleProtocol::~ListenDrizzleProtocol()
61
 
{
62
 
  /* This is strdup'd from the options */
63
 
  free(bind_address);
64
 
}
65
 
 
66
 
const char* ListenDrizzleProtocol::getHost(void) const
67
 
{
68
 
  return bind_address;
69
 
}
70
 
 
71
 
in_port_t ListenDrizzleProtocol::getPort(void) const
72
 
{
73
 
  char *env;
74
 
 
75
 
  if (port == 0)
76
 
  {
77
 
    port= DRIZZLE_TCP_PORT;
78
 
 
79
 
    if ((env = getenv("DRIZZLE_TCP_PORT")))
80
 
      port= (uint32_t) atoi(env);
81
 
 
82
 
    assert(port != 0);
83
 
  }
84
 
 
85
 
  return (in_port_t) port;
86
 
}
87
 
 
88
 
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
89
 
{
90
 
  int new_fd;
91
 
  new_fd= acceptTcp(fd);
92
 
  if (new_fd == -1)
93
 
    return NULL;
94
 
 
95
 
  return new (nothrow) ClientDrizzleProtocol(new_fd, using_mysql41_protocol);
96
 
}
97
 
 
98
 
drizzled::atomic<uint64_t> ClientDrizzleProtocol::connectionCount;
99
 
drizzled::atomic<uint64_t> ClientDrizzleProtocol::failedConnections;
100
 
drizzled::atomic<uint64_t> ClientDrizzleProtocol::connected;
101
 
 
102
 
ClientDrizzleProtocol::ClientDrizzleProtocol(int fd, bool using_mysql41_protocol_arg):
103
 
  using_mysql41_protocol(using_mysql41_protocol_arg)
104
 
{
105
 
  net.vio= 0;
106
 
 
107
 
  if (fd == -1)
108
 
    return;
109
 
 
110
 
  if (drizzleclient_net_init_sock(&net, fd, 0, buffer_length))
111
 
    throw bad_alloc();
112
 
 
113
 
  drizzleclient_net_set_read_timeout(&net, read_timeout);
114
 
  drizzleclient_net_set_write_timeout(&net, write_timeout);
115
 
  net.retry_count=retry_count;
116
 
}
117
 
 
118
 
ClientDrizzleProtocol::~ClientDrizzleProtocol()
119
 
{
120
 
  if (net.vio)
121
 
    drizzleclient_vio_close(net.vio);
122
 
}
123
 
 
124
 
int ClientDrizzleProtocol::getFileDescriptor(void)
125
 
{
126
 
  return drizzleclient_net_get_sd(&net);
127
 
}
128
 
 
129
 
bool ClientDrizzleProtocol::isConnected()
130
 
{
131
 
  return net.vio != 0;
132
 
}
133
 
 
134
 
bool ClientDrizzleProtocol::isReading(void)
135
 
{
136
 
  return net.reading_or_writing == 1;
137
 
}
138
 
 
139
 
bool ClientDrizzleProtocol::isWriting(void)
140
 
{
141
 
  return net.reading_or_writing == 2;
142
 
}
143
 
 
144
 
bool ClientDrizzleProtocol::flush()
145
 
{
146
 
  if (net.vio == NULL)
147
 
    return false;
148
 
  bool ret= drizzleclient_net_write(&net, (unsigned char*) packet.ptr(),
149
 
                           packet.length());
150
 
  packet.length(0);
151
 
  return ret;
152
 
}
153
 
 
154
 
void ClientDrizzleProtocol::close(void)
155
 
{
156
 
  if (net.vio)
157
 
  { 
158
 
    drizzleclient_net_close(&net);
159
 
    drizzleclient_net_end(&net);
160
 
    connected.decrement();
161
 
  }
162
 
}
163
 
 
164
 
bool ClientDrizzleProtocol::authenticate()
165
 
{
166
 
  bool connection_is_valid;
167
 
 
168
 
  connectionCount.increment();
169
 
  connected.increment();
170
 
 
171
 
  /* Use "connect_timeout" value during connection phase */
172
 
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
173
 
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
174
 
 
175
 
  connection_is_valid= checkConnection();
176
 
 
177
 
  if (connection_is_valid)
178
 
    sendOK();
179
 
  else
180
 
  {
181
 
    sendError(session->main_da.sql_errno(), session->main_da.message());
182
 
    failedConnections.increment();
183
 
    return false;
184
 
  }
185
 
 
186
 
  /* Connect completed, set read/write timeouts back to default */
187
 
  drizzleclient_net_set_read_timeout(&net, read_timeout);
188
 
  drizzleclient_net_set_write_timeout(&net, write_timeout);
189
 
  return true;
190
 
}
191
 
 
192
 
bool ClientDrizzleProtocol::readCommand(char **l_packet, uint32_t *packet_length)
193
 
{
194
 
  /*
195
 
    This thread will do a blocking read from the client which
196
 
    will be interrupted when the next command is received from
197
 
    the client, the connection is closed or "net_wait_timeout"
198
 
    number of seconds has passed
199
 
  */
200
 
#ifdef NEVER
201
 
  /* We can do this much more efficiently with poll timeouts or watcher thread,
202
 
     disabling for now, which means net_wait_timeout == read_timeout. */
203
 
  drizzleclient_net_set_read_timeout(&net,
204
 
                                     session->variables.net_wait_timeout);
205
 
#endif
206
 
 
207
 
  net.pkt_nr=0;
208
 
 
209
 
  *packet_length= drizzleclient_net_read(&net);
210
 
  if (*packet_length == packet_error)
211
 
  {
212
 
    /* Check if we can continue without closing the connection */
213
 
 
214
 
    if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
215
 
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
216
 
    if (session->main_da.status() == Diagnostics_area::DA_ERROR)
217
 
      sendError(session->main_da.sql_errno(), session->main_da.message());
218
 
    else
219
 
      sendOK();
220
 
 
221
 
    if (net.error != 3)
222
 
      return false;                       // We have to close it.
223
 
 
224
 
    net.error= 0;
225
 
    *packet_length= 0;
226
 
    return true;
227
 
  }
228
 
 
229
 
  *l_packet= (char*) net.read_pos;
230
 
 
231
 
  /*
232
 
    'packet_length' contains length of data, as it was stored in packet
233
 
    header. In case of malformed header, drizzleclient_net_read returns zero.
234
 
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
235
 
    number of bytes was actually read from network.
236
 
    There is also an extra safety measure in drizzleclient_net_read:
237
 
    it sets packet[packet_length]= 0, but only for non-zero packets.
238
 
  */
239
 
 
240
 
  if (*packet_length == 0)                       /* safety */
241
 
  {
242
 
    /* Initialize with COM_SLEEP packet */
243
 
    (*l_packet)[0]= (unsigned char) COM_SLEEP;
244
 
    *packet_length= 1;
245
 
  }
246
 
  else if (using_mysql41_protocol)
247
 
  {
248
 
    /* Map from MySQL commands to Drizzle commands. */
249
 
    switch ((int)(*l_packet)[0])
250
 
    {
251
 
    case 0: /* SLEEP */
252
 
    case 1: /* QUIT */
253
 
    case 2: /* INIT_DB */
254
 
    case 3: /* QUERY */
255
 
      break;
256
 
 
257
 
    case 8: /* SHUTDOWN */
258
 
      (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
259
 
      break;
260
 
 
261
 
    case 14: /* PING */
262
 
      (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
263
 
      break;
264
 
 
265
 
 
266
 
    default:
267
 
      /* Just drop connection for MySQL commands we don't support. */
268
 
      (*l_packet)[0]= (unsigned char) COM_QUIT;
269
 
      *packet_length= 1;
270
 
      break;
271
 
    }
272
 
  }
273
 
 
274
 
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
275
 
  (*l_packet)[*packet_length]= '\0';                  /* safety */
276
 
 
277
 
#ifdef NEVER
278
 
  /* See comment above. */
279
 
  /* Restore read timeout value */
280
 
  drizzleclient_net_set_read_timeout(&net,
281
 
                                     session->variables.net_read_timeout);
282
 
#endif
283
 
 
284
 
  return true;
 
27
/* Declared non-static only because of the embedded library. */
 
28
static void net_send_error_packet(THD *thd, uint32_t sql_errno, const char *err);
 
29
static void write_eof_packet(THD *thd, NET *net,
 
30
                             uint32_t server_status, uint32_t total_warn_count);
 
31
 
 
32
bool Protocol::net_store_data(const unsigned char *from, size_t length)
 
33
{
 
34
  ulong packet_length=packet->length();
 
35
  /* 
 
36
     The +9 comes from that strings of length longer than 16M require
 
37
     9 bytes to be stored (see net_store_length).
 
38
  */
 
39
  if (packet_length+9+length > packet->alloced_length() &&
 
40
      packet->realloc(packet_length+9+length))
 
41
    return 1;
 
42
  unsigned char *to= net_store_length((unsigned char*) packet->ptr()+packet_length, length);
 
43
  memcpy(to,from,length);
 
44
  packet->length((uint) (to+length-(unsigned char*) packet->ptr()));
 
45
  return 0;
 
46
}
 
47
 
 
48
 
 
49
 
 
50
 
 
51
/*
 
52
  net_store_data() - extended version with character set conversion.
 
53
  
 
54
  It is optimized for short strings whose length after
 
55
  conversion is garanteed to be less than 251, which accupies
 
56
  exactly one byte to store length. It allows not to use
 
57
  the "convert" member as a temporary buffer, conversion
 
58
  is done directly to the "packet" member.
 
59
  The limit 251 is good enough to optimize send_fields()
 
60
  because column, table, database names fit into this limit.
 
61
*/
 
62
 
 
63
bool Protocol::net_store_data(const unsigned char *from, size_t length,
 
64
                              const CHARSET_INFO * const from_cs,
 
65
                                                          const CHARSET_INFO * const to_cs)
 
66
{
 
67
  uint32_t dummy_errors;
 
68
  /* Calculate maxumum possible result length */
 
69
  uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
 
70
  if (conv_length > 250)
 
71
  {
 
72
    /*
 
73
      For strings with conv_length greater than 250 bytes
 
74
      we don't know how many bytes we will need to store length: one or two,
 
75
      because we don't know result length until conversion is done.
 
76
      For example, when converting from utf8 (mbmaxlen=3) to latin1,
 
77
      conv_length=300 means that the result length can vary between 100 to 300.
 
78
      length=100 needs one byte, length=300 needs to bytes.
 
79
      
 
80
      Thus conversion directly to "packet" is not worthy.
 
81
      Let's use "convert" as a temporary buffer.
 
82
    */
 
83
    return (convert->copy((const char*) from, length, from_cs,
 
84
                          to_cs, &dummy_errors) ||
 
85
            net_store_data((const unsigned char*) convert->ptr(), convert->length()));
 
86
  }
 
87
 
 
88
  ulong packet_length= packet->length();
 
89
  ulong new_length= packet_length + conv_length + 1;
 
90
 
 
91
  if (new_length > packet->alloced_length() && packet->realloc(new_length))
 
92
    return 1;
 
93
 
 
94
  char *length_pos= (char*) packet->ptr() + packet_length;
 
95
  char *to= length_pos + 1;
 
96
 
 
97
  to+= copy_and_convert(to, conv_length, to_cs,
 
98
                        (const char*) from, length, from_cs, &dummy_errors);
 
99
 
 
100
  net_store_length((unsigned char*) length_pos, to - length_pos - 1);
 
101
  packet->length((uint) (to - packet->ptr()));
 
102
  return 0;
 
103
}
 
104
 
 
105
 
 
106
/**
 
107
  Send a error string to client.
 
108
 
 
109
  Design note:
 
110
  net_printf_error and net_send_error are low-level functions
 
111
  that shall be used only when a new connection is being
 
112
  established or at server startup.
 
113
 
 
114
  For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
 
115
  critical that every error that can be intercepted is issued in one
 
116
  place only, my_message_sql.
 
117
*/
 
118
void net_send_error(THD *thd, uint32_t sql_errno, const char *err)
 
119
{
 
120
  assert(sql_errno);
 
121
  assert(err && err[0]);
 
122
 
 
123
  /*
 
124
    It's one case when we can push an error even though there
 
125
    is an OK or EOF already.
 
126
  */
 
127
  thd->main_da.can_overwrite_status= true;
 
128
 
 
129
  /* Abort multi-result sets */
 
130
  thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
131
 
 
132
  net_send_error_packet(thd, sql_errno, err);
 
133
 
 
134
  thd->main_da.can_overwrite_status= false;
285
135
}
286
136
 
287
137
/**
290
140
  The ok packet has the following structure:
291
141
 
292
142
  - 0               : Marker (1 byte)
293
 
  - affected_rows    : Stored in 1-9 bytes
294
 
  - id        : Stored in 1-9 bytes
295
 
  - server_status    : Copy of session->server_status;  Can be used by client
 
143
  - affected_rows       : Stored in 1-9 bytes
 
144
  - id          : Stored in 1-9 bytes
 
145
  - server_status       : Copy of thd->server_status;  Can be used by client
296
146
  to check if we are inside an transaction.
297
 
  New in 4.0 client
298
 
  - warning_count    : Stored in 2 bytes; New in 4.1 client
299
 
  - message        : Stored as packed length (1-9 bytes) + message.
 
147
  New in 4.0 protocol
 
148
  - warning_count       : Stored in 2 bytes; New in 4.1 protocol
 
149
  - message             : Stored as packed length (1-9 bytes) + message.
300
150
  Is not stored if no message.
301
151
 
302
 
  @param session           Thread handler
303
 
  @param affected_rows       Number of rows changed by statement
304
 
  @param id           Auto_increment id for first row (if used)
305
 
  @param message       Message to send to the client (Used by mysql_status)
 
152
  @param thd               Thread handler
 
153
  @param affected_rows     Number of rows changed by statement
 
154
  @param id                Auto_increment id for first row (if used)
 
155
  @param message           Message to send to the client (Used by mysql_status)
306
156
*/
307
157
 
308
 
void ClientDrizzleProtocol::sendOK()
 
158
static void
 
159
net_send_ok(THD *thd,
 
160
            uint32_t server_status, uint32_t total_warn_count,
 
161
            ha_rows affected_rows, uint64_t id, const char *message)
309
162
{
 
163
  NET *net= &thd->net;
310
164
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
311
 
  const char *message= NULL;
312
 
  uint32_t tmp;
313
165
 
314
 
  if (!net.vio)    // hack for re-parsing queries
 
166
  if (! net->vio)       // hack for re-parsing queries
315
167
  {
316
168
    return;
317
169
  }
318
170
 
319
 
  buff[0]=0;                    // No fields
320
 
  if (session->main_da.status() == Diagnostics_area::DA_OK)
321
 
  {
322
 
    if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da.found_rows())
323
 
      pos=drizzleclient_net_store_length(buff+1,session->main_da.found_rows());
324
 
    else
325
 
      pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
326
 
    pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
327
 
    int2store(pos, session->main_da.server_status());
328
 
    pos+=2;
329
 
    tmp= min(session->main_da.total_warn_count(), (uint32_t)65535);
330
 
    message= session->main_da.message();
331
 
  }
332
 
  else
333
 
  {
334
 
    pos=drizzleclient_net_store_length(buff+1,0);
335
 
    pos=drizzleclient_net_store_length(pos, 0);
336
 
    int2store(pos, session->server_status);
337
 
    pos+=2;
338
 
    tmp= min(session->total_warn_count, (uint32_t)65535);
339
 
  }
 
171
  buff[0]=0;                                    // No fields
 
172
  pos=net_store_length(buff+1,affected_rows);
 
173
  pos=net_store_length(pos, id);
 
174
 
 
175
  int2store(pos, server_status);
 
176
  pos+=2;
340
177
 
341
178
  /* We can only return up to 65535 warnings in two bytes */
 
179
  uint32_t tmp= cmin(total_warn_count, (uint)65535);
342
180
  int2store(pos, tmp);
343
181
  pos+= 2;
344
182
 
345
 
  session->main_da.can_overwrite_status= true;
 
183
  thd->main_da.can_overwrite_status= true;
346
184
 
347
185
  if (message && message[0])
348
 
  {
349
 
    size_t length= strlen(message);
350
 
    pos=drizzleclient_net_store_length(pos,length);
351
 
    memcpy(pos,(unsigned char*) message,length);
352
 
    pos+=length;
353
 
  }
354
 
  drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
355
 
  drizzleclient_net_flush(&net);
 
186
    pos= net_store_data(pos, (unsigned char*) message, strlen(message));
 
187
  my_net_write(net, buff, (size_t) (pos-buff));
 
188
  net_flush(net);
356
189
 
357
 
  session->main_da.can_overwrite_status= false;
 
190
  thd->main_da.can_overwrite_status= false;
358
191
}
359
192
 
360
193
/**
362
195
 
363
196
  The eof packet has the following structure:
364
197
 
365
 
  - 254    (DRIZZLE_PROTOCOL_NO_MORE_DATA)    : Marker (1 byte)
366
 
  - warning_count    : Stored in 2 bytes; New in 4.1 client
367
 
  - status_flag    : Stored in 2 bytes;
 
198
  - 254 (DRIZZLE_PROTOCOL_NO_MORE_DATA) : Marker (1 byte)
 
199
  - warning_count       : Stored in 2 bytes; New in 4.1 protocol
 
200
  - status_flag : Stored in 2 bytes;
368
201
  For flags like SERVER_MORE_RESULTS_EXISTS.
369
202
 
370
203
  Note that the warning count will not be sent if 'no_flush' is set as
371
204
  we don't want to report the warning count until all data is sent to the
372
205
  client.
373
 
*/
374
 
 
375
 
void ClientDrizzleProtocol::sendEOF()
 
206
 
 
207
  @param thd            Thread handler
 
208
  @param no_flush       Set to 1 if there will be more data to the client,
 
209
                    like in send_fields().
 
210
*/    
 
211
 
 
212
static void
 
213
net_send_eof(THD *thd, uint32_t server_status, uint32_t total_warn_count)
376
214
{
 
215
  NET *net= &thd->net;
377
216
  /* Set to true if no active vio, to work well in case of --init-file */
378
 
  if (net.vio != 0)
 
217
  if (net->vio != 0)
379
218
  {
380
 
    session->main_da.can_overwrite_status= true;
381
 
    writeEOFPacket(session->main_da.server_status(),
382
 
                   session->main_da.total_warn_count());
383
 
    drizzleclient_net_flush(&net);
384
 
    session->main_da.can_overwrite_status= false;
 
219
    thd->main_da.can_overwrite_status= true;
 
220
    write_eof_packet(thd, net, server_status, total_warn_count);
 
221
    net_flush(net);
 
222
    thd->main_da.can_overwrite_status= false;
385
223
  }
386
 
  packet.shrink(buffer_length);
387
 
}
388
 
 
389
 
 
390
 
void ClientDrizzleProtocol::sendError(uint32_t sql_errno, const char *err)
391
 
{
 
224
}
 
225
 
 
226
 
 
227
/**
 
228
  Format EOF packet according to the current protocol and
 
229
  write it to the network output buffer.
 
230
*/
 
231
 
 
232
static void write_eof_packet(THD *thd, NET *net,
 
233
                             uint32_t server_status,
 
234
                             uint32_t total_warn_count)
 
235
{
 
236
  unsigned char buff[5];
 
237
  /*
 
238
    Don't send warn count during SP execution, as the warn_list
 
239
    is cleared between substatements, and mysqltest gets confused
 
240
  */
 
241
  uint32_t tmp= cmin(total_warn_count, (uint)65535);
 
242
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
 
243
  int2store(buff+1, tmp);
 
244
  /*
 
245
    The following test should never be true, but it's better to do it
 
246
    because if 'is_fatal_error' is set the server is not going to execute
 
247
    other queries (see the if test in dispatch_command / COM_QUERY)
 
248
  */
 
249
  if (thd->is_fatal_error)
 
250
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
251
  int2store(buff + 3, server_status);
 
252
  my_net_write(net, buff, 5);
 
253
}
 
254
 
 
255
void net_send_error_packet(THD *thd, uint32_t sql_errno, const char *err)
 
256
{
 
257
  NET *net= &thd->net;
392
258
  uint32_t length;
393
259
  /*
394
260
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
395
261
  */
396
262
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
397
263
 
398
 
  assert(sql_errno);
399
 
  assert(err && err[0]);
400
 
 
401
 
  /*
402
 
    It's one case when we can push an error even though there
403
 
    is an OK or EOF already.
404
 
  */
405
 
  session->main_da.can_overwrite_status= true;
406
 
 
407
 
  /* Abort multi-result sets */
408
 
  session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
409
 
 
410
 
  /**
411
 
    Send a error string to client.
412
 
 
413
 
    For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
414
 
    critical that every error that can be intercepted is issued in one
415
 
    place only, my_message_sql.
416
 
  */
417
 
 
418
 
  if (net.vio == 0)
 
264
  if (net->vio == 0)
419
265
  {
420
266
    return;
421
267
  }
423
269
  int2store(buff,sql_errno);
424
270
  pos= buff+2;
425
271
 
426
 
  /* The first # is to make the client backward compatible */
 
272
  /* The first # is to make the protocol backward compatible */
427
273
  buff[2]= '#';
428
 
  pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
429
 
  pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
 
274
  pos= (unsigned char*) my_stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
430
275
 
431
 
  char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
432
 
  tmp+= strlen((char*)pos);
433
 
  tmp[0]= '\0';
434
 
  length= (uint32_t)(tmp-(char*)buff);
 
276
  length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
 
277
                  (char*) buff);
435
278
  err= (char*) buff;
436
279
 
437
 
  drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
438
 
 
439
 
  session->main_da.can_overwrite_status= false;
440
 
}
 
280
  net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, 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
  uint32_t is used as agrument type because of MySQL type conventions:
 
291
  - uint32_t for 0..65536
 
292
  - ulong for 0..4294967296
 
293
  - uint64_t for bigger numbers.
 
294
*/
 
295
 
 
296
static unsigned char *net_store_length_fast(unsigned char *packet, uint32_t length)
 
297
{
 
298
  if (length < 251)
 
299
  {
 
300
    *packet=(unsigned char) 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
unsigned char *net_store_data(unsigned char *to, const unsigned char *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
unsigned char *net_store_data(unsigned char *to,int32_t from)
 
414
{
 
415
  char buff[20];
 
416
  uint32_t 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
unsigned char *net_store_data(unsigned char *to,int64_t from)
 
423
{
 
424
  char buff[22];
 
425
  uint32_t 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
 
441
460
 
442
461
/**
443
462
  Send name and type of result to client.
444
463
 
445
464
  Sum fields has table name empty and field_name.
446
465
 
447
 
  @param Session        Thread data object
448
 
  @param list            List of items to send to client
449
 
  @param flag            Bit mask with the following functions:
 
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:
450
469
                        - 1 send number of rows
451
470
                        - 2 send default values
452
471
                        - 4 don't write eof packet
453
472
 
454
473
  @retval
455
 
    0    ok
 
474
    0   ok
456
475
  @retval
457
 
    1    Error  (Note that in this case the error is not sent to the
 
476
    1   Error  (Note that in this case the error is not sent to the
458
477
    client)
459
478
*/
460
 
bool ClientDrizzleProtocol::sendFields(List<Item> *list)
 
479
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
461
480
{
462
481
  List_iterator_fast<Item> it(*list);
463
482
  Item *item;
464
483
  unsigned char buff[80];
465
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;
466
488
 
467
 
  unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
468
 
  (void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
 
489
  if (flags & SEND_NUM_ROWS)
 
490
  {                             // Packet with number of elements
 
491
    unsigned char *pos= net_store_length(buff, list->elements);
 
492
    (void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
 
493
  }
469
494
 
470
495
  while ((item=it++))
471
496
  {
472
497
    char *pos;
473
 
    SendField field;
 
498
    const CHARSET_INFO * const cs= system_charset_info;
 
499
    Send_field field;
474
500
    item->make_field(&field);
475
501
 
476
 
    packet.length(0);
477
 
 
478
 
    if (store(STRING_WITH_LEN("def")) ||
479
 
        store(field.db_name) ||
480
 
        store(field.table_name) ||
481
 
        store(field.org_table_name) ||
482
 
        store(field.col_name) ||
483
 
        store(field.org_col_name) ||
484
 
        packet.realloc(packet.length()+12))
 
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))
485
517
      goto err;
486
518
 
487
519
    /* Store fixed length fields */
488
 
    pos= (char*) packet.ptr()+packet.length();
489
 
    *pos++= 12;                // Length of packed fields
490
 
    /* No conversion */
491
 
    int2store(pos, field.charsetnr);
492
 
    int4store(pos+2, field.length);
493
 
 
494
 
    if (using_mysql41_protocol)
 
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)
495
523
    {
496
 
      /* Switch to MySQL field numbering. */
497
 
      switch (field.type)
498
 
      {
499
 
      case DRIZZLE_TYPE_LONG:
500
 
        pos[6]= 3;
501
 
        break;
502
 
 
503
 
      case DRIZZLE_TYPE_DOUBLE:
504
 
        pos[6]= 5;
505
 
        break;
506
 
 
507
 
      case DRIZZLE_TYPE_NULL:
508
 
        pos[6]= 6;
509
 
        break;
510
 
 
511
 
      case DRIZZLE_TYPE_TIMESTAMP:
512
 
        pos[6]= 7;
513
 
        break;
514
 
 
515
 
      case DRIZZLE_TYPE_LONGLONG:
516
 
        pos[6]= 8;
517
 
        break;
518
 
 
519
 
      case DRIZZLE_TYPE_DATETIME:
520
 
        pos[6]= 12;
521
 
        break;
522
 
 
523
 
      case DRIZZLE_TYPE_DATE:
524
 
        pos[6]= 14;
525
 
        break;
526
 
 
527
 
      case DRIZZLE_TYPE_VARCHAR:
528
 
        pos[6]= 15;
529
 
        break;
530
 
 
531
 
      case DRIZZLE_TYPE_DECIMAL:
532
 
        pos[6]= (char)246;
533
 
        break;
534
 
 
535
 
      case DRIZZLE_TYPE_ENUM:
536
 
        pos[6]= (char)247;
537
 
        break;
538
 
 
539
 
      case DRIZZLE_TYPE_BLOB:
540
 
        pos[6]= (char)252;
541
 
        break;
542
 
      }
 
524
      /* No conversion */
 
525
      int2store(pos, field.charsetnr);
 
526
      int4store(pos+2, field.length);
543
527
    }
544
528
    else
545
529
    {
546
 
      /* Add one to compensate for tinyint removal from enum. */
547
 
      pos[6]= field.type + 1;
 
530
      /* With conversion */
 
531
      uint32_t 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);
548
545
    }
549
 
 
 
546
    pos[6]= field.type;
550
547
    int2store(pos+7,field.flags);
551
548
    pos[9]= (char) field.decimals;
552
 
    pos[10]= 0;                // For the future
553
 
    pos[11]= 0;                // For the future
 
549
    pos[10]= 0;                         // For the future
 
550
    pos[11]= 0;                         // For the future
554
551
    pos+= 12;
555
552
 
556
 
    packet.length((uint32_t) (pos - packet.ptr()));
557
 
    if (flush())
558
 
      break;
 
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 */
559
558
  }
560
559
 
561
 
  /*
562
 
    Mark the end of meta-data result set, and store session->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
 
  writeEOFPacket(session->server_status, session->total_warn_count);
567
 
  return 0;
 
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));
568
570
 
569
571
err:
570
572
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
571
 
             MYF(0));
572
 
  return 1;
573
 
}
574
 
 
575
 
bool ClientDrizzleProtocol::store(Field *from)
576
 
{
577
 
  if (from->is_null())
578
 
    return store();
 
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, (unsigned char*) packet->ptr(),
 
581
                           packet->length()));
 
582
}
 
583
 
 
584
 
 
585
/**
 
586
  Send \\0 end terminated string.
 
587
 
 
588
  @param from   NULL 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
  uint32_t 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((unsigned char*) from, length, fromcs, tocs);
 
669
  }
 
670
  /* Store without conversion */
 
671
  return net_store_data((unsigned char*) 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((unsigned char*) 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((unsigned char*) 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((unsigned char*) 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((unsigned char*) 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((unsigned char*) 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((unsigned char*) 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((unsigned char*) buffer->ptr(), buffer->length());
 
747
}
 
748
 
 
749
 
 
750
bool Protocol_text::store(Field *field)
 
751
{
 
752
  if (field->is_null())
 
753
    return store_null();
579
754
  char buff[MAX_FIELD_WIDTH];
580
755
  String str(buff,sizeof(buff), &my_charset_bin);
581
 
 
582
 
  from->val_str(&str);
583
 
 
584
 
  return netStoreData((const unsigned char *)str.ptr(), str.length());
585
 
}
586
 
 
587
 
bool ClientDrizzleProtocol::store(void)
588
 
{
589
 
  char buff[1];
590
 
  buff[0]= (char)251;
591
 
  return packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
592
 
}
593
 
 
594
 
bool ClientDrizzleProtocol::store(int32_t from)
595
 
{
596
 
  char buff[12];
597
 
  return netStoreData((unsigned char*) buff,
598
 
                      (size_t) (internal::int10_to_str(from, buff, -10) - buff));
599
 
}
600
 
 
601
 
bool ClientDrizzleProtocol::store(uint32_t from)
602
 
{
603
 
  char buff[11];
604
 
  return netStoreData((unsigned char*) buff,
605
 
                      (size_t) (internal::int10_to_str(from, buff, 10) - buff));
606
 
}
607
 
 
608
 
bool ClientDrizzleProtocol::store(int64_t from)
609
 
{
610
 
  char buff[22];
611
 
  return netStoreData((unsigned char*) buff,
612
 
                      (size_t) (internal::int64_t10_to_str(from, buff, -10) - buff));
613
 
}
614
 
 
615
 
bool ClientDrizzleProtocol::store(uint64_t from)
616
 
{
617
 
  char buff[21];
618
 
  return netStoreData((unsigned char*) buff,
619
 
                      (size_t) (internal::int64_t10_to_str(from, buff, 10) - buff));
620
 
}
621
 
 
622
 
bool ClientDrizzleProtocol::store(double from, uint32_t decimals, String *buffer)
623
 
{
624
 
  buffer->set_real(from, decimals, session->charset());
625
 
  return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
626
 
}
627
 
 
628
 
bool ClientDrizzleProtocol::store(const char *from, size_t length)
629
 
{
630
 
  return netStoreData((const unsigned char *)from, length);
631
 
}
632
 
 
633
 
bool ClientDrizzleProtocol::wasAborted(void)
634
 
{
635
 
  return net.error && net.vio != 0;
636
 
}
637
 
 
638
 
bool ClientDrizzleProtocol::haveMoreData(void)
639
 
{
640
 
  return drizzleclient_net_more_data(&net);
641
 
}
642
 
 
643
 
bool ClientDrizzleProtocol::haveError(void)
644
 
{
645
 
  return net.error || net.vio == 0;
646
 
}
647
 
 
648
 
bool ClientDrizzleProtocol::checkConnection(void)
649
 
{
650
 
  uint32_t pkt_len= 0;
651
 
  char *end;
652
 
 
653
 
  // TCP/IP connection
654
 
  {
655
 
    char ip[NI_MAXHOST];
656
 
    uint16_t peer_port;
657
 
 
658
 
    if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
659
 
    {
660
 
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
661
 
      return false;
662
 
    }
663
 
 
664
 
    session->getSecurityContext().setIp(ip);
665
 
  }
666
 
  drizzleclient_net_keepalive(&net, true);
667
 
 
668
 
  uint32_t server_capabilites;
669
 
  {
670
 
    /* buff[] needs to big enough to hold the server_version variable */
671
 
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
672
 
 
673
 
    server_capabilites= CLIENT_BASIC_FLAGS;
674
 
 
675
 
    if (using_mysql41_protocol)
676
 
      server_capabilites|= CLIENT_PROTOCOL_MYSQL41;
677
 
 
678
 
#ifdef HAVE_COMPRESS
679
 
    server_capabilites|= CLIENT_COMPRESS;
680
 
#endif /* HAVE_COMPRESS */
681
 
 
682
 
    end= buff + strlen(PANDORA_RELEASE_VERSION);
683
 
    if ((end - buff) >= SERVER_VERSION_LENGTH)
684
 
      end= buff + (SERVER_VERSION_LENGTH - 1);
685
 
    memcpy(buff, PANDORA_RELEASE_VERSION, end - buff);
686
 
    *end= 0;
687
 
    end++;
688
 
 
689
 
    int4store((unsigned char*) end, session->variables.pseudo_thread_id);
690
 
    end+= 4;
691
 
 
692
 
    /* We don't use scramble anymore. */
693
 
    memset(end, 'X', SCRAMBLE_LENGTH_323);
694
 
    end+= SCRAMBLE_LENGTH_323;
695
 
    *end++= 0; /* an empty byte for some reason */
696
 
 
697
 
    int2store(end, server_capabilites);
698
 
    /* write server characteristics: up to 16 bytes allowed */
699
 
    end[2]=(char) default_charset_info->number;
700
 
    int2store(end+3, session->server_status);
701
 
    memset(end+5, 0, 13);
702
 
    end+= 18;
703
 
 
704
 
    /* Write scramble tail. */
705
 
    memset(end, 'X', SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
706
 
    end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
707
 
    *end++= 0; /* an empty byte for some reason */
708
 
 
709
 
    /* At this point we write connection message and read reply */
710
 
    if (drizzleclient_net_write_command(&net
711
 
          , (unsigned char) PROTOCOL_VERSION
712
 
          , (unsigned char*) ""
713
 
          , 0
714
 
          , (unsigned char*) buff
715
 
          , (size_t) (end-buff)) 
716
 
        ||    (pkt_len= drizzleclient_net_read(&net)) == packet_error 
717
 
        || pkt_len < MIN_HANDSHAKE_SIZE)
718
 
    {
719
 
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
720
 
      return false;
721
 
    }
722
 
  }
723
 
  if (packet.alloc(buffer_length))
724
 
    return false; /* The error is set by alloc(). */
725
 
 
726
 
  client_capabilities= uint2korr(net.read_pos);
727
 
 
728
 
 
729
 
  client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
730
 
  session->max_client_packet_length= uint4korr(net.read_pos + 4);
731
 
  end= (char*) net.read_pos + 32;
732
 
 
733
 
  /*
734
 
    Disable those bits which are not supported by the server.
735
 
    This is a precautionary measure, if the client lies. See Bug#27944.
736
 
  */
737
 
  client_capabilities&= server_capabilites;
738
 
 
739
 
  if (end >= (char*) net.read_pos + pkt_len + 2)
740
 
  {
741
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
742
 
    return false;
743
 
  }
744
 
 
745
 
  net.return_status= &session->server_status;
746
 
 
747
 
  char *user= end;
748
 
  char *passwd= strchr(user, '\0')+1;
749
 
  uint32_t user_len= passwd - user - 1;
750
 
  char *l_db= passwd;
751
 
 
752
 
  /*
753
 
    Old clients send null-terminated string as password; new clients send
754
 
    the size (1 byte) + string (not null-terminated). Hence in case of empty
755
 
    password both send '\0'.
756
 
 
757
 
    This strlen() can't be easily deleted without changing client.
758
 
 
759
 
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
760
 
    *passwd > 127 and become 2**32-127+ after casting to uint.
761
 
  */
762
 
  uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
763
 
    (unsigned char)(*passwd++) : strlen(passwd);
764
 
  l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
765
 
 
766
 
  /* strlen() can't be easily deleted without changing client */
767
 
  uint32_t db_len= l_db ? strlen(l_db) : 0;
768
 
 
769
 
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
770
 
  {
771
 
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
772
 
    return false;
773
 
  }
774
 
 
775
 
  /* If username starts and ends in "'", chop them off */
776
 
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
777
 
  {
778
 
    user[user_len-1]= 0;
779
 
    user++;
780
 
    user_len-= 2;
781
 
  }
782
 
 
783
 
  session->getSecurityContext().setUser(user);
784
 
 
785
 
  return session->checkUser(passwd, passwd_len, l_db);
786
 
}
787
 
 
788
 
bool ClientDrizzleProtocol::netStoreData(const unsigned char *from, size_t length)
789
 
{
790
 
  size_t packet_length= packet.length();
791
 
  /*
792
 
     The +9 comes from that strings of length longer than 16M require
793
 
     9 bytes to be stored (see drizzleclient_net_store_length).
794
 
  */
795
 
  if (packet_length+9+length > packet.alloced_length() &&
796
 
      packet.realloc(packet_length+9+length))
797
 
    return 1;
798
 
  unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet.ptr()+packet_length, length);
799
 
  memcpy(to,from,length);
800
 
  packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
801
 
  return 0;
802
 
}
803
 
 
804
 
/**
805
 
  Format EOF packet according to the current client and
806
 
  write it to the network output buffer.
807
 
*/
808
 
 
809
 
void ClientDrizzleProtocol::writeEOFPacket(uint32_t server_status,
810
 
                                         uint32_t total_warn_count)
811
 
{
812
 
  unsigned char buff[5];
813
 
  /*
814
 
    Don't send warn count during SP execution, as the warn_list
815
 
    is cleared between substatements, and mysqltest gets confused
816
 
  */
817
 
  uint32_t tmp= min(total_warn_count, (uint32_t)65535);
818
 
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
819
 
  int2store(buff+1, tmp);
820
 
  /*
821
 
    The following test should never be true, but it's better to do it
822
 
    because if 'is_fatal_error' is set the server is not going to execute
823
 
    other queries (see the if test in dispatch_command / COM_QUERY)
824
 
  */
825
 
  if (session->is_fatal_error)
826
 
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
827
 
  int2store(buff + 3, server_status);
828
 
  drizzleclient_net_write(&net, buff, 5);
829
 
}
830
 
 
831
 
static int init(module::Context &context)
832
 
{
833
 
  drizzle_status_table_function_ptr= new DrizzleProtocolStatus;
834
 
 
835
 
  context.add(drizzle_status_table_function_ptr);
836
 
 
837
 
  const module::option_map &vm= context.getOptions();
838
 
  if (vm.count("port"))
839
 
  { 
840
 
    if (port > 65535)
841
 
    {
842
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of port\n"));
843
 
      exit(-1);
844
 
    }
845
 
  }
846
 
 
847
 
  if (vm.count("connect-timeout"))
848
 
  {
849
 
    if (connect_timeout < 1 || connect_timeout > 300)
850
 
    {
851
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for connect_timeout\n"));
852
 
      exit(-1);
853
 
    }
854
 
  }
855
 
 
856
 
  if (vm.count("read-timeout"))
857
 
  {
858
 
    if (read_timeout < 1 || read_timeout > 300)
859
 
    {
860
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for read_timeout\n"));
861
 
      exit(-1);
862
 
    }
863
 
  }
864
 
 
865
 
  if (vm.count("write-timeout"))
866
 
  {
867
 
    if (write_timeout < 1 || write_timeout > 300)
868
 
    {
869
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for write_timeout\n"));
870
 
      exit(-1);
871
 
    }
872
 
  }
873
 
 
874
 
  if (vm.count("retry-count"))
875
 
  {
876
 
    if (retry_count < 1 || retry_count > 100)
877
 
    {
878
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for retry_count\n"));
879
 
      exit(-1);
880
 
    }
881
 
  }
882
 
 
883
 
  if (vm.count("buffer-length"))
884
 
  {
885
 
    if (buffer_length < 1024 || buffer_length > 1024*1024)
886
 
    {
887
 
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for buffer_length\n"));
888
 
      exit(-1);
889
 
    }
890
 
  }
891
 
 
892
 
  if (vm.count("bind-address"))
893
 
  {
894
 
    bind_address= strdup(vm["bind-address"].as<string>().c_str());
895
 
  }
896
 
 
897
 
  else
898
 
  {
899
 
    bind_address= NULL;
900
 
  }
901
 
  
902
 
  context.add(new ListenDrizzleProtocol("drizzle_protocol", false)); 
903
 
  return 0;
904
 
}
905
 
 
906
 
static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
907
 
                           N_("Port number to use for connection or 0 for "
908
 
                              "default to, in order of "
909
 
                              "preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
910
 
                              "built-in default (4427)."),
911
 
                           NULL, NULL, 0, 0, 65535, 0);
912
 
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
913
 
                           PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
914
 
                           NULL, NULL, 10, 1, 300, 0);
915
 
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
916
 
                           N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
917
 
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
918
 
                           N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
919
 
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
920
 
                           N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
921
 
static DRIZZLE_SYSVAR_UINT(buffer_length, buffer_length, PLUGIN_VAR_RQCMDARG,
922
 
                           N_("Buffer length."), NULL, NULL, 16384, 1024,
923
 
                           1024*1024, 0);
924
 
static DRIZZLE_SYSVAR_STR(bind_address, bind_address, PLUGIN_VAR_READONLY,
925
 
                          N_("Address to bind to."), NULL, NULL, NULL);
926
 
 
927
 
static void init_options(drizzled::module::option_context &context)
928
 
{
929
 
  context("port",
930
 
          po::value<uint32_t>(&port)->default_value(0),
931
 
          N_("Port number to use for connection or 0 for "
932
 
                              "default to, in order of "
933
 
                              "preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
934
 
                              "built-in default (4427)."));
935
 
  context("connect-timeout",
936
 
          po::value<uint32_t>(&connect_timeout)->default_value(10),
937
 
          N_("Connect Timeout."));
938
 
  context("read-timeout",
939
 
          po::value<uint32_t>(&read_timeout)->default_value(30),
940
 
          N_("Read Timeout."));
941
 
  context("write-timeout",
942
 
          po::value<uint32_t>(&write_timeout)->default_value(60),
943
 
          N_("Write Timeout."));
944
 
  context("retry-count",
945
 
          po::value<uint32_t>(&retry_count)->default_value(10),
946
 
          N_("Retry Count."));
947
 
  context("buffer-length",
948
 
          po::value<uint32_t>(&buffer_length)->default_value(16384),
949
 
          N_("Buffer length."));
950
 
  context("bind-address",
951
 
          po::value<string>(),
952
 
          N_("Address to bind to."));
953
 
}
954
 
 
955
 
static drizzle_sys_var* sys_variables[]= {
956
 
  DRIZZLE_SYSVAR(port),
957
 
  DRIZZLE_SYSVAR(connect_timeout),
958
 
  DRIZZLE_SYSVAR(read_timeout),
959
 
  DRIZZLE_SYSVAR(write_timeout),
960
 
  DRIZZLE_SYSVAR(retry_count),
961
 
  DRIZZLE_SYSVAR(buffer_length),
962
 
  DRIZZLE_SYSVAR(bind_address),
963
 
  NULL
964
 
};
965
 
 
966
 
static int drizzle_protocol_connection_count_func(drizzle_show_var *var, char *buff)
967
 
{
968
 
  var->type= SHOW_LONGLONG;
969
 
  var->value= buff;
970
 
  *((uint64_t *)buff)= ClientDrizzleProtocol::connectionCount;
971
 
  return 0;
972
 
}
973
 
 
974
 
static int drizzle_protocol_connected_count_func(drizzle_show_var *var, char *buff)
975
 
{
976
 
  var->type= SHOW_LONGLONG;
977
 
  var->value= buff;
978
 
  *((uint64_t *)buff)= ClientDrizzleProtocol::connected;
979
 
  return 0;
980
 
}
981
 
 
982
 
static int drizzle_protocol_failed_count_func(drizzle_show_var *var, char *buff)
983
 
{
984
 
  var->type= SHOW_LONGLONG;
985
 
  var->value= buff;
986
 
  *((uint64_t *)buff)= ClientDrizzleProtocol::failedConnections;
987
 
  return 0;
988
 
}
989
 
 
990
 
static st_show_var_func_container drizzle_protocol_connection_count=
991
 
  { &drizzle_protocol_connection_count_func };
992
 
 
993
 
static st_show_var_func_container drizzle_protocol_connected_count=
994
 
  { &drizzle_protocol_connected_count_func };
995
 
 
996
 
static st_show_var_func_container drizzle_protocol_failed_count=
997
 
  { &drizzle_protocol_failed_count_func };
998
 
 
999
 
static drizzle_show_var drizzle_protocol_status_variables[]= {
1000
 
  {"Connections",
1001
 
  (char*) &drizzle_protocol_connection_count, SHOW_FUNC},
1002
 
  {"Connected",
1003
 
  (char*) &drizzle_protocol_connected_count, SHOW_FUNC},
1004
 
  {"Failed_connections",
1005
 
  (char*) &drizzle_protocol_failed_count, SHOW_FUNC},
1006
 
  {NULL, NULL, SHOW_LONGLONG}
1007
 
};
1008
 
 
1009
 
DrizzleProtocolStatus::Generator::Generator(drizzled::Field **fields) :
1010
 
  plugin::TableFunction::Generator(fields)
1011
 
{
1012
 
  status_var_ptr= drizzle_protocol_status_variables;
1013
 
}
1014
 
 
1015
 
bool DrizzleProtocolStatus::Generator::populate()
1016
 
{
1017
 
  MY_ALIGNED_BYTE_ARRAY(buff_data, SHOW_VAR_FUNC_BUFF_SIZE, int64_t);
1018
 
  char * const buff= (char *) &buff_data;
1019
 
  drizzle_show_var tmp;
1020
 
 
1021
 
  if (status_var_ptr->name)
1022
 
  {
1023
 
    std::ostringstream oss;
1024
 
    string return_value;
1025
 
    const char *value;
1026
 
    int type;
1027
 
 
1028
 
    push(status_var_ptr->name);
1029
 
 
1030
 
    if (status_var_ptr->type == SHOW_FUNC)
1031
 
    {
1032
 
      ((mysql_show_var_func)((st_show_var_func_container *)status_var_ptr->value)->func)(&tmp, buff);
1033
 
      value= buff;
1034
 
      type= tmp.type;
1035
 
    }
1036
 
    else
1037
 
    {
1038
 
      value= status_var_ptr->value;
1039
 
      type= status_var_ptr->type;
1040
 
    }
1041
 
 
1042
 
    switch(type)
1043
 
    {
1044
 
    case SHOW_LONGLONG:
1045
 
      oss << *(uint64_t*) value;
1046
 
      return_value= oss.str();
1047
 
      break;
1048
 
    default:
1049
 
      assert(0);
1050
 
    }
1051
 
    if (return_value.length())
1052
 
      push(return_value);
1053
 
    else
1054
 
      push(" ");
1055
 
 
1056
 
    status_var_ptr++;
1057
 
 
1058
 
    return true;
1059
 
  }
1060
 
  return false;
1061
 
}
1062
 
 
1063
 
} /* namespace drizzle_protocol */
1064
 
 
1065
 
DRIZZLE_PLUGIN(drizzle_protocol::init, drizzle_protocol::sys_variables, drizzle_protocol::init_options);
 
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
  uint32_t 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((unsigned char*) 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((unsigned char*) 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
  uint32_t length;
 
806
  uint32_t 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((unsigned char*) buff, length);
 
815
}
 
816