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
22
#include <libdrizzle/drizzle_com.h>
23
#include <libdrizzle/libdrizzle.h>
24
#include <libdrizzle/errmsg.h>
25
#include <libdrizzle/drizzle.h>
26
#include <libdrizzle/gettext.h>
27
#include <libdrizzle/net_serv.h>
28
#include <libdrizzle/drizzle_data.h>
29
#include <libdrizzle/local_infile.h>
31
#include "libdrizzle_priv.h"
33
#include <vio/violite.h>
35
#include <drizzled/version.h>
44
#include <sys/socket.h>
47
#define CONNECT_TIMEOUT 0
49
static bool drizzle_client_init= false;
50
unsigned int drizzle_server_last_errno;
52
/* Server error code and message */
53
char drizzle_server_last_error[DRIZZLE_ERRMSG_SIZE];
56
Note that the drizzle argument must be initialized with drizzle_init()
57
before calling drizzle_connect !
62
static DRIZZLE_METHODS client_methods=
64
cli_read_query_result, /* read_query_result */
65
cli_advanced_command, /* advanced_command */
66
cli_read_rows, /* read_rows */
67
cli_use_result, /* use_result */
68
cli_fetch_lengths, /* fetch_lengths */
69
cli_flush_use_result, /* flush_use_result */
70
cli_list_fields, /* list_fields */
71
cli_unbuffered_fetch, /* unbuffered_fetch */
72
cli_read_statistics, /* read_statistics */
73
cli_read_query_result, /* next_result */
74
cli_read_change_user_result, /* read_change_user_result */
79
/****************************************************************************
80
Init DRIZZLE structure or allocate one
81
****************************************************************************/
84
drizzle_create(DRIZZLE *ptr)
87
if (!drizzle_client_init)
89
drizzle_client_init=true;
91
if (!drizzle_get_default_port())
93
drizzle_set_default_port(DRIZZLE_PORT);
95
struct servent *serv_ptr;
99
if builder specifically requested a default port, use that
100
(even if it coincides with our factory default).
101
only if they didn't do we check /etc/services (and, failing
102
on that, fall back to the factory default of 4427).
103
either default can be overridden by the environment variable
104
DRIZZLE_TCP_PORT, which in turn can be overridden with command
108
#if DRIZZLE_PORT_DEFAULT == 0
109
if ((serv_ptr = getservbyname("drizzle", "tcp")))
110
drizzle_set_default_port((uint32_t) ntohs((uint16_t) serv_ptr->s_port));
112
if ((env = getenv("DRIZZLE_TCP_PORT")))
113
drizzle_set_default_port((uint32_t) atoi(env));
117
(void) signal(SIGPIPE, SIG_IGN);
123
ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
127
drizzle_set_error(NULL, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
130
memset(ptr, 0, sizeof(DRIZZLE));
135
memset(ptr, 0, sizeof(DRIZZLE));
138
ptr->options.connect_timeout= CONNECT_TIMEOUT;
139
strcpy(ptr->net.sqlstate, sqlstate_get_not_error());
142
Only enable LOAD DATA INFILE by default if configured with
143
--enable-local-infile
146
#if defined(ENABLED_LOCAL_INFILE)
147
ptr->options.client_flag|= CLIENT_LOCAL_FILES;
150
ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION;
151
ptr->options.report_data_truncation= true; /* default */
154
By default we don't reconnect because it could silently corrupt data (after
155
reconnection you potentially lose table locks, user variables, session
156
variables (transactions but they are specifically dealt with in
157
drizzle_reconnect()).
158
This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
159
How this change impacts existing apps:
160
- existing apps which relyed on the default will see a behaviour change;
161
they will have to set reconnect=1 after drizzle_connect().
162
- existing apps which explicitely asked for reconnection (the only way they
163
could do it was by setting drizzle.reconnect to 1 after drizzle_connect())
164
will not see a behaviour change.
165
- existing apps which explicitely asked for no reconnection
166
(drizzle.reconnect=0) will not see a behaviour change.
174
static void read_user_name(char *name)
177
strcpy(name,"root"); /* allow use of surun */
183
if ((str=getlogin()) == NULL)
185
if ((skr=getpwuid(geteuid())) != NULL)
187
else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
188
!(str=getenv("LOGIN")))
191
strncpy(name,str,USERNAME_LENGTH);
193
(void) cuserid(name);
195
strcpy(name,"UNKNOWN_USER");
202
drizzle_connect(DRIZZLE *drizzle,const char *host, const char *user,
203
const char *passwd, const char *db,
205
const char * unix_port __attribute__((__unused__)),
206
uint32_t client_flag)
208
char buff[NAME_LEN+USERNAME_LENGTH+100];
209
char *end,*host_info=NULL;
211
NET *net= &drizzle->net;
213
drizzle->methods= &client_methods;
214
net->vio = 0; /* If something goes wrong */
215
drizzle->client_flag=0; /* For handshake */
217
/* Some empty-string-tests are done because of ODBC */
218
if (!host || !host[0])
219
host=drizzle->options.host;
220
if (!user || !user[0])
222
user=drizzle->options.user;
228
passwd=drizzle->options.password;
233
db=drizzle->options.db;
235
port=drizzle->options.port;
237
drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
240
Part 0: Grab a socket and connect it to the server
244
struct addrinfo *res_lst, hints, *t_res;
246
char port_buf[NI_MAXSERV];
254
snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
256
memset(&hints, 0, sizeof(hints));
257
hints.ai_socktype= SOCK_STREAM;
259
snprintf(port_buf, NI_MAXSERV, "%d", port);
260
gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
264
drizzle_set_extended_error(drizzle, CR_UNKNOWN_HOST, sqlstate_get_unknown(),
265
ER(CR_UNKNOWN_HOST), host, errno);
270
for (t_res= res_lst; t_res != NULL; t_res= t_res->ai_next)
272
int sock= socket(t_res->ai_family, t_res->ai_socktype,
277
net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
284
if (connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
286
vio_delete(net->vio);
293
freeaddrinfo(res_lst);
298
drizzle_set_extended_error(drizzle, CR_CONN_HOST_ERROR, sqlstate_get_unknown(),
299
ER(CR_CONN_HOST_ERROR), host, errno);
303
if (my_net_init(net, net->vio))
305
vio_delete(net->vio);
307
drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
310
vio_keepalive(net->vio,true);
312
/* If user set read_timeout, let it override the default */
313
if (drizzle->options.read_timeout)
314
my_net_set_read_timeout(net, drizzle->options.read_timeout);
316
/* If user set write_timeout, let it override the default */
317
if (drizzle->options.write_timeout)
318
my_net_set_write_timeout(net, drizzle->options.write_timeout);
320
if (drizzle->options.max_allowed_packet)
321
net->max_packet_size= drizzle->options.max_allowed_packet;
323
/* Get version info */
324
drizzle->protocol_version= PROTOCOL_VERSION; /* Assume this */
325
if (drizzle->options.connect_timeout &&
326
vio_poll_read(net->vio, drizzle->options.connect_timeout))
328
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
329
ER(CR_SERVER_LOST_INITIAL_COMM_WAIT),
335
Part 1: Connection established, read and parse first packet
338
if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
340
if (drizzle->net.last_errno == CR_SERVER_LOST)
341
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
342
ER(CR_SERVER_LOST_INITIAL_COMM_READ),
346
/* Check if version of protocol matches current one */
348
drizzle->protocol_version= net->read_pos[0];
349
if (drizzle->protocol_version != PROTOCOL_VERSION)
351
drizzle_set_extended_error(drizzle, CR_VERSION_ERROR, sqlstate_get_unknown(),
352
ER(CR_VERSION_ERROR), drizzle->protocol_version,
356
end= strchr((char*) net->read_pos+1, '\0');
357
drizzle->thread_id=uint4korr(end+1);
360
Scramble is split into two parts because old clients does not understand
361
long scrambles; here goes the first part.
363
strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
364
end+= SCRAMBLE_LENGTH_323+1;
366
if (pkt_length >= (uint32_t) (end+1 - (char*) net->read_pos))
367
drizzle->server_capabilities=uint2korr(end);
368
if (pkt_length >= (uint32_t) (end+18 - (char*) net->read_pos))
370
/* New protocol with 16 bytes to describe server characteristics */
371
drizzle->server_language=end[2];
372
drizzle->server_status=uint2korr(end+3);
375
if (pkt_length >= (uint32_t) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
376
(char *) net->read_pos))
377
strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
378
SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
380
drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
382
if (drizzle->options.secure_auth && passwd[0] &&
383
!(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
385
drizzle_set_error(drizzle, CR_SECURE_AUTH, sqlstate_get_unknown());
389
/* Save connection information */
390
if (!(drizzle->host_info= (char *)malloc(strlen(host_info)+1+strlen(host)+1
391
+(end - (char*) net->read_pos))) ||
392
!(drizzle->user=strdup(user)) ||
393
!(drizzle->passwd=strdup(passwd)))
395
drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
398
drizzle->host= drizzle->host_info+strlen(host_info)+1;
399
drizzle->server_version= drizzle->host+strlen(host)+1;
400
strcpy(drizzle->host_info,host_info);
401
strcpy(drizzle->host,host);
402
strcpy(drizzle->server_version,(char*) net->read_pos+1);
406
Part 2: format and send client info to the server for access check
409
client_flag|=drizzle->options.client_flag;
410
client_flag|=CLIENT_CAPABILITIES;
411
if (client_flag & CLIENT_MULTI_STATEMENTS)
412
client_flag|= CLIENT_MULTI_RESULTS;
415
client_flag|=CLIENT_CONNECT_WITH_DB;
417
/* Remove options that server doesn't support */
418
client_flag= ((client_flag &
419
~(CLIENT_COMPRESS | CLIENT_SSL)) |
420
(client_flag & drizzle->server_capabilities));
421
client_flag&= ~CLIENT_COMPRESS;
423
int4store(buff, client_flag);
424
int4store(buff+4, net->max_packet_size);
425
buff[8]= (char) 45; // utf8 charset number
426
memset(buff+9, 0, 32-9);
429
drizzle->client_flag=client_flag;
431
/* This needs to be changed as it's not useful with big packets */
433
strncpy(end,user,USERNAME_LENGTH); /* Max user name */
435
read_user_name((char*) end);
437
/* We have to handle different version of handshake here */
438
end= strchr(end, '\0') + 1;
442
*end++= SCRAMBLE_LENGTH;
443
memset(end, 0, SCRAMBLE_LENGTH-1);
444
memcpy(end, passwd, strlen(passwd));
445
end+= SCRAMBLE_LENGTH;
449
*end++= '\0'; /* empty password */
451
/* Add database if needed */
452
if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
454
end= strncpy(end, db, NAME_LEN) + NAME_LEN + 1;
455
drizzle->db= strdup(db);
458
/* Write authentication package */
459
if (my_net_write(net, (unsigned char*) buff, (size_t) (end-buff)) || net_flush(net))
461
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
462
ER(CR_SERVER_LOST_SEND_AUTH),
468
Part 3: Authorization data's been sent. Now server can reply with
469
OK-packet, or re-request scrambled password.
472
if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
474
if (drizzle->net.last_errno == CR_SERVER_LOST)
475
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
476
ER(CR_SERVER_LOST_READ_AUTH),
481
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
485
if (db && drizzle_select_db(drizzle, db))
487
if (drizzle->net.last_errno == CR_SERVER_LOST)
488
drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
489
ER(CR_SERVER_LOST_SETTING_DB),
499
/* Free alloced memory */
500
drizzle_disconnect(drizzle);
501
drizzle_close_free(drizzle);
502
if (!(((uint32_t) client_flag) & CLIENT_REMEMBER_OPTIONS))
503
drizzle_close_free_options(drizzle);
511
/**************************************************************************
513
**************************************************************************/
516
drizzle_select_db(DRIZZLE *drizzle, const char *db)
520
if ((error=simple_command(drizzle,COM_INIT_DB, (const unsigned char*) db,
521
(uint32_t) strlen(db),0)))
523
if (drizzle->db != NULL)
525
drizzle->db=strdup(db);
529
bool drizzle_reconnect(DRIZZLE *drizzle)
534
if (!drizzle->reconnect ||
535
(drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
537
/* Allow reconnect next time */
538
drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
539
drizzle_set_error(drizzle, CR_SERVER_GONE_ERROR, sqlstate_get_unknown());
542
drizzle_create(&tmp_drizzle);
543
tmp_drizzle.options= drizzle->options;
544
tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
546
if (!drizzle_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
547
drizzle->db, drizzle->port, 0,
548
drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
550
drizzle->net.last_errno= tmp_drizzle.net.last_errno;
551
strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
552
strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
556
tmp_drizzle.reconnect= 1;
557
tmp_drizzle.free_me= drizzle->free_me;
559
/* Don't free options as these are now used in tmp_drizzle */
560
memset(&drizzle->options, 0, sizeof(drizzle->options));
562
drizzle_close(drizzle);
563
*drizzle=tmp_drizzle;
564
net_clear(&drizzle->net, 1);
565
drizzle->affected_rows= ~(uint64_t) 0;
569
/**************************************************************************
571
**************************************************************************/
573
void drizzle_disconnect(DRIZZLE *drizzle)
575
int save_errno= errno;
576
if (drizzle->net.vio != 0)
578
vio_delete(drizzle->net.vio);
579
drizzle->net.vio= 0; /* Marker */
581
net_end(&drizzle->net);
582
free_old_query(drizzle);
587
/*************************************************************************
588
Send a QUIT to the server and close the connection
589
If handle is alloced by DRIZZLE connect free it.
590
*************************************************************************/
592
void drizzle_close_free_options(DRIZZLE *drizzle)
594
if (drizzle->options.user != NULL)
595
free(drizzle->options.user);
596
if (drizzle->options.host != NULL)
597
free(drizzle->options.host);
598
if (drizzle->options.password != NULL)
599
free(drizzle->options.password);
600
if (drizzle->options.db != NULL)
601
free(drizzle->options.db);
602
if (drizzle->options.my_cnf_file != NULL)
603
free(drizzle->options.my_cnf_file);
604
if (drizzle->options.my_cnf_group != NULL)
605
free(drizzle->options.my_cnf_group);
606
if (drizzle->options.client_ip != NULL)
607
free(drizzle->options.client_ip);
608
memset(&drizzle->options, 0, sizeof(drizzle->options));
613
void drizzle_close_free(DRIZZLE *drizzle)
615
if (drizzle->host_info != NULL)
616
free((unsigned char*) drizzle->host_info);
617
if (drizzle->user != NULL)
619
if (drizzle->passwd != NULL)
620
free(drizzle->passwd);
621
if (drizzle->db != NULL)
623
if (drizzle->info_buffer != NULL)
624
free(drizzle->info_buffer);
625
drizzle->info_buffer= 0;
627
/* Clear pointers for better safety */
628
drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
632
void drizzle_close(DRIZZLE *drizzle)
634
if (drizzle) /* Some simple safety */
636
/* If connection is still up, send a QUIT message */
637
if (drizzle->net.vio != 0)
639
free_old_query(drizzle);
640
drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
641
drizzle->reconnect=0;
642
simple_command(drizzle,COM_QUIT,(unsigned char*) 0,0,1);
643
drizzle_disconnect(drizzle); /* Sets drizzle->net.vio= 0 */
645
drizzle_close_free_options(drizzle);
646
drizzle_close_free(drizzle);
647
if (drizzle->free_me)
648
free((unsigned char*) drizzle);
654
bool cli_read_query_result(DRIZZLE *drizzle)
657
uint32_t field_count;
658
DRIZZLE_DATA *fields;
661
if ((length = cli_safe_read(drizzle)) == packet_error)
663
free_old_query(drizzle); /* Free old result */
665
pos=(unsigned char*) drizzle->net.read_pos;
666
if ((field_count= net_field_length(&pos)) == 0)
668
drizzle->affected_rows= net_field_length_ll(&pos);
669
drizzle->insert_id= net_field_length_ll(&pos);
671
drizzle->server_status= uint2korr(pos); pos+=2;
672
drizzle->warning_count= uint2korr(pos); pos+=2;
674
if (pos < drizzle->net.read_pos+length && net_field_length(&pos))
675
drizzle->info=(char*) pos;
678
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
682
if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES))
684
drizzle_set_error(drizzle, CR_MALFORMED_PACKET, sqlstate_get_unknown());
688
error= handle_local_infile(drizzle,(char*) pos);
689
if ((length= cli_safe_read(drizzle)) == packet_error || error)
691
goto get_info; /* Get info packet */
693
if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
694
drizzle->server_status|= SERVER_STATUS_IN_TRANS;
696
if (!(fields=cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, 7)))
698
if (!(drizzle->fields= unpack_fields(fields, (uint32_t) field_count, 0)))
700
drizzle->status= DRIZZLE_STATUS_GET_RESULT;
701
drizzle->field_count= (uint32_t) field_count;
707
Send the query and return so we can do something else.
708
Needs to be followed by drizzle_read_query_result() when we want to
709
finish processing it.
713
drizzle_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
715
return(simple_command(drizzle, COM_QUERY, (unsigned char*) query, length, 1));
720
drizzle_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
722
if (drizzle_send_query(drizzle,query,length))
724
return((int) (*drizzle->methods->read_query_result)(drizzle));
728
/**************************************************************************
729
Alloc result struct for buffered results. All rows are read to buffer.
730
drizzle_data_seek may be used.
731
**************************************************************************/
733
DRIZZLE_RES * drizzle_store_result(DRIZZLE *drizzle)
737
if (!drizzle->fields)
739
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
741
drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown());
744
drizzle->status=DRIZZLE_STATUS_READY; /* server is ready */
745
if (!(result=(DRIZZLE_RES*) malloc((uint32_t) (sizeof(DRIZZLE_RES)+
747
drizzle->field_count))))
749
drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
752
memset(result, 0,(sizeof(DRIZZLE_RES)+ sizeof(uint32_t) *
753
drizzle->field_count));
754
result->methods= drizzle->methods;
755
result->eof= 1; /* Marker for buffered */
756
result->lengths= (uint32_t*) (result+1);
758
(*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
760
free((unsigned char*) result);
763
drizzle->affected_rows= result->row_count= result->data->rows;
764
result->data_cursor= result->data->data;
765
result->fields= drizzle->fields;
766
result->field_count= drizzle->field_count;
767
/* The rest of result members is zeroed in malloc */
768
drizzle->fields=0; /* fields is now in result */
769
/* just in case this was mistakenly called after drizzle_stmt_execute() */
770
drizzle->unbuffered_fetch_owner= 0;
771
return(result); /* Data fetched */
775
/**************************************************************************
776
Alloc struct for use with unbuffered reads. Data is fetched by domand
777
when calling to drizzle_fetch_row.
778
DRIZZLE_DATA_seek is a noop.
780
No other queries may be specified with the same DRIZZLE handle.
781
There shouldn't be much processing per row because DRIZZLE server shouldn't
782
have to wait for the client (and will not wait more than 30 sec/packet).
783
**************************************************************************/
785
DRIZZLE_RES * cli_use_result(DRIZZLE *drizzle)
789
if (!drizzle->fields)
791
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
793
drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown());
796
if (!(result=(DRIZZLE_RES*) malloc(sizeof(*result)+
797
sizeof(uint32_t)*drizzle->field_count)))
799
memset(result, 0, sizeof(*result)+ sizeof(uint32_t)*drizzle->field_count);
800
result->lengths=(uint32_t*) (result+1);
801
result->methods= drizzle->methods;
802
if (!(result->row=(DRIZZLE_ROW)
803
malloc(sizeof(result->row[0])*(drizzle->field_count+1))))
804
{ /* Ptrs: to one row */
805
free((unsigned char*) result);
808
result->fields= drizzle->fields;
809
result->field_count= drizzle->field_count;
810
result->current_field=0;
811
result->handle= drizzle;
812
result->current_row= 0;
813
drizzle->fields=0; /* fields is now in result */
814
drizzle->status=DRIZZLE_STATUS_USE_RESULT;
815
drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
816
return(result); /* Data is read to be fetched */
822
Set the internal error message to DRIZZLE handler
824
@param drizzle connection handle (client side)
825
@param errcode CR_ error code, passed to ER macro to get
827
@parma sqlstate SQL standard sqlstate
830
void drizzle_set_error(DRIZZLE *drizzle, int errcode, const char *sqlstate)
833
assert(drizzle != 0);
838
net->last_errno= errcode;
839
strcpy(net->last_error, ER(errcode));
840
strcpy(net->sqlstate, sqlstate);
844
drizzle_server_last_errno= errcode;
845
strcpy(drizzle_server_last_error, ER(errcode));
851
unsigned int drizzle_errno(const DRIZZLE *drizzle)
853
return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno;
857
const char * drizzle_error(const DRIZZLE *drizzle)
859
return drizzle ? _(drizzle->net.last_error) : _(drizzle_server_last_error);
863
Set an error message on the client.
865
@param drizzle connection handle
866
@param errcode CR_* errcode, for client errors
867
@param sqlstate SQL standard sql state, sqlstate_get_unknown() for the
868
majority of client errors.
869
@param format error message template, in sprintf format
870
@param ... variable number of arguments
873
void drizzle_set_extended_error(DRIZZLE *drizzle, int errcode,
874
const char *sqlstate,
875
const char *format, ...)
879
assert(drizzle != 0);
882
net->last_errno= errcode;
883
va_start(args, format);
884
vsnprintf(net->last_error, sizeof(net->last_error)-1,
887
strcpy(net->sqlstate, sqlstate);
895
Flush result set sent from server
898
void cli_flush_use_result(DRIZZLE *drizzle)
900
/* Clear the current execution status */
904
if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
906
if (pkt_len <= 8 && drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
908
char *pos= (char*) drizzle->net.read_pos + 1;
909
drizzle->warning_count=uint2korr(pos); pos+=2;
910
drizzle->server_status=uint2korr(pos); pos+=2;
912
break; /* End of data */
918
/**************************************************************************
919
Get column lengths of the current row
920
If one uses drizzle_use_result, res->lengths contains the length information,
921
else the lengths are calculated from the offset between pointers.
922
**************************************************************************/
924
void cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count)
926
uint32_t *prev_length;
930
prev_length=0; /* Keep gcc happy */
931
for (end=column + field_count + 1 ; column != end ; column++, to++)
938
if (start) /* Found end of prev string */
939
*prev_length= (uint32_t) (*column-start-1);