~drizzle-trunk/drizzle/development

1 by brian
clean slate
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
*/
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
22
#include <drizzled/server_includes.h>
549 by Monty Taylor
Took gettext.h out of header files.
23
#include <drizzled/error.h>
468 by Monty Taylor
Repaced sql_state stuff with template function and c++ algorithm.
24
#include <drizzled/sql_state.h>
779.3.37 by Monty Taylor
Renmaed libdrizzle in the tree to libdrizzleclient to avoid namespace clashes
25
#include <libdrizzleclient/pack.h>
584.1.15 by Monty Taylor
The mega-patch from hell. Renamed sql_class to session (since that's what it is) and removed it and field and table from common_includes.
26
#include <drizzled/protocol.h>
27
#include <drizzled/session.h>
1 by brian
clean slate
28
29
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
30
/* Declared non-static only because of the embedded library. */
520.1.22 by Brian Aker
Second pass of thd cleanup
31
static void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err);
32
static void write_eof_packet(Session *session, NET *net,
482 by Brian Aker
Remove uint.
33
                             uint32_t server_status, uint32_t total_warn_count);
1 by brian
clean slate
34
481 by Brian Aker
Remove all of uchar.
35
bool Protocol::net_store_data(const unsigned char *from, size_t length)
1 by brian
clean slate
36
{
628 by Brian Aker
Collection of dead code removal
37
  size_t packet_length= packet->length();
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
38
  /*
1 by brian
clean slate
39
     The +9 comes from that strings of length longer than 16M require
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
40
     9 bytes to be stored (see drizzleclient_net_store_length).
1 by brian
clean slate
41
  */
42
  if (packet_length+9+length > packet->alloced_length() &&
43
      packet->realloc(packet_length+9+length))
44
    return 1;
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
45
  unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet->ptr()+packet_length, length);
1 by brian
clean slate
46
  memcpy(to,from,length);
628 by Brian Aker
Collection of dead code removal
47
  packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
1 by brian
clean slate
48
  return 0;
49
}
50
51
52
53
54
/*
55
  net_store_data() - extended version with character set conversion.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
56
1 by brian
clean slate
57
  It is optimized for short strings whose length after
58
  conversion is garanteed to be less than 251, which accupies
59
  exactly one byte to store length. It allows not to use
60
  the "convert" member as a temporary buffer, conversion
61
  is done directly to the "packet" member.
62
  The limit 251 is good enough to optimize send_fields()
63
  because column, table, database names fit into this limit.
64
*/
65
481 by Brian Aker
Remove all of uchar.
66
bool Protocol::net_store_data(const unsigned char *from, size_t length,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
67
                              const CHARSET_INFO * const from_cs,
68
							  const CHARSET_INFO * const to_cs)
