~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/drizzle_protocol/oldlibdrizzle.cc

  • Committer: Brian Aker
  • Date: 2010-02-07 01:33:54 UTC
  • Revision ID: brian@gaz-20100207013354-d2pg1n68u5c09pgo
Remove giant include header to its own file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2003 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
/**
17
 
  @file
18
 
 
19
 
  Low level functions for storing data to be send to the MySQL client.
20
 
  The actual communction is handled by the net_xxx functions in net_serv.cc
21
 
*/
22
 
#include <drizzled/server_includes.h>
23
 
#include <drizzled/drizzled_error_messages.h>
24
 
 
 
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/my_error.h"
 
24
#include <drizzled/query_id.h>
 
25
#include <drizzled/sql_state.h>
 
26
#include <drizzled/session.h>
 
27
#include "drizzled/internal/my_sys.h"
 
28
#include "drizzled/internal/m_string.h"
 
29
#include <algorithm>
 
30
 
 
31
#include "pack.h"
 
32
#include "errmsg.h"
 
33
#include "oldlibdrizzle.h"
 
34
#include "options.h"
 
35
 
 
36
#define PROTOCOL_VERSION 10
 
37
 
 
38
namespace drizzled
 
39
{
 
40
extern uint32_t global_thread_id;
 
41
}
 
42
 
 
43
using namespace std;
 
44
using namespace drizzled;
 
45
 
 
46
static const uint32_t DRIZZLE_TCP_PORT= 4427;
25
47
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;
 
48
static uint32_t port;
 
49
static uint32_t connect_timeout;
 
50
static uint32_t read_timeout;
 
51
static uint32_t write_timeout;
 
52
static uint32_t retry_count;
 
53
static uint32_t buffer_length;
 
54
static char* bind_address;
 
55
 
 
56
const char* ListenDrizzleProtocol::getHost(void) const
 
57
{
 
58
  return bind_address;
 
59
}
 
60
 
 
61
in_port_t ListenDrizzleProtocol::getPort(void) const
 
62
{
 
63
  char *env;
 
64
 
 
65
  if (port == 0)
 
66
  {
 
67
    port= DRIZZLE_TCP_PORT;
 
68
 
 
69
    if ((env = getenv("DRIZZLE_TCP_PORT")))
 
70
      port= (uint32_t) atoi(env);
 
71
 
 
72
    assert(port != 0);
 
73
  }
 
74
 
 
75
  return (in_port_t) port;
 
76
}
 
77
 
 
78
plugin::Client *ListenDrizzleProtocol::getClient(int fd)
 
79
{
 
80
  int new_fd;
 
81
  new_fd= acceptTcp(fd);
 
82
  if (new_fd == -1)
 
83
    return NULL;
 
84
 
 
85
  return new (nothrow) ClientDrizzleProtocol(new_fd, using_mysql41_protocol);
 
86
}
 
87
 
 
88
ClientDrizzleProtocol::ClientDrizzleProtocol(int fd, bool using_mysql41_protocol_arg):
 
89
  using_mysql41_protocol(using_mysql41_protocol_arg)
 
90
{
 
91
  net.vio= 0;
 
92
 
 
93
  if (fd == -1)
 
94
    return;
 
95
 
 
96
  if (drizzleclient_net_init_sock(&net, fd, 0, buffer_length))
 
97
    throw bad_alloc();
 
98
 
 
99
  drizzleclient_net_set_read_timeout(&net, read_timeout);
 
100
  drizzleclient_net_set_write_timeout(&net, write_timeout);
 
101
  net.retry_count=retry_count;
 
102
}
 
103
 
 
104
ClientDrizzleProtocol::~ClientDrizzleProtocol()
 
105
{
 
106
  if (net.vio)
 
107
    drizzleclient_vio_close(net.vio);
 
108
}
 
109
 
 
110
int ClientDrizzleProtocol::getFileDescriptor(void)
 
111
{
 
112
  return drizzleclient_net_get_sd(&net);
 
113
}
 
114
 
 
115
bool ClientDrizzleProtocol::isConnected()
 
116
{
 
117
  return net.vio != 0;
 
118
}
 
119
 
 
120
bool ClientDrizzleProtocol::isReading(void)
 
