~drizzle-trunk/drizzle/development

971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
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
1241.9.12 by Monty Taylor
Trims more out of server_includes.h.
20
#include "config.h"
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
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>
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
26
#include "drizzled/internal/m_string.h"
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
27
#include <algorithm>
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
28
#include <boost/program_options.hpp>
29
#include <drizzled/module/option_map.h>
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
30
#include "errmsg.h"
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
31
#include "mysql_protocol.h"
1337.4.2 by Eric Day
Added MYSQL_PASSWORD() UDF.
32
#include "mysql_password.h"
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
33
#include "options.h"
1726.3.4 by LinuxJedi
Add a data_dictionary table for the MySQL protocol plugin
34
#include "table_function.h"
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
35
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
36
namespace po= boost::program_options;
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
37
using namespace std;
38
using namespace drizzled;
39
40
#define PROTOCOL_VERSION 10
41
42
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
43
static uint32_t port;
44
static uint32_t connect_timeout;
45
static uint32_t read_timeout;
46
static uint32_t write_timeout;
47
static uint32_t retry_count;
48
static uint32_t buffer_length;
49
static char* bind_address;
1337.4.5 by Eric Day
Added MySQL password hash support.
50
static uint32_t random_seed1;
51
static uint32_t random_seed2;
52
static const uint32_t random_max= 0x3FFFFFFF;
53
static const double random_max_double= (double)0x3FFFFFFF;
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
54
1726.3.6 by LinuxJedi
Add data_dictionary table for drizzle protocol status
55
static plugin::TableFunction* mysql_status_table_function_ptr= NULL;
1726.3.4 by LinuxJedi
Add a data_dictionary table for the MySQL protocol plugin
56
1666.4.19 by Monty Taylor
Free strdup'd option strings.
57
ListenMySQLProtocol::~ListenMySQLProtocol()
58
{
59
  /* This is strdup'd from the options */
60
  free(bind_address);
61
}
62
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
63
const char* ListenMySQLProtocol::getHost(void) const
64
{
65
  return bind_address;
66
}
67
68
in_port_t ListenMySQLProtocol::getPort(void) const
69
{
70
  return (in_port_t) port;
71
}
72
73
plugin::Client *ListenMySQLProtocol::getClient(int fd)
74
{
75
  int new_fd;
76
  new_fd= acceptTcp(fd);
77
  if (new_fd == -1)
78
    return NULL;
79
80
  return new (nothrow) ClientMySQLProtocol(new_fd, using_mysql41_protocol);
81
}
82
1726.3.4 by LinuxJedi
Add a data_dictionary table for the MySQL protocol plugin
83
drizzled::atomic<uint64_t> ClientMySQLProtocol::connectionCount;
84
drizzled::atomic<uint64_t> ClientMySQLProtocol::failedConnections;
85
drizzled::atomic<uint64_t> ClientMySQLProtocol::connected;
86
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
87
ClientMySQLProtocol::ClientMySQLProtocol(int fd, bool using_mysql41_protocol_arg):
88
  using_mysql41_protocol(using_mysql41_protocol_arg)