1 by brian
clean slate
69
{
482 by Brian Aker
Remove uint.
70
  uint32_t dummy_errors;
1 by brian
clean slate
71
  /* Calculate maxumum possible result length */
482 by Brian Aker
Remove uint.
72
  uint32_t conv_length= to_cs->mbmaxlen * length / from_cs->mbminlen;
1 by brian
clean slate
73
  if (conv_length > 250)
74
  {
75
    /*
76
      For strings with conv_length greater than 250 bytes
77
      we don't know how many bytes we will need to store length: one or two,
78
      because we don't know result length until conversion is done.
79
      For example, when converting from utf8 (mbmaxlen=3) to latin1,
80
      conv_length=300 means that the result length can vary between 100 to 300.
81
      length=100 needs one byte, length=300 needs to bytes.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
82
1 by brian
clean slate
83
      Thus conversion directly to "packet" is not worthy.
84
      Let's use "convert" as a temporary buffer.
85
    */
86
    return (convert->copy((const char*) from, length, from_cs,
87
                          to_cs, &dummy_errors) ||
481 by Brian Aker
Remove all of uchar.
88
            net_store_data((const unsigned char*) convert->ptr(), convert->length()));
1 by brian
clean slate
89
  }
90
628 by Brian Aker
Collection of dead code removal
91
  size_t packet_length= packet->length();
92
  size_t new_length= packet_length + conv_length + 1;
1 by brian
clean slate
93
94
  if (new_length > packet->alloced_length() && packet->realloc(new_length))
95
    return 1;
96
97
  char *length_pos= (char*) packet->ptr() + packet_length;
98
  char *to= length_pos + 1;
99
100
  to+= copy_and_convert(to, conv_length, to_cs,
101
                        (const char*) from, length, from_cs, &dummy_errors);
102
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
103
  drizzleclient_net_store_length((unsigned char*) length_pos, to - length_pos - 1);
895 by Brian Aker
Completion (?) of uint conversion.
104
  packet->length((uint32_t) (to - packet->ptr()));
1 by brian
clean slate
105
  return 0;
106
}
107
108
109
/**
110
  Send a error string to client.
111
112
  Design note:
113
  net_printf_error and net_send_error are low-level functions
114
  that shall be used only when a new connection is being
115
  established or at server startup.
116
117
  For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
118
  critical that every error that can be intercepted is issued in one
119
  place only, my_message_sql.
120
*/
520.1.22 by Brian Aker
Second pass of thd cleanup
121
void net_send_error(Session *session, uint32_t sql_errno, const char *err)
1 by brian
clean slate
122
{
51.1.76 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
123
  assert(sql_errno);
124
  assert(err && err[0]);
1 by brian
clean slate
125
126
  /*
127
    It's one case when we can push an error even though there
128
    is an OK or EOF already.
129
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
130
  session->main_da.can_overwrite_status= true;
1 by brian
clean slate
131
132
  /* Abort multi-result sets */
520.1.22 by Brian Aker
Second pass of thd cleanup
133
  session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
134
135
  net_send_error_packet(session, sql_errno, err);
136
137
  session->main_da.can_overwrite_status= false;
1 by brian
clean slate
138
}
139
140
/**
141
  Return ok to the client.
142
143
  The ok packet has the following structure:
144
145
  - 0               : Marker (1 byte)
146
  - affected_rows	: Stored in 1-9 bytes
147
  - id		: Stored in 1-9 bytes
520.1.22 by Brian Aker
Second pass of thd cleanup
148
  - server_status	: Copy of session->server_status;  Can be used by client
1 by brian
clean slate
149
  to check if we are inside an transaction.
150
  New in 4.0 protocol
151
  - warning_count	: Stored in 2 bytes; New in 4.1 protocol
152
  - message		: Stored as packed length (1-9 bytes) + message.
153
  Is not stored if no message.
154
520.1.22 by Brian Aker
Second pass of thd cleanup
155
  @param session		   Thread handler
1 by brian
clean slate
156
  @param affected_rows	   Number of rows changed by statement
157
  @param id		   Auto_increment id for first row (if used)
158
  @param message	   Message to send to the client (Used by mysql_status)
159
*/
160
202.1.17 by Monty Taylor
Patch from andrey - made some functions static as they are not used outside of protocol.cc.
161
static void
520.1.22 by Brian Aker
Second pass of thd cleanup
162
net_send_ok(Session *session,
482 by Brian Aker
Remove uint.
163
            uint32_t server_status, uint32_t total_warn_count,
151 by Brian Aker
Ulonglong to uint64_t
164
            ha_rows affected_rows, uint64_t id, const char *message)
1 by brian
clean slate
165
{
520.1.22 by Brian Aker
Second pass of thd cleanup
166
  NET *net= &session->net;
481 by Brian Aker
Remove all of uchar.
167
  unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
1 by brian
clean slate
168
169
  if (! net->vio)	// hack for re-parsing queries
170
  {
51.1.76 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
171
    return;
1 by brian
clean slate
172
  }
173
174
  buff[0]=0;					// No fields
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
175
  pos=drizzleclient_net_store_length(buff+1,affected_rows);
176
  pos=drizzleclient_net_store_length(pos, id);
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
177
178
  int2store(pos, server_status);
179
  pos+=2;
180
181
  /* We can only return up to 65535 warnings in two bytes */
895 by Brian Aker
Completion (?) of uint conversion.
182
  uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
183
  int2store(pos, tmp);
184
  pos+= 2;
185
520.1.22 by Brian Aker
Second pass of thd cleanup
186
  session->main_da.can_overwrite_status= true;
1 by brian
clean slate
187
188
  if (message && message[0])
481 by Brian Aker
Remove all of uchar.
189
    pos= net_store_data(pos, (unsigned char*) message, strlen(message));
840.1.17 by Monty Taylor
Renamed my_net_* to drizzleclient_net_* to help with namespace issues.
190
  drizzleclient_net_write(net, buff, (size_t) (pos-buff));
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
191
  drizzleclient_net_flush(net);
1 by brian
clean slate
192
520.1.22 by Brian Aker
Second pass of thd cleanup
193
  session->main_da.can_overwrite_status= false;
1 by brian
clean slate
194
}
195
196
/**
197
  Send eof (= end of result set) to the client.
198
199
  The eof packet has the following structure:
200
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
201
  - 254	(DRIZZLE_PROTOCOL_NO_MORE_DATA)	: Marker (1 byte)
1 by brian
clean slate
202
  - warning_count	: Stored in 2 bytes; New in 4.1 protocol
203
  - status_flag	: Stored in 2 bytes;
204
  For flags like SERVER_MORE_RESULTS_EXISTS.
205
206
  Note that the warning count will not be sent if 'no_flush' is set as
207
  we don't want to report the warning count until all data is sent to the
208
  client.
209
520.1.22 by Brian Aker
Second pass of thd cleanup
210
  @param session		Thread handler
1 by brian
clean slate
211
  @param no_flush	Set to 1 if there will be more data to the client,
212
                    like in send_fields().
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
213
*/
1 by brian
clean slate
214
202.1.17 by Monty Taylor
Patch from andrey - made some functions static as they are not used outside of protocol.cc.
215
static void
520.1.22 by Brian Aker
Second pass of thd cleanup
216
net_send_eof(Session *session, uint32_t server_status, uint32_t total_warn_count)
1 by brian
clean slate
217
{
520.1.22 by Brian Aker
Second pass of thd cleanup
218
  NET *net= &session->net;
51.1.76 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
219
  /* Set to true if no active vio, to work well in case of --init-file */
1 by brian
clean slate
220
  if (net->vio != 0)
221
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
222
    session->main_da.can_overwrite_status= true;
223
    write_eof_packet(session, net, server_status, total_warn_count);
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
224
    drizzleclient_net_flush(net);
520.1.22 by Brian Aker
Second pass of thd cleanup
225
    session->main_da.can_overwrite_status= false;
1 by brian
clean slate
226
  }
