~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/oldlibdrizzle/oldlibdrizzle.cc

  • Committer: Monty Taylor
  • Date: 2009-06-08 13:39:05 UTC
  • mto: This revision was merged to the branch mainline in revision 1060.
  • Revision ID: mordred@inaugust.com-20090608133905-3hogrrafmfg6e5hs
Removed CHARSET_INFO stuff from protocol plugin interface - it makes no sense.

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 */
 
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
 */
15
19
 
16
20
/**
17
21
  @file
19
23
  Low level functions for storing data to be send to the MySQL client.
20
24
  The actual communction is handled by the net_xxx functions in net_serv.cc
21
25
*/
 
26
 
22
27
#include <drizzled/server_includes.h>
23
 
#include <drizzled/drizzled_error_messages.h>
 
28
#include <drizzled/error.h>
24
29
#include <drizzled/sql_state.h>
 
30
#include <drizzled/protocol.h>
 
31
#include <drizzled/session.h>
 
32
#include <drizzled/data_home.h>
 
33
#include "pack.h"
 
34
#include "errmsg.h"
 
35
#include "oldlibdrizzle.h"
 
36
 
 
37
/*
 
38
  Function called by drizzleclient_net_init() to set some check variables
 
39
*/
25
40
 
26
41
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,
 
42
 
 
43
static void write_eof_packet(Session *session, NET *net,
30
44
                             uint32_t server_status, uint32_t total_warn_count);
31
45
 
32
 
bool Protocol::net_store_data(const unsigned char *from, size_t length)
33
 
{
34
 
  ulong packet_length=packet->length();
35
 
  /* 
 
46
bool ProtocolOldLibdrizzle::isConnected()
 
47
{
 
48
  return net.vio != 0;
 
49
}
 
50
 
 
51
void ProtocolOldLibdrizzle::setReadTimeout(uint32_t timeout)
 
52
{
 
53
  drizzleclient_net_set_read_timeout(&net, timeout);
 
54
}
 
55
 
 
56
void ProtocolOldLibdrizzle::setWriteTimeout(uint32_t timeout)
 
57
{
 
58
  drizzleclient_net_set_write_timeout(&net, timeout);
 
59
}
 
60
 
 
61
void ProtocolOldLibdrizzle::setRetryCount(uint32_t count)
 
62
{
 
63
  net.retry_count=count;
 
64
}
 
65
 
 
66
void ProtocolOldLibdrizzle::setError(char error)
 
67
{
 
68
  net.error= error;
 
69
}
 
70
 
 
71
bool ProtocolOldLibdrizzle::haveError(void)
 
72
{
 
73
  return net.error || net.vio == 0;
 
74
}
 
75
 
 
76
bool ProtocolOldLibdrizzle::wasAborted(void)
 
77
{
 
78
  return net.error && net.vio != 0;
 
79
}
 
80
 
 
81
bool ProtocolOldLibdrizzle::haveMoreData(void)
 
82
{
 
83
  return drizzleclient_net_more_data(&net);
 
84
}
 
85
 
 
86
void ProtocolOldLibdrizzle::enableCompression(void)
 
87
{
 
88
  net.compress= true;
 
89
}
 
90
 
 
91
bool ProtocolOldLibdrizzle::isReading(void)
 
92
{
 
93
  return net.reading_or_writing == 1;
 
94
}
 
95
 
 
96
bool ProtocolOldLibdrizzle::isWriting(void)
 
97
{
 
98
  return net.reading_or_writing == 2;
 
99
}
 
100
 
 
101
bool ProtocolOldLibdrizzle::netStoreData(const unsigned char *from, size_t length)
 
102
{
 
103
  size_t packet_length= packet->length();
 
104
  /*
36
105
     The +9 comes from that strings of length longer than 16M require
37
 
     9 bytes to be stored (see net_store_length).
 
106
     9 bytes to be stored (see drizzleclient_net_store_length).
38
107
  */
39
108
  if (packet_length+9+length > packet->alloced_length() &&
40
109
      packet->realloc(packet_length+9+length))
41
110
    return 1;
42
 
  unsigned char *to= net_store_length((unsigned char*) packet->ptr()+packet_length, length);
 
111
  unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet->ptr()+packet_length, length);
43
112
  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
 
}
 
113
  packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
 
114
  return 0;
 
115
}
 
116
 
136
117
 
