~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/protocol.cc

Removed reference to aio.h - we don't reference its use anywhere.

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>
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;
 
1
/* Copyright (C) 2000-2003 MySQL AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation; version 2 of the License.
 
6
 
 
7
   This program is distributed in the hope that it will be useful,
 
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
10
   GNU General Public License for more details.
 
11
 
 
12
   You should have received a copy of the GNU General Public License
 
13
   along with this program; if not, write to the Free Software
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
/**
 
17
  @file
 
18
 
 
19
  Low level functions for storing data to be send to the MySQL client.
 
20
  The actual communction is handled by the net_xxx functions in net_serv.cc
 
21
*/
 
22
 
 
23
#ifdef USE_PRAGMA_IMPLEMENTATION
 
24
#pragma implementation                          // gcc: Class implementation
 
25
#endif
 
26
 
 
27
#include "mysql_priv.h"
 
28
#include <stdarg.h>
 
29
 
49
30
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;
 
31
/* Declared non-static only because of the embedded library. */
 
32
void net_send_error_packet(THD *thd, uint sql_errno, const char *err);
 
33
void net_send_ok(THD *, uint, uint, ha_rows, ulonglong, const char *);
 
34
void net_send_eof(THD *thd, uint server_status, uint total_warn_count);
 
35
static void write_eof_packet(THD *thd, NET *net,
 
36
                             uint server_status, uint total_warn_count);
 
37
 
 
38
bool Protocol::net_store_data(const uchar *from, size_t length)
 
39
{
 
40
  ulong packet_length=packet->length();
 
41
  /* 
 
42
     The +9 comes from that strings of length longer than 16M require
 
43
     9 bytes to be stored (see net_store_length).
 
44
  */
 
45
  if (packet_length+9+length > packet->alloced_length() &&
 
46
      packet->realloc(packet_length+9+length))
 
47
    return 1;
 
48
  uchar *to= net_store_length((uchar*) packet->ptr()+packet_length, length);
 
49
  memcpy(to,from,length);
 
50
  packet->length((uint) (to+length-(uchar*) packet->ptr()));
 
51
  return 0;
 
52
}
 
53
 
 
54
 
 
55
 
 
56
 
 
57
/*
 
58
  net_store_data() - extended version with character set conversion.
 
59
  
 
60
  It is optimized for short strings whose length after
 
61
  conversion is garanteed to be less than 251, which accupies
 
62
  exactly one byte to store length. It allows not to use
 
63
  the "convert" member as a temporary buffer, conversion
 
64
  is done directly to the "packet" member.
 
65
  The limit 251 is good enough to optimize send_fields()
 
66
  because column, table, database names fit into this limit.
 
67
*/
 