227
}
228
229
230
/**
231
  Format EOF packet according to the current protocol and
232
  write it to the network output buffer.
233
*/
234
520.1.22 by Brian Aker
Second pass of thd cleanup
235
static void write_eof_packet(Session *session, NET *net,
482 by Brian Aker
Remove uint.
236
                             uint32_t server_status,
237
                             uint32_t total_warn_count)
1 by brian
clean slate
238
{
481 by Brian Aker
Remove all of uchar.
239
  unsigned char buff[5];
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
240
  /*
241
    Don't send warn count during SP execution, as the warn_list
242
    is cleared between substatements, and mysqltest gets confused
243
  */
895 by Brian Aker
Completion (?) of uint conversion.
244
  uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
245
  buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
246
  int2store(buff+1, tmp);
247
  /*
248
    The following test should never be true, but it's better to do it
249
    because if 'is_fatal_error' is set the server is not going to execute
250
    other queries (see the if test in dispatch_command / COM_QUERY)
251
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
252
  if (session->is_fatal_error)
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
253
    server_status&= ~SERVER_MORE_RESULTS_EXISTS;
254
  int2store(buff + 3, server_status);
840.1.17 by Monty Taylor
Renamed my_net_* to drizzleclient_net_* to help with namespace issues.
255
  drizzleclient_net_write(net, buff, 5);
1 by brian
clean slate
256
}
257
520.1.22 by Brian Aker
Second pass of thd cleanup
258
void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err)
1 by brian
clean slate
259
{
520.1.22 by Brian Aker
Second pass of thd cleanup
260
  NET *net= &session->net;
482 by Brian Aker
Remove uint.
261
  uint32_t length;
1 by brian
clean slate
262
  /*
261.4.1 by Felipe
- Renamed MYSQL_ERROR to DRIZZLE_ERROR.
263
    buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
1 by brian
clean slate
264
  */
481 by Brian Aker
Remove all of uchar.
265
  unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
1 by brian
clean slate
266
267
  if (net->vio == 0)
268
  {
51.1.76 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
269
    return;
1 by brian
clean slate
270
  }
271
272
  int2store(buff,sql_errno);
273
  pos= buff+2;
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
274
275
  /* The first # is to make the protocol backward compatible */
276
  buff[2]= '#';
840.1.21 by Monty Taylor
ZOMG. Renamed all the rest of the stuff in libdrizzleclient to be drizzleclient_*. I love commandline perl.
277
  pos= (unsigned char*) strcpy((char*) buff+3, drizzleclient_errno_to_sqlstate(sql_errno));
278
  pos+= strlen(drizzleclient_errno_to_sqlstate(sql_errno));
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
279
629.5.3 by Toru Maesaka
Third pass of replacing MySQL's strmake() with libc calls
280
  char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
281
  tmp+= strlen((char*)pos);
282
  tmp[0]= '\0';
283
  length= (uint32_t)(tmp-(char*)buff);
1 by brian
clean slate
284
  err= (char*) buff;
285
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
286
  drizzleclient_net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
51.1.76 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
287
  return;
1 by brian
clean slate
288
}
289
290
291
/**
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
292
  Faster drizzleclient_net_store_length when we know that length is less than 65536.
1 by brian
clean slate
293
  We keep a separate version for that range because it's widely used in
294
  libmysql.
295
482 by Brian Aker
Remove uint.
296
  uint32_t is used as agrument type because of MySQL type conventions:
297
  - uint32_t for 0..65536
1 by brian
clean slate
298
  - ulong for 0..4294967296
151 by Brian Aker
Ulonglong to uint64_t
299
  - uint64_t for bigger numbers.
1 by brian
clean slate
300
*/
301
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
302
static unsigned char *drizzleclient_net_store_length_fast(unsigned char *packet, uint32_t length)
1 by brian
clean slate
303
{
304
  if (length < 251)
305
  {
481 by Brian Aker
Remove all of uchar.
306
    *packet=(unsigned char) length;
1 by brian
clean slate
307
    return packet+1;
308
  }
309
  *packet++=252;
628 by Brian Aker
Collection of dead code removal
310
  int2store(packet,(uint32_t) length);
311
1 by brian
clean slate
312
  return packet+2;
313
}
314
315
/**
316
  Send the status of the current statement execution over network.
317
520.1.22 by Brian Aker
Second pass of thd cleanup
318
  @param  session   in fact, carries two parameters, NET for the transport and
1 by brian
clean slate
319
                Diagnostics_area as the source of status information.
320
321
  In MySQL, there are two types of SQL statements: those that return
322
  a result set and those that return status information only.
323
324
  If a statement returns a result set, it consists of 3 parts:
325
  - result set meta-data
326
  - variable number of result set rows (can be 0)
327
  - followed and terminated by EOF or ERROR packet
328
329
  Once the  client has seen the meta-data information, it always
330
  expects an EOF or ERROR to terminate the result set. If ERROR is
331
  received, the result set rows are normally discarded (this is up
332
  to the client implementation, libmysql at least does discard them).
333
  EOF, on the contrary, means "successfully evaluated the entire
334
  result set". Since we don't know how many rows belong to a result
335
  set until it's evaluated, EOF/ERROR is the indicator of the end
336
  of the row stream. Note, that we can not buffer result set rows
337
  on the server -- there may be an arbitrary number of rows. But
338
  we do buffer the last packet (EOF/ERROR) in the Diagnostics_area and
339
  delay sending it till the very end of execution (here), to be able to
340
  change EOF to an ERROR if commit failed or some other error occurred
341
  during the last cleanup steps taken after execution.
342
343
  A statement that does not return a result set doesn't send result
344
  set meta-data either. Instead it returns one of:
345
  - OK packet
346
  - ERROR packet.
347
  Similarly to the EOF/ERROR of the previous statement type, OK/ERROR
348
  packet is "buffered" in the diagnostics area and sent to the client
349
  in the end of statement.
350
351
  @pre  The diagnostics area is assigned or disabled. It can not be empty
352
        -- we assume that every SQL statement or COM_* command
353
        generates OK, ERROR, or EOF status.
354
355
  @post The status information is encoded to protocol format and sent to the
356
        client.
357
358
  @return We conventionally return void, since the only type of error
359
          that can happen here is a NET (transport) error, and that one
360
          will become visible when we attempt to read from the NET the
361
          next command.
362
          Diagnostics_area::is_sent is set for debugging purposes only.
363
*/
364
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
365
void drizzleclient_net_end_statement(Session *session)
1 by brian
clean slate
366
{
520.1.22 by Brian Aker
Second pass of thd cleanup
367
  assert(! session->main_da.is_sent);
1 by brian
clean slate
368
369
  /* Can not be true, but do not take chances in production. */
520.1.22 by Brian Aker
Second pass of thd cleanup
370
  if (session->main_da.is_sent)
1 by brian
clean slate
371
    return;
372
520.1.22 by Brian Aker
Second pass of thd cleanup
373
  switch (session->main_da.status()) {
1 by brian
clean slate
374
  case Diagnostics_area::DA_ERROR:
375
    /* The query failed, send error to log and abort bootstrap. */
520.1.22 by Brian Aker
Second pass of thd cleanup
376
    net_send_error(session,
377
                   session->main_da.sql_errno(),
378
                   session->main_da.message());
1 by brian
clean slate
379
    break;
380
  case Diagnostics_area::DA_EOF:
520.1.22 by Brian Aker
Second pass of thd cleanup
381
    net_send_eof(session,
382
                 session->main_da.server_status(),
383
                 session->main_da.total_warn_count());
1 by brian
clean slate
384
    break;
385
  case Diagnostics_area::DA_OK:
520.1.22 by Brian Aker
Second pass of thd cleanup
386
    net_send_ok(session,
387
                session->main_da.server_status(),
388
                session->main_da.total_warn_count(),
389
                session->main_da.affected_rows(),
390
                session->main_da.last_insert_id(),
391
                session->main_da.message());
1 by brian
clean slate
392
    break;
393
  case Diagnostics_area::DA_DISABLED:
394
    break;
395
  case Diagnostics_area::DA_EMPTY:
396
  default:
722.2.12 by Monty Taylor
Removed assert(0); Added function ptr in libdrizzle.
397
    //TODO: Something is being masked here by commenting this out
398
    //  assert(0);
520.1.22 by Brian Aker
Second pass of thd cleanup
399
    net_send_ok(session, session->server_status, session->total_warn_count,
1 by brian
clean slate
400
                0, 0, NULL);
401
    break;
402
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
403
  session->main_da.is_sent= true;
1 by brian
clean slate
404
}
405
406
407
/****************************************************************************
408
  Functions used by the protocol functions (like net_send_ok) to store
409
  strings and numbers in the header result packet.
410
****************************************************************************/
411
412
/* The following will only be used for short strings < 65K */
413
481 by Brian Aker
Remove all of uchar.
414
unsigned char *net_store_data(unsigned char *to, const unsigned char *from, size_t length)
1 by brian
clean slate
415
{
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
416
  to=drizzleclient_net_store_length_fast(to,length);
1 by brian
clean slate
417
  memcpy(to,from,length);
418
  return to+length;
419
}
420
481 by Brian Aker
Remove all of uchar.
421
unsigned char *net_store_data(unsigned char *to,int32_t from)
1 by brian
clean slate
422
{
423
  char buff[20];
895 by Brian Aker
Completion (?) of uint conversion.
424
  uint32_t length=(uint32_t) (int10_to_str(from,buff,10)-buff);
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
425
  to=drizzleclient_net_store_length_fast(to,length);
1 by brian
clean slate
426
  memcpy(to,buff,length);
427
  return to+length;
428
}
429
481 by Brian Aker
Remove all of uchar.
430
unsigned char *net_store_data(unsigned char *to,int64_t from)
1 by brian
clean slate
431
{
432
  char buff[22];
895 by Brian Aker
Completion (?) of uint conversion.
433
  uint32_t length=(uint32_t) (int64_t10_to_str(from,buff,10)-buff);
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
434
  to=drizzleclient_net_store_length_fast(to,length);
1 by brian
clean slate
435
  memcpy(to,buff,length);
436
  return to+length;
437
}
438
439
440
/*****************************************************************************
441
  Default Protocol functions
442
*****************************************************************************/
443
520.1.22 by Brian Aker
Second pass of thd cleanup
444
void Protocol::init(Session *session_arg)
1 by brian
clean slate
445
{
520.1.22 by Brian Aker
Second pass of thd cleanup
446
  session=session_arg;
447
  packet= &session->packet;
448
  convert= &session->convert_buffer;
1 by brian
clean slate
449
}
450
451
452
bool Protocol::flush()
453
{
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
454
  return drizzleclient_net_flush(&session->net);
1 by brian
clean slate
455
}
456
457
458
/**
459
  Send name and type of result to client.
460
461
  Sum fields has table name empty and field_name.
462
520.1.21 by Brian Aker
THD -> Session rename
463
  @param Session		Thread data object
1 by brian
clean slate
464
  @param list	        List of items to send to client
465
  @param flag	        Bit mask with the following functions:
466
                        - 1 send number of rows
467
                        - 2 send default values
468
                        - 4 don't write eof packet
469
470
  @retval
471
    0	ok
472
  @retval
473
    1	Error  (Note that in this case the error is not sent to the
474
    client)
475
*/
482 by Brian Aker
Remove uint.
476
bool Protocol::send_fields(List<Item> *list, uint32_t flags)
1 by brian
clean slate
477
{
478
  List_iterator_fast<Item> it(*list);
479
  Item *item;
481 by Brian Aker
Remove all of uchar.
480
  unsigned char buff[80];
1 by brian
clean slate
481
  String tmp((char*) buff,sizeof(buff),&my_charset_bin);
520.1.22 by Brian Aker
Second pass of thd cleanup
482
  Protocol_text prot(session);
1 by brian
clean slate
483
  String *local_packet= prot.storage_packet();
748 by Brian Aker
Removal of client side collation.
484
  const CHARSET_INFO * const session_charset= default_charset_info;
1 by brian
clean slate
485
486
  if (flags & SEND_NUM_ROWS)
487
  {				// Packet with number of elements
840.1.20 by Monty Taylor
Renamed non-prefixed things from libdrizzleclient to drizzleclient.
488
    unsigned char *pos= drizzleclient_net_store_length(buff, list->elements);
840.1.17 by Monty Taylor
Renamed my_net_* to drizzleclient_net_* to help with namespace issues.
489
    (void) drizzleclient_net_write(&session->net, buff, (size_t) (pos-buff));
1 by brian
clean slate
490
  }
491
492
  while ((item=it++))
493
  {
494
    char *pos;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
495
    const CHARSET_INFO * const cs= system_charset_info;
1 by brian
clean slate
496
    Send_field field;
497
    item->make_field(&field);
498
499
    prot.prepare_for_resend();
500
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
501
520.1.22 by Brian Aker
Second pass of thd cleanup
502
    if (prot.store(STRING_WITH_LEN("def"), cs, session_charset) ||
895 by Brian Aker
Completion (?) of uint conversion.
503
        prot.store(field.db_name, (uint32_t) strlen(field.db_name),
504
                   cs, session_charset) ||
505
        prot.store(field.table_name, (uint32_t) strlen(field.table_name),
506
                   cs, session_charset) ||
507
        prot.store(field.org_table_name, (uint32_t) strlen(field.org_table_name),
508
                   cs, session_charset) ||
509
        prot.store(field.col_name, (uint32_t) strlen(field.col_name),
510
                   cs, session_charset) ||
511
        prot.store(field.org_col_name, (uint32_t) strlen(field.org_col_name),
520.1.22 by Brian Aker
Second pass of thd cleanup
512
                   cs, session_charset) ||
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
513
        local_packet->realloc(local_packet->length()+12))
514
      goto err;
515
516
    /* Store fixed length fields */
517
    pos= (char*) local_packet->ptr()+local_packet->length();
518
    *pos++= 12;				// Length of packed fields
520.1.22 by Brian Aker
Second pass of thd cleanup
519
    if (item->collation.collation == &my_charset_bin || session_charset == NULL)
1 by brian
clean slate
520
    {
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
521
      /* No conversion */
522
      int2store(pos, field.charsetnr);
523
      int4store(pos+2, field.length);
1 by brian
clean slate
524
    }
525
    else
526
    {
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
527
      /* With conversion */
482 by Brian Aker
Remove uint.
528
      uint32_t max_char_len;
520.1.22 by Brian Aker
Second pass of thd cleanup
529
      int2store(pos, session_charset->number);
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
530
      /*
531
        For TEXT/BLOB columns, field_length describes the maximum data
532
        length in bytes. There is no limit to the number of characters
533
        that a TEXT column can store, as long as the data fits into
534
        the designated space.
535
        For the rest of textual columns, field_length is evaluated as
536
        char_count * mbmaxlen, where character count is taken from the
537
        definition of the column. In other words, the maximum number
538
        of characters here is limited by the column definition.
539
      */
540
      max_char_len= field.length / item->collation.collation->mbmaxlen;
520.1.22 by Brian Aker
Second pass of thd cleanup
541
      int4store(pos+2, max_char_len * session_charset->mbmaxlen);
264.2.4 by Andrey Hristov
Remove support for the old, pre-4.1, protocol
542
    }
543
    pos[6]= field.type;
544
    int2store(pos+7,field.flags);
545
    pos[9]= (char) field.decimals;
546
    pos[10]= 0;				// For the future
547
    pos[11]= 0;				// For the future
548
    pos+= 12;
1 by brian
clean slate
549
895 by Brian Aker
Completion (?) of uint conversion.
550
    local_packet->length((uint32_t) (pos - local_packet->ptr()));
1 by brian
clean slate
551
    if (flags & SEND_DEFAULTS)
552
      item->send(&prot, &tmp);			// Send default value
553
    if (prot.write())
554
      break;					/* purecov: inspected */
555
  }
556
557
  if (flags & SEND_EOF)
558
  {
559
    /*
520.1.22 by Brian Aker
Second pass of thd cleanup
560
      Mark the end of meta-data result set, and store session->server_status,
1 by brian
clean slate
561
      to show that there is no cursor.
562
      Send no warning information, as it will be sent at statement end.
563
    */
520.1.22 by Brian Aker
Second pass of thd cleanup
564
    write_eof_packet(session, &session->net, session->server_status, session->total_warn_count);
1 by brian
clean slate
565
  }
51.1.76 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
566
  return(prepare_for_send(list));
1 by brian
clean slate
567
568
err:
569
  my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
570
             MYF(0));	/* purecov: inspected */
51.1.76 by Jay Pipes
Standardized TRUE/FALSE, removed/replaced DBUG symbols
571
  return(1);				/* purecov: inspected */
1 by brian
clean slate
572
}
573
574
575
bool Protocol::write()
576
{
840.1.17 by Monty Taylor
Renamed my_net_* to drizzleclient_net_* to help with namespace issues.
577
  return(drizzleclient_net_write(&session->net, (unsigned char*) packet->ptr(),
1 by brian
clean slate
578
                           packet->length()));
579
}
580
581
582
/**
583
  Send \\0 end terminated string.
584
461 by Monty Taylor
Removed NullS. bu-bye.
585
  @param from	NULL or \\0 terminated string
1 by brian
clean slate
586
587
  @note
588
    In most cases one should use store(from, length) instead of this function
589
590
  @retval
591
    0		ok
592
  @retval
593
    1		error
594
*/
595
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
596
bool Protocol::store(const char *from, const CHARSET_INFO * const cs)
1 by brian
clean slate
597
{
598
  if (!from)
599
    return store_null();
482 by Brian Aker
Remove uint.
600
  uint32_t length= strlen(from);
1 by brian
clean slate
601
  return store(from, length, cs);
602
}
603
604
605
/**
606
  Send a set of strings as one long string with ',' in between.
607
*/
608
609
bool Protocol::store(I_List<i_string>* str_list)
610
{
611
  char buf[256];
612
  String tmp(buf, sizeof(buf), &my_charset_bin);
205 by Brian Aker
uint32 -> uin32_t
613
  uint32_t len;
1 by brian
clean slate
614
  I_List_iterator<i_string> it(*str_list);
615
  i_string* s;
616
617
  tmp.length(0);
618
  while ((s=it++))
619
  {
620
    tmp.append(s->ptr);
621
    tmp.append(',');
622
  }
623
  if ((len= tmp.length()))
624
    len--;					// Remove last ','
625
  return store((char*) tmp.ptr(), len,  tmp.charset());
626
}
627
628
584.1.14 by Monty Taylor
Removed field.h from common_includes.
629
bool Protocol::store(String *str)
630
{
631
  return store((char*) str->ptr(), str->length(), str->charset());
632
}
633
634
void Protocol::free()
635
{
636
  packet->free();
637
}
638
639
1 by brian
clean slate
640
/****************************************************************************
641
  Functions to handle the simple (default) protocol where everything is
642
  This protocol is the one that is used by default between the MySQL server
643
  and client when you are not using prepared statements.
644
645
  All data are sent as 'packed-string-length' followed by 'string-data'
646
****************************************************************************/
647
648
void Protocol_text::prepare_for_resend()
649
{
650
  packet->length(0);
651
}
652
653
bool Protocol_text::store_null()
654
{
655
  char buff[1];
656
  buff[0]= (char)251;
657
  return packet->append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
658
}
659
660
661
/**
662
  Auxilary function to convert string to the given character set
663
  and store in network buffer.
664
*/
665
666
bool Protocol::store_string_aux(const char *from, size_t length,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
667
                                const CHARSET_INFO * const fromcs,
668
								const CHARSET_INFO * const tocs)