89
{
90
  net.vio= 0;
91
92
  if (fd == -1)
93
    return;
94
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
95
  if (drizzleclient_net_init_sock(&net, fd, buffer_length))
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
96
    throw bad_alloc();
97
98
  drizzleclient_net_set_read_timeout(&net, read_timeout);
99
  drizzleclient_net_set_write_timeout(&net, write_timeout);
100
  net.retry_count=retry_count;
101
}
102
103
ClientMySQLProtocol::~ClientMySQLProtocol()
104
{
105
  if (net.vio)
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
106
    vio_close(net.vio);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
107
}
108
109
int ClientMySQLProtocol::getFileDescriptor(void)
110
{
111
  return drizzleclient_net_get_sd(&net);
112
}
113
114
bool ClientMySQLProtocol::isConnected()
115
{
116
  return net.vio != 0;
117
}
118
119
bool ClientMySQLProtocol::isReading(void)
120
{
121
  return net.reading_or_writing == 1;
122
}
123
124
bool ClientMySQLProtocol::isWriting(void)
125
{
126
  return net.reading_or_writing == 2;
127
}
128
129
bool ClientMySQLProtocol::flush()
130
{
131
  if (net.vio == NULL)
132
    return false;
133
  bool ret= drizzleclient_net_write(&net, (unsigned char*) packet.ptr(),
134
                           packet.length());
135
  packet.length(0);
136
  return ret;
137
}
138
139
void ClientMySQLProtocol::close(void)
140
{
141
  if (net.vio)
142
  { 
143
    drizzleclient_net_close(&net);
144
    drizzleclient_net_end(&net);
1726.3.4 by LinuxJedi
Add a data_dictionary table for the MySQL protocol plugin
145
    connected.decrement();
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
146
  }
147
}
148
149
bool ClientMySQLProtocol::authenticate()
150
{
151
  bool connection_is_valid;
152
1726.3.4 by LinuxJedi
Add a data_dictionary table for the MySQL protocol plugin
153
  connectionCount.increment();
154
  connected.increment();
155
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
156
  /* Use "connect_timeout" value during connection phase */
157
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
158
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
159
160
  connection_is_valid= checkConnection();
161
162
  if (connection_is_valid)
163
    sendOK();
164
  else
165
  {
166
    sendError(session->main_da.sql_errno(), session->main_da.message());
1726.3.4 by LinuxJedi
Add a data_dictionary table for the MySQL protocol plugin
167
    failedConnections.increment();
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
168
    return false;
169
  }
170
  /* Connect completed, set read/write timeouts back to default */
171
  drizzleclient_net_set_read_timeout(&net, read_timeout);
172
  drizzleclient_net_set_write_timeout(&net, write_timeout);
173
  return true;
174
}
175
176
bool ClientMySQLProtocol::readCommand(char **l_packet, uint32_t *packet_length)
177
{
178
  /*
179
    This thread will do a blocking read from the client which
180
    will be interrupted when the next command is received from
181
    the client, the connection is closed or "net_wait_timeout"
182
    number of seconds has passed
183
  */
184
#ifdef NEVER
185
  /* We can do this much more efficiently with poll timeouts or watcher thread,
186
     disabling for now, which means net_wait_timeout == read_timeout. */
187
  drizzleclient_net_set_read_timeout(&net,
188
                                     session->variables.net_wait_timeout);
189
#endif
190
191
  net.pkt_nr=0;
192
193
  *packet_length= drizzleclient_net_read(&net);
194
  if (*packet_length == packet_error)
195
  {
196
    /* Check if we can continue without closing the connection */
197
1302.4.8 by Eric Day
Added prototest test case for mysql_protocol.
198
    if(net.last_errno== ER_NET_PACKET_TOO_LARGE)
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
199
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
200
    if (session->main_da.status() == Diagnostics_area::DA_ERROR)
201
      sendError(session->main_da.sql_errno(), session->main_da.message());
202
    else
203
      sendOK();
204
205
    if (net.error != 3)
206
      return false;                       // We have to close it.
207
208
    net.error= 0;
209
    *packet_length= 0;
210
    return true;
211
  }
212
213
  *l_packet= (char*) net.read_pos;
214
215
  /*
216
    'packet_length' contains length of data, as it was stored in packet
217
    header. In case of malformed header, drizzleclient_net_read returns zero.
218
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
219
    number of bytes was actually read from network.
220
    There is also an extra safety measure in drizzleclient_net_read:
221
    it sets packet[packet_length]= 0, but only for non-zero packets.
222
  */
223
224
  if (*packet_length == 0)                       /* safety */
225
  {
226
    /* Initialize with COM_SLEEP packet */
227
    (*l_packet)[0]= (unsigned char) COM_SLEEP;
228
    *packet_length= 1;
229
  }
230
  else if (using_mysql41_protocol)
231
  {
232
    /* Map from MySQL commands to Drizzle commands. */
233
    switch ((int)(*l_packet)[0])
234
    {
235
    case 0: /* SLEEP */
236
    case 1: /* QUIT */
237
    case 2: /* INIT_DB */
238
    case 3: /* QUERY */
239
      break;
240
241
    case 8: /* SHUTDOWN */
242
      (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
243
      break;
244
245
    case 14: /* PING */
971.8.5 by Eric Day
Added test cases for --mysql flag.
246
      (*l_packet)[0]= (unsigned char) COM_PING;
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
247
      break;
248
249
250
    default:
1302.4.8 by Eric Day
Added prototest test case for mysql_protocol.
251
      /* Respond with unknown command for MySQL commands we don't support. */
252
      (*l_packet)[0]= (unsigned char) COM_END;
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
253
      *packet_length= 1;
254
      break;
255
    }
256
  }
257
258
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
259
  (*l_packet)[*packet_length]= '\0';                  /* safety */
260
261
#ifdef NEVER
262
  /* See comment above. */
263
  /* Restore read timeout value */
264
  drizzleclient_net_set_read_timeout(&net,
265
                                     session->variables.net_read_timeout);
266
#endif
267
268
  return true;
269
}
270
271
/**
272
  Return ok to the client.
273
274
  The ok packet has the following structure:
275
276
  - 0               : Marker (1 byte)
277
  - affected_rows    : Stored in 1-9 bytes
278
  - id        : Stored in 1-9 bytes
279
  - server_status    : Copy of session->server_status;  Can be used by client
280
  to check if we are inside an transaction.
281
  New in 4.0 client
282
  - warning_count    : Stored in 2 bytes; New in 4.1 client
283
  - message        : Stored as packed length (1-9 bytes) + message.
284
  Is not stored if no message.
285
286
  @param session           Thread handler
287
  @param affected_rows       Number of rows changed by statement
288
  @param id           Auto_increment id for first row (if used)
289
  @param message       Message to send to the client (Used by mysql_status)
290
*/
291
292
void ClientMySQLProtocol::sendOK()
293
{
294
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
295
  const char *message= NULL;
296
  uint32_t tmp;
297
298
  if (!net.vio)    // hack for re-parsing queries
299
  {
300
    return;
301
  }
302
303
  buff[0]=0;                    // No fields
304
  if (session->main_da.status() == Diagnostics_area::DA_OK)
305
  {
306
    if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da.found_rows())
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
307
      pos=storeLength(buff+1,session->main_da.found_rows());
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
308
    else
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
309
      pos=storeLength(buff+1,session->main_da.affected_rows());
310
    pos=storeLength(pos, session->main_da.last_insert_id());
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
311
    int2store(pos, session->main_da.server_status());
312
    pos+=2;
313
    tmp= min(session->main_da.total_warn_count(), (uint32_t)65535);
314
    message= session->main_da.message();
315
  }
316
  else
317
  {
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
318
    pos=storeLength(buff+1,0);
319
    pos=storeLength(pos, 0);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
320
    int2store(pos, session->server_status);
321
    pos+=2;
322
    tmp= min(session->total_warn_count, (uint32_t)65535);
323
  }
324
325
  /* We can only return up to 65535 warnings in two bytes */
326
  int2store(pos, tmp);
327
  pos+= 2;
328
329
  session->main_da.can_overwrite_status= true;
330
331
  if (message && message[0])
332
  {
333
    size_t length= strlen(message);
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
334
    pos=storeLength(pos,length);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
335
    memcpy(pos,(unsigned char*) message,length);
336
    pos+=length;
337
  }
338
  drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
339
  drizzleclient_net_flush(&net);
340
341
  session->main_da.can_overwrite_status= false;
342
}
343
344
/**
345
  Send eof (= end of result set) to the client.
346
347
  The eof packet has the following structure:
348
349
  - 254    (DRIZZLE_PROTOCOL_NO_MORE_DATA)    : Marker (1 byte)
350
  - warning_count    : Stored in 2 bytes; New in 4.1 client
351
  - status_flag    : Stored in 2 bytes;
352
  For flags like SERVER_MORE_RESULTS_EXISTS.
353
354
  Note that the warning count will not be sent if 'no_flush' is set as
355
  we don't want to report the warning count until all data is sent to the
356
  client.
357
*/
358
359
void ClientMySQLProtocol::sendEOF()
360
{
361
  /* Set to true if no active vio, to work well in case of --init-file */
362
  if (net.vio != 0)
363
  {
364
    session->main_da.can_overwrite_status= true;
365
    writeEOFPacket(session->main_da.server_status(),
366
                   session->main_da.total_warn_count());
367
    drizzleclient_net_flush(&net);
368
    session->main_da.can_overwrite_status= false;
369
  }
370
  packet.shrink(buffer_length);
371
}
372
373
374
void ClientMySQLProtocol::sendError(uint32_t sql_errno, const char *err)
375
{
376
  uint32_t length;
377
  /*
378
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
379
  */
380
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
381
382
  assert(sql_errno);
383
  assert(err && err[0]);
384
385
  /*
386
    It's one case when we can push an error even though there
387
    is an OK or EOF already.
388
  */
389
  session->main_da.can_overwrite_status= true;
390
391
  /* Abort multi-result sets */
392
  session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
393
394
  /**
395
    Send a error string to client.
396
397
    For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
398
    critical that every error that can be intercepted is issued in one
399
    place only, my_message_sql.
400
  */
401
402
  if (net.vio == 0)
403
  {
404
    return;
405
  }
406
407
  int2store(buff,sql_errno);
408
  pos= buff+2;
409
410
  /* The first # is to make the client backward compatible */
411
  buff[2]= '#';
412
  pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
413
  pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
414
415
  char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
416
  tmp+= strlen((char*)pos);
417
  tmp[0]= '\0';
418
  length= (uint32_t)(tmp-(char*)buff);
419
  err= (char*) buff;
420
421
  drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
422
423
  session->main_da.can_overwrite_status= false;
424
}
425
426
/**
427
  Send name and type of result to client.
428
429
  Sum fields has table name empty and field_name.
430
431
  @param Session        Thread data object
432
  @param list            List of items to send to client
433
  @param flag            Bit mask with the following functions:
434
                        - 1 send number of rows
435
                        - 2 send default values
436
                        - 4 don't write eof packet
437
438
  @retval
439
    0    ok
440
  @retval
441
    1    Error  (Note that in this case the error is not sent to the
442
    client)
443
*/
444
bool ClientMySQLProtocol::sendFields(List<Item> *list)
445
{
446
  List_iterator_fast<Item> it(*list);
447
  Item *item;
448
  unsigned char buff[80];
449
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
450
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
451
  unsigned char *row_pos= storeLength(buff, list->elements);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
452
  (void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
453
454
  while ((item=it++))
455
  {
456
    char *pos;
457
    SendField field;
458
    item->make_field(&field);
459
460
    packet.length(0);
461
462
    if (store(STRING_WITH_LEN("def")) ||
463
        store(field.db_name) ||
464
        store(field.table_name) ||
465
        store(field.org_table_name) ||
466
        store(field.col_name) ||
467
        store(field.org_col_name) ||
468
        packet.realloc(packet.length()+12))
469
      goto err;
470
471
    /* Store fixed length fields */
472
    pos= (char*) packet.ptr()+packet.length();
473
    *pos++= 12;                // Length of packed fields
474
    /* No conversion */
475
    int2store(pos, field.charsetnr);
476
    int4store(pos+2, field.length);
477
478
    if (using_mysql41_protocol)
479
    {
480
      /* Switch to MySQL field numbering. */
481
      switch (field.type)
482
      {
483
      case DRIZZLE_TYPE_LONG:
484
        pos[6]= 3;
485
        break;
486
487
      case DRIZZLE_TYPE_DOUBLE:
488
        pos[6]= 5;
489
        break;
490
491
      case DRIZZLE_TYPE_NULL:
492
        pos[6]= 6;
493
        break;
494
495
      case DRIZZLE_TYPE_TIMESTAMP:
496
        pos[6]= 7;
497
        break;
498
499
      case DRIZZLE_TYPE_LONGLONG:
500
        pos[6]= 8;
501
        break;
502
503
      case DRIZZLE_TYPE_DATETIME:
504
        pos[6]= 12;
505
        break;
506
507
      case DRIZZLE_TYPE_DATE:
508
        pos[6]= 14;
509
        break;
510
511
      case DRIZZLE_TYPE_VARCHAR:
512
        pos[6]= 15;
513
        break;
514
1218 by Brian Aker
Merge Eric
515
      case DRIZZLE_TYPE_DECIMAL:
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
516
        pos[6]= (char)246;
517
        break;
518
519
      case DRIZZLE_TYPE_ENUM:
520
        pos[6]= (char)247;
521
        break;
522
523
      case DRIZZLE_TYPE_BLOB:
524
        pos[6]= (char)252;
525
        break;
526
      }
527
    }
528
    else
529
    {
530
      /* Add one to compensate for tinyint removal from enum. */
531
      pos[6]= field.type + 1;
532
    }
533
534
    int2store(pos+7,field.flags);
535
    pos[9]= (char) field.decimals;
536
    pos[10]= 0;                // For the future
537
    pos[11]= 0;                // For the future
538
    pos+= 12;
539
540
    packet.length((uint32_t) (pos - packet.ptr()));
541
    if (flush())
542
      break;
543
  }
544
545
  /*
546
    Mark the end of meta-data result set, and store session->server_status,
547
    to show that there is no cursor.
548
    Send no warning information, as it will be sent at statement end.
549
  */
550
  writeEOFPacket(session->server_status, session->total_warn_count);
551
  return 0;
552
553
err:
554
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
555
             MYF(0));
556
  return 1;
557
}
558
559
bool ClientMySQLProtocol::store(Field *from)
560
{
561
  if (from->is_null())
562
    return store();
563
  char buff[MAX_FIELD_WIDTH];
564
  String str(buff,sizeof(buff), &my_charset_bin);
565
566
  from->val_str(&str);
567
568
  return netStoreData((const unsigned char *)str.ptr(), str.length());
569
}
570
571
bool ClientMySQLProtocol::store(void)
572
{
573
  char buff[1];
574
  buff[0]= (char)251;
575
  return packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
576
}
577
578
bool ClientMySQLProtocol::store(int32_t from)
579
{
580
  char buff[12];
581
  return netStoreData((unsigned char*) buff,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
582
                      (size_t) (internal::int10_to_str(from, buff, -10) - buff));
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
583
}
584
585
bool ClientMySQLProtocol::store(uint32_t from)
586
{
587
  char buff[11];
588
  return netStoreData((unsigned char*) buff,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
589
                      (size_t) (internal::int10_to_str(from, buff, 10) - buff));
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
590
}
591
592
bool ClientMySQLProtocol::store(int64_t from)
593
{
594
  char buff[22];
595
  return netStoreData((unsigned char*) buff,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
596
                      (size_t) (internal::int64_t10_to_str(from, buff, -10) - buff));
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
597
}
598
599
bool ClientMySQLProtocol::store(uint64_t from)
600
{
601
  char buff[21];
602
  return netStoreData((unsigned char*) buff,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
603
                      (size_t) (internal::int64_t10_to_str(from, buff, 10) - buff));
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
604
}
605
606
bool ClientMySQLProtocol::store(double from, uint32_t decimals, String *buffer)
607
{
608
  buffer->set_real(from, decimals, session->charset());
609
  return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
610
}
611
612
bool ClientMySQLProtocol::store(const char *from, size_t length)
613
{
614
  return netStoreData((const unsigned char *)from, length);
615
}
616
617
bool ClientMySQLProtocol::wasAborted(void)
618
{
619
  return net.error && net.vio != 0;
620
}
621
622
bool ClientMySQLProtocol::haveMoreData(void)
623
{
624
  return drizzleclient_net_more_data(&net);
625
}
626
627
bool ClientMySQLProtocol::haveError(void)
628
{
629
  return net.error || net.vio == 0;
630
}
631
632
bool ClientMySQLProtocol::checkConnection(void)
633
{
634
  uint32_t pkt_len= 0;
635
  char *end;
1337.4.5 by Eric Day
Added MySQL password hash support.
636
  char scramble[SCRAMBLE_LENGTH];
637
638
  makeScramble(scramble);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
639
640
  // TCP/IP connection
641
  {
642
    char ip[NI_MAXHOST];
643
    uint16_t peer_port;
644
645
    if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
646
    {
1273.11.5 by Dennis Schoen
add getSecurityContext()
647
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
648
      return false;
649
    }
650
1273.11.5 by Dennis Schoen
add getSecurityContext()
651
    session->getSecurityContext().setIp(ip);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
652
  }
653
  drizzleclient_net_keepalive(&net, true);
654
655
  uint32_t server_capabilites;
656
  {
657
    /* buff[] needs to big enough to hold the server_version variable */
658
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
659
660
    server_capabilites= CLIENT_BASIC_FLAGS;
661
662
    if (using_mysql41_protocol)
663
      server_capabilites|= CLIENT_PROTOCOL_MYSQL41;
664
665
#ifdef HAVE_COMPRESS
666
    server_capabilites|= CLIENT_COMPRESS;
667
#endif /* HAVE_COMPRESS */
668
1502.4.1 by Monty Taylor
Don't overwrite the pandora_vc_revinfo file if we don't have new
669
    end= buff + strlen(PANDORA_RELEASE_VERSION);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
670
    if ((end - buff) >= SERVER_VERSION_LENGTH)
671
      end= buff + (SERVER_VERSION_LENGTH - 1);
1502.4.1 by Monty Taylor
Don't overwrite the pandora_vc_revinfo file if we don't have new
672
    memcpy(buff, PANDORA_RELEASE_VERSION, end - buff);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
673
    *end= 0;
674
    end++;
675
1724.4.1 by LinuxJedi
Pass the thread ID instead of the next available thread ID to the client.
676
    int4store((unsigned char*) end, session->variables.pseudo_thread_id);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
677
    end+= 4;
678
679
    /* We don't use scramble anymore. */
1337.4.5 by Eric Day
Added MySQL password hash support.
680
    memcpy(end, scramble, SCRAMBLE_LENGTH_323);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
681
    end+= SCRAMBLE_LENGTH_323;
682
    *end++= 0; /* an empty byte for some reason */
683
684
    int2store(end, server_capabilites);
685
    /* write server characteristics: up to 16 bytes allowed */
686
    end[2]=(char) default_charset_info->number;
687
    int2store(end+3, session->server_status);
688
    memset(end+5, 0, 13);
689
    end+= 18;
690
691
    /* Write scramble tail. */
1337.4.5 by Eric Day
Added MySQL password hash support.
692
    memcpy(end, scramble + SCRAMBLE_LENGTH_323, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
693
    end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
694
    *end++= 0; /* an empty byte for some reason */
695
696
    /* At this point we write connection message and read reply */
697
    if (drizzleclient_net_write_command(&net
698
          , (unsigned char) PROTOCOL_VERSION
699
          , (unsigned char*) ""
700
          , 0
701
          , (unsigned char*) buff
702
          , (size_t) (end-buff)) 
703
        ||    (pkt_len= drizzleclient_net_read(&net)) == packet_error 
704
        || pkt_len < MIN_HANDSHAKE_SIZE)
705
    {
1273.11.5 by Dennis Schoen
add getSecurityContext()
706
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
707
      return false;
708
    }
709
  }
710
  if (packet.alloc(buffer_length))
711
    return false; /* The error is set by alloc(). */
712
713
  client_capabilities= uint2korr(net.read_pos);
1302.4.4 by Eric Day
Updates for handshake testing.
714
  if (!(client_capabilities & CLIENT_PROTOCOL_MYSQL41))
715
  {
716
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
717
    return false;
718
  }
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
719
720
  client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
721
  session->max_client_packet_length= uint4korr(net.read_pos + 4);
722
  end= (char*) net.read_pos + 32;
723
724
  /*
725
    Disable those bits which are not supported by the server.
726
    This is a precautionary measure, if the client lies. See Bug#27944.
727
  */
728
  client_capabilities&= server_capabilites;
729
730
  if (end >= (char*) net.read_pos + pkt_len + 2)
731
  {
1273.11.5 by Dennis Schoen
add getSecurityContext()
732
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
733
    return false;
734
  }
735
736
  net.return_status= &session->server_status;
737
738
  char *user= end;
739
  char *passwd= strchr(user, '\0')+1;
740
  uint32_t user_len= passwd - user - 1;
741
  char *l_db= passwd;
742
743
  /*
1302.4.17 by Eric Day
Fixed valgrind warnings exposed by prototest.
744
    Only support new password format.
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
745
746
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
747
    *passwd > 127 and become 2**32-127+ after casting to uint.
748
  */
1302.4.17 by Eric Day
Fixed valgrind warnings exposed by prototest.
749
  uint32_t passwd_len;
750
  if (client_capabilities & CLIENT_SECURE_CONNECTION &&
751
      passwd < (char *) net.read_pos + pkt_len)
1337.4.5 by Eric Day
Added MySQL password hash support.
752
  {
1302.4.17 by Eric Day
Fixed valgrind warnings exposed by prototest.
753
    passwd_len= (unsigned char)(*passwd++);
1337.4.10 by Eric Day
Merged trunk, rsolved conflicts.
754
    if (passwd_len > 0)
755
    {
756
      session->getSecurityContext().setPasswordType(SecurityContext::MYSQL_HASH);
757
      session->getSecurityContext().setPasswordContext(scramble, SCRAMBLE_LENGTH);
758
    }
1337.4.5 by Eric Day
Added MySQL password hash support.
759
  }
1302.4.17 by Eric Day
Fixed valgrind warnings exposed by prototest.
760
  else
761
    passwd_len= 0;
1337.4.5 by Eric Day
Added MySQL password hash support.
762
1302.4.17 by Eric Day
Fixed valgrind warnings exposed by prototest.
763
  if (client_capabilities & CLIENT_CONNECT_WITH_DB &&
764
      passwd < (char *) net.read_pos + pkt_len)
765
  {
766
    l_db= l_db + passwd_len + 1;
767
  }
768
  else
769
    l_db= NULL;
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
770
771
  /* strlen() can't be easily deleted without changing client */
772
  uint32_t db_len= l_db ? strlen(l_db) : 0;
773
774
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
775
  {
1273.11.5 by Dennis Schoen
add getSecurityContext()
776
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
777
    return false;
778
  }
779
780
  /* If username starts and ends in "'", chop them off */
781
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
782
  {
783
    user[user_len-1]= 0;
784
    user++;
785
    user_len-= 2;
786
  }
787
1273.11.5 by Dennis Schoen
add getSecurityContext()
788
  session->getSecurityContext().setUser(user);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
789
790
  return session->checkUser(passwd, passwd_len, l_db);
791
}
792
793
bool ClientMySQLProtocol::netStoreData(const unsigned char *from, size_t length)
794
{
795
  size_t packet_length= packet.length();
796
  /*
797
     The +9 comes from that strings of length longer than 16M require
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
798
     9 bytes to be stored (see storeLength).
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
799
  */
800
  if (packet_length+9+length > packet.alloced_length() &&
801
      packet.realloc(packet_length+9+length))
802
    return 1;
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
803
  unsigned char *to= storeLength((unsigned char*) packet.ptr()+packet_length, length);
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
804
  memcpy(to,from,length);
805
  packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
806
  return 0;
807
}
808
809
/**
810
  Format EOF packet according to the current client and
811
  write it to the network output buffer.
812
*/
813
814
void ClientMySQLProtocol::writeEOFPacket(uint32_t server_status,
815
                                         uint32_t total_warn_count)
816
{
817
  unsigned char buff[5];
818
  /*
819
    Don't send warn count during SP execution, as the warn_list
820
    is cleared between substatements, and mysqltest gets confused
821
  */
822
  uint32_t tmp= min(total_warn_count, (uint32_t)65535);
823
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
824
  int2store(buff+1, tmp);
825
  /*
826
    The following test should never be true, but it's better to do it
827
    because if 'is_fatal_error' is set the server is not going to execute
828
    other queries (see the if test in dispatch_command / COM_QUERY)
829
  */
830
  if (session->is_fatal_error)
831
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
832
  int2store(buff + 3, server_status);
833
  drizzleclient_net_write(&net, buff, 5);
834
}
835
1337.4.1 by Eric Day
Removed unused functions and extra complexity in MySQL module. Not rewriting any code here (yet?), just reshuffling to make it easier to manage.
836
/*
837
  Store an integer with simple packing into a output package
838
839
  buffer      Store the packed integer here
840
  length    integers to store
841
842
  This is mostly used to store lengths of strings.  We have to cast
843
  the result for the LL() becasue of a bug in Forte CC compiler.
844
845
  RETURN
846
  Position in 'buffer' after the packed length
847
*/
848
849
unsigned char *ClientMySQLProtocol::storeLength(unsigned char *buffer, uint64_t length)
850
{
851
  if (length < (uint64_t) 251LL)
852
  {
853
    *buffer=(unsigned char) length;
854
    return buffer+1;
855
  }
856
  /* 251 is reserved for NULL */
857
  if (length < (uint64_t) 65536LL)
858
  {
859
    *buffer++=252;
860
    int2store(buffer,(uint32_t) length);
861
    return buffer+2;
862
  }
863
  if (length < (uint64_t) 16777216LL)
864
  {
865
    *buffer++=253;
866
    int3store(buffer,(uint32_t) length);
867
    return buffer+3;
868
  }
869
  *buffer++=254;
870
  int8store(buffer,length);
871
  return buffer+8;
872
}
873
1337.4.5 by Eric Day
Added MySQL password hash support.
874
void ClientMySQLProtocol::makeScramble(char *scramble)
875
{
876
  /* This is the MySQL algorithm with minimal changes. */
877
  random_seed1= (random_seed1 * 3 + random_seed2) % random_max;
878
  random_seed2= (random_seed1 + random_seed2 + 33) % random_max;
879
  uint32_t seed= static_cast<uint32_t>((static_cast<double>(random_seed1) / random_max_double) * 0xffffffff);
880
881
  void *pointer= this;
882
  uint32_t pointer_seed;
883
  memcpy(&pointer_seed, &pointer, 4);
884
  uint32_t random1= (seed + pointer_seed) % random_max;
1724.4.1 by LinuxJedi
Pass the thread ID instead of the next available thread ID to the client.
885
  uint32_t random2= (seed + session->variables.pseudo_thread_id + net.vio->sd) % random_max;
1337.4.5 by Eric Day
Added MySQL password hash support.
886
887
  for (char *end= scramble + SCRAMBLE_LENGTH; scramble != end; scramble++)
888
  {
889
    random1= (random1 * 3 + random2) % random_max;
890
    random2= (random1 + random2 + 33) % random_max;
891
    *scramble= static_cast<char>((static_cast<double>(random1) / random_max_double) * 94 + 33);
892
  }
893
}
894
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
895
static ListenMySQLProtocol *listen_obj= NULL;
1337.4.2 by Eric Day
Added MYSQL_PASSWORD() UDF.
896
plugin::Create_function<MySQLPassword> *mysql_password= NULL;
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
897
1530.2.6 by Monty Taylor
Moved plugin::Context to module::Context.
898
static int init(drizzled::module::Context &context)
1639.2.2 by Vijay Samuel
Merge fixes for variable.test
899
{  
1726.3.6 by LinuxJedi
Add data_dictionary table for drizzle protocol status
900
  mysql_status_table_function_ptr= new MysqlProtocolStatus;
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
901
1726.3.6 by LinuxJedi
Add data_dictionary table for drizzle protocol status
902
  context.add(mysql_status_table_function_ptr);
1337.4.5 by Eric Day
Added MySQL password hash support.
903
  /* Initialize random seeds for the MySQL algorithm with minimal changes. */
904
  time_t seed_time= time(NULL);
905
  random_seed1= seed_time % random_max;
906
  random_seed2= (seed_time / 2) % random_max;
907
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
908
  const module::option_map &vm= context.getOptions();
909
  if (vm.count("port"))
910
  { 
911
    if (port > 65535)
912
    {
1639.2.4 by Vijay Samuel
Merge fixes for variables.test and error printing.
913
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value of port\n"));
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
914
      exit(-1);
915
    }
916
  }
917
918
  if (vm.count("connect-timeout"))
919
  {
920
    if (connect_timeout < 1 || connect_timeout > 300)
921
    {
1639.2.4 by Vijay Samuel
Merge fixes for variables.test and error printing.
922
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for connect_timeout\n"));
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
923
      exit(-1);
924
    }
925
  }
926
927
  if (vm.count("read-timeout"))
928
  {
929
    if (read_timeout < 1 || read_timeout > 300)
930
    {
1639.2.4 by Vijay Samuel
Merge fixes for variables.test and error printing.
931
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for read_timeout\n"));
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
932
      exit(-1);
933
    }
934
  }
935
936
  if (vm.count("write-timeout"))
937
  {
938
    if (write_timeout < 1 || write_timeout > 300)
939
    {
1639.2.4 by Vijay Samuel
Merge fixes for variables.test and error printing.
940
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for write_timeout\n"));
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
941
      exit(-1);
942
    }
943
  }
944
945
  if (vm.count("retry-count"))
946
  {
947
    if (retry_count < 1 || retry_count > 100)
948
    {
1639.2.4 by Vijay Samuel
Merge fixes for variables.test and error printing.
949
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for retry_count"));
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
950
      exit(-1);
951
    }
952
  }
953
954
  if (vm.count("buffer-length"))
955
  {
956
    if (buffer_length < 1024 || buffer_length > 1024*1024)
957
    {
1639.2.4 by Vijay Samuel
Merge fixes for variables.test and error printing.
958
      errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for buffer_length\n"));
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
959
      exit(-1);
960
    }
961
  }
962
963
  if (vm.count("bind-address"))
964
  {
965
    bind_address= strdup(vm["bind-address"].as<string>().c_str());
966
  }
967
968
  else
969
  {
970
    bind_address= NULL;
971
  }
972
1337.4.2 by Eric Day
Added MYSQL_PASSWORD() UDF.
973
  mysql_password= new plugin::Create_function<MySQLPassword>(MySQLPasswordName);
1337.4.10 by Eric Day
Merged trunk, rsolved conflicts.
974
  context.add(mysql_password);
1337.4.2 by Eric Day
Added MYSQL_PASSWORD() UDF.
975
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
976
  listen_obj= new ListenMySQLProtocol("mysql_protocol", true);
1324.2.2 by Monty Taylor
Use the plugin::Context everywhere.
977
  context.add(listen_obj); 
1337.4.10 by Eric Day
Merged trunk, rsolved conflicts.
978
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
979
  return 0;
980
}
981
982
static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
983
                           N_("Port number to use for connection or 0 for default to with MySQL "
984
                              "protocol."),
985
                           NULL, NULL, 3306, 0, 65535, 0);