121
{
 
122
  return net.reading_or_writing == 1;
 
123
}
 
124
 
 
125
bool ClientDrizzleProtocol::isWriting(void)
 
126
{
 
127
  return net.reading_or_writing == 2;
 
128
}
 
129
 
 
130
bool ClientDrizzleProtocol::flush()
 
131
{
 
132
  if (net.vio == NULL)
 
133
    return false;
 
134
  bool ret= drizzleclient_net_write(&net, (unsigned char*) packet.ptr(),
 
135
                           packet.length());
 
136
  packet.length(0);
 
137
  return ret;
 
138
}
 
139
 
 
140
void ClientDrizzleProtocol::close(void)
 
141
{
 
142
  if (net.vio)
 
143
  { 
 
144
    drizzleclient_net_close(&net);
 
145
    drizzleclient_net_end(&net);
 
146
  }
 
147
}
 
148
 
 
149
bool ClientDrizzleProtocol::authenticate()
 
150
{
 
151
  bool connection_is_valid;
 
152
 
 
153
  /* Use "connect_timeout" value during connection phase */
 
154
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
 
155
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
 
156
 
 
157
  connection_is_valid= checkConnection();
 
158
 
 
159
  if (connection_is_valid)
 
160
    sendOK();
 
161
  else
 
162
  {
 
163
    sendError(session->main_da.sql_errno(), session->main_da.message());
 
164
    return false;
 
165
  }
 
166
 
 
167
  /* Connect completed, set read/write timeouts back to default */
 
168
  drizzleclient_net_set_read_timeout(&net, read_timeout);
 
169
  drizzleclient_net_set_write_timeout(&net, write_timeout);
 
170
  return true;
 
171
}
 
172
 
 
173
bool ClientDrizzleProtocol::readCommand(char **l_packet, uint32_t *packet_length)
 