68
 
 
69
bool Protocol::net_store_data(const uchar *from, size_t length,
 
70
                              CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
 
71
{
 
72
  uint dummy_errors;
 
73
  /* Calculate maxumum possible result length */
 
74
  uint conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
 
75
  if (conv_length > 250)
 
76
  {
 
77
    /*
 
78
      For strings with conv_length greater than 250 bytes
 
79
      we don't know how many bytes we will need to store length: one or two,
 
80
      because we don't know result length until conversion is done.
 
81
      For example, when converting from utf8 (mbmaxlen=3) to latin1,
 
82
      conv_length=300 means that the result length can vary between 100 to 300.
 
83
      length=100 needs one byte, length=300 needs to bytes.
 
84
      
 
85
      Thus conversion directly to "packet" is not worthy.
 
86
      Let's use "convert" as a temporary buffer.
 
87
    */
 
88
    return (convert->copy((const char*) from, length, from_cs,
 
89
                          to_cs, &dummy_errors) ||
 
90
            net_store_data((const uchar*) convert->ptr(), convert->length()));
 
91
  }
 
92
 
 
93
  ulong packet_length= packet->length();
 
94
  ulong new_length= packet_length + conv_length + 1;
 
95
 
 
96
  if (new_length > packet->alloced_length() && packet->realloc(new_length))
 
97
    return 1;
 
98
 
 
99
  char *length_pos= (char*) packet->ptr() + packet_length;
 
100
  char *to= length_pos + 1;
 
101
 
 
102
  to+= copy_and_convert(to, conv_length, to_cs,
 
103
                        (const char*) from, length, from_cs, &dummy_errors);
 
104
 
 
105
  net_store_length((uchar*) length_pos, to - length_pos - 1);
 
106
  packet->length((uint) (to - packet->ptr()));
 
107
  return 0;
 
108
}
 
109
 
 
110
 
 
111
/**
 
112
  Send a error string to client.
 
113
 
 
114
  Design note:
 
115
  net_printf_error and net_send_error are low-level functions
 
116
  that shall be used only when a new connection is being
 
117
  established or at server startup.
 
118
 
 
119
  For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
 
120
  critical that every error that can be intercepted is issued in one
 
121
  place only, my_message_sql.
 
122
*/
 
123
void net_send_error(THD *thd, uint sql_errno, const char *err)
 
124
{
 
125
  DBUG_ENTER("net_send_error");
 
126
 
 
127
  DBUG_ASSERT(sql_errno);
 
128
  DBUG_ASSERT(err && err[0]);
 
129
 
 
130
  DBUG_PRINT("enter",("sql_errno: %d  err: %s", sql_errno, err));
 
131
 
 
132
  /*
 
133
    It's one case when we can push an error even though there
 
134
    is an OK or EOF already.
 
135
  */
 
136
  thd->main_da.can_overwrite_status= TRUE;
 
137
 
 
138
  /* Abort multi-result sets */
 
139
  thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
140
 
 
141
  net_send_error_packet(thd, sql_errno, err);
 
142
 
 
143
  thd->main_da.can_overwrite_status= FALSE;
 
144
 
 
145
  DBUG_VOID_RETURN;
285
146
}
286
147
 
287
148
/**
290
151
  The ok packet has the following structure:
291
152
 
292
153
  - 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
 
154
  - affected_rows       : Stored in 1-9 bytes
 
155
  - id          : Stored in 1-9 bytes
 
156
  - server_status       : Copy of thd->server_status;  Can be used by client
296
157
  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.
 
158
  New in 4.0 protocol
 
159
  - warning_count       : Stored in 2 bytes; New in 4.1 protocol
 
160
  - message             : Stored as packed length (1-9 bytes) + message.
300
161
  Is not stored if no message.
301
162
 
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)
 
163
  @param thd               Thread handler
 
164
  @param affected_rows     Number of rows changed by statement
 
165
  @param id                Auto_increment id for first row (if used)
 
166
  @param message           Message to send to the client (Used by mysql_status)
306
167
*/
307
168
 
308
 
void ClientDrizzleProtocol::sendOK()
 
169
void
 
170
net_send_ok(THD *thd,
 
171
            uint server_status, uint total_warn_count,
 
172
            ha_rows affected_rows, ulonglong id, const char *message)
309
173
{
310
 
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
311
 
  const char *message= NULL;
312
 
  uint32_t tmp;
313
 
 
314
 
  if (!net.vio)    // hack for re-parsing queries
315
 
  {
316
 
    return;
317
 
  }
318
 
 
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
 
  }
340
 
 
341
 
  /* We can only return up to 65535 warnings in two bytes */
342
 
  int2store(pos, tmp);
343
 
  pos+= 2;
344
 
 
345
 
  session->main_da.can_overwrite_status= true;
 
174
  NET *net= &thd->net;
 
175
  uchar buff[MYSQL_ERRMSG_SIZE+10],*pos;
 
176
  DBUG_ENTER("my_ok");
 
177
 
 
178
  if (! net->vio)       // hack for re-parsing queries
 
179
  {
 
180
    DBUG_PRINT("info", ("vio present: NO"));
 
181
    DBUG_VOID_RETURN;
 
182
  }
 
183
 
 
184
  buff[0]=0;                                    // No fields
 
185
  pos=net_store_length(buff+1,affected_rows);
 
186
  pos=net_store_length(pos, id);
 
187
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
188
  {
 
189
    DBUG_PRINT("info",
 
190
               ("affected_rows: %lu  id: %lu  status: %u  warning_count: %u",
 
191
                (ulong) affected_rows,          
 
192
                (ulong) id,
 
193
                (uint) (server_status & 0xffff),
 
194
                (uint) total_warn_count));
 
195
    int2store(pos, server_status);
 
196
    pos+=2;
 
197
 
 
198
    /* We can only return up to 65535 warnings in two bytes */
 
199
    uint tmp= min(total_warn_count, 65535);
 
200
    int2store(pos, tmp);
 
201
    pos+= 2;
 
202
  }
 
203
  else if (net->return_status)                  // For 4.0 protocol
 
204
  {
 
205
    int2store(pos, server_status);
 
206
    pos+=2;
 
207
  }
 
208
  thd->main_da.can_overwrite_status= TRUE;
346
209
 
347
210
  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);
356
 
 
357
 
  session->main_da.can_overwrite_status= false;
 
211
    pos= net_store_data(pos, (uchar*) message, strlen(message));
 
212
  VOID(my_net_write(net, buff, (size_t) (pos-buff)));
 
213
  VOID(net_flush(net));
 
214
 
 
215
  thd->main_da.can_overwrite_status= FALSE;
 
216
  DBUG_PRINT("info", ("OK sent, so no more error sending allowed"));
 
217
 
 
218
  DBUG_VOID_RETURN;
358
219
}
359
220
 
 
221
static uchar eof_buff[1]= { (uchar) 254 };      /* Marker for end of fields */
 
222
 
360
223
/**
361
224
  Send eof (= end of result set) to the client.
362
225
 
363
226
  The eof packet has the following structure:
364
227
 
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;
 
228
  - 254         : Marker (1 byte)
 
229
  - warning_count       : Stored in 2 bytes; New in 4.1 protocol
 
230
  - status_flag : Stored in 2 bytes;
368
231
  For flags like SERVER_MORE_RESULTS_EXISTS.
369
232
 
370
233
  Note that the warning count will not be sent if 'no_flush' is set as
371
234
  we don't want to report the warning count until all data is sent to the
372
235
  client.
373
 
*/
374
 
 
375
 
void ClientDrizzleProtocol::sendEOF()
376
 
{
377
 
  /* Set to true if no active vio, to work well in case of --init-file */
378
 
  if (net.vio != 0)
379
 
  {
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;
385
 
  }
386
 
  packet.shrink(buffer_length);
387
 
}
388
 
 
389
 
 
390
 
void ClientDrizzleProtocol::sendError(uint32_t sql_errno, const char *err)
391
 