986
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
987
                           PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
988
                           NULL, NULL, 10, 1, 300, 0);
989
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
990
                           N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
991
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
992
                           N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
993
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
994
                           N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
995
static DRIZZLE_SYSVAR_UINT(buffer_length, buffer_length, PLUGIN_VAR_RQCMDARG,
996
                           N_("Buffer length."), NULL, NULL, 16384, 1024,
997
                           1024*1024, 0);
998
static DRIZZLE_SYSVAR_STR(bind_address, bind_address, PLUGIN_VAR_READONLY,
999
                          N_("Address to bind to."), NULL, NULL, NULL);
1000
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
1001
static void init_options(drizzled::module::option_context &context)
1002
{
1003
  context("port",
1004
          po::value<uint32_t>(&port)->default_value(3306),
1005
          N_("Port number to use for connection or 0 for default to with MySQL "
1006
                              "protocol."));
1007
  context("connect-timeout",
1008
          po::value<uint32_t>(&connect_timeout)->default_value(10),
1009
          N_("Connect Timeout."));
1010
  context("read-timeout",
1011
          po::value<uint32_t>(&read_timeout)->default_value(30),
1012
          N_("Read Timeout."));
1013
  context("write-timeout",
1014
          po::value<uint32_t>(&write_timeout)->default_value(60),
1015
          N_("Write Timeout."));
1016
  context("retry-count",
1017
          po::value<uint32_t>(&retry_count)->default_value(10),
1018
          N_("Retry Count."));
1019
  context("buffer-length",
1020
          po::value<uint32_t>(&buffer_length)->default_value(16384),
1021
          N_("Buffer length."));
1022
  context("bind-address",
1023
          po::value<string>(),
1024
          N_("Address to bind to."));
1025
}
1026
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1027
static drizzle_sys_var* sys_variables[]= {
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
1028
  DRIZZLE_SYSVAR(port),
1029
  DRIZZLE_SYSVAR(connect_timeout),
1030
  DRIZZLE_SYSVAR(read_timeout),
1031
  DRIZZLE_SYSVAR(write_timeout),
1032
  DRIZZLE_SYSVAR(retry_count),
1033
  DRIZZLE_SYSVAR(buffer_length),
1034
  DRIZZLE_SYSVAR(bind_address),
1035
  NULL
1036
};
1037
1726.3.4 by LinuxJedi
Add a data_dictionary table for the MySQL protocol plugin
1038
static int mysql_protocol_connection_count_func(drizzle_show_var *var, char *buff)
1039
{
1040
  var->type= SHOW_LONGLONG;
1041
  var->value= buff;
1042
  *((uint64_t *)buff)= ClientMySQLProtocol::connectionCount;
1043
  return 0;
1044
}
1045
1046
static int mysql_protocol_connected_count_func(drizzle_show_var *var, char *buff)
1047
{
1048
  var->type= SHOW_LONGLONG;
1049
  var->value= buff;
1050
  *((uint64_t *)buff)= ClientMySQLProtocol::connected;
1051
  return 0;
1052
}
1053
1054
static int mysql_protocol_failed_count_func(drizzle_show_var *var, char *buff)
1055
{
1056
  var->type= SHOW_LONGLONG;
1057
  var->value= buff;
1058
  *((uint64_t *)buff)= ClientMySQLProtocol::failedConnections;
1059
  return 0;
1060
}
1061
1062
static st_show_var_func_container mysql_protocol_connection_count=
1063
  { &mysql_protocol_connection_count_func };