174
{
 
175
  /*
 
176
    This thread will do a blocking read from the client which
 
177
    will be interrupted when the next command is received from
 
178
    the client, the connection is closed or "net_wait_timeout"
 
179
    number of seconds has passed
 
180
  */
 
181
#ifdef NEVER
 
182
  /* We can do this much more efficiently with poll timeouts or watcher thread,
 
183
     disabling for now, which means net_wait_timeout == read_timeout. */
 
184
  drizzleclient_net_set_read_timeout(&net,
 
185
                                     session->variables.net_wait_timeout);
 
186
#endif
 
187
 
 
188
  net.pkt_nr=0;
 
189
 
 
190
  *packet_length= drizzleclient_net_read(&net);
 
191
  if (*packet_length == packet_error)
 
192
  {
 
193
    /* Check if we can continue without closing the connection */
 
194
 
 
195
    if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
 
196
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
 
197
    if (session->main_da.status() == Diagnostics_area::DA_ERROR)
 
198
      sendError(session->main_da.sql_errno(), session->main_da.message());
 
199
    else
 
200
      sendOK();
 
201
 
 
202
    if (net.error != 3)
 
203
      return false;                       // We have to close it.
 
204
 
 
205
    net.error= 0;
 
206
    *packet_length= 0;
 
207
    return true;
 
208
  }
 
209
 
 
210
  *l_packet= (char*) net.read_pos;
 
211
 
 
212
  /*
 
213
    'packet_length' contains length of data, as it was stored in packet
 
214
    header. In case of malformed header, drizzleclient_net_read returns zero.
 
215
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
 
216
    number of bytes was actually read from network.
 
217
    There is also an extra safety measure in drizzleclient_net_read:
 
218
    it sets packet[packet_length]= 0, but only for non-zero packets.
 
219
  */
 
220
 
 
221
  if (*packet_length == 0)                       /* safety */
 
222
  {
 
223
    /* Initialize with COM_SLEEP packet */
 
224
    (*l_packet)[0]= (unsigned char) COM_SLEEP;
 
225
    *packet_length= 1;
 
226
  }
 
227
  else if (using_mysql41_protocol)
 
228
  {
 
229
    /* Map from MySQL commands to Drizzle commands. */
 
230
    switch ((int)(*l_packet)[0])
 
231
    {
 
232
    case 0: /* SLEEP */
 
233
    case 1: /* QUIT */
 
234
    case 2: /* INIT_DB */
 
235
    case 3: /* QUERY */
 
236
      break;
 
237
 
 
238
    case 8: /* SHUTDOWN */
 
239
      (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
 
240
      break;
 
241
 
 
242
    case 14: /* PING */
 
243
      (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
 
244
      break;
 
245
 
 
246
 
 
247
    default:
 
248
      /* Just drop connection for MySQL commands we don't support. */
 
249
      (*l_packet)[0]= (unsigned char) COM_QUIT;
 
250
      *packet_length= 1;
 
251
      break;
 
252
    }
 
253
  }
 
254
 
 
255
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
 
256
  (*l_packet)[*packet_length]= '\0';                  /* safety */
 
257
 
 
258
#ifdef NEVER
 
259
  /* See comment above. */
 
260
  /* Restore read timeout value */
 
261
  drizzleclient_net_set_read_timeout(&net,
 
262
                                     session->variables.net_read_timeout);
 
263
#endif
 
264
 
 
265
  return true;
134
266
}
135
267
 
136
268
/**
139
271
  The ok packet has the following structure:
140
272
 
141
273
  - 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
 
274
  - affected_rows    : Stored in 1-9 bytes
 
275
  - id        : Stored in 1-9 bytes
 
276
  - server_status    : Copy of session->server_status;  Can be used by client
145
277
  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.
 
278
  New in 4.0 client
 
279
  - warning_count    : Stored in 2 bytes; New in 4.1 client
 
280
  - message        : Stored as packed length (1-9 bytes) + message.
149
281
  Is not stored if no message.
150
282
 
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)
 
283
  @param session           Thread handler
 
284
  @param affected_rows       Number of rows changed by statement
 
285
  @param id           Auto_increment id for first row (if used)
 
286
  @param message       Message to send to the client (Used by mysql_status)
155
287
*/
156
288
 
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)
 
289
void ClientDrizzleProtocol::sendOK()
161
290
{
162
 
  NET *net= &thd->net;
163
 
  uchar buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
 
291
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
 
292
  const char *message= NULL;
 
293
  uint32_t tmp;
164
294
 
165
 
  if (! net->vio)       // hack for re-parsing queries
 
295
  if (!net.vio)    // hack for re-parsing queries
166
296
  {
167
297
    return;
168
298
  }
169
299
 
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;
 
300
  buff[0]=0;                    // No fields
 
301
  if (session->main_da.status() == Diagnostics_area::DA_OK)
 
302
  {
 
303
    if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da.found_rows())
 
304
      pos=drizzleclient_net_store_length(buff+1,session->main_da.found_rows());
 
305
    else
 
306
      pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
 
307
    pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
 
308
    int2store(pos, session->main_da.server_status());
 
309
    pos+=2;
 
310
    tmp= min(session->main_da.total_warn_count(), (uint32_t)65535);
 
311
    message= session->main_da.message();
 
312
  }
 
313
  else
 
314
  {
 
315
    pos=drizzleclient_net_store_length(buff+1,0);
 
316
    pos=drizzleclient_net_store_length(pos, 0);
 
317
    int2store(pos, session->server_status);
 
318
    pos+=2;
 
319
    tmp= min(session->total_warn_count, (uint32_t)65535);
 
320
  }
176
321
 
177
322
  /* We can only return up to 65535 warnings in two bytes */
178
 
  uint tmp= min(total_warn_count, (uint)65535);
179
323
  int2store(pos, tmp);
180
324
  pos+= 2;
181
325
 
182
 
  thd->main_da.can_overwrite_status= true;
 
326
  session->main_da.can_overwrite_status= true;
183
327
 
184
328
  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));
 
329
  {
 
330
    size_t length= strlen(message);
 
331
    pos=drizzleclient_net_store_length(pos,length);
 
332
    memcpy(pos,(unsigned char*) message,length);
 
333
    pos+=length;
 
334
  }
 
335
  drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
 
336
  drizzleclient_net_flush(&net);
188
337
 
189
 
  thd->main_da.can_overwrite_status= false;
 