{
392
 
  uint32_t length;
393
 
  /*
394
 
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
395
 
  */
396
 
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
397
 
 
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)
419
 
  {
420
 
    return;
 
236
 
 
237
  @param thd            Thread handler
 
238
  @param no_flush       Set to 1 if there will be more data to the client,
 
239
                    like in send_fields().
 
240
*/    
 
241
 
 
242
void
 
243
net_send_eof(THD *thd, uint server_status, uint total_warn_count)
 
244
{
 
245
  NET *net= &thd->net;
 
246
  DBUG_ENTER("net_send_eof");
 
247
  /* Set to TRUE if no active vio, to work well in case of --init-file */
 
248
  if (net->vio != 0)
 
249
  {
 
250
    thd->main_da.can_overwrite_status= TRUE;
 
251
    write_eof_packet(thd, net, server_status, total_warn_count);
 
252
    VOID(net_flush(net));
 
253
    thd->main_da.can_overwrite_status= FALSE;
 
254
    DBUG_PRINT("info", ("EOF sent, so no more error sending allowed"));
 
255
  }
 
256
  DBUG_VOID_RETURN;
 
257
}
 
258
 
 
259
 
 
260
/**
 
261
  Format EOF packet according to the current protocol and
 
262
  write it to the network output buffer.
 
263
*/
 
264
 
 
265
static void write_eof_packet(THD *thd, NET *net,
 
266
                             uint server_status,
 
267
                             uint total_warn_count)
 
268
{
 
269
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
270
  {
 
271
    uchar buff[5];
 
272
    /*
 
273
      Don't send warn count during SP execution, as the warn_list
 
274
      is cleared between substatements, and mysqltest gets confused
 
275
    */
 
276
    uint tmp= min(total_warn_count, 65535);
 
277
    buff[0]= 254;
 
278
    int2store(buff+1, tmp);
 
279
    /*
 
280
      The following test should never be true, but it's better to do it
 
281
      because if 'is_fatal_error' is set the server is not going to execute
 
282
      other queries (see the if test in dispatch_command / COM_QUERY)
 
283
    */
 
284
    if (thd->is_fatal_error)
 
285
      server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
286
    int2store(buff + 3, server_status);
 
287
    VOID(my_net_write(net, buff, 5));
 
288
  }
 
289
  else
 
290
    VOID(my_net_write(net, eof_buff, 1));
 
291
}
 
292
 
 
293
/**
 
294
  Please client to send scrambled_password in old format.
 
295
     
 
296
  @param thd thread handle
 
297
 
 
298
  @retval
 
299
    0  ok
 
300
  @retval
 
301
   !0  error
 
302
*/
 
303
 
 
304
bool send_old_password_request(THD *thd)
 
305
{
 
306
  NET *net= &thd->net;
 
307
  return my_net_write(net, eof_buff, 1) || net_flush(net);
 
308
}
 
309
 
 
310
 
 
311
void net_send_error_packet(THD *thd, uint sql_errno, const char *err)
 
312
{
 
313
  NET *net= &thd->net;
 
314
  uint length;
 
315
  /*
 
316
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + MYSQL_ERRMSG_SIZE:512
 
317
  */
 
318
  uchar buff[2+1+SQLSTATE_LENGTH+MYSQL_ERRMSG_SIZE], *pos;
 
319
 
 
320
  DBUG_ENTER("send_error_packet");
 
321
 
 
322
  if (net->vio == 0)
 
323
  {
 
324
    if (thd->bootstrap)
 
325
    {
 
326
      /* In bootstrap it's ok to print on stderr */
 
327
      fprintf(stderr,"ERROR: %d  %s\n",sql_errno,err);
 
328
    }
 
329
    DBUG_VOID_RETURN;
421
330
  }
422
331
 
423
332
  int2store(buff,sql_errno);
424
333
  pos= buff+2;
425
 
 
426
 
  /* The first # is to make the client backward compatible */
427
 
  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));
430
 
 
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);
 
334
  if (thd->client_capabilities & CLIENT_PROTOCOL_41)
 
335
  {
 
336
    /* The first # is to make the protocol backward compatible */
 
337
    buff[2]= '#';
 
338
    pos= (uchar*) strmov((char*) buff+3, mysql_errno_to_sqlstate(sql_errno));
 
339
  }
 
340
  length= (uint) (strmake((char*) pos, err, MYSQL_ERRMSG_SIZE-1) -
 
341
                  (char*) buff);
435
342
  err= (char*) buff;
436
343
 
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
 
}
 
344
  VOID(net_write_command(net,(uchar) 255, (uchar*) "", 0, (uchar*) err,
 
345
                         length));
 
346
  DBUG_VOID_RETURN;
 
347
}
 
348
 
 
349
 
 
350
/**
 
351
  Faster net_store_length when we know that length is less than 65536.
 
352
  We keep a separate version for that range because it's widely used in
 
353
  libmysql.
 
354
 
 
355
  uint is used as agrument type because of MySQL type conventions:
 
356
  - uint for 0..65536
 
357
  - ulong for 0..4294967296
 
358
  - ulonglong for bigger numbers.
 
359
*/
 
360
 
 
361
static uchar *net_store_length_fast(uchar *packet, uint length)
 
362
{
 
363
  if (length < 251)
 
364
  {
 
365
    *packet=(uchar) length;
 
366
    return packet+1;
 
367
  }
 
368
  *packet++=252;
 
369
  int2store(packet,(uint) length);
 
370
  return packet+2;
 
371
}
 