1064
1065
static st_show_var_func_container mysql_protocol_connected_count=
1066
  { &mysql_protocol_connected_count_func };
1067
1068
static st_show_var_func_container mysql_protocol_failed_count=
1069
  { &mysql_protocol_failed_count_func };
1070
1071
static drizzle_show_var mysql_protocol_status_variables[]= {
1072
  {"Connections",
1073
  (char*) &mysql_protocol_connection_count, SHOW_FUNC},
1074
  {"Connected",
1075
  (char*) &mysql_protocol_connected_count, SHOW_FUNC},
1076
  {"Failed_connections",
1077
  (char*) &mysql_protocol_failed_count, SHOW_FUNC},
1078
  {NULL, NULL, SHOW_LONGLONG}
1079
};
1080
1081
MysqlProtocolStatus::Generator::Generator(drizzled::Field **fields) :
1082
  plugin::TableFunction::Generator(fields)
1083
{
1084
  status_var_ptr= mysql_protocol_status_variables;
1085
}
1086
1087
bool MysqlProtocolStatus::Generator::populate()
1088
{
1089
  MY_ALIGNED_BYTE_ARRAY(buff_data, SHOW_VAR_FUNC_BUFF_SIZE, int64_t);
1090
  char * const buff= (char *) &buff_data;
1091
  drizzle_show_var tmp;
1092
1093
  if (status_var_ptr->name)
1094
  {
1095
    std::ostringstream oss;
1096
    string return_value;
1097
    const char *value;
1098
    int type;
1099
1100
    push(status_var_ptr->name);
1101
1102
    if (status_var_ptr->type == SHOW_FUNC)
1103
    {
1104
      ((mysql_show_var_func)((st_show_var_func_container *)status_var_ptr->value)->func)(&tmp, buff);
1105
      value= buff;
1106
      type= tmp.type;
1107
    }
1108
    else
1109
    {
1110
      value= status_var_ptr->value;
1111
      type= status_var_ptr->type;
1112
    }
1113
1114
    switch(type)
1115
    {
1116
    case SHOW_LONGLONG:
1117
      oss << *(uint64_t*) value;
1118
      return_value= oss.str();
1119
      break;
1120
    default:
1121
      assert(0);
1122
    }
1123
    if (return_value.length())
1124
      push(return_value);
1125
    else
1126
      push(" ");
1127
1128
    status_var_ptr++;
1129
1130
    return true;
1131
  }
1132
  return false;
1133
}
1134
1228.1.5 by Monty Taylor
Merged in some naming things.
1135
DRIZZLE_DECLARE_PLUGIN
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
1136
{
1241.10.2 by Monty Taylor
Added support for embedding the drizzle version number in the plugin file.
1137
  DRIZZLE_VERSION_ID,
1639.2.2 by Vijay Samuel
Merge fixes for variable.test
1138
  "mysql-protocol",
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
1139
  "0.1",
1140
  "Eric Day",
1141
  "MySQL Protocol Module",
1142
  PLUGIN_LICENSE_GPL,
1143
  init,             /* Plugin Init */
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
1144
  sys_variables, /* system variables */
1639.3.1 by Vijay Samuel
Merge program_options into mysql_protocol.
1145
  init_options    /* config options */
971.7.10 by Eric Day
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.
1146
}
1228.1.5 by Monty Taylor
Merged in some naming things.
1147
DRIZZLE_DECLARE_PLUGIN_END;