338
  session->main_da.can_overwrite_status= false;
190
339
}
191
340
 
192
341
/**
194
343
 
195
344
  The eof packet has the following structure:
196
345
 
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;
 
346
  - 254    (DRIZZLE_PROTOCOL_NO_MORE_DATA)    : Marker (1 byte)
 
347
  - warning_count    : Stored in 2 bytes; New in 4.1 client
 
348
  - status_flag    : Stored in 2 bytes;
200
349
  For flags like SERVER_MORE_RESULTS_EXISTS.
201
350
 
202
351
  Note that the warning count will not be sent if 'no_flush' is set as
203
352
  we don't want to report the warning count until all data is sent to the
204
353
  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)
 
354
*/
 
355
 
 
356
void ClientDrizzleProtocol::sendEOF()
213
357
{
214
 
  NET *net= &thd->net;
215
358
  /* Set to true if no active vio, to work well in case of --init-file */
216
 
  if (net->vio != 0)
 
359
  if (net.vio != 0)
217
360
  {
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;
 
361
    session->main_da.can_overwrite_status= true;
 
362
    writeEOFPacket(session->main_da.server_status(),
 
363
                   session->main_da.total_warn_count());
 
364
    drizzleclient_net_flush(&net);
 
365
    session->main_da.can_overwrite_status= false;
222
366
  }
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;
 
367
  packet.shrink(buffer_length);
 
368
}
 
369
 
 
370
 
 
371
void ClientDrizzleProtocol::sendError(uint32_t sql_errno, const char *err)
 
372
{
 
373
  uint32_t length;
258
374
  /*
259
375
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
260
376
  */
261
 
  uchar buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
262
 
 
263
 
  if (net->vio == 0)
 
377
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
 
378
 
 
379
  assert(sql_errno);
 
380
  assert(err && err[0]);
 
381
 
 
382
  /*
 
383
    It's one case when we can push an error even though there
 
384
    is an OK or EOF already.
 
385
  */
 
386
  session->main_da.can_overwrite_status= true;
 
387
 
 
388
  /* Abort multi-result sets */
 
389
  session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
390
 
 
391
  /**
 
392
    Send a error string to client.
 
393
 
 
394
    For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
 
395
    critical that every error that can be intercepted is issued in one
 
396
    place only, my_message_sql.
 
397
  */
 
398
 
 
399
  if (net.vio == 0)
264
400
  {
265
401
    return;
266
402
  }
268
404
  int2store(buff,sql_errno);
269
405
  pos= buff+2;
270
406
 
271
 
  /* The first # is to make the protocol backward compatible */
 
407
  /* The first # is to make the client backward compatible */
272
408
  buff[2]= '#';
273
 
  pos= (uchar*) stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
 
409
  pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
 
410
  pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
274
411
 
275
 
  length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
276
 
                  (char*) buff);
 
412
  char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
 
413
  tmp+= strlen((char*)pos);
 
414
  tmp[0]= '\0';
 
415
  length= (uint32_t)(tmp-(char*)buff);
277
416
  err= (char*) buff;
278
417
 
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
 
 
 
418
  drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
 
419
 
 
420
  session->main_da.can_overwrite_status= false;
 
421
}
460
422
 
461
423
/**
462
424
  Send name and type of result to client.
463
425
 
464
426
  Sum fields has table name empty and field_name.
465
427
 
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:
 
428
  @param Session        Thread data object
 
429
  @param list            List of items to send to client
 
430
  @param flag            Bit mask with the following functions:
469
431
                        - 1 send number of rows
470
432
                        - 2 send default values
471
433
                        - 4 don't write eof packet
472
434
 
473
435
  @retval
474
 
    0   ok
 
436
    0    ok
475
437
  @retval
476
 
    1   Error  (Note that in this case the error is not sent to the
 
438
    1    Error  (Note that in this case the error is not sent to the
477
439
    client)
478
440
*/
479
 
bool Protocol::send_fields(List<Item> *list, uint flags)
 
441
bool ClientDrizzleProtocol::sendFields(List<Item> *list)
480
442
{
481
443
  List_iterator_fast<Item> it(*list);
482
444
  Item *item;
483
 
  uchar buff[80];
 
445
  unsigned char buff[80];
484
446
  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
447
 
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
 
  }
 