372
 
 
373
/**
 
374
  Send the status of the current statement execution over network.
 
375
 
 
376
  @param  thd   in fact, carries two parameters, NET for the transport and
 
377
                Diagnostics_area as the source of status information.
 
378
 
 
379
  In MySQL, there are two types of SQL statements: those that return
 
380
  a result set and those that return status information only.
 
381
 
 
382
  If a statement returns a result set, it consists of 3 parts:
 
383
  - result set meta-data
 
384
  - variable number of result set rows (can be 0)
 
385
  - followed and terminated by EOF or ERROR packet
 
386
 
 
387
  Once the  client has seen the meta-data information, it always
 
388
  expects an EOF or ERROR to terminate the result set. If ERROR is
 
389
  received, the result set rows are normally discarded (this is up
 
390
  to the client implementation, libmysql at least does discard them).
 
391
  EOF, on the contrary, means "successfully evaluated the entire
 
392
  result set". Since we don't know how many rows belong to a result
 
393
  set until it's evaluated, EOF/ERROR is the indicator of the end
 
394
  of the row stream. Note, that we can not buffer result set rows
 
395
  on the server -- there may be an arbitrary number of rows. But
 
396
  we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
 
397
  delay sending it till the very end of execution (here), to be able to
 
398
  change EOF to an ERROR if commit failed or some other error occurred
 
399
  during the last cleanup steps taken after execution.
 
400
 
 
401
  A statement that does not return a result set doesn't send result
 
402
  set meta-data either. Instead it returns one of:
 
403
  - OK packet
 
404
  - ERROR packet.
 
405
  Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
 
406
  packet is "buffered" in the diagnostics area and sent to the client
 
407
  in the end of statement.
 
408
 
 
409
  @pre  The diagnostics area is assigned or disabled. It can not be empty
 
410
        -- we assume that every SQL statement or COM_* command
 
411
        generates OK, ERROR, or EOF status.
 
412
 
 
413
  @post The status information is encoded to protocol format and sent to the
 
414
        client.
 
415
 
 
416
  @return We conventionally return void, since the only type of error
 
417
          that can happen here is a NET (transport) error, and that one
 
418
          will become visible when we attempt to read from the NET the
 
419
          next command.
 
420
          Diagnostics_area::is_sent is set for debugging purposes only.
 
421
*/
 
422
 
 
423
void net_end_statement(THD *thd)
 
424
{
 
425
  DBUG_ASSERT(! thd->main_da.is_sent);
 
426
 
 
427
  /* Can not be true, but do not take chances in production. */
 
428
  if (thd->main_da.is_sent)
 
429
    return;
 
430
 
 
431
  switch (thd->main_da.status()) {
 
432
  case Diagnostics_area::DA_ERROR:
 
433
    /* The query failed, send error to log and abort bootstrap. */
 
434
    net_send_error(thd,
 
435
                   thd->main_da.sql_errno(),
 
436
                   thd->main_da.message());
 
437
    break;
 
438
  case Diagnostics_area::DA_EOF:
 
439
    net_send_eof(thd,
 
440
                 thd->main_da.server_status(),
 
441
                 thd->main_da.total_warn_count());
 
442
    break;
 
443
  case Diagnostics_area::DA_OK:
 
444
    net_send_ok(thd,
 
445
                thd->main_da.server_status(),
 
446
                thd->main_da.total_warn_count(),
 
447
                thd->main_da.affected_rows(),
 
448
                thd->main_da.last_insert_id(),
 
449
                thd->main_da.message());
 
450
    break;
 
451
  case Diagnostics_area::DA_DISABLED:
 
452
    break;
 
453
  case Diagnostics_area::DA_EMPTY:
 
454
  default:
 
455
    DBUG_ASSERT(0);
 
456
    net_send_ok(thd, thd->server_status, thd->total_warn_count,
 
457
                0, 0, NULL);
 
458
    break;
 
459
  }
 
460
  thd->main_da.is_sent= TRUE;
 
461
}
 
462
 
 
463
 
 
464
/****************************************************************************
 
465
  Functions used by the protocol functions (like net_send_ok) to store
 
466
  strings and numbers in the header result packet.
 
467
****************************************************************************/
 
468
 
 
469
/* The following will only be used for short strings < 65K */
 
470
 
 
471
uchar *net_store_data(uchar *to, const uchar *from, size_t length)
 
472
{
 
473
  to=net_store_length_fast(to,length);
 
474
  memcpy(to,from,length);
 
475
  return to+length;
 
476
}
 
477
 
 
478
uchar *net_store_data(uchar *to,int32 from)
 
479
{
 
480
  char buff[20];
 
481
  uint length=(uint) (int10_to_str(from,buff,10)-buff);
 
482
  to=net_store_length_fast(to,length);
 
483
  memcpy(to,buff,length);
 
484
  return to+length;
 
485
}
 
486
 
 
487
uchar *net_store_data(uchar *to,longlong from)
 
488
{
 
489
  char buff[22];
 
490
  uint length=(uint) (longlong10_to_str(from,buff,10)-buff);
 
491
  to=net_store_length_fast(to,length);
 
492
  memcpy(to,buff,length);
 
493
  return to+length;
 
494
}
 
