Merge lp:~brianaker/drizzle/bug-fix-654219 into lp:~drizzle-trunk/drizzle/development

Proposed by Brian Aker
Status: Merged
Approved by: Brian Aker
Approved revision: not available
Merged at revision: 1822
Proposed branch: lp:~brianaker/drizzle/bug-fix-654219
Merge into: lp:~drizzle-trunk/drizzle/development
Diff against target: 3037 lines (+292/-2456) (has conflicts)
17 files modified
plugin/drizzle_protocol/drizzle_protocol.cc (+34/-883)
plugin/drizzle_protocol/drizzle_protocol.h (+15/-66)
plugin/drizzle_protocol/errmsg.cc (+1/-93)
plugin/drizzle_protocol/errmsg.h (+0/-80)
plugin/drizzle_protocol/net_serv.cc (+0/-896)
plugin/drizzle_protocol/net_serv.h (+0/-94)
plugin/drizzle_protocol/options.h (+0/-125)
plugin/drizzle_protocol/pack.cc (+0/-132)
plugin/drizzle_protocol/pack.h (+0/-34)
plugin/drizzle_protocol/plugin.ini (+10/-5)
plugin/drizzle_protocol/status_table.h (+13/-8)
plugin/information_schema_dictionary/key_column_usage.cc (+51/-2)
plugin/information_schema_dictionary/key_column_usage.h (+3/-0)
plugin/information_schema_dictionary/tests/r/key_column_usage.result (+36/-36)
tests/include.am (+2/-2)
tests/suite/regression/r/654219.result (+63/-0)
tests/suite/regression/t/654219.test (+64/-0)
Text conflict in plugin/drizzle_protocol/drizzle_protocol.cc
Contents conflict in plugin/drizzle_protocol/vio.cc
Contents conflict in plugin/drizzle_protocol/vio.h
Contents conflict in plugin/drizzle_protocol/viosocket.cc
To merge this branch: bzr merge lp:~brianaker/drizzle/bug-fix-654219
Reviewer Review Type Date Requested Status
Drizzle Merge Team Pending
Review via email: mp+37684@code.launchpad.net

Description of the change

This fixes bug 654219.

To post a comment you must log in.
Revision history for this message
Lee Bieber (kalebral-deactivatedaccount) wrote :