448
  unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
 
449
  (void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
494
450
 
495
451
  while ((item=it++))
496
452
  {
497
453
    char *pos;
498
 
    const CHARSET_INFO * const cs= system_charset_info;
499
 
    Send_field field;
 
454
    SendField field;
500
455
    item->make_field(&field);
501
456
 
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))
 
457
    packet.length(0);
 
458
 
 
459
    if (store(STRING_WITH_LEN("def")) ||
 
460
        store(field.db_name) ||
 
461
        store(field.table_name) ||
 
462
        store(field.org_table_name) ||
 
463
        store(field.col_name) ||
 
464
        store(field.org_col_name) ||
 
465
        packet.realloc(packet.length()+12))
517
466
      goto err;
518
467
 
519
468
    /* 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)
 
469
    pos= (char*) packet.ptr()+packet.length();
 
470
    *pos++= 12;                // Length of packed fields
 
471
    /* No conversion */
 
472
    int2store(pos, field.charsetnr);
 
473
    int4store(pos+2, field.length);
 
474
 
 
475
    if (using_mysql41_protocol)
523
476
    {
524
 
      /* No conversion */
525
 
      int2store(pos, field.charsetnr);
526
 
      int4store(pos+2, field.length);
 
477
      /* Switch to MySQL field numbering. */
 
478
      switch (field.type)
 
479
      {
 
480
      case DRIZZLE_TYPE_LONG:
 
481
        pos[6]= 3;
 
482
        break;
 
483
 
 
484
      case DRIZZLE_TYPE_DOUBLE:
 
485
        pos[6]= 5;
 
486
        break;
 
487
 
 
488
      case DRIZZLE_TYPE_NULL:
 
489
        pos[6]= 6;
 
490
        break;
 
491
 
 
492
      case DRIZZLE_TYPE_TIMESTAMP:
 
493
        pos[6]= 7;
 
494
        break;
 
495
 
 
496
      case DRIZZLE_TYPE_LONGLONG:
 
497
        pos[6]= 8;
 
498
        break;
 
499
 
 
500
      case DRIZZLE_TYPE_DATETIME:
 
501
        pos[6]= 12;
 
502
        break;
 
503
 
 
504
      case DRIZZLE_TYPE_DATE:
 
505
        pos[6]= 14;
 
506
        break;
 
507
 
 
508
      case DRIZZLE_TYPE_VARCHAR:
 
509
        pos[6]= 15;
 
510
        break;
 
511
 
 
512
      case DRIZZLE_TYPE_DECIMAL:
 
513
        pos[6]= (char)246;
 
514
        break;
 
515
 
 
516
      case DRIZZLE_TYPE_ENUM:
 
517
        pos[6]= (char)247;
 
518
        break;
 
519
 
 
520
      case DRIZZLE_TYPE_BLOB:
 
521
        pos[6]= (char)252;
 
522
        break;
 
523
      }
527
524
    }
528
525
    else
529
526
    {
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);
 
527
      /* Add one to compensate for tinyint removal from enum. */
 
528
      pos[6]= field.type + 1;
545
529
    }
546
 
    pos[6]= field.type;
 
530
 
547
531
    int2store(pos+7,field.flags);
548
532
    pos[9]= (char) field.decimals;
549
 
    pos[10]= 0;                         // For the future
550
 
    pos[11]= 0;                         // For the future
 
533
    pos[10]= 0;                // For the future
 
534
    pos[11]= 0;                // For the future
551
535
    pos+= 12;
552
536
 
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 */
 
537
    packet.length((uint32_t) (pos - packet.ptr()));
 
538
    if (flush())
 
539
      break;
558
540
  }
559
541
 
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));
 
542
  /*
 
543
    Mark the end of meta-data result set, and store session->server_status,
 
544
    to show that there is no cursor.
 
545
    Send no warning information, as it will be sent at statement end.
 
546
  */
 
547
  writeEOFPacket(session->server_status, session->total_warn_count);
 
548
  return 0;
570
549
 
571
550
err:
572
551
  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()
 
552
             MYF(0));
 
553
  return 1;
 