495
 
 
496
 
 
497
/*****************************************************************************
 
498
  Default Protocol functions
 
499
*****************************************************************************/
 
500
 
 
501
void Protocol::init(THD *thd_arg)
 
502
{
 
503
  thd=thd_arg;
 
504
  packet= &thd->packet;
 
505
  convert= &thd->convert_buffer;
 
506
#ifndef DBUG_OFF
 
507
  field_types= 0;
 
508
#endif
 
509
}
 
510
 
 
511
/**
 
512
  Finish the result set with EOF packet, as is expected by the client,
 
513
  if there is an error evaluating the next row and a continue handler
 
514
  for the error.
 
515
*/
 
516
 
 
517
void Protocol::end_partial_result_set(THD *thd)
 
518
{
 
519
  net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
 
520
}
 
521
 
 
522
 
 
523
bool Protocol::flush()
 
524
{
 
525
  return net_flush(&thd->net);
 
526
}
 
527
 
441
528
 
442
529
/**
443
530
  Send name and type of result to client.
444
531
 
445
532
  Sum fields has table name empty and field_name.
446
533
 
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:
 
534
  @param THD            Thread data object
 
535
  @param list           List of items to send to client
 
536
  @param flag           Bit mask with the following functions:
450
537
                        - 1 send number of rows
451
538
                        - 2 send default values
452
539
                        - 4 don't write eof packet
453
540
 
454
541
  @retval
455
 
    0    ok
 
542
    0   ok
456
543
  @retval
457
 
    1    Error  (Note that in this case the error is not sent to the
 
544
    1   Error  (Note that in this case the error is not sent to the
458
545
    client)
459
546
*/
460
 
bool ClientDrizzleProtocol::sendFields(List<Item> *list)
 
547
bool Protocol::send_fields(List<Item> *list, uint flags)
461
548
{
462
549
  List_iterator_fast<Item> it(*list);
463
550
  Item *item;
464
 
  unsigned char buff[80];
 
551
  uchar buff[80];
465
552
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
466
 
 
467
 
  unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
468
 
  (void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
 
553
  Protocol_text prot(thd);
 
554
  String *local_packet= prot.storage_packet();
 
555
  CHARSET_INFO *thd_charset= thd->variables.character_set_results;
 
556
  DBUG_ENTER("send_fields");
 
557
 
 
558
  if (flags & SEND_NUM_ROWS)
 
559
  {                             // Packet with number of elements
 
560
    uchar *pos= net_store_length(buff, list->elements);
 
561
    (void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
 
562
  }
 
563
 
 
564
#ifndef DBUG_OFF
 
565
  field_types= (enum_field_types*) thd->alloc(sizeof(field_types) *
 
566
                                              list->elements);
 
567
  uint count= 0;
 
568
#endif
469
569
 
470
570
  while ((item=it++))
471
571
  {
472
572
    char *pos;
473
 
    SendField field;
 
573
    CHARSET_INFO *cs= system_charset_info;
 
574
    Send_field field;
474
575
    item->make_field(&field);
475
576
 
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))
485
 
      goto err;
486
 
 
487
 
    /* 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)
 
577
    /* Keep things compatible for old clients */
 
578
    if (field.type == MYSQL_TYPE_VARCHAR)
 
579
      field.type= MYSQL_TYPE_VAR_STRING;
 
580
 
 
581
    prot.prepare_for_resend();
 
582
 
 
583
    if (thd->client_capabilities & CLIENT_PROTOCOL_41)
495
584
    {
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
 
      }
 
585
      if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
 
586
          prot.store(field.db_name, (uint) strlen(field.db_name),
 
587
                     cs, thd_charset) ||
 
588
          prot.store(field.table_name, (uint) strlen(field.table_name),
 
589
                     cs, thd_charset) ||
 
590
          prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
 
591
                     cs, thd_charset) ||
 
592
          prot.store(field.col_name, (uint) strlen(field.col_name),
 
593
                     cs, thd_charset) ||
 
594
          prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
 
595
                     cs, thd_charset) ||
 
596
          local_packet->realloc(local_packet->length()+12))
 
597
        goto err;
 
598
      /* Store fixed length fields */
 
599
      pos= (char*) local_packet->ptr()+local_packet->length();
 
600
      *pos++= 12;                               // Length of packed fields
 
601
      if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
 
602
      {
 
603
        /* No conversion */
 
604
        int2store(pos, field.charsetnr);
 
605
        int4store(pos+2, field.length);
 
606
      }
 
607
      else
 
608
      {
 
609
        /* With conversion */
 
610
        uint max_char_len;
 
611
        int2store(pos, thd_charset->number);
 
612
        /*
 
613
          For TEXT/BLOB columns, field_length describes the maximum data
 
614
          length in bytes. There is no limit to the number of characters
 
615
          that a TEXT column can store, as long as the data fits into
 
616
          the designated space.
 
617
          For the rest of textual columns, field_length is evaluated as
 
618
          char_count * mbmaxlen, where character count is taken from the
 
619
          definition of the column. In other words, the maximum number
 
620
          of characters here is limited by the column definition.
 
621
        */
 
622
        max_char_len= (field.type >= (int) MYSQL_TYPE_TINY_BLOB &&
 
623
                      field.type <= (int) MYSQL_TYPE_BLOB) ?
 
624
                      field.length / item->collation.collation->mbminlen :
 
625
                      field.length / item->collation.collation->mbmaxlen;
 
626
        int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
 
627
      }
 