1 by brian
clean slate
669
{
670
  /* 'tocs' is set 0 when client issues SET character_set_results=NULL */
671
  if (tocs && !my_charset_same(fromcs, tocs) &&
672
      fromcs != &my_charset_bin &&
673
      tocs != &my_charset_bin)
674
  {
675
    /* Store with conversion */
481 by Brian Aker
Remove all of uchar.
676
    return net_store_data((unsigned char*) from, length, fromcs, tocs);
1 by brian
clean slate
677
  }
678
  /* Store without conversion */
481 by Brian Aker
Remove all of uchar.
679
  return net_store_data((unsigned char*) from, length);
1 by brian
clean slate
680
}
681
682
683
bool Protocol_text::store(const char *from, size_t length,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
684
                          const CHARSET_INFO * const fromcs,
685
						  const CHARSET_INFO * const tocs)
1 by brian
clean slate
686
{
687
  return store_string_aux(from, length, fromcs, tocs);
688
}
689
690
691
bool Protocol_text::store(const char *from, size_t length,
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
692
                          const CHARSET_INFO * const fromcs)
1 by brian
clean slate
693
{
748 by Brian Aker
Removal of client side collation.
694
  const CHARSET_INFO * const tocs= default_charset_info;
1 by brian
clean slate
695
  return store_string_aux(from, length, fromcs, tocs);
696
}
697
698
152 by Brian Aker
longlong replacement
699
bool Protocol_text::store_tiny(int64_t from)
1 by brian
clean slate
700
{
701
  char buff[20];
481 by Brian Aker
Remove all of uchar.
702
  return net_store_data((unsigned char*) buff,
1 by brian
clean slate
703
			(size_t) (int10_to_str((int) from, buff, -10) - buff));
704
}
705
706
152 by Brian Aker
longlong replacement
707
bool Protocol_text::store_short(int64_t from)
1 by brian
clean slate
708
{
709
  char buff[20];
481 by Brian Aker
Remove all of uchar.
710
  return net_store_data((unsigned char*) buff,
1 by brian
clean slate
711
			(size_t) (int10_to_str((int) from, buff, -10) -
712
                                  buff));
713
}
714
715
152 by Brian Aker
longlong replacement
716
bool Protocol_text::store_long(int64_t from)
1 by brian
clean slate
717
{
718
  char buff[20];
481 by Brian Aker
Remove all of uchar.
719
  return net_store_data((unsigned char*) buff,
1 by brian
clean slate
720
			(size_t) (int10_to_str((long int)from, buff,
721
                                               (from <0)?-10:10)-buff));
722
}
723
724
152 by Brian Aker
longlong replacement
725
bool Protocol_text::store_int64_t(int64_t from, bool unsigned_flag)
1 by brian
clean slate
726
{
727
  char buff[22];
481 by Brian Aker
Remove all of uchar.
728
  return net_store_data((unsigned char*) buff,
152 by Brian Aker
longlong replacement
729
			(size_t) (int64_t10_to_str(from,buff,
1 by brian
clean slate
730
                                                    unsigned_flag ? 10 : -10)-
731
                                  buff));
732
}
733
734
735
bool Protocol_text::store_decimal(const my_decimal *d)
736
{
737
  char buff[DECIMAL_MAX_STR_LENGTH];
738
  String str(buff, sizeof(buff), &my_charset_bin);
739
  (void) my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
481 by Brian Aker
Remove all of uchar.
740
  return net_store_data((unsigned char*) str.ptr(), str.length());
1 by brian
clean slate
741
}
742
743
205 by Brian Aker
uint32 -> uin32_t
744
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
1 by brian
clean slate
745
{
520.1.22 by Brian Aker
Second pass of thd cleanup
746
  buffer->set_real((double) from, decimals, session->charset());
481 by Brian Aker
Remove all of uchar.
747
  return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
1 by brian
clean slate
748
}
749
750
205 by Brian Aker
uint32 -> uin32_t
751
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
1 by brian
clean slate
752
{
520.1.22 by Brian Aker
Second pass of thd cleanup
753
  buffer->set_real(from, decimals, session->charset());
481 by Brian Aker
Remove all of uchar.
754
  return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
1 by brian
clean slate
755
}
756
757
758
bool Protocol_text::store(Field *field)
759
{
760
  if (field->is_null())
761
    return store_null();
762
  char buff[MAX_FIELD_WIDTH];
763
  String str(buff,sizeof(buff), &my_charset_bin);
748 by Brian Aker
Removal of client side collation.
764
  const CHARSET_INFO * const tocs= default_charset_info;
1 by brian
clean slate
765
766
  field->val_str(&str);
767
768
  return store_string_aux(str.ptr(), str.length(), str.charset(), tocs);
769
}
770
771
772
/**
773
  @todo
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
774
    Second_part format ("%06") needs to change when
1 by brian
clean slate
775
    we support 0-6 decimals for time.
776
*/
777
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
778
bool Protocol_text::store(DRIZZLE_TIME *tm)
1 by brian
clean slate
779
{
780
  char buff[40];
482 by Brian Aker
Remove uint.
781
  uint32_t length;
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
782
  length= sprintf(buff, "%04d-%02d-%02d %02d:%02d:%02d",
1 by brian
clean slate
783
			   (int) tm->year,
784
			   (int) tm->month,
785
			   (int) tm->day,
786
			   (int) tm->hour,
787
			   (int) tm->minute,
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
788
			   (int) tm->second);
1 by brian
clean slate
789
  if (tm->second_part)
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
790
    length+= sprintf(buff+length, ".%06d",
791
                                     (int)tm->second_part);
481 by Brian Aker
Remove all of uchar.
792
  return net_store_data((unsigned char*) buff, length);
1 by brian
clean slate
793
}
794
795
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
796
bool Protocol_text::store_date(DRIZZLE_TIME *tm)
1 by brian
clean slate
797
{
798
  char buff[MAX_DATE_STRING_REP_LENGTH];
799
  size_t length= my_date_to_str(tm, buff);
481 by Brian Aker
Remove all of uchar.
800
  return net_store_data((unsigned char*) buff, length);
1 by brian
clean slate
801
}
802
803
804
/**
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
805
  @todo
806
    Second_part format ("%06") needs to change when
1 by brian
clean slate
807
    we support 0-6 decimals for time.
808
*/
809
236.1.24 by Monty Taylor
Renamed MYSQL_TIME to DRIZZLE_TIME.
810
bool Protocol_text::store_time(DRIZZLE_TIME *tm)
1 by brian
clean slate
811
{
812
  char buff[40];
482 by Brian Aker
Remove uint.
813
  uint32_t length;
814
  uint32_t day= (tm->year || tm->month) ? 0 : tm->day;
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
815
  length= sprintf(buff, "%s%02ld:%02d:%02d",
1 by brian
clean slate
816
			   tm->neg ? "-" : "",
817
			   (long) day*24L+(long) tm->hour,
818
			   (int) tm->minute,
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
819
			   (int) tm->second);
1 by brian
clean slate
820
  if (tm->second_part)
171.1.1 by Patrick Galbraith
Dar, I forgot to commit this earlier.
821
    length+= sprintf(buff+length, ".%06d", (int)tm->second_part);
481 by Brian Aker
Remove all of uchar.
822
  return net_store_data((unsigned char*) buff, length);
1 by brian
clean slate
823
}
824