137
118
/**
138
119
  Return ok to the client.
140
121
  The ok packet has the following structure:
141
122
 
142
123
  - 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
 
124
  - affected_rows    : Stored in 1-9 bytes
 
125
  - id        : Stored in 1-9 bytes
 
126
  - server_status    : Copy of session->server_status;  Can be used by client
146
127
  to check if we are inside an transaction.
147
128
  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
  - warning_count    : Stored in 2 bytes; New in 4.1 protocol
 
130
  - message        : Stored as packed length (1-9 bytes) + message.
150
131
  Is not stored if no message.
151
132
 
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)
 
133
  @param session           Thread handler
 
134
  @param affected_rows       Number of rows changed by statement
 
135
  @param id           Auto_increment id for first row (if used)
 
136
  @param message       Message to send to the client (Used by mysql_status)
156
137
*/
157
138
 
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)
 
139
void ProtocolOldLibdrizzle::sendOK()
162
140
{
163
 
  NET *net= &thd->net;
164
141
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
 
142
  const char *message= NULL;
 
143
  uint32_t tmp;
165
144
 
166
 
  if (! net->vio)       // hack for re-parsing queries
 
145
  if (!net.vio)    // hack for re-parsing queries
167
146
  {
168
147
    return;
169
148
  }
170
149
 
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;
 
150
  buff[0]=0;                    // No fields
 
151
  if (session->main_da.status() == Diagnostics_area::DA_OK)
 
152
  {
 
153
    pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
 
154
    pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
 
155
    int2store(pos, session->main_da.server_status());
 
156
    pos+=2;
 
157
    tmp= cmin(session->main_da.total_warn_count(), (uint32_t)65535);
 
158
    message= session->main_da.message();
 
159
  }
 
160
  else
 
161
  {
 
162
    pos=drizzleclient_net_store_length(buff+1,0);
 
163
    pos=drizzleclient_net_store_length(pos, 0);
 
164
    int2store(pos, session->server_status);
 
165
    pos+=2;
 
166
    tmp= cmin(session->total_warn_count, (uint32_t)65535);
 
167
  }
177
168
 
178
169
  /* We can only return up to 65535 warnings in two bytes */
179
 
  uint32_t tmp= cmin(total_warn_count, (uint)65535);
180
170
  int2store(pos, tmp);
181
171
  pos+= 2;
182
172
 
183
 
  thd->main_da.can_overwrite_status= true;
 
173
  session->main_da.can_overwrite_status= true;
184
174
 
185
175
  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);
 
176
  {
 
177
    size_t length= strlen(message);
 
178
    pos=drizzleclient_net_store_length(pos,length);
 
179
    memcpy(pos,(unsigned char*) message,length);
 
180
    pos+=length;
 
181
  }
 
182
  drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
 
183
  drizzleclient_net_flush(&net);
189
184
 
190
 
  thd->main_da.can_overwrite_status= false;
 
185
  session->main_da.can_overwrite_status= false;
191
186
}
192
187
 
193
188
/**
195
190
 
196
191
  The eof packet has the following structure:
197
192
 
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;
 
193
  - 254    (DRIZZLE_PROTOCOL_NO_MORE_DATA)    : Marker (1 byte)
 
194
  - warning_count    : Stored in 2 bytes; New in 4.1 protocol
 
195
  - status_flag    : Stored in 2 bytes;
201
196
  For flags like SERVER_MORE_RESULTS_EXISTS.
202
197
 
203
198
  Note that the warning count will not be sent if 'no_flush' is set as
204
199
  we don't want to report the warning count until all data is sent to the
205
200
  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)
 
201
*/
 
202
 
 
203
void ProtocolOldLibdrizzle::sendEOF()
214
204
{
215
 
  NET *net= &thd->net;
216
205
  /* Set to true if no active vio, to work well in case of --init-file */
217
 
  if (net->vio != 0)
 
206
  if (net.vio != 0)
218
207
  {
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;
 
208
    session->main_da.can_overwrite_status= true;
 
209
    write_eof_packet(session, &net, session->main_da.server_status(),
 
210
                     session->main_da.total_warn_count());
 
211
    drizzleclient_net_flush(&net);
 
212
    session->main_da.can_overwrite_status= false;
223
213
  }
224
214
}
225
215
 
229
219
  write it to the network output buffer.
230
220
*/
231
221
 