628
      pos[6]= field.type;
 
629
      int2store(pos+7,field.flags);
 
630
      pos[9]= (char) field.decimals;
 
631
      pos[10]= 0;                               // For the future
 
632
      pos[11]= 0;                               // For the future
 
633
      pos+= 12;
543
634
    }
544
635
    else
545
636
    {
546
 
      /* Add one to compensate for tinyint removal from enum. */
547
 
      pos[6]= field.type + 1;
 
637
      if (prot.store(field.table_name, (uint) strlen(field.table_name),
 
638
                     cs, thd_charset) ||
 
639
          prot.store(field.col_name, (uint) strlen(field.col_name),
 
640
                     cs, thd_charset) ||
 
641
          local_packet->realloc(local_packet->length()+10))
 
642
        goto err;
 
643
      pos= (char*) local_packet->ptr()+local_packet->length();
 
644
 
 
645
#ifdef TO_BE_DELETED_IN_6
 
646
      if (!(thd->client_capabilities & CLIENT_LONG_FLAG))
 
647
      {
 
648
        pos[0]=3;
 
649
        int3store(pos+1,field.length);
 
650
        pos[4]=1;
 
651
        pos[5]=field.type;
 
652
        pos[6]=2;
 
653
        pos[7]= (char) field.flags;
 
654
        pos[8]= (char) field.decimals;
 
655
        pos+= 9;
 
656
      }
 
657
      else
 
658
#endif
 
659
      {
 
660
        pos[0]=3;
 
661
        int3store(pos+1,field.length);
 
662
        pos[4]=1;
 
663
        pos[5]=field.type;
 
664
        pos[6]=3;
 
665
        int2store(pos+7,field.flags);
 
666
        pos[9]= (char) field.decimals;
 
667
        pos+= 10;
 
668
      }
548
669
    }
549
 
 
550
 
    int2store(pos+7,field.flags);
551
 
    pos[9]= (char) field.decimals;
552
 
    pos[10]= 0;                // For the future
553
 
    pos[11]= 0;                // For the future
554
 
    pos+= 12;
555
 
 
556
 
    packet.length((uint32_t) (pos - packet.ptr()));
557
 
    if (flush())
558
 
      break;
559
 
  }
560
 
 
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;
 
670
    local_packet->length((uint) (pos - local_packet->ptr()));
 
671
    if (flags & SEND_DEFAULTS)
 
672
      item->send(&prot, &tmp);                  // Send default value
 
673
    if (prot.write())
 
674
      break;                                    /* purecov: inspected */
 
675
#ifndef DBUG_OFF
 
676
    field_types[count++]= field.type;
 
677
#endif
 
678
  }
 
679
 
 
680
  if (flags & SEND_EOF)
 
681
  {
 
682
    /*
 
683
      Mark the end of meta-data result set, and store thd->server_status,
 
684
      to show that there is no cursor.
 
685
      Send no warning information, as it will be sent at statement end.
 
686
    */
 
687
    write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
 
688
  }
 
689
  DBUG_RETURN(prepare_for_send(list));
568
690
 
569
691
err:
570
692
  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();
 
693
             MYF(0));   /* purecov: inspected */
 
694
  DBUG_RETURN(1);                               /* purecov: inspected */
 
695
}
 
696
 
 
697
 
 
698
bool Protocol::write()
 
699
{
 
700
  DBUG_ENTER("Protocol::write");
 
701
  DBUG_RETURN(my_net_write(&thd->net, (uchar*) packet->ptr(),
 
702
                           packet->length()));
 
703
}
 
704
 
 
705
 
 
706
/**
 
707
  Send \\0 end terminated string.
 
708
 
 
709
  @param from   NullS or \\0 terminated string
 
710
 
 
711
  @note
 
712
    In most cases one should use store(from, length) instead of this function
 
713
 
 
714
  @retval
 
715
    0           ok
 
716
  @retval
 
717
    1           error
 
718
*/
 
719
 
 
720
bool Protocol::store(const char *from, CHARSET_INFO *cs)
 
721
{
 
722
  if (!from)
 
723
    return store_null();
 
724
  uint length= strlen(from);
 
725
  return store(from, length, cs);
 
726
}
 
727
 
 
728
 
 
729
/**
 
730
  Send a set of strings as one long string with ',' in between.
 
731
*/
 
732
 
 
733
bool Protocol::store(I_List<i_string>* str_list)
 
734
{
 
735
  char buf[256];
 
736
  String tmp(buf, sizeof(buf), &my_charset_bin);
 
737
  uint32 len;
 
738
  I_List_iterator<i_string> it(*str_list);
 
739
  i_string* s;
 
740
 
 
741
  tmp.length(0);
 
742
  while ((s=it++))
 
743
  {
 
744
    tmp.append(s->ptr);
 
745
    tmp.append(',');
 
746
  }
 
747
  if ((len= tmp.length()))
 
748
    len--;                                      // Remove last ','
 
749
  return store((char*) tmp.ptr(), len,  tmp.charset());
 
750
}
 
751
 
 
752
 
 
753
/****************************************************************************
 
754
  Functions to handle the simple (default) protocol where everything is
 
755
  This protocol is the one that is used by default between the MySQL server
 
756
  and client when you are not using prepared statements.
 
757
 
 
758
  All data are sent as 'packed-string-length' followed by 'string-data'
 
759
****************************************************************************/
 