Need to re-merge with trunk getting conflicts.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'plugin/drizzle_protocol/drizzle_protocol.cc'
--- plugin/drizzle_protocol/drizzle_protocol.cc 2010-10-02 21:15:42 +0000
+++ plugin/drizzle_protocol/drizzle_protocol.cc 2010-10-06 01:14:00 +0000
@@ -1,6 +1,7 @@
1/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-1/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:2 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3 *3 *
4<<<<<<< TREE
4 * Copyright (C) 2008 Sun Microsystems5 * Copyright (C) 2008 Sun Microsystems
5 *6 *
6 * This program is free software; you can redistribute it and/or modify7 * This program is free software; you can redistribute it and/or modify
@@ -15,8 +16,26 @@
15 * You should have received a copy of the GNU General Public License16 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software17 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19=======
20 * Copyright (C) 2010 Brian Aker
21 *
22 * This program is free software; you can redistribute it and/or modify
23 * it under the terms of the GNU General Public License as published by
24 * the Free Software Foundation; either version 2 of the License, or
25 * (at your option) any later version.
26 *
27 * This program is distributed in the hope that it will be useful,
28 * but WITHOUT ANY WARRANTY; without even the implied warranty of
29 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
30 * GNU General Public License for more details.
31 *
32 * You should have received a copy of the GNU General Public License
33 * along with this program; if not, write to the Free Software
34 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
35>>>>>>> MERGE-SOURCE
18 */36 */
1937
38
20#include "config.h"39#include "config.h"
21#include <drizzled/gettext.h>40#include <drizzled/gettext.h>
22#include <drizzled/error.h>41#include <drizzled/error.h>
@@ -29,13 +48,8 @@
29#include <iostream>48#include <iostream>
30#include <boost/program_options.hpp>49#include <boost/program_options.hpp>
31#include <drizzled/module/option_map.h>50#include <drizzled/module/option_map.h>
32#include "pack.h"
33#include "errmsg.h"
34#include "drizzle_protocol.h"51#include "drizzle_protocol.h"
35#include "options.h"52#include "plugin/drizzle_protocol/status_table.h"
36#include "table_function.h"
37
38#define PROTOCOL_VERSION 10
3953
40namespace po= boost::program_options;54namespace po= boost::program_options;
41using namespace drizzled;55using namespace drizzled;
@@ -44,18 +58,15 @@
44namespace drizzle_protocol58namespace drizzle_protocol
45{59{
4660
47
48static const uint32_t DRIZZLE_TCP_PORT= 4427;
49static const unsigned int PACKET_BUFFER_EXTRA_ALLOC= 1024;
50static uint32_t port;61static uint32_t port;
51static uint32_t connect_timeout;62static uint32_t connect_timeout;
52static uint32_t read_timeout;63static uint32_t read_timeout;
53static uint32_t write_timeout;64static uint32_t write_timeout;
54static uint32_t retry_count;65static uint32_t retry_count;
55static uint32_t buffer_length;66static uint32_t buffer_length;
56static char* bind_address= NULL;67static char* bind_address;
5768
58static plugin::TableFunction* drizzle_status_table_function_ptr= NULL;69static const uint32_t DRIZZLE_TCP_PORT= 4427;
5970
60ListenDrizzleProtocol::~ListenDrizzleProtocol()71ListenDrizzleProtocol::~ListenDrizzleProtocol()
61{72{
@@ -70,770 +81,11 @@
7081
71in_port_t ListenDrizzleProtocol::getPort(void) const82in_port_t ListenDrizzleProtocol::getPort(void) const
72{83{
73 char *env;
74
75 if (port == 0)
76 {
77 port= DRIZZLE_TCP_PORT;
78
79 if ((env = getenv("DRIZZLE_TCP_PORT")))
80 port= (uint32_t) atoi(env);
81
82 assert(port != 0);
83 }
84
85 return (in_port_t) port;84 return (in_port_t) port;
86}85}
8786
88plugin::Client *ListenDrizzleProtocol::getClient(int fd)87static int init(drizzled::module::Context &context)
89{88{
90 int new_fd;
91 new_fd= acceptTcp(fd);
92 if (new_fd == -1)
93 return NULL;
94
95 return new (nothrow) ClientDrizzleProtocol(new_fd, using_mysql41_protocol);
96}
97
98drizzled::atomic<uint64_t> ClientDrizzleProtocol::connectionCount;
99drizzled::atomic<uint64_t> ClientDrizzleProtocol::failedConnections;
100drizzled::atomic<uint64_t> ClientDrizzleProtocol::connected;
101
102ClientDrizzleProtocol::ClientDrizzleProtocol(int fd, bool using_mysql41_protocol_arg):
103 using_mysql41_protocol(using_mysql41_protocol_arg)
104{
105 net.vio= 0;
106
107 if (fd == -1)
108 return;
109
110 if (drizzleclient_net_init_sock(&net, fd, 0, buffer_length))
111 throw bad_alloc();
112
113 drizzleclient_net_set_read_timeout(&net, read_timeout);
114 drizzleclient_net_set_write_timeout(&net, write_timeout);
115 net.retry_count=retry_count;
116}
117
118ClientDrizzleProtocol::~ClientDrizzleProtocol()
119{
120 if (net.vio)
121 drizzleclient_vio_close(net.vio);
122}
123
124int ClientDrizzleProtocol::getFileDescriptor(void)
125{
126 return drizzleclient_net_get_sd(&net);
127}
128
129bool ClientDrizzleProtocol::isConnected()
130{
131 return net.vio != 0;
132}
133
134bool ClientDrizzleProtocol::isReading(void)
135{
136 return net.reading_or_writing == 1;
137}
138
139bool ClientDrizzleProtocol::isWriting(void)
140{
141 return net.reading_or_writing == 2;
142}
143
144bool ClientDrizzleProtocol::flush()
145{
146 if (net.vio == NULL)
147 return false;
148 bool ret= drizzleclient_net_write(&net, (unsigned char*) packet.ptr(),
149 packet.length());
150 packet.length(0);
151 return ret;
152}
153
154void ClientDrizzleProtocol::close(void)
155{
156 if (net.vio)
157 {
158 drizzleclient_net_close(&net);
159 drizzleclient_net_end(&net);
160 connected.decrement();
161 }
162}
163
164bool ClientDrizzleProtocol::authenticate()
165{
166 bool connection_is_valid;
167
168 connectionCount.increment();
169 connected.increment();
170
171 /* Use "connect_timeout" value during connection phase */
172 drizzleclient_net_set_read_timeout(&net, connect_timeout);
173 drizzleclient_net_set_write_timeout(&net, connect_timeout);
174
175 connection_is_valid= checkConnection();
176
177 if (connection_is_valid)
178 sendOK();
179 else
180 {
181 sendError(session->main_da.sql_errno(), session->main_da.message());
182 failedConnections.increment();
183 return false;
184 }
185
186 /* Connect completed, set read/write timeouts back to default */
187 drizzleclient_net_set_read_timeout(&net, read_timeout);
188 drizzleclient_net_set_write_timeout(&net, write_timeout);
189 return true;
190}
191
192bool ClientDrizzleProtocol::readCommand(char **l_packet, uint32_t *packet_length)
193{
194 /*
195 This thread will do a blocking read from the client which
196 will be interrupted when the next command is received from
197 the client, the connection is closed or "net_wait_timeout"
198 number of seconds has passed
199 */
200#ifdef NEVER
201 /* We can do this much more efficiently with poll timeouts or watcher thread,
202 disabling for now, which means net_wait_timeout == read_timeout. */
203 drizzleclient_net_set_read_timeout(&net,
204 session->variables.net_wait_timeout);
205#endif
206
207 net.pkt_nr=0;
208
209 *packet_length= drizzleclient_net_read(&net);
210 if (*packet_length == packet_error)
211 {
212 /* Check if we can continue without closing the connection */
213
214 if(net.last_errno== CR_NET_PACKET_TOO_LARGE)
215 my_error(ER_NET_PACKET_TOO_LARGE, MYF(0));
216 if (session->main_da.status() == Diagnostics_area::DA_ERROR)
217 sendError(session->main_da.sql_errno(), session->main_da.message());
218 else
219 sendOK();
220
221 if (net.error != 3)
222 return false; // We have to close it.
223
224 net.error= 0;
225 *packet_length= 0;
226 return true;
227 }
228
229 *l_packet= (char*) net.read_pos;
230
231 /*
232 'packet_length' contains length of data, as it was stored in packet
233 header. In case of malformed header, drizzleclient_net_read returns zero.
234 If packet_length is not zero, drizzleclient_net_read ensures that the returned
235 number of bytes was actually read from network.
236 There is also an extra safety measure in drizzleclient_net_read:
237 it sets packet[packet_length]= 0, but only for non-zero packets.
238 */
239
240 if (*packet_length == 0) /* safety */
241 {
242 /* Initialize with COM_SLEEP packet */
243 (*l_packet)[0]= (unsigned char) COM_SLEEP;
244 *packet_length= 1;
245 }
246 else if (using_mysql41_protocol)
247 {
248 /* Map from MySQL commands to Drizzle commands. */
249 switch ((int)(*l_packet)[0])
250 {
251 case 0: /* SLEEP */
252 case 1: /* QUIT */
253 case 2: /* INIT_DB */
254 case 3: /* QUERY */
255 break;
256
257 case 8: /* SHUTDOWN */
258 (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
259 break;
260
261 case 14: /* PING */
262 (*l_packet)[0]= (unsigned char) COM_SHUTDOWN;
263 break;
264
265
266 default:
267 /* Just drop connection for MySQL commands we don't support. */
268 (*l_packet)[0]= (unsigned char) COM_QUIT;
269 *packet_length= 1;
270 break;
271 }
272 }
273
274 /* Do not rely on drizzleclient_net_read, extra safety against programming errors. */
275 (*l_packet)[*packet_length]= '\0'; /* safety */
276
277#ifdef NEVER
278 /* See comment above. */
279 /* Restore read timeout value */
280 drizzleclient_net_set_read_timeout(&net,
281 session->variables.net_read_timeout);
282#endif
283
284 return true;
285}
286
287/**
288 Return ok to the client.
289
290 The ok packet has the following structure:
291
292 - 0 : Marker (1 byte)
293 - affected_rows : Stored in 1-9 bytes
294 - id : Stored in 1-9 bytes
295 - server_status : Copy of session->server_status; Can be used by client
296 to check if we are inside an transaction.
297 New in 4.0 client
298 - warning_count : Stored in 2 bytes; New in 4.1 client
299 - message : Stored as packed length (1-9 bytes) + message.
300 Is not stored if no message.
301
302 @param session Thread handler
303 @param affected_rows Number of rows changed by statement
304 @param id Auto_increment id for first row (if used)
305 @param message Message to send to the client (Used by mysql_status)
306*/
307
308void ClientDrizzleProtocol::sendOK()
309{
310 unsigned char buff[DRIZZLE_ERRMSG_SIZE+10],*pos;
311 const char *message= NULL;
312 uint32_t tmp;
313
314 if (!net.vio) // hack for re-parsing queries
315 {
316 return;
317 }
318
319 buff[0]=0; // No fields
320 if (session->main_da.status() == Diagnostics_area::DA_OK)
321 {
322 if (client_capabilities & CLIENT_FOUND_ROWS && session->main_da.found_rows())
323 pos=drizzleclient_net_store_length(buff+1,session->main_da.found_rows());
324 else
325 pos=drizzleclient_net_store_length(buff+1,session->main_da.affected_rows());
326 pos=drizzleclient_net_store_length(pos, session->main_da.last_insert_id());
327 int2store(pos, session->main_da.server_status());
328 pos+=2;
329 tmp= min(session->main_da.total_warn_count(), (uint32_t)65535);
330 message= session->main_da.message();
331 }
332 else
333 {
334 pos=drizzleclient_net_store_length(buff+1,0);
335 pos=drizzleclient_net_store_length(pos, 0);
336 int2store(pos, session->server_status);
337 pos+=2;
338 tmp= min(session->total_warn_count, (uint32_t)65535);
339 }
340
341 /* We can only return up to 65535 warnings in two bytes */
342 int2store(pos, tmp);
343 pos+= 2;
344
345 session->main_da.can_overwrite_status= true;
346
347 if (message && message[0])
348 {
349 size_t length= strlen(message);
350 pos=drizzleclient_net_store_length(pos,length);
351 memcpy(pos,(unsigned char*) message,length);
352 pos+=length;
353 }
354 drizzleclient_net_write(&net, buff, (size_t) (pos-buff));
355 drizzleclient_net_flush(&net);
356
357 session->main_da.can_overwrite_status= false;
358}
359
360/**
361 Send eof (= end of result set) to the client.
362
363 The eof packet has the following structure:
364
365 - 254 (DRIZZLE_PROTOCOL_NO_MORE_DATA) : Marker (1 byte)
366 - warning_count : Stored in 2 bytes; New in 4.1 client
367 - status_flag : Stored in 2 bytes;
368 For flags like SERVER_MORE_RESULTS_EXISTS.
369
370 Note that the warning count will not be sent if 'no_flush' is set as
371 we don't want to report the warning count until all data is sent to the
372 client.
373*/
374
375void ClientDrizzleProtocol::sendEOF()
376{
377 /* Set to true if no active vio, to work well in case of --init-file */
378 if (net.vio != 0)
379 {
380 session->main_da.can_overwrite_status= true;
381 writeEOFPacket(session->main_da.server_status(),
382 session->main_da.total_warn_count());
383 drizzleclient_net_flush(&net);
384 session->main_da.can_overwrite_status= false;
385 }
386 packet.shrink(buffer_length);
387}
388
389
390void ClientDrizzleProtocol::sendError(uint32_t sql_errno, const char *err)
391{
392 uint32_t length;
393 /*
394 buff[]: sql_errno:2 + ('#':1 + SQLSTATE_LENGTH:5) + DRIZZLE_ERRMSG_SIZE:512
395 */
396 unsigned char buff[2+1+SQLSTATE_LENGTH+DRIZZLE_ERRMSG_SIZE], *pos;
397
398 assert(sql_errno);
399 assert(err && err[0]);
400
401 /*
402 It's one case when we can push an error even though there
403 is an OK or EOF already.
404 */
405 session->main_da.can_overwrite_status= true;
406
407 /* Abort multi-result sets */
408 session->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
409
410 /**
411 Send a error string to client.
412
413 For SIGNAL/RESIGNAL and GET DIAGNOSTICS functionality it's
414 critical that every error that can be intercepted is issued in one
415 place only, my_message_sql.
416 */
417
418 if (net.vio == 0)
419 {
420 return;
421 }
422
423 int2store(buff,sql_errno);
424 pos= buff+2;
425
426 /* The first # is to make the client backward compatible */
427 buff[2]= '#';
428 pos= (unsigned char*) strcpy((char*) buff+3, drizzle_errno_to_sqlstate(sql_errno));
429 pos+= strlen(drizzle_errno_to_sqlstate(sql_errno));
430
431 char *tmp= strncpy((char*)pos, err, DRIZZLE_ERRMSG_SIZE-1);
432 tmp+= strlen((char*)pos);
433 tmp[0]= '\0';
434 length= (uint32_t)(tmp-(char*)buff);
435 err= (char*) buff;
436
437 drizzleclient_net_write_command(&net,(unsigned char) 255, (unsigned char*) "", 0, (unsigned char*) err, length);
438
439 session->main_da.can_overwrite_status= false;
440}
441
442/**
443 Send name and type of result to client.
444
445 Sum fields has table name empty and field_name.
446
447 @param Session Thread data object
448 @param list List of items to send to client
449 @param flag Bit mask with the following functions:
450 - 1 send number of rows
451 - 2 send default values
452 - 4 don't write eof packet
453
454 @retval
455 0 ok
456 @retval
457 1 Error (Note that in this case the error is not sent to the
458 client)
459*/
460bool ClientDrizzleProtocol::sendFields(List<Item> *list)
461{
462 List_iterator_fast<Item> it(*list);
463 Item *item;
464 unsigned char buff[80];
465 String tmp((char*) buff,sizeof(buff),&my_charset_bin);
466
467 unsigned char *row_pos= drizzleclient_net_store_length(buff, list->elements);
468 (void) drizzleclient_net_write(&net, buff, (size_t) (row_pos-buff));
469
470 while ((item=it++))
471 {
472 char *pos;
473 SendField field;
474 item->make_field(&field);
475
476 packet.length(0);
477
478 if (store(STRING_WITH_LEN("def")) ||
479 store(field.db_name) ||
480 store(field.table_name) ||
481 store(field.org_table_name) ||
482 store(field.col_name) ||
483 store(field.org_col_name) ||
484 packet.realloc(packet.length()+12))
485 goto err;
486
487 /* Store fixed length fields */
488 pos= (char*) packet.ptr()+packet.length();
489 *pos++= 12; // Length of packed fields
490 /* No conversion */
491 int2store(pos, field.charsetnr);
492 int4store(pos+2, field.length);
493
494 if (using_mysql41_protocol)
495 {
496 /* Switch to MySQL field numbering. */
497 switch (field.type)
498 {
499 case DRIZZLE_TYPE_LONG:
500 pos[6]= 3;
501 break;
502
503 case DRIZZLE_TYPE_DOUBLE:
504 pos[6]= 5;
505 break;
506
507 case DRIZZLE_TYPE_NULL:
508 pos[6]= 6;
509 break;
510
511 case DRIZZLE_TYPE_TIMESTAMP:
512 pos[6]= 7;
513 break;
514
515 case DRIZZLE_TYPE_LONGLONG:
516 pos[6]= 8;
517 break;
518
519 case DRIZZLE_TYPE_DATETIME:
520 pos[6]= 12;
521 break;
522
523 case DRIZZLE_TYPE_DATE:
524 pos[6]= 14;
525 break;
526
527 case DRIZZLE_TYPE_VARCHAR:
528 pos[6]= 15;
529 break;
530
531 case DRIZZLE_TYPE_DECIMAL:
532 pos[6]= (char)246;
533 break;
534
535 case DRIZZLE_TYPE_ENUM:
536 pos[6]= (char)247;
537 break;
538
539 case DRIZZLE_TYPE_BLOB:
540 pos[6]= (char)252;
541 break;
542 }
543 }
544 else
545 {
546 /* Add one to compensate for tinyint removal from enum. */
547 pos[6]= field.type + 1;
548 }
549
550 int2store(pos+7,field.flags);
551 pos[9]= (char) field.decimals;
552 pos[10]= 0; // For the future
553 pos[11]= 0; // For the future
554 pos+= 12;
555
556 packet.length((uint32_t) (pos - packet.ptr()));
557 if (flush())
558 break;
559 }
560
561 /*
562 Mark the end of meta-data result set, and store session->server_status,
563 to show that there is no cursor.
564 Send no warning information, as it will be sent at statement end.
565 */
566 writeEOFPacket(session->server_status, session->total_warn_count);
567 return 0;
568
569err:
570 my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
571 MYF(0));
572 return 1;
573}
574
575bool ClientDrizzleProtocol::store(Field *from)
576{
577 if (from->is_null())
578 return store();
579 char buff[MAX_FIELD_WIDTH];
580 String str(buff,sizeof(buff), &my_charset_bin);
581
582 from->val_str(&str);
583
584 return netStoreData((const unsigned char *)str.ptr(), str.length());
585}
586
587bool ClientDrizzleProtocol::store(void)
588{
589 char buff[1];
590 buff[0]= (char)251;
591 return packet.append(buff, sizeof(buff), PACKET_BUFFER_EXTRA_ALLOC);
592}
593
594bool ClientDrizzleProtocol::store(int32_t from)
595{
596 char buff[12];
597 return netStoreData((unsigned char*) buff,
598 (size_t) (internal::int10_to_str(from, buff, -10) - buff));
599}
600
601bool ClientDrizzleProtocol::store(uint32_t from)
602{
603 char buff[11];
604 return netStoreData((unsigned char*) buff,
605 (size_t) (internal::int10_to_str(from, buff, 10) - buff));
606}
607
608bool ClientDrizzleProtocol::store(int64_t from)
609{
610 char buff[22];
611 return netStoreData((unsigned char*) buff,
612 (size_t) (internal::int64_t10_to_str(from, buff, -10) - buff));
613}
614
615bool ClientDrizzleProtocol::store(uint64_t from)
616{
617 char buff[21];
618 return netStoreData((unsigned char*) buff,
619 (size_t) (internal::int64_t10_to_str(from, buff, 10) - buff));
620}
621
622bool ClientDrizzleProtocol::store(double from, uint32_t decimals, String *buffer)
623{
624 buffer->set_real(from, decimals, session->charset());
625 return netStoreData((unsigned char*) buffer->ptr(), buffer->length());
626}
627
628bool ClientDrizzleProtocol::store(const char *from, size_t length)
629{
630 return netStoreData((const unsigned char *)from, length);
631}
632
633bool ClientDrizzleProtocol::wasAborted(void)
634{
635 return net.error && net.vio != 0;
636}
637
638bool ClientDrizzleProtocol::haveMoreData(void)
639{
640 return drizzleclient_net_more_data(&net);
641}
642
643bool ClientDrizzleProtocol::haveError(void)
644{
645 return net.error || net.vio == 0;
646}
647
648bool ClientDrizzleProtocol::checkConnection(void)
649{
650 uint32_t pkt_len= 0;
651 char *end;
652
653 // TCP/IP connection
654 {
655 char ip[NI_MAXHOST];
656 uint16_t peer_port;
657
658 if (drizzleclient_net_peer_addr(&net, ip, &peer_port, NI_MAXHOST))
659 {
660 my_error(ER_BAD_HOST_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
661 return false;
662 }
663
664 session->getSecurityContext().setIp(ip);
665 }
666 drizzleclient_net_keepalive(&net, true);
667
668 uint32_t server_capabilites;
669 {
670 /* buff[] needs to big enough to hold the server_version variable */
671 char buff[SERVER_VERSION_LENGTH + SCRAMBLE_LENGTH + 64];
672
673 server_capabilites= CLIENT_BASIC_FLAGS;
674
675 if (using_mysql41_protocol)
676 server_capabilites|= CLIENT_PROTOCOL_MYSQL41;
677
678#ifdef HAVE_COMPRESS
679 server_capabilites|= CLIENT_COMPRESS;
680#endif /* HAVE_COMPRESS */
681
682 end= buff + strlen(PANDORA_RELEASE_VERSION);
683 if ((end - buff) >= SERVER_VERSION_LENGTH)
684 end= buff + (SERVER_VERSION_LENGTH - 1);
685 memcpy(buff, PANDORA_RELEASE_VERSION, end - buff);
686 *end= 0;
687 end++;
688
689 int4store((unsigned char*) end, session->variables.pseudo_thread_id);
690 end+= 4;
691
692 /* We don't use scramble anymore. */
693 memset(end, 'X', SCRAMBLE_LENGTH_323);
694 end+= SCRAMBLE_LENGTH_323;
695 *end++= 0; /* an empty byte for some reason */
696
697 int2store(end, server_capabilites);
698 /* write server characteristics: up to 16 bytes allowed */
699 end[2]=(char) default_charset_info->number;
700 int2store(end+3, session->server_status);
701 memset(end+5, 0, 13);
702 end+= 18;
703
704 /* Write scramble tail. */
705 memset(end, 'X', SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
706 end+= (SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
707 *end++= 0; /* an empty byte for some reason */
708
709 /* At this point we write connection message and read reply */
710 if (drizzleclient_net_write_command(&net
711 , (unsigned char) PROTOCOL_VERSION
712 , (unsigned char*) ""
713 , 0
714 , (unsigned char*) buff
715 , (size_t) (end-buff))
716 || (pkt_len= drizzleclient_net_read(&net)) == packet_error
717 || pkt_len < MIN_HANDSHAKE_SIZE)
718 {
719 my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
720 return false;
721 }
722 }
723 if (packet.alloc(buffer_length))
724 return false; /* The error is set by alloc(). */
725
726 client_capabilities= uint2korr(net.read_pos);
727
728
729 client_capabilities|= ((uint32_t) uint2korr(net.read_pos + 2)) << 16;
730 session->max_client_packet_length= uint4korr(net.read_pos + 4);
731 end= (char*) net.read_pos + 32;
732
733 /*
734 Disable those bits which are not supported by the server.
735 This is a precautionary measure, if the client lies. See Bug#27944.
736 */
737 client_capabilities&= server_capabilites;
738
739 if (end >= (char*) net.read_pos + pkt_len + 2)
740 {
741 my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
742 return false;
743 }
744
745 net.return_status= &session->server_status;
746
747 char *user= end;
748 char *passwd= strchr(user, '\0')+1;
749 uint32_t user_len= passwd - user - 1;
750 char *l_db= passwd;
751
752 /*
753 Old clients send null-terminated string as password; new clients send
754 the size (1 byte) + string (not null-terminated). Hence in case of empty
755 password both send '\0'.
756
757 This strlen() can't be easily deleted without changing client.
758
759 Cast *passwd to an unsigned char, so that it doesn't extend the sign for
760 *passwd > 127 and become 2**32-127+ after casting to uint.
761 */
762 uint32_t passwd_len= client_capabilities & CLIENT_SECURE_CONNECTION ?
763 (unsigned char)(*passwd++) : strlen(passwd);
764 l_db= client_capabilities & CLIENT_CONNECT_WITH_DB ? l_db + passwd_len + 1 : 0;
765
766 /* strlen() can't be easily deleted without changing client */
767 uint32_t db_len= l_db ? strlen(l_db) : 0;
768
769 if (passwd + passwd_len + db_len > (char *) net.read_pos + pkt_len)
770 {
771 my_error(ER_HANDSHAKE_ERROR, MYF(0), session->getSecurityContext().getIp().c_str());
772 return false;
773 }
774
775 /* If username starts and ends in "'", chop them off */
776 if (user_len > 1 && user[0] == '\'' && user[user_len - 1] == '\'')
777 {
778 user[user_len-1]= 0;
779 user++;
780 user_len-= 2;
781 }
782
783 session->getSecurityContext().setUser(user);
784
785 return session->checkUser(passwd, passwd_len, l_db);
786}
787
788bool ClientDrizzleProtocol::netStoreData(const unsigned char *from, size_t length)
789{
790 size_t packet_length= packet.length();
791 /*
792 The +9 comes from that strings of length longer than 16M require
793 9 bytes to be stored (see drizzleclient_net_store_length).
794 */
795 if (packet_length+9+length > packet.alloced_length() &&
796 packet.realloc(packet_length+9+length))
797 return 1;
798 unsigned char *to= drizzleclient_net_store_length((unsigned char*) packet.ptr()+packet_length, length);
799 memcpy(to,from,length);
800 packet.length((size_t) (to+length-(unsigned char*) packet.ptr()));
801 return 0;
802}
803
804/**
805 Format EOF packet according to the current client and
806 write it to the network output buffer.
807*/
808
809void ClientDrizzleProtocol::writeEOFPacket(uint32_t server_status,
810 uint32_t total_warn_count)
811{
812 unsigned char buff[5];
813 /*
814 Don't send warn count during SP execution, as the warn_list
815 is cleared between substatements, and mysqltest gets confused
816 */
817 uint32_t tmp= min(total_warn_count, (uint32_t)65535);
818 buff[0]= DRIZZLE_PROTOCOL_NO_MORE_DATA;
819 int2store(buff+1, tmp);
820 /*
821 The following test should never be true, but it's better to do it
822 because if 'is_fatal_error' is set the server is not going to execute
823 other queries (see the if test in dispatch_command / COM_QUERY)
824 */
825 if (session->is_fatal_error)
826 server_status&= ~SERVER_MORE_RESULTS_EXISTS;
827 int2store(buff + 3, server_status);
828 drizzleclient_net_write(&net, buff, 5);
829}
830
831static int init(module::Context &context)
832{
833 drizzle_status_table_function_ptr= new DrizzleProtocolStatus;
834
835 context.add(drizzle_status_table_function_ptr);
836
837 const module::option_map &vm= context.getOptions();89 const module::option_map &vm= context.getOptions();
838 if (vm.count("port"))90 if (vm.count("port"))
839 { 91 {
@@ -875,7 +127,7 @@
875 {127 {
876 if (retry_count < 1 || retry_count > 100)128 if (retry_count < 1 || retry_count > 100)
877 {129 {
878 errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for retry_count\n"));130 errmsg_printf(ERRMSG_LVL_ERROR, _("Invalid value for retry_count"));
879 exit(-1);131 exit(-1);
880 }132 }
881 }133 }
@@ -898,17 +150,16 @@
898 {150 {
899 bind_address= NULL;151 bind_address= NULL;
900 }152 }
901 153
902 context.add(new ListenDrizzleProtocol("drizzle_protocol", false)); 154 context.add(new StatusTable);
155 context.add(new ListenDrizzleProtocol("drizzle_protocol", true));
156
903 return 0;157 return 0;
904}158}
905159
906static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,160static DRIZZLE_SYSVAR_UINT(port, port, PLUGIN_VAR_RQCMDARG,
907 N_("Port number to use for connection or 0 for "161 N_("Port number to use for connection or 0 for default to with Drizzle/MySQL protocol."),
908 "default to, in order of "162 NULL, NULL, DRIZZLE_TCP_PORT, 0, 65535, 0);
909 "preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
910 "built-in default (4427)."),
911 NULL, NULL, 0, 0, 65535, 0);
912static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,163static DRIZZLE_SYSVAR_UINT(connect_timeout, connect_timeout,
913 PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),164 PLUGIN_VAR_RQCMDARG, N_("Connect Timeout."),
914 NULL, NULL, 10, 1, 300, 0);165 NULL, NULL, 10, 1, 300, 0);
@@ -927,11 +178,8 @@
927static void init_options(drizzled::module::option_context &context)178static void init_options(drizzled::module::option_context &context)
928{179{
929 context("port",180 context("port",
930 po::value<uint32_t>(&port)->default_value(0),181 po::value<uint32_t>(&port)->default_value(DRIZZLE_TCP_PORT),
931 N_("Port number to use for connection or 0 for "182 N_("Port number to use for connection or 0 for default to with Drizzle/MySQL protocol."));
932 "default to, in order of "
933 "preference, drizzle.cnf, $DRIZZLE_TCP_PORT, "
934 "built-in default (4427)."));
935 context("connect-timeout",183 context("connect-timeout",
936 po::value<uint32_t>(&connect_timeout)->default_value(10),184 po::value<uint32_t>(&connect_timeout)->default_value(10),
937 N_("Connect Timeout."));185 N_("Connect Timeout."));
@@ -963,103 +211,6 @@
963 NULL211 NULL
964};212};
965213
966static int drizzle_protocol_connection_count_func(drizzle_show_var *var, char *buff)
967{
968 var->type= SHOW_LONGLONG;
969 var->value= buff;
970 *((uint64_t *)buff)= ClientDrizzleProtocol::connectionCount;
971 return 0;
972}
973
974static int drizzle_protocol_connected_count_func(drizzle_show_var *var, char *buff)
975{
976 var->type= SHOW_LONGLONG;
977 var->value= buff;
978 *((uint64_t *)buff)= ClientDrizzleProtocol::connected;
979 return 0;
980}
981
982static int drizzle_protocol_failed_count_func(drizzle_show_var *var, char *buff)
983{
984 var->type= SHOW_LONGLONG;
985 var->value= buff;
986 *((uint64_t *)buff)= ClientDrizzleProtocol::failedConnections;
987 return 0;
988}
989
990static st_show_var_func_container drizzle_protocol_connection_count=
991 { &drizzle_protocol_connection_count_func };
992
993static st_show_var_func_container drizzle_protocol_connected_count=
994 { &drizzle_protocol_connected_count_func };
995
996static st_show_var_func_container drizzle_protocol_failed_count=
997 { &drizzle_protocol_failed_count_func };
998
999static drizzle_show_var drizzle_protocol_status_variables[]= {
1000 {"Connections",
1001 (char*) &drizzle_protocol_connection_count, SHOW_FUNC},
1002 {"Connected",
1003 (char*) &drizzle_protocol_connected_count, SHOW_FUNC},
1004 {"Failed_connections",
1005 (char*) &drizzle_protocol_failed_count, SHOW_FUNC},
1006 {NULL, NULL, SHOW_LONGLONG}
1007};
1008
1009DrizzleProtocolStatus::Generator::Generator(drizzled::Field **fields) :
1010 plugin::TableFunction::Generator(fields)
1011{
1012 status_var_ptr= drizzle_protocol_status_variables;
1013}
1014
1015bool DrizzleProtocolStatus::Generator::populate()
1016{
1017 MY_ALIGNED_BYTE_ARRAY(buff_data, SHOW_VAR_FUNC_BUFF_SIZE, int64_t);
1018 char * const buff= (char *) &buff_data;
1019 drizzle_show_var tmp;
1020
1021 if (status_var_ptr->name)
1022 {
1023 std::ostringstream oss;
1024 string return_value;
1025 const char *value;
1026 int type;
1027
1028 push(status_var_ptr->name);
1029
1030 if (status_var_ptr->type == SHOW_FUNC)
1031 {
1032 ((mysql_show_var_func)((st_show_var_func_container *)status_var_ptr->value)->func)(&tmp, buff);
1033 value= buff;
1034 type= tmp.type;
1035 }
1036 else
1037 {
1038 value= status_var_ptr->value;
1039 type= status_var_ptr->type;
1040 }
1041
1042 switch(type)
1043 {
1044 case SHOW_LONGLONG:
1045 oss << *(uint64_t*) value;
1046 return_value= oss.str();
1047 break;
1048 default:
1049 assert(0);
1050 }
1051 if (return_value.length())
1052 push(return_value);
1053 else
1054 push(" ");
1055
1056 status_var_ptr++;
1057
1058 return true;
1059 }
1060 return false;
1061}
1062
1063} /* namespace drizzle_protocol */214} /* namespace drizzle_protocol */
1064215
1065DRIZZLE_PLUGIN(drizzle_protocol::init, drizzle_protocol::sys_variables, drizzle_protocol::init_options);216DRIZZLE_PLUGIN(drizzle_protocol::init, drizzle_protocol::sys_variables, drizzle_protocol::init_options);
1066217
=== modified file 'plugin/drizzle_protocol/drizzle_protocol.h'
--- plugin/drizzle_protocol/drizzle_protocol.h 2010-09-01 19:17:03 +0000
+++ plugin/drizzle_protocol/drizzle_protocol.h 2010-10-06 01:14:00 +0000
@@ -1,11 +1,12 @@
1/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-1/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:2 * vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3 *3 *
4 * Copyright (C) 2008 Sun Microsystems4 * Copyright (C) 2010 Brian Aker
5 *5 *
6 * This program is free software; you can redistribute it and/or modify6 * 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 by7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License.8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
9 *10 *
10 * This program is distributed in the hope that it will be useful,11 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -17,6 +18,7 @@
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */19 */
1920
21
20#ifndef PLUGIN_DRIZZLE_PROTOCOL_DRIZZLE_PROTOCOL_H22#ifndef PLUGIN_DRIZZLE_PROTOCOL_DRIZZLE_PROTOCOL_H
21#define PLUGIN_DRIZZLE_PROTOCOL_DRIZZLE_PROTOCOL_H23#define PLUGIN_DRIZZLE_PROTOCOL_DRIZZLE_PROTOCOL_H
2224
@@ -25,77 +27,24 @@
25#include <drizzled/atomics.h>27#include <drizzled/atomics.h>
26#include "drizzled/plugin/table_function.h"28#include "drizzled/plugin/table_function.h"
2729
28#include "net_serv.h"30#include "plugin/mysql_protocol/mysql_protocol.h"
2931
30namespace drizzle_protocol32namespace drizzle_protocol
31{33{
3234
33class ListenDrizzleProtocol: public drizzled::plugin::ListenTcp35class ListenDrizzleProtocol: public ListenMySQLProtocol
34{36{
35private:
36 bool using_mysql41_protocol;
37
38public:37public:
39 ListenDrizzleProtocol(std::string name_arg, bool using_mysql41_protocol_arg):38 ListenDrizzleProtocol(std::string name_arg, bool using_mysql41_protocol_arg):
40 drizzled::plugin::ListenTcp(name_arg),39 ListenMySQLProtocol(name_arg, using_mysql41_protocol_arg)
41 using_mysql41_protocol(using_mysql41_protocol_arg)
42 { }40 { }
43 virtual ~ListenDrizzleProtocol();41
44 virtual const char* getHost(void) const;42 ~ListenDrizzleProtocol();
45 virtual in_port_t getPort(void) const;43
46 virtual drizzled::plugin::Client *getClient(int fd);44 const char* getHost(void) const;
47};45 in_port_t getPort(void) const;
4846};
49class ClientDrizzleProtocol: public drizzled::plugin::Client47
50{
51private:
52 NET net;
53 drizzled::String packet;
54 uint32_t client_capabilities;
55 bool using_mysql41_protocol;
56
57 bool checkConnection(void);
58 bool netStoreData(const unsigned char *from, size_t length);
59 void writeEOFPacket(uint32_t server_status, uint32_t total_warn_count);
60
61public:
62 ClientDrizzleProtocol(int fd, bool using_mysql41_protocol_arg);
63 virtual ~ClientDrizzleProtocol();
64
65 static drizzled::atomic<uint64_t> connectionCount;
66 static drizzled::atomic<uint64_t> failedConnections;
67 static drizzled::atomic<uint64_t> connected;
68
69 virtual int getFileDescriptor(void);
70 virtual bool isConnected();
71 virtual bool isReading(void);
72 virtual bool isWriting(void);
73 virtual bool flush(void);
74 virtual void close(void);
75
76 virtual bool authenticate(void);
77 virtual bool readCommand(char **packet, uint32_t *packet_length);
78
79 virtual void sendOK(void);
80 virtual void sendEOF(void);
81 virtual void sendError(uint32_t sql_errno, const char *err);
82
83 virtual bool sendFields(drizzled::List<drizzled::Item> *list);
84
85 using Client::store;
86 virtual bool store(drizzled::Field *from);
87 virtual bool store(void);
88 virtual bool store(int32_t from);
89 virtual bool store(uint32_t from);
90 virtual bool store(int64_t from);
91 virtual bool store(uint64_t from);
92 virtual bool store(double from, uint32_t decimals, drizzled::String *buffer);
93 virtual bool store(const char *from, size_t length);
94
95 virtual bool haveError(void);
96 virtual bool haveMoreData(void);
97 virtual bool wasAborted(void);
98};
9948
100} /* namespace drizzle_protocol */49} /* namespace drizzle_protocol */
10150
10251
=== modified file 'plugin/drizzle_protocol/errmsg.cc'
--- plugin/drizzle_protocol/errmsg.cc 2010-03-04 18:06:27 +0000
+++ plugin/drizzle_protocol/errmsg.cc 2010-10-06 01:14:00 +0000
@@ -17,7 +17,7 @@
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */18 */
1919
20/* Error messages for MySQL clients */20/* Stub file for error messages */
2121
22#include "config.h"22#include "config.h"
23#include <drizzled/gettext.h>23#include <drizzled/gettext.h>
@@ -25,96 +25,4 @@
2525
26namespace drizzle_protocol26namespace drizzle_protocol
27{27{
28
29static const char *client_errors[]=
30{
31 N_("Unknown Drizzle error"),
32 N_("Can't create UNIX socket (%d)"),
33 N_("Can't connect to local Drizzle server through socket '%-.100s' (%d)"),
34 N_("Can't connect to Drizzle server on '%-.100s:%lu' (%d)"),
35 N_("Can't create TCP/IP socket (%d)"),
36 N_("Unknown Drizzle server host '%-.100s' (%d)"),
37 N_("Drizzle server has gone away"),
38 N_("Protocol mismatch; server version = %d, client version = %d"),
39 N_("Drizzle client ran out of memory"),
40 N_("Wrong host info"),
41 N_("Localhost via UNIX socket"),
42 N_("%-.100s via TCP/IP"),
43 N_("Error in server handshake"),
44 N_("Lost connection to Drizzle server during query"),
45 N_("Commands out of sync; you can't run this command now"),
46 N_("Named pipe: %-.32s"),
47 N_("Can't wait for named pipe to host: %-.64s pipe: %-.32s (%lu)"),
48 N_("Can't open named pipe to host: %-.64s pipe: %-.32s (%lu)"),
49 N_("Can't set state of named pipe to host: %-.64s pipe: %-.32s (%lu)"),
50 N_("Can't initialize character set %-.32s (path: %-.100s)"),
51 N_("Got packet bigger than 'max_allowed_packet' bytes"),
52 N_("Embedded server"),
53 N_("Error on SHOW SLAVE STATUS:"),
54 N_("Error on SHOW SLAVE HOSTS:"),
55 N_("Error connecting to slave:"),
56 N_("Error connecting to master:"),
57 N_("SSL connection error"),
58 N_("Malformed packet"),
59 N_("(unused error message)"),
60 N_("Invalid use of null pointer"),
61 N_("Statement not prepared"),
62 N_("No data supplied for parameters in prepared statement"),
63 N_("Data truncated"),
64 N_("No parameters exist in the statement"),
65 N_("Invalid parameter number"),
66 N_("Can't send long data for non-string/non-binary data types "
67 "(parameter: %d)"),
68 N_("Using unsupported buffer type: %d (parameter: %d)"),
69 N_("Shared memory: %-.100s"),
70 N_("(unused error message)"),
71 N_("(unused error message)"),
72 N_("(unused error message)"),
73 N_("(unused error message)"),
74 N_("(unused error message)"),
75 N_("(unused error message)"),
76 N_("(unused error message)"),
77 N_("(unused error message)"),
78 N_("(unused error message)"),
79 N_("Wrong or unknown protocol"),
80 N_("Invalid connection handle"),
81 N_("Connection using old (pre-4.1.1) authentication protocol refused "
82 "(client option 'secure_auth' enabled)"),
83 N_("Row retrieval was canceled by drizzle_stmt_close() call"),
84 N_("Attempt to read column without prior row fetch"),
85 N_("Prepared statement contains no metadata"),
86 N_("Attempt to read a row while there is no result set associated with "
87 "the statement"),
88 N_("This feature is not implemented yet"),
89 N_("Lost connection to Drizzle server while waiting for initial "
90 "communication packet, system error: %d"),
91 N_("Lost connection to Drizzle server while reading initial communication "
92 "packet, system error: %d"),
93 N_("Lost connection to Drizzle server while sending authentication "
94 "information, system error: %d"),
95 N_("Lost connection to Drizzle server while reading authorization "
96 "information, system error: %d"),
97 N_("Lost connection to Drizzle server while setting initial database, "
98 "system error: %d"),
99 N_("Statement closed indirectly because of a preceding %s() call"),
100/* CR_NET_UNCOMPRESS_ERROR 08S01 */
101 N_("Couldn't uncompress communication packet"),
102/* CR_NET_READ_ERROR 08S01 */
103 N_("Got an error reading communication packets"),
104/* CR_NET_READ_INTERRUPTED 08S01 */
105 N_("Got timeout reading communication packets"),
106/* CR_NET_ERROR_ON_WRITE 08S01 */
107 N_("Got an error writing communication packets"),
108/* CR_NET_WRITE_INTERRUPTED 08S01 */
109 N_("Got timeout writing communication packets"),
110 ""
111};
112
113
114const char *
115drizzleclient_get_client_error(unsigned int err_index)
116{
117 return _(client_errors[err_index]);
118}
119
120} /* namespace drizzle_protocol */28} /* namespace drizzle_protocol */
12129
=== modified file 'plugin/drizzle_protocol/errmsg.h'
--- plugin/drizzle_protocol/errmsg.h 2010-03-04 18:06:27 +0000
+++ plugin/drizzle_protocol/errmsg.h 2010-10-06 01:14:00 +0000
@@ -23,86 +23,6 @@
23namespace drizzle_protocol23namespace drizzle_protocol
24{24{
2525
26/* Error messages for MySQL clients */
27/* (Error messages for the daemon are in sql/share/errmsg.txt) */
28
29const char * drizzleclient_get_client_error(unsigned int err_index);
30
31#define CR_MIN_ERROR 2000 /* For easier client code */
32#define CR_MAX_ERROR 2999
33#if !defined(ER)
34#define ER(X) drizzleclient_get_client_error((X)-CR_MIN_ERROR)
35#endif
36#define CLIENT_ERRMAP 2 /* Errormap used by my_error() */
37
38/* Do not add error numbers before CR_ERROR_FIRST. */
39/* If necessary to add lower numbers, change CR_ERROR_FIRST accordingly. */
40enum CR_CLIENT_ERRORS {
41 CR_ERROR_FIRST =2000, /*Copy first error nr.*/
42 CR_UNKNOWN_ERROR =2000,
43 CR_SOCKET_CREATE_ERROR =2001,
44 CR_CONNECTION_ERROR =2002,
45 CR_CONN_HOST_ERROR =2003,
46 CR_IPSOCK_ERROR =2004,
47 CR_UNKNOWN_HOST =2005,
48 CR_SERVER_GONE_ERROR =2006,
49 CR_VERSION_ERROR =2007,
50 CR_OUT_OF_MEMORY =2008,
51 CR_WRONG_HOST_INFO =2009,
52 CR_LOCALHOST_CONNECTION =2010,
53 CR_TCP_CONNECTION =2011,
54 CR_SERVER_HANDSHAKE_ERR =2012,
55 CR_SERVER_LOST =2013,
56 CR_COMMANDS_OUT_OF_SYNC =2014,
57 CR_NAMEDPIPE_CONNECTION =2015,
58 CR_NAMEDPIPEWAIT_ERROR =2016,
59 CR_NAMEDPIPEOPEN_ERROR =2017,
60 CR_NAMEDPIPESETSTATE_ERROR =2018,
61 CR_CANT_READ_CHARSET =2019,
62 CR_NET_PACKET_TOO_LARGE =2020,
63 CR_EMBEDDED_CONNECTION =2021,
64 CR_PROBE_SLAVE_STATUS =2022,
65 CR_PROBE_SLAVE_HOSTS =2023,
66 CR_PROBE_SLAVE_CONNECT =2024,
67 CR_PROBE_MASTER_CONNECT =2025,
68 CR_SSL_CONNECTION_ERROR =2026,
69 CR_MALFORMED_PACKET =2027,
70
71 CR_NULL_POINTER =2029,
72 CR_NO_PREPARE_STMT =2030,
73 CR_PARAMS_NOT_BOUND =2031,
74 CR_DATA_TRUNCATED =2032,
75 CR_NO_PARAMETERS_EXISTS =2033,
76 CR_INVALID_PARAMETER_NO =2034,
77 CR_INVALID_BUFFER_USE =2035,
78 CR_UNSUPPORTED_PARAM_TYPE =2036,
79
80 CR_CONN_UNKNOW_PROTOCOL =2047,
81 CR_INVALID_CONN_HANDLE =2048,
82 CR_SECURE_AUTH =2049,
83 CR_FETCH_CANCELED =2050,
84 CR_NO_DATA =2051,
85 CR_NO_STMT_METADATA =2052,
86 CR_NO_RESULT_SET =2053,
87 CR_NOT_IMPLEMENTED =2054,
88 CR_SERVER_LOST_INITIAL_COMM_WAIT =2055,
89 CR_SERVER_LOST_INITIAL_COMM_READ =2056,
90 CR_SERVER_LOST_SEND_AUTH =2057,
91 CR_SERVER_LOST_READ_AUTH =2058,
92 CR_SERVER_LOST_SETTING_DB =2059,
93
94 CR_STMT_CLOSED =2060,
95
96 CR_NET_UNCOMPRESS_ERROR= 2061,
97 CR_NET_READ_ERROR= 2062,
98 CR_NET_READ_INTERRUPTED= 2063,
99 CR_NET_ERROR_ON_WRITE= 2064,
100 CR_NET_WRITE_INTERRUPTED= 2065,
101
102 /* Add error numbers before CR_ERROR_LAST and change it accordingly. */
103 CR_ERROR_LAST =2065 /*Copy last error nr:*/
104};
105
106} /* namespace drizzle_protocol */26} /* namespace drizzle_protocol */
10727
108#endif /* PLUGIN_DRIZZLE_PROTOCOL_ERRMSG_H */28#endif /* PLUGIN_DRIZZLE_PROTOCOL_ERRMSG_H */
10929
=== removed file 'plugin/drizzle_protocol/net_serv.cc'
--- plugin/drizzle_protocol/net_serv.cc 2010-05-19 01:22:29 +0000
+++ plugin/drizzle_protocol/net_serv.cc 1970-01-01 00:00:00 +0000
@@ -1,896 +0,0 @@
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, Inc.
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; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21#include "config.h"
22#include <drizzled/session.h>
23
24#include <assert.h>
25#include <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28#include <signal.h>
29#include <errno.h>
30#include <sys/socket.h>
31#include <sys/poll.h>
32#include <zlib.h>
33#include <algorithm>
34
35#include "errmsg.h"
36#include "vio.h"
37#include "net_serv.h"
38
39using namespace std;
40
41namespace drizzle_protocol
42{
43
44/*
45 The following handles the differences when this is linked between the
46 client and the server.
47
48 This gives an error if a too big packet is found
49 The server can change this with the -O switch, but because the client
50 can't normally do this the client should have a bigger max_allowed_packet.
51*/
52
53 /* Constants when using compression */
54#define NET_HEADER_SIZE 4 /* standard header size */
55#define COMP_HEADER_SIZE 3 /* compression header extra size */
56
57#define MAX_PACKET_LENGTH (256L*256L*256L-1)
58const char *not_error_sqlstate= "00000";
59
60static bool net_write_buff(NET *net, const unsigned char *packet, uint32_t len);
61static int drizzleclient_net_real_write(NET *net, const unsigned char *packet, size_t len);
62
63/** Init with packet info. */
64
65bool drizzleclient_net_init(NET *net, Vio* vio, uint32_t buffer_length)
66{
67 net->vio = vio;
68 net->max_packet= (uint32_t) buffer_length;
69 net->max_packet_size= max(buffer_length,
70 drizzled::global_system_variables.max_allowed_packet);
71
72 if (!(net->buff=(unsigned char*) malloc((size_t) net->max_packet+
73 NET_HEADER_SIZE + COMP_HEADER_SIZE)))
74 return(1);
75 net->buff_end=net->buff+net->max_packet;
76 net->error=0; net->return_status=0;
77 net->pkt_nr=net->compress_pkt_nr=0;
78 net->write_pos=net->read_pos = net->buff;
79 net->last_error[0]=0;
80 net->compress=0; net->reading_or_writing=0;
81 net->where_b = net->remain_in_buf=0;
82 net->last_errno=0;
83 net->unused= 0;
84
85 if (vio != 0) /* If real connection */
86 {
87 net->fd = drizzleclient_vio_fd(vio); /* For perl DBI/DBD */
88 drizzleclient_vio_fastsend(vio);
89 }
90 return(0);
91}
92
93bool drizzleclient_net_init_sock(NET * net, int sock, int flags,
94 uint32_t buffer_length)
95{
96
97 Vio *drizzleclient_vio_tmp= drizzleclient_vio_new(sock, VIO_TYPE_TCPIP, flags);
98 if (drizzleclient_vio_tmp == NULL)
99 return true;
100 else
101 if (drizzleclient_net_init(net, drizzleclient_vio_tmp, buffer_length))
102 {
103 /* Only delete the temporary vio if we didn't already attach it to the
104 * NET object.
105 */
106 if (drizzleclient_vio_tmp && (net->vio != drizzleclient_vio_tmp))
107 drizzleclient_vio_delete(drizzleclient_vio_tmp);
108 else
109 {
110 (void) shutdown(sock, SHUT_RDWR);
111 (void) close(sock);
112 }
113 return true;
114 }
115 return false;
116}
117
118void drizzleclient_net_end(NET *net)
119{
120 if (net->buff != NULL)
121 free(net->buff);
122 net->buff= NULL;
123 return;
124}
125
126void drizzleclient_net_close(NET *net)
127{
128 if (net->vio != NULL)
129 {
130 drizzleclient_vio_delete(net->vio);
131 net->vio= 0;
132 }
133}
134
135bool drizzleclient_net_peer_addr(NET *net, char *buf, uint16_t *port, size_t buflen)
136{
137 return drizzleclient_vio_peer_addr(net->vio, buf, port, buflen);
138}
139
140void drizzleclient_net_keepalive(NET *net, bool flag)
141{
142 drizzleclient_vio_keepalive(net->vio, flag);
143}
144
145int drizzleclient_net_get_sd(NET *net)
146{
147 return net->vio->sd;
148}
149
150bool drizzleclient_net_more_data(NET *net)
151{
152 return (net->vio == 0 || net->vio->read_pos < net->vio->read_end);
153}
154
155/** Realloc the packet buffer. */
156
157static bool drizzleclient_net_realloc(NET *net, size_t length)
158{
159 unsigned char *buff;
160 size_t pkt_length;
161
162 if (length >= net->max_packet_size)
163 {
164 /* @todo: 1 and 2 codes are identical. */
165 net->error= 1;
166 net->last_errno= CR_NET_PACKET_TOO_LARGE;
167 return(1);
168 }
169 pkt_length = (length+IO_SIZE-1) & ~(IO_SIZE-1);
170 /*
171 We must allocate some extra bytes for the end 0 and to be able to
172 read big compressed blocks
173 */
174 if (!(buff= (unsigned char*) realloc((char*) net->buff, pkt_length +
175 NET_HEADER_SIZE + COMP_HEADER_SIZE)))
176 {
177 /* @todo: 1 and 2 codes are identical. */
178 net->error= 1;
179 net->last_errno= CR_OUT_OF_MEMORY;
180 /* In the server the error is reported by MY_WME flag. */
181 return(1);
182 }
183 net->buff=net->write_pos=buff;
184 net->buff_end=buff+(net->max_packet= (uint32_t) pkt_length);
185 return(0);
186}
187
188
189/**
190 Check if there is any data to be read from the socket.
191
192 @param sd socket descriptor
193
194 @retval
195 0 No data to read
196 @retval
197 1 Data or EOF to read
198 @retval
199 -1 Don't know if data is ready or not
200*/
201
202static bool net_data_is_ready(int sd)
203{
204 struct pollfd ufds;
205 int res;
206
207 ufds.fd= sd;
208 ufds.events= POLLIN | POLLPRI;
209 if (!(res= poll(&ufds, 1, 0)))
210 return 0;
211 if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
212 return 0;
213 return 1;
214}
215
216/**
217 Remove unwanted characters from connection
218 and check if disconnected.
219
220 Read from socket until there is nothing more to read. Discard
221 what is read.
222
223 If there is anything when to read 'drizzleclient_net_clear' is called this
224 normally indicates an error in the protocol.
225
226 When connection is properly closed (for TCP it means with
227 a FIN packet), then select() considers a socket "ready to read",
228 in the sense that there's EOF to read, but read() returns 0.
229
230 @param net NET handler
231 @param clear_buffer if <> 0, then clear all data from comm buff
232*/
233
234void drizzleclient_net_clear(NET *net, bool clear_buffer)
235{
236 if (clear_buffer)
237 {
238 while (net_data_is_ready(net->vio->sd) > 0)
239 {
240 /* The socket is ready */
241 if (drizzleclient_vio_read(net->vio, net->buff,
242 (size_t) net->max_packet) <= 0)
243 {
244 net->error= 2;
245 break;
246 }
247 }
248 }
249 net->pkt_nr=net->compress_pkt_nr=0; /* Ready for new command */
250 net->write_pos=net->buff;
251 return;
252}
253
254
255/** Flush write_buffer if not empty. */
256
257bool drizzleclient_net_flush(NET *net)
258{
259 bool error= 0;
260 if (net->buff != net->write_pos)
261 {
262 error=drizzleclient_net_real_write(net, net->buff,
263 (size_t) (net->write_pos - net->buff)) ? 1 : 0;
264 net->write_pos=net->buff;
265 }
266 /* Sync packet number if using compression */
267 if (net->compress)
268 net->pkt_nr=net->compress_pkt_nr;
269 return(error);
270}
271
272
273/*****************************************************************************
274 ** Write something to server/client buffer
275 *****************************************************************************/
276
277/**
278 Write a logical packet with packet header.
279
280 Format: Packet length (3 bytes), packet number(1 byte)
281 When compression is used a 3 byte compression length is added
282
283 @note
284 If compression is used the original package is modified!
285*/
286
287bool
288drizzleclient_net_write(NET *net,const unsigned char *packet,size_t len)
289{
290 unsigned char buff[NET_HEADER_SIZE];
291 if (unlikely(!net->vio)) /* nowhere to write */
292 return 0;
293 /*
294 Big packets are handled by splitting them in packets of MAX_PACKET_LENGTH
295 length. The last packet is always a packet that is < MAX_PACKET_LENGTH.
296 (The last packet may even have a length of 0)
297 */
298 while (len >= MAX_PACKET_LENGTH)
299 {
300 const uint32_t z_size = MAX_PACKET_LENGTH;
301 int3store(buff, z_size);
302 buff[3]= (unsigned char) net->pkt_nr++;
303 if (net_write_buff(net, buff, NET_HEADER_SIZE) ||
304 net_write_buff(net, packet, z_size))
305 return 1;
306 packet += z_size;
307 len-= z_size;
308 }
309 /* Write last packet */
310 int3store(buff,len);
311 buff[3]= (unsigned char) net->pkt_nr++;
312 if (net_write_buff(net, buff, NET_HEADER_SIZE))
313 return 1;
314 return net_write_buff(net,packet,len) ? 1 : 0;
315}
316
317/**
318 Send a command to the server.
319
320 The reason for having both header and packet is so that libdrizzle
321 can easy add a header to a special command (like prepared statements)
322 without having to re-alloc the string.
323
324 As the command is part of the first data packet, we have to do some data
325 juggling to put the command in there, without having to create a new
326 packet.
327
328 This function will split big packets into sub-packets if needed.
329 (Each sub packet can only be 2^24 bytes)
330
331 @param net NET handler
332 @param command Command in MySQL server (enum enum_server_command)
333 @param header Header to write after command
334 @param head_len Length of header
335 @param packet Query or parameter to query
336 @param len Length of packet
337
338 @retval
339 0 ok
340 @retval
341 1 error
342*/
343
344bool
345drizzleclient_net_write_command(NET *net,unsigned char command,
346 const unsigned char *header, size_t head_len,
347 const unsigned char *packet, size_t len)
348{
349 uint32_t length=len+1+head_len; /* 1 extra byte for command */
350 unsigned char buff[NET_HEADER_SIZE+1];
351 uint32_t header_size=NET_HEADER_SIZE+1;
352
353 buff[4]=command; /* For first packet */
354
355 if (length >= MAX_PACKET_LENGTH)
356 {
357 /* Take into account that we have the command in the first header */
358 len= MAX_PACKET_LENGTH - 1 - head_len;
359 do
360 {
361 int3store(buff, MAX_PACKET_LENGTH);
362 buff[3]= (unsigned char) net->pkt_nr++;
363 if (net_write_buff(net, buff, header_size) ||
364 net_write_buff(net, header, head_len) ||
365 net_write_buff(net, packet, len))
366 return(1);
367 packet+= len;
368 length-= MAX_PACKET_LENGTH;
369 len= MAX_PACKET_LENGTH;
370 head_len= 0;
371 header_size= NET_HEADER_SIZE;
372 } while (length >= MAX_PACKET_LENGTH);
373 len=length; /* Data left to be written */
374 }
375 int3store(buff,length);
376 buff[3]= (unsigned char) net->pkt_nr++;
377 return((net_write_buff(net, buff, header_size) ||
378 (head_len && net_write_buff(net, header, head_len)) ||
379 net_write_buff(net, packet, len) || drizzleclient_net_flush(net)) ? 1 : 0 );
380}
381
382/**
383 Caching the data in a local buffer before sending it.
384
385 Fill up net->buffer and send it to the client when full.
386
387 If the rest of the to-be-sent-packet is bigger than buffer,
388 send it in one big block (to avoid copying to internal buffer).
389 If not, copy the rest of the data to the buffer and return without
390 sending data.
391
392 @param net Network handler
393 @param packet Packet to send
394 @param len Length of packet
395
396 @note
397 The cached buffer can be sent as it is with 'drizzleclient_net_flush()'.
398 In this code we have to be careful to not send a packet longer than
399 MAX_PACKET_LENGTH to drizzleclient_net_real_write() if we are using the compressed
400 protocol as we store the length of the compressed packet in 3 bytes.
401
402 @retval
403 0 ok
404 @retval
405 1
406*/
407
408static bool
409net_write_buff(NET *net, const unsigned char *packet, uint32_t len)
410{
411 uint32_t left_length;
412 if (net->compress && net->max_packet > MAX_PACKET_LENGTH)
413 left_length= MAX_PACKET_LENGTH - (net->write_pos - net->buff);
414 else
415 left_length= (uint32_t) (net->buff_end - net->write_pos);
416
417 if (len > left_length)
418 {
419 if (net->write_pos != net->buff)
420 {
421 /* Fill up already used packet and write it */
422 memcpy(net->write_pos,packet,left_length);
423 if (drizzleclient_net_real_write(net, net->buff,
424 (size_t) (net->write_pos - net->buff) + left_length))
425 return 1;
426 net->write_pos= net->buff;
427 packet+= left_length;
428 len-= left_length;
429 }
430 if (net->compress)
431 {
432 /*
433 We can't have bigger packets than 16M with compression
434 Because the uncompressed length is stored in 3 bytes
435 */
436 left_length= MAX_PACKET_LENGTH;
437 while (len > left_length)
438 {
439 if (drizzleclient_net_real_write(net, packet, left_length))
440 return 1;
441 packet+= left_length;
442 len-= left_length;
443 }
444 }
445 if (len > net->max_packet)
446 return drizzleclient_net_real_write(net, packet, len) ? 1 : 0;
447 /* Send out rest of the blocks as full sized blocks */
448 }
449 memcpy(net->write_pos,packet,len);
450 net->write_pos+= len;
451 return 0;
452}
453
454
455/**
456 Read and write one packet using timeouts.
457 If needed, the packet is compressed before sending.
458
459 @todo
460 - TODO is it needed to set this variable if we have no socket
461*/
462
463/*
464 TODO: rewrite this in a manner to do non-block writes. If a write can not be made, and we are
465 in the server, yield to another process and come back later.
466*/
467static int
468drizzleclient_net_real_write(NET *net, const unsigned char *packet, size_t len)
469{
470 size_t length;
471 const unsigned char *pos, *end;
472 uint32_t retry_count= 0;
473
474 /* Backup of the original SO_RCVTIMEO timeout */
475
476 if (net->error == 2)
477 return(-1); /* socket can't be used */
478
479 net->reading_or_writing=2;
480 if (net->compress)
481 {
482 size_t complen;
483 unsigned char *b;
484 const uint32_t header_length=NET_HEADER_SIZE+COMP_HEADER_SIZE;
485 if (!(b= (unsigned char*) malloc(len + NET_HEADER_SIZE +
486 COMP_HEADER_SIZE)))
487 {
488 net->error= 2;
489 net->last_errno= CR_OUT_OF_MEMORY;
490 /* In the server, the error is reported by MY_WME flag. */
491 net->reading_or_writing= 0;
492 return(1);
493 }
494 memcpy(b+header_length,packet,len);
495
496 complen= len * 120 / 100 + 12;
497 unsigned char * compbuf= (unsigned char *) malloc(complen);
498 if (compbuf != NULL)
499 {
500 uLongf tmp_complen= complen;
501 int res= compress((Bytef*) compbuf, &tmp_complen,
502 (Bytef*) (b+header_length),
503 len);
504 complen= tmp_complen;
505
506 free(compbuf);
507
508 if ((res != Z_OK) || (complen >= len))
509 complen= 0;
510 else
511 {
512 size_t tmplen= complen;
513 complen= len;
514 len= tmplen;
515 }
516 }
517 else
518 {
519 complen=0;
520 }
521 int3store(&b[NET_HEADER_SIZE],complen);
522 int3store(b,len);
523 b[3]=(unsigned char) (net->compress_pkt_nr++);
524 len+= header_length;
525 packet= b;
526 }
527
528 pos= packet;
529 end=pos+len;
530 /* Loop until we have read everything */
531 while (pos != end)
532 {
533 assert(pos);
534 if ((long) (length= drizzleclient_vio_write(net->vio, pos, (size_t) (end-pos))) <= 0)
535 {
536 /*
537 * We could end up here with net->vio == NULL
538 * See LP bug#436685
539 * If that is the case, we exit the while loop
540 */
541 if (net->vio == NULL)
542 break;
543
544 const bool interrupted= drizzleclient_vio_should_retry(net->vio);
545 /*
546 If we read 0, or we were interrupted this means that
547 we need to switch to blocking mode and wait until the timeout
548 on the socket kicks in.
549 */
550 if ((interrupted || length == 0))
551 {
552 bool old_mode;
553
554 while (drizzleclient_vio_blocking(net->vio, true, &old_mode) < 0)
555 {
556 if (drizzleclient_vio_should_retry(net->vio) && retry_count++ < net->retry_count)
557 continue;
558 net->error= 2; /* Close socket */
559 net->last_errno= CR_NET_PACKET_TOO_LARGE;
560 goto end;
561 }
562 retry_count=0;
563 continue;
564 }
565 else
566 {
567 if (retry_count++ < net->retry_count)
568 continue;
569 }
570
571 if (drizzleclient_vio_errno(net->vio) == EINTR)
572 {
573 continue;
574 }
575 net->error= 2; /* Close socket */
576 net->last_errno= (interrupted ? CR_NET_WRITE_INTERRUPTED :
577 CR_NET_ERROR_ON_WRITE);
578 break;
579 }
580 pos+=length;
581 current_session->status_var.bytes_sent+= length;
582 }
583end:
584 if ((net->compress) && (packet != NULL))
585 free((char*) packet);
586 net->reading_or_writing=0;
587
588 return(((int) (pos != end)));
589}
590
591
592/**
593 Reads one packet to net->buff + net->where_b.
594 Long packets are handled by drizzleclient_net_read().
595 This function reallocates the net->buff buffer if necessary.
596
597 @return
598 Returns length of packet.
599*/
600
601static uint32_t
602my_real_read(NET *net, size_t *complen)
603{
604 unsigned char *pos;
605 size_t length;
606 uint32_t i,retry_count=0;
607 size_t len=packet_error;
608 uint32_t remain= (net->compress ? NET_HEADER_SIZE+COMP_HEADER_SIZE :
609 NET_HEADER_SIZE);
610
611 *complen = 0;
612
613 net->reading_or_writing= 1;
614 /* Read timeout is set in drizzleclient_net_set_read_timeout */
615
616 pos = net->buff + net->where_b; /* net->packet -4 */
617
618 for (i= 0; i < 2 ; i++)
619 {
620 while (remain > 0)
621 {
622 /* First read is done with non blocking mode */
623 if ((long) (length= drizzleclient_vio_read(net->vio, pos, remain)) <= 0L)
624 {
625 if (net->vio == NULL)
626 goto end;
627
628 const bool interrupted = drizzleclient_vio_should_retry(net->vio);
629
630 if (interrupted)
631 { /* Probably in MIT threads */
632 if (retry_count++ < net->retry_count)
633 continue;
634 }
635 if (drizzleclient_vio_errno(net->vio) == EINTR)
636 {
637 continue;
638 }
639 len= packet_error;
640 net->error= 2; /* Close socket */
641 net->last_errno= (drizzleclient_vio_was_interrupted(net->vio) ?
642 CR_NET_READ_INTERRUPTED :
643 CR_NET_READ_ERROR);
644 ER(net->last_errno);
645 goto end;
646 }
647 remain -= (uint32_t) length;
648 pos+= length;
649 current_session->status_var.bytes_received+= length;
650 }
651 if (i == 0)
652 { /* First parts is packet length */
653 uint32_t helping;
654
655 if (net->buff[net->where_b + 3] != (unsigned char) net->pkt_nr)
656 {
657 len= packet_error;
658 /* Not a NET error on the client. XXX: why? */
659 goto end;
660 }
661 net->compress_pkt_nr= ++net->pkt_nr;
662 if (net->compress)
663 {
664 /*
665 If the packet is compressed then complen > 0 and contains the
666 number of bytes in the uncompressed packet
667 */
668 *complen=uint3korr(&(net->buff[net->where_b + NET_HEADER_SIZE]));
669 }
670
671 len=uint3korr(net->buff+net->where_b);
672 if (!len) /* End of big multi-packet */
673 goto end;
674 helping = max(len,*complen) + net->where_b;
675 /* The necessary size of net->buff */
676 if (helping >= net->max_packet)
677 {
678 if (drizzleclient_net_realloc(net,helping))
679 {
680 len= packet_error; /* Return error and close connection */
681 goto end;
682 }
683 }
684 pos=net->buff + net->where_b;
685 remain = (uint32_t) len;
686 }
687 }
688
689end:
690 net->reading_or_writing= 0;
691
692 return(len);
693}
694
695
696/**
697 Read a packet from the client/server and return it without the internal
698 package header.
699
700 If the packet is the first packet of a multi-packet packet
701 (which is indicated by the length of the packet = 0xffffff) then
702 all sub packets are read and concatenated.
703
704 If the packet was compressed, its uncompressed and the length of the
705 uncompressed packet is returned.
706
707 @return
708 The function returns the length of the found packet or packet_error.
709 net->read_pos points to the read data.
710*/
711
712uint32_t
713drizzleclient_net_read(NET *net)
714{
715 size_t len, complen;
716
717 if (!net->compress)
718 {
719 len = my_real_read(net,&complen);
720 if (len == MAX_PACKET_LENGTH)
721 {
722 /* First packet of a multi-packet. Concatenate the packets */
723 uint32_t save_pos = net->where_b;
724 size_t total_length= 0;
725 do
726 {
727 net->where_b += len;
728 total_length += len;
729 len = my_real_read(net,&complen);
730 } while (len == MAX_PACKET_LENGTH);
731 if (len != packet_error)
732 len+= total_length;
733 net->where_b = save_pos;
734 }
735 net->read_pos = net->buff + net->where_b;
736 if (len != packet_error)
737 net->read_pos[len]=0; /* Safeguard for drizzleclient_use_result */
738 return len;
739 }
740 else
741 {
742 /* We are using the compressed protocol */
743
744 uint32_t buf_length;
745 uint32_t start_of_packet;
746 uint32_t first_packet_offset;
747 uint32_t read_length, multi_byte_packet=0;
748
749 if (net->remain_in_buf)
750 {
751 buf_length= net->buf_length; /* Data left in old packet */
752 first_packet_offset= start_of_packet= (net->buf_length -
753 net->remain_in_buf);
754 /* Restore the character that was overwritten by the end 0 */
755 net->buff[start_of_packet]= net->save_char;
756 }
757 else
758 {
759 /* reuse buffer, as there is nothing in it that we need */
760 buf_length= start_of_packet= first_packet_offset= 0;
761 }
762 for (;;)
763 {
764 uint32_t packet_len;
765
766 if (buf_length - start_of_packet >= NET_HEADER_SIZE)
767 {
768 read_length = uint3korr(net->buff+start_of_packet);
769 if (!read_length)
770 {
771 /* End of multi-byte packet */
772 start_of_packet += NET_HEADER_SIZE;
773 break;
774 }
775 if (read_length + NET_HEADER_SIZE <= buf_length - start_of_packet)
776 {
777 if (multi_byte_packet)
778 {
779 /* Remove packet header for second packet */
780 memmove(net->buff + first_packet_offset + start_of_packet,
781 net->buff + first_packet_offset + start_of_packet +
782 NET_HEADER_SIZE,
783 buf_length - start_of_packet);
784 start_of_packet += read_length;
785 buf_length -= NET_HEADER_SIZE;
786 }
787 else
788 start_of_packet+= read_length + NET_HEADER_SIZE;
789
790 if (read_length != MAX_PACKET_LENGTH) /* last package */
791 {
792 multi_byte_packet= 0; /* No last zero len packet */
793 break;
794 }
795 multi_byte_packet= NET_HEADER_SIZE;
796 /* Move data down to read next data packet after current one */
797 if (first_packet_offset)
798 {
799 memmove(net->buff,net->buff+first_packet_offset,
800 buf_length-first_packet_offset);
801 buf_length-=first_packet_offset;
802 start_of_packet -= first_packet_offset;
803 first_packet_offset=0;
804 }
805 continue;
806 }
807 }
808 /* Move data down to read next data packet after current one */
809 if (first_packet_offset)
810 {
811 memmove(net->buff,net->buff+first_packet_offset,
812 buf_length-first_packet_offset);
813 buf_length-=first_packet_offset;
814 start_of_packet -= first_packet_offset;
815 first_packet_offset=0;
816 }
817
818 net->where_b=buf_length;
819 if ((packet_len = my_real_read(net,&complen)) == packet_error)
820 return packet_error;
821
822 if (complen)
823 {
824 unsigned char * compbuf= (unsigned char *) malloc(complen);
825 if (compbuf != NULL)
826 {
827 uLongf tmp_complen= complen;
828 int error= uncompress((Bytef*) compbuf, &tmp_complen,
829 (Bytef*) (net->buff + net->where_b),
830 (uLong)packet_len);
831 complen= tmp_complen;
832
833 if (error != Z_OK)
834 {
835 net->error= 2; /* caller will close socket */
836 net->last_errno= CR_NET_UNCOMPRESS_ERROR;
837 }
838 else
839 {
840 memcpy((net->buff + net->where_b), compbuf, complen);
841 }
842 free(compbuf);
843 }
844 }
845 else
846 complen= packet_len;
847
848 }
849 buf_length+= complen;
850
851 net->read_pos= net->buff+ first_packet_offset + NET_HEADER_SIZE;
852 net->buf_length= buf_length;
853 net->remain_in_buf= (uint32_t) (buf_length - start_of_packet);
854 len = ((uint32_t) (start_of_packet - first_packet_offset) - NET_HEADER_SIZE -
855 multi_byte_packet);
856 net->save_char= net->read_pos[len]; /* Must be saved */
857 net->read_pos[len]=0; /* Safeguard for drizzleclient_use_result */
858 }
859 return len;
860 }
861
862
863void drizzleclient_net_set_read_timeout(NET *net, uint32_t timeout)
864{
865 net->read_timeout= timeout;
866#ifndef __sun
867 if (net->vio)
868 drizzleclient_vio_timeout(net->vio, 0, timeout);
869#endif
870 return;
871}
872
873
874void drizzleclient_net_set_write_timeout(NET *net, uint32_t timeout)
875{
876 net->write_timeout= timeout;
877#ifndef __sun
878 if (net->vio)
879 drizzleclient_vio_timeout(net->vio, 1, timeout);
880#endif
881 return;
882}
883/**
884 Clear possible error state of struct NET
885
886 @param net clear the state of the argument
887*/
888
889void drizzleclient_drizzleclient_net_clear_error(NET *net)
890{
891 net->last_errno= 0;
892 net->last_error[0]= '\0';
893 strcpy(net->sqlstate, not_error_sqlstate);
894}
895
896} /* namespace drizzle_protocol */
8970
=== removed file 'plugin/drizzle_protocol/net_serv.h'
--- plugin/drizzle_protocol/net_serv.h 2010-03-04 18:06:27 +0000
+++ plugin/drizzle_protocol/net_serv.h 1970-01-01 00:00:00 +0000
@@ -1,94 +0,0 @@
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, Inc.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20
21#ifndef PLUGIN_DRIZZLE_PROTOCOL_NET_SERV_H
22#define PLUGIN_DRIZZLE_PROTOCOL_NET_SERV_H
23
24#include "vio.h"
25
26#include <stdint.h>
27
28namespace drizzle_protocol
29{
30
31#define LIBDRIZZLE_ERRMSG_SIZE 512
32#define LIBDRIZZLE_SQLSTATE_LENGTH 5
33
34typedef struct st_net {
35 Vio *vio;
36 unsigned char *buff,*buff_end,*write_pos,*read_pos;
37 int fd; /* For Perl DBI/dbd */
38 /*
39 The following variable is set if we are doing several queries in one
40 command ( as in LOAD TABLE ... FROM MASTER ),
41 and do not want to confuse the client with OK at the wrong time
42 */
43 unsigned long remain_in_buf,length, buf_length, where_b;
44 unsigned long max_packet,max_packet_size;
45 unsigned int pkt_nr,compress_pkt_nr;
46 unsigned int write_timeout;
47 unsigned int read_timeout;
48 unsigned int retry_count;
49 int fcntl;
50 unsigned int *return_status;
51 unsigned char reading_or_writing;
52 char save_char;
53 bool compress;
54 /*
55 Pointer to query object in query cache, do not equal NULL (0) for
56 queries in cache that have not stored its results yet
57 */
58 /*
59 Unused, please remove with the next incompatible ABI change.
60 */
61 unsigned char *unused;
62 unsigned int last_errno;
63 unsigned char error;
64 /** Client library error message buffer. Actually belongs to struct MYSQL. */
65 char last_error[LIBDRIZZLE_ERRMSG_SIZE];
66 /** Client library sqlstate buffer. Set along with the error message. */
67 char sqlstate[LIBDRIZZLE_SQLSTATE_LENGTH+1];
68 void *extension;
69} NET;
70
71bool drizzleclient_net_init(NET *net, Vio* vio, uint32_t buffer_length);
72void drizzleclient_net_end(NET *net);
73void drizzleclient_net_clear(NET *net, bool clear_buffer);
74bool drizzleclient_net_flush(NET *net);
75bool drizzleclient_net_write(NET *net,const unsigned char *packet, size_t len);
76bool drizzleclient_net_write_command(NET *net,unsigned char command,
77 const unsigned char *header, size_t head_len,
78 const unsigned char *packet, size_t len);
79uint32_t drizzleclient_net_read(NET *net);
80void drizzleclient_net_close(NET *net);
81bool drizzleclient_net_init_sock(NET * net, int sock, int flags,
82 uint32_t buffer_length);
83bool drizzleclient_net_peer_addr(NET *net, char *buf, uint16_t *port, size_t buflen);
84void drizzleclient_net_keepalive(NET *net, bool flag);
85int drizzleclient_net_get_sd(NET *net);
86bool drizzleclient_net_more_data(NET *net);
87
88void drizzleclient_net_set_write_timeout(NET *net, uint32_t timeout);
89void drizzleclient_net_set_read_timeout(NET *net, uint32_t timeout);
90void drizzleclient_drizzleclient_net_clear_error(NET *net);
91
92} /* namespace drizzle_protocol */
93
94#endif /* PLUGIN_DRIZZLE_PROTOCOL_NET_SERV_H */
950
=== removed file 'plugin/drizzle_protocol/options.h'
--- plugin/drizzle_protocol/options.h 2010-03-04 18:06:27 +0000
+++ plugin/drizzle_protocol/options.h 1970-01-01 00:00:00 +0000
@@ -1,125 +0,0 @@
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, Inc.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef PLUGIN_DRIZZLE_PROTOCOL_OPTIONS_H
21#define PLUGIN_DRIZZLE_PROTOCOL_OPTIONS_H
22
23namespace drizzle_protocol
24{
25
26enum drizzle_option
27{
28 DRIZZLE_OPT_CONNECT_TIMEOUT, DRIZZLE_OPT_COMPRESS, DRIZZLE_OPT_NAMED_PIPE,
29 DRIZZLE_INIT_COMMAND, DRIZZLE_READ_DEFAULT_FILE, DRIZZLE_READ_DEFAULT_GROUP,
30 DRIZZLE_OPT_PROTOCOL, DRIZZLE_SHARED_MEMORY_BASE_NAME, DRIZZLE_OPT_READ_TIMEOUT,
31 DRIZZLE_OPT_WRITE_TIMEOUT, DRIZZLE_OPT_USE_RESULT,
32 DRIZZLE_OPT_USE_REMOTE_CONNECTION,
33 DRIZZLE_OPT_GUESS_CONNECTION, DRIZZLE_SET_CLIENT_IP, DRIZZLE_SECURE_AUTH,
34 DRIZZLE_REPORT_DATA_TRUNCATION, DRIZZLE_OPT_RECONNECT,
35 DRIZZLE_OPT_SSL_VERIFY_SERVER_CERT
36};
37
38struct st_drizzleclient_options {
39 unsigned int connect_timeout, read_timeout, write_timeout;
40 unsigned int port;
41 unsigned long client_flag;
42 char *host,*user,*password,*db;
43 char *my_cnf_file,*my_cnf_group;
44 char *ssl_key; /* PEM key file */
45 char *ssl_cert; /* PEM cert file */
46 char *ssl_ca; /* PEM CA file */
47 char *ssl_capath; /* PEM directory of CA-s? */
48 char *ssl_cipher; /* cipher to use */
49 char *shared_memory_base_name;
50 unsigned long max_allowed_packet;
51 bool use_ssl; /* if to use SSL or not */
52 bool compress,named_pipe;
53 bool unused1;
54 bool unused2;
55 bool unused3;
56 bool unused4;
57 enum drizzle_option methods_to_use;
58 char *client_ip;
59 /* Refuse client connecting to server if it uses old (pre-4.1.1) protocol */
60 bool secure_auth;
61 /* 0 - never report, 1 - always report (default) */
62 bool report_data_truncation;
63
64 /* function pointers for local infile support */
65 int (*local_infile_init)(void **, const char *, void *);
66 int (*local_infile_read)(void *, char *, unsigned int);
67 void (*local_infile_end)(void *);
68 int (*local_infile_error)(void *, char *, unsigned int);
69 void *local_infile_userdata;
70 void *extension;
71};
72
73
74#define CLIENT_NET_READ_TIMEOUT 365*24*3600 /* Timeout on read */
75#define CLIENT_NET_WRITE_TIMEOUT 365*24*3600 /* Timeout on write */
76
77#define CLIENT_LONG_PASSWORD 1 /* new more secure passwords */
78#define CLIENT_FOUND_ROWS 2 /* Found instead of affected rows */
79#define CLIENT_LONG_FLAG 4 /* Get all column flags */
80#define CLIENT_CONNECT_WITH_DB 8 /* One can specify db on connect */
81#define CLIENT_NO_SCHEMA 16 /* Don't allow database.table.column */
82#define CLIENT_COMPRESS 32 /* Can use compression protocol */
83#define CLIENT_ODBC 64 /* Odbc client */
84#define CLIENT_IGNORE_SPACE 256 /* Ignore spaces before '(' */
85#define CLIENT_PROTOCOL_MYSQL41 512 /* New 4.1 protocol */
86#define CLIENT_SSL 2048 /* Switch to SSL after handshake */
87#define CLIENT_IGNORE_SIGPIPE 4096 /* IGNORE sigpipes */
88#define CLIENT_RESERVED 16384 /* Old flag for 4.1 protocol */
89#define CLIENT_SECURE_CONNECTION 32768 /* New 4.1 authentication */
90#define CLIENT_MULTI_STATEMENTS (1UL << 16) /* Enable/disable multi-stmt support */
91#define CLIENT_MULTI_RESULTS (1UL << 17) /* Enable/disable multi-results */
92
93#define CLIENT_SSL_VERIFY_SERVER_CERT (1UL << 30)
94#define CLIENT_REMEMBER_OPTIONS (1UL << 31)
95
96/* Gather all possible capabilites (flags) supported by the server */
97#define CLIENT_ALL_FLAGS (CLIENT_LONG_PASSWORD | \
98 CLIENT_FOUND_ROWS | \
99 CLIENT_LONG_FLAG | \
100 CLIENT_CONNECT_WITH_DB | \
101 CLIENT_NO_SCHEMA | \
102 CLIENT_COMPRESS | \
103 CLIENT_ODBC | \
104 CLIENT_IGNORE_SPACE | \
105 CLIENT_SSL | \
106 CLIENT_IGNORE_SIGPIPE | \
107 CLIENT_RESERVED | \
108 CLIENT_SECURE_CONNECTION | \
109 CLIENT_MULTI_STATEMENTS | \
110 CLIENT_MULTI_RESULTS | \
111 CLIENT_SSL_VERIFY_SERVER_CERT | \
112 CLIENT_REMEMBER_OPTIONS)
113
114/*
115 Switch off the flags that are optional and depending on build flags
116 If any of the optional flags is supported by the build it will be switched
117 on before sending to the client during the connection handshake.
118*/
119#define CLIENT_BASIC_FLAGS (((CLIENT_ALL_FLAGS & ~CLIENT_SSL) \
120 & ~CLIENT_COMPRESS) \
121 & ~CLIENT_SSL_VERIFY_SERVER_CERT)
122
123} /* namespace drizzle_protocol */
124
125#endif /* PLUGIN_DRIZZLE_PROTOCOL_OPTIONS_H */
1260
=== removed file 'plugin/drizzle_protocol/pack.cc'
--- plugin/drizzle_protocol/pack.cc 2010-03-04 18:06:27 +0000
+++ plugin/drizzle_protocol/pack.cc 1970-01-01 00:00:00 +0000
@@ -1,132 +0,0 @@
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, Inc.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#include "config.h"
21#include <drizzled/korr.h>
22
23#include <stdint.h>
24
25#include "pack.h"
26
27namespace drizzle_protocol
28{
29
30/* Get the length of next field. Change parameter to point at fieldstart */
31uint32_t drizzleclient_net_field_length(unsigned char **packet)
32{
33 register unsigned char *pos= (unsigned char *)*packet;
34 if (*pos < 251)
35 {
36 (*packet)++;
37 return (uint32_t) *pos;
38 }
39 if (*pos == 251)
40 {
41 (*packet)++;
42 return NULL_LENGTH;
43 }
44 if (*pos == 252)
45 {
46 (*packet)+=3;
47 return (uint32_t) uint2korr(pos+1);
48 }
49 if (*pos == 253)
50 {
51 (*packet)+=4;
52 return (uint32_t) uint3korr(pos+1);
53 }
54 (*packet)+=9; /* Must be 254 when here */
55 return (uint32_t) uint4korr(pos+1);
56}
57
58/* The same as above but returns int64_t */
59uint64_t drizzleclient_drizzleclient_net_field_length_ll(unsigned char **packet)
60{
61 register unsigned char *pos= *packet;
62 if (*pos < 251)
63 {
64 (*packet)++;
65 return (uint64_t) *pos;
66 }
67 if (*pos == 251)
68 {
69 (*packet)++;
70 return (uint64_t) NULL_LENGTH;
71 }
72 if (*pos == 252)
73 {
74 (*packet)+=3;
75 return (uint64_t) uint2korr(pos+1);
76 }
77 if (*pos == 253)
78 {
79 (*packet)+=4;
80 return (uint64_t) uint3korr(pos+1);
81 }
82 (*packet)+=9; /* Must be 254 when here */
83#ifdef NO_CLIENT_LONGLONG
84 return (uint64_t) uint4korr(pos+1);
85#else
86 return (uint64_t) uint8korr(pos+1);
87#endif
88}
89
90/*
91 Store an integer with simple packing into a output package
92
93 SYNOPSIS
94 drizzleclient_net_store_length()
95 pkg Store the packed integer here
96 length integers to store
97
98 NOTES
99 This is mostly used to store lengths of strings.
100 We have to cast the result for the LL() becasue of a bug in Forte CC
101 compiler.
102
103 RETURN
104 Position in 'pkg' after the packed length
105*/
106
107unsigned char *drizzleclient_net_store_length(unsigned char *packet, uint64_t length)
108{
109 if (length < (uint64_t) 251LL)
110 {
111 *packet=(unsigned char) length;
112 return packet+1;
113 }
114 /* 251 is reserved for NULL */
115 if (length < (uint64_t) 65536LL)
116 {
117 *packet++=252;
118 int2store(packet,(uint32_t) length);
119 return packet+2;
120 }
121 if (length < (uint64_t) 16777216LL)
122 {
123 *packet++=253;
124 int3store(packet,(uint32_t) length);
125 return packet+3;
126 }
127 *packet++=254;
128 int8store(packet,length);
129 return packet+8;
130}
131
132} /* namespace drizzle_protocol */
1330
=== removed file 'plugin/drizzle_protocol/pack.h'
--- plugin/drizzle_protocol/pack.h 2010-03-04 18:06:27 +0000
+++ plugin/drizzle_protocol/pack.h 1970-01-01 00:00:00 +0000
@@ -1,34 +0,0 @@
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
18 */
19
20#ifndef PLUGIN_DRIZZLE_PROTOCOL_PACK_H
21#define PLUGIN_DRIZZLE_PROTOCOL_PACK_H
22
23namespace drizzle_protocol
24{
25
26#define NULL_LENGTH UINT32_MAX
27
28uint32_t drizzleclient_net_field_length(unsigned char **packet);
29uint64_t drizzleclient_drizzleclient_net_field_length_ll(unsigned char **packet);
30unsigned char *drizzleclient_net_store_length(unsigned char *pkg, uint64_t length);
31
32} /* namespace drizzle_protocol */
33
34#endif /* PLUGIN_DRIZZLE_PROTOCOL_PACK_H */
350
=== modified file 'plugin/drizzle_protocol/plugin.ini'
--- plugin/drizzle_protocol/plugin.ini 2010-09-01 19:17:03 +0000
+++ plugin/drizzle_protocol/plugin.ini 2010-10-06 01:14:00 +0000
@@ -1,12 +1,17 @@
1[plugin]1[plugin]
2title=Drizzle Protocol Module2title=Drizzle Protocol Module
3description=Drizzle protocol module that uses the old libdrizzle library (previously libmysql).3description=Drizzle protocol module.
4version=0.24version=0.3
5author=Eric Day5author=Brian Aker
6license=PLUGIN_LICENSE_GPL6license=PLUGIN_LICENSE_GPL
7libs=drizzled/algorithm/libhash.la7libs=drizzled/algorithm/libhash.la
8load_by_default=yes8load_by_default=yes
9ldlfags=$(LIBZ)9ldlfags=$(LIBZ)
10headers=drizzle_protocol.h errmsg.h net_serv.h options.h pack.h vio.h table_function.h10headers=
11sources=drizzle_protocol.cc errmsg.cc net_serv.cc pack.cc vio.cc viosocket.cc11 drizzle_protocol.h
12 errmsg.h
13 status_table.h
14sources=
15 drizzle_protocol.cc
16 errmsg.h
12static=yes17static=yes
1318
=== renamed file 'plugin/drizzle_protocol/table_function.h' => 'plugin/drizzle_protocol/status_table.h'
--- plugin/drizzle_protocol/table_function.h 2010-09-08 22:20:35 +0000
+++ plugin/drizzle_protocol/status_table.h 2010-10-06 01:14:00 +0000
@@ -18,18 +18,18 @@
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */19 */
2020
21#ifndef PLUGIN_DRIZZLE_PROTOCOL_TABLE_FUNCTION_H21#ifndef PLUGIN_DRIZZLE_PROTOCOL_STATUS_TABLE_H
22#define PLUGIN_DRIZZLE_PROTOCOL_TABLE_FUNCTION_H22#define PLUGIN_DRIZZLE_PROTOCOL_STATUS_TABLE_H
2323
24#include "drizzled/plugin/table_function.h"24#include "drizzled/plugin/table_function.h"
25namespace drizzle_protocol25namespace drizzle_protocol
26{26{
2727
2828
29class DrizzleProtocolStatus : public drizzled::plugin::TableFunction29class StatusTable : public drizzled::plugin::TableFunction
30{30{
31public:31public:
32 DrizzleProtocolStatus() :32 StatusTable() :
33 drizzled::plugin::TableFunction("DATA_DICTIONARY","DRIZZLE_PROTOCOL_STATUS")33 drizzled::plugin::TableFunction("DATA_DICTIONARY","DRIZZLE_PROTOCOL_STATUS")
34 {34 {
35 add_field("VARIABLE_NAME");35 add_field("VARIABLE_NAME");
@@ -38,12 +38,17 @@
3838
39 class Generator : public drizzled::plugin::TableFunction::Generator39 class Generator : public drizzled::plugin::TableFunction::Generator
40 {40 {
41 drizzled::drizzle_show_var *status_var_ptr;
4241
43 public:42 public:
44 Generator(drizzled::Field **fields);43 Generator(drizzled::Field **fields) :
44 drizzled::plugin::TableFunction::Generator(fields)
45 {
46 }
4547
46 bool populate();48 bool populate()
49 {
50 return false;
51 }
47 };52 };
4853
49 Generator *generator(drizzled::Field **arg)54 Generator *generator(drizzled::Field **arg)
@@ -54,4 +59,4 @@
5459
55}60}
5661
57#endif /* PLUGIN_DRIZZLE_PROTOCOL_TABLE_FUNCTION_H */62#endif /* PLUGIN_DRIZZLE_PROTOCOL_STATUS_TABLE_H */
5863
=== renamed file 'plugin/drizzle_protocol/vio.cc' => 'plugin/drizzle_protocol/vio.cc.THIS'
=== renamed file 'plugin/drizzle_protocol/vio.h' => 'plugin/drizzle_protocol/vio.h.THIS'
=== renamed file 'plugin/drizzle_protocol/viosocket.cc' => 'plugin/drizzle_protocol/viosocket.cc.THIS'
=== modified file 'plugin/information_schema_dictionary/key_column_usage.cc'
--- plugin/information_schema_dictionary/key_column_usage.cc 2010-07-11 15:57:03 +0000
+++ plugin/information_schema_dictionary/key_column_usage.cc 2010-10-06 01:14:00 +0000
@@ -41,7 +41,9 @@
41 InformationSchema::Generator(arg),41 InformationSchema::Generator(arg),
42 generator(getSession()),42 generator(getSession()),
43 index_iterator(0),43 index_iterator(0),
44 index_part_iterator(0)44 index_part_iterator(0),
45 fk_constraint_iterator(0),
46 fk_constraint_column_name_iterator(0)
45{47{
46 while (not (table_message= generator))48 while (not (table_message= generator))
47 { };49 { };
@@ -84,7 +86,7 @@
84 push(table_message->field(fieldnr).name());86 push(table_message->field(fieldnr).name());
8587
86 /* ORDINAL_POSITION */88 /* ORDINAL_POSITION */
87 push(static_cast<int64_t>(index_part_iterator));89 push(static_cast<int64_t>((index_part_iterator +1)));
8890
89 if (index_part_iterator == index.index_part_size() -1)91 if (index_part_iterator == index.index_part_size() -1)
90 {92 {
@@ -100,9 +102,56 @@
100 }102 }
101 }103 }
102104
105 if (fk_constraint_iterator != table_message->fk_constraint_size())
106 {
107 drizzled::message::Table::ForeignKeyConstraint foreign_key= table_message->fk_constraint(fk_constraint_iterator);
108
109 {
110 /* Constraints live in the same catalog.schema as the table they refer too. */
111 /* CONSTRAINT_CATALOG */
112 push(table_message->catalog());
113
114 /* CONSTRAINT_SCHEMA */
115 push(table_message->schema());
116
117 /* CONSTRAINT_NAME */
118 push(foreign_key.name());
119
120 /* TABLE_CATALOG */
121 push(table_message->catalog());
122
123 /* TABLE_SCHEMA */
124 push(table_message->schema());
125
126 /* TABLE_NAME */
127 push(table_message->name());
128
129 /* COLUMN_NAME */
130 push(foreign_key.column_names(fk_constraint_column_name_iterator));
131
132 /* ORDINAL_POSITION */
133 push(static_cast<int64_t>((fk_constraint_column_name_iterator + 1)));
134
135 if (fk_constraint_column_name_iterator == foreign_key.column_names_size() -1)
136 {
137 fk_constraint_iterator++;
138 fk_constraint_column_name_iterator= 0;
139 }
140 else
141 {
142 fk_constraint_column_name_iterator++;
143 }
144
145 return true;
146 }
147 }
148
103 index_iterator= 0;149 index_iterator= 0;
104 index_part_iterator= 0;150 index_part_iterator= 0;
105151
152 fk_constraint_iterator= 0;
153 fk_constraint_column_name_iterator= 0;
154
106 } while ((table_message= generator));155 } while ((table_message= generator));
107156
108 return false;157 return false;
109158
=== modified file 'plugin/information_schema_dictionary/key_column_usage.h'
--- plugin/information_schema_dictionary/key_column_usage.h 2010-07-09 21:52:18 +0000
+++ plugin/information_schema_dictionary/key_column_usage.h 2010-10-06 01:14:00 +0000
@@ -34,6 +34,9 @@
34 int32_t index_iterator;34 int32_t index_iterator;
35 int32_t index_part_iterator;35 int32_t index_part_iterator;
3636
37 int32_t fk_constraint_iterator;
38 int32_t fk_constraint_column_name_iterator;
39
37 public:40 public:
38 Generator(drizzled::Field **arg);41 Generator(drizzled::Field **arg);
3942
4043
=== modified file 'plugin/information_schema_dictionary/tests/r/key_column_usage.result'
--- plugin/information_schema_dictionary/tests/r/key_column_usage.result 2010-07-09 21:52:18 +0000
+++ plugin/information_schema_dictionary/tests/r/key_column_usage.result 2010-10-06 01:14:00 +0000
@@ -336,40 +336,40 @@
336) ;336) ;
337select * from information_schema.key_column_usage WHERE table_schema="everything" ORDER BY TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME;337select * from information_schema.key_column_usage WHERE table_schema="everything" ORDER BY TABLE_SCHEMA, TABLE_NAME, COLUMN_NAME;
338CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION338CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION
339 everything PRIMARY everything branch branch_id 0339 everything PRIMARY everything branch branch_id 1
340 everything PRIMARY everything container container_id 0340 everything PRIMARY everything container container_id 1
341 everything PRIMARY everything document document_id 0341 everything PRIMARY everything document document_id 1
342 everything PRIMARY everything genstats_attributes genstats_attributes_id 0342 everything PRIMARY everything genstats_attributes genstats_attributes_id 1
343 everything PRIMARY everything htmlcode htmlcode_id 0343 everything PRIMARY everything htmlcode htmlcode_id 1
344 everything PRIMARY everything htmlpage htmlpage_id 0344 everything PRIMARY everything htmlpage htmlpage_id 1
345 everything PRIMARY everything image image_id 0345 everything PRIMARY everything image image_id 1
346 everything PRIMARY everything javascript javascript_id 0346 everything PRIMARY everything javascript javascript_id 1
347 everything PRIMARY everything knowledge_item knowledge_item_id 0347 everything PRIMARY everything knowledge_item knowledge_item_id 1
348 everything PRIMARY everything links from_node 0348 everything PRIMARY everything links from_node 1
349 everything PRIMARY everything links linktype 2349 everything PRIMARY everything links linktype 3
350 everything PRIMARY everything links to_node 1350 everything PRIMARY everything links to_node 2
351 everything PRIMARY everything mail mail_id 0351 everything PRIMARY everything mail mail_id 1
352 everything PRIMARY everything node node_id 0352 everything PRIMARY everything node node_id 1
353 everything PRIMARY everything nodegroup nodegroup_id 0353 everything PRIMARY everything nodegroup nodegroup_id 1
354 everything PRIMARY everything nodegroup rank 1354 everything PRIMARY everything nodegroup rank 2
355 everything PRIMARY everything nodelet nodelet_id 0355 everything PRIMARY everything nodelet nodelet_id 1
356 everything PRIMARY everything nodemethod nodemethod_id 0356 everything PRIMARY everything nodemethod nodemethod_id 1
357 everything PRIMARY everything nodetype nodetype_id 0357 everything PRIMARY everything nodetype nodetype_id 1
358 everything PRIMARY everything project project_id 0358 everything PRIMARY everything project project_id 1
359 everything PRIMARY everything project_document project_document_id 0359 everything PRIMARY everything project_document project_document_id 1
360 everything PRIMARY everything question question_id 0360 everything PRIMARY everything question question_id 1
361 everything PRIMARY everything question rank 1361 everything PRIMARY everything question rank 2
362 everything PRIMARY everything redirects redirects_id 0362 everything PRIMARY everything redirects redirects_id 1
363 everything PRIMARY everything releases releases_id 0363 everything PRIMARY everything releases releases_id 1
364 everything PRIMARY everything revision inside_workspace 1364 everything PRIMARY everything revision inside_workspace 2
365 everything PRIMARY everything revision node_id 0365 everything PRIMARY everything revision node_id 1
366 everything PRIMARY everything revision revision_id 2366 everything PRIMARY everything revision revision_id 3
367 everything PRIMARY everything setting setting_id 0367 everything PRIMARY everything setting setting_id 1
368 everything PRIMARY everything symlink symlink_id 0368 everything PRIMARY everything symlink symlink_id 1
369 everything PRIMARY everything themesetting themesetting_id 0369 everything PRIMARY everything themesetting themesetting_id 1
370 everything PRIMARY everything typeversion typeversion_id 0370 everything PRIMARY everything typeversion typeversion_id 1
371 everything PRIMARY everything user user_id 0371 everything PRIMARY everything user user_id 1
372 everything PRIMARY everything version version_id 0372 everything PRIMARY everything version version_id 1
373 everything PRIMARY everything weblog entry_id 0373 everything PRIMARY everything weblog entry_id 1
374 everything PRIMARY everything workspace workspace_id 0374 everything PRIMARY everything workspace workspace_id 1
375drop schema everything;375drop schema everything;
376376
=== modified file 'tests/include.am'
--- tests/include.am 2010-10-02 21:15:42 +0000
+++ tests/include.am 2010-10-06 01:14:00 +0000
@@ -22,8 +22,8 @@
22GENSCRIPTS = tests/dtr tests/mtr tests/test-run22GENSCRIPTS = tests/dtr tests/mtr tests/test-run
23PRESCRIPTS = tests/test-run.pl tests/stress-test.pl23PRESCRIPTS = tests/test-run.pl tests/stress-test.pl
24PLUGIN_TESTS = $(pandora_plugin_test_list)24PLUGIN_TESTS = $(pandora_plugin_test_list)
25NORMAL_TESTS = main,jp,tamil,$(PLUGIN_TESTS)25NORMAL_TESTS = main,jp,tamil,regression,$(PLUGIN_TESTS)
26ALL_TESTS = main,big,jp,tamil,$(PLUGIN_TESTS)26ALL_TESTS = main,big,jp,tamil,regression,$(PLUGIN_TESTS)
27noinst_SCRIPTS = $(GENSCRIPTS) $(PRESCRIPTS)27noinst_SCRIPTS = $(GENSCRIPTS) $(PRESCRIPTS)
28CLEANFILES += $(GENSCRIPTS) tests/mtr28CLEANFILES += $(GENSCRIPTS) tests/mtr
2929
3030
=== added directory 'tests/suite/regression'
=== added directory 'tests/suite/regression/r'
=== added file 'tests/suite/regression/r/654219.result'
--- tests/suite/regression/r/654219.result 1970-01-01 00:00:00 +0000
+++ tests/suite/regression/r/654219.result 2010-10-06 01:14:00 +0000
@@ -0,0 +1,63 @@
1CREATE TABLE `prim_key` (
2`id` INT NOT NULL,
3`val` VARCHAR(20) COLLATE utf8_general_ci DEFAULT NULL,
4PRIMARY KEY (`id`)
5);
6CREATE TABLE `fore_key0` (
7`id` INT NOT NULL,
8`id_ref0` INT DEFAULT NULL,
9PRIMARY KEY (`id`),
10KEY `id_ref0` (`id_ref0`),
11CONSTRAINT `fore_key0_ibfk_1` FOREIGN KEY (`id_ref0`) REFERENCES
12`prim_key` (`id`)
13);
14CREATE TABLE `fore_key1` (
15`id` INT NOT NULL,
16`id_ref1` INT DEFAULT NULL,
17PRIMARY KEY (`id`),
18KEY `id_ref1` (`id_ref1`),
19CONSTRAINT `fore_key1_ibfk_1` FOREIGN KEY (`id_ref1`) REFERENCES
20`prim_key` (`id`) ON UPDATE CASCADE
21);
22SELECT CONSTRAINT_NAME,TABLE_NAME,COLUMN_NAME,ORDINAL_POSITION FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE;
23CONSTRAINT_NAME TABLE_NAME COLUMN_NAME ORDINAL_POSITION
24PRIMARY prim_key id 1
25PRIMARY fore_key1 id 1
26fore_key1_ibfk_1 fore_key1 id_ref1 1
27PRIMARY fore_key0 id 1
28fore_key0_ibfk_1 fore_key0 id_ref0 1
29DROP TABLE fore_key1;
30DROP TABLE fore_key0;
31DROP TABLE prim_key;
32CREATE TABLE t1
33(
34s1 INT,
35s2 INT,
36s3 INT,
37PRIMARY KEY(s3)
38);
39CREATE TABLE t3
40(
41s1 INT,
42s2 INT,
43s3 INT,
44KEY(s1),
45CONSTRAINT CO FOREIGN KEY (s2)
46REFERENCES t1(s3)
47);
48SELECT CONSTRAINT_NAME,TABLE_NAME,COLUMN_NAME,ORDINAL_POSITION FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE;
49CONSTRAINT_NAME TABLE_NAME COLUMN_NAME ORDINAL_POSITION
50CO t3 s2 1
51PRIMARY t1 s3 1
52DROP TABLE t3;
53DROP TABLE t1;
54CREATE TABLE t1 (c1 INT NOT NULL, c2 INT NOT NULL, c3 CHAR(5), c4 INT, c5 INT, constraint pk_t1 PRIMARY KEY (c5,c4));
55CREATE TABLE T2 (tc1 INT NOT NULL, c1 INT NOT NULL, c2 INT NOT NULL, c5 CHAR(5), constraint fk_t2 FOREIGN KEY (c1,c2) REFERENCES t1 (c5,c4));
56SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME IN ('t1', 't2');
57CONSTRAINT_NAME TABLE_NAME COLUMN_NAME ORDINAL_POSITION
58PRIMARY t1 c5 1
59PRIMARY t1 c4 2
60fk_t2 t2 c1 1
61fk_t2 t2 c2 2
62DROP TABLE t2;
63DROP TABLE t1;
064
=== added directory 'tests/suite/regression/t'
=== added file 'tests/suite/regression/t/654219.test'
--- tests/suite/regression/t/654219.test 1970-01-01 00:00:00 +0000
+++ tests/suite/regression/t/654219.test 2010-10-06 01:14:00 +0000
@@ -0,0 +1,64 @@
1CREATE TABLE `prim_key` (
2 `id` INT NOT NULL,
3 `val` VARCHAR(20) COLLATE utf8_general_ci DEFAULT NULL,
4 PRIMARY KEY (`id`)
5);
6
7CREATE TABLE `fore_key0` (
8 `id` INT NOT NULL,
9 `id_ref0` INT DEFAULT NULL,
10 PRIMARY KEY (`id`),
11 KEY `id_ref0` (`id_ref0`),
12 CONSTRAINT `fore_key0_ibfk_1` FOREIGN KEY (`id_ref0`) REFERENCES
13 `prim_key` (`id`)
14);
15
16CREATE TABLE `fore_key1` (
17 `id` INT NOT NULL,
18 `id_ref1` INT DEFAULT NULL,
19 PRIMARY KEY (`id`),
20 KEY `id_ref1` (`id_ref1`),
21 CONSTRAINT `fore_key1_ibfk_1` FOREIGN KEY (`id_ref1`) REFERENCES
22 `prim_key` (`id`) ON UPDATE CASCADE
23);
24
25SELECT CONSTRAINT_NAME,TABLE_NAME,COLUMN_NAME,ORDINAL_POSITION FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE;
26
27DROP TABLE fore_key1;
28DROP TABLE fore_key0;
29DROP TABLE prim_key;
30
31# Taken from MySQL example
32CREATE TABLE t1
33(
34 s1 INT,
35 s2 INT,
36 s3 INT,
37 PRIMARY KEY(s3)
38);
39
40CREATE TABLE t3
41(
42 s1 INT,
43 s2 INT,
44 s3 INT,
45 KEY(s1),
46 CONSTRAINT CO FOREIGN KEY (s2)
47 REFERENCES t1(s3)
48);
49
50SELECT CONSTRAINT_NAME,TABLE_NAME,COLUMN_NAME,ORDINAL_POSITION FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE;
51
52DROP TABLE t3;
53DROP TABLE t1;
54
55# Taken from SQL Server example
56CREATE TABLE t1 (c1 INT NOT NULL, c2 INT NOT NULL, c3 CHAR(5), c4 INT, c5 INT, constraint pk_t1 PRIMARY KEY (c5,c4));
57
58CREATE TABLE T2 (tc1 INT NOT NULL, c1 INT NOT NULL, c2 INT NOT NULL, c5 CHAR(5), constraint fk_t2 FOREIGN KEY (c1,c2) REFERENCES t1 (c5,c4));
59
60SELECT CONSTRAINT_NAME, TABLE_NAME, COLUMN_NAME, ORDINAL_POSITION FROM INFORMATION_SCHEMA.KEY_COLUMN_USAGE WHERE TABLE_NAME IN ('t1', 't2');
61
62DROP TABLE t2;
63DROP TABLE t1;
64