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"
31
#include "local_infile.h"
33
#include <drizzled/gettext.h>
42
#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[LIBDRIZZLE_ERRMSG_SIZE];
56
Note that the drizzle argument must be initialized with drizzle_init()
57
before calling drizzleclient_connect !
62
static DRIZZLE_METHODS client_methods=
64
drizzleclient_cli_read_query_result, /* read_query_result */
65
drizzleclient_cli_advanced_command, /* advanced_command */
66
drizzleclient_cli_read_rows, /* read_rows */
67
drizzleclient_cli_use_result, /* use_result */
68
drizzleclient_cli_fetch_lengths, /* fetch_lengths */
69
drizzleclient_cli_flush_use_result, /* flush_use_result */
70
drizzleclient_cli_list_fields, /* list_fields */
71
drizzleclient_cli_unbuffered_fetch, /* unbuffered_fetch */
72
drizzleclient_cli_read_statistics, /* read_statistics */
73
drizzleclient_cli_read_query_result, /* next_result */
74
drizzleclient_cli_read_change_user_result, /* read_change_user_result */
79
/****************************************************************************
80
Init DRIZZLE structure or allocate one
81
****************************************************************************/
84
drizzleclient_create(DRIZZLE *ptr)
87
if (!drizzle_client_init)
89
drizzle_client_init=true;
91
if (!drizzleclient_get_default_port())
93
drizzleclient_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
drizzleclient_set_default_port((uint32_t) ntohs((uint16_t) serv_ptr->s_port));
112
if ((env = getenv("DRIZZLE_TCP_PORT")))
113
drizzleclient_set_default_port((uint32_t) atoi(env));
117
(void) signal(SIGPIPE, SIG_IGN);
123
ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
127
drizzleclient_set_error(NULL, CR_OUT_OF_MEMORY, drizzleclient_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, drizzleclient_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
drizzleclient_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 drizzleclient_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 drizzleclient_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
drizzleclient_connect(DRIZZLE *drizzle,const char *host, const char *user,
203
const char *passwd, const char *db,
205
const char * unix_port,
206
uint32_t client_flag)
209
char buff[NAME_LEN+USERNAME_LENGTH+100];
210
char *end,*host_info=NULL;
212
NET *net= &drizzle->net;
214
drizzle->methods= &client_methods;
215
net->vio = 0; /* If something goes wrong */
216
drizzle->client_flag=0; /* For handshake */
218
/* Some empty-string-tests are done because of ODBC */
219
if (!host || !host[0])
220
host=drizzle->options.host;
221
if (!user || !user[0])
223
user=drizzle->options.user;
229
passwd=drizzle->options.password;
234
db=drizzle->options.db;
236
port=drizzle->options.port;
238
drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
241
Part 0: Grab a socket and connect it to the server
245
struct addrinfo *res_lst, hints, *t_res;
247
char port_buf[NI_MAXSERV];
250
port= drizzleclient_get_default_port();
255
snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
257
memset(&hints, 0, sizeof(hints));
258
hints.ai_socktype= SOCK_STREAM;
260
snprintf(port_buf, NI_MAXSERV, "%d", port);
261
gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
265
drizzleclient_set_extended_error(drizzle, CR_UNKNOWN_HOST, drizzleclient_sqlstate_get_unknown(),
266
ER(CR_UNKNOWN_HOST), host, errno);
271
for (t_res= res_lst; t_res != NULL; t_res= t_res->ai_next)
273
int sock= socket(t_res->ai_family, t_res->ai_socktype,
278
net->vio= drizzleclient_vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
285
if (drizzleclient_connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
287
drizzleclient_vio_delete(net->vio);
294
freeaddrinfo(res_lst);
299
drizzleclient_set_extended_error(drizzle, CR_CONN_HOST_ERROR, drizzleclient_sqlstate_get_unknown(),
300
ER(CR_CONN_HOST_ERROR), host, errno);
304
if (drizzleclient_net_init(net, net->vio))
306
drizzleclient_vio_delete(net->vio);
308
drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
311
drizzleclient_vio_keepalive(net->vio,true);
313
/* If user set read_timeout, let it override the default */
314
if (drizzle->options.read_timeout)
315
drizzleclient_net_set_read_timeout(net, drizzle->options.read_timeout);
317
/* If user set write_timeout, let it override the default */
318
if (drizzle->options.write_timeout)
319
drizzleclient_net_set_write_timeout(net, drizzle->options.write_timeout);
321
if (drizzle->options.max_allowed_packet)
322
net->max_packet_size= drizzle->options.max_allowed_packet;
324
/* Get version info */
325
drizzle->protocol_version= PROTOCOL_VERSION; /* Assume this */
326
if (drizzle->options.connect_timeout &&
327
drizzleclient_vio_poll_read(net->vio, drizzle->options.connect_timeout))
329
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
330
ER(CR_SERVER_LOST_INITIAL_COMM_WAIT),
336
Part 1: Connection established, read and parse first packet
339
if ((pkt_length=drizzleclient_cli_safe_read(drizzle)) == packet_error)
341
if (drizzle->net.last_errno == CR_SERVER_LOST)
342
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
343
ER(CR_SERVER_LOST_INITIAL_COMM_READ),
347
/* Check if version of protocol matches current one */
349
drizzle->protocol_version= net->read_pos[0];
350
if (drizzle->protocol_version != PROTOCOL_VERSION)
352
drizzleclient_set_extended_error(drizzle, CR_VERSION_ERROR, drizzleclient_sqlstate_get_unknown(),
353
ER(CR_VERSION_ERROR), drizzle->protocol_version,
357
end= strchr((char*) net->read_pos+1, '\0');
358
drizzle->thread_id=uint4korr(end+1);
361
Scramble is split into two parts because old clients does not understand
362
long scrambles; here goes the first part.
364
strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
365
end+= SCRAMBLE_LENGTH_323+1;
367
if (pkt_length >= (uint32_t) (end+1 - (char*) net->read_pos))
368
drizzle->server_capabilities=uint2korr(end);
369
if (pkt_length >= (uint32_t) (end+18 - (char*) net->read_pos))
371
/* New protocol with 16 bytes to describe server characteristics */
372
drizzle->server_language=end[2];
373
drizzle->server_status=uint2korr(end+3);
376
if (pkt_length >= (uint32_t) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
377
(char *) net->read_pos))
378
strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
379
SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
381
drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
383
if (drizzle->options.secure_auth && passwd[0] &&
384
!(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
386
drizzleclient_set_error(drizzle, CR_SECURE_AUTH, drizzleclient_sqlstate_get_unknown());
390
/* Save connection information */
391
if (!(drizzle->host_info= (char *)malloc(strlen(host_info)+1+strlen(host)+1
392
+(end - (char*) net->read_pos))) ||
393
!(drizzle->user=strdup(user)) ||
394
!(drizzle->passwd=strdup(passwd)))
396
drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
399
drizzle->host= drizzle->host_info+strlen(host_info)+1;
400
drizzle->server_version= drizzle->host+strlen(host)+1;
401
strcpy(drizzle->host_info,host_info);
402
strcpy(drizzle->host,host);
403
strcpy(drizzle->server_version,(char*) net->read_pos+1);
407
Part 2: format and send client info to the server for access check
410
client_flag|=drizzle->options.client_flag;
411
client_flag|=CLIENT_CAPABILITIES;
412
if (client_flag & CLIENT_MULTI_STATEMENTS)
413
client_flag|= CLIENT_MULTI_RESULTS;
416
client_flag|=CLIENT_CONNECT_WITH_DB;
418
/* Remove options that server doesn't support */
419
client_flag= ((client_flag &
420
~(CLIENT_COMPRESS | CLIENT_SSL)) |
421
(client_flag & drizzle->server_capabilities));
422
client_flag&= ~CLIENT_COMPRESS;
424
int4store(buff, client_flag);
425
int4store(buff+4, net->max_packet_size);
426
buff[8]= (char) 45; // utf8 charset number
427
memset(buff+9, 0, 32-9);
430
drizzle->client_flag=client_flag;
432
/* This needs to be changed as it's not useful with big packets */
434
strncpy(end,user,USERNAME_LENGTH); /* Max user name */
436
read_user_name((char*) end);
438
/* We have to handle different version of handshake here */
439
end= strchr(end, '\0') + 1;
443
*end++= SCRAMBLE_LENGTH;
444
memset(end, 0, SCRAMBLE_LENGTH-1);
445
memcpy(end, passwd, strlen(passwd));
446
end+= SCRAMBLE_LENGTH;
450
*end++= '\0'; /* empty password */
452
/* Add database if needed */
453
if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
455
size_t db_len= strlen(db);
457
if (db_len >= NAME_LEN)
458
db_len= NAME_LEN - 1;
459
end= memcpy(end, db, db_len);
463
drizzle->db= strdup(db);
466
/* Write authentication package */
467
if (drizzleclient_net_write(net, (unsigned char*) buff, (size_t) (end-buff)) || drizzleclient_net_flush(net))
469
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
470
ER(CR_SERVER_LOST_SEND_AUTH),
476
Part 3: Authorization data's been sent. Now server can reply with
477
OK-packet, or re-request scrambled password.
480
if ((pkt_length=drizzleclient_cli_safe_read(drizzle)) == packet_error)
482
if (drizzle->net.last_errno == CR_SERVER_LOST)
483
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
484
ER(CR_SERVER_LOST_READ_AUTH),
489
if (client_flag & CLIENT_COMPRESS) /* We will use compression */
493
if (db && drizzleclient_select_db(drizzle, db))
495
if (drizzle->net.last_errno == CR_SERVER_LOST)
496
drizzleclient_set_extended_error(drizzle, CR_SERVER_LOST, drizzleclient_sqlstate_get_unknown(),
497
ER(CR_SERVER_LOST_SETTING_DB),
507
/* Free alloced memory */
508
drizzleclient_disconnect(drizzle);
509
drizzleclient_close_free(drizzle);
510
if (!(((uint32_t) client_flag) & CLIENT_REMEMBER_OPTIONS))
511
drizzleclient_close_free_options(drizzle);
519
/**************************************************************************
521
**************************************************************************/
524
drizzleclient_select_db(DRIZZLE *drizzle, const char *db)
528
if ((error=simple_command(drizzle,COM_INIT_DB, (const unsigned char*) db,
529
(uint32_t) strlen(db),0)))
531
if (drizzle->db != NULL)
533
drizzle->db=strdup(db);
537
bool drizzleclient_reconnect(DRIZZLE *drizzle)
542
if (!drizzle->reconnect ||
543
(drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
545
/* Allow reconnect next time */
546
drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
547
drizzleclient_set_error(drizzle, CR_SERVER_GONE_ERROR, drizzleclient_sqlstate_get_unknown());
550
drizzleclient_create(&tmp_drizzle);
551
tmp_drizzle.options= drizzle->options;
552
tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
554
if (!drizzleclient_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
555
drizzle->db, drizzle->port, 0,
556
drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
558
drizzle->net.last_errno= tmp_drizzle.net.last_errno;
559
strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
560
strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
564
tmp_drizzle.reconnect= 1;
565
tmp_drizzle.free_me= drizzle->free_me;
567
/* Don't free options as these are now used in tmp_drizzle */
568
memset(&drizzle->options, 0, sizeof(drizzle->options));
570
drizzleclient_close(drizzle);
571
*drizzle=tmp_drizzle;
572
drizzleclient_net_clear(&drizzle->net, 1);
573
drizzle->affected_rows= ~(uint64_t) 0;
577
/**************************************************************************
579
**************************************************************************/
581
void drizzleclient_disconnect(DRIZZLE *drizzle)
583
int save_errno= errno;
584
if (drizzle->net.vio != 0)
586
drizzleclient_vio_delete(drizzle->net.vio);
587
drizzle->net.vio= 0; /* Marker */
589
drizzleclient_net_end(&drizzle->net);
590
drizzleclient_free_old_query(drizzle);
595
/*************************************************************************
596
Send a QUIT to the server and close the connection
597
If handle is alloced by DRIZZLE connect free it.
598
*************************************************************************/
600
void drizzleclient_close_free_options(DRIZZLE *drizzle)
602
if (drizzle->options.user != NULL)
603
free(drizzle->options.user);
604
if (drizzle->options.host != NULL)
605
free(drizzle->options.host);
606
if (drizzle->options.password != NULL)
607
free(drizzle->options.password);
608
if (drizzle->options.db != NULL)
609
free(drizzle->options.db);
610
if (drizzle->options.my_cnf_file != NULL)
611
free(drizzle->options.my_cnf_file);
612
if (drizzle->options.my_cnf_group != NULL)
613
free(drizzle->options.my_cnf_group);
614
if (drizzle->options.client_ip != NULL)
615
free(drizzle->options.client_ip);
616
memset(&drizzle->options, 0, sizeof(drizzle->options));
621
void drizzleclient_close_free(DRIZZLE *drizzle)
623
if (drizzle->host_info != NULL)
624
free((unsigned char*) drizzle->host_info);
625
if (drizzle->user != NULL)
627
if (drizzle->passwd != NULL)
628
free(drizzle->passwd);
629
if (drizzle->db != NULL)
631
if (drizzle->info_buffer != NULL)
632
free(drizzle->info_buffer);
633
drizzle->info_buffer= 0;
635
/* Clear pointers for better safety */
636
drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
640
void drizzleclient_close(DRIZZLE *drizzle)
642
if (drizzle) /* Some simple safety */
644
/* If connection is still up, send a QUIT message */
645
if (drizzle->net.vio != 0)
647
drizzleclient_free_old_query(drizzle);
648
drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
649
drizzle->reconnect=0;
650
simple_command(drizzle,COM_QUIT,(unsigned char*) 0,0,1);
651
drizzleclient_disconnect(drizzle); /* Sets drizzle->net.vio= 0 */
653
drizzleclient_close_free_options(drizzle);
654
drizzleclient_close_free(drizzle);
655
if (drizzle->free_me)
656
free((unsigned char*) drizzle);
662
bool drizzleclient_cli_read_query_result(DRIZZLE *drizzle)
665
uint32_t field_count;
666
DRIZZLE_DATA *fields;
669
if ((length = drizzleclient_cli_safe_read(drizzle)) == packet_error)
671
drizzleclient_free_old_query(drizzle); /* Free old result */
673
pos=(unsigned char*) drizzle->net.read_pos;
674
if ((field_count= drizzleclient_net_field_length(&pos)) == 0)
676
drizzle->affected_rows= drizzleclient_drizzleclient_net_field_length_ll(&pos);
677
drizzle->insert_id= drizzleclient_drizzleclient_net_field_length_ll(&pos);
679
drizzle->server_status= uint2korr(pos); pos+=2;
680
drizzle->warning_count= uint2korr(pos); pos+=2;
682
if (pos < drizzle->net.read_pos+length && drizzleclient_net_field_length(&pos))
683
drizzle->info=(char*) pos;
686
if (field_count == NULL_LENGTH) /* LOAD DATA LOCAL INFILE */
690
if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES))
692
drizzleclient_set_error(drizzle, CR_MALFORMED_PACKET, drizzleclient_sqlstate_get_unknown());
696
error= drizzleclient_handle_local_infile(drizzle,(char*) pos);
697
if ((length= drizzleclient_cli_safe_read(drizzle)) == packet_error || error)
699
goto get_info; /* Get info packet */
701
if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
702
drizzle->server_status|= SERVER_STATUS_IN_TRANS;
704
if (!(fields=drizzleclient_cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, 7)))
706
if (!(drizzle->fields= drizzleclient_unpack_fields(fields, (uint32_t) field_count, 0)))
708
drizzle->status= DRIZZLE_STATUS_GET_RESULT;
709
drizzle->field_count= (uint32_t) field_count;
715
Send the query and return so we can do something else.
716
Needs to be followed by drizzleclient_read_query_result() when we want to
717
finish processing it.
721
drizzleclient_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
723
return(simple_command(drizzle, COM_QUERY, (unsigned char*) query, length, 1));
728
drizzleclient_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
730
if (drizzleclient_send_query(drizzle,query,length))
732
return((int) (*drizzle->methods->read_query_result)(drizzle));
736
/**************************************************************************
737
Alloc result struct for buffered results. All rows are read to buffer.
738
drizzleclient_data_seek may be used.
739
**************************************************************************/
741
DRIZZLE_RES * drizzleclient_store_result(DRIZZLE *drizzle)
745
if (!drizzle->fields)
747
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
749
drizzleclient_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, drizzleclient_sqlstate_get_unknown());
752
drizzle->status=DRIZZLE_STATUS_READY; /* server is ready */
753
if (!(result=(DRIZZLE_RES*) malloc((uint32_t) (sizeof(DRIZZLE_RES)+
755
drizzle->field_count))))
757
drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
760
memset(result, 0,(sizeof(DRIZZLE_RES)+ sizeof(uint32_t) *
761
drizzle->field_count));
762
result->methods= drizzle->methods;
763
result->eof= 1; /* Marker for buffered */
764
result->lengths= (uint32_t*) (result+1);
766
(*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
768
free((unsigned char*) result);
771
drizzle->affected_rows= result->row_count= result->data->rows;
772
result->data_cursor= result->data->data;
773
result->fields= drizzle->fields;
774
result->field_count= drizzle->field_count;
775
/* The rest of result members is zeroed in malloc */
776
drizzle->fields=0; /* fields is now in result */
777
/* just in case this was mistakenly called after drizzle_stmt_execute() */
778
drizzle->unbuffered_fetch_owner= 0;
779
return(result); /* Data fetched */
783
/**************************************************************************
784
Alloc struct for use with unbuffered reads. Data is fetched by domand
785
when calling to drizzleclient_fetch_row.
786
DRIZZLE_DATA_seek is a noop.
788
No other queries may be specified with the same DRIZZLE handle.
789
There shouldn't be much processing per row because DRIZZLE server shouldn't
790
have to wait for the client (and will not wait more than 30 sec/packet).
791
**************************************************************************/
793
DRIZZLE_RES * drizzleclient_cli_use_result(DRIZZLE *drizzle)
797
if (!drizzle->fields)
799
if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
801
drizzleclient_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, drizzleclient_sqlstate_get_unknown());
804
if (!(result=(DRIZZLE_RES*) malloc(sizeof(*result)+
805
sizeof(uint32_t)*drizzle->field_count)))
807
memset(result, 0, sizeof(*result)+ sizeof(uint32_t)*drizzle->field_count);
808
result->lengths=(uint32_t*) (result+1);
809
result->methods= drizzle->methods;
810
if (!(result->row=(DRIZZLE_ROW)
811
malloc(sizeof(result->row[0])*(drizzle->field_count+1))))
812
{ /* Ptrs: to one row */
813
free((unsigned char*) result);
816
result->fields= drizzle->fields;
817
result->field_count= drizzle->field_count;
818
result->current_field=0;
819
result->handle= drizzle;
820
result->current_row= 0;
821
drizzle->fields=0; /* fields is now in result */
822
drizzle->status=DRIZZLE_STATUS_USE_RESULT;
823
drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
824
return(result); /* Data is read to be fetched */
830
Set the internal error message to DRIZZLE handler
832
@param drizzle connection handle (client side)
833
@param errcode CR_ error code, passed to ER macro to get
835
@parma sqlstate SQL standard sqlstate
838
void drizzleclient_set_error(DRIZZLE *drizzle, int errcode, const char *sqlstate)
841
assert(drizzle != 0);
846
net->last_errno= errcode;
847
strcpy(net->last_error, ER(errcode));
848
strcpy(net->sqlstate, sqlstate);
852
drizzle_server_last_errno= errcode;
853
strcpy(drizzle_server_last_error, ER(errcode));
859
unsigned int drizzleclient_errno(const DRIZZLE *drizzle)
861
return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno;
865
const char * drizzleclient_error(const DRIZZLE *drizzle)
867
return drizzle ? _(drizzle->net.last_error) : _(drizzle_server_last_error);
871
Set an error message on the client.
873
@param drizzle connection handle
874
@param errcode CR_* errcode, for client errors
875
@param sqlstate SQL standard sql state, drizzleclient_sqlstate_get_unknown() for the
876
majority of client errors.
877
@param format error message template, in sprintf format
878
@param ... variable number of arguments
881
void drizzleclient_set_extended_error(DRIZZLE *drizzle, int errcode,
882
const char *sqlstate,
883
const char *format, ...)
887
assert(drizzle != 0);
890
net->last_errno= errcode;
891
va_start(args, format);
892
vsnprintf(net->last_error, sizeof(net->last_error)-1,
895
strcpy(net->sqlstate, sqlstate);
903
Flush result set sent from server
906
void drizzleclient_cli_flush_use_result(DRIZZLE *drizzle)
908
/* Clear the current execution status */
912
if ((pkt_len=drizzleclient_cli_safe_read(drizzle)) == packet_error)
914
if (pkt_len <= 8 && drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
916
char *pos= (char*) drizzle->net.read_pos + 1;
917
drizzle->warning_count=uint2korr(pos); pos+=2;
918
drizzle->server_status=uint2korr(pos); pos+=2;
920
break; /* End of data */
926
/**************************************************************************
927
Get column lengths of the current row
928
If one uses drizzleclient_use_result, res->lengths contains the length information,
929
else the lengths are calculated from the offset between pointers.
930
**************************************************************************/
932
void drizzleclient_cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count)
934
uint32_t *prev_length;
938
prev_length=0; /* Keep gcc happy */
939
for (end=column + field_count + 1 ; column != end ; column++, to++)
946
if (start) /* Found end of prev string */
947
*prev_length= (uint32_t) (*column-start-1);