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
20
#include <drizzled/global.h>
21
#include <drizzled/common.h>
23
#include "libdrizzle_priv.h"
25
#include "libdrizzle.h"
30
#include "drizzle_data.h"
32
#include <drizzled/gettext.h>
41
#include <sys/socket.h>
44
#include <arpa/inet.h>
45
#include <netinet/in.h>
48
#define CONNECT_TIMEOUT 0
49
#define PROTOCOL_VERSION 10
52
static bool drizzle_client_init= false;
53
unsigned int drizzle_server_last_errno;
55
/* Server error code and message */
56
char drizzle_server_last_error[LIBDRIZZLE_ERRMSG_SIZE];
59
Note that the drizzle argument must be initialized with drizzle_init()
60
before calling drizzleclient_connect !
65
static DRIZZLE_METHODS client_methods=
67
drizzleclient_cli_read_query_result, /* read_query_result */
68
drizzleclient_cli_advanced_command, /* advanced_command */
69
drizzleclient_cli_read_rows, /* read_rows */
70
drizzleclient_cli_use_result, /* use_result */
71
drizzleclient_cli_fetch_lengths, /* fetch_lengths */
72
drizzleclient_cli_flush_use_result, /* flush_use_result */
73
drizzleclient_cli_list_fields, /* list_fields */
74
drizzleclient_cli_unbuffered_fetch, /* unbuffered_fetch */
75
drizzleclient_cli_read_statistics, /* read_statistics */
76
drizzleclient_cli_read_query_result, /* next_result */
81
/****************************************************************************
82
Init DRIZZLE structure or allocate one
83
****************************************************************************/
86
drizzleclient_create(DRIZZLE *ptr)
89
if (!drizzle_client_init)
91
drizzle_client_init=true;
93
if (!drizzleclient_get_default_port())
95
drizzleclient_set_default_port(DRIZZLE_TCP_PORT);
97
struct servent *serv_ptr;
101
if builder specifically requested a default port, use that
102
(even if it coincides with our factory default).
103
only if they didn't do we check /etc/services (and, failing
104
on that, fall back to the factory default of 4427).
105
either default can be overridden by the environment variable
106
DRIZZLE_TCP_PORT, which in turn can be overridden with command
110
#if DRIZZLE_TCP_PORT_DEFAULT == 0
111
if ((serv_ptr = getservbyname("drizzle", "tcp")))
112
drizzleclient_set_default_port((uint32_t) ntohs((uint16_t) serv_ptr->s_port));
114
if ((env = getenv("DRIZZLE_TCP_PORT")))
115
drizzleclient_set_default_port((uint32_t) atoi(env));
119
(void) signal(SIGPIPE, SIG_IGN);
125
ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
129
drizzleclient_set_error(NULL, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
132
memset(ptr, 0, sizeof(DRIZZLE));
137
memset(ptr, 0, sizeof(DRIZZLE));
140
ptr->options.connect_timeout= CONNECT_TIMEOUT;
141
strcpy(ptr->net.sqlstate, drizzleclient_sqlstate_get_not_error());
144
Only enable LOAD DATA INFILE by default if configured with
145
--enable-local-infile
148
#if defined(ENABLED_LOCAL_INFILE)
149
ptr->options.client_flag|= CLIENT_LOCAL_FILES;
152
ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION;
153
ptr->options.report_data_truncation= true; /* default */
156
By default we don't reconnect because it could silently corrupt data (after
157
reconnection you potentially lose table locks, user variables, session
158
variables (transactions but they are specifically dealt with in
159
drizzleclient_reconnect()).
160
This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
161
How this change impacts existing apps:
162
- existing apps which relyed on the default will see a behaviour change;
163
they will have to set reconnect=1 after drizzleclient_connect().
164
- existing apps which explicitely asked for reconnection (the only way they
165
could do it was by setting drizzle.reconnect to 1 after drizzleclient_connect())
166
will not see a behaviour change.
167
- existing apps which explicitely asked for no reconnection
168
(drizzle.reconnect=0) will not see a behaviour change.
176
static void read_user_name(char *name)
179
strcpy(name,"root"); /* allow use of surun */
185
if ((str=getlogin()) == NULL)
187
if ((skr=getpwuid(geteuid())) != NULL)
189
else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
190
!(str=getenv("LOGIN")))
193
strncpy(name,str,USERNAME_LENGTH);
195
(void) cuserid(name);
197
strcpy(name,"UNKNOWN_USER");
204
drizzleclient_connect(DRIZZLE *drizzle,const char *host, const char *user,
205
const char *passwd, const char *db,
207
const char * unix_port,
208
uint32_t client_flag)
211
char buff[NAME_LEN+USERNAME_LENGTH+100];
212
char *end,*host_info=NULL;
214
NET *net= &drizzle->net;
216
drizzle->methods= &client_methods;
217
net->vio = 0; /* If something goes wrong */
218
drizzle->client_flag=0; /* For handshake */
220
/* Some empty-string-tests are done because of ODBC */
221
if (!host || !host[0])
222
host=drizzle->options.host;
223
if (!user || !user[0])
225
user=drizzle->options.user;
231
passwd=drizzle->options.password;
236
db=drizzle->options.db;
238
port=drizzle->options.port;
240
drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
243
Part 0: Grab a socket and connect it to the server
247
struct addrinfo *res_lst, hints, *t_res;
249
char port_buf[NI_MAXSERV];
252
port= drizzleclient_get_default_port();
257
snprintf(host_info=buff, sizeof(buff)-1, _("%-.100s via TCP/IP"), host);
259
memset(&hints, 0, sizeof(hints));
260
hints.ai_socktype= SOCK_STREAM;
262
snprintf(port_buf, NI_MAXSERV, "%d", port);
263
gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
267
drizzleclient_set_extended_error(drizzle, CR_UNKNOWN_HOST, drizzleclient_sqlstate_get_unknown(),
268
ER(CR_UNKNOWN_HOST), host, errno);
273
for (t_res= res_lst; t_res != NULL; t_res= t_res->ai_next)
275
int sock= socket(t_res->ai_family, t_res->ai_socktype,
280
net->vio= drizzleclient_vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
287
if (drizzleclient_connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
289
drizzleclient_vio_delete(net->vio);
296
freeaddrinfo(res_lst);
301
drizzleclient_set_extended_error(drizzle, CR_CONN_HOST_ERROR,
302
drizzleclient_sqlstate_get_unknown(),
303
ER(CR_CONN_HOST_ERROR),
308
if (drizzleclient_net_init(net, net->vio))
310
drizzleclient_vio_delete(net->vio);
312
drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
315
drizzleclient_vio_keepalive(net->vio,true);
317
/* If user set read_timeout, let it override the default */
318
if (drizzle->options.read_timeout)
319
drizzleclient_net_set_read_timeout(net, drizzle->options.read_timeout);
321
/* If user set write_timeout, let it override the default */
322
if (drizzle->options.write_timeout)
323
drizzleclient_net_set_write_timeout(net, drizzle->options.write_timeout);
325
if (drizzle->options.max_allowed_packet)
326
net->max_packet_size= drizzle->options.max_allowed_packet;
328
/* Get version info */
329
drizzle->protocol_version= PROTOCOL_VERSION; /* Assume this */
330
if (drizzle->options.connect_timeout &&
331
drizzleclient_vio_poll_read(net->vio, drizzle->options.connect_timeout))
333
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
334
ER(CR_SERVER_LOST_INITIAL_COMM_WAIT),
340
Part 1: Connection established, read and parse first packet
343
if ((pkt_length=drizzleclient_cli_safe_read(drizzle)) == packet_error)
345
if (drizzle->net.last_errno == CR_SERVER_LOST)
346
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
347
ER(CR_SERVER_LOST_INITIAL_COMM_READ),
351
/* Check if version of protocol matches current one */
353
drizzle->protocol_version= net->read_pos[0];
354
if (drizzle->protocol_version != PROTOCOL_VERSION)
356
drizzleclient_set_extended_error(drizzle, CR_VERSION_ERROR, drizzleclient_sqlstate_get_unknown(),
357
ER(CR_VERSION_ERROR), drizzle->protocol_version,
361
end= strchr((char*) net->read_pos+1, '\0');
362
drizzle->thread_id=uint4korr(end+1);
365
Scramble is split into two parts because old clients does not understand
366
long scrambles; here goes the first part.
368
strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
369
end+= SCRAMBLE_LENGTH_323+1;
371
if (pkt_length >= (uint32_t) (end+1 - (char*) net->read_pos))
372
drizzle->server_capabilities=uint2korr(end);
373
if (pkt_length >= (uint32_t) (end+18 - (char*) net->read_pos))
375
/* New protocol with 16 bytes to describe server characteristics */
376
drizzle->server_language=end[2];
377
drizzle->server_status=uint2korr(end+3);
380
if (pkt_length >= (uint32_t) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
381
(char *) net->read_pos))
382
strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
383
SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
385
drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
387
if (drizzle->options.secure_auth && passwd[0] &&
388
!(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
390
drizzleclient_set_error(drizzle, CR_SECURE_AUTH, drizzleclient_sqlstate_get_unknown());
394
/* Save connection information */
395
if (!(drizzle->host_info= (char *)malloc(strlen(host_info)+1+strlen(host)+1
396
+(end - (char*) net->read_pos))) ||
397
!(drizzle->user=strdup(user)) ||
398
!(drizzle->passwd=strdup(passwd)))
400
drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
403
drizzle->host= drizzle->host_info+strlen(host_info)+1;
404
drizzle->server_version= drizzle->host+strlen(host)+1;
405
strcpy(drizzle->host_info,host_info);
406
strcpy(drizzle->host,host);
407
strcpy(drizzle->server_version,(char*) net->read_pos+1);
411
Part 2: format and send client info to the server for access check
414
client_flag|=drizzle->options.client_flag;
415
client_flag|=CLIENT_CAPABILITIES;
416
if (client_flag & CLIENT_MULTI_STATEMENTS)
417
client_flag|= CLIENT_MULTI_RESULTS;
420
client_flag|=CLIENT_CONNECT_WITH_DB;
422
/* Remove options that server doesn't support */
423
client_flag= ((client_flag &
424
~(CLIENT_COMPRESS | CLIENT_SSL)) |
425
(client_flag & drizzle->server_capabilities));
426
client_flag&= ~CLIENT_COMPRESS;
428
int4store(buff, client_flag);
429
int4store(buff+4, net->max_packet_size);
430
buff[8]= (char) 45; // utf8 charset number
431
memset(buff+9, 0, 32-9);
434
drizzle->client_flag=client_flag;
436
/* This needs to be changed as it's not useful with big packets */
438
strncpy(end,user,USERNAME_LENGTH); /* Max user name */
440
read_user_name((char*) end);
442
/* We have to handle different version of handshake here */
443
end= strchr(end, '\0') + 1;
447
*end++= SCRAMBLE_LENGTH;
448
memset(end, 0, SCRAMBLE_LENGTH-1);
449
memcpy(end, passwd, strlen(passwd));
450
end+= SCRAMBLE_LENGTH;
454
*end++= '\0'; /* empty password */
456
/* Add database if needed */
457
if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
459
size_t db_len= strlen(db);
461
if (db_len >= NAME_LEN)
462
db_len= NAME_LEN - 1;
463
end= (char *)memcpy(end, db, db_len);
467
drizzle->db= strdup(db);
470
/* Write authentication package */
471
if (drizzleclient_net_write(net, (unsigned char*) buff, (size_t) (end-buff)) || drizzleclient_net_flush(net))
473
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
474
ER(CR_SERVER_LOST_SEND_AUTH),
480
Part 3: Authorization data's been sent. Now server can reply with
481
OK-packet, or re-request scrambled password.
484
if ((pkt_length=drizzleclient_cli_safe_read(drizzle)) == packet_error)
486
if (drizzle->net.last_errno == CR_SERVER_LOST)
487
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
488
ER(CR_SERVER_LOST_READ_AUTH),
493
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
497
if (db && drizzleclient_select_db(drizzle, db))
499
if (drizzle->net.last_errno == CR_SERVER_LOST)
500
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
501
ER(CR_SERVER_LOST_SETTING_DB),
511
/* Free alloced memory */
512
drizzleclient_disconnect(drizzle);
513
drizzleclient_close_free(drizzle);
514
if (!(((uint32_t) client_flag) & CLIENT_REMEMBER_OPTIONS))
515
drizzleclient_close_free_options(drizzle);
523
/**************************************************************************
525
**************************************************************************/
528
drizzleclient_select_db(DRIZZLE *drizzle, const char *db)
532
if ((error=simple_command(drizzle,COM_INIT_DB, (const unsigned char*) db,
533
(uint32_t) strlen(db),0)))
535
if (drizzle->db != NULL)
537
drizzle->db=strdup(db);
541
bool drizzleclient_reconnect(DRIZZLE *drizzle)
546
if (!drizzle->reconnect ||
547
(drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
549
/* Allow reconnect next time */
550
drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
551
drizzleclient_set_error(drizzle, CR_SERVER_GONE_ERROR, drizzleclient_sqlstate_get_unknown());
554
drizzleclient_create(&tmp_drizzle);
555
tmp_drizzle.options= drizzle->options;
556
tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
558
if (!drizzleclient_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
559
drizzle->db, drizzle->port, 0,
560
drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
562
drizzle->net.last_errno= tmp_drizzle.net.last_errno;
563
strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
564
strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
568
tmp_drizzle.reconnect= 1;
569
tmp_drizzle.free_me= drizzle->free_me;
571
/* Don't free options as these are now used in tmp_drizzle */
572
memset(&drizzle->options, 0, sizeof(drizzle->options));
574
drizzleclient_close(drizzle);
575
*drizzle=tmp_drizzle;
576
drizzleclient_net_clear(&drizzle->net, 1);
577
drizzle->affected_rows= ~(uint64_t) 0;
581
/**************************************************************************
583
**************************************************************************/
585
void drizzleclient_disconnect(DRIZZLE *drizzle)
587
int save_errno= errno;
588
if (drizzle->net.vio != 0)
590
drizzleclient_vio_delete(drizzle->net.vio);
591
drizzle->net.vio= 0; /* Marker */
593
drizzleclient_net_end(&drizzle->net);
594
drizzleclient_free_old_query(drizzle);
599
/*************************************************************************
600
Send a QUIT to the server and close the connection
601
If handle is alloced by DRIZZLE connect free it.
602
*************************************************************************/
604
void drizzleclient_close_free_options(DRIZZLE *drizzle)
606
if (drizzle->options.user != NULL)
607
free(drizzle->options.user);
608
if (drizzle->options.host != NULL)
609
free(drizzle->options.host);
610
if (drizzle->options.password != NULL)
611
free(drizzle->options.password);
612
if (drizzle->options.db != NULL)
613
free(drizzle->options.db);
614
if (drizzle->options.my_cnf_file != NULL)
615
free(drizzle->options.my_cnf_file);
616
if (drizzle->options.my_cnf_group != NULL)
617
free(drizzle->options.my_cnf_group);
618
if (drizzle->options.client_ip != NULL)
619
free(drizzle->options.client_ip);
620
memset(&drizzle->options, 0, sizeof(drizzle->options));
625
void drizzleclient_close_free(DRIZZLE *drizzle)
627
if (drizzle->host_info != NULL)
628
free((unsigned char*) drizzle->host_info);
629
if (drizzle->user != NULL)
631
if (drizzle->passwd != NULL)
632
free(drizzle->passwd);
633
if (drizzle->db != NULL)
635
if (drizzle->info_buffer != NULL)
636
free(drizzle->info_buffer);
637
drizzle->info_buffer= 0;
639
/* Clear pointers for better safety */
640
drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
644
void drizzleclient_close(DRIZZLE *drizzle)
646
if (drizzle) /* Some simple safety */
648
/* If connection is still up, send a QUIT message */
649
if (drizzle->net.vio != 0)
651
drizzleclient_free_old_query(drizzle);
652
drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
653
drizzle->reconnect=0;
654
simple_command(drizzle,COM_QUIT,(unsigned char*) 0,0,1);
655
drizzleclient_disconnect(drizzle); /* Sets drizzle->net.vio= 0 */
657
drizzleclient_close_free_options(drizzle);
658
drizzleclient_close_free(drizzle);
659
if (drizzle->free_me)
660
free((unsigned char*) drizzle);
666
bool drizzleclient_cli_read_query_result(DRIZZLE *drizzle)
669
uint32_t field_count;
670
DRIZZLE_DATA *fields;
673
if ((length = drizzleclient_cli_safe_read(drizzle)) == packet_error)
675
drizzleclient_free_old_query(drizzle); /* Free old result */
677
pos=(unsigned char*) drizzle->net.read_pos;
678
if ((field_count= drizzleclient_net_field_length(&pos)) == 0)
680
drizzle->affected_rows= drizzleclient_drizzleclient_net_field_length_ll(&pos);
681
drizzle->insert_id= drizzleclient_drizzleclient_net_field_length_ll(&pos);
683
drizzle->server_status= uint2korr(pos); pos+=2;
684
drizzle->warning_count= uint2korr(pos); pos+=2;
686
if (pos < drizzle->net.read_pos+length && drizzleclient_net_field_length(&pos))
687
drizzle->info=(char*) pos;
690
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
692
drizzleclient_set_error(drizzle, CR_MALFORMED_PACKET, drizzleclient_sqlstate_get_unknown());
696
if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
697
drizzle->server_status|= SERVER_STATUS_IN_TRANS;
699
if (!(fields=drizzleclient_cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, 7)))
701
if (!(drizzle->fields= drizzleclient_unpack_fields(fields, (uint32_t) field_count, 0)))
703
drizzle->status= DRIZZLE_STATUS_GET_RESULT;
704
drizzle->field_count= (uint32_t) field_count;
710
Send the query and return so we can do something else.
711
Needs to be followed by drizzleclient_read_query_result() when we want to
712
finish processing it.
716
drizzleclient_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
718
return(simple_command(drizzle, COM_QUERY, (unsigned char*) query, length, 1));
723
drizzleclient_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
725
if (drizzleclient_send_query(drizzle,query,length))
727
return((int) (*drizzle->methods->read_query_result)(drizzle));
731
/**************************************************************************
732
Alloc result struct for buffered results. All rows are read to buffer.
733
drizzleclient_data_seek may be used.
734
**************************************************************************/
736
DRIZZLE_RES * drizzleclient_store_result(DRIZZLE *drizzle)
740
if (!drizzle->fields)
742
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
744
drizzleclient_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, drizzleclient_sqlstate_get_unknown());
747
drizzle->status=DRIZZLE_STATUS_READY; /* server is ready */
748
if (!(result=(DRIZZLE_RES*) malloc((uint32_t) (sizeof(DRIZZLE_RES)+
750
drizzle->field_count))))
752
drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
755
memset(result, 0,(sizeof(DRIZZLE_RES)+ sizeof(uint32_t) *
756
drizzle->field_count));
757
result->methods= drizzle->methods;
758
result->eof= 1; /* Marker for buffered */
759
result->lengths= (uint32_t*) (result+1);
761
(*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
763
free((unsigned char*) result);
766
drizzle->affected_rows= result->row_count= result->data->rows;
767
result->data_cursor= result->data->data;
768
result->fields= drizzle->fields;
769
result->field_count= drizzle->field_count;
770
/* The rest of result members is zeroed in malloc */
771
drizzle->fields=0; /* fields is now in result */
772
/* just in case this was mistakenly called after drizzle_stmt_execute() */
773
drizzle->unbuffered_fetch_owner= 0;
774
return(result); /* Data fetched */
778
/**************************************************************************
779
Alloc struct for use with unbuffered reads. Data is fetched by domand
780
when calling to drizzleclient_fetch_row.
781
DRIZZLE_DATA_seek is a noop.
783
No other queries may be specified with the same DRIZZLE handle.
784
There shouldn't be much processing per row because DRIZZLE server shouldn't
785
have to wait for the client (and will not wait more than 30 sec/packet).
786
**************************************************************************/
788
DRIZZLE_RES * drizzleclient_cli_use_result(DRIZZLE *drizzle)
792
if (!drizzle->fields)
794
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
796
drizzleclient_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, drizzleclient_sqlstate_get_unknown());
799
if (!(result=(DRIZZLE_RES*) malloc(sizeof(*result)+
800
sizeof(uint32_t)*drizzle->field_count)))
802
memset(result, 0, sizeof(*result)+ sizeof(uint32_t)*drizzle->field_count);
803
result->lengths=(uint32_t*) (result+1);
804
result->methods= drizzle->methods;
805
if (!(result->row=(DRIZZLE_ROW)
806
malloc(sizeof(result->row[0])*(drizzle->field_count+1))))
807
{ /* Ptrs: to one row */
808
free((unsigned char*) result);
811
result->fields= drizzle->fields;
812
result->field_count= drizzle->field_count;
813
result->current_field=0;
814
result->handle= drizzle;
815
result->current_row= 0;
816
drizzle->fields=0; /* fields is now in result */
817
drizzle->status=DRIZZLE_STATUS_USE_RESULT;
818
drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
819
return(result); /* Data is read to be fetched */
825
Set the internal error message to DRIZZLE handler
827
@param drizzle connection handle (client side)
828
@param errcode CR_ error code, passed to ER macro to get
830
@parma sqlstate SQL standard sqlstate
833
void drizzleclient_set_error(DRIZZLE *drizzle, int errcode, const char *sqlstate)
836
assert(drizzle != 0);
841
net->last_errno= errcode;
842
strcpy(net->last_error, ER(errcode));
843
strcpy(net->sqlstate, sqlstate);
847
drizzle_server_last_errno= errcode;
848
strcpy(drizzle_server_last_error, ER(errcode));
854
unsigned int drizzleclient_errno(const DRIZZLE *drizzle)
856
return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno;
860
const char * drizzleclient_error(const DRIZZLE *drizzle)
862
return drizzle ? _(drizzle->net.last_error) : _(drizzle_server_last_error);
866
Set an error message on the client.
868
@param drizzle connection handle
869
@param errcode CR_* errcode, for client errors
870
@param sqlstate SQL standard sql state, drizzleclient_sqlstate_get_unknown() for the
871
majority of client errors.
872
@param format error message template, in sprintf format
873
@param ... variable number of arguments
876
void drizzleclient_set_extended_error(DRIZZLE *drizzle, int errcode,
877
const char *sqlstate,
878
const char *format, ...)
882
assert(drizzle != 0);
885
net->last_errno= errcode;
886
va_start(args, format);
887
vsnprintf(net->last_error, sizeof(net->last_error)-1,
890
strcpy(net->sqlstate, sqlstate);
898
Flush result set sent from server
901
void drizzleclient_cli_flush_use_result(DRIZZLE *drizzle)
903
/* Clear the current execution status */
907
if ((pkt_len=drizzleclient_cli_safe_read(drizzle)) == packet_error)
909
if (pkt_len <= 8 && drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
911
char *pos= (char*) drizzle->net.read_pos + 1;
912
drizzle->warning_count=uint2korr(pos); pos+=2;
913
drizzle->server_status=uint2korr(pos); pos+=2;
915
break; /* End of data */
921
/**************************************************************************
922
Get column lengths of the current row
923
If one uses drizzleclient_use_result, res->lengths contains the length information,
924
else the lengths are calculated from the offset between pointers.
925
**************************************************************************/
927
void drizzleclient_cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count)
929
uint32_t *prev_length;
933
prev_length=0; /* Keep gcc happy */
934
for (end=column + field_count + 1 ; column != end ; column++, to++)
941
if (start) /* Found end of prev string */
942
*prev_length= (uint32_t) (*column-start-1);