~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/oldlibdrizzle/oldlibdrizzle.cc

  • Committer: Eric Day
  • Date: 2009-08-27 07:26:22 UTC
  • mto: This revision was merged to the branch mainline in revision 1131.
  • Revision ID: eday@oddments.org-20090827072622-72te13ua0wdlc2ky
Reworked listen interface to not require binding of TCP ports.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* Copyright (C) 2000-2003 MySQL AB
2
 
 
3
 
   This program is free software; you can redistribute it and/or modify
4
 
   it under the terms of the GNU General Public License as published by
5
 
   the Free Software Foundation; version 2 of the License.
6
 
 
7
 
   This program is distributed in the hope that it will be useful,
8
 
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
 
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
 
   GNU General Public License for more details.
11
 
 
12
 
   You should have received a copy of the GNU General Public License
13
 
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
 
 
16
 
/**
17
 
  @file
18
 
 
19
 
  Low level functions for storing data to be send to the MySQL client.
20
 
  The actual communction is handled by the net_xxx functions in net_serv.cc
21
 
*/
 
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
 
22
20
#include <drizzled/server_includes.h>
23
 
#include <drizzled/drizzled_error_messages.h>
 
21
#include <drizzled/gettext.h>
 
22
#include <drizzled/error.h>
 
23
#include <drizzled/query_id.h>
24
24
#include <drizzled/sql_state.h>
 
25
#include <drizzled/session.h>
 
26
#include "pack.h"
 
27
#include "errmsg.h"
 
28
#include "oldlibdrizzle.h"
 
29
#include "libdrizzle.h"
 
30
 
 
31
#include <algorithm>
 
32
 
 
33
using namespace std;
 
34
using namespace drizzled;
 
35
 
 
36
#define PROTOCOL_VERSION 10
 
37
 
 
38
extern uint32_t drizzled_tcp_port;
25
39
 
26
40
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
27
 
/* Declared non-static only because of the embedded library. */
28
 
static void net_send_error_packet(THD *thd, uint32_t sql_errno, const char *err);
29
 
static void write_eof_packet(THD *thd, NET *net,
 
41
static uint32_t connect_timeout;
 
42
static uint32_t read_timeout;
 
43
static uint32_t write_timeout;
 
44
static uint32_t retry_count;
 
45
 
 
46
in_port_t ListenOldLibdrizzle::getPort(void) const
 
47
{
 
48
  return (in_port_t) drizzled_tcp_port;
 
49
}
 
50
 
 
51
plugin::Client *ListenOldLibdrizzle::getClient(int fd)
 
52
{
 
53
  if (fd == -1)
 
54
    return new (nothrow) ClientOldLibdrizzle(-1);
 
55
 
 
56
  int new_fd;
 
57
  new_fd= acceptTcp(fd);
 
58
  if (new_fd == -1)
 
59
    return NULL;
 
60
 
 
61
  return new (nothrow) ClientOldLibdrizzle(new_fd);
 
62
}
 
63
 
 
64
static void write_eof_packet(Session *session, NET *net,
30
65
                             uint32_t server_status, uint32_t total_warn_count);
31
66
 
32
 
bool Protocol::net_store_data(const unsigned char *from, size_t length)
33
 
{
34
 
  ulong packet_length=packet->length();
35
 
  /* 
 
67
bool ClientOldLibdrizzle::isConnected()
 
68
{
 
69
  return net.vio != 0;
 
70
}
 
71
 
 
72
void ClientOldLibdrizzle::setError(char error)
 
73
{
 
74
  net.error= error;
 
75
}
 
76
 
 
77
bool ClientOldLibdrizzle::haveError(void)
 
78
{
 
79
  return net.error || net.vio == 0;
 
80
}
 
81
 
 
82
bool ClientOldLibdrizzle::wasAborted(void)
 
83
{
 
84
  return net.error && net.vio != 0;
 
85
}
 
86
 
 
87
bool ClientOldLibdrizzle::haveMoreData(void)
 
88
{
 
89
  return drizzleclient_net_more_data(&net);
 
90
}
 
91
 
 
92
bool ClientOldLibdrizzle::isReading(void)
 
93
{
 
94
  return net.reading_or_writing == 1;
 
95
}
 
96
 
 
97
bool ClientOldLibdrizzle::isWriting(void)
 
98
{
 
99
  return net.reading_or_writing == 2;
 
100
}
 
101
 
 
102
bool ClientOldLibdrizzle::netStoreData(const unsigned char *from, size_t length)
 
103
{
 
104
  size_t packet_length= packet->length();
 
105
  /*
36
106
     The +9 comes from that strings of length longer than 16M require
37
 
     9 bytes to be stored (see net_store_length).
 
107
     9 bytes to be stored (see drizzleclient_net_store_length).
38
108
  */
39
109
  if (packet_length+9+length > packet->alloced_length() &&
40
110
      packet->realloc(packet_length+9+length))
41
111
    return 1;
42
 
  unsigned char *to= net_store_length((unsigned char*) packet->ptr()+packet_length, length);
 
112
  unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet->ptr()+packet_length, length);
43
113
  memcpy(to,from,length);
44
 
  packet->length((uint) (to+length-(unsigned char*) packet->ptr()));
45
 
  return 0;
46
 
}
47
 
 
48
 
 
49
 
 
50
 
 
51
 
/*
52
 
  net_store_data() - extended version with character set conversion.
53
 
  
54
 
  It is optimized for short strings whose length after
55
 
  conversion is garanteed to be less than 251, which accupies
56
 
  exactly one byte to store length. It allows not to use
57
 
  the "convert" member as a temporary buffer, conversion
58
 
  is done directly to the "packet" member.
59
 
  The limit 251 is good enough to optimize send_fields()
60
 
  because column, table, database names fit into this limit.
61
 
*/
62
 
 
63
 
bool Protocol::net_store_data(const unsigned char *from, size_t length,
64
 
                              const CHARSET_INFO * const from_cs,
65
 
                                                          const CHARSET_INFO * const to_cs)
66
 
{
67
 
  uint32_t dummy_errors;
68
 
  /* Calculate maxumum possible result length */
69
 
  uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
70
 
  if (conv_length > 250)
71
 
  {
72
 
    /*
73
 
      For strings with conv_length greater than 250 bytes
74
 
      we don't know how many bytes we will need to store length: one or two,
75
 
      because we don't know result length until conversion is done.
76
 
      For example, when converting from utf8 (mbmaxlen=3) to latin1,
77
 
      conv_length=300 means that the result length can vary between 100 to 300.
78
 
      length=100 needs one byte, length=300 needs to bytes.
79
 
      
80
 
      Thus conversion directly to "packet" is not worthy.
81
 
      Let's use "convert" as a temporary buffer.
82
 
    */
83
 
    return (convert->copy((const char*) from, length, from_cs,
84
 
                          to_cs, &dummy_errors) ||
85
 
            net_store_data((const unsigned char*) convert->ptr(), convert->length()));
86
 
  }
87
 
 
88
 
  ulong packet_length= packet->length();
89
 
  ulong new_length= packet_length + conv_length + 1;
90
 
 
91
 
  if (new_length > packet->alloced_length() && packet->realloc(new_length))
92
 
    return 1;
93
 
 
94
 
  char *length_pos= (char*) packet->ptr() + packet_length;
95
 
  char *to= length_pos + 1;
96
 
 
97
 
  to+= copy_and_convert(to, conv_length, to_cs,
98
 
                        (const char*) from, length, from_cs, &dummy_errors);
99
 
 
100
 
  net_store_length((unsigned char*) length_pos, to - length_pos - 1);
101
 
  packet->length((uint) (to - packet->ptr()));
102
 
  return 0;
103
 
}
104
 
 
105
 
 
106
 
