77
76
#include <sys/un.h>
80
#define SOCKET_ERROR -1
82
#define CONNECT_TIMEOUT 0
84
#include "client_settings.h"
85
#include <drizzled/version.h>
86
#include <libdrizzle/sql_common.h>
89
char *drizzle_unix_port= 0;
90
const char *unknown_sqlstate= "HY000";
91
const char *not_error_sqlstate= "00000";
92
const char *cant_connect_sqlstate= "08001";
94
static bool drizzle_client_init= false;
95
static bool org_my_init_done= false;
97
static void drizzle_close_free_options(DRIZZLE *drizzle);
98
static void drizzle_close_free(DRIZZLE *drizzle);
100
static int wait_for_data(int fd, int32_t timeout);
101
int connect_with_timeout(int fd, const struct sockaddr *name, uint namelen, int32_t 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(). connect_with_timeout() 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
connect_with_timeout() will behave exactly like connect().
115
Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
116
*****************************************************************************/
119
int connect_with_timeout(int fd, const struct sockaddr *name, uint namelen, int32_t timeout)
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! */
147
return wait_for_data(fd, timeout);
152
Wait up to timeout seconds for a connection to be established.
154
We prefer to do this with poll() as there is no limitations with this.
155
If not, we will use select()
158
static int wait_for_data(int fd, int32_t timeout)
164
ufds.events= POLLIN | POLLPRI;
165
if (!(res= poll(&ufds, 1, (int) timeout*1000)))
170
if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)) || (ufds.revents & POLLHUP))
81
#include <drizzled/gettext.h>
82
#include "libdrizzle.h"
176
86
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
177
87
struct passwd *getpwuid(uid_t);
178
88
char* getlogin(void);
181
static void read_user_name(char *name)
184
strcpy(name,"root"); /* allow use of surun */
190
if ((str=getlogin()) == NULL)
192
if ((skr=getpwuid(geteuid())) != NULL)
194
else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
195
!(str=getenv("LOGIN")))
198
strncpy(name,str,USERNAME_LENGTH);
200
(void) cuserid(name);
202
strcpy(name,"UNKNOWN_USER");
210
Set the internal error message to DRIZZLE handler
212
@param drizzle connection handle (client side)
213
@param errcode CR_ error code, passed to ER macro to get
215
@parma sqlstate SQL standard sqlstate
218
void set_drizzle_error(DRIZZLE *drizzle, int errcode, const char *sqlstate)
221
assert(drizzle != 0);
226
net->last_errno= errcode;
227
strcpy(net->last_error, ER(errcode));
228
strcpy(net->sqlstate, sqlstate);
232
drizzle_server_last_errno= errcode;
233
strcpy(drizzle_server_last_error, ER(errcode));
239
Clear possible error state of struct NET
241
@param net clear the state of the argument
244
void net_clear_error(NET *net)
247
net->last_error[0]= '\0';
248
strcpy(net->sqlstate, not_error_sqlstate);
252
Set an error message on the client.
254
@param drizzle connection handle
255
@param errcode CR_* errcode, for client errors
256
@param sqlstate SQL standard sql state, unknown_sqlstate for the
257
majority of client errors.
258
@param format error message template, in sprintf format
259
@param ... variable number of arguments
262
static void set_drizzle_extended_error(DRIZZLE *drizzle, int errcode,
263
const char *sqlstate,
264
const char *format, ...)
268
assert(drizzle != 0);
271
net->last_errno= errcode;
272
va_start(args, format);
273
vsnprintf(net->last_error, sizeof(net->last_error)-1,
276
strcpy(net->sqlstate, sqlstate);
281
92
/*****************************************************************************
282
93
Read a packet from server. Give error message if socket was down
283
94
or packet is an error message
284
95
*****************************************************************************/
286
uint32_t cli_safe_read(DRIZZLE *drizzle)
97
/* I'm not sure if this is even used anymore, but now that libdrizzleclient is
98
server only, this is safe to set here. */
99
extern "C" bool safe_read_error_impl(NET *net);
101
bool safe_read_error_impl(NET *net)
104
return drizzleclient_vio_was_interrupted(net->vio);
109
safe_read_error_hook_func safe_read_error_hook= safe_read_error_impl;
111
uint32_t drizzleclient_cli_safe_read(DRIZZLE *drizzle)
288
113
NET *net= &drizzle->net;
290
init_sigpipe_variables
292
/* Don't give sigpipe errors if the client doesn't want them */
293
set_sigpipe(drizzle);
294
116
if (net->vio != 0)
295
len=my_net_read(net);
296
reset_sigpipe(drizzle);
117
len=drizzleclient_net_read(net);
298
119
if (len == packet_error || len == 0)
300
#ifdef DRIZZLE_SERVER
301
if (net->vio && vio_was_interrupted(net->vio))
302
return (packet_error);
303
#endif /*DRIZZLE_SERVER*/
305
set_drizzle_error(drizzle, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
306
CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
121
if (safe_read_error_hook != NULL)
122
if (safe_read_error_hook(net))
123
return (packet_error);
124
drizzleclient_disconnect(drizzle);
125
drizzleclient_set_error(drizzle, net->last_errno == CR_NET_PACKET_TOO_LARGE ?
126
CR_NET_PACKET_TOO_LARGE : CR_SERVER_LOST,
127
drizzleclient_sqlstate_get_unknown());
307
128
return (packet_error);
309
130
if (net->read_pos[0] == 255)
497
274
*drizzle->unbuffered_fetch_owner= true;
500
free_rows(result->data);
502
free_root(&result->field_alloc,MYF(0));
277
drizzleclient_free_rows(result->data);
278
/* TODO: free result->fields */
504
my_free((uchar*) result->row,MYF(0));
505
my_free((uchar*) result,MYF(0));
509
/****************************************************************************
510
Get options from my.cnf
511
****************************************************************************/
513
static const char *default_options[]=
515
"port","socket","compress","password","pipe", "timeout", "user",
516
"init-command", "host", "database", "return-found-rows",
517
"ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
518
"character-sets-dir", "default-character-set", "interactive-timeout",
519
"connect-timeout", "local-infile", "disable-local-infile",
520
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
521
"multi-results", "multi-statements", "multi-queries", "secure-auth",
522
"report-data-truncation",
526
static TYPELIB option_types={array_elements(default_options)-1,
527
"options",default_options, NULL};
529
const char *sql_protocol_names_lib[] =
530
{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
531
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
532
sql_protocol_names_lib, NULL};
534
static int add_init_command(struct st_drizzle_options *options, const char *cmd)
538
if (!options->init_commands)
540
options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
542
init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
545
if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
546
insert_dynamic(options->init_commands, (uchar*)&tmp))
548
my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
555
void drizzle_read_default_options(struct st_drizzle_options *options,
556
const char *filename,const char *group)
559
char *argv_buff[1],**argv;
560
const char *groups[3];
562
argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
563
groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
565
load_defaults(filename, groups, &argc, &argv);
566
if (argc != 1) /* If some default option */
571
if (option[0][0] == '-' && option[0][1] == '-')
573
char *end=strrchr(*option,'=');
578
*end=0; /* Remove '=' */
580
/* Change all '_' in variable name to '-' */
581
for (end= *option ; *(end= strrchr(end,'_')) ; )
583
switch (find_type(*option+2,&option_types,2)) {
586
options->port=atoi(opt_arg);
591
my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
592
options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
595
case 3: /* compress */
597
options->client_flag|= CLIENT_COMPRESS;
599
case 4: /* password */
602
my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
603
options->password=my_strdup(opt_arg,MYF(MY_WME));
606
case 20: /* connect_timeout */
607
case 6: /* timeout */
609
options->connect_timeout=atoi(opt_arg);
614
my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
615
options->user=my_strdup(opt_arg,MYF(MY_WME));
618
case 8: /* init-command */
619
add_init_command(options,opt_arg);
624
my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
625
options->host=my_strdup(opt_arg,MYF(MY_WME));
628
case 10: /* database */
631
my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
632
options->db=my_strdup(opt_arg,MYF(MY_WME));
635
case 12: /* return-found-rows */
636
options->client_flag|=CLIENT_FOUND_ROWS;
638
case 13: /* Ignore SSL options */
644
case 17: /* charset-lib */
645
my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
646
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
649
my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
650
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
652
case 19: /* Interactive-timeout */
653
options->client_flag|= CLIENT_INTERACTIVE;
656
if (!opt_arg || atoi(opt_arg) != 0)
657
options->client_flag|= CLIENT_LOCAL_FILES;
659
options->client_flag&= ~CLIENT_LOCAL_FILES;
662
options->client_flag&= ~CLIENT_LOCAL_FILES;
664
case 24: /* max-allowed-packet */
666
options->max_allowed_packet= atoi(opt_arg);
668
case 25: /* protocol */
669
if ((options->protocol= find_type(opt_arg,
670
&sql_protocol_typelib,0)) <= 0)
672
fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
676
case 27: /* multi-results */
677
options->client_flag|= CLIENT_MULTI_RESULTS;
679
case 28: /* multi-statements */
680
case 29: /* multi-queries */
681
options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
683
case 30: /* secure-auth */
684
options->secure_auth= true;
686
case 31: /* report-data-truncation */
687
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
700
/**************************************************************************
701
Get column lengths of the current row
702
If one uses drizzle_use_result, res->lengths contains the length information,
703
else the lengths are calculated from the offset between pointers.
704
**************************************************************************/
706
static void cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count)
708
uint32_t *prev_length;
712
prev_length=0; /* Keep gcc happy */
713
for (end=column + field_count + 1 ; column != end ; column++, to++)
720
if (start) /* Found end of prev string */
721
*prev_length= (uint32_t) (*column-start-1);
727
/***************************************************************************
728
Change field rows to field structs
729
***************************************************************************/
732
unpack_fields(DRIZZLE_DATA *data, MEM_ROOT *alloc,uint fields,
736
DRIZZLE_FIELD *field,*result;
737
uint32_t lengths[9]; /* Max of fields */
739
field= result= (DRIZZLE_FIELD*) alloc_root(alloc,
740
(uint) sizeof(*field)*fields);
743
free_rows(data); /* Free old data */
746
memset((char*) field, 0, (uint) sizeof(DRIZZLE_FIELD)*fields);
748
for (row= data->data; row ; row = row->next,field++)
751
/* fields count may be wrong */
752
assert((uint) (field - result) < fields);
753
cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
754
field->catalog= strmake_root(alloc,(char*) row->data[0], lengths[0]);
755
field->db= strmake_root(alloc,(char*) row->data[1], lengths[1]);
756
field->table= strmake_root(alloc,(char*) row->data[2], lengths[2]);
757
field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
758
field->name= strmake_root(alloc,(char*) row->data[4], lengths[4]);
759
field->org_name= strmake_root(alloc,(char*) row->data[5], lengths[5]);
761
field->catalog_length= lengths[0];
762
field->db_length= lengths[1];
763
field->table_length= lengths[2];
764
field->org_table_length= lengths[3];
765
field->name_length= lengths[4];
766
field->org_name_length= lengths[5];
768
/* Unpack fixed length parts */
769
pos= (uchar*) row->data[6];
770
field->charsetnr= uint2korr(pos);
771
field->length= (uint) uint4korr(pos+2);
772
field->type= (enum enum_field_types) pos[6];
773
field->flags= uint2korr(pos+7);
774
field->decimals= (uint) pos[9];
776
if (INTERNAL_NUM_FIELD(field))
777
field->flags|= NUM_FLAG;
778
if (default_value && row->data[7])
780
field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
781
field->def_length= lengths[7];
785
field->max_length= 0;
788
free_rows(data); /* Free old data */
280
free((unsigned char*) result->row);
281
free((unsigned char*) result);
792
288
/* Read all rows (fields or data) from server */
794
DRIZZLE_DATA *cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
290
DRIZZLE_DATA *drizzleclient_cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
797
293
uint32_t pkt_len;
941
/****************************************************************************
942
Init DRIZZLE structure or allocate one
943
****************************************************************************/
946
drizzle_create(DRIZZLE *ptr)
949
if (!drizzle_client_init)
951
drizzle_client_init=true;
952
org_my_init_done=my_init_done;
954
/* Will init threads */
960
drizzle_port = DRIZZLE_PORT;
962
struct servent *serv_ptr;
966
if builder specifically requested a default port, use that
967
(even if it coincides with our factory default).
968
only if they didn't do we check /etc/services (and, failing
969
on that, fall back to the factory default of 4427).
970
either default can be overridden by the environment variable
971
DRIZZLE_TCP_PORT, which in turn can be overridden with command
975
#if DRIZZLE_PORT_DEFAULT == 0
976
if ((serv_ptr = getservbyname("drizzle", "tcp")))
977
drizzle_port = (uint) ntohs((ushort) serv_ptr->s_port);
979
if ((env = getenv("DRIZZLE_TCP_PORT")))
980
drizzle_port =(uint) atoi(env);
984
(void) signal(SIGPIPE, SIG_IGN);
988
/* Init if new thread */
989
if (my_thread_init())
994
ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
998
set_drizzle_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
1001
memset(ptr, 0, sizeof(DRIZZLE));
1006
memset(ptr, 0, sizeof(DRIZZLE));
1009
ptr->options.connect_timeout= CONNECT_TIMEOUT;
1010
ptr->charset=default_client_charset_info;
1011
strcpy(ptr->net.sqlstate, not_error_sqlstate);
1014
Only enable LOAD DATA INFILE by default if configured with
1015
--enable-local-infile
1018
#if defined(ENABLED_LOCAL_INFILE) && !defined(DRIZZLE_SERVER)
1019
ptr->options.client_flag|= CLIENT_LOCAL_FILES;
1022
ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION;
1023
ptr->options.report_data_truncation= true; /* default */
1026
By default we don't reconnect because it could silently corrupt data (after
1027
reconnection you potentially lose table locks, user variables, session
1028
variables (transactions but they are specifically dealt with in
1029
drizzle_reconnect()).
1030
This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
1031
How this change impacts existing apps:
1032
- existing apps which relyed on the default will see a behaviour change;
1033
they will have to set reconnect=1 after drizzle_connect().
1034
- existing apps which explicitely asked for reconnection (the only way they
1035
could do it was by setting drizzle.reconnect to 1 after drizzle_connect())
1036
will not see a behaviour change.
1037
- existing apps which explicitely asked for no reconnection
1038
(drizzle.reconnect=0) will not see a behaviour change.
1047
Free all memory and resources used by the client library
1050
When calling this there should not be any other threads using
1053
To make things simpler when used with windows dll's (which calls this
1054
function automaticly), it's safe to call this function multiple times.
1058
void drizzle_server_end()
1060
if (!drizzle_client_init)
1065
/* If library called my_init(), free memory allocated by it */
1066
if (!org_my_init_done)
1073
drizzle_thread_end();
1076
drizzle_client_init= org_my_init_done= 0;
1077
#ifdef EMBEDDED_SERVER
1080
fclose(stderror_file);
1088
Fill in SSL part of DRIZZLE structure and set 'use_ssl' flag.
1089
NB! Errors are not reported until you do drizzle_connect.
1092
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
1095
Note that the drizzle argument must be initialized with drizzle_init()
1096
before calling drizzle_connect !
1099
static bool cli_read_query_result(DRIZZLE *drizzle);
1100
static DRIZZLE_RES *cli_use_result(DRIZZLE *drizzle);
1102
static DRIZZLE_METHODS client_methods=
1104
cli_read_query_result, /* read_query_result */
1105
cli_advanced_command, /* advanced_command */
1106
cli_read_rows, /* read_rows */
1107
cli_use_result, /* use_result */
1108
cli_fetch_lengths, /* fetch_lengths */
1109
cli_flush_use_result, /* flush_use_result */
1110
#ifndef DRIZZLE_SERVER
1111
cli_list_fields, /* list_fields */
1112
cli_unbuffered_fetch, /* unbuffered_fetch */
1113
cli_read_statistics, /* read_statistics */
1114
cli_read_query_result, /* next_result */
1115
cli_read_change_user_result, /* read_change_user_result */
1122
int drizzle_init_character_set(DRIZZLE *drizzle)
1124
const char *default_collation_name;
1126
/* Set character set */
1127
if (!drizzle->options.charset_name)
1129
default_collation_name= DRIZZLE_DEFAULT_COLLATION_NAME;
1130
if (!(drizzle->options.charset_name=
1131
my_strdup(DRIZZLE_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
1135
default_collation_name= NULL;
1138
const char *save= charsets_dir;
1139
if (drizzle->options.charset_dir)
1140
charsets_dir=drizzle->options.charset_dir;
1141
drizzle->charset=get_charset_by_csname(drizzle->options.charset_name,
1142
MY_CS_PRIMARY, MYF(MY_WME));
1143
if (drizzle->charset && default_collation_name)
1145
const CHARSET_INFO *collation;
1147
get_charset_by_name(default_collation_name, MYF(MY_WME))))
1149
if (!my_charset_same(drizzle->charset, collation))
1151
my_printf_error(ER_UNKNOWN_ERROR,
1152
"COLLATION %s is not valid for CHARACTER SET %s",
1154
default_collation_name, drizzle->options.charset_name);
1155
drizzle->charset= NULL;
1159
drizzle->charset= collation;
1163
drizzle->charset= NULL;
1168
if (!drizzle->charset)
1170
if (drizzle->options.charset_dir)
1171
set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
1172
ER(CR_CANT_READ_CHARSET),
1173
drizzle->options.charset_name,
1174
drizzle->options.charset_dir);
1177
char cs_dir_name[FN_REFLEN];
1178
get_charsets_dir(cs_dir_name);
1179
set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
1180
ER(CR_CANT_READ_CHARSET),
1181
drizzle->options.charset_name,
1192
CLI_DRIZZLE_CONNECT(DRIZZLE *drizzle,const char *host, const char *user,
1193
const char *passwd, const char *db,
1194
uint32_t port, const char *unix_socket, uint32_t client_flag)
1196
char buff[NAME_LEN+USERNAME_LENGTH+100];
1197
char *end,*host_info=NULL;
1198
uint32_t pkt_length;
1199
NET *net= &drizzle->net;
1200
init_sigpipe_variables
1202
/* Don't give sigpipe errors if the client doesn't want them */
1203
set_sigpipe(drizzle);
1204
drizzle->methods= &client_methods;
1205
net->vio = 0; /* If something goes wrong */
1206
drizzle->client_flag=0; /* For handshake */
1208
/* use default options */
1209
if (drizzle->options.my_cnf_file || drizzle->options.my_cnf_group)
1211
drizzle_read_default_options(&drizzle->options,
1212
(drizzle->options.my_cnf_file ?
1213
drizzle->options.my_cnf_file : "my"),
1214
drizzle->options.my_cnf_group);
1215
my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1216
my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1217
drizzle->options.my_cnf_file=drizzle->options.my_cnf_group=0;
1220
/* Some empty-string-tests are done because of ODBC */
1221
if (!host || !host[0])
1222
host=drizzle->options.host;
1223
if (!user || !user[0])
1225
user=drizzle->options.user;
1231
passwd=drizzle->options.password;
1236
db=drizzle->options.db;
1238
port=drizzle->options.port;
1240
unix_socket=drizzle->options.unix_socket;
1242
drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
1245
Part 0: Grab a socket and connect it to the server
1248
(!drizzle->options.protocol ||
1249
drizzle->options.protocol == DRIZZLE_PROTOCOL_TCP))
1251
struct addrinfo *res_lst, hints, *t_res;
1253
char port_buf[NI_MAXSERV];
1255
unix_socket=0; /* This is not used */
1263
snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
1265
memset(&hints, 0, sizeof(hints));
1266
hints.ai_socktype= SOCK_STREAM;
1268
snprintf(port_buf, NI_MAXSERV, "%d", port);
1269
gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
1273
set_drizzle_extended_error(drizzle, CR_UNKNOWN_HOST, unknown_sqlstate,
1274
ER(CR_UNKNOWN_HOST), host, errno);
1279
for (t_res= res_lst; t_res != NULL; t_res= t_res->ai_next)
1281
int sock= socket(t_res->ai_family, t_res->ai_socktype,
1282
t_res->ai_protocol);
1283
if (sock == SOCKET_ERROR)
1286
net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
1293
if (connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
1295
vio_delete(net->vio);
1302
freeaddrinfo(res_lst);
1307
set_drizzle_extended_error(drizzle, CR_CONN_HOST_ERROR, unknown_sqlstate,
1308
ER(CR_CONN_HOST_ERROR), host, socket_errno);
1312
if (my_net_init(net, net->vio))
1314
vio_delete(net->vio);
1316
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1319
vio_keepalive(net->vio,true);
1321
/* If user set read_timeout, let it override the default */
1322
if (drizzle->options.read_timeout)
1323
my_net_set_read_timeout(net, drizzle->options.read_timeout);
1325
/* If user set write_timeout, let it override the default */
1326
if (drizzle->options.write_timeout)
1327
my_net_set_write_timeout(net, drizzle->options.write_timeout);
1329
if (drizzle->options.max_allowed_packet)
1330
net->max_packet_size= drizzle->options.max_allowed_packet;
1332
/* Get version info */
1333
drizzle->protocol_version= PROTOCOL_VERSION; /* Assume this */
1334
if (drizzle->options.connect_timeout &&
1335
vio_poll_read(net->vio, drizzle->options.connect_timeout))
1337
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1338
ER(CR_SERVER_LOST_EXTENDED),
1339
"waiting for initial communication packet",
1345
Part 1: Connection established, read and parse first packet
1348
if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
1350
if (drizzle->net.last_errno == CR_SERVER_LOST)
1351
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1352
ER(CR_SERVER_LOST_EXTENDED),
1353
"reading initial communication packet",
1357
/* Check if version of protocol matches current one */
1359
drizzle->protocol_version= net->read_pos[0];
1360
if (drizzle->protocol_version != PROTOCOL_VERSION)
1362
set_drizzle_extended_error(drizzle, CR_VERSION_ERROR, unknown_sqlstate,
1363
ER(CR_VERSION_ERROR), drizzle->protocol_version,
1367
end=strend((char*) net->read_pos+1);
1368
drizzle->thread_id=uint4korr(end+1);
1371
Scramble is split into two parts because old clients does not understand
1372
long scrambles; here goes the first part.
1374
strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
1375
end+= SCRAMBLE_LENGTH_323+1;
1377
if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
1378
drizzle->server_capabilities=uint2korr(end);
1379
if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
1381
/* New protocol with 16 bytes to describe server characteristics */
1382
drizzle->server_language=end[2];
1383
drizzle->server_status=uint2korr(end+3);
1386
if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
1387
(char *) net->read_pos))
1388
strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
1389
SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
1391
drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
1393
if (drizzle->options.secure_auth && passwd[0] &&
1394
!(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
1396
set_drizzle_error(drizzle, CR_SECURE_AUTH, unknown_sqlstate);
1400
if (drizzle_init_character_set(drizzle))
1403
/* Save connection information */
1404
if (!my_multi_malloc(MYF(0),
1405
&drizzle->host_info, (uint) strlen(host_info)+1,
1406
&drizzle->host, (uint) strlen(host)+1,
1407
&drizzle->unix_socket,unix_socket ?
1408
(uint) strlen(unix_socket)+1 : (uint) 1,
1409
&drizzle->server_version,
1410
(uint) (end - (char*) net->read_pos),
1412
!(drizzle->user=my_strdup(user,MYF(0))) ||
1413
!(drizzle->passwd=my_strdup(passwd,MYF(0))))
1415
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1418
strcpy(drizzle->host_info,host_info);
1419
strcpy(drizzle->host,host);
1421
strcpy(drizzle->unix_socket,unix_socket);
1423
drizzle->unix_socket=0;
1424
strcpy(drizzle->server_version,(char*) net->read_pos+1);
1428
Part 2: format and send client info to the server for access check
1431
client_flag|=drizzle->options.client_flag;
1432
client_flag|=CLIENT_CAPABILITIES;
1433
if (client_flag & CLIENT_MULTI_STATEMENTS)
1434
client_flag|= CLIENT_MULTI_RESULTS;
1437
client_flag|=CLIENT_CONNECT_WITH_DB;
1439
/* Remove options that server doesn't support */
1440
client_flag= ((client_flag &
1441
~(CLIENT_COMPRESS | CLIENT_SSL)) |
1442
(client_flag & drizzle->server_capabilities));
1443
client_flag&= ~CLIENT_COMPRESS;
1445
int4store(buff, client_flag);
1446
int4store(buff+4, net->max_packet_size);
1447
buff[8]= (char) drizzle->charset->number;
1448
memset(buff+9, 0, 32-9);
1451
drizzle->client_flag=client_flag;
1453
/* This needs to be changed as it's not useful with big packets */
1454
if (user && user[0])
1455
strncpy(end,user,USERNAME_LENGTH); /* Max user name */
1457
read_user_name((char*) end);
1459
/* We have to handle different version of handshake here */
1460
end= strend(end) + 1;
1464
*end++= SCRAMBLE_LENGTH;
1465
memset(end, 0, SCRAMBLE_LENGTH-1);
1466
memcpy(end, passwd, strlen(passwd));
1467
end+= SCRAMBLE_LENGTH;
1471
*end++= '\0'; /* empty password */
1473
/* Add database if needed */
1474
if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
1476
end= strncpy(end, db, NAME_LEN) + NAME_LEN + 1;
1477
drizzle->db= my_strdup(db,MYF(MY_WME));
1480
/* Write authentication package */
1481
if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
1483
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1484
ER(CR_SERVER_LOST_EXTENDED),
1485
"sending authentication information",
1491
Part 3: Authorization data's been sent. Now server can reply with
1492
OK-packet, or re-request scrambled password.
1495
if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
1497
if (drizzle->net.last_errno == CR_SERVER_LOST)
1498
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1499
ER(CR_SERVER_LOST_EXTENDED),
1500
"reading authorization packet",
1505
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
1509
if (db && drizzle_select_db(drizzle, db))
1511
if (drizzle->net.last_errno == CR_SERVER_LOST)
1512
set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1513
ER(CR_SERVER_LOST_EXTENDED),
1514
"Setting intital database",
1519
if (drizzle->options.init_commands)
1521
DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
1522
char **ptr= (char**)init_commands->buffer;
1523
char **end_command= ptr + init_commands->elements;
1525
bool reconnect=drizzle->reconnect;
1526
drizzle->reconnect=0;
1528
for (; ptr < end_command; ptr++)
1531
if (drizzle_real_query(drizzle,*ptr, (uint32_t) strlen(*ptr)))
1533
if (drizzle->fields)
1535
if (!(res= cli_use_result(drizzle)))
1537
drizzle_free_result(res);
1540
drizzle->reconnect=reconnect;
1543
reset_sigpipe(drizzle);
1547
reset_sigpipe(drizzle);
1549
/* Free alloced memory */
1550
end_server(drizzle);
1551
drizzle_close_free(drizzle);
1552
if (!(((uint32_t) client_flag) & CLIENT_REMEMBER_OPTIONS))
1553
drizzle_close_free_options(drizzle);
1559
bool drizzle_reconnect(DRIZZLE *drizzle)
1561
DRIZZLE tmp_drizzle;
1564
if (!drizzle->reconnect ||
1565
(drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
1567
/* Allow reconnect next time */
1568
drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
1569
set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
1572
drizzle_create(&tmp_drizzle);
1573
tmp_drizzle.options= drizzle->options;
1574
tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
1576
if (!drizzle_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
1577
drizzle->db, drizzle->port, drizzle->unix_socket,
1578
drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
1580
drizzle->net.last_errno= tmp_drizzle.net.last_errno;
1581
strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
1582
strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
1585
if (drizzle_set_character_set(&tmp_drizzle, drizzle->charset->csname))
1587
memset(&tmp_drizzle.options, 0, sizeof(tmp_drizzle.options));
1588
drizzle_close(&tmp_drizzle);
1589
drizzle->net.last_errno= tmp_drizzle.net.last_errno;
1590
strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
1591
strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
1595
tmp_drizzle.reconnect= 1;
1596
tmp_drizzle.free_me= drizzle->free_me;
1598
/* Don't free options as these are now used in tmp_drizzle */
1599
memset(&drizzle->options, 0, sizeof(drizzle->options));
1601
drizzle_close(drizzle);
1602
*drizzle=tmp_drizzle;
1603
net_clear(&drizzle->net, 1);
1604
drizzle->affected_rows= ~(uint64_t) 0;
1609
/**************************************************************************
1610
Set current database
1611
**************************************************************************/
1614
drizzle_select_db(DRIZZLE *drizzle, const char *db)
1618
if ((error=simple_command(drizzle,COM_INIT_DB, (const uchar*) db,
1619
(uint32_t) strlen(db),0)))
1621
my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
1622
drizzle->db=my_strdup(db,MYF(MY_WME));
1627
/*************************************************************************
1628
Send a QUIT to the server and close the connection
1629
If handle is alloced by DRIZZLE connect free it.
1630
*************************************************************************/
1632
static void drizzle_close_free_options(DRIZZLE *drizzle)
1634
my_free(drizzle->options.user,MYF(MY_ALLOW_ZERO_PTR));
1635
my_free(drizzle->options.host,MYF(MY_ALLOW_ZERO_PTR));
1636
my_free(drizzle->options.password,MYF(MY_ALLOW_ZERO_PTR));
1637
my_free(drizzle->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
1638
my_free(drizzle->options.db,MYF(MY_ALLOW_ZERO_PTR));
1639
my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1640
my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1641
my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
1642
my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
1643
my_free(drizzle->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
1644
if (drizzle->options.init_commands)
1646
DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
1647
char **ptr= (char**)init_commands->buffer;
1648
char **end= ptr + init_commands->elements;
1649
for (; ptr<end; ptr++)
1650
my_free(*ptr,MYF(MY_WME));
1651
delete_dynamic(init_commands);
1652
my_free((char*)init_commands,MYF(MY_WME));
1654
memset(&drizzle->options, 0, sizeof(drizzle->options));
1659
static void drizzle_close_free(DRIZZLE *drizzle)
1661
my_free((uchar*) drizzle->host_info,MYF(MY_ALLOW_ZERO_PTR));
1662
my_free(drizzle->user,MYF(MY_ALLOW_ZERO_PTR));
1663
my_free(drizzle->passwd,MYF(MY_ALLOW_ZERO_PTR));
1664
my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
1665
my_free(drizzle->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
1666
drizzle->info_buffer= 0;
1668
/* Clear pointers for better safety */
1669
drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
1673
void drizzle_close(DRIZZLE *drizzle)
1675
if (drizzle) /* Some simple safety */
1677
/* If connection is still up, send a QUIT message */
1678
if (drizzle->net.vio != 0)
1680
free_old_query(drizzle);
1681
drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
1682
drizzle->reconnect=0;
1683
simple_command(drizzle,COM_QUIT,(uchar*) 0,0,1);
1684
end_server(drizzle); /* Sets drizzle->net.vio= 0 */
1686
drizzle_close_free_options(drizzle);
1687
drizzle_close_free(drizzle);
1688
if (drizzle->free_me)
1689
my_free((uchar*) drizzle,MYF(0));
1695
static bool cli_read_query_result(DRIZZLE *drizzle)
1698
uint32_t field_count;
1699
DRIZZLE_DATA *fields;
1702
if ((length = cli_safe_read(drizzle)) == packet_error)
1704
free_old_query(drizzle); /* Free old result */
1705
#ifdef DRIZZLE_CLIENT /* Avoid warn of unused labels*/
1708
pos=(uchar*) drizzle->net.read_pos;
1709
if ((field_count= net_field_length(&pos)) == 0)
1711
drizzle->affected_rows= net_field_length_ll(&pos);
1712
drizzle->insert_id= net_field_length_ll(&pos);
1714
drizzle->server_status= uint2korr(pos); pos+=2;
1715
drizzle->warning_count= uint2korr(pos); pos+=2;
1717
if (pos < drizzle->net.read_pos+length && net_field_length(&pos))
1718
drizzle->info=(char*) pos;
1721
#ifdef DRIZZLE_CLIENT
1722
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
1726
if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES))
1728
set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
1732
error= handle_local_infile(drizzle,(char*) pos);
1733
if ((length= cli_safe_read(drizzle)) == packet_error || error)
1735
goto get_info; /* Get info packet */
1738
if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
1739
drizzle->server_status|= SERVER_STATUS_IN_TRANS;
1741
if (!(fields=cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, 7)))
1743
if (!(drizzle->fields= unpack_fields(fields,&drizzle->field_alloc,
1744
(uint) field_count, 0)))
1746
drizzle->status= DRIZZLE_STATUS_GET_RESULT;
1747
drizzle->field_count= (uint) field_count;
1753
Send the query and return so we can do something else.
1754
Needs to be followed by drizzle_read_query_result() when we want to
1755
finish processing it.
1759
drizzle_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
1761
return(simple_command(drizzle, COM_QUERY, (uchar*) query, length, 1));
1766
drizzle_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
1768
if (drizzle_send_query(drizzle,query,length))
1770
return((int) (*drizzle->methods->read_query_result)(drizzle));
1774
/**************************************************************************
1775
Alloc result struct for buffered results. All rows are read to buffer.
1776
drizzle_data_seek may be used.
1777
**************************************************************************/
1779
DRIZZLE_RES * drizzle_store_result(DRIZZLE *drizzle)
1781
DRIZZLE_RES *result;
1783
if (!drizzle->fields)
1785
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
1787
set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
1790
drizzle->status=DRIZZLE_STATUS_READY; /* server is ready */
1791
if (!(result=(DRIZZLE_RES*) my_malloc((uint) (sizeof(DRIZZLE_RES)+
1793
drizzle->field_count),
1794
MYF(MY_WME | MY_ZEROFILL))))
1796
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1799
result->methods= drizzle->methods;
1800
result->eof= 1; /* Marker for buffered */
1801
result->lengths= (uint32_t*) (result+1);
1803
(*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
1805
my_free((uchar*) result,MYF(0));
1808
drizzle->affected_rows= result->row_count= result->data->rows;
1809
result->data_cursor= result->data->data;
1810
result->fields= drizzle->fields;
1811
result->field_alloc= drizzle->field_alloc;
1812
result->field_count= drizzle->field_count;
1813
/* The rest of result members is zeroed in malloc */
1814
drizzle->fields=0; /* fields is now in result */
1815
clear_alloc_root(&drizzle->field_alloc);
1816
/* just in case this was mistakenly called after drizzle_stmt_execute() */
1817
drizzle->unbuffered_fetch_owner= 0;
1818
return(result); /* Data fetched */
1822
/**************************************************************************
1823
Alloc struct for use with unbuffered reads. Data is fetched by domand
1824
when calling to drizzle_fetch_row.
1825
DRIZZLE_DATA_seek is a noop.
1827
No other queries may be specified with the same DRIZZLE handle.
1828
There shouldn't be much processing per row because DRIZZLE server shouldn't
1829
have to wait for the client (and will not wait more than 30 sec/packet).
1830
**************************************************************************/
1832
static DRIZZLE_RES * cli_use_result(DRIZZLE *drizzle)
1834
DRIZZLE_RES *result;
1836
if (!drizzle->fields)
1838
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
1840
set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
1843
if (!(result=(DRIZZLE_RES*) my_malloc(sizeof(*result)+
1844
sizeof(uint32_t)*drizzle->field_count,
1845
MYF(MY_WME | MY_ZEROFILL))))
1847
result->lengths=(uint32_t*) (result+1);
1848
result->methods= drizzle->methods;
1849
if (!(result->row=(DRIZZLE_ROW)
1850
my_malloc(sizeof(result->row[0])*(drizzle->field_count+1), MYF(MY_WME))))
1851
{ /* Ptrs: to one row */
1852
my_free((uchar*) result,MYF(0));
1855
result->fields= drizzle->fields;
1856
result->field_alloc= drizzle->field_alloc;
1857
result->field_count= drizzle->field_count;
1858
result->current_field=0;
1859
result->handle= drizzle;
1860
result->current_row= 0;
1861
drizzle->fields=0; /* fields is now in result */
1862
clear_alloc_root(&drizzle->field_alloc);
1863
drizzle->status=DRIZZLE_STATUS_USE_RESULT;
1864
drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
1865
return(result); /* Data is read to be fetched */
1869
435
/**************************************************************************
1870
436
Return next row of the query results
1871
437
**************************************************************************/
1874
drizzle_fetch_row(DRIZZLE_RES *res)
440
drizzleclient_fetch_row(DRIZZLE_RES *res)
1877
443
{ /* Unbufferred fetch */