1
/* Copyright (C) 2000-2004 DRIZZLE AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation.
7
There are special exceptions to the terms and conditions of the GPL as it
8
is applied to this software. View the full text of the exception in file
9
EXCEPTIONS-CLIENT in the directory of this software distribution.
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
GNU General Public License for more details.
16
You should have received a copy of the GNU General Public License
17
along with this program; if not, write to the Free Software
18
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
20
#include <drizzled/global.h>
21
#include <mysys/my_sys.h>
31
#include <sys/socket.h>
32
#include <netinet/in.h>
33
#include <arpa/inet.h>
38
#ifdef HAVE_SYS_SELECT_H
39
#include <sys/select.h>
49
#define INADDR_NONE -1
52
#include <sql_common.h>
53
#include "client_settings.h"
54
#include <drizzled/version.h>
56
#undef net_buffer_length
57
#undef max_allowed_packet
59
uint32_t net_buffer_length= 8192;
60
uint32_t max_allowed_packet= 1024L*1024L*1024L;
63
#define SOCKET_ERROR -1
66
If allowed through some configuration, then this needs to
69
#define MAX_LONG_DATA_LENGTH 8192
70
#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
73
static DRIZZLE_PARAMETERS drizzle_internal_parameters=
74
{&max_allowed_packet, &net_buffer_length, 0};
76
const DRIZZLE_PARAMETERS * drizzle_get_parameters(void)
78
return &drizzle_internal_parameters;
81
bool drizzle_thread_init()
83
return my_thread_init();
86
void drizzle_thread_end()
93
Expand wildcard to a sql string
97
append_wild(char *to, char *end, const char *wild)
99
end-=5; /* Some extra */
102
to= strcpy(to," like '");
103
to+= 7; /* strlen(" like '"); */
105
while (*wild && to < end)
107
if (*wild == '\\' || *wild == '\'')
111
if (*wild) /* Too small buffer */
112
*to++='%'; /* Nicer this way */
118
/**************************************************************************
119
Ignore SIGPIPE handler
121
**************************************************************************/
124
my_pipe_sig_handler(int sig __attribute__((unused)))
126
#ifdef DONT_REMEMBER_SIGNAL
127
(void) signal(SIGPIPE, my_pipe_sig_handler);
132
/**************************************************************************
133
Change user and database
134
**************************************************************************/
136
int cli_read_change_user_result(DRIZZLE *drizzle)
140
pkt_length= cli_safe_read(drizzle);
142
if (pkt_length == packet_error)
148
bool drizzle_change_user(DRIZZLE *drizzle, const char *user,
149
const char *passwd, const char *db)
151
char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
154
const CHARSET_INFO *saved_cs= drizzle->charset;
156
/* Get the connection-default character set. */
158
if (drizzle_init_character_set(drizzle))
160
drizzle->charset= saved_cs;
164
/* Use an empty string instead of NULL. */
171
/* Store user into the buffer */
172
end= strncpy(end, user, USERNAME_LENGTH) + USERNAME_LENGTH + 1;
174
/* write scrambled password according to server capabilities */
178
*end++= SCRAMBLE_LENGTH;
179
end+= SCRAMBLE_LENGTH;
183
*end++= '\0'; /* empty password */
184
/* Add database if needed */
185
end= strncpy(end, db ? db : "", NAME_LEN) + NAME_LEN + 1;
187
/* Add character set number. */
189
if (drizzle->server_capabilities & CLIENT_SECURE_CONNECTION)
191
int2store(end, (ushort) drizzle->charset->number);
195
/* Write authentication package */
196
(void)simple_command(drizzle,COM_CHANGE_USER, (uchar*) buff, (uint32_t) (end-buff), 1);
198
rc= (*drizzle->methods->read_change_user_result)(drizzle);
202
/* Free old connect information */
206
free(drizzle->passwd);
210
/* alloc new connect information */
211
drizzle->user= strdup(user);
212
drizzle->passwd= strdup(passwd);
213
drizzle->db= db ? strdup(db) : 0;
217
drizzle->charset= saved_cs;
223
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
224
struct passwd *getpwuid(uid_t);
225
char* getlogin(void);
228
/**************************************************************************
229
Do a query. If query returned rows, free old rows.
230
Read data by drizzle_store_result or by repeat call of drizzle_fetch_row
231
**************************************************************************/
234
drizzle_query(DRIZZLE *drizzle, const char *query)
236
return drizzle_real_query(drizzle,query, (uint) strlen(query));
240
/**************************************************************************
241
Return next field of the query results
242
**************************************************************************/
245
drizzle_fetch_field(DRIZZLE_RES *result)
247
if (result->current_field >= result->field_count)
249
return &result->fields[result->current_field++];
253
/**************************************************************************
254
Move to a specific row and column
255
**************************************************************************/
258
drizzle_data_seek(DRIZZLE_RES *result, uint64_t row)
262
for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
263
result->current_row=0;
264
result->data_cursor = tmp;
268
/*************************************************************************
269
put the row or field cursor one a position one got from DRIZZLE_ROW_tell()
270
This doesn't restore any data. The next drizzle_fetch_row or
271
drizzle_fetch_field will return the next row or field after the last used
272
*************************************************************************/
275
drizzle_row_seek(DRIZZLE_RES *result, DRIZZLE_ROW_OFFSET row)
277
DRIZZLE_ROW_OFFSET return_value=result->data_cursor;
278
result->current_row= 0;
279
result->data_cursor= row;
285
drizzle_field_seek(DRIZZLE_RES *result, DRIZZLE_FIELD_OFFSET field_offset)
287
DRIZZLE_FIELD_OFFSET return_value=result->current_field;
288
result->current_field=field_offset;
293
/*****************************************************************************
294
List all tables in a database
295
If wild is given then only the tables matching wild is returned
296
*****************************************************************************/
299
drizzle_list_tables(DRIZZLE *drizzle, const char *wild)
302
char *ptr= strcpy(buff, "show tables");
303
ptr+= 11; /* strlen("show tables"); */
305
append_wild(ptr,buff+sizeof(buff),wild);
306
if (drizzle_query(drizzle,buff))
308
return (drizzle_store_result(drizzle));
312
DRIZZLE_FIELD *cli_list_fields(DRIZZLE *drizzle)
315
if (!(query= cli_read_rows(drizzle,(DRIZZLE_FIELD*) 0, 8)))
318
drizzle->field_count= (uint) query->rows;
319
return unpack_fields(query,&drizzle->field_alloc, drizzle->field_count, 1);
323
/**************************************************************************
324
List all fields in a table
325
If wild is given then only the fields matching wild is returned
326
Instead of this use query:
327
show fields in 'table' like "wild"
328
**************************************************************************/
331
drizzle_list_fields(DRIZZLE *drizzle, const char *table, const char *wild)
334
DRIZZLE_FIELD *fields;
335
char buff[257], *end;
337
end= strncpy(buff, table, 128) + 128;
338
end= strncpy(end+1, wild ? wild : "", 128) + 128;
340
free_old_query(drizzle);
341
if (simple_command(drizzle, COM_FIELD_LIST, (uchar*) buff,
342
(uint32_t) (end-buff), 1) ||
343
!(fields= (*drizzle->methods->list_fields)(drizzle)))
346
if (!(result = (DRIZZLE_RES *) malloc(sizeof(DRIZZLE_RES))))
349
memset(result, 0, sizeof(DRIZZLE_RES));
351
result->methods= drizzle->methods;
352
result->field_alloc=drizzle->field_alloc;
354
result->field_count = drizzle->field_count;
355
result->fields= fields;
360
/* List all running processes (threads) in server */
363
drizzle_list_processes(DRIZZLE *drizzle)
365
DRIZZLE_DATA *fields;
369
if (simple_command(drizzle,COM_PROCESS_INFO,0,0,0))
371
free_old_query(drizzle);
372
pos=(uchar*) drizzle->net.read_pos;
373
field_count=(uint) net_field_length(&pos);
374
if (!(fields = (*drizzle->methods->read_rows)(drizzle,(DRIZZLE_FIELD*) 0, 7)))
376
if (!(drizzle->fields=unpack_fields(fields,&drizzle->field_alloc,field_count,0)))
378
drizzle->status=DRIZZLE_STATUS_GET_RESULT;
379
drizzle->field_count=field_count;
380
return(drizzle_store_result(drizzle));
385
drizzle_shutdown(DRIZZLE *drizzle, enum drizzle_enum_shutdown_level shutdown_level)
388
level[0]= (uchar) shutdown_level;
389
return(simple_command(drizzle, COM_SHUTDOWN, level, 1, 0));
394
drizzle_refresh(DRIZZLE *drizzle,uint options)
397
bits[0]= (uchar) options;
398
return(simple_command(drizzle, COM_REFRESH, bits, 1, 0));
403
drizzle_kill(DRIZZLE *drizzle, uint32_t pid)
407
return(simple_command(drizzle,COM_PROCESS_KILL,buff,sizeof(buff),0));
412
drizzle_set_server_option(DRIZZLE *drizzle, enum enum_drizzle_set_option option)
415
int2store(buff, (uint) option);
416
return(simple_command(drizzle, COM_SET_OPTION, buff, sizeof(buff), 0));
420
const char *cli_read_statistics(DRIZZLE *drizzle)
422
drizzle->net.read_pos[drizzle->packet_length]=0; /* End of stat string */
423
if (!drizzle->net.read_pos[0])
425
set_drizzle_error(drizzle, CR_WRONG_HOST_INFO, unknown_sqlstate);
426
return drizzle->net.last_error;
428
return (char*) drizzle->net.read_pos;
433
drizzle_ping(DRIZZLE *drizzle)
436
res= simple_command(drizzle,COM_PING,0,0,0);
437
if (res == CR_SERVER_LOST && drizzle->reconnect)
438
res= simple_command(drizzle,COM_PING,0,0,0);
444
drizzle_get_server_info(const DRIZZLE *drizzle)
446
return((char*) drizzle->server_version);
451
drizzle_get_host_info(const DRIZZLE *drizzle)
453
return(drizzle->host_info);
458
drizzle_get_proto_info(const DRIZZLE *drizzle)
460
return (drizzle->protocol_version);
464
drizzle_get_client_info(void)
466
return (char*) DRIZZLE_SERVER_VERSION;
469
uint32_t drizzle_get_client_version(void)
471
return DRIZZLE_VERSION_ID;
474
bool drizzle_eof(const DRIZZLE_RES *res)
479
const DRIZZLE_FIELD * drizzle_fetch_field_direct(const DRIZZLE_RES *res, unsigned int fieldnr)
481
return &(res)->fields[fieldnr];
484
const DRIZZLE_FIELD * drizzle_fetch_fields(const DRIZZLE_RES *res)
489
DRIZZLE_ROW_OFFSET drizzle_row_tell(const DRIZZLE_RES *res)
491
return res->data_cursor;
494
DRIZZLE_FIELD_OFFSET drizzle_field_tell(const DRIZZLE_RES *res)
496
return res->current_field;
501
unsigned int drizzle_field_count(const DRIZZLE *drizzle)
503
return drizzle->field_count;
506
uint64_t drizzle_affected_rows(const DRIZZLE *drizzle)
508
return drizzle->affected_rows;
511
uint64_t drizzle_insert_id(const DRIZZLE *drizzle)
513
return drizzle->insert_id;
516
const char * drizzle_sqlstate(const DRIZZLE *drizzle)
518
return drizzle ? drizzle->net.sqlstate : cant_connect_sqlstate;
521
uint32_t drizzle_warning_count(const DRIZZLE *drizzle)
523
return drizzle->warning_count;
526
const char * drizzle_info(const DRIZZLE *drizzle)
528
return drizzle->info;
531
uint32_t drizzle_thread_id(const DRIZZLE *drizzle)
533
return drizzle->thread_id;
536
const char * drizzle_character_set_name(const DRIZZLE *drizzle)
538
return drizzle->charset->csname;
541
void drizzle_get_character_set_info(const DRIZZLE *drizzle, MY_CHARSET_INFO *csinfo)
543
csinfo->number = drizzle->charset->number;
544
csinfo->state = drizzle->charset->state;
545
csinfo->csname = drizzle->charset->csname;
546
csinfo->name = drizzle->charset->name;
547
csinfo->comment = drizzle->charset->comment;
548
csinfo->mbminlen = drizzle->charset->mbminlen;
549
csinfo->mbmaxlen = drizzle->charset->mbmaxlen;
551
if (drizzle->options.charset_dir)
552
csinfo->dir = drizzle->options.charset_dir;
554
csinfo->dir = charsets_dir;
557
uint drizzle_thread_safe(void)
563
bool drizzle_embedded(void)
568
/****************************************************************************
569
Some support functions
570
****************************************************************************/
573
Functions called my my_net_init() to set some application specific variables
576
void my_net_local_init(NET *net)
578
net->max_packet= (uint) net_buffer_length;
579
my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
580
my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
582
net->max_packet_size= max(net_buffer_length, max_allowed_packet);
586
This function is used to create HEX string that you
587
can use in a SQL statement in of the either ways:
588
INSERT INTO blob_column VALUES (0xAABBCC); (any DRIZZLE version)
589
INSERT INTO blob_column VALUES (X'AABBCC');
591
The string in "from" is encoded to a HEX string.
592
The result is placed in "to" and a terminating null byte is appended.
594
The string pointed to by "from" must be "length" bytes long.
595
You must allocate the "to" buffer to be at least length*2+1 bytes long.
596
Each character needs two bytes, and you need room for the terminating
597
null byte. When drizzle_hex_string() returns, the contents of "to" will
598
be a null-terminated string. The return value is the length of the
599
encoded string, not including the terminating null character.
601
The return value does not contain any leading 0x or a leading X' and
602
trailing '. The caller must supply whichever of those is desired.
606
drizzle_hex_string(char *to, const char *from, uint32_t length)
611
for (end= from + length; from < end; from++)
613
*to++= _dig_vec_upper[((unsigned char) *from) >> 4];
614
*to++= _dig_vec_upper[((unsigned char) *from) & 0x0F];
617
return (uint32_t) (to-to0);
621
Add escape characters to a string (blob?) to make it suitable for a insert
622
to should at least have place for length*2+1 chars
623
Returns the length of the to string
627
drizzle_escape_string(char *to,const char *from, uint32_t length)
629
return escape_string_for_drizzle(default_charset_info, to, 0, from, length);
633
drizzle_real_escape_string(DRIZZLE *drizzle, char *to,const char *from,
636
if (drizzle->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
637
return escape_quotes_for_drizzle(drizzle->charset, to, 0, from, length);
638
return escape_string_for_drizzle(drizzle->charset, to, 0, from, length);
642
myodbc_remove_escape(const DRIZZLE *drizzle, char *name)
646
bool use_mb_flag= use_mb(drizzle->charset);
649
for (end=name; *end ; end++) ;
652
for (to=name ; *name ; name++)
656
if (use_mb_flag && (l = my_ismbchar( drizzle->charset, name , end ) ) )
664
if (*name == '\\' && name[1])
671
int cli_unbuffered_fetch(DRIZZLE *drizzle, char **row)
673
if (packet_error == cli_safe_read(drizzle))
676
*row= ((drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA) ? NULL :
677
(char*) (drizzle->net.read_pos+1));
681
/********************************************************************
683
*********************************************************************/
686
Commit the current transaction
689
bool drizzle_commit(DRIZZLE *drizzle)
691
return((bool) drizzle_real_query(drizzle, "commit", 6));
695
Rollback the current transaction
698
bool drizzle_rollback(DRIZZLE *drizzle)
700
return((bool) drizzle_real_query(drizzle, "rollback", 8));
705
Set autocommit to either true or false
708
bool drizzle_autocommit(DRIZZLE *drizzle, bool auto_mode)
710
return((bool) drizzle_real_query(drizzle, auto_mode ?
711
"set autocommit=1":"set autocommit=0",
716
/********************************************************************
717
Multi query execution + SPs APIs
718
*********************************************************************/
721
Returns true/false to indicate whether any more query results exist
722
to be read using drizzle_next_result()
725
bool drizzle_more_results(const DRIZZLE *drizzle)
727
return (drizzle->server_status & SERVER_MORE_RESULTS_EXISTS) ? true:false;
732
Reads and returns the next query results
734
int drizzle_next_result(DRIZZLE *drizzle)
736
if (drizzle->status != DRIZZLE_STATUS_READY)
738
set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
742
net_clear_error(&drizzle->net);
743
drizzle->affected_rows= ~(uint64_t) 0;
745
if (drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
746
return((*drizzle->methods->next_result)(drizzle));
748
return(-1); /* No more results */
752
DRIZZLE_RES * drizzle_use_result(DRIZZLE *drizzle)
754
return (*drizzle->methods->use_result)(drizzle);
757
bool drizzle_read_query_result(DRIZZLE *drizzle)
759
return (*drizzle->methods->read_query_result)(drizzle);