/**
107
 
  Send a error string to client.
108
 
 
109
 
  Design note:
110
 
  net_printf_error and net_send_error are low-level functions
111
 
  that shall be used only when a new connection is being
112
 
  established or at server startup.
113
 
 
114
 
  For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
115
 
  critical that every error that can be intercepted is issued in one
116
 
  place only, my_message_sql.
117
 
*/
118
 
void net_send_error(THD *thd, uint32_t sql_errno, const char *err)
119
 
{
120
 
  assert(sql_errno);
121
 
  assert(err && err[0]);
122
 
 
123
 
  /*
124
 
    It's one case when we can push an error even though there
125
 
    is an OK or EOF already.
126
 
  */
127
 
  thd->main_da.can_overwrite_status= true;
128
 
 
129
 
  /* Abort multi-result sets */
130
 
  thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
131
 
 
132
 
  net_send_error_packet(thd, sql_errno, err);
133
 
 
134
 
  thd->main_da.can_overwrite_status= false;
135
 
}
 
114
  packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
 
115
  return 0;
 
116
}
 
117
 
136
118
 
137
119
/**
138
120
  Return ok to the client.
140
122
  The ok packet has the following structure:
141
123
 
142
124
  - 0               : Marker (1 byte)
143
 
  - affected_rows       : Stored in 1-9 bytes
144
 
  - id          : Stored in 1-9 bytes
145
 
  - server_status       : Copy of thd->server_status;  Can be used by client
 
125
  - affected_rows    : Stored in 1-9 bytes
 
126
  - id        : Stored in 1-9 bytes
 
127
  - server_status    : Copy of session->server_status;  Can be used by client
146
128
  to check if we are inside an transaction.
147
 
  New in 4.0 protocol
148
 
  - warning_count       : Stored in 2 bytes; New in 4.1 protocol
149
 
  - message             : Stored as packed length (1-9 bytes) + message.
 
129
  New in 4.0 client
 
130
  - warning_count    : Stored in 2 bytes; New in 4.1 client
 
131
  - message        : Stored as packed length (1-9 bytes) + message.
150
132
  Is not stored if no message.
151
133
 
152
 
  @param thd               Thread handler
153
 
  @param affected_rows     Number of rows changed by statement
154
 
  @param id                Auto_increment id for first row (if used)
155
 
  @param message           Message to send to the client (Used by mysql_status)
 
134
  @param session           Thread handler
 
135
  @param affected_rows       Number of rows changed by statement
 
136
  @param id           Auto_increment id for first row (if used)
 
137
  @param message       Message to send to the client (Used by mysql_status)
156
138
*/
157
139
 
158
 
static void
159
 
net_send_ok(THD *thd,
160
 
            uint32_t server_status, uint32_t total_warn_count,
161
 
            ha_rows affected_rows, uint64_t id, const char *message)
 
140
void ClientOldLibdrizzle::sendOK()
162
141
{
163
 
  NET *net= &thd->net;
164
142
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
 
143
  const char *message= NULL;
 
144
  uint32_t tmp;
165
145
 
166
 
  if (! net->vio)       // hack for re-parsing queries
 
146
  if (!net.vio)    // hack for re-parsing queries
167
147
  {
168
148
    return;
169
149
  }
170
150
 
171
 
  buff[0]=0;                                    // No fields
172
 
  pos=net_store_length(buff+1,affected_rows);
173
 
  pos=net_store_length(pos, id);
174
 
 
175
 
  int2store(pos, server_status);
176
 
  pos+=2;
 
151
  buff[0]=0;                    // No fields
 
152
  if (session->main_da.status() == Diagnostics_area::DA_OK)
 
153
  {
 
154
    if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da.found_rows())
 
155
      pos=drizzleclient_net_store_length(buff+1,session->main_da.found_rows());
 
156
    else
 
157
      pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
 
158
    pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
 
159
    int2store(pos, session->main_da.server_status());
 
160
    pos+=2;
 
161
    tmp= min(session->main_da.total_warn_count(), (uint32_t)65535);
 
162
    message= session->main_da.message();
 
163
  }
 
164
  else
 
165
  {
 
166
    pos=drizzleclient_net_store_length(buff+1,0);
 
167
    pos=drizzleclient_net_store_length(pos, 0);
 
168
    int2store(pos, session->server_status);
 
169
    pos+=2;
 
170
    tmp= min(session->total_warn_count, (uint32_t)65535);
 
171
  }
177
172
 
178
173
  /* We can only return up to 65535 warnings in two bytes */
179
 
  uint32_t tmp= cmin(total_warn_count, (uint)65535);
180
174
  int2store(pos, tmp);
181
175
  pos+= 2;
182
176
 
183
 
  thd->main_da.can_overwrite_status= true;
 
177
  session->main_da.can_overwrite_status= true;
184
178
 
185
179
  if (message && message[0])
186
 
    pos= net_store_data(pos, (unsigned char*) message, strlen(message));
187
 
  my_net_write(net, buff, (size_t) (pos-buff));
188
 
  net_flush(net);
 
180
  {
 
181
    size_t length= strlen(message);
 
182
    pos=drizzleclient_net_store_length(pos,length);
 
183
    memcpy(pos,(unsigned char*) message,length);
 
184
    pos+=length;
 
185
  }
 
186
  drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
 
187
  drizzleclient_net_flush(&net);
189
188
 
190
 
  thd->main_da.can_overwrite_status= false;
 
189
  session->main_da.can_overwrite_status= false;
191
190
}
192
191
 
193
192
/**
195
194
 
196
195
  The eof packet has the following structure:
197
196
 
198
 
  - 254 (DRIZZLE_PROTOCOL_NO_MORE_DATA) : Marker (1 byte)
199
 
  - warning_count       : Stored in 2 bytes; New in 4.1 protocol
200
 
  - status_flag : Stored in 2 bytes;
 
197
  - 254    (DRIZZLE_PROTOCOL_NO_MORE_DATA)    : Marker (1 byte)
 
198
  - warning_count    : Stored in 2 bytes; New in 4.1 client
 
199
  - status_flag    : Stored in 2 bytes;
201
200
  For flags like SERVER_MORE_RESULTS_EXISTS.
202
201
 
203
202
  Note that the warning count will not be sent if 'no_flush' is set as
204
203
  we don't want to report the warning count until all data is sent to the
205
204
  client.
206
 
 
207
 
  @param thd            Thread handler
208
 
  @param no_flush       Set to 1 if there will be more data to the client,
209
 
                    like in send_fields().
210
 
*/    
211
 
 
212
 