232
 
static void write_eof_packet(THD *thd, NET *net,
 
222
static void write_eof_packet(Session *session, NET *net,
233
223
                             uint32_t server_status,
234
224
                             uint32_t total_warn_count)
235
225
{
238
228
    Don't send warn count during SP execution, as the warn_list
239
229
    is cleared between substatements, and mysqltest gets confused
240
230
  */
241
 
  uint32_t tmp= cmin(total_warn_count, (uint)65535);
 
231
  uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
242
232
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
243
233
  int2store(buff+1, tmp);
244
234
  /*
246
236
    because if 'is_fatal_error' is set the server is not going to execute
247
237
    other queries (see the if test in dispatch_command / COM_QUERY)
248
238
  */
249
 
  if (thd->is_fatal_error)
 
239
  if (session->is_fatal_error)
250
240
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
251
241
  int2store(buff + 3, server_status);
252
 
  my_net_write(net, buff, 5);
 
242
  drizzleclient_net_write(net, buff, 5);
253
243
}
254
244
 
255
 
void net_send_error_packet(THD *thd, uint32_t sql_errno, const char *err)
 
245
void ProtocolOldLibdrizzle::sendError(uint32_t sql_errno, const char *err)
256
246
{
257
 
  NET *net= &thd->net;
258
247
  uint32_t length;
259
248
  /*
260
249
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
261
250
  */
262
251
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
263
252
 
264
 
  if (net->vio == 0)
 
253
  assert(sql_errno);
 
254
  assert(err && err[0]);
 
255
 
 
256
  /*
 
257
    It's one case when we can push an error even though there
 
258
    is an OK or EOF already.
 
259
  */
 
260
  session->main_da.can_overwrite_status= true;
 
261
 
 
262
  /* Abort multi-result sets */
 
263
  session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
264
 
 
265
  /**
 
266
    Send a error string to client.
 
267
 
 
268
    For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
 
269
    critical that every error that can be intercepted is issued in one
 
270
    place only, my_message_sql.
 
271
  */
 
272
 
 
273
  if (net.vio == 0)
265
274
  {
266
275
    return;
267
276
  }
271
280
 
272
281
  /* The first # is to make the protocol backward compatible */
273
282
  buff[2]= '#';
274
 
  pos= (unsigned char*) my_stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
 
283
  pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
 
284
  pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
275
285
 
276
 
  length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
277
 
                  (char*) buff);
 
286
  char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
 
287
  tmp+= strlen((char*)pos);
 
288
  tmp[0]= '\0';
 
289
  length= (uint32_t)(tmp-(char*)buff);
278
290
  err= (char*) buff;
279
291
 
280
 
  net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
281
 
  return;
282
 
}
283
 
 
284
 
 
285
 
/**
286
 
  Faster net_store_length when we know that length is less than 65536.
287
 
  We keep a separate version for that range because it's widely used in
288
 
  libmysql.
289
 
 
290
 
  uint32_t is used as agrument type because of MySQL type conventions:
291
 
  - uint32_t for 0..65536
292
 
  - ulong for 0..4294967296
293
 
  - uint64_t for bigger numbers.
294
 
*/
295
 
 
296
 
static unsigned char *net_store_length_fast(unsigned char *packet, uint32_t length)
297
 
{
298
 
  if (length < 251)
299
 
  {
300
 
    *packet=(unsigned char) length;
301
 
    return packet+1;
302
 
  }
303
 
  *packet++=252;
304
 
  int2store(packet,(uint) length);
305
 
  return packet+2;
306
 
}
307
 
 
308
 