554
}
 
555
 
 
556
bool ClientDrizzleProtocol::store(Field *from)
 
557
{
 
558
  if (from->is_null())
 
559
    return store();
 
560
  char buff[MAX_FIELD_WIDTH];
 
561
  String str(buff,sizeof(buff), &my_charset_bin);
 
562
 
 
563
  from->val_str(&str);
 
564
 
 
565
  return netStoreData((const unsigned char *)str.ptr(), str.length());
 
566
}
 
567
 
 
568
bool ClientDrizzleProtocol::store(void)
646
569
{
647
570
  char buff[1];
648
571
  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)
 
572
  return packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
 
573
}
 
574
 
 
575
bool ClientDrizzleProtocol::store(int32_t from)
 
576
{
 
577
  char buff[12];
 
578
  return netStoreData((unsigned char*) buff,
 
579
                      (size_t) (internal::int10_to_str(from, buff, -10) - buff));
 
580
}
 
581
 
 
582
bool ClientDrizzleProtocol::store(uint32_t from)
 
583
{
 
584
  char buff[11];
 
585
  return netStoreData((unsigned char*) buff,
 
586
                      (size_t) (internal::int10_to_str(from, buff, 10) - buff));
 
587
}
 
588
 
 
589
bool ClientDrizzleProtocol::store(int64_t from)
718
590
{
719
591
  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
 
 
 
592
  return netStoreData((unsigned char*) buff,
 
593
                      (size_t) (internal::int64_t10_to_str(from, buff, -10) - buff));
 
594
}
 
595
 
 
596
bool ClientDrizzleProtocol::store(uint64_t from)
 
597
{
 
598
  char buff[21];
 
599
  return netStoreData((unsigned char*) buff,
 
600
                      (size_t) (internal::int64_t10_to_str(from, buff, 10) - buff));
 
601
}
 
602
 
 
603
bool ClientDrizzleProtocol::store(double from, uint32_t decimals, String *buffer)
 
604
{
 
605
  buffer->set_real(from, decimals, session->charset());
 
606
  return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
 
607
}
 
608
 
 
609
bool ClientDrizzleProtocol::store(const char *from, size_t length)
 
610
{
 
611
  return netStoreData((const unsigned char *)from, length);
 
612
}
 
613
 
 
614
bool ClientDrizzleProtocol::wasAborted(void)
 
615
{
 
616
  return net.error && net.vio != 0;
 
617
}
 
618
 
 
619
bool ClientDrizzleProtocol::haveMoreData(void)
 
620
{
 
621
  return drizzleclient_net_more_data(&net);
 
622
}
 
623
 
 
624
bool ClientDrizzleProtocol::haveError(void)
 
625
{
 
626
  return net.error || net.vio == 0;
 
627
}
 
628
 
 
629
bool ClientDrizzleProtocol::checkConnection(void)
 