static void
213
 
net_send_eof(THD *thd, uint32_t server_status, uint32_t total_warn_count)
 
205
*/
 
206
 
 
207
void ClientOldLibdrizzle::sendEOF()
214
208
{
215
 
  NET *net= &thd->net;
216
209
  /* Set to true if no active vio, to work well in case of --init-file */
217
 
  if (net->vio != 0)
 
210
  if (net.vio != 0)
218
211
  {
219
 
    thd->main_da.can_overwrite_status= true;
220
 
    write_eof_packet(thd, net, server_status, total_warn_count);
221
 
    net_flush(net);
222
 
    thd->main_da.can_overwrite_status= false;
 
212
    session->main_da.can_overwrite_status= true;
 
213
    write_eof_packet(session, &net, session->main_da.server_status(),
 
214
                     session->main_da.total_warn_count());
 
215
    drizzleclient_net_flush(&net);
 
216
    session->main_da.can_overwrite_status= false;
223
217
  }
224
218
}
225
219
 
226
220
 
227
221
/**
228
 
  Format EOF packet according to the current protocol and
 
222
  Format EOF packet according to the current client and
229
223
  write it to the network output buffer.
230
224
*/
231
225
 
232
 
static void write_eof_packet(THD *thd, NET *net,
 
226
static void write_eof_packet(Session *session, NET *net,
233
227
                             uint32_t server_status,
234
228
                             uint32_t total_warn_count)
235
229
{
238
232
    Don't send warn count during SP execution, as the warn_list
239
233
    is cleared between substatements, and mysqltest gets confused
240
234
  */
241
 
  uint32_t tmp= cmin(total_warn_count, (uint)65535);
 
235
  uint32_t tmp= min(total_warn_count, (uint32_t)65535);
242
236
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
243
237
  int2store(buff+1, tmp);
244
238
  /*
246
240
    because if 'is_fatal_error' is set the server is not going to execute
247
241
    other queries (see the if test in dispatch_command / COM_QUERY)
248
242
  */
249
 
  if (thd->is_fatal_error)
 
243
  if (session->is_fatal_error)
250
244
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
251
245
  int2store(buff + 3, server_status);
252
 
  my_net_write(net, buff, 5);
 
246
  drizzleclient_net_write(net, buff, 5);
253
247
}
254
248
 
255
 
void net_send_error_packet(THD *thd, uint32_t sql_errno, const char *err)
 
249
void ClientOldLibdrizzle::sendError(uint32_t sql_errno, const char *err)
256
250
{
257
 
  NET *net= &thd->net;
258
251
  uint32_t length;
259
252
  /*
260
253
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
261
254
  */
262
255
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
263
256
 
264
 
  if (net->vio == 0)
 
257
  assert(sql_errno);
 
258
  assert(err && err[0]);
 
259
 
 
260
  /*
 
261
    It's one case when we can push an error even though there
 
262
    is an OK or EOF already.
 
263
  */
 
264
  session->main_da.can_overwrite_status= true;
 
265
 
 
266
  /* Abort multi-result sets */
 
267
  session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
268
 
 
269
  /**
 
270
    Send a error string to client.
 
271
 
 
272
    For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
 
273
    critical that every error that can be intercepted is issued in one
 
274
    place only, my_message_sql.
 
275
  */
 
276
 
 
277
  if (net.vio == 0)
265
278
  {
266
279
    return;
267
280
  }
269
282
  int2store(buff,sql_errno);
270
283
  pos= buff+2;
271
284
 
272
 
  /* The first # is to make the protocol backward compatible */
 
285
  /* The first # is to make the client backward compatible */
273
286
  buff[2]= '#';
274
 
  pos= (unsigned char*) my_stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
 
287
  pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
 
288
  pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
275
289
 
276
 
  length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
277
 
                  (char*) buff);
 
290
  char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
 
291
  tmp+= strlen((char*)pos);
 
292
  tmp[0]= '\0';
 
293
  length= (uint32_t)(tmp-(char*)buff);
278
294
  err= (char*) buff;
279
295
 
280
 
  net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
281
 
  return;
282
 
}
283
 
 
284
 
 
285
 
/**
286
 
  Faster net_store_length when we know that length is less than 65536.
287
 
  We keep a separate version for that range because it's widely used in
288
 
  libmysql.
289
 
 
290
 
  uint32_t is used as agrument type because of MySQL type conventions:
291
 
  - uint32_t for 0..65536
292
 
  - ulong for 0..4294967296
293
 
  - uint64_t for bigger numbers.
294
 
*/
295
 
 
296
 
static unsigned char *net_store_length_fast(unsigned char *packet, uint32_t length)
297
 
{
298
 
  if (length < 251)
299
 
  {
300
 
    *packet=(unsigned char) length;
301
 
    return packet+1;
302
 
  }
303
 
  *packet++=252;
304
 
  int2store(packet,(uint) length);
305
 
  return packet+2;
306
 
}
307
 
 
308
 
/**
309
 
  Send the status of the current statement execution over network.
310
 
 
311
 
  @param  thd   in fact, carries two parameters, NET for the transport and
312
 
                Diagnostics_area as the source of status information.
313
 
 
314
 
  In MySQL, there are two types of SQL statements: those that return
315
 
  a result set and those that return status information only.
316
 
 
317
 
  If a statement returns a result set, it consists of 3 parts:
318
 
  - result set meta-data
319
 
  - variable number of result set rows (can be 0)
320
 
  - followed and terminated by EOF or ERROR packet
321
 
 
322
 
  Once the  client has seen the meta-data information, it always
323
 
  expects an EOF or ERROR to terminate the result set. If ERROR is
324
 
  received, the result set rows are normally discarded (this is up
325
 
  to the client implementation, libmysql at least does discard them).
326
 
  EOF, on the contrary, means "successfully evaluated the entire
327
 
  result set". Since we don't know how many rows belong to a result
328
 
  set until it's evaluated, EOF/ERROR is the indicator of the end
329
 
  of the row stream. Note, that we can not buffer result set rows
330
 
  on the server -- there may be an arbitrary number of rows. But
331
 
  we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
332
 
  delay sending it till the very end of execution (here), to be able to
333
 
  change EOF to an ERROR if commit failed or some other error occurred
334
 
  during the last cleanup steps taken after execution.
335
 
 
336
 
  A statement that does not return a result set doesn't send result
337
 
  set meta-data either. Instead it returns one of:
338
 
  - OK packet
339
 
  - ERROR packet.
340
 
  Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
341
 
  packet is "buffered" in the diagnostics area and sent to the client
342
 
  in the end of statement.
343
 
 
344
 
  @pre  The diagnostics area is assigned or disabled. It can not be empty
345
 
        -- we assume that every SQL statement or COM_* command
346
 
        generates OK, ERROR, or EOF status.
347
 
 
348
 
  @post The status information is encoded to protocol format and sent to the
349
 
        client.
350
 
 
351
 
  @return We conventionally return void, since the only type of error
352
 
          that can happen here is a NET (transport) error, and that one
353
 
          will become visible when we attempt to read from the NET the
354
 
          next command.
355
 
          Diagnostics_area::is_sent is set for debugging purposes only.
356
 
*/
357
 
 
358
 
