1
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems, Inc.
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
21
This file is included by both libdrizzle.c (the DRIZZLE client C API)
22
and the drizzled server to connect to another DRIZZLE server.
24
The differences for the two cases are:
26
- Things that only works for the client:
27
- Trying to automaticly determinate user name if not supplied to
29
- Support for reading local file with LOAD DATA LOCAL
30
- SHARED memory handling
33
- Things that only works for the server
34
- Alarm handling on connect
36
In all other cases, the code should be idential for the client and
42
#include <libdrizzle/libdrizzle.h>
43
#include <libdrizzle/net_serv.h>
44
#include "libdrizzle_priv.h"
45
#include <libdrizzle/pack.h>
48
#include <sys/ioctl.h>
52
/* Remove client convenience wrappers */
53
#undef max_allowed_packet
54
#undef net_buffer_length
56
#include <libdrizzle/errmsg.h>
57
#include <vio/violite.h>
66
#include <sys/socket.h>
67
#include <netinet/in.h>
68
#include <arpa/inet.h>
73
#ifdef HAVE_SYS_SELECT_H
74
#include <sys/select.h>
82
#include <drizzled/gettext.h>
83
#include "local_infile.h"
92
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
93
struct passwd *getpwuid(uid_t);
99
/*****************************************************************************
100
Read a packet from server. Give error message if socket was down
101
or packet is an error message
102
*****************************************************************************/
104
uint32_t cli_safe_read(DRIZZLE *drizzle)
106
NET *net= &drizzle->net;
110
len=my_net_read(net);
112
if (len == packet_error || len == 0)
114
#ifdef DRIZZLE_SERVER
115
if (net->vio && vio_was_interrupted(net->vio))
116
return (packet_error);
117
#endif /*DRIZZLE_SERVER*/
118
drizzle_disconnect(drizzle);
119
drizzle_set_error(drizzle, net->last_errno == CR_NET_PACKET_TOO_LARGE ?
120
CR_NET_PACKET_TOO_LARGE : CR_SERVER_LOST,
121
sqlstate_get_unknown());
122
return (packet_error);
124
if (net->read_pos[0] == 255)
128
char *pos=(char*) net->read_pos+1;
129
net->last_errno=uint2korr(pos);
134
strncpy(net->sqlstate, pos+1, SQLSTATE_LENGTH);
135
pos+= SQLSTATE_LENGTH+1;
140
The SQL state hasn't been received -- it should be reset to HY000
141
(unknown error sql state).
144
strcpy(net->sqlstate, sqlstate_get_unknown());
147
strncpy(net->last_error,(char*) pos, min((uint32_t) len,
148
(uint32_t) sizeof(net->last_error)-1));
151
drizzle_set_error(drizzle, CR_UNKNOWN_ERROR, sqlstate_get_unknown());
153
Cover a protocol design error: error packet does not
154
contain the server status. Therefore, the client has no way
155
to find out whether there are more result sets of
156
a multiple-result-set statement pending. Luckily, in 5.0 an
157
error always aborts execution of a statement, wherever it is
158
a multi-statement or a stored procedure, so it should be
159
safe to unconditionally turn off the flag here.
161
drizzle->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
163
return(packet_error);
169
cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
170
const unsigned char *header, uint32_t header_length,
171
const unsigned char *arg, uint32_t arg_length, bool skip_check)
173
NET *net= &drizzle->net;
175
bool stmt_skip= false;
177
if (drizzle->net.vio == 0)
178
{ /* Do reconnect if possible */
179
if (drizzle_reconnect(drizzle) || stmt_skip)
182
if (drizzle->status != DRIZZLE_STATUS_READY ||
183
drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
185
drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC,
186
sqlstate_get_unknown());
190
net_clear_error(net);
192
drizzle->affected_rows= ~(uint64_t) 0;
194
We don't want to clear the protocol buffer on COM_QUIT, because if
195
the previous command was a shutdown command, we may have the
196
response for the COM_QUIT already in the communication buffer
198
net_clear(&drizzle->net, (command != COM_QUIT));
200
if (net_write_command(net,(unsigned char) command, header, header_length,
203
if (net->last_errno == CR_NET_PACKET_TOO_LARGE)
205
drizzle_set_error(drizzle, CR_NET_PACKET_TOO_LARGE, sqlstate_get_unknown());
208
drizzle_disconnect(drizzle);
209
if (drizzle_reconnect(drizzle) || stmt_skip)
211
if (net_write_command(net,(unsigned char) command, header, header_length,
214
drizzle_set_error(drizzle, CR_SERVER_GONE_ERROR, sqlstate_get_unknown());
220
result= ((drizzle->packet_length=cli_safe_read(drizzle)) == packet_error ?
226
void free_old_query(DRIZZLE *drizzle)
230
/* TODO - we need to de-alloc field storage */
231
free(drizzle->fields->catalog);
232
free(drizzle->fields->db);
233
free(drizzle->fields->table);
234
free(drizzle->fields->org_table);
235
free(drizzle->fields->name);
236
free(drizzle->fields->org_name);
237
free(drizzle->fields->def);
238
free(drizzle->fields);
241
/* init_alloc_root(&drizzle->field_alloc,8192,0); */ /* Assume rowlength < 8192 */
243
drizzle->field_count= 0; /* For API */
244
drizzle->warning_count= 0;
254
drizzle_free_result(DRIZZLE_RES *result)
258
DRIZZLE *drizzle= result->handle;
261
if (drizzle->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
262
drizzle->unbuffered_fetch_owner= 0;
263
if (drizzle->status == DRIZZLE_STATUS_USE_RESULT)
265
(*drizzle->methods->flush_use_result)(drizzle);
266
drizzle->status=DRIZZLE_STATUS_READY;
267
if (drizzle->unbuffered_fetch_owner)
268
*drizzle->unbuffered_fetch_owner= true;
271
free_rows(result->data);
272
/* TODO: free result->fields */
274
free((unsigned char*) result->row);
275
free((unsigned char*) result);
282
/* Read all rows (fields or data) from server */
284
DRIZZLE_DATA *cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
291
DRIZZLE_DATA *result;
292
DRIZZLE_ROWS **prev_ptr,*cur;
293
NET *net = &drizzle->net;
295
if ((pkt_len= cli_safe_read(drizzle)) == packet_error)
297
if (!(result=(DRIZZLE_DATA*) malloc(sizeof(DRIZZLE_DATA))))
299
drizzle_set_error(drizzle, CR_OUT_OF_MEMORY,
300
sqlstate_get_unknown());
303
memset(result, 0, sizeof(DRIZZLE_DATA));
304
prev_ptr= &result->data;
306
result->fields=fields;
309
The last EOF packet is either a 254 (0xFE) character followed by 1-7 status bytes.
311
This doesn't conflict with normal usage of 254 which stands for a
312
string where the length of the string is 8 bytes. (see net_field_length())
315
while (*(cp=net->read_pos) != DRIZZLE_PROTOCOL_NO_MORE_DATA || pkt_len >= 8)
318
if (!(cur= (DRIZZLE_ROWS*) malloc(sizeof(DRIZZLE_ROWS))) ||
319
!(cur->data= ((DRIZZLE_ROW) malloc((fields+1)*sizeof(char *)+pkt_len))))
322
drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
326
prev_ptr= &cur->next;
327
to= (char*) (cur->data+fields+1);
329
for (field=0 ; field < fields ; field++)
331
if ((len= net_field_length(&cp)) == NULL_LENGTH)
333
cur->data[field] = 0;
337
cur->data[field] = to;
338
if (len > (uint32_t) (end_to - to))
341
drizzle_set_error(drizzle, CR_MALFORMED_PACKET,
342
sqlstate_get_unknown());
351
if (DRIZZLE_FIELDs[field].max_length < len)
352
DRIZZLE_FIELDs[field].max_length=len;
356
cur->data[field]=to; /* End of last field */
357
if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
363
*prev_ptr=0; /* last pointer is null */
364
if (pkt_len > 1) /* DRIZZLE 4.1 protocol */
366
drizzle->warning_count= uint2korr(cp+1);
367
drizzle->server_status= uint2korr(cp+3);
373
Read one row. Uses packet buffer as storage for fields.
374
When next packet is read, the previous field values are destroyed
379
read_one_row(DRIZZLE *drizzle, uint32_t fields, DRIZZLE_ROW row, uint32_t *lengths)
382
uint32_t pkt_len,len;
383
unsigned char *pos, *prev_pos, *end_pos;
384
NET *net= &drizzle->net;
386
if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
388
if (pkt_len <= 8 && net->read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
390
if (pkt_len > 1) /* DRIZZLE 4.1 protocol */
392
drizzle->warning_count= uint2korr(net->read_pos+1);
393
drizzle->server_status= uint2korr(net->read_pos+3);
395
return 1; /* End of data */
397
prev_pos= 0; /* allowed to write at packet[-1] */
400
for (field=0 ; field < fields ; field++)
402
if ((len= net_field_length(&pos)) == NULL_LENGTH)
409
if (len > (uint32_t) (end_pos - pos))
411
drizzle_set_error(drizzle, CR_UNKNOWN_ERROR,
412
sqlstate_get_unknown());
415
row[field] = (char*) pos;
420
*prev_pos=0; /* Terminate prev field */
423
row[field]=(char*) prev_pos+1; /* End of last field */
424
*prev_pos=0; /* Terminate last field */
429
/**************************************************************************
430
Return next row of the query results
431
**************************************************************************/
434
drizzle_fetch_row(DRIZZLE_RES *res)
437
{ /* Unbufferred fetch */
440
DRIZZLE *drizzle= res->handle;
441
if (drizzle->status != DRIZZLE_STATUS_USE_RESULT)
443
drizzle_set_error(drizzle,
444
res->unbuffered_fetch_cancelled ?
445
CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
446
sqlstate_get_unknown());
448
else if (!(read_one_row(drizzle, res->field_count, res->row, res->lengths)))
451
return(res->current_row=res->row);
454
drizzle->status=DRIZZLE_STATUS_READY;
456
Reset only if owner points to us: there is a chance that somebody
457
started new query after drizzle_stmt_close():
459
if (drizzle->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
460
drizzle->unbuffered_fetch_owner= 0;
461
/* Don't clear handle in drizzle_free_result */
464
return((DRIZZLE_ROW) NULL);
468
if (!res->data_cursor)
470
return(res->current_row=(DRIZZLE_ROW) NULL);
472
tmp = res->data_cursor->data;
473
res->data_cursor = res->data_cursor->next;
474
return(res->current_row=tmp);
479
/**************************************************************************
480
Get column lengths of the current row
481
If one uses drizzle_use_result, res->lengths contains the length information,
482
else the lengths are calculated from the offset between pointers.
483
**************************************************************************/
486
drizzle_fetch_lengths(DRIZZLE_RES *res)
490
if (!(column=res->current_row))
491
return 0; /* Something is wrong */
493
(*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
499
drizzle_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
502
case DRIZZLE_OPT_CONNECT_TIMEOUT:
503
drizzle->options.connect_timeout= *(uint32_t*) arg;
505
case DRIZZLE_OPT_READ_TIMEOUT:
506
drizzle->options.read_timeout= *(uint32_t*) arg;
508
case DRIZZLE_OPT_WRITE_TIMEOUT:
509
drizzle->options.write_timeout= *(uint32_t*) arg;
511
case DRIZZLE_OPT_COMPRESS:
512
drizzle->options.compress= 1; /* Remember for connect */
513
drizzle->options.client_flag|= CLIENT_COMPRESS;
515
case DRIZZLE_OPT_LOCAL_INFILE: /* Allow LOAD DATA LOCAL ?*/
516
if (!arg || (*(uint32_t*) arg) ? 1 : 0)
517
drizzle->options.client_flag|= CLIENT_LOCAL_FILES;
519
drizzle->options.client_flag&= ~CLIENT_LOCAL_FILES;
521
case DRIZZLE_READ_DEFAULT_FILE:
522
if (drizzle->options.my_cnf_file != NULL)
523
free(drizzle->options.my_cnf_file);
524
drizzle->options.my_cnf_file=strdup(arg);
526
case DRIZZLE_READ_DEFAULT_GROUP:
527
if (drizzle->options.my_cnf_group != NULL)
528
free(drizzle->options.my_cnf_group);
529
drizzle->options.my_cnf_group=strdup(arg);
531
case DRIZZLE_OPT_PROTOCOL:
533
case DRIZZLE_OPT_USE_REMOTE_CONNECTION:
534
case DRIZZLE_OPT_GUESS_CONNECTION:
535
drizzle->options.methods_to_use= option;
537
case DRIZZLE_SET_CLIENT_IP:
538
drizzle->options.client_ip= strdup(arg);
540
case DRIZZLE_SECURE_AUTH:
541
drizzle->options.secure_auth= *(const bool *) arg;
543
case DRIZZLE_REPORT_DATA_TRUNCATION:
544
drizzle->options.report_data_truncation= (*(const bool *) arg) ? 1 : 0;
546
case DRIZZLE_OPT_RECONNECT:
547
drizzle->reconnect= *(const bool *) arg;
549
case DRIZZLE_OPT_SSL_VERIFY_SERVER_CERT:
550
if (*(const bool*) arg)
551
drizzle->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;
553
drizzle->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
562
/****************************************************************************
563
Functions to get information from the DRIZZLE structure
564
These are functions to make shared libraries more usable.
565
****************************************************************************/
568
uint64_t drizzle_num_rows(const DRIZZLE_RES *res)
570
return res->row_count;
573
unsigned int drizzle_num_fields(const DRIZZLE_RES *res)
575
return res->field_count;
580
Get version number for server in a form easy to test on
583
drizzle_get_server_version()
590
We will ensure that a newer server always has a bigger number.
593
Signed number > 323000
597
drizzle_get_server_version(const DRIZZLE *drizzle)
599
uint32_t major, minor, version;
600
char *pos= drizzle->server_version, *end_pos;
601
major= (uint32_t) strtoul(pos, &end_pos, 10); pos=end_pos+1;
602
minor= (uint32_t) strtoul(pos, &end_pos, 10); pos=end_pos+1;
603
version= (uint32_t) strtoul(pos, &end_pos, 10);
604
return (uint32_t) major*10000L+(uint32_t) (minor*100+version);