630
{
 
631
  uint32_t pkt_len= 0;
 
632
  char *end;
 
633
 
 
634
  // TCP/IP connection
 
635
  {
 
636
    char ip[NI_MAXHOST];
 
637
    uint16_t peer_port;
 
638
 
 
639
    if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
 
640
    {
 
641
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
642
      return false;
 
643
    }
 
644
 
 
645
    session->security_ctx.ip.assign(ip);
 
646
  }
 
647
  drizzleclient_net_keepalive(&net, true);
 
648
 
 
649
  uint32_t server_capabilites;
 
650
  {
 
651
    /* buff[] needs to big enough to hold the server_version variable */
 
652
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
 
653
 
 
654
    server_capabilites= CLIENT_BASIC_FLAGS;
 
655
 
 
656
    if (using_mysql41_protocol)
 
657
      server_capabilites|= CLIENT_PROTOCOL_MYSQL41;
 
658
 
 
659
#ifdef HAVE_COMPRESS
 
660
    server_capabilites|= CLIENT_COMPRESS;
 
661
#endif /* HAVE_COMPRESS */
 
662
 
 
663
    end= buff + strlen(VERSION);
 
664
    if ((end - buff) >= SERVER_VERSION_LENGTH)
 
665
      end= buff + (SERVER_VERSION_LENGTH - 1);
 
666
    memcpy(buff, VERSION, end - buff);
 
667
    *end= 0;
 
668
    end++;
 
669
 
 
670
    int4store((unsigned char*) end, global_thread_id);
 
671
    end+= 4;
 
672
 
 
673
    /* We don't use scramble anymore. */
 
674
    memset(end, 'X', SCRAMBLE_LENGTH_323);
 
675
    end+= SCRAMBLE_LENGTH_323;
 
676
    *end++= 0; /* an empty byte for some reason */
 
677
 
 
678
    int2store(end, server_capabilites);
 
679
    /* write server characteristics: up to 16 bytes allowed */
 
680
    end[2]=(char) default_charset_info->number;
 
681
    int2store(end+3, session->server_status);
 
682
    memset(end+5, 0, 13);
 
683
    end+= 18;
 
684
 
 
685
    /* Write scramble tail. */
 
686
    memset(end, 'X', SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
 
687
    end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
 
688
    *end++= 0; /* an empty byte for some reason */
 
689
 
 
690
    /* At this point we write connection message and read reply */
 
691
    if (drizzleclient_net_write_command(&net
 
692
          , (unsigned char) PROTOCOL_VERSION
 
693
          , (unsigned char*) ""
 
694
          , 0
 
695
          , (unsigned char*) buff
 
696
          , (size_t) (end-buff)) 
 
697
        ||    (pkt_len= drizzleclient_net_read(&net)) == packet_error 
 
698
        || pkt_len < MIN_HANDSHAKE_SIZE)
 
699
    {
 
700
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
701
      return false;
 
702
    }
 
703
  }
 
704
  if (packet.alloc(buffer_length))
 
705
    return false; /* The error is set by alloc(). */
 
706
 
 
707
  client_capabilities= uint2korr(net.read_pos);
 
708
 
 
709
 
 
710
  client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
 
711
  session->max_client_packet_length= uint4korr(net.read_pos + 4);
 
712
  end= (char*) net.read_pos + 32;
 
713
 
 
714
  /*
 
715
    Disable those bits which are not supported by the server.
 
716
    This is a precautionary measure, if the client lies. See Bug#27944.
 
717
  */
 
718
  client_capabilities&= server_capabilites;
 
719
 
 
720
  if (end >= (char*) net.read_pos + pkt_len + 2)
 
721
  {
 
722
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
723
    return false;
 
724
  }
 
725
 
 
726
  net.return_status= &session->server_status;
 
727
 
 
728
  char *user= end;
 
729
  char *passwd= strchr(user, '\0')+1;
 
730
  uint32_t user_len= passwd - user - 1;
 
731
  char *l_db= passwd;
 
732
 
 
733
  /*
 
734
    Old clients send null-terminated string as password; new clients send
 
735
    the size (1 byte) + string (not null-terminated). Hence in case of empty
 
736
    password both send '\0'.
 
737
 
 
738
    This strlen() can't be easily deleted without changing client.
 
739
 
 
740
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
 
741
    *passwd > 127 and become 2**32-127+ after casting to uint.
 
742
  */
 
743
  uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
 
744
    (unsigned char)(*passwd++) : strlen(passwd);
 
745
  l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
 
746
 
 
747
  /* strlen() can't be easily deleted without changing client */
 
748
  uint32_t db_len= l_db ? strlen(l_db) : 0;
 
749
 
 
750
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
 
751
  {
 
752
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
753
    return false;
 
754
  }
 
755
 
 
756
  /* If username starts and ends in "'", chop them off */
 
757
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
 
758
  {
 
759
    user[user_len-1]= 0;
 
760
    user++;
 
761
    user_len-= 2;
 
762
  }
 
763
 
 
764
  session->security_ctx.user.assign(user);
 
765
 
 
766
  return session->checkUser(passwd, passwd_len, l_db);
 
767
}
 
768
 
 
769
bool ClientDrizzleProtocol::netStoreData(const unsigned char *from, size_t length)
 
770
{
 
771
  size_t packet_length= packet.length();
 
772
  /*
 
773
     The +9 comes from that strings of length longer than 16M require
 
774
     9 bytes to be stored (see drizzleclient_net_store_length).
 
775
  */
 
776
  if (packet_length+9+length > packet.alloced_length() &&
 
777
      packet.realloc(packet_length+9+length))
 
778
    return 1;
 
779
  unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet.ptr()+packet_length, length);
 
780
  memcpy(to,from,length);
 
781
  packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
 
782
  return 0;
 
783
}
 
