20
20
The actual communction is handled by the net_xxx functions in net_serv.cc
22
22
#include <drizzled/server_includes.h>
23
#include <drizzled/drizzled_error_messages.h>
23
#include <drizzled/error.h>
24
24
#include <drizzled/sql_state.h>
25
#include <libdrizzleclient/pack.h>
26
#include <drizzled/protocol.h>
27
#include <drizzled/session.h>
26
29
static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
27
30
/* 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,
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,
30
33
uint32_t server_status, uint32_t total_warn_count);
32
35
bool Protocol::net_store_data(const unsigned char *from, size_t length)
34
ulong packet_length=packet->length();
37
size_t packet_length= packet->length();
36
39
The +9 comes from that strings of length longer than 16M require
37
9 bytes to be stored (see net_store_length).
40
9 bytes to be stored (see drizzleclient_net_store_length).
39
42
if (packet_length+9+length > packet->alloced_length() &&
40
43
packet->realloc(packet_length+9+length))
42
unsigned char *to= net_store_length((unsigned char*) packet->ptr()+packet_length, length);
45
unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet->ptr()+packet_length, length);
43
46
memcpy(to,from,length);
44
packet->length((uint) (to+length-(unsigned char*) packet->ptr()));
47
packet->length((size_t) (to+length-(unsigned char*) packet->ptr()));
76
79
For example, when converting from utf8 (mbmaxlen=3) to latin1,
77
80
conv_length=300 means that the result length can vary between 100 to 300.
78
81
length=100 needs one byte, length=300 needs to bytes.
80
83
Thus conversion directly to "packet" is not worthy.
81
84
Let's use "convert" as a temporary buffer.
85
88
net_store_data((const unsigned char*) convert->ptr(), convert->length()));
88
ulong packet_length= packet->length();
89
ulong new_length= packet_length + conv_length + 1;
91
size_t packet_length= packet->length();
92
size_t new_length= packet_length + conv_length + 1;
91
94
if (new_length > packet->alloced_length() && packet->realloc(new_length))
97
100
to+= copy_and_convert(to, conv_length, to_cs,
98
101
(const char*) from, length, from_cs, &dummy_errors);
100
net_store_length((unsigned char*) length_pos, to - length_pos - 1);
101
packet->length((uint) (to - packet->ptr()));
103
drizzleclient_net_store_length((unsigned char*) length_pos, to - length_pos - 1);
104
packet->length((uint32_t) (to - packet->ptr()));
115
118
critical that every error that can be intercepted is issued in one
116
119
place only, my_message_sql.
118
void net_send_error(THD *thd, uint32_t sql_errno, const char *err)
121
void net_send_error(Session *session, uint32_t sql_errno, const char *err)
120
123
assert(sql_errno);
121
124
assert(err && err[0]);
124
127
It's one case when we can push an error even though there
125
128
is an OK or EOF already.
127
thd->main_da.can_overwrite_status= true;
130
session->main_da.can_overwrite_status= true;
129
132
/* Abort multi-result sets */
130
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
132
net_send_error_packet(thd, sql_errno, err);
134
thd->main_da.can_overwrite_status= false;
133
session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
135
net_send_error_packet(session, sql_errno, err);
137
session->main_da.can_overwrite_status= false;
142
145
- 0 : Marker (1 byte)
143
146
- affected_rows : Stored in 1-9 bytes
144
147
- id : Stored in 1-9 bytes
145
- server_status : Copy of thd->server_status; Can be used by client
148
- server_status : Copy of session->server_status; Can be used by client
146
149
to check if we are inside an transaction.
147
150
New in 4.0 protocol
148
151
- warning_count : Stored in 2 bytes; New in 4.1 protocol
149
152
- message : Stored as packed length (1-9 bytes) + message.
150
153
Is not stored if no message.
152
@param thd Thread handler
155
@param session Thread handler
153
156
@param affected_rows Number of rows changed by statement
154
157
@param id Auto_increment id for first row (if used)
155
158
@param message Message to send to the client (Used by mysql_status)
159
net_send_ok(THD *thd,
162
net_send_ok(Session *session,
160
163
uint32_t server_status, uint32_t total_warn_count,
161
164
ha_rows affected_rows, uint64_t id, const char *message)
166
NET *net= &session->net;
164
167
unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
166
169
if (! net->vio) // hack for re-parsing queries
171
174
buff[0]=0; // No fields
172
pos=net_store_length(buff+1,affected_rows);
173
pos=net_store_length(pos, id);
175
pos=drizzleclient_net_store_length(buff+1,affected_rows);
176
pos=drizzleclient_net_store_length(pos, id);
175
178
int2store(pos, server_status);
178
181
/* We can only return up to 65535 warnings in two bytes */
179
uint32_t tmp= cmin(total_warn_count, (uint)65535);
182
uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
180
183
int2store(pos, tmp);
183
thd->main_da.can_overwrite_status= true;
186
session->main_da.can_overwrite_status= true;
185
188
if (message && message[0])
186
189
pos= net_store_data(pos, (unsigned char*) message, strlen(message));
187
my_net_write(net, buff, (size_t) (pos-buff));
190
drizzleclient_net_write(net, buff, (size_t) (pos-buff));
191
drizzleclient_net_flush(net);
190
thd->main_da.can_overwrite_status= false;
193
session->main_da.can_overwrite_status= false;
204
207
we don't want to report the warning count until all data is sent to the
207
@param thd Thread handler
210
@param session Thread handler
208
211
@param no_flush Set to 1 if there will be more data to the client,
209
212
like in send_fields().
213
net_send_eof(THD *thd, uint32_t server_status, uint32_t total_warn_count)
216
net_send_eof(Session *session, uint32_t server_status, uint32_t total_warn_count)
218
NET *net= &session->net;
216
219
/* Set to true if no active vio, to work well in case of --init-file */
217
220
if (net->vio != 0)
219
thd->main_da.can_overwrite_status= true;
220
write_eof_packet(thd, net, server_status, total_warn_count);
222
thd->main_da.can_overwrite_status= false;
222
session->main_da.can_overwrite_status= true;
223
write_eof_packet(session, net, server_status, total_warn_count);
224
drizzleclient_net_flush(net);
225
session->main_da.can_overwrite_status= false;
229
232
write it to the network output buffer.
232
static void write_eof_packet(THD *thd, NET *net,
235
static void write_eof_packet(Session *session, NET *net,
233
236
uint32_t server_status,
234
237
uint32_t total_warn_count)
238
241
Don't send warn count during SP execution, as the warn_list
239
242
is cleared between substatements, and mysqltest gets confused
241
uint32_t tmp= cmin(total_warn_count, (uint)65535);
244
uint32_t tmp= cmin(total_warn_count, (uint32_t)65535);
242
245
buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
243
246
int2store(buff+1, tmp);
246
249
because if 'is_fatal_error' is set the server is not going to execute
247
250
other queries (see the if test in dispatch_command / COM_QUERY)
249
if (thd->is_fatal_error)
252
if (session->is_fatal_error)
250
253
server_status&= ~SERVER_MORE_RESULTS_EXISTS;
251
254
int2store(buff + 3, server_status);
252
my_net_write(net, buff, 5);
255
drizzleclient_net_write(net, buff, 5);
255
void net_send_error_packet(THD *thd, uint32_t sql_errno, const char *err)
258
void net_send_error_packet(Session *session, uint32_t sql_errno, const char *err)
260
NET *net= &session->net;
260
263
buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
272
275
/* The first # is to make the protocol backward compatible */
274
pos= (unsigned char*) my_stpcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
277
pos= (unsigned char*) strcpy((char*) buff+3, drizzleclient_errno_to_sqlstate(sql_errno));
278
pos+= strlen(drizzleclient_errno_to_sqlstate(sql_errno));
276
length= (uint) (strmake((char*) pos, err, DRIZZLE_ERRMSG_SIZE-1) -
280
char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
281
tmp+= strlen((char*)pos);
283
length= (uint32_t)(tmp-(char*)buff);
278
284
err= (char*) buff;
280
net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
286
drizzleclient_net_write_command(net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
286
Faster net_store_length when we know that length is less than 65536.
292
Faster drizzleclient_net_store_length when we know that length is less than 65536.
287
293
We keep a separate version for that range because it's widely used in
304
int2store(packet,(uint) length);
310
int2store(packet,(uint32_t) length);
309
316
Send the status of the current statement execution over network.
311
@param thd in fact, carries two parameters, NET for the transport and
318
@param session in fact, carries two parameters, NET for the transport and
312
319
Diagnostics_area as the source of status information.
314
321
In MySQL, there are two types of SQL statements: those that return
355
362
Diagnostics_area::is_sent is set for debugging purposes only.
358
void net_end_statement(THD *thd)
365
void drizzleclient_net_end_statement(Session *session)
360
assert(! thd->main_da.is_sent);
367
assert(! session->main_da.is_sent);
362
369
/* Can not be true, but do not take chances in production. */
363
if (thd->main_da.is_sent)
370
if (session->main_da.is_sent)
366
switch (thd->main_da.status()) {
373
switch (session->main_da.status()) {
367
374
case Diagnostics_area::DA_ERROR:
368
375
/* The query failed, send error to log and abort bootstrap. */
370
thd->main_da.sql_errno(),
371
thd->main_da.message());
376
net_send_error(session,
377
session->main_da.sql_errno(),
378
session->main_da.message());
373
380
case Diagnostics_area::DA_EOF:
375
thd->main_da.server_status(),
376
thd->main_da.total_warn_count());
381
net_send_eof(session,
382
session->main_da.server_status(),
383
session->main_da.total_warn_count());
378
385
case Diagnostics_area::DA_OK:
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());
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());
386
393
case Diagnostics_area::DA_DISABLED:
388
395
case Diagnostics_area::DA_EMPTY:
391
net_send_ok(thd, thd->server_status, thd->total_warn_count,
397
//TODO: Something is being masked here by commenting this out
399
net_send_ok(session, session->server_status, session->total_warn_count,
395
thd->main_da.is_sent= true;
403
session->main_da.is_sent= true;
413
421
unsigned char *net_store_data(unsigned char *to,int32_t from)
416
uint32_t length=(uint) (int10_to_str(from,buff,10)-buff);
417
to=net_store_length_fast(to,length);
424
uint32_t length=(uint32_t) (int10_to_str(from,buff,10)-buff);
425
to=drizzleclient_net_store_length_fast(to,length);
418
426
memcpy(to,buff,length);
419
427
return to+length;
422
430
unsigned char *net_store_data(unsigned char *to,int64_t from)
425
uint32_t length=(uint) (int64_t10_to_str(from,buff,10)-buff);
426
to=net_store_length_fast(to,length);
433
uint32_t length=(uint32_t) (int64_t10_to_str(from,buff,10)-buff);
434
to=drizzleclient_net_store_length_fast(to,length);
427
435
memcpy(to,buff,length);
428
436
return to+length;
433
441
Default Protocol functions
434
442
*****************************************************************************/
436
void Protocol::init(THD *thd_arg)
439
packet= &thd->packet;
440
convert= &thd->convert_buffer;
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
449
void Protocol::end_partial_result_set(THD *thd)
451
net_send_eof(thd, thd->server_status, 0 /* no warnings, we're inside SP */);
444
void Protocol::init(Session *session_arg)
447
packet= &session->packet;
448
convert= &session->convert_buffer;
455
452
bool Protocol::flush()
457
return net_flush(&thd->net);
454
return drizzleclient_net_flush(&session->net);
483
480
unsigned char buff[80];
484
481
String tmp((char*) buff,sizeof(buff),&my_charset_bin);
485
Protocol_text prot(thd);
482
Protocol_text prot(session);
486
483
String *local_packet= prot.storage_packet();
487
const CHARSET_INFO * const thd_charset= thd->variables.character_set_results;
484
const CHARSET_INFO * const session_charset= default_charset_info;
489
486
if (flags & SEND_NUM_ROWS)
490
487
{ // 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));
488
unsigned char *pos= drizzleclient_net_store_length(buff, list->elements);
489
(void) drizzleclient_net_write(&session->net, buff, (size_t) (pos-buff));
495
492
while ((item=it++))
502
499
prot.prepare_for_resend();
505
if (prot.store(STRING_WITH_LEN("def"), cs, thd_charset) ||
506
prot.store(field.db_name, (uint) strlen(field.db_name),
508
prot.store(field.table_name, (uint) strlen(field.table_name),
510
prot.store(field.org_table_name, (uint) strlen(field.org_table_name),
512
prot.store(field.col_name, (uint) strlen(field.col_name),
514
prot.store(field.org_col_name, (uint) strlen(field.org_col_name),
502
if (prot.store(STRING_WITH_LEN("def"), cs, session_charset) ||
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),
512
cs, session_charset) ||
516
513
local_packet->realloc(local_packet->length()+12))
519
516
/* Store fixed length fields */
520
517
pos= (char*) local_packet->ptr()+local_packet->length();
521
518
*pos++= 12; // Length of packed fields
522
if (item->collation.collation == &my_charset_bin || thd_charset == NULL)
519
if (item->collation.collation == &my_charset_bin || session_charset == NULL)
524
521
/* No conversion */
525
522
int2store(pos, field.charsetnr);
541
538
of characters here is limited by the column definition.
543
540
max_char_len= field.length / item->collation.collation->mbmaxlen;
544
int4store(pos+2, max_char_len * thd_charset->mbmaxlen);
541
int4store(pos+2, max_char_len * session_charset->mbmaxlen);
546
543
pos[6]= field.type;
547
544
int2store(pos+7,field.flags);
560
557
if (flags & SEND_EOF)
563
Mark the end of meta-data result set, and store thd->server_status,
560
Mark the end of meta-data result set, and store session->server_status,
564
561
to show that there is no cursor.
565
562
Send no warning information, as it will be sent at statement end.
567
write_eof_packet(thd, &thd->net, thd->server_status, thd->total_warn_count);
564
write_eof_packet(session, &session->net, session->server_status, session->total_warn_count);
569
566
return(prepare_for_send(list));
629
bool Protocol::store(String *str)
631
return store((char*) str->ptr(), str->length(), str->charset());
634
void Protocol::free()
632
640
/****************************************************************************
633
641
Functions to handle the simple (default) protocol where everything is
634
642
This protocol is the one that is used by default between the MySQL server
683
691
bool Protocol_text::store(const char *from, size_t length,
684
692
const CHARSET_INFO * const fromcs)
686
const CHARSET_INFO * const tocs= this->thd->variables.character_set_results;
694
const CHARSET_INFO * const tocs= default_charset_info;
687
695
return store_string_aux(from, length, fromcs, tocs);
736
744
bool Protocol_text::store(float from, uint32_t decimals, String *buffer)
738
buffer->set_real((double) from, decimals, thd->charset());
746
buffer->set_real((double) from, decimals, session->charset());
739
747
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());
743
751
bool Protocol_text::store(double from, uint32_t decimals, String *buffer)
745
buffer->set_real(from, decimals, thd->charset());
753
buffer->set_real(from, decimals, session->charset());
746
754
return net_store_data((unsigned char*) buffer->ptr(), buffer->length());