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
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; either version 2 of the License, or
9
* (at your option) any later version.
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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1
/* Copyright (C) 2008 Drizzle Open Source Project
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; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
23
17
This file is included by both libdrizzle.c (the DRIZZLE client C API)
515
501
free_rows(result->data);
516
/* TODO: free result->fields */
503
free_root(&result->field_alloc,MYF(0));
518
free((uchar*) result->row);
519
free((uchar*) result);
505
my_free((uchar*) result->row,MYF(0));
506
my_free((uchar*) result,MYF(0));
510
/****************************************************************************
511
Get options from my.cnf
512
****************************************************************************/
514
static const char *default_options[]=
516
"port","socket","compress","password","pipe", "timeout", "user",
517
"init-command", "host", "database", "return-found-rows",
518
"ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
519
"character-sets-dir", "default-character-set", "interactive-timeout",
520
"connect-timeout", "local-infile", "disable-local-infile",
521
"ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
522
"multi-results", "multi-statements", "multi-queries", "secure-auth",
523
"report-data-truncation",
527
static TYPELIB option_types={array_elements(default_options)-1,
528
"options",default_options, NULL};
530
const char *sql_protocol_names_lib[] =
531
{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
532
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
533
sql_protocol_names_lib, NULL};
535
static int add_init_command(struct st_drizzle_options *options, const char *cmd)
539
if (!options->init_commands)
541
options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
543
init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
546
if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
547
insert_dynamic(options->init_commands, (uchar*)&tmp))
549
my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
556
void drizzle_read_default_options(struct st_drizzle_options *options,
557
const char *filename,const char *group)
560
char *argv_buff[1],**argv;
561
const char *groups[3];
563
argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
564
groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
566
load_defaults(filename, groups, &argc, &argv);
567
if (argc != 1) /* If some default option */
572
if (option[0][0] == '-' && option[0][1] == '-')
574
char *end=strrchr(*option,'=');
579
*end=0; /* Remove '=' */
581
/* Change all '_' in variable name to '-' */
582
for (end= *option ; *(end= strrchr(end,'_')) ; )
584
switch (find_type(*option+2,&option_types,2)) {
587
options->port=atoi(opt_arg);
592
my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
593
options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
596
case 3: /* compress */
598
options->client_flag|= CLIENT_COMPRESS;
600
case 4: /* password */
603
my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
604
options->password=my_strdup(opt_arg,MYF(MY_WME));
607
case 20: /* connect_timeout */
608
case 6: /* timeout */
610
options->connect_timeout=atoi(opt_arg);
615
my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
616
options->user=my_strdup(opt_arg,MYF(MY_WME));
619
case 8: /* init-command */
620
add_init_command(options,opt_arg);
625
my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
626
options->host=my_strdup(opt_arg,MYF(MY_WME));
629
case 10: /* database */
632
my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
633
options->db=my_strdup(opt_arg,MYF(MY_WME));
636
case 12: /* return-found-rows */
637
options->client_flag|=CLIENT_FOUND_ROWS;
639
case 13: /* Ignore SSL options */
645
case 17: /* charset-lib */
646
my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
647
options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
650
my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
651
options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
653
case 19: /* Interactive-timeout */
654
options->client_flag|= CLIENT_INTERACTIVE;
657
if (!opt_arg || atoi(opt_arg) != 0)
658
options->client_flag|= CLIENT_LOCAL_FILES;
660
options->client_flag&= ~CLIENT_LOCAL_FILES;
663
options->client_flag&= ~CLIENT_LOCAL_FILES;
665
case 24: /* max-allowed-packet */
667
options->max_allowed_packet= atoi(opt_arg);
669
case 25: /* protocol */
670
if ((options->protocol= find_type(opt_arg,
671
&sql_protocol_typelib,0)) <= 0)
673
fprintf(stderr, _("Unknown option to protocol: %s\n"), opt_arg);
677
case 27: /* multi-results */
678
options->client_flag|= CLIENT_MULTI_RESULTS;
680
case 28: /* multi-statements */
681
case 29: /* multi-queries */
682
options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
684
case 30: /* secure-auth */
685
options->secure_auth= true;
687
case 31: /* report-data-truncation */
688
options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
574
752
/* fields count may be wrong */
575
753
assert((uint) (field - result) < fields);
576
754
cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
577
field->catalog= strdup((char*) row->data[0]);
578
field->db= strdup((char*) row->data[1]);
579
field->table= strdup((char*) row->data[2]);
580
field->org_table= strdup((char*) row->data[3]);
581
field->name= strdup((char*) row->data[4]);
582
field->org_name= strdup((char*) row->data[5]);
755
field->catalog= strmake_root(alloc,(char*) row->data[0], lengths[0]);
756
field->db= strmake_root(alloc,(char*) row->data[1], lengths[1]);
757
field->table= strmake_root(alloc,(char*) row->data[2], lengths[2]);
758
field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
759
field->name= strmake_root(alloc,(char*) row->data[4], lengths[4]);
760
field->org_name= strmake_root(alloc,(char*) row->data[5], lengths[5]);
584
762
field->catalog_length= lengths[0];
585
763
field->db_length= lengths[1];
894
1107
cli_read_rows, /* read_rows */
895
1108
cli_use_result, /* use_result */
896
1109
cli_fetch_lengths, /* fetch_lengths */
897
cli_flush_use_result, /* flush_use_result */
898
cli_list_fields, /* list_fields */
1110
cli_flush_use_result, /* flush_use_result */
1111
#ifndef DRIZZLE_SERVER
1112
cli_list_fields, /* list_fields */
899
1113
cli_unbuffered_fetch, /* unbuffered_fetch */
900
1114
cli_read_statistics, /* read_statistics */
901
1115
cli_read_query_result, /* next_result */
902
1116
cli_read_change_user_result, /* read_change_user_result */
1123
int drizzle_init_character_set(DRIZZLE *drizzle)
1125
const char *default_collation_name;
1127
/* Set character set */
1128
if (!drizzle->options.charset_name)
1130
default_collation_name= DRIZZLE_DEFAULT_COLLATION_NAME;
1131
if (!(drizzle->options.charset_name=
1132
my_strdup(DRIZZLE_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
1136
default_collation_name= NULL;
1139
const char *save= charsets_dir;
1140
if (drizzle->options.charset_dir)
1141
charsets_dir=drizzle->options.charset_dir;
1142
drizzle->charset=get_charset_by_csname(drizzle->options.charset_name,
1143
MY_CS_PRIMARY, MYF(MY_WME));
1144
if (drizzle->charset && default_collation_name)
1146
const CHARSET_INFO *collation;
1148
get_charset_by_name(default_collation_name, MYF(MY_WME))))
1150
if (!my_charset_same(drizzle->charset, collation))
1152
my_printf_error(ER_UNKNOWN_ERROR,
1153
_("COLLATION %s is not valid for CHARACTER SET %s"),
1155
default_collation_name, drizzle->options.charset_name);
1156
drizzle->charset= NULL;
1160
drizzle->charset= collation;
1164
drizzle->charset= NULL;
1169
if (!drizzle->charset)
1171
if (drizzle->options.charset_dir)
1172
set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
1173
ER(CR_CANT_READ_CHARSET),
1174
drizzle->options.charset_name,
1175
drizzle->options.charset_dir);
1178
char cs_dir_name[FN_REFLEN];
1179
get_charsets_dir(cs_dir_name);
1180
set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
1181
ER(CR_CANT_READ_CHARSET),
1182
drizzle->options.charset_name,
907
1193
CLI_DRIZZLE_CONNECT(DRIZZLE *drizzle,const char *host, const char *user,
908
const char *passwd, const char *db,
910
const char * unix_port __attribute__((__unused__)),
911
uint32_t client_flag)
1194
const char *passwd, const char *db,
1195
uint32_t port, const char *unix_socket, uint32_t client_flag)
913
1197
char buff[NAME_LEN+USERNAME_LENGTH+100];
914
1198
char *end,*host_info=NULL;
915
1199
uint32_t pkt_length;
916
1200
NET *net= &drizzle->net;
1201
init_sigpipe_variables
1203
/* Don't give sigpipe errors if the client doesn't want them */
1204
set_sigpipe(drizzle);
918
1205
drizzle->methods= &client_methods;
919
1206
net->vio = 0; /* If something goes wrong */
920
1207
drizzle->client_flag=0; /* For handshake */
1209
/* use default options */
1210
if (drizzle->options.my_cnf_file || drizzle->options.my_cnf_group)
1212
drizzle_read_default_options(&drizzle->options,
1213
(drizzle->options.my_cnf_file ?
1214
drizzle->options.my_cnf_file : "my"),
1215
drizzle->options.my_cnf_group);
1216
my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1217
my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1218
drizzle->options.my_cnf_file=drizzle->options.my_cnf_group=0;
922
1221
/* Some empty-string-tests are done because of ODBC */
923
1222
if (!host || !host[0])
924
1223
host=drizzle->options.host;
1399
if (drizzle_init_character_set(drizzle))
1094
1402
/* Save connection information */
1095
if (!(drizzle->host_info= (char *)malloc(strlen(host_info)+1+strlen(host)+1
1096
+(end - (char*) net->read_pos))) ||
1097
!(drizzle->user=strdup(user)) ||
1098
!(drizzle->passwd=strdup(passwd)))
1403
if (!my_multi_malloc(MYF(0),
1404
&drizzle->host_info, (uint) strlen(host_info)+1,
1405
&drizzle->host, (uint) strlen(host)+1,
1406
&drizzle->unix_socket,unix_socket ?
1407
(uint) strlen(unix_socket)+1 : (uint) 1,
1408
&drizzle->server_version,
1409
(uint) (end - (char*) net->read_pos),
1411
!(drizzle->user=my_strdup(user,MYF(0))) ||
1412
!(drizzle->passwd=my_strdup(passwd,MYF(0))))
1100
1414
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1103
drizzle->host= drizzle->host_info+strlen(host_info)+1;
1104
drizzle->server_version= drizzle->host+strlen(host)+1;
1105
1417
strcpy(drizzle->host_info,host_info);
1106
1418
strcpy(drizzle->host,host);
1420
strcpy(drizzle->unix_socket,unix_socket);
1422
drizzle->unix_socket=0;
1107
1423
strcpy(drizzle->server_version,(char*) net->read_pos+1);
1108
1424
drizzle->port=port;
1111
1427
Part 2: format and send client info to the server for access check
1114
1430
client_flag|=drizzle->options.client_flag;
1115
1431
client_flag|=CLIENT_CAPABILITIES;
1116
1432
if (client_flag & CLIENT_MULTI_STATEMENTS)
1279
1628
static void drizzle_close_free_options(DRIZZLE *drizzle)
1281
if (drizzle->options.user != NULL)
1282
free(drizzle->options.user);
1283
if (drizzle->options.host != NULL)
1284
free(drizzle->options.host);
1285
if (drizzle->options.password != NULL)
1286
free(drizzle->options.password);
1287
if (drizzle->options.db != NULL)
1288
free(drizzle->options.db);
1289
if (drizzle->options.my_cnf_file != NULL)
1290
free(drizzle->options.my_cnf_file);
1291
if (drizzle->options.my_cnf_group != NULL)
1292
free(drizzle->options.my_cnf_group);
1293
if (drizzle->options.client_ip != NULL)
1294
free(drizzle->options.client_ip);
1630
my_free(drizzle->options.user,MYF(MY_ALLOW_ZERO_PTR));
1631
my_free(drizzle->options.host,MYF(MY_ALLOW_ZERO_PTR));
1632
my_free(drizzle->options.password,MYF(MY_ALLOW_ZERO_PTR));
1633
my_free(drizzle->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
1634
my_free(drizzle->options.db,MYF(MY_ALLOW_ZERO_PTR));
1635
my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1636
my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1637
my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
1638
my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
1639
my_free(drizzle->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
1640
if (drizzle->options.init_commands)
1642
DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
1643
char **ptr= (char**)init_commands->buffer;
1644
char **end= ptr + init_commands->elements;
1645
for (; ptr<end; ptr++)
1646
my_free(*ptr,MYF(MY_WME));
1647
delete_dynamic(init_commands);
1648
my_free((char*)init_commands,MYF(MY_WME));
1295
1650
memset(&drizzle->options, 0, sizeof(drizzle->options));
1431
1786
drizzle->status=DRIZZLE_STATUS_READY; /* server is ready */
1432
if (!(result=(DRIZZLE_RES*) malloc((uint) (sizeof(DRIZZLE_RES)+
1787
if (!(result=(DRIZZLE_RES*) my_malloc((uint) (sizeof(DRIZZLE_RES)+
1433
1788
sizeof(uint32_t) *
1434
drizzle->field_count))))
1789
drizzle->field_count),
1790
MYF(MY_WME | MY_ZEROFILL))))
1436
1792
set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1439
memset(result, 0,(sizeof(DRIZZLE_RES)+ sizeof(uint32_t) *
1440
drizzle->field_count));
1441
1795
result->methods= drizzle->methods;
1442
1796
result->eof= 1; /* Marker for buffered */
1443
1797
result->lengths= (uint32_t*) (result+1);
1444
1798
if (!(result->data=
1445
1799
(*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
1447
free((uchar*) result);
1801
my_free((uchar*) result,MYF(0));
1450
1804
drizzle->affected_rows= result->row_count= result->data->rows;
1451
1805
result->data_cursor= result->data->data;
1452
1806
result->fields= drizzle->fields;
1807
result->field_alloc= drizzle->field_alloc;
1453
1808
result->field_count= drizzle->field_count;
1454
1809
/* The rest of result members is zeroed in malloc */
1455
1810
drizzle->fields=0; /* fields is now in result */
1811
clear_alloc_root(&drizzle->field_alloc);
1456
1812
/* just in case this was mistakenly called after drizzle_stmt_execute() */
1457
1813
drizzle->unbuffered_fetch_owner= 0;
1458
1814
return(result); /* Data fetched */
1480
1836
set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
1483
if (!(result=(DRIZZLE_RES*) malloc(sizeof(*result)+
1484
sizeof(uint32_t)*drizzle->field_count)))
1839
if (!(result=(DRIZZLE_RES*) my_malloc(sizeof(*result)+
1840
sizeof(uint32_t)*drizzle->field_count,
1841
MYF(MY_WME | MY_ZEROFILL))))
1486
memset(result, 0, sizeof(*result)+ sizeof(uint32_t)*drizzle->field_count);
1487
1843
result->lengths=(uint32_t*) (result+1);
1488
1844
result->methods= drizzle->methods;
1489
1845
if (!(result->row=(DRIZZLE_ROW)
1490
malloc(sizeof(result->row[0])*(drizzle->field_count+1))))
1846
my_malloc(sizeof(result->row[0])*(drizzle->field_count+1), MYF(MY_WME))))
1491
1847
{ /* Ptrs: to one row */
1492
free((uchar*) result);
1848
my_free((uchar*) result,MYF(0));
1495
1851
result->fields= drizzle->fields;
1852
result->field_alloc= drizzle->field_alloc;
1496
1853
result->field_count= drizzle->field_count;
1497
1854
result->current_field=0;
1498
1855
result->handle= drizzle;
1499
1856
result->current_row= 0;
1500
1857
drizzle->fields=0; /* fields is now in result */
1858
clear_alloc_root(&drizzle->field_alloc);
1501
1859
drizzle->status=DRIZZLE_STATUS_USE_RESULT;
1502
1860
drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
1503
1861
return(result); /* Data is read to be fetched */
1597
1955
drizzle->options.client_flag&= ~CLIENT_LOCAL_FILES;
1957
case DRIZZLE_INIT_COMMAND:
1958
add_init_command(&drizzle->options,arg);
1599
1960
case DRIZZLE_READ_DEFAULT_FILE:
1600
if (drizzle->options.my_cnf_file != NULL)
1601
free(drizzle->options.my_cnf_file);
1602
drizzle->options.my_cnf_file=strdup(arg);
1961
my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1962
drizzle->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
1604
1964
case DRIZZLE_READ_DEFAULT_GROUP:
1605
if (drizzle->options.my_cnf_group != NULL)
1606
free(drizzle->options.my_cnf_group);
1607
drizzle->options.my_cnf_group=strdup(arg);
1965
my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1966
drizzle->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
1968
case DRIZZLE_SET_CHARSET_DIR:
1969
my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
1970
drizzle->options.charset_dir=my_strdup(arg,MYF(MY_WME));
1972
case DRIZZLE_SET_CHARSET_NAME:
1973
my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
1974
drizzle->options.charset_name=my_strdup(arg,MYF(MY_WME));
1609
1976
case DRIZZLE_OPT_PROTOCOL:
1977
drizzle->options.protocol= *(const uint*) arg;
1611
1979
case DRIZZLE_OPT_USE_REMOTE_CONNECTION:
1612
1980
case DRIZZLE_OPT_GUESS_CONNECTION:
1613
1981
drizzle->options.methods_to_use= option;
1615
1983
case DRIZZLE_SET_CLIENT_IP:
1616
drizzle->options.client_ip= strdup(arg);
1984
drizzle->options.client_ip= my_strdup(arg, MYF(MY_WME));
1618
1986
case DRIZZLE_SECURE_AUTH:
1619
1987
drizzle->options.secure_auth= *(const bool *) arg;
1693
2061
return (uint32_t) major*10000L+(uint32_t) (minor*100+version);
2066
drizzle_set_character_set function sends SET NAMES cs_name to
2067
the server (which changes character_set_client, character_set_result
2068
and character_set_connection) and updates drizzle->charset so other
2069
functions like drizzle_real_escape will work correctly.
2071
int drizzle_set_character_set(DRIZZLE *drizzle, const char *cs_name)
2073
const CHARSET_INFO *cs;
2074
const char *save_csdir= charsets_dir;
2076
if (drizzle->options.charset_dir)
2077
charsets_dir= drizzle->options.charset_dir;
2079
if (strlen(cs_name) < MY_CS_NAME_SIZE &&
2080
(cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
2082
char buff[MY_CS_NAME_SIZE + 10];
2083
charsets_dir= save_csdir;
2084
sprintf(buff, "SET NAMES %s", cs_name);
2085
if (!drizzle_real_query(drizzle, buff, strlen(buff)))
2087
drizzle->charset= cs;
2092
char cs_dir_name[FN_REFLEN];
2093
get_charsets_dir(cs_dir_name);
2094
set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
2095
ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
2097
charsets_dir= save_csdir;
2098
return drizzle->net.last_errno;