760
 
 
761
void Protocol_text::prepare_for_resend()
 
762
{
 
763
  packet->length(0);
 
764
#ifndef DBUG_OFF
 
765
  field_pos= 0;
 
766
#endif
 
767
}
 
768
 
 
769
bool Protocol_text::store_null()
 
770
{
 
771
#ifndef DBUG_OFF
 
772
  field_pos++;
 
773
#endif
 
774
  char buff[1];
 
775
  buff[0]= (char)251;
 
776
  return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
 
777
}
 
778
 
 
779
 
 
780
/**
 
781
  Auxilary function to convert string to the given character set
 
782
  and store in network buffer.
 
783
*/
 
784
 
 
785
bool Protocol::store_string_aux(const char *from, size_t length,
 
786
                                CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
 
787
{
 
788
  /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
 
789
  if (tocs && !my_charset_same(fromcs, tocs) &&
 
790
      fromcs != &my_charset_bin &&
 
791
      tocs != &my_charset_bin)
 
792
  {
 
793
    /* Store with conversion */
 
794
    return net_store_data((uchar*) from, length, fromcs, tocs);
 
795
  }
 
796
  /* Store without conversion */
 
797
  return net_store_data((uchar*) from, length);
 
798
}
 
799
 
 
800
 
 
801
bool Protocol_text::store(const char *from, size_t length,
 
802
                          CHARSET_INFO *fromcs, CHARSET_INFO *tocs)
 
803
{
 
804
#ifndef DBUG_OFF
 
805
  DBUG_ASSERT(field_types == 0 ||
 
806
              field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
 
807
              (field_types[field_pos] >= MYSQL_TYPE_ENUM && field_types[field_pos] <= MYSQL_TYPE_STRING));
 
808
  field_pos++;
 
809
#endif
 
810
  return store_string_aux(from, length, fromcs, tocs);
 
811
}
 
812
 
 
813
 
 
814
bool Protocol_text::store(const char *from, size_t length,
 
815
                          CHARSET_INFO *fromcs)
 
816
{
 
817
  CHARSET_INFO *tocs= this->thd->variables.character_set_results;
 
818
#ifndef DBUG_OFF
 
819
  DBUG_ASSERT(field_types == 0 ||
 
820
              field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL ||
 
821
              field_types[field_pos] == MYSQL_TYPE_NEWDATE ||
 
822
              (field_types[field_pos] >= MYSQL_TYPE_ENUM && field_types[field_pos] <= MYSQL_TYPE_STRING));
 
823
  field_pos++;
 
824
#endif
 
825
  return store_string_aux(from, length, fromcs, tocs);
 
826
}
 
827
 
 
828
 
 
829
bool Protocol_text::store_tiny(longlong from)
 
830
{
 
831
#ifndef DBUG_OFF
 
832
  DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_TINY);
 
833
  field_pos++;
 
834
#endif
 
835
  char buff[20];
 
836
  return net_store_data((uchar*) buff,
 
837
                        (size_t) (int10_to_str((int) from, buff, -10) - buff));
 
838
}
 
839
 
 
840
 
 
841
bool Protocol_text::store_short(longlong from)
 
842
{
 
843
#ifndef DBUG_OFF
 
844
  DBUG_ASSERT(field_types == 0 ||
 
845
              field_types[field_pos] == MYSQL_TYPE_YEAR ||
 
846
              field_types[field_pos] == MYSQL_TYPE_SHORT);
 
847
  field_pos++;
 
848
#endif
 
849
  char buff[20];
 
850
  return net_store_data((uchar*) buff,
 
851
                        (size_t) (int10_to_str((int) from, buff, -10) -
 
852
                                  buff));
 
853
}
 
854
 
 
855
 
 
856
bool Protocol_text::store_long(longlong from)
 
857
{
 
858
#ifndef DBUG_OFF
 
859
  DBUG_ASSERT(field_types == 0 ||
 
860
              field_types[field_pos] == MYSQL_TYPE_LONG);
 
861
  field_pos++;
 
862
#endif
 
863
  char buff[20];
 
864
  return net_store_data((uchar*) buff,
 
865
                        (size_t) (int10_to_str((long int)from, buff,
 
866
                                               (from <0)?-10:10)-buff));
 
867
}
 
868
 
 
869
 
 
870
bool Protocol_text::store_longlong(longlong from, bool unsigned_flag)
 
871
{
 
872
#ifndef DBUG_OFF
 
873
  DBUG_ASSERT(field_types == 0 ||
 
874
              field_types[field_pos] == MYSQL_TYPE_LONGLONG);
 
875
  field_pos++;
 
876
#endif
 
877
  char buff[22];
 
878
  return net_store_data((uchar*) buff,
 
879
                        (size_t) (longlong10_to_str(from,buff,
 
880
                                                    unsigned_flag ? 10 : -10)-
 
881
                                  buff));
 
882
}
 
883
 
 
884
 
 
885
bool Protocol_text::store_decimal(const my_decimal *d)
 