void net_end_statement(THD *thd)
359
 
{
360
 
  assert(! thd->main_da.is_sent);
361
 
 
362
 
  /* Can not be true, but do not take chances in production. */
363
 
  if (thd->main_da.is_sent)
 
296
  drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
 
297
 
 
298
  session->main_da.can_overwrite_status= false;
 
299
}
 
300
 
 
301
 
 
302
ClientOldLibdrizzle::ClientOldLibdrizzle(int fd)
 
303
{
 
304
  scramble[0]= 0;
 
305
  net.vio= 0;
 
306
 
 
307
  if (fd == -1)
364
308
    return;
365
309
 
366
 
  switch (thd->main_da.status()) {
367
 
  case Diagnostics_area::DA_ERROR:
368
 
    /* The query failed, send error to log and abort bootstrap. */
369
 
    net_send_error(thd,
370
 
                   thd->main_da.sql_errno(),
371
 
                   thd->main_da.message());
372
 
    break;
373
 
  case Diagnostics_area::DA_EOF:
374
 
    net_send_eof(thd,
375
 
                 thd->main_da.server_status(),
376
 
                 thd->main_da.total_warn_count());
377
 
    break;
378
 
  case Diagnostics_area::DA_OK:
379
 
    net_send_ok(thd,
380
 
                thd->main_da.server_status(),
381
 
                thd->main_da.total_warn_count(),
382
 
                thd->main_da.affected_rows(),
383
 
                thd->main_da.last_insert_id(),
384
 
                thd->main_da.message());
385
 
    break;
386
 
  case Diagnostics_area::DA_DISABLED:
387
 
    break;
388
 
  case Diagnostics_area::DA_EMPTY:
389
 
  default:
390
 
    assert(0);
391
 
    net_send_ok(thd, thd->server_status, thd->total_warn_count,
392
 
                0, 0, NULL);
393
 
    break;
394
 
  }
395
 
  thd->main_da.is_sent= true;
396
 
}
397
 
 
398
 
 
399
 
/****************************************************************************
400
 
  Functions used by the protocol functions (like net_send_ok) to store
401
 
  strings and numbers in the header result packet.
402
 
****************************************************************************/
403
 
 
404
 
/* The following will only be used for short strings < 65K */
405
 
 
406
 
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
407
 
{
408
 
  to=net_store_length_fast(to,length);
409
 
  memcpy(to,from,length);
410
 
  return to+length;
411
 
}
412
 
 
413
 
unsigned char *net_store_data(unsigned char *to,int32_t from)
414
 
{
415
 
  char buff[20];
416
 
  uint32_t length=(uint) (int10_to_str(from,buff,10)-buff);
417
 
  to=net_store_length_fast(to,length);
418
 
  memcpy(to,buff,length);
419
 
  return to+length;
420
 
}
421
 
 
422
 
unsigned char *net_store_data(unsigned char *to,int64_t from)
423
 
{
424
 
  char buff[22];
425
 
  uint32_t length=(uint) (int64_t10_to_str(from,buff,10)-buff);
426
 
  to=net_store_length_fast(to,length);
427
 
  memcpy(to,buff,length);
428
 
  return to+length;
429
 
}
430
 
 
431
 
 
432
 
/*****************************************************************************
433
 
  Default Protocol functions
434
 
*****************************************************************************/
435
 
 
436
 
void Protocol::init(THD *thd_arg)
437
 
{
438
 
  thd=thd_arg;
439
 
  packet= &thd->packet;
440
 
  convert= &thd->convert_buffer;
441
 
}
442
 
 
443
 
/**
444
 
  Finish the result set with EOF packet, as is expected by the client,
445
 
  if there is an error evaluating the next row and a continue handler
446
 
  for the error.
447
 
*/
448
 
 
449
 
void Protocol::end_partial_result_set(THD *thd)
450
 
{
451
 
  net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
452
 
}
453
 
 
454
 
 
455
 
bool Protocol::flush()
456
 
{
457
 
  return net_flush(&thd->net);
 
310
  if (drizzleclient_net_init_sock(&net, fd, 0))
 
311
    throw bad_alloc();
 
312
 
 
313
  drizzleclient_net_set_read_timeout(&net, read_timeout);
 
314
  drizzleclient_net_set_write_timeout(&net, write_timeout);
 
315
  net.retry_count=retry_count;
 
316
}
 
317
 
 
318
ClientOldLibdrizzle::~ClientOldLibdrizzle()
 
319
{
 
320
  if (net.vio)
 
321
    drizzleclient_vio_close(net.vio);
 
322
}
 
323
 
 
324
void ClientOldLibdrizzle::setSession(Session *session_arg)
 
325
{
 
326
  session= session_arg;
 
327
  packet= &session->packet;
 
328
  convert= &session->convert_buffer;
 
329
  prepareForResend();
458
330
}
459
331
 
460
332
 
463
335
 
464
336
  Sum fields has table name empty and field_name.
465
337
 
466
 
  @param THD            Thread data object
467
 
  @param list           List of items to send to client
468
 
  @param flag           Bit mask with the following functions:
 
338
  @param Session        Thread data object
 
339
  @param list            List of items to send to client
 
340
  @param flag            Bit mask with the following functions:
469
341
                        - 1 send number of rows
470
342
                        - 2 send default values
471
343
                        - 4 don't write eof packet
472
344
 
473
345
  @retval
474
 
    0   ok
 
346
    0    ok
475
347
  @retval