784
 
 
785
/**
 
786
  Format EOF packet according to the current client and
 
787
  write it to the network output buffer.
 
788
*/
 
789
 
 
790
void ClientDrizzleProtocol::writeEOFPacket(uint32_t server_status,
 
791
                                         uint32_t total_warn_count)
 
792
{
 
793
  unsigned char buff[5];
 
794
  /*
 
795
    Don't send warn count during SP execution, as the warn_list
 
796
    is cleared between substatements, and mysqltest gets confused
 
797
  */
 
798
  uint32_t tmp= min(total_warn_count, (uint32_t)65535);
 
799
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
 
800
  int2store(buff+1, tmp);
 
801
  /*
 
802
    The following test should never be true, but it's better to do it
 
803
    because if 'is_fatal_error' is set the server is not going to execute
 
804
    other queries (see the if test in dispatch_command / COM_QUERY)
 
805
  */
 
806
  if (session->is_fatal_error)
 
807
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
808
  int2store(buff + 3, server_status);
 
809
  drizzleclient_net_write(&net, buff, 5);
 
810
}
 
811
 
 
812
static ListenDrizzleProtocol *listen_obj= NULL;
 
813
 
 
814
static int init(plugin::Registry &registry)
 
815
{
 
816
  listen_obj= new ListenDrizzleProtocol("drizzle_protocol", false);
 
817
  registry.add(listen_obj); 
 
818
  return 0;
 
819
}
 
820
 
 
821
static int deinit(plugin::Registry &registry)
 
822
{
 
823
  registry.remove(listen_obj);
 
824
  delete listen_obj;
 
825
  return 0;
 
826
}
 
827
 
 
828
static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
 
829
                           N_("Port number to use for connection or 0 for "
 
830
                              "default to, in order of "
 
831
                              "preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
 
832
                              "built-in default (4427)."),
 
833
                           NULL, NULL, 0, 0, 65535, 0);
 
834
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
 
835
                           PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
 
836
                           NULL, NULL, 10, 1, 300, 0);
 
837
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
 
838
                           N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
 
839
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
 
840
                           N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
 
841
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
 
842
                           N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
 
843
static DRIZZLE_SYSVAR_UINT(buffer_length, buffer_length, PLUGIN_VAR_RQCMDARG,
 
844
                           N_("Buffer length."), NULL, NULL, 16384, 1024,
 
845
                           1024*1024, 0);
 
846
static DRIZZLE_SYSVAR_STR(bind_address, bind_address, PLUGIN_VAR_READONLY,
 
847
                          N_("Address to bind to."), NULL, NULL, NULL);
 
848
 
 
849
static drizzle_sys_var* sys_variables[]= {
 
850
  DRIZZLE_SYSVAR(port),
 
851
  DRIZZLE_SYSVAR(connect_timeout),
 
852
  DRIZZLE_SYSVAR(read_timeout),
 
853
  DRIZZLE_SYSVAR(write_timeout),
 
854
  DRIZZLE_SYSVAR(retry_count),
 
855
  DRIZZLE_SYSVAR(buffer_length),
 
856
  DRIZZLE_SYSVAR(bind_address),
 
857
  NULL
 
858
};
 
859
 
 
860
DRIZZLE_DECLARE_PLUGIN
 
861
{
 
862
  DRIZZLE_VERSION_ID,
 
863
  "drizzle_protocol",
 
864
  "0.1",
 
865
  "Eric Day",
 
866
  "Drizzle Protocol Module",
 
867
  PLUGIN_LICENSE_GPL,
 
868
  init,             /* Plugin Init */
 
869
  deinit,           /* Plugin Deinit */
 
870
  NULL,             /* status variables */
 
871
  sys_variables,    /* system variables */
 
872
  NULL              /* config options */
 
873
}
 
874
DRIZZLE_DECLARE_PLUGIN_END;