/**
309
 
  Send the status of the current statement execution over network.
310
 
 
311
 
  @param  thd   in fact, carries two parameters, NET for the transport and
312
 
                Diagnostics_area as the source of status information.
313
 
 
314
 
  In MySQL, there are two types of SQL statements: those that return
315
 
  a result set and those that return status information only.
316
 
 
317
 
  If a statement returns a result set, it consists of 3 parts:
318
 
  - result set meta-data
319
 
  - variable number of result set rows (can be 0)
320
 
  - followed and terminated by EOF or ERROR packet
321
 
 
322
 
  Once the  client has seen the meta-data information, it always
323
 
  expects an EOF or ERROR to terminate the result set. If ERROR is
324
 
  received, the result set rows are normally discarded (this is up
325
 
  to the client implementation, libmysql at least does discard them).
326
 
  EOF, on the contrary, means "successfully evaluated the entire
327
 
  result set". Since we don't know how many rows belong to a result
328
 
  set until it's evaluated, EOF/ERROR is the indicator of the end
329
 
  of the row stream. Note, that we can not buffer result set rows
330
 
  on the server -- there may be an arbitrary number of rows. But
331
 
  we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
332
 
  delay sending it till the very end of execution (here), to be able to
333
 
  change EOF to an ERROR if commit failed or some other error occurred
334
 
  during the last cleanup steps taken after execution.
335
 
 
336
 
  A statement that does not return a result set doesn't send result
337
 
  set meta-data either. Instead it returns one of:
338
 
  - OK packet
339
 
  - ERROR packet.
340
 
  Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
341
 
  packet is "buffered" in the diagnostics area and sent to the client
342
 
  in the end of statement.
343
 
 
344
 
  @pre  The diagnostics area is assigned or disabled. It can not be empty
345
 
        -- we assume that every SQL statement or COM_* command
346
 
        generates OK, ERROR, or EOF status.
347
 
 
348
 
  @post The status information is encoded to protocol format and sent to the
349
 
        client.
350
 
 
351
 
  @return We conventionally return void, since the only type of error
352
 
          that can happen here is a NET (transport) error, and that one
353
 
          will become visible when we attempt to read from the NET the
354
 
          next command.
355
 
          Diagnostics_area::is_sent is set for debugging purposes only.
356
 
*/
357
 
 
358
 
void net_end_statement(THD *thd)
359
 
{
360
 
  assert(! thd->main_da.is_sent);
361
 
 
362
 
  /* Can not be true, but do not take chances in production. */
363
 
  if (thd->main_da.is_sent)
364
 
    return;
365
 
 
366
 
  switch (thd->main_da.status()) {
367
 
  case Diagnostics_area::DA_ERROR:
368
 
    /* The query failed, send error to log and abort bootstrap. */
369
 
    net_send_error(thd,
370
 
                   thd->main_da.sql_errno(),
371
 
                   thd->main_da.message());
372
 
    break;
373
 
  case Diagnostics_area::DA_EOF:
374
 
    net_send_eof(thd,
375
 
                 thd->main_da.server_status(),
376
 
                 thd->main_da.total_warn_count());
377
 
    break;
378
 
  case Diagnostics_area::DA_OK:
379
 
    net_send_ok(thd,
380
 
                thd->main_da.server_status(),
381
 
                thd->main_da.total_warn_count(),
382
 
                thd->main_da.affected_rows(),
383
 
                thd->main_da.last_insert_id(),
384
 
                thd->main_da.message());
385
 
    break;
386
 
  case Diagnostics_area::DA_DISABLED:
387
 
    break;
388
 
  case Diagnostics_area::DA_EMPTY:
389
 
  default:
390
 
    assert(0);
391
 
    net_send_ok(thd, thd->server_status, thd->total_warn_count,
392
 
                0, 0, NULL);
393
 
    break;
394
 
  }
395
 
  thd->main_da.is_sent= true;
396
 
}
397
 
 
398
 
 
399
 
/****************************************************************************
400
 
  Functions used by the protocol functions (like net_send_ok) to store
401
 
  strings and numbers in the header result packet.
402
 
****************************************************************************/
403
 
 
404
 
/* The following will only be used for short strings < 65K */
405
 
 
406
 
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
407
 
{
408
 
  to=net_store_length_fast(to,length);
409
 
  memcpy(to,from,length);
410
 
  return to+length;
411
 
}
412
 
 
413
 
unsigned char *net_store_data(unsigned char *to,int32_t from)
414
 
{
415
 
  char buff[20];
416
 
  uint32_t length=(uint) (int10_to_str(from,buff,10)-buff);
417
 
  to=net_store_length_fast(to,length);
418
 
  memcpy(to,buff,length);
419
 
  return to+length;
420
 
}
421
 
 
422
 
unsigned char *net_store_data(unsigned char *to,int64_t from)
423
 
{
424
 
  char buff[22];
425
 
  uint32_t length=(uint) (int64_t10_to_str(from,buff,10)-buff);
426
 
  to=net_store_length_fast(to,length);
427
 
  memcpy(to,buff,length);
428
 
  return to+length;
429
 
}
430
 
 
431
 
 
432
 