886
{
 
887
#ifndef DBUG_OFF
 
888
  DBUG_ASSERT(field_types == 0 ||
 
889
              field_types[field_pos] == MYSQL_TYPE_NEWDECIMAL);
 
890
  field_pos++;
 
891
#endif
 
892
  char buff[DECIMAL_MAX_STR_LENGTH];
 
893
  String str(buff, sizeof(buff), &my_charset_bin);
 
894
  (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
 
895
  return net_store_data((uchar*) str.ptr(), str.length());
 
896
}
 
897
 
 
898
 
 
899
bool Protocol_text::store(float from, uint32 decimals, String *buffer)
 
900
{
 
901
#ifndef DBUG_OFF
 
902
  DBUG_ASSERT(field_types == 0 ||
 
903
              field_types[field_pos] == MYSQL_TYPE_FLOAT);
 
904
  field_pos++;
 
905
#endif
 
906
  buffer->set_real((double) from, decimals, thd->charset());
 
907
  return net_store_data((uchar*) buffer->ptr(), buffer->length());
 
908
}
 
909
 
 
910
 
 
911
bool Protocol_text::store(double from, uint32 decimals, String *buffer)
 
912
{
 
913
#ifndef DBUG_OFF
 
914
  DBUG_ASSERT(field_types == 0 ||
 
915
              field_types[field_pos] == MYSQL_TYPE_DOUBLE);
 
916
  field_pos++;
 
917
#endif
 
918
  buffer->set_real(from, decimals, thd->charset());
 
919
  return net_store_data((uchar*) buffer->ptr(), buffer->length());
 
920
}
 
921
 
 
922
 
 
923
bool Protocol_text::store(Field *field)
 
924
{
 
925
  if (field->is_null())
 
926
    return store_null();
 
927
#ifndef DBUG_OFF
 
928
  field_pos++;
 
929
#endif
579
930
  char buff[MAX_FIELD_WIDTH];
580
931
  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);
 
932
  CHARSET_INFO *tocs= this->thd->variables.character_set_results;
 
933
#ifndef DBUG_OFF
 
934
  TABLE *table= field->table;
 
935
  my_bitmap_map *old_map= 0;
 
936
  if (table->file)
 
937
    old_map= dbug_tmp_use_all_columns(table, table->read_set);
 
938
#endif
 
939
 
 
940
  field->val_str(&str);
 
941
#ifndef DBUG_OFF
 
942
  if (old_map)
 
943
    dbug_tmp_restore_column_map(table->read_set, old_map);
 
944
#endif
 
945
 
 
946
  return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
 
947
}
 
948
 
 
949
 
 
950
/**
 
951
  @todo
 
952
    Second_part format ("%06") needs to change when 
 
953
    we support 0-6 decimals for time.
 
954
*/
 
955
 
 
956
bool Protocol_text::store(MYSQL_TIME *tm)
 
957
{
 
958
#ifndef DBUG_OFF
 
959
  DBUG_ASSERT(field_types == 0 ||
 
960
              field_types[field_pos] == MYSQL_TYPE_DATETIME ||
 
961
              field_types[field_pos] == MYSQL_TYPE_TIMESTAMP);
 
962
  field_pos++;
 
963
#endif
 
964
  char buff[40];
 
965
  uint length;
 
966
  length= my_sprintf(buff,(buff, "%04d-%02d-%02d %02d:%02d:%02d",
 
967
                           (int) tm->year,
 
968
                           (int) tm->month,
 
969
                           (int) tm->day,
 
970
                           (int) tm->hour,
 
971
                           (int) tm->minute,
 
972
                           (int) tm->second));
 
973
  if (tm->second_part)
 
974
    length+= my_sprintf(buff+length,(buff+length, ".%06d",
 
975
                                     (int)tm->second_part));
 
976
  return net_store_data((uchar*) buff, length);
 
977
}
 
978
 
 
979
 
 
980
bool Protocol_text::store_date(MYSQL_TIME *tm)
 
981
{
 
982
#ifndef DBUG_OFF
 
983
  DBUG_ASSERT(field_types == 0 ||
 
984
              field_types[field_pos] == MYSQL_TYPE_DATE);
 
985
  field_pos++;
 
986
#endif
 
987
  char buff[MAX_DATE_STRING_REP_LENGTH];
 
988
  size_t length= my_date_to_str(tm, buff);
 
989
  return net_store_data((uchar*) buff, length);
 
990
}
 
991
 
 
992
 
 
993
/**
 
994
  @todo 
 
995
    Second_part format ("%06") needs to change when 
 
996
    we support 0-6 decimals for time.
 
997
*/
 
998
 
 
999
bool Protocol_text::store_time(MYSQL_TIME *tm)
 
1000
{
 
1001
#ifndef DBUG_OFF
 
1002
  DBUG_ASSERT(field_types == 0 ||
 
1003
              field_types[field_pos] == MYSQL_TYPE_TIME);
 
1004
  field_pos++;
 
1005
#endif
 
1006
  char buff[40];
 
1007
  uint length;
 
1008
  uint day= (tm->year || tm->month) ? 0 : tm->day;
 
1009
  length= my_sprintf(buff,(buff, "%s%02ld:%02d:%02d",
 
1010
                           tm->neg ? "-" : "",
 
1011
                           (long) day*24L+(long) tm->hour,
 
1012
                           (int) tm->minute,
 
1013
                           (int) tm->second));
 
1014
  if (tm->second_part)
 
1015
    length+= my_sprintf(buff+length,(buff+length, ".%06d", (int)tm->second_part));
 
1016
  return net_store_data((uchar*) buff, length);
 
1017
}
 
1018