476
 
    1   Error  (Note that in this case the error is not sent to the
 
348
    1    Error  (Note that in this case the error is not sent to the
477
349
    client)
478
350
*/
479
 
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
 
351
bool ClientOldLibdrizzle::sendFields(List<Item> *list)
480
352
{
481
353
  List_iterator_fast<Item> it(*list);
482
354
  Item *item;
483
355
  unsigned char buff[80];
484
356
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
485
 
  Protocol_text prot(thd);
486
 
  String *local_packet= prot.storage_packet();
487
 
  const CHARSET_INFO * const thd_charset= thd->variables.character_set_results;
488
357
 
489
 
  if (flags & SEND_NUM_ROWS)
490
 
  {                             // Packet with number of elements
491
 
    unsigned char *pos= net_store_length(buff, list->elements);
492
 
    (void) my_net_write(&thd->net, buff, (size_t) (pos-buff));
493
 
  }
 
358
  unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
 
359
  (void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
494
360
 
495
361
  while ((item=it++))
496
362
  {
497
363
    char *pos;
498
 
    const CHARSET_INFO * const cs= system_charset_info;
499
 
    Send_field field;
 
364
    SendField field;
500
365
    item->make_field(&field);
501
366
 
502
 
    prot.prepare_for_resend();
503
 
 
504
 
 
505
 
    if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
506
 
        prot.store(field.db_name, (uint) strlen(field.db_name),
507
 
                   cs, thd_charset) ||
508
 
        prot.store(field.table_name, (uint) strlen(field.table_name),
509
 
                   cs, thd_charset) ||
510
 
        prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
511
 
                   cs, thd_charset) ||
512
 
        prot.store(field.col_name, (uint) strlen(field.col_name),
513
 
                   cs, thd_charset) ||
514
 
        prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
515
 
                   cs, thd_charset) ||
516
 
        local_packet->realloc(local_packet->length()+12))
 
367
    prepareForResend();
 
368
 
 
369
    if (store(STRING_WITH_LEN("def")) ||
 
370
        store(field.db_name) ||
 
371
        store(field.table_name) ||
 
372
        store(field.org_table_name) ||
 
373
        store(field.col_name) ||
 
374
        store(field.org_col_name) ||
 
375
        packet->realloc(packet->length()+12))
517
376
      goto err;
518
377
 
519
378
    /* Store fixed length fields */
520
 
    pos= (char*) local_packet->ptr()+local_packet->length();
521
 
    *pos++= 12;                         // Length of packed fields
522
 
    if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
523
 
    {
524
 
      /* No conversion */
525
 
      int2store(pos, field.charsetnr);
526
 
      int4store(pos+2, field.length);
527
 
    }
528
 
    else
529
 
    {
530
 
      /* With conversion */
531
 
      uint32_t max_char_len;
532
 
      int2store(pos, thd_charset->number);
533
 
      /*
534
 
        For TEXT/BLOB columns, field_length describes the maximum data
535
 
        length in bytes. There is no limit to the number of characters
536
 
        that a TEXT column can store, as long as the data fits into
537
 
        the designated space.
538
 
        For the rest of textual columns, field_length is evaluated as
539
 
        char_count * mbmaxlen, where character count is taken from the
540
 
        definition of the column. In other words, the maximum number
541
 
        of characters here is limited by the column definition.
542
 
      */
543
 
      max_char_len= field.length / item->collation.collation->mbmaxlen;
544
 
      int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
545
 
    }
 
379
    pos= (char*) packet->ptr()+packet->length();
 
380
    *pos++= 12;                // Length of packed fields
 
381
    /* No conversion */
 
382
    int2store(pos, field.charsetnr);
 
383
    int4store(pos+2, field.length);
546
384
    pos[6]= field.type;
547
385
    int2store(pos+7,field.flags);
548
386
    pos[9]= (char) field.decimals;
549
 
    pos[10]= 0;                         // For the future
550
 
    pos[11]= 0;                         // For the future
 
387
    pos[10]= 0;                // For the future
 
388
    pos[11]= 0;                // For the future
551
389
    pos+= 12;
552
390
 
553
 
    local_packet->length((uint) (pos - local_packet->ptr()));
554
 
    if (flags & SEND_DEFAULTS)
555
 
      item->send(&prot, &tmp);                  // Send default value
556
 
    if (prot.write())
557
 
      break;                                    /* purecov: inspected */
558
 
  }
559
 
 
560
 
  if (flags & SEND_EOF)
561
 
  {
562
 
    /*
563
 
      Mark the end of meta-data result set, and store thd->server_status,
564
 
      to show that there is no cursor.
565
 
      Send no warning information, as it will be sent at statement end.
566
 
    */
567
 
    write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
568
 
  }
569
 
  return(prepare_for_send(list));
 
391
    packet->length((uint32_t) (pos - packet->ptr()));
 
392
    if (flush())
 
393
      break;                    /* purecov: inspected */
 
394
  }
 
395
 
 
396
  /*
 
397
    Mark the end of meta-data result set, and store session->server_status,
 
398
    to show that there is no cursor.
 
399
    Send no warning information, as it will be sent at statement end.
 
400
  */
 
401
  write_eof_packet(session, &net, session->server_status,
 
402
                   session->total_warn_count);
 
403
 
 
404
  field_count= list->elements;
 
405
  return 0;
570
406
 
571
407
err:
572
408
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
573
 
             MYF(0));   /* purecov: inspected */
574
 
  return(1);                            /* purecov: inspected */
575
 
}
576
 
 
577
 
 
578
 
bool Protocol::write()
579
 
{
580
 
  return(my_net_write(&thd->net, (unsigned char*) packet->ptr(),
581
 
                           packet->length()));
582
 
}
583
 
 
584
 
 
585
 
/**
586
 
  Send \\0 end terminated string.
587
 
 
588
 
  @param from   NULL or \\0 terminated string
589
 
 
590
 
  @note
591
 
    In most cases one should use store(from, length) instead of this function
592
 
 
593
 
  @retval
594
 
    0           ok
595
 
  @retval
596
 
    1           error
597
 
*/
598
 
 
599
 
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
600
 
{
601
 
  if (!from)
602
 
    return store_null();
603
 
  uint32_t length= strlen(from);
604
 
  return store(from, length, cs);
605
 
}
606
 
 
607
 
 
608
 
/**
609
 
  Send a set of strings as one long string with ',' in between.
610
 
*/
611
 
 
612
 
bool Protocol::store(I_List<i_string>* str_list)
613
 
{
614
 
  char buf[256];
615
 
  String tmp(buf, sizeof(buf), &my_charset_bin);
616
 
  uint32_t len;
617
 
  I_List_iterator<i_string> it(*str_list);
618
 
  i_string* s;
619
 
 
620
 
  tmp.length(0);
621
 
  while ((s=it++))
622
 
  {
623
 
    tmp.append(s->ptr);
624
 
    tmp.append(',');
625
 
  }
626
 
  if ((len= tmp.length()))
627
 
    len--;                                      // Remove last ','
628
 
  return store((char*) tmp.ptr(), len,  tmp.charset());
629
 
}
630
 
 
631
 
 
632
 
/****************************************************************************
633
 
  Functions to handle the simple (default) protocol where everything is
634
 
  This protocol is the one that is used by default between the MySQL server
635
 
  and client when you are not using prepared statements.
636
 
 
637
 
  All data are sent as 'packed-string-length' followed by 'string-data'
638
 
****************************************************************************/
639
 
 
640
 
void Protocol_text::prepare_for_resend()
 
409
             MYF(0));    /* purecov: inspected */
 
410
  return 1;                /* purecov: inspected */
 
411
}
 
412
 
 
413
 
 
414
bool ClientOldLibdrizzle::flush()
 
415
{
 
416
  if (net.vio == NULL)
 
417
    return false;
 
418
  bool ret= drizzleclient_net_write(&net, (unsigned char*) packet->ptr(),
 
419
                           packet->length());
 
420
  prepareForResend();
 
421
  return ret;
 
422
}
 
423
 
 
424
void ClientOldLibdrizzle::free()
 
425
{
 
426
  packet->free();
 
427
}
 
428
 
 
429
int ClientOldLibdrizzle::getFileDescriptor(void)
 
430
{
 
431
  return drizzleclient_net_get_sd(&net);
 
432
}
 
433
 
 
434
bool ClientOldLibdrizzle::authenticate()
 
435
{
 
436
  bool connection_is_valid;
 
437
 
 
438
  /* Use "connect_timeout" value during connection phase */
 
439
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
 
440
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
 
441
 
 
442
  connection_is_valid= checkConnection();
 
443
 
 
444
  if (connection_is_valid)
 
445
    sendOK();
 
446
  else
 
447
  {
 
448
    sendError(session->main_da.sql_errno(), session->main_da.message());
 
449
    return false;
 
450
  }
 
451
 
 
452
  /* Connect completed, set read/write timeouts back to default */
 
453
  drizzleclient_net_set_read_timeout(&net, read_timeout);
 
454
  drizzleclient_net_set_write_timeout(&net, write_timeout);
 
455
  return true;
 
456
}
 
457
 
 
458
bool ClientOldLibdrizzle::readCommand(char **l_packet, uint32_t *packet_length)
 
459
{
 
460
  /*
 
461
    This thread will do a blocking read from the client which
 
462
    will be interrupted when the next command is received from
 
463
    the client, the connection is closed or "net_wait_timeout"
 
464
    number of seconds has passed
 
465
  */
 
466
#ifdef NEVER
 
467
  /* We can do this much more efficiently with poll timeouts or watcher thread,
 
468
     disabling for now, which means net_wait_timeout == read_timeout. */
 
469
  drizzleclient_net_set_read_timeout(&net,
 
470
                                     session->variables.net_wait_timeout);
 
471
#endif
 
472
 
 
473
  net.pkt_nr=0;
 
474
 
 
475
  *packet_length= drizzleclient_net_read(&net);
 
476
  if (*packet_length == packet_error)
 
477
  {
 
478
    /* Check if we can continue without closing the connection */
 
479
 
 
480
    if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
 
481
      my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
 
482
    if (session->main_da.status() == Diagnostics_area::DA_ERROR)
 
483
      sendError(session->main_da.sql_errno(), session->main_da.message());
 
484
    else
 
485
      sendOK();
 
486
 
 
487
    if (net.error != 3)
 
488
      return false;                       // We have to close it.
 
489
 
 
490
    net.error= 0;
 
491
    *packet_length= 0;
 
492
    return true;
 
493
  }
 
494
 
 
495
  *l_packet= (char*) net.read_pos;
 
496
 
 
497
  /*
 
498
    'packet_length' contains length of data, as it was stored in packet
 
499
    header. In case of malformed header, drizzleclient_net_read returns zero.
 
500
    If packet_length is not zero, drizzleclient_net_read ensures that the returned
 
501
    number of bytes was actually read from network.
 
502
    There is also an extra safety measure in drizzleclient_net_read:
 
503
    it sets packet[packet_length]= 0, but only for non-zero packets.
 
504
  */
 
505
 
 
506
  if (*packet_length == 0)                       /* safety */
 
507
  {
 
508
    /* Initialize with COM_SLEEP packet */
 
509
    (*l_packet)[0]= (unsigned char) COM_SLEEP;
 
510
    *packet_length= 1;
 
511
  }
 
512
  /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
 
513
  (*l_packet)[*packet_length]= '\0';                  /* safety */
 
514
 
 
515
#ifdef NEVER
 
516
  /* See comment above. */
 
517
  /* Restore read timeout value */
 
518
  drizzleclient_net_set_read_timeout(&net,
 
519
                                     session->variables.net_read_timeout);
 
520
#endif
 
521
 
 
522
  return true;
 
523
}
 
524
 
 
525
void ClientOldLibdrizzle::close(void)
 
526
{
 
527
  if (net.vio)
 
528
  { 
 
529
    drizzleclient_net_close(&net);
 
530
    drizzleclient_net_end(&net);
 
531
  }
 
532
}
 
533
 
 
534
void ClientOldLibdrizzle::forceClose(void)
 
535
{
 
536
  if (net.vio)
 
537
    drizzleclient_vio_close(net.vio);
 
538
}
 
539
 
 
540
void ClientOldLibdrizzle::prepareForResend()
641
541
{
642
542
  packet->length(0);
643
543
}
644
544
 
645
 
bool Protocol_text::store_null()
 
545
bool ClientOldLibdrizzle::store(void)
646
546
{
647
547
  char buff[1];
648
548
  buff[0]= (char)251;
650
550
}
651
551
 
652
552
 
653
 
/**
654
 
  Auxilary function to convert string to the given character set
655
 
  and store in network buffer.
656
 
*/
657
 
 
658
 
bool Protocol::store_string_aux(const char *from, size_t length,
659
 
                                const CHARSET_INFO * const fromcs,
660
 
                                                                const CHARSET_INFO * const tocs)
661
 
{
662
 
  /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
663
 
  if (tocs && !my_charset_same(fromcs, tocs) &&
664
 
      fromcs != &my_charset_bin &&
665
 
      tocs != &my_charset_bin)
666
 
  {
667
 
    /* Store with conversion */
668
 
    return net_store_data((unsigned char*) from, length, fromcs, tocs);
669
 
  }
670
 
  /* Store without conversion */
671
 
  return net_store_data((unsigned char*) from, length);
672
 
}
673
 
 
674
 
 
675
 
bool Protocol_text::store(const char *from, size_t length,
676
 
                          const CHARSET_INFO * const fromcs,
677
 
                                                  const CHARSET_INFO * const tocs)
678
 
{
679
 
  return store_string_aux(from, length, fromcs, tocs);
680
 
}
681
 
 
682
 
 
683
 
bool Protocol_text::store(const char *from, size_t length,
684
 
                          const CHARSET_INFO * const fromcs)
685
 
{
686
 
  const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
687
 
  return store_string_aux(from, length, fromcs, tocs);
688
 
}
689
 
 
690
 
 
691
 
bool Protocol_text::store_tiny(int64_t from)
692
 
{
693
 
  char buff[20];
694
 
  return net_store_data((unsigned char*) buff,
695
 
                        (size_t) (int10_to_str((int) from, buff, -10) - buff));
696
 
}
697
 
 
698
 
 
699
 
bool Protocol_text::store_short(int64_t from)
700
 
{
701
 
  char buff[20];
702
 
  return net_store_data((unsigned char*) buff,
703
 
                        (size_t) (int10_to_str((int) from, buff, -10) -
704
 
                                  buff));
705
 
}
706
 
 
707
 
 
708
 
bool Protocol_text::store_long(int64_t from)
709
 
{
710
 
  char buff[20];
711
 
  return net_store_data((unsigned char*) buff,
712
 
                        (size_t) (int10_to_str((long int)from, buff,
713
 
                                               (from <0)?-10:10)-buff));
714
 
}
715
 
 
716
 
 
717
 
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
 
553
bool ClientOldLibdrizzle::store(const char *from, size_t length)
 
554
{
 
555
  return netStoreData((const unsigned char *)from, length);
 
556
}
 
557
 
 
558
 
 
559
bool ClientOldLibdrizzle::store(int32_t from)
 
560
{
 
561
  char buff[12];
 
562
  return netStoreData((unsigned char*) buff,
 
563
                      (size_t) (int10_to_str(from, buff, -10) - buff));
 
564
}
 
565
 
 
566
bool ClientOldLibdrizzle::store(uint32_t from)
 
567
{
 
568
  char buff[11];
 
569
  return netStoreData((unsigned char*) buff,
 
570
                      (size_t) (int10_to_str(from, buff, 10) - buff));
 
571
}
 
572
 
 
573
bool ClientOldLibdrizzle::store(int64_t from)
718
574
{
719
575
  char buff[22];
720
 
  return net_store_data((unsigned char*) buff,
721
 
                        (size_t) (int64_t10_to_str(from,buff,
722
 
                                                    unsigned_flag ? 10 : -10)-
723
 
                                  buff));
724
 
}
725
 
 
726
 
 
727
 
bool Protocol_text::store_decimal(const my_decimal *d)
728
 
{
729
 
  char buff[DECIMAL_MAX_STR_LENGTH];
730
 
  String str(buff, sizeof(buff), &my_charset_bin);
731
 
  (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
732
 
  return net_store_data((unsigned char*) str.ptr(), str.length());
733
 
}
734
 
 
735
 
 
736
 
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
737
 
{
738
 
  buffer->set_real((double) from, decimals, thd->charset());
739
 
  return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
740
 
}
741
 
 
742
 
 
743
 
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
744
 
{
745
 
  buffer->set_real(from, decimals, thd->charset());
746
 
  return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
747
 
}
748
 
 
749
 
 
750
 
bool Protocol_text::store(Field *field)
751
 
{
752
 
  if (field->is_null())
753
 
    return store_null();
 
576
  return netStoreData((unsigned char*) buff,
 
577
                      (size_t) (int64_t10_to_str(from, buff, -10) - buff));
 
578
}
 
579
 
 
580
bool ClientOldLibdrizzle::store(uint64_t from)
 
581
{
 
582
  char buff[21];
 
583
  return netStoreData((unsigned char*) buff,
 
584
                      (size_t) (int64_t10_to_str(from, buff, 10) - buff));
 
585
}
 
586
 
 
587
 
 
588
bool ClientOldLibdrizzle::store(double from, uint32_t decimals, String *buffer)
 
589
{
 
590
  buffer->set_real(from, decimals, session->charset());
 
591
  return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
 
592
}
 
593
 
 
594
 
 
595
bool ClientOldLibdrizzle::store(Field *from)
 
596
{
 
597
  if (from->is_null())
 
598
    return store();
754
599
  char buff[MAX_FIELD_WIDTH];
755
600
  String str(buff,sizeof(buff), &my_charset_bin);
756
 
  const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
757
 
 
758
 
  field->val_str(&str);
759
 
 
760
 
  return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
 
601
 
 
602
  from->val_str(&str);
 
603
 
 
604
  return netStoreData((const unsigned char *)str.ptr(), str.length());
761
605
}
762
606
 
763
607
 
764
608
/**
765
609
  @todo
766
 
    Second_part format ("%06") needs to change when 
767
 
    we support 0-6 decimals for time.
768
 
*/
769
 
 
770
 
bool Protocol_text::store(DRIZZLE_TIME *tm)
771
 
{
772
 
  char buff[40];
773
 
  uint32_t length;
774
 
  length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
775
 
                           (int) tm->year,
776
 
                           (int) tm->month,
777
 
                           (int) tm->day,
778
 
                           (int) tm->hour,
779
 
                           (int) tm->minute,
780
 
                           (int) tm->second);
781
 
  if (tm->second_part)
782
 
    length+= sprintf(buff+length, ".%06d",
783
 
                                     (int)tm->second_part);
784
 
  return net_store_data((unsigned char*) buff, length);
785
 
}
786
 
 
787
 
 
788
 
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
789
 
{
790
 
  char buff[MAX_DATE_STRING_REP_LENGTH];
791
 
  size_t length= my_date_to_str(tm, buff);
792
 
  return net_store_data((unsigned char*) buff, length);
793
 
}
794
 
 
795
 
 
796
 
/**
797
 
  @todo 
798
 
    Second_part format ("%06") needs to change when 
799
 
    we support 0-6 decimals for time.
800
 
*/
801
 
 
802
 
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
803
 
{
804
 
  char buff[40];
805
 
  uint32_t length;
806
 
  uint32_t day= (tm->year || tm->month) ? 0 : tm->day;
807
 
  length= sprintf(buff, "%s%02ld:%02d:%02d",
808
 
                           tm->neg ? "-" : "",
809
 
                           (long) day*24L+(long) tm->hour,
810
 
                           (int) tm->minute,
811
 
                           (int) tm->second);
812
 
  if (tm->second_part)
813
 
    length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
814
 
  return net_store_data((unsigned char*) buff, length);
815
 
}
816
 
 
 
610
    Second_part format ("%06") needs to change when
 
611
    we support 0-6 decimals for time.
 
612
*/
 
613
 
 
614
bool ClientOldLibdrizzle::store(const DRIZZLE_TIME *tm)
 
615
{
 
616
  char buff[40];
 
617
  uint32_t length;
 
618
  uint32_t day;
 
619
 
 
620
  switch (tm->time_type)
 
621
  {
 
622
  case DRIZZLE_TIMESTAMP_DATETIME:
 
623
    length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
 
624
                    (int) tm->year,
 
625
                    (int) tm->month,
 
626
                    (int) tm->day,
 
627
                    (int) tm->hour,
 
628
                    (int) tm->minute,
 
629
                    (int) tm->second);
 
630
    if (tm->second_part)
 
631
      length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
 
632
    break;
 
633
 
 
634
  case DRIZZLE_TIMESTAMP_DATE:
 
635
    length= sprintf(buff, "%04d-%02d-%02d",
 
636
                    (int) tm->year,
 
637
                    (int) tm->month,
 
638
                    (int) tm->day);
 
639
    break;
 
640
 
 
641
  case DRIZZLE_TIMESTAMP_TIME:
 
642
    day= (tm->year || tm->month) ? 0 : tm->day;
 
643
    length= sprintf(buff, "%s%02ld:%02d:%02d", tm->neg ? "-" : "",
 
644
                    (long) day*24L+(long) tm->hour, (int) tm->minute,
 
645
                    (int) tm->second);
 
646
    if (tm->second_part)
 
647
      length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
 
648
    break;
 
649
 
 
650
  case DRIZZLE_TIMESTAMP_NONE:
 
651
  case DRIZZLE_TIMESTAMP_ERROR:
 
652
  default:
 
653
    assert(0);
 
654
    return false;
 
655
  }
 
656
 
 
657
  return netStoreData((unsigned char*) buff, length);
 
658
}
 
659
 
 
660
bool ClientOldLibdrizzle::checkConnection(void)
 
661
{
 
662
  uint32_t pkt_len= 0;
 
663
  char *end;
 
664
  uint64_t rnd_tmp;
 
665
  const Query_id& local_query_id= Query_id::get_query_id();
 
666
  struct rand_struct rand;
 
667
 
 
668
  // TCP/IP connection
 
669
  {
 
670
    char ip[NI_MAXHOST];
 
671
    uint16_t port;
 
672
 
 
673
    if (drizzleclient_net_peer_addr(&net, ip, &port, NI_MAXHOST))
 
674
    {
 
675
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
676
      return false;
 
677
    }
 
678
 
 
679
    session->security_ctx.ip.assign(ip);
 
680
  }
 
681
  drizzleclient_net_keepalive(&net, true);
 
682
 
 
683
  uint32_t server_capabilites;
 
684
  {
 
685
    /* buff[] needs to big enough to hold the server_version variable */
 
686
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
 
687
 
 
688
    server_capabilites= CLIENT_BASIC_FLAGS;
 
689
 
 
690
#ifdef HAVE_COMPRESS
 
691
    server_capabilites|= CLIENT_COMPRESS;
 
692
#endif /* HAVE_COMPRESS */
 
693
 
 
694
    end= buff + strlen(VERSION);
 
695
    if ((end - buff) >= SERVER_VERSION_LENGTH)
 
696
      end= buff + (SERVER_VERSION_LENGTH - 1);
 
697
    memcpy(buff, VERSION, end - buff);
 
698
    *end= 0;
 
699
    end++;
 
700
 
 
701
    int4store((unsigned char*) end, global_thread_id);
 
702
    end+= 4;
 
703
    /*
 
704
      So as _checkConnection is the only entry point to authorization
 
705
      procedure, scramble is set here. This gives us new scramble for
 
706
      each handshake.
 
707
    */
 
708
    rnd_tmp= sql_rnd();
 
709
    drizzleclient_randominit(&rand, rnd_tmp + (uint64_t) &session,
 
710
                             rnd_tmp + (uint64_t)local_query_id.value());
 
711
    drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
 
712
    /*
 
713
      Old clients does not understand long scrambles, but can ignore packet
 
714
      tail: that's why first part of the scramble is placed here, and second
 
715
      part at the end of packet.
 
716
    */
 
717
    end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
 
718
    end+= SCRAMBLE_LENGTH_323;
 
719
 
 
720
    *end++= 0; /* an empty byte for some reason */
 
721
 
 
722
    int2store(end, server_capabilites);
 
723
    /* write server characteristics: up to 16 bytes allowed */
 
724
    end[2]=(char) default_charset_info->number;
 
725
    int2store(end+3, session->server_status);
 
726
    memset(end+5, 0, 13);
 
727
    end+= 18;
 
728
    /* write scramble tail */
 
729
    size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
 
730
    end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
 
731
    end+= scramble_len;
 
732
 
 
733
    *end++= 0; /* an empty byte for some reason */
 
734
 
 
735
    /* At this point we write connection message and read reply */
 
736
    if (drizzleclient_net_write_command(&net
 
737
          , (unsigned char) PROTOCOL_VERSION
 
738
          , (unsigned char*) ""
 
739
          , 0
 
740
          , (unsigned char*) buff
 
741
          , (size_t) (end-buff)) 
 
742
        ||    (pkt_len= drizzleclient_net_read(&net)) == packet_error 
 
743
        || pkt_len < MIN_HANDSHAKE_SIZE)
 
744
    {
 
745
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
746
      return false;
 
747
    }
 
748
  }
 
749
  if (session->packet.alloc(session->variables.net_buffer_length))
 
750
    return false; /* The error is set by alloc(). */
 
751
 
 
752
  client_capabilities= uint2korr(net.read_pos);
 
753
 
 
754
 
 
755
  client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
 
756
  session->max_client_packet_length= uint4korr(net.read_pos + 4);
 
757
  end= (char*) net.read_pos + 32;
 
758
 
 
759
  /*
 
760
    Disable those bits which are not supported by the server.
 
761
    This is a precautionary measure, if the client lies. See Bug#27944.
 
762
  */
 
763
  client_capabilities&= server_capabilites;
 
764
 
 
765
  if (end >= (char*) net.read_pos + pkt_len + 2)
 
766
  {
 
767
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
768
    return false;
 
769
  }
 
770
 
 
771
  net.return_status= &session->server_status;
 
772
 
 
773
  char *user= end;
 
774
  char *passwd= strchr(user, '\0')+1;
 
775
  uint32_t user_len= passwd - user - 1;
 
776
  char *l_db= passwd;
 
777
 
 
778
  /*
 
779
    Old clients send null-terminated string as password; new clients send
 
780
    the size (1 byte) + string (not null-terminated). Hence in case of empty
 
781
    password both send '\0'.
 
782
 
 
783
    This strlen() can't be easily deleted without changing client.
 
784
 
 
785
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
 
786
    *passwd > 127 and become 2**32-127+ after casting to uint.
 
787
  */
 
788
  uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
 
789
    (unsigned char)(*passwd++) : strlen(passwd);
 
790
  l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
 
791
 
 
792
  /* strlen() can't be easily deleted without changing client */
 
793
  uint32_t db_len= l_db ? strlen(l_db) : 0;
 
794
 
 
795
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
 
796
  {
 
797
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
798
    return false;
 
799
  }
 
800
 
 
801
  /* If username starts and ends in "'", chop them off */
 
802
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
 
803
  {
 
804
    user[user_len-1]= 0;
 
805
    user++;
 
806
    user_len-= 2;
 
807
  }
 
808
 
 
809
  session->security_ctx.user.assign(user);
 
810
 
 
811
  return session->checkUser(passwd, passwd_len, l_db);
 
812
}
 
813
 
 
814
static ListenOldLibdrizzle listen_obj;
 
815
 
 
816
static int init(drizzled::plugin::Registry &registry)
 
817
{
 
818
  registry.listen.add(listen_obj); 
 
819
  return 0;
 
820
}
 
821
 
 
822
static int deinit(drizzled::plugin::Registry &registry)
 
823
{
 
824
  registry.listen.remove(listen_obj);
 
825
  return 0;
 
826
}
 
827
 
 
828
static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
 
829
                           PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
 
830
                           NULL, NULL, 10, 1, 300, 0);
 
831
static DRIZZLE_SYSVAR_UINT(read_timeout, read_timeout, PLUGIN_VAR_RQCMDARG,
 
832
                           N_("Read Timeout."), NULL, NULL, 30, 1, 300, 0);
 
833
static DRIZZLE_SYSVAR_UINT(write_timeout, write_timeout, PLUGIN_VAR_RQCMDARG,
 
834
                           N_("Write Timeout."), NULL, NULL, 60, 1, 300, 0);
 
835
static DRIZZLE_SYSVAR_UINT(retry_count, retry_count, PLUGIN_VAR_RQCMDARG,
 
836
                           N_("Retry Count."), NULL, NULL, 10, 1, 100, 0);
 
837
 
 
838
static struct st_mysql_sys_var* system_variables[]= {
 
839
  DRIZZLE_SYSVAR(connect_timeout),
 
840
  DRIZZLE_SYSVAR(read_timeout),
 
841
  DRIZZLE_SYSVAR(write_timeout),
 
842
  DRIZZLE_SYSVAR(retry_count),
 
843
  NULL
 
844
};
 
845
 
 
846
drizzle_declare_plugin(oldlibdrizzle)
 
847
{
 
848
  "oldlibdrizzle",
 
849
  "0.1",
 
850
  "Eric Day",
 
851
  "Old libdrizzle Client",
 
852
  PLUGIN_LICENSE_GPL,
 
853
  init,             /* Plugin Init */
 
854
  deinit,           /* Plugin Deinit */
 
855
  NULL,             /* status variables */
 
856
  system_variables, /* system variables */
 
857
  NULL              /* config options */
 
858
}
 
859
drizzle_declare_plugin_end;