/*****************************************************************************
433
 
  Default Protocol functions
434
 
*****************************************************************************/
435
 
 
436
 
void Protocol::init(THD *thd_arg)
437
 
{
438
 
  thd=thd_arg;
439
 
  packet= &thd->packet;
440
 
  convert= &thd->convert_buffer;
441
 
}
442
 
 
443
 
/**
444
 
  Finish the result set with EOF packet, as is expected by the client,
445
 
  if there is an error evaluating the next row and a continue handler
446
 
  for the error.
447
 
*/
448
 
 
449
 
void Protocol::end_partial_result_set(THD *thd)
450
 
{
451
 
  net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
452
 
}
453
 
 
454
 
 
455
 
bool Protocol::flush()
456
 
{
457
 
  return net_flush(&thd->net);
 
292
  drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
 
293
 
 
294
  session->main_da.can_overwrite_status= false;
 
295
}
 
296
 
 
297
 
 
298
ProtocolOldLibdrizzle::ProtocolOldLibdrizzle()
 
299
{
 
300
  scramble[0]= 0;
 
301
  net.vio= 0;
 
302
}
 
303
 
 
304
void ProtocolOldLibdrizzle::setSession(Session *session_arg)
 
305
{
 
306
  session= session_arg;
 
307
  packet= &session->packet;
 
308
  convert= &session->convert_buffer;
458
309
}
459
310
 
460
311
 
463
314
 
464
315
  Sum fields has table name empty and field_name.
465
316
 
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:
 
317
  @param Session        Thread data object
 
318
  @param list            List of items to send to client
 
319
  @param flag            Bit mask with the following functions:
469
320
                        - 1 send number of rows
470
321
                        - 2 send default values
471
322
                        - 4 don't write eof packet
472
323
 
473
324
  @retval
474
 
    0   ok
 
325
    0    ok
475
326
  @retval
476
 
    1   Error  (Note that in this case the error is not sent to the
 
327
    1    Error  (Note that in this case the error is not sent to the
477
328
    client)
478
329
*/
479
 
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
 
330
bool ProtocolOldLibdrizzle::sendFields(List<Item> *list, uint32_t flags)
480
331
{
481
332
  List_iterator_fast<Item> it(*list);
482
333
  Item *item;
483
334
  unsigned char buff[80];
484
335
  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
336
 
489
337
  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));
 
338
  {                // Packet with number of elements
 
339
    unsigned char *pos= drizzleclient_net_store_length(buff, list->elements);
 
340
    (void) drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
493
341
  }
494
342
 
495
343
  while ((item=it++))
496
344
  {
497
345
    char *pos;
498
 
    const CHARSET_INFO * const cs= system_charset_info;
499
346
    Send_field field;
500
347
    item->make_field(&field);
501
348
 
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))
 
349
    prepareForResend();
 
350
 
 
351
    if (store(STRING_WITH_LEN("def")) ||
 
352
        store(field.db_name) ||
 
353
        store(field.table_name) ||
 
354
        store(field.org_table_name) ||
 
355
        store(field.col_name) ||
 
356
        store(field.org_col_name) ||
 
357
        packet->realloc(packet->length()+12))
517
358
      goto err;
518
359
 
519
360
    /* 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
 
    }
 
361
    pos= (char*) packet->ptr()+packet->length();
 
362
    *pos++= 12;                // Length of packed fields
 
363
    /* No conversion */
 
364
    int2store(pos, field.charsetnr);
 
365
    int4store(pos+2, field.length);
546
366
    pos[6]= field.type;
547
367
    int2store(pos+7,field.flags);
548
368
    pos[9]= (char) field.decimals;
549
 
    pos[10]= 0;                         // For the future
550
 
    pos[11]= 0;                         // For the future
 
369
    pos[10]= 0;                // For the future
 
370
    pos[11]= 0;                // For the future
551
371
    pos+= 12;
552
372
 
553
 
    local_packet->length((uint) (pos - local_packet->ptr()));
 
373
    packet->length((uint32_t) (pos - packet->ptr()));
554
374
    if (flags & SEND_DEFAULTS)
555
 
      item->send(&prot, &tmp);                  // Send default value
556
 
    if (prot.write())
557
 
      break;                                    /* purecov: inspected */
 
375
      item->send(this, &tmp);            // Send default value
 
376
    if (write())
 
