1
/* Copyright (C) 2008 Drizzle Open Source Project
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
17
This file is included by both libdrizzle.c (the DRIZZLE client C API)
18
and the drizzled server to connect to another DRIZZLE server.
20
The differences for the two cases are:
22
- Things that only works for the client:
23
- Trying to automaticly determinate user name if not supplied to
25
- Support for reading local file with LOAD DATA LOCAL
26
- SHARED memory handling
27
- Protection against sigpipe
30
- Things that only works for the server
31
- Alarm handling on connect
33
In all other cases, the code should be idential for the client and
37
#include <drizzled/global.h>
42
#include <sys/ioctl.h>
46
/* Remove client convenience wrappers */
47
#undef max_allowed_packet
48
#undef net_buffer_length
50
#define CLI_DRIZZLE_CONNECT STDCALL drizzle_connect
52
#include <mysys/my_sys.h>
53
#include <mysys/mysys_err.h>
54
#include <mystrings/m_string.h>
55
#include <mystrings/m_ctype.h>
56
#include <drizzled/error.h>
58
#include <vio/violite.h>
59
#include <mysys/my_pthread.h> /* because of signal() */
68
#include <sys/socket.h>
69
#include <netinet/in.h>
70
#include <arpa/inet.h>
75
#ifdef HAVE_SYS_SELECT_H
76
#include <sys/select.h>
82
#define SOCKET_ERROR -1
84
#define CONNECT_TIMEOUT 0
86
#include "client_settings.h"
87
#include <libdrizzle/sql_common.h>
90
char *drizzle_unix_port= 0;
91
const char *unknown_sqlstate= "HY000";
92
const char *not_error_sqlstate= "00000";
93
const char *cant_connect_sqlstate= "08001";
95
static bool drizzle_client_init= false;
96
static bool org_my_init_done= false;
98
static void drizzle_close_free_options(DRIZZLE *drizzle);
99
static void drizzle_close_free(DRIZZLE *drizzle);
101
static int wait_for_data(my_socket fd, uint timeout);
103
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
105
/* Server error code and message */
106
unsigned int drizzle_server_last_errno;
107
char drizzle_server_last_error[DRIZZLE_ERRMSG_SIZE];
109
/****************************************************************************
110
A modified version of connect(). my_connect() allows you to specify
111
a timeout value, in seconds, that we should wait until we
112
derermine we can't connect to a particular host. If timeout is 0,
113
my_connect() will behave exactly like connect().
115
Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
116
*****************************************************************************/
118
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
121
int flags, res, s_err;
124
If they passed us a timeout of zero, we should behave
125
exactly like the normal connect() call does.
129
return connect(fd, (struct sockaddr*) name, namelen);
131
flags = fcntl(fd, F_GETFL, 0); /* Set socket to not block */
133
fcntl(fd, F_SETFL, flags | O_NONBLOCK); /* and save the flags.. */
136
res= connect(fd, (struct sockaddr*) name, namelen);
137
s_err= errno; /* Save the error... */
138
fcntl(fd, F_SETFL, flags);
139
if ((res != 0) && (s_err != EINPROGRESS))
141
errno= s_err; /* Restore it */
144
if (res == 0) /* Connected quickly! */
146
return wait_for_data(fd, timeout);
151
Wait up to timeout seconds for a connection to be established.
153
We prefer to do this with poll() as there is no limitations with this.
154
If not, we will use select()
157
static int wait_for_data(my_socket fd, uint timeout)
164
ufds.events= POLLIN | POLLPRI;
165
if (!(res= poll(&ufds, 1, (int) timeout*1000)))
170
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)))
174
SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
177
time_t start_time, now_time;
180
if (fd >= FD_SETSIZE) /* Check if wrong error */
181
return 0; /* Can't use timeout */
184
Our connection is "in progress." We can use the select() call to wait
185
up to a specified period of time for the connection to suceed.
186
If select() returns 0 (after waiting howevermany seconds), our socket
187
never became writable (host is probably unreachable.) Otherwise, if
188
select() returns 1, then one of two conditions exist:
190
1. An error occured. We use getsockopt() to check for this.
191
2. The connection was set up sucessfully: getsockopt() will
192
return 0 as an error.
194
Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
195
who posted this method of timing out a connect() in
196
comp.unix.programmer on August 15th, 1997.
202
select could be interrupted by a signal, and if it is,
203
the timeout should be adjusted and the select restarted
204
to work around OSes that don't restart select and
205
implementations of select that don't adjust tv upon
206
failure to reflect the time remaining
208
start_time= my_time(0);
211
tv.tv_sec = (long) timeout;
214
if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
217
if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
220
if (res == 0) /* timeout */
222
now_time= my_time(0);
223
timeout-= (uint) (now_time - start_time);
224
if (errno != EINTR || (int) timeout <= 0)
229
select() returned something more interesting than zero, let's
230
see if we have any errors. If the next two statements pass,
231
we've got an open socket!
235
if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
239
{ /* getsockopt could succeed */
241
return(-1); /* but return an error... */
244
#endif /* HAVE_POLL */
248
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
249
struct passwd *getpwuid(uid_t);
250
char* getlogin(void);
253
static void read_user_name(char *name)
256
strcpy(name,"root"); /* allow use of surun */
262
if ((str=getlogin()) == NULL)
264
if ((skr=getpwuid(geteuid())) != NULL)
266
else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
267
!(str=getenv("LOGIN")))
270
strncpy(name,str,USERNAME_LENGTH);
272
(void) cuserid(name);
274
strcpy(name,"UNKNOWN_USER");
282
Set the internal error message to DRIZZLE handler
284
@param drizzle connection handle (client side)
285
@param errcode CR_ error code, passed to ER macro to get
287
@parma sqlstate SQL standard sqlstate
290
void set_drizzle_error(DRIZZLE *drizzle, int errcode, const char *sqlstate)
293
assert(drizzle != 0);
298
net->last_errno= errcode;
299
strcpy(net->last_error, ER(errcode));
300
strcpy(net->sqlstate, sqlstate);
304
drizzle_server_last_errno= errcode;
305
strcpy(drizzle_server_last_error, ER(errcode));
311
Clear possible error state of struct NET
313
@param net clear the state of the argument
316
void net_clear_error(NET *net)
319
net->last_error[0]= '\0';
320
strcpy(net->sqlstate, not_error_sqlstate);
324
Set an error message on the client.
326
@param drizzle connection handle
327
@param errcode CR_* errcode, for client errors
328
@param sqlstate SQL standard sql state, unknown_sqlstate for the
329
majority of client errors.
330
@param format error message template, in sprintf format
331
@param ... variable number of arguments
334
static void set_drizzle_extended_error(DRIZZLE *drizzle, int errcode,
335
const char *sqlstate,
336
const char *format, ...)
340
assert(drizzle != 0);
343
net->last_errno= errcode;
344
va_start(args, format);
345
vsnprintf(net->last_error, sizeof(net->last_error)-1,
348
strcpy(net->sqlstate, sqlstate);
353
/*****************************************************************************
354
Read a packet from server. Give error message if socket was down
355
or packet is an error message
356
*****************************************************************************/
358
uint32_t cli_safe_read(DRIZZLE *drizzle)
360
NET *net= &drizzle->net;
362
init_sigpipe_variables
364
/* Don't give sigpipe errors if the client doesn't want them */
365
set_sigpipe(drizzle);
367
len=my_net_read(net);
368
reset_sigpipe(drizzle);
370
if (len == packet_error || len == 0)
373
if (net->vio && vio_was_interrupted(net->vio))
374
return (packet_error);
375
#endif /*DRIZZLE_SERVER*/
377
set_drizzle_error(drizzle, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
378
CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
379
return (packet_error);
381
if (net->read_pos[0] == 255)
385
char *pos=(char*) net->read_pos+1;
386
net->last_errno=uint2korr(pos);
389
if (protocol_41(drizzle) && pos[0] == '#')
391
strncpy(net->sqlstate, pos+1, SQLSTATE_LENGTH);
392
pos+= SQLSTATE_LENGTH+1;
397
The SQL state hasn't been received -- it should be reset to HY000
398
(unknown error sql state).
401
strcpy(net->sqlstate, unknown_sqlstate);
404
strncpy(net->last_error,(char*) pos, min((uint) len,
405
(uint32_t) sizeof(net->last_error)-1));
408
set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
410
Cover a protocol design error: error packet does not
411
contain the server status. Therefore, the client has no way
412
to find out whether there are more result sets of
413
a multiple-result-set statement pending. Luckily, in 5.0 an
414
error always aborts execution of a statement, wherever it is
415
a multi-statement or a stored procedure, so it should be
416
safe to unconditionally turn off the flag here.
418
drizzle->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
420
return(packet_error);
425
void free_rows(DRIZZLE_DATA *cur)
429
free_root(&cur->alloc,MYF(0));
430
my_free((uchar*) cur,MYF(0));
435
cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
436
const unsigned char *header, uint32_t header_length,
437
const unsigned char *arg, uint32_t arg_length, bool skip_check)
439
NET *net= &drizzle->net;
441
init_sigpipe_variables
442
my_bool stmt_skip= false;
444
/* Don't give sigpipe errors if the client doesn't want them */
445
set_sigpipe(drizzle);
447
if (drizzle->net.vio == 0)
448
{ /* Do reconnect if possible */
449
if (drizzle_reconnect(drizzle) || stmt_skip)
452
if (drizzle->status != DRIZZLE_STATUS_READY ||
453
drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
455
set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
459
net_clear_error(net);
461
drizzle->affected_rows= ~(uint64_t) 0;
463
We don't want to clear the protocol buffer on COM_QUIT, because if
464
the previous command was a shutdown command, we may have the
465
response for the COM_QUIT already in the communication buffer
467
net_clear(&drizzle->net, (command != COM_QUIT));
469
if (net_write_command(net,(uchar) command, header, header_length,
472
if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
474
set_drizzle_error(drizzle, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
478
if (drizzle_reconnect(drizzle) || stmt_skip)
480
if (net_write_command(net,(uchar) command, header, header_length,
483
set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
489
result= ((drizzle->packet_length=cli_safe_read(drizzle)) == packet_error ?
492
reset_sigpipe(drizzle);
496
void free_old_query(DRIZZLE *drizzle)
499
free_root(&drizzle->field_alloc,MYF(0));
500
init_alloc_root(&drizzle->field_alloc,8192,0); /* Assume rowlength < 8192 */
502
drizzle->field_count= 0; /* For API */
503
drizzle->warning_count= 0;
509
Flush result set sent from server
512
static void cli_flush_use_result(DRIZZLE *drizzle)
514
/* Clear the current execution status */
518
if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
520
if (pkt_len <= 8 && drizzle->net.read_pos[0] == 254)
522
if (protocol_41(drizzle))
524
char *pos= (char*) drizzle->net.read_pos + 1;
525
drizzle->warning_count=uint2korr(pos); pos+=2;
526
drizzle->server_status=uint2korr(pos); pos+=2;
528
break; /* End of data */
535
/**************************************************************************
537
**************************************************************************/
539
void end_server(DRIZZLE *drizzle)
541
int save_errno= errno;
542
if (drizzle->net.vio != 0)
544
init_sigpipe_variables
545
set_sigpipe(drizzle);
546
vio_delete(drizzle->net.vio);
547
reset_sigpipe(drizzle);
548
drizzle->net.vio= 0; /* Marker */
550
net_end(&drizzle->net);
551
free_old_query(drizzle);
558
drizzle_free_result(DRIZZLE_RES *result)
562
DRIZZLE *drizzle= result->handle;
565
if (drizzle->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
566
drizzle->unbuffered_fetch_owner= 0;
567
if (drizzle->status == DRIZZLE_STATUS_USE_RESULT)
569
(*drizzle->methods->flush_use_result)(drizzle);
570
drizzle->status=DRIZZLE_STATUS_READY;
571
if (drizzle->unbuffered_fetch_owner)
572
*drizzle->unbuffered_fetch_owner= true;
575
free_rows(result->data);
577
free_root(&result->field_alloc,MYF(0));
579
my_free((uchar*) result->row,MYF(0));
580
my_free((uchar*) result,MYF(0));
585
/****************************************************************************
586
Get options from my.cnf
587
****************************************************************************/
589
static const char *default_options[]=
591
"port","socket","compress","password","pipe", "timeout", "user",
592
"init-command", "host", "database", "return-found-rows",
593
"ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
594
"character-sets-dir", "default-character-set", "interactive-timeout",
595
"connect-timeout", "local-infile", "disable-local-infile",
596
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
597
"multi-results", "multi-statements", "multi-queries", "secure-auth",
598
"report-data-truncation",
602
static TYPELIB option_types={array_elements(default_options)-1,
603
"options",default_options, NULL};
605
const char *sql_protocol_names_lib[] =
606
{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
607
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
608
sql_protocol_names_lib, NULL};
610
static int add_init_command(struct st_drizzle_options *options, const char *cmd)
614
if (!options->init_commands)
616
options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
618
init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
621
if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
622
insert_dynamic(options->init_commands, (uchar*)&tmp))
624
my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
631
void drizzle_read_default_options(struct st_drizzle_options *options,
632
const char *filename,const char *group)
635
char *argv_buff[1],**argv;
636
const char *groups[3];
638
argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
639
groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
641
load_defaults(filename, groups, &argc, &argv);
642
if (argc != 1) /* If some default option */
647
if (option[0][0] == '-' && option[0][1] == '-')
649
char *end=strcend(*option,'=');
654
*end=0; /* Remove '=' */
656
/* Change all '_' in variable name to '-' */
657
for (end= *option ; *(end= strcend(end,'_')) ; )
659
switch (find_type(*option+2,&option_types,2)) {
662
options->port=atoi(opt_arg);
667
my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
668
options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
671
case 3: /* compress */
673
options->client_flag|= CLIENT_COMPRESS;
675
case 4: /* password */
678
my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
679
options->password=my_strdup(opt_arg,MYF(MY_WME));
682
case 20: /* connect_timeout */
683
case 6: /* timeout */
685
options->connect_timeout=atoi(opt_arg);
690
my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
691
options->user=my_strdup(opt_arg,MYF(MY_WME));
694
case 8: /* init-command */
695
add_init_command(options,opt_arg);
700
my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
701
options->host=my_strdup(opt_arg,MYF(MY_WME));
704
case 10: /* database */
707
my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
708
options->db=my_strdup(opt_arg,MYF(MY_WME));
711
case 12: /* return-found-rows */
712
options->client_flag|=CLIENT_FOUND_ROWS;
714
case 13: /* Ignore SSL options */
720
case 17: /* charset-lib */
721
my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
722
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
725
my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
726
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
728
case 19: /* Interactive-timeout */
729
options->client_flag|= CLIENT_INTERACTIVE;
732
if (!opt_arg || atoi(opt_arg) != 0)
733
options->client_flag|= CLIENT_LOCAL_FILES;
735
options->client_flag&= ~CLIENT_LOCAL_FILES;
738
options->client_flag&= ~CLIENT_LOCAL_FILES;
740
case 24: /* max-allowed-packet */
742
options->max_allowed_packet= atoi(opt_arg);
744
case 25: /* protocol */
745
if ((options->protocol= find_type(opt_arg,
746
&sql_protocol_typelib,0)) <= 0)
748
fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
752
case 27: /* multi-results */
753
options->client_flag|= CLIENT_MULTI_RESULTS;
755
case 28: /* multi-statements */
756
case 29: /* multi-queries */
757
options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
759
case 30: /* secure-auth */
760
options->secure_auth= true;
762
case 31: /* report-data-truncation */
763
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
776
/**************************************************************************
777
Get column lengths of the current row
778
If one uses drizzle_use_result, res->lengths contains the length information,
779
else the lengths are calculated from the offset between pointers.
780
**************************************************************************/
782
static void cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count)
784
uint32_t *prev_length;
788
prev_length=0; /* Keep gcc happy */
789
for (end=column + field_count + 1 ; column != end ; column++, to++)
796
if (start) /* Found end of prev string */
797
*prev_length= (ulong) (*column-start-1);
803
/***************************************************************************
804
Change field rows to field structs
805
***************************************************************************/
808
unpack_fields(DRIZZLE_DATA *data,MEM_ROOT *alloc,uint fields,
809
my_bool default_value, uint server_capabilities)
812
DRIZZLE_FIELD *field,*result;
813
uint32_t lengths[9]; /* Max of fields */
815
field= result= (DRIZZLE_FIELD*) alloc_root(alloc,
816
(uint) sizeof(*field)*fields);
819
free_rows(data); /* Free old data */
822
memset((char*) field, 0, (uint) sizeof(DRIZZLE_FIELD)*fields);
823
if (server_capabilities & CLIENT_PROTOCOL_41)
825
/* server is 4.1, and returns the new field result format */
826
for (row=data->data; row ; row = row->next,field++)
829
/* fields count may be wrong */
830
assert((uint) (field - result) < fields);
831
cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
832
field->catalog= strmake_root(alloc,(char*) row->data[0], lengths[0]);
833
field->db= strmake_root(alloc,(char*) row->data[1], lengths[1]);
834
field->table= strmake_root(alloc,(char*) row->data[2], lengths[2]);
835
field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
836
field->name= strmake_root(alloc,(char*) row->data[4], lengths[4]);
837
field->org_name= strmake_root(alloc,(char*) row->data[5], lengths[5]);
839
field->catalog_length= lengths[0];
840
field->db_length= lengths[1];
841
field->table_length= lengths[2];
842
field->org_table_length= lengths[3];
843
field->name_length= lengths[4];
844
field->org_name_length= lengths[5];
846
/* Unpack fixed length parts */
847
pos= (uchar*) row->data[6];
848
field->charsetnr= uint2korr(pos);
849
field->length= (uint) uint4korr(pos+2);
850
field->type= (enum enum_field_types) pos[6];
851
field->flags= uint2korr(pos+7);
852
field->decimals= (uint) pos[9];
854
if (INTERNAL_NUM_FIELD(field))
855
field->flags|= NUM_FLAG;
856
if (default_value && row->data[7])
858
field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
859
field->def_length= lengths[7];
863
field->max_length= 0;
866
#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL
869
/* old protocol, for backward compatibility */
870
for (row=data->data; row ; row = row->next,field++)
872
cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
873
field->org_table= field->table= strdup_root(alloc,(char*) row->data[0]);
874
field->name= strdup_root(alloc,(char*) row->data[1]);
875
field->length= (uint) uint3korr(row->data[2]);
876
field->type= (enum enum_field_types) (uchar) row->data[3][0];
878
field->catalog=(char*) "";
879
field->db= (char*) "";
880
field->catalog_length= 0;
882
field->org_table_length= field->table_length= lengths[0];
883
field->name_length= lengths[1];
885
if (server_capabilities & CLIENT_LONG_FLAG)
887
field->flags= uint2korr(row->data[4]);
888
field->decimals=(uint) (uchar) row->data[4][2];
892
field->flags= (uint) (uchar) row->data[4][0];
893
field->decimals=(uint) (uchar) row->data[4][1];
895
if (INTERNAL_NUM_FIELD(field))
896
field->flags|= NUM_FLAG;
897
if (default_value && row->data[5])
899
field->def=strdup_root(alloc,(char*) row->data[5]);
900
field->def_length= lengths[5];
904
field->max_length= 0;
907
#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */
908
free_rows(data); /* Free old data */
912
/* Read all rows (fields or data) from server */
914
DRIZZLE_DATA *cli_read_rows(DRIZZLE *drizzle,DRIZZLE_FIELD *DRIZZLE_FIELDs,
922
DRIZZLE_DATA *result;
923
DRIZZLE_ROWS **prev_ptr,*cur;
924
NET *net = &drizzle->net;
926
if ((pkt_len= cli_safe_read(drizzle)) == packet_error)
928
if (!(result=(DRIZZLE_DATA*) my_malloc(sizeof(DRIZZLE_DATA),
929
MYF(MY_WME | MY_ZEROFILL))))
931
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
934
init_alloc_root(&result->alloc,8192,0); /* Assume rowlength < 8192 */
935
result->alloc.min_malloc=sizeof(DRIZZLE_ROWS);
936
prev_ptr= &result->data;
938
result->fields=fields;
941
The last EOF packet is either a single 254 character or (in DRIZZLE 4.1)
942
254 followed by 1-7 status bytes.
944
This doesn't conflict with normal usage of 254 which stands for a
945
string where the length of the string is 8 bytes. (see net_field_length())
948
while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
951
if (!(cur= (DRIZZLE_ROWS*) alloc_root(&result->alloc,
952
sizeof(DRIZZLE_ROWS))) ||
953
!(cur->data= ((DRIZZLE_ROW)
954
alloc_root(&result->alloc,
955
(fields+1)*sizeof(char *)+pkt_len))))
958
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
962
prev_ptr= &cur->next;
963
to= (char*) (cur->data+fields+1);
965
for (field=0 ; field < fields ; field++)
967
if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
969
cur->data[field] = 0;
973
cur->data[field] = to;
974
if (len > (ulong) (end_to - to))
977
set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
980
memcpy(to,(char*) cp,len); to[len]=0;
985
if (DRIZZLE_FIELDs[field].max_length < len)
986
DRIZZLE_FIELDs[field].max_length=len;
990
cur->data[field]=to; /* End of last field */
991
if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
997
*prev_ptr=0; /* last pointer is null */
998
if (pkt_len > 1) /* DRIZZLE 4.1 protocol */
1000
drizzle->warning_count= uint2korr(cp+1);
1001
drizzle->server_status= uint2korr(cp+3);
1007
Read one row. Uses packet buffer as storage for fields.
1008
When next packet is read, the previous field values are destroyed
1013
read_one_row(DRIZZLE *drizzle, uint32_t fields, DRIZZLE_ROW row, uint32_t *lengths)
1017
uchar *pos, *prev_pos, *end_pos;
1018
NET *net= &drizzle->net;
1020
if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
1022
if (pkt_len <= 8 && net->read_pos[0] == 254)
1024
if (pkt_len > 1) /* DRIZZLE 4.1 protocol */
1026
drizzle->warning_count= uint2korr(net->read_pos+1);
1027
drizzle->server_status= uint2korr(net->read_pos+3);
1029
return 1; /* End of data */
1031
prev_pos= 0; /* allowed to write at packet[-1] */
1033
end_pos=pos+pkt_len;
1034
for (field=0 ; field < fields ; field++)
1036
if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
1043
if (len > (ulong) (end_pos - pos))
1045
set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
1048
row[field] = (char*) pos;
1053
*prev_pos=0; /* Terminate prev field */
1056
row[field]=(char*) prev_pos+1; /* End of last field */
1057
*prev_pos=0; /* Terminate last field */
1062
/****************************************************************************
1063
Init DRIZZLE structure or allocate one
1064
****************************************************************************/
1067
drizzle_create(DRIZZLE *ptr)
1070
if (!drizzle_client_init)
1072
drizzle_client_init=true;
1073
org_my_init_done=my_init_done;
1075
/* Will init threads */
1083
drizzle_port = MYSQL_PORT;
1085
struct servent *serv_ptr;
1089
if builder specifically requested a default port, use that
1090
(even if it coincides with our factory default).
1091
only if they didn't do we check /etc/services (and, failing
1092
on that, fall back to the factory default of 4427).
1093
either default can be overridden by the environment variable
1094
MYSQL_TCP_PORT, which in turn can be overridden with command
1098
#if MYSQL_PORT_DEFAULT == 0
1099
if ((serv_ptr = getservbyname("drizzle", "tcp")))
1100
drizzle_port = (uint) ntohs((ushort) serv_ptr->s_port);
1102
if ((env = getenv("DRIZZLE_TCP_PORT")))
1103
drizzle_port =(uint) atoi(env);
1106
#if defined(SIGPIPE)
1107
(void) signal(SIGPIPE, SIG_IGN);
1111
/* Init if new thread */
1112
if (my_thread_init())
1117
ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
1121
set_drizzle_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
1124
memset(ptr, 0, sizeof(DRIZZLE));
1129
memset(ptr, 0, sizeof(DRIZZLE));
1132
ptr->options.connect_timeout= CONNECT_TIMEOUT;
1133
ptr->charset=default_client_charset_info;
1134
strcpy(ptr->net.sqlstate, not_error_sqlstate);
1137
Only enable LOAD DATA INFILE by default if configured with
1138
--enable-local-infile
1141
#if defined(ENABLED_LOCAL_INFILE) && !defined(DRIZZLE_SERVER)
1142
ptr->options.client_flag|= CLIENT_LOCAL_FILES;
1145
ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION;
1146
ptr->options.report_data_truncation= true; /* default */
1149
By default we don't reconnect because it could silently corrupt data (after
1150
reconnection you potentially lose table locks, user variables, session
1151
variables (transactions but they are specifically dealt with in
1152
drizzle_reconnect()).
1153
This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
1154
How this change impacts existing apps:
1155
- existing apps which relyed on the default will see a behaviour change;
1156
they will have to set reconnect=1 after drizzle_connect().
1157
- existing apps which explicitely asked for reconnection (the only way they
1158
could do it was by setting drizzle.reconnect to 1 after drizzle_connect())
1159
will not see a behaviour change.
1160
- existing apps which explicitely asked for no reconnection
1161
(drizzle.reconnect=0) will not see a behaviour change.
1170
Free all memory and resources used by the client library
1173
When calling this there should not be any other threads using
1176
To make things simpler when used with windows dll's (which calls this
1177
function automaticly), it's safe to call this function multiple times.
1181
void STDCALL drizzle_server_end()
1183
if (!drizzle_client_init)
1186
finish_client_errs();
1189
/* If library called my_init(), free memory allocated by it */
1190
if (!org_my_init_done)
1197
drizzle_thread_end();
1200
drizzle_client_init= org_my_init_done= 0;
1201
#ifdef EMBEDDED_SERVER
1204
fclose(stderror_file);
1212
Fill in SSL part of DRIZZLE structure and set 'use_ssl' flag.
1213
NB! Errors are not reported until you do drizzle_connect.
1216
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
1219
Note that the drizzle argument must be initialized with drizzle_init()
1220
before calling drizzle_connect !
1223
static bool cli_read_query_result(DRIZZLE *drizzle);
1224
static DRIZZLE_RES *cli_use_result(DRIZZLE *drizzle);
1226
static DRIZZLE_METHODS client_methods=
1228
cli_read_query_result, /* read_query_result */
1229
cli_advanced_command, /* advanced_command */
1230
cli_read_rows, /* read_rows */
1231
cli_use_result, /* use_result */
1232
cli_fetch_lengths, /* fetch_lengths */
1233
cli_flush_use_result, /* flush_use_result */
1234
#ifndef MYSQL_SERVER
1235
cli_list_fields, /* list_fields */
1236
cli_unbuffered_fetch, /* unbuffered_fetch */
1237
cli_read_statistics, /* read_statistics */
1238
cli_read_query_result, /* next_result */
1239
cli_read_change_user_result, /* read_change_user_result */
1246
int drizzle_init_character_set(DRIZZLE *drizzle)
1248
const char *default_collation_name;
1250
/* Set character set */
1251
if (!drizzle->options.charset_name)
1253
default_collation_name= MYSQL_DEFAULT_COLLATION_NAME;
1254
if (!(drizzle->options.charset_name=
1255
my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
1259
default_collation_name= NULL;
1262
const char *save= charsets_dir;
1263
if (drizzle->options.charset_dir)
1264
charsets_dir=drizzle->options.charset_dir;
1265
drizzle->charset=get_charset_by_csname(drizzle->options.charset_name,
1266
MY_CS_PRIMARY, MYF(MY_WME));
1267
if (drizzle->charset && default_collation_name)
1269
CHARSET_INFO *collation;
1271
get_charset_by_name(default_collation_name, MYF(MY_WME))))
1273
if (!my_charset_same(drizzle->charset, collation))
1275
my_printf_error(ER_UNKNOWN_ERROR,
1276
"COLLATION %s is not valid for CHARACTER SET %s",
1278
default_collation_name, drizzle->options.charset_name);
1279
drizzle->charset= NULL;
1283
drizzle->charset= collation;
1287
drizzle->charset= NULL;
1292
if (!drizzle->charset)
1294
if (drizzle->options.charset_dir)
1295
set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
1296
ER(CR_CANT_READ_CHARSET),
1297
drizzle->options.charset_name,
1298
drizzle->options.charset_dir);
1301
char cs_dir_name[FN_REFLEN];
1302
get_charsets_dir(cs_dir_name);
1303
set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
1304
ER(CR_CANT_READ_CHARSET),
1305
drizzle->options.charset_name,
1316
CLI_DRIZZLE_CONNECT(DRIZZLE *drizzle,const char *host, const char *user,
1317
const char *passwd, const char *db,
1318
uint32_t port, const char *unix_socket, uint32_t client_flag)
1320
char buff[NAME_LEN+USERNAME_LENGTH+100];
1321
char *end,*host_info=NULL;
1322
uint32_t pkt_length;
1323
NET *net= &drizzle->net;
1324
init_sigpipe_variables
1326
/* Don't give sigpipe errors if the client doesn't want them */
1327
set_sigpipe(drizzle);
1328
drizzle->methods= &client_methods;
1329
net->vio = 0; /* If something goes wrong */
1330
drizzle->client_flag=0; /* For handshake */
1332
/* use default options */
1333
if (drizzle->options.my_cnf_file || drizzle->options.my_cnf_group)
1335
drizzle_read_default_options(&drizzle->options,
1336
(drizzle->options.my_cnf_file ?
1337
drizzle->options.my_cnf_file : "my"),
1338
drizzle->options.my_cnf_group);
1339
my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1340
my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1341
drizzle->options.my_cnf_file=drizzle->options.my_cnf_group=0;
1344
/* Some empty-string-tests are done because of ODBC */
1345
if (!host || !host[0])
1346
host=drizzle->options.host;
1347
if (!user || !user[0])
1349
user=drizzle->options.user;
1355
passwd=drizzle->options.password;
1360
db=drizzle->options.db;
1362
port=drizzle->options.port;
1364
unix_socket=drizzle->options.unix_socket;
1366
drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
1369
Part 0: Grab a socket and connect it to the server
1372
(!drizzle->options.protocol ||
1373
drizzle->options.protocol == DRIZZLE_PROTOCOL_TCP))
1375
struct addrinfo *res_lst, hints, *t_res;
1377
char port_buf[NI_MAXSERV];
1379
unix_socket=0; /* This is not used */
1387
snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
1389
memset(&hints, 0, sizeof(hints));
1390
hints.ai_socktype= SOCK_STREAM;
1391
hints.ai_protocol= IPPROTO_TCP;
1392
hints.ai_family= AF_UNSPEC;
1394
snprintf(port_buf, NI_MAXSERV, "%d", port);
1395
gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
1399
set_drizzle_extended_error(drizzle, CR_UNKNOWN_HOST, unknown_sqlstate,
1400
ER(CR_UNKNOWN_HOST), host, errno);
1405
/* We only look at the first item (something to think about changing in the future) */
1408
my_socket sock= socket(t_res->ai_family, t_res->ai_socktype,
1409
t_res->ai_protocol);
1410
if (sock == SOCKET_ERROR)
1412
set_drizzle_extended_error(drizzle, CR_IPSOCK_ERROR, unknown_sqlstate,
1413
ER(CR_IPSOCK_ERROR), socket_errno);
1414
freeaddrinfo(res_lst);
1418
net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
1421
set_drizzle_error(drizzle, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
1423
freeaddrinfo(res_lst);
1427
if (my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
1428
drizzle->options.connect_timeout))
1430
set_drizzle_extended_error(drizzle, CR_CONN_HOST_ERROR, unknown_sqlstate,
1431
ER(CR_CONN_HOST_ERROR), host, socket_errno);
1432
vio_delete(net->vio);
1434
freeaddrinfo(res_lst);
1439
freeaddrinfo(res_lst);
1444
set_drizzle_error(drizzle, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
1448
if (my_net_init(net, net->vio))
1450
vio_delete(net->vio);
1452
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1455
vio_keepalive(net->vio,true);
1457
/* If user set read_timeout, let it override the default */
1458
if (drizzle->options.read_timeout)
1459
my_net_set_read_timeout(net, drizzle->options.read_timeout);
1461
/* If user set write_timeout, let it override the default */
1462
if (drizzle->options.write_timeout)
1463
my_net_set_write_timeout(net, drizzle->options.write_timeout);
1465
if (drizzle->options.max_allowed_packet)
1466
net->max_packet_size= drizzle->options.max_allowed_packet;
1468
/* Get version info */
1469
drizzle->protocol_version= PROTOCOL_VERSION; /* Assume this */
1470
if (drizzle->options.connect_timeout &&
1471
vio_poll_read(net->vio, drizzle->options.connect_timeout))
1473
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1474
ER(CR_SERVER_LOST_EXTENDED),
1475
"waiting for initial communication packet",
1481
Part 1: Connection established, read and parse first packet
1484
if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
1486
if (drizzle->net.last_errno == CR_SERVER_LOST)
1487
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1488
ER(CR_SERVER_LOST_EXTENDED),
1489
"reading initial communication packet",
1493
/* Check if version of protocol matches current one */
1495
drizzle->protocol_version= net->read_pos[0];
1496
if (drizzle->protocol_version != PROTOCOL_VERSION)
1498
set_drizzle_extended_error(drizzle, CR_VERSION_ERROR, unknown_sqlstate,
1499
ER(CR_VERSION_ERROR), drizzle->protocol_version,
1503
end=strend((char*) net->read_pos+1);
1504
drizzle->thread_id=uint4korr(end+1);
1507
Scramble is split into two parts because old clients does not understand
1508
long scrambles; here goes the first part.
1510
strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
1511
end+= SCRAMBLE_LENGTH_323+1;
1513
if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
1514
drizzle->server_capabilities=uint2korr(end);
1515
if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
1517
/* New protocol with 16 bytes to describe server characteristics */
1518
drizzle->server_language=end[2];
1519
drizzle->server_status=uint2korr(end+3);
1522
if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
1523
(char *) net->read_pos))
1524
strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
1525
SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
1527
drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
1529
if (drizzle->options.secure_auth && passwd[0] &&
1530
!(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
1532
set_drizzle_error(drizzle, CR_SECURE_AUTH, unknown_sqlstate);
1536
if (drizzle_init_character_set(drizzle))
1539
/* Save connection information */
1540
if (!my_multi_malloc(MYF(0),
1541
&drizzle->host_info, (uint) strlen(host_info)+1,
1542
&drizzle->host, (uint) strlen(host)+1,
1543
&drizzle->unix_socket,unix_socket ?
1544
(uint) strlen(unix_socket)+1 : (uint) 1,
1545
&drizzle->server_version,
1546
(uint) (end - (char*) net->read_pos),
1548
!(drizzle->user=my_strdup(user,MYF(0))) ||
1549
!(drizzle->passwd=my_strdup(passwd,MYF(0))))
1551
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1554
strcpy(drizzle->host_info,host_info);
1555
strcpy(drizzle->host,host);
1557
strcpy(drizzle->unix_socket,unix_socket);
1559
drizzle->unix_socket=0;
1560
strcpy(drizzle->server_version,(char*) net->read_pos+1);
1564
Part 2: format and send client info to the server for access check
1567
client_flag|=drizzle->options.client_flag;
1568
client_flag|=CLIENT_CAPABILITIES;
1569
if (client_flag & CLIENT_MULTI_STATEMENTS)
1570
client_flag|= CLIENT_MULTI_RESULTS;
1573
client_flag|=CLIENT_CONNECT_WITH_DB;
1575
/* Remove options that server doesn't support */
1576
client_flag= ((client_flag &
1577
~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
1578
(client_flag & drizzle->server_capabilities));
1579
client_flag&= ~CLIENT_COMPRESS;
1581
if (client_flag & CLIENT_PROTOCOL_41)
1583
/* 4.1 server and 4.1 client has a 32 byte option flag */
1584
int4store(buff,client_flag);
1585
int4store(buff+4, net->max_packet_size);
1586
buff[8]= (char) drizzle->charset->number;
1587
memset(buff+9, 0, 32-9);
1592
int2store(buff,client_flag);
1593
int3store(buff+2,net->max_packet_size);
1596
drizzle->client_flag=client_flag;
1598
/* This needs to be changed as it's not useful with big packets */
1599
if (user && user[0])
1600
strncpy(end,user,USERNAME_LENGTH); /* Max user name */
1602
read_user_name((char*) end);
1604
/* We have to handle different version of handshake here */
1605
end= strend(end) + 1;
1609
*end++= SCRAMBLE_LENGTH;
1610
memset(end, 0, SCRAMBLE_LENGTH-1);
1611
memcpy(end, passwd, strlen(passwd));
1612
end+= SCRAMBLE_LENGTH;
1616
*end++= '\0'; /* empty password */
1618
/* Add database if needed */
1619
if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
1621
end= strncpy(end, db, NAME_LEN) + NAME_LEN + 1;
1622
drizzle->db= my_strdup(db,MYF(MY_WME));
1625
/* Write authentication package */
1626
if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
1628
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1629
ER(CR_SERVER_LOST_EXTENDED),
1630
"sending authentication information",
1636
Part 3: Authorization data's been sent. Now server can reply with
1637
OK-packet, or re-request scrambled password.
1640
if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
1642
if (drizzle->net.last_errno == CR_SERVER_LOST)
1643
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1644
ER(CR_SERVER_LOST_EXTENDED),
1645
"reading authorization packet",
1650
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
1654
if (db && drizzle_select_db(drizzle, db))
1656
if (drizzle->net.last_errno == CR_SERVER_LOST)
1657
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1658
ER(CR_SERVER_LOST_EXTENDED),
1659
"Setting intital database",
1664
if (drizzle->options.init_commands)
1666
DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
1667
char **ptr= (char**)init_commands->buffer;
1668
char **end_command= ptr + init_commands->elements;
1670
my_bool reconnect=drizzle->reconnect;
1671
drizzle->reconnect=0;
1673
for (; ptr < end_command; ptr++)
1676
if (drizzle_real_query(drizzle,*ptr, (ulong) strlen(*ptr)))
1678
if (drizzle->fields)
1680
if (!(res= cli_use_result(drizzle)))
1682
drizzle_free_result(res);
1685
drizzle->reconnect=reconnect;
1688
reset_sigpipe(drizzle);
1692
reset_sigpipe(drizzle);
1694
/* Free alloced memory */
1695
end_server(drizzle);
1696
drizzle_close_free(drizzle);
1697
if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
1698
drizzle_close_free_options(drizzle);
1704
my_bool drizzle_reconnect(DRIZZLE *drizzle)
1706
DRIZZLE tmp_drizzle;
1709
if (!drizzle->reconnect ||
1710
(drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
1712
/* Allow reconnect next time */
1713
drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
1714
set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
1717
drizzle_create(&tmp_drizzle);
1718
tmp_drizzle.options= drizzle->options;
1719
tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
1721
if (!drizzle_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
1722
drizzle->db, drizzle->port, drizzle->unix_socket,
1723
drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
1725
drizzle->net.last_errno= tmp_drizzle.net.last_errno;
1726
strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
1727
strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
1730
if (drizzle_set_character_set(&tmp_drizzle, drizzle->charset->csname))
1732
memset((char*) &tmp_drizzle.options, 0, sizeof(tmp_drizzle.options));
1733
drizzle_close(&tmp_drizzle);
1734
drizzle->net.last_errno= tmp_drizzle.net.last_errno;
1735
strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
1736
strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
1740
tmp_drizzle.reconnect= 1;
1741
tmp_drizzle.free_me= drizzle->free_me;
1743
/* Don't free options as these are now used in tmp_drizzle */
1744
memset((char*) &drizzle->options, 0, sizeof(drizzle->options));
1746
drizzle_close(drizzle);
1747
*drizzle=tmp_drizzle;
1748
net_clear(&drizzle->net, 1);
1749
drizzle->affected_rows= ~(uint64_t) 0;
1754
/**************************************************************************
1755
Set current database
1756
**************************************************************************/
1759
drizzle_select_db(DRIZZLE *drizzle, const char *db)
1763
if ((error=simple_command(drizzle,COM_INIT_DB, (const uchar*) db,
1764
(ulong) strlen(db),0)))
1766
my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
1767
drizzle->db=my_strdup(db,MYF(MY_WME));
1772
/*************************************************************************
1773
Send a QUIT to the server and close the connection
1774
If handle is alloced by DRIZZLE connect free it.
1775
*************************************************************************/
1777
static void drizzle_close_free_options(DRIZZLE *drizzle)
1779
my_free(drizzle->options.user,MYF(MY_ALLOW_ZERO_PTR));
1780
my_free(drizzle->options.host,MYF(MY_ALLOW_ZERO_PTR));
1781
my_free(drizzle->options.password,MYF(MY_ALLOW_ZERO_PTR));
1782
my_free(drizzle->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
1783
my_free(drizzle->options.db,MYF(MY_ALLOW_ZERO_PTR));
1784
my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1785
my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1786
my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
1787
my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
1788
my_free(drizzle->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
1789
if (drizzle->options.init_commands)
1791
DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
1792
char **ptr= (char**)init_commands->buffer;
1793
char **end= ptr + init_commands->elements;
1794
for (; ptr<end; ptr++)
1795
my_free(*ptr,MYF(MY_WME));
1796
delete_dynamic(init_commands);
1797
my_free((char*)init_commands,MYF(MY_WME));
1799
memset((char*) &drizzle->options, 0, sizeof(drizzle->options));
1804
static void drizzle_close_free(DRIZZLE *drizzle)
1806
my_free((uchar*) drizzle->host_info,MYF(MY_ALLOW_ZERO_PTR));
1807
my_free(drizzle->user,MYF(MY_ALLOW_ZERO_PTR));
1808
my_free(drizzle->passwd,MYF(MY_ALLOW_ZERO_PTR));
1809
my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
1810
my_free(drizzle->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
1811
drizzle->info_buffer= 0;
1813
/* Clear pointers for better safety */
1814
drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
1818
void STDCALL drizzle_close(DRIZZLE *drizzle)
1820
if (drizzle) /* Some simple safety */
1822
/* If connection is still up, send a QUIT message */
1823
if (drizzle->net.vio != 0)
1825
free_old_query(drizzle);
1826
drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
1827
drizzle->reconnect=0;
1828
simple_command(drizzle,COM_QUIT,(uchar*) 0,0,1);
1829
end_server(drizzle); /* Sets drizzle->net.vio= 0 */
1831
drizzle_close_free_options(drizzle);
1832
drizzle_close_free(drizzle);
1833
if (drizzle->free_me)
1834
my_free((uchar*) drizzle,MYF(0));
1840
static bool cli_read_query_result(DRIZZLE *drizzle)
1844
DRIZZLE_DATA *fields;
1847
if ((length = cli_safe_read(drizzle)) == packet_error)
1849
free_old_query(drizzle); /* Free old result */
1850
#ifdef MYSQL_CLIENT /* Avoid warn of unused labels*/
1853
pos=(uchar*) drizzle->net.read_pos;
1854
if ((field_count= net_field_length(&pos)) == 0)
1856
drizzle->affected_rows= net_field_length_ll(&pos);
1857
drizzle->insert_id= net_field_length_ll(&pos);
1858
if (protocol_41(drizzle))
1860
drizzle->server_status=uint2korr(pos); pos+=2;
1861
drizzle->warning_count=uint2korr(pos); pos+=2;
1863
else if (drizzle->server_capabilities & CLIENT_TRANSACTIONS)
1865
/* DRIZZLE 4.0 protocol */
1866
drizzle->server_status=uint2korr(pos); pos+=2;
1867
drizzle->warning_count= 0;
1869
if (pos < drizzle->net.read_pos+length && net_field_length(&pos))
1870
drizzle->info=(char*) pos;
1874
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
1878
if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES))
1880
set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
1884
error= handle_local_infile(drizzle,(char*) pos);
1885
if ((length= cli_safe_read(drizzle)) == packet_error || error)
1887
goto get_info; /* Get info packet */
1890
if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
1891
drizzle->server_status|= SERVER_STATUS_IN_TRANS;
1893
if (!(fields=cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, protocol_41(drizzle) ? 7:5)))
1895
if (!(drizzle->fields=unpack_fields(fields,&drizzle->field_alloc,
1896
(uint) field_count,0,
1897
drizzle->server_capabilities)))
1899
drizzle->status= DRIZZLE_STATUS_GET_RESULT;
1900
drizzle->field_count= (uint) field_count;
1906
Send the query and return so we can do something else.
1907
Needs to be followed by drizzle_read_query_result() when we want to
1908
finish processing it.
1912
drizzle_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
1914
return(simple_command(drizzle, COM_QUERY, (uchar*) query, length, 1));
1919
drizzle_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
1921
if (drizzle_send_query(drizzle,query,length))
1923
return((int) (*drizzle->methods->read_query_result)(drizzle));
1927
/**************************************************************************
1928
Alloc result struct for buffered results. All rows are read to buffer.
1929
drizzle_data_seek may be used.
1930
**************************************************************************/
1932
DRIZZLE_RES * STDCALL drizzle_store_result(DRIZZLE *drizzle)
1934
DRIZZLE_RES *result;
1936
if (!drizzle->fields)
1938
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
1940
set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
1943
drizzle->status=DRIZZLE_STATUS_READY; /* server is ready */
1944
if (!(result=(DRIZZLE_RES*) my_malloc((uint) (sizeof(DRIZZLE_RES)+
1946
drizzle->field_count),
1947
MYF(MY_WME | MY_ZEROFILL))))
1949
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1952
result->methods= drizzle->methods;
1953
result->eof= 1; /* Marker for buffered */
1954
result->lengths= (uint32_t*) (result+1);
1956
(*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
1958
my_free((uchar*) result,MYF(0));
1961
drizzle->affected_rows= result->row_count= result->data->rows;
1962
result->data_cursor= result->data->data;
1963
result->fields= drizzle->fields;
1964
result->field_alloc= drizzle->field_alloc;
1965
result->field_count= drizzle->field_count;
1966
/* The rest of result members is zeroed in malloc */
1967
drizzle->fields=0; /* fields is now in result */
1968
clear_alloc_root(&drizzle->field_alloc);
1969
/* just in case this was mistakenly called after drizzle_stmt_execute() */
1970
drizzle->unbuffered_fetch_owner= 0;
1971
return(result); /* Data fetched */
1975
/**************************************************************************
1976
Alloc struct for use with unbuffered reads. Data is fetched by domand
1977
when calling to drizzle_fetch_row.
1978
DRIZZLE_DATA_seek is a noop.
1980
No other queries may be specified with the same DRIZZLE handle.
1981
There shouldn't be much processing per row because DRIZZLE server shouldn't
1982
have to wait for the client (and will not wait more than 30 sec/packet).
1983
**************************************************************************/
1985
static DRIZZLE_RES * cli_use_result(DRIZZLE *drizzle)
1987
DRIZZLE_RES *result;
1989
if (!drizzle->fields)
1991
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
1993
set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
1996
if (!(result=(DRIZZLE_RES*) my_malloc(sizeof(*result)+
1997
sizeof(ulong)*drizzle->field_count,
1998
MYF(MY_WME | MY_ZEROFILL))))
2000
result->lengths=(uint32_t*) (result+1);
2001
result->methods= drizzle->methods;
2002
if (!(result->row=(DRIZZLE_ROW)
2003
my_malloc(sizeof(result->row[0])*(drizzle->field_count+1), MYF(MY_WME))))
2004
{ /* Ptrs: to one row */
2005
my_free((uchar*) result,MYF(0));
2008
result->fields= drizzle->fields;
2009
result->field_alloc= drizzle->field_alloc;
2010
result->field_count= drizzle->field_count;
2011
result->current_field=0;
2012
result->handle= drizzle;
2013
result->current_row= 0;
2014
drizzle->fields=0; /* fields is now in result */
2015
clear_alloc_root(&drizzle->field_alloc);
2016
drizzle->status=DRIZZLE_STATUS_USE_RESULT;
2017
drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
2018
return(result); /* Data is read to be fetched */
2022
/**************************************************************************
2023
Return next row of the query results
2024
**************************************************************************/
2027
drizzle_fetch_row(DRIZZLE_RES *res)
2030
{ /* Unbufferred fetch */
2033
DRIZZLE *drizzle= res->handle;
2034
if (drizzle->status != DRIZZLE_STATUS_USE_RESULT)
2036
set_drizzle_error(drizzle,
2037
res->unbuffered_fetch_cancelled ?
2038
CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
2041
else if (!(read_one_row(drizzle, res->field_count, res->row, res->lengths)))
2044
return(res->current_row=res->row);
2047
drizzle->status=DRIZZLE_STATUS_READY;
2049
Reset only if owner points to us: there is a chance that somebody
2050
started new query after drizzle_stmt_close():
2052
if (drizzle->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
2053
drizzle->unbuffered_fetch_owner= 0;
2054
/* Don't clear handle in drizzle_free_result */
2057
return((DRIZZLE_ROW) NULL);
2061
if (!res->data_cursor)
2063
return(res->current_row=(DRIZZLE_ROW) NULL);
2065
tmp = res->data_cursor->data;
2066
res->data_cursor = res->data_cursor->next;
2067
return(res->current_row=tmp);
2072
/**************************************************************************
2073
Get column lengths of the current row
2074
If one uses drizzle_use_result, res->lengths contains the length information,
2075
else the lengths are calculated from the offset between pointers.
2076
**************************************************************************/
2079
drizzle_fetch_lengths(DRIZZLE_RES *res)
2083
if (!(column=res->current_row))
2084
return 0; /* Something is wrong */
2086
(*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
2087
return res->lengths;
2092
drizzle_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
2095
case DRIZZLE_OPT_CONNECT_TIMEOUT:
2096
drizzle->options.connect_timeout= *(uint*) arg;
2098
case DRIZZLE_OPT_READ_TIMEOUT:
2099
drizzle->options.read_timeout= *(uint*) arg;
2101
case DRIZZLE_OPT_WRITE_TIMEOUT:
2102
drizzle->options.write_timeout= *(uint*) arg;
2104
case DRIZZLE_OPT_COMPRESS:
2105
drizzle->options.compress= 1; /* Remember for connect */
2106
drizzle->options.client_flag|= CLIENT_COMPRESS;
2108
case DRIZZLE_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
2109
if (!arg || test(*(uint*) arg))
2110
drizzle->options.client_flag|= CLIENT_LOCAL_FILES;
2112
drizzle->options.client_flag&= ~CLIENT_LOCAL_FILES;
2114
case DRIZZLE_INIT_COMMAND:
2115
add_init_command(&drizzle->options,arg);
2117
case DRIZZLE_READ_DEFAULT_FILE:
2118
my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
2119
drizzle->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
2121
case DRIZZLE_READ_DEFAULT_GROUP:
2122
my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
2123
drizzle->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
2125
case DRIZZLE_SET_CHARSET_DIR:
2126
my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
2127
drizzle->options.charset_dir=my_strdup(arg,MYF(MY_WME));
2129
case DRIZZLE_SET_CHARSET_NAME:
2130
my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
2131
drizzle->options.charset_name=my_strdup(arg,MYF(MY_WME));
2133
case DRIZZLE_OPT_PROTOCOL:
2134
drizzle->options.protocol= *(uint*) arg;
2136
case DRIZZLE_OPT_USE_REMOTE_CONNECTION:
2137
case DRIZZLE_OPT_GUESS_CONNECTION:
2138
drizzle->options.methods_to_use= option;
2140
case DRIZZLE_SET_CLIENT_IP:
2141
drizzle->options.client_ip= my_strdup(arg, MYF(MY_WME));
2143
case DRIZZLE_SECURE_AUTH:
2144
drizzle->options.secure_auth= *(my_bool *) arg;
2146
case DRIZZLE_REPORT_DATA_TRUNCATION:
2147
drizzle->options.report_data_truncation= test(*(my_bool *) arg);
2149
case DRIZZLE_OPT_RECONNECT:
2150
drizzle->reconnect= *(my_bool *) arg;
2152
case DRIZZLE_OPT_SSL_VERIFY_SERVER_CERT:
2153
if (*(my_bool*) arg)
2154
drizzle->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;
2156
drizzle->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
2165
/****************************************************************************
2166
Functions to get information from the DRIZZLE structure
2167
These are functions to make shared libraries more usable.
2168
****************************************************************************/
2171
uint64_t STDCALL drizzle_num_rows(const DRIZZLE_RES *res)
2173
return res->row_count;
2176
unsigned int STDCALL drizzle_num_fields(const DRIZZLE_RES *res)
2178
return res->field_count;
2181
uint STDCALL drizzle_errno(const DRIZZLE *drizzle)
2183
return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno;
2187
const char * STDCALL drizzle_error(const DRIZZLE *drizzle)
2189
return drizzle ? drizzle->net.last_error : drizzle_server_last_error;
2194
Get version number for server in a form easy to test on
2197
drizzle_get_server_version()
2204
We will ensure that a newer server always has a bigger number.
2207
Signed number > 323000
2211
drizzle_get_server_version(const DRIZZLE *drizzle)
2213
uint major, minor, version;
2214
char *pos= drizzle->server_version, *end_pos;
2215
major= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1;
2216
minor= (uint) strtoul(pos, &end_pos, 10); pos=end_pos+1;
2217
version= (uint) strtoul(pos, &end_pos, 10);
2218
return (ulong) major*10000L+(ulong) (minor*100+version);
2223
drizzle_set_character_set function sends SET NAMES cs_name to
2224
the server (which changes character_set_client, character_set_result
2225
and character_set_connection) and updates drizzle->charset so other
2226
functions like drizzle_real_escape will work correctly.
2228
int STDCALL drizzle_set_character_set(DRIZZLE *drizzle, const char *cs_name)
2230
struct charset_info_st *cs;
2231
const char *save_csdir= charsets_dir;
2233
if (drizzle->options.charset_dir)
2234
charsets_dir= drizzle->options.charset_dir;
2236
if (strlen(cs_name) < MY_CS_NAME_SIZE &&
2237
(cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
2239
char buff[MY_CS_NAME_SIZE + 10];
2240
charsets_dir= save_csdir;
2241
/* Skip execution of "SET NAMES" for pre-4.1 servers */
2242
if (drizzle_get_server_version(drizzle) < 40100)
2244
sprintf(buff, "SET NAMES %s", cs_name);
2245
if (!drizzle_real_query(drizzle, buff, strlen(buff)))
2247
drizzle->charset= cs;
2252
char cs_dir_name[FN_REFLEN];
2253
get_charsets_dir(cs_dir_name);
2254
set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
2255
ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
2257
charsets_dir= save_csdir;
2258
return drizzle->net.last_errno;