377
      break;                    /* purecov: inspected */
558
378
  }
559
379
 
560
380
  if (flags & SEND_EOF)
561
381
  {
562
382
    /*
563
 
      Mark the end of meta-data result set, and store thd->server_status,
 
383
      Mark the end of meta-data result set, and store session->server_status,
564
384
      to show that there is no cursor.
565
385
      Send no warning information, as it will be sent at statement end.
566
386
    */
567
 
    write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
 
387
    write_eof_packet(session, &net, session->server_status, session->total_warn_count);
568
388
  }
569
 
  return(prepare_for_send(list));
 
389
 
 
390
  field_count= list->elements;
 
391
  return 0;
570
392
 
571
393
err:
572
394
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
573
 
             MYF(0));   /* purecov: inspected */
574
 
  return(1);                            /* purecov: inspected */
 
395
             MYF(0));    /* purecov: inspected */
 
396
  return 1;                /* purecov: inspected */
575
397
}
576
398
 
577
399
 
578
 
bool Protocol::write()
 
400
bool ProtocolOldLibdrizzle::write()
579
401
{
580
 
  return(my_net_write(&thd->net, (unsigned char*) packet->ptr(),
 
402
  return(drizzleclient_net_write(&net, (unsigned char*) packet->ptr(),
581
403
                           packet->length()));
582
404
}
583
405
 
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()
 
406
void ProtocolOldLibdrizzle::free()
 
407
{
 
408
  packet->free();
 
409
}
 
410
 
 
411
 
 
412
void ProtocolOldLibdrizzle::setRandom(uint64_t seed1, uint64_t seed2)
 
413
{
 
414
  drizzleclient_randominit(&rand, seed1, seed2);
 
415
}
 
416
 
 
417
bool ProtocolOldLibdrizzle::setFileDescriptor(int fd)
 
418
{
 
419
  if (drizzleclient_net_init_sock(&net, fd, 0))
 
420
    return true;
 
421
  return false;
 
422
}
 
423
 
 
424
int ProtocolOldLibdrizzle::fileDescriptor(void)
 
425
{
 
426
  return drizzleclient_net_get_sd(&net);
 
427
}
 
428
 
 
429
bool ProtocolOldLibdrizzle::authenticate()
 
430
{
 
431
  bool connection_is_valid;
 
432
 
 
433
  /* Use "connect_timeout" value during connection phase */
 
434
  drizzleclient_net_set_read_timeout(&net, connect_timeout);
 
435
  drizzleclient_net_set_write_timeout(&net, connect_timeout);
 
436
 
 
437
  connection_is_valid= checkConnection();
 
438
 
 
439
  if (connection_is_valid)
 
440
    sendOK();
 
441
  else
 
442
  {
 
443
    sendError(session->main_da.sql_errno(), session->main_da.message());
 
444
    return false;
 
445
  }
 
446
 
 
447
  /* Connect completed, set read/write timeouts back to default */
 
448
  drizzleclient_net_set_read_timeout(&net,
 
449
                                     session->variables.net_read_timeout);
 
450
  drizzleclient_net_set_write_timeout(&net,
 
451
                                      session->variables.net_write_timeout);
 
452
  return true;
 
453
}
 
454
 
 
455
bool ProtocolOldLibdrizzle::readCommand(char **l_packet, uint32_t *packet_length)
 
456
{
 
457
  /*
 
458
    This thread will do a blocking read from the client which
 
459
    will be interrupted when the next command is received from
 
460
    the client, the connection is closed or "net_wait_timeout"
 
461
    number of seconds has passed
 
462
  */
 
463
#ifdef NEVER
 
464
  /* We can do this much more efficiently with poll timeouts or watcher thread,
 
465
     disabling for now, which means net_wait_timeout == read_timeout. */
 
466
  drizzleclient_net_set_read_timeout(&net,
 
467
                                     session->variables.net_wait_timeout);
 
468
#endif
 
469
 
 
470
  session->clear_error();
 
471
  session->main_da.reset_diagnostics_area();
 
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
      session->protocol->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 ProtocolOldLibdrizzle::close(void)
 
526
{
 
527
  if (net.vio)
 
528
  { 
 
529
    drizzleclient_net_close(&net);
 
530
    drizzleclient_net_end(&net);
 
531
  }
 
532
}
 
533
 
 
534
void ProtocolOldLibdrizzle::forceClose(void)
 
535
{
 
536
  if (net.vio)
 
537
    drizzleclient_vio_close(net.vio);
 
538
}
 
539
 
 
540
void ProtocolOldLibdrizzle::prepareForResend()
641
541
{
642
542
  packet->length(0);
643
543
}
644
544
 
645
 
bool Protocol_text::store_null()
 
545
bool ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::store(const char *from, size_t length)
 
554
{
 
555
  return netStoreData((const unsigned char *)from, length);
 
556
}
 
557
 
 
558
 
 
559
bool ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::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 ProtocolOldLibdrizzle::checkConnection(void)
 
661
{
 
662
  uint32_t pkt_len= 0;
 
663
  char *end;
 
664
 
 
665
  // TCP/IP connection
 
666
  {
 
667
    char ip[NI_MAXHOST];
 
668
 
 
669
    if (drizzleclient_net_peer_addr(&net, ip, &session->peer_port, NI_MAXHOST))
 
670
    {
 
671
      my_error(ER_BAD_HOST_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
672
      return false;
 
673
    }
 
674
 
 
675
    session->security_ctx.ip.assign(ip);
 
676
  }
 
677
  drizzleclient_net_keepalive(&net, true);
 
678
 
 
679
  uint32_t server_capabilites;
 
680
  {
 
681
    /* buff[] needs to big enough to hold the server_version variable */
 
682
    char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
 
683
 
 
684
    server_capabilites= CLIENT_BASIC_FLAGS;
 
685
 
 
686
#ifdef HAVE_COMPRESS
 
687
    server_capabilites|= CLIENT_COMPRESS;
 
688
#endif /* HAVE_COMPRESS */
 
689
 
 
690
    end= buff + strlen(server_version);
 
691
    if ((end - buff) >= SERVER_VERSION_LENGTH)
 
692
      end= buff + (SERVER_VERSION_LENGTH - 1);
 
693
    memcpy(buff, server_version, end - buff);
 
694
    *end= 0;
 
695
    end++;
 
696
 
 
697
    int4store((unsigned char*) end, thread_id);
 
698
    end+= 4;
 
699
    /*
 
700
      So as _checkConnection is the only entry point to authorization
 
701
      procedure, scramble is set here. This gives us new scramble for
 
702
      each handshake.
 
703
    */
 
704
    drizzleclient_create_random_string(scramble, SCRAMBLE_LENGTH, &rand);
 
705
    /*
 
706
      Old clients does not understand long scrambles, but can ignore packet
 
707
      tail: that's why first part of the scramble is placed here, and second
 
708
      part at the end of packet.
 
709
    */
 
710
    end= strncpy(end, scramble, SCRAMBLE_LENGTH_323);
 
711
    end+= SCRAMBLE_LENGTH_323;
 
712
 
 
713
    *end++= 0; /* an empty byte for some reason */
 
714
 
 
715
    int2store(end, server_capabilites);
 
716
    /* write server characteristics: up to 16 bytes allowed */
 
717
    end[2]=(char) default_charset_info->number;
 
718
    int2store(end+3, session->server_status);
 
719
    memset(end+5, 0, 13);
 
720
    end+= 18;
 
721
    /* write scramble tail */
 
722
    size_t scramble_len= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
 
723
    end= strncpy(end, scramble + SCRAMBLE_LENGTH_323, scramble_len);
 
724
    end+= scramble_len;
 
725
 
 
726
    *end++= 0; /* an empty byte for some reason */
 
727
 
 
728
    /* At this point we write connection message and read reply */
 
729
    if (drizzleclient_net_write_command(&net
 
730
          , (unsigned char) protocol_version
 
731
          , (unsigned char*) ""
 
732
          , 0
 
733
          , (unsigned char*) buff
 
734
          , (size_t) (end-buff)) 
 
735
        ||    (pkt_len= drizzleclient_net_read(&net)) == packet_error 
 
736
        || pkt_len < MIN_HANDSHAKE_SIZE)
 
737
    {
 
738
      my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
739
      return false;
 
740
    }
 
741
  }
 
742
  if (session->packet.alloc(session->variables.net_buffer_length))
 
743
    return false; /* The error is set by alloc(). */
 
744
 
 
745
  session->client_capabilities= uint2korr(net.read_pos);
 
746
 
 
747
 
 
748
  session->client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
 
749
  session->max_client_packet_length= uint4korr(net.read_pos + 4);
 
750
  session->update_charset();
 
751
  end= (char*) net.read_pos + 32;
 
752
 
 
753
  /*
 
754
    Disable those bits which are not supported by the server.
 
755
    This is a precautionary measure, if the client lies. See Bug#27944.
 
756
  */
 
757
  session->client_capabilities&= server_capabilites;
 
758
 
 
759
  if (end >= (char*) net.read_pos + pkt_len + 2)
 
760
  {
 
761
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
762
    return false;
 
763
  }
 
764
 
 
765
  net.return_status= &session->server_status;
 
766
 
 
767
  char *user= end;
 
768
  char *passwd= strchr(user, '\0')+1;
 
769
  uint32_t user_len= passwd - user - 1;
 
770
  char *l_db= passwd;
 
771
  char db_buff[NAME_LEN + 1];           // buffer to store db in utf8
 
772
  char user_buff[USERNAME_LENGTH + 1];    // buffer to store user in utf8
 
773
  uint32_t dummy_errors;
 
774
 
 
775
  /*
 
776
    Old clients send null-terminated string as password; new clients send
 
777
    the size (1 byte) + string (not null-terminated). Hence in case of empty
 
778
    password both send '\0'.
 
779
 
 
780
    This strlen() can't be easily deleted without changing protocol.
 
781
 
 
782
    Cast *passwd to an unsigned char, so that it doesn't extend the sign for
 
783
    *passwd > 127 and become 2**32-127+ after casting to uint.
 
784
  */
 
785
  uint32_t passwd_len= session->client_capabilities & CLIENT_SECURE_CONNECTION ?
 
786
    (unsigned char)(*passwd++) : strlen(passwd);
 
787
  l_db= session->client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
 
788
 
 
789
  /* strlen() can't be easily deleted without changing protocol */
 
790
  uint32_t db_len= l_db ? strlen(l_db) : 0;
 
791
 
 
792
  if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
 
793
  {
 
794
    my_error(ER_HANDSHAKE_ERROR, MYF(0), session->security_ctx.ip.c_str());
 
795
    return false;
 
796
  }
 
797
 
 
798
  /* Since 4.1 all database names are stored in utf8 */
 
799
  if (l_db)
 
800
  {
 
801
    db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
 
802
                             system_charset_info,
 
803
                             l_db, db_len,
 
804
                             session->charset(), &dummy_errors)]= 0;
 
805
    l_db= db_buff;
 
806
  }
 
807
 
 
808
  user_buff[user_len= copy_and_convert(user_buff, sizeof(user_buff)-1,
 
809
                                       system_charset_info, user, user_len,
 
810
                                       session->charset(), &dummy_errors)]= '\0';
 
811
  user= user_buff;
 
812
 
 
813
  /* If username starts and ends in "'", chop them off */
 
814
  if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
 
815
  {
 
816
    user[user_len-1]= 0;
 
817
    user++;
 
818
    user_len-= 2;
 
819
  }
 
820
 
 
821
  session->security_ctx.user.assign(user);
 
822
 
 
823
  return session->checkUser(passwd, passwd_len, l_db);
 
824
}
 
825
 
 
826
static ProtocolFactoryOldLibdrizzle *factory= NULL;
 
827
 
 
828
static int init(PluginRegistry &registry)
 
829
{
 
830
  factory= new ProtocolFactoryOldLibdrizzle;
 
831
  registry.add(factory); 
 
832
  return 0;
 
833
}
 
834
 
 
835
static int deinit(PluginRegistry &registry)
 
836
{
 
837
  if (factory)
 
838
  {
 
839
    registry.remove(factory);
 
840
    delete factory;
 
841
  }
 
842
  return 0;
 
843
}
 
844
 
 
845
drizzle_declare_plugin(oldlibdrizzle)
 
846
{
 
847
  "oldlibdrizzle",
 
848
  "0.1",
 
849
  "Eric Day",
 
850
  "Old libdrizzle Protocol",
 
851
  PLUGIN_LICENSE_GPL,
 
852
  init,   /* Plugin Init */
 
853
  deinit, /* Plugin Deinit */
 
854
  NULL,   /* status variables */
 
855
  NULL,   /* system variables */
 
856
  NULL    /* config options */
 
857
}
 
858
drizzle_declare_plugin_end;