~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/client.c

  • Committer: Monty Taylor
  • Date: 2008-08-16 21:06:22 UTC
  • Revision ID: monty@inaugust.com-20080816210622-zpnn13unyinqzn72
Updated po files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 
 *
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.
9
 
 *
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.
14
 
 *
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
18
 
 */
 
1
/* Copyright (C) 2008 Drizzle Open Source Project
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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 */
19
15
 
20
16
/*
21
17
  This file is included by both libdrizzle.c (the DRIZZLE client C API)
28
24
    drizzle_connect()
29
25
  - Support for reading local file with LOAD DATA LOCAL
30
26
  - SHARED memory handling
 
27
  - Protection against sigpipe
31
28
  - Prepared statements
32
 
 
 
29
 
33
30
  - Things that only works for the server
34
31
  - Alarm handling on connect
35
 
 
 
32
 
36
33
  In all other cases, the code should be idential for the client and
37
34
  server.
38
35
*/
39
36
 
40
 
#include <stdarg.h>
 
37
#include <drizzled/global.h>
41
38
 
42
 
#include <libdrizzle/libdrizzle.h>
43
 
#include <libdrizzle/net_serv.h>
44
 
#include "libdrizzle_priv.h"
45
 
#include <libdrizzle/pack.h>
 
39
#include "drizzle.h"
46
40
 
47
41
#include <sys/poll.h>
48
42
#include <sys/ioctl.h>
53
47
#undef max_allowed_packet
54
48
#undef net_buffer_length
55
49
 
56
 
#include <libdrizzle/errmsg.h>
 
50
#define CLI_DRIZZLE_CONNECT drizzle_connect
 
51
 
 
52
#include <mysys/my_sys.h>
 
53
#include <mystrings/m_string.h>
 
54
#include <mystrings/m_ctype.h>
 
55
#include <drizzled/error.h>
 
56
#include "errmsg.h"
 
57
#include <vio/violite.h>
57
58
 
58
59
#include <sys/stat.h>
59
60
#include <signal.h>
76
77
#include <sys/un.h>
77
78
 
78
79
#include <errno.h>
79
 
 
80
 
 
81
 
#include <drizzled/gettext.h>
82
 
#include "local_infile.h"
83
 
 
84
 
 
85
 
 
86
 
 
87
 
 
88
 
 
 
80
#define SOCKET_ERROR -1
 
81
 
 
82
#define CONNECT_TIMEOUT 0
 
83
 
 
84
#include "client_settings.h"
 
85
#include <drizzled/version.h>
 
86
#include <libdrizzle/sql_common.h>
 
87
 
 
88
uint    drizzle_port=0;
 
89
char    *drizzle_unix_port= 0;
 
90
const char  *unknown_sqlstate= "HY000";
 
91
const char  *not_error_sqlstate= "00000";
 
92
const char  *cant_connect_sqlstate= "08001";
 
93
 
 
94
static bool drizzle_client_init= false;
 
95
static bool org_my_init_done= false;
 
96
 
 
97
static void drizzle_close_free_options(DRIZZLE *drizzle);
 
98
static void drizzle_close_free(DRIZZLE *drizzle);
 
99
 
 
100
static int wait_for_data(int fd, int32_t timeout);
 
101
int connect_with_timeout(int fd, const struct sockaddr *name, uint namelen, int32_t timeout);
 
102
 
 
103
CHARSET_INFO *default_client_charset_info = &my_charset_latin1;
 
104
 
 
105
/* Server error code and message */
 
106
unsigned int drizzle_server_last_errno;
 
107
char drizzle_server_last_error[DRIZZLE_ERRMSG_SIZE];
 
108
 
 
109
/****************************************************************************
 
110
  A modified version of connect().  connect_with_timeout() allows you to specify
 
111
  a timeout value, in seconds, that we should wait until we
 
112
  derermine we can't connect to a particular host.  If timeout is 0,
 
113
  connect_with_timeout() will behave exactly like connect().
 
114
 
 
115
  Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
 
116
*****************************************************************************/
 
117
 
 
118
 
 
119
int connect_with_timeout(int fd, const struct sockaddr *name, uint namelen, int32_t timeout)
 
120
{
 
121
  int flags, res, s_err;
 
122
 
 
123
  /*
 
124
    If they passed us a timeout of zero, we should behave
 
125
    exactly like the normal connect() call does.
 
126
  */
 
127
 
 
128
  if (timeout == 0)
 
129
    return connect(fd, (struct sockaddr*) name, namelen);
 
130
 
 
131
  flags = fcntl(fd, F_GETFL, 0);    /* Set socket to not block */
 
132
#ifdef O_NONBLOCK
 
133
  fcntl(fd, F_SETFL, flags | O_NONBLOCK);  /* and save the flags..  */
 
134
#endif
 
135
 
 
136
  res= connect(fd, (struct sockaddr*) name, namelen);
 
137
  s_err= errno;      /* Save the error... */
 
138
  fcntl(fd, F_SETFL, flags);
 
139
  if ((res != 0) && (s_err != EINPROGRESS))
 
140
  {
 
141
    errno= s_err;      /* Restore it */
 
142
    return(-1);
 
143
  }
 
144
  if (res == 0)        /* Connected quickly! */
 
145
    return(0);
 
146
 
 
147
  return wait_for_data(fd, timeout);
 
148
}
 
149
 
 
150
 
 
151
/*
 
152
  Wait up to timeout seconds for a connection to be established.
 
153
 
 
154
  We prefer to do this with poll() as there is no limitations with this.
 
155
  If not, we will use select()
 
156
*/
 
157
 
 
158
static int wait_for_data(int fd, int32_t timeout)
 
159
{
 
160
  struct pollfd ufds;
 
161
  int res;
 
162
 
 
163
  ufds.fd= fd;
 
164
  ufds.events= POLLIN | POLLPRI;
 
165
  if (!(res= poll(&ufds, 1, (int) timeout*1000)))
 
166
  {
 
167
    errno= EINTR;
 
168
    return -1;
 
169
  }
 
170
  if (res < 0 || !(ufds.revents & (POLLIN | POLLPRI)) || (ufds.revents & POLLHUP))
 
171
    return -1;
 
172
  return 0;
 
173
}
89
174
 
90
175
 
91
176
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
93
178
char* getlogin(void);
94
179
#endif
95
180
 
96
 
 
 
181
static void read_user_name(char *name)
 
182
{
 
183
  if (geteuid() == 0)
 
184
    strcpy(name,"root");    /* allow use of surun */
 
185
  else
 
186
  {
 
187
#ifdef HAVE_GETPWUID
 
188
    struct passwd *skr;
 
189
    const char *str;
 
190
    if ((str=getlogin()) == NULL)
 
191
    {
 
192
      if ((skr=getpwuid(geteuid())) != NULL)
 
193
  str=skr->pw_name;
 
194
      else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
 
195
         !(str=getenv("LOGIN")))
 
196
  str="UNKNOWN_USER";
 
197
    }
 
198
    strncpy(name,str,USERNAME_LENGTH);
 
199
#elif HAVE_CUSERID
 
200
    (void) cuserid(name);
 
201
#else
 
202
    strcpy(name,"UNKNOWN_USER");
 
203
#endif
 
204
  }
 
205
  return;
 
206
}
 
207
 
 
208
 
 
209
/**
 
210
  Set the internal error message to DRIZZLE handler
 
211
 
 
212
  @param drizzle connection handle (client side)
 
213
  @param errcode  CR_ error code, passed to ER macro to get
 
214
                  error text
 
215
  @parma sqlstate SQL standard sqlstate
 
216
*/
 
217
 
 
218
void set_drizzle_error(DRIZZLE *drizzle, int errcode, const char *sqlstate)
 
219
{
 
220
  NET *net;
 
221
  assert(drizzle != 0);
 
222
 
 
223
  if (drizzle)
 
224
  {
 
225
    net= &drizzle->net;
 
226
    net->last_errno= errcode;
 
227
    strcpy(net->last_error, ER(errcode));
 
228
    strcpy(net->sqlstate, sqlstate);
 
229
  }
 
230
  else
 
231
  {
 
232
    drizzle_server_last_errno= errcode;
 
233
    strcpy(drizzle_server_last_error, ER(errcode));
 
234
  }
 
235
  return;
 
236
}
 
237
 
 
238
/**
 
239
  Clear possible error state of struct NET
 
240
 
 
241
  @param net  clear the state of the argument
 
242
*/
 
243
 
 
244
void net_clear_error(NET *net)
 
245
{
 
246
  net->last_errno= 0;
 
247
  net->last_error[0]= '\0';
 
248
  strcpy(net->sqlstate, not_error_sqlstate);
 
249
}
 
250
 
 
251
/**
 
252
  Set an error message on the client.
 
253
 
 
254
  @param drizzle connection handle
 
255
  @param errcode   CR_* errcode, for client errors
 
256
  @param sqlstate  SQL standard sql state, unknown_sqlstate for the
 
257
                   majority of client errors.
 
258
  @param format    error message template, in sprintf format
 
259
  @param ...       variable number of arguments
 
260
*/
 
261
 
 
262
static void set_drizzle_extended_error(DRIZZLE *drizzle, int errcode,
 
263
                                     const char *sqlstate,
 
264
                                     const char *format, ...)
 
265
{
 
266
  NET *net;
 
267
  va_list args;
 
268
  assert(drizzle != 0);
 
269
 
 
270
  net= &drizzle->net;
 
271
  net->last_errno= errcode;
 
272
  va_start(args, format);
 
273
  vsnprintf(net->last_error, sizeof(net->last_error)-1,
 
274
               format, args);
 
275
  va_end(args);
 
276
  strcpy(net->sqlstate, sqlstate);
 
277
 
 
278
  return;
 
279
}
97
280
 
98
281
/*****************************************************************************
99
282
  Read a packet from server. Give error message if socket was down
100
283
  or packet is an error message
101
284
*****************************************************************************/
102
 
safe_read_error_hook_func safe_read_error_hook= NULL;
103
285
 
104
286
uint32_t cli_safe_read(DRIZZLE *drizzle)
105
287
{
106
288
  NET *net= &drizzle->net;
107
289
  uint32_t len=0;
 
290
  init_sigpipe_variables
108
291
 
 
292
  /* Don't give sigpipe errors if the client doesn't want them */
 
293
  set_sigpipe(drizzle);
109
294
  if (net->vio != 0)
110
295
    len=my_net_read(net);
 
296
  reset_sigpipe(drizzle);
111
297
 
112
298
  if (len == packet_error || len == 0)
113
299
  {
114
 
    if (safe_read_error_hook != NULL)
115
 
      if (safe_read_error_hook(net))
116
 
        return (packet_error);
117
 
    drizzle_disconnect(drizzle);
118
 
    drizzle_set_error(drizzle, net->last_errno == CR_NET_PACKET_TOO_LARGE ?
119
 
                      CR_NET_PACKET_TOO_LARGE : CR_SERVER_LOST,
120
 
                      sqlstate_get_unknown());
 
300
#ifdef DRIZZLE_SERVER
 
301
    if (net->vio && vio_was_interrupted(net->vio))
 
302
      return (packet_error);
 
303
#endif /*DRIZZLE_SERVER*/
 
304
    end_server(drizzle);
 
305
    set_drizzle_error(drizzle, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
 
306
                    CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
121
307
    return (packet_error);
122
308
  }
123
309
  if (net->read_pos[0] == 255)
130
316
      len-=2;
131
317
      if (pos[0] == '#')
132
318
      {
133
 
        strncpy(net->sqlstate, pos+1, LIBDRIZZLE_SQLSTATE_LENGTH);
134
 
        pos+= LIBDRIZZLE_SQLSTATE_LENGTH+1;
 
319
        strncpy(net->sqlstate, pos+1, SQLSTATE_LENGTH);
 
320
        pos+= SQLSTATE_LENGTH+1;
135
321
      }
136
322
      else
137
323
      {
140
326
          (unknown error sql state).
141
327
        */
142
328
 
143
 
        strcpy(net->sqlstate, sqlstate_get_unknown());
 
329
        strcpy(net->sqlstate, unknown_sqlstate);
144
330
      }
145
331
 
146
 
      strncpy(net->last_error,(char*) pos, min((uint32_t) len,
 
332
      strncpy(net->last_error,(char*) pos, min((uint) len,
147
333
              (uint32_t) sizeof(net->last_error)-1));
148
334
    }
149
335
    else
150
 
      drizzle_set_error(drizzle, CR_UNKNOWN_ERROR, sqlstate_get_unknown());
 
336
      set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
151
337
    /*
152
338
      Cover a protocol design error: error packet does not
153
339
      contain the server status. Therefore, the client has no way
164
350
  return len;
165
351
}
166
352
 
 
353
void free_rows(DRIZZLE_DATA *cur)
 
354
{
 
355
  if (cur)
 
356
  {
 
357
    free_root(&cur->alloc,MYF(0));
 
358
    my_free((uchar*) cur,MYF(0));
 
359
  }
 
360
}
 
361
 
167
362
bool
168
363
cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
169
364
         const unsigned char *header, uint32_t header_length,
171
366
{
172
367
  NET *net= &drizzle->net;
173
368
  bool result= 1;
 
369
  init_sigpipe_variables
174
370
  bool stmt_skip= false;
175
371
 
 
372
  /* Don't give sigpipe errors if the client doesn't want them */
 
373
  set_sigpipe(drizzle);
 
374
 
176
375
  if (drizzle->net.vio == 0)
177
376
  {            /* Do reconnect if possible */
178
377
    if (drizzle_reconnect(drizzle) || stmt_skip)
181
380
  if (drizzle->status != DRIZZLE_STATUS_READY ||
182
381
      drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
183
382
  {
184
 
    drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC,
185
 
                      sqlstate_get_unknown());
 
383
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
186
384
    return(1);
187
385
  }
188
386
 
196
394
  */
197
395
  net_clear(&drizzle->net, (command != COM_QUIT));
198
396
 
199
 
  if (net_write_command(net,(unsigned char) command, header, header_length,
 
397
  if (net_write_command(net,(uchar) command, header, header_length,
200
398
      arg, arg_length))
201
399
  {
202
 
    if (net->last_errno == CR_NET_PACKET_TOO_LARGE)
 
400
    if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
203
401
    {
204
 
      drizzle_set_error(drizzle, CR_NET_PACKET_TOO_LARGE, sqlstate_get_unknown());
 
402
      set_drizzle_error(drizzle, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
205
403
      goto end;
206
404
    }
207
 
    drizzle_disconnect(drizzle);
 
405
    end_server(drizzle);
208
406
    if (drizzle_reconnect(drizzle) || stmt_skip)
209
407
      goto end;
210
 
    if (net_write_command(net,(unsigned char) command, header, header_length,
 
408
    if (net_write_command(net,(uchar) command, header, header_length,
211
409
        arg, arg_length))
212
410
    {
213
 
      drizzle_set_error(drizzle, CR_SERVER_GONE_ERROR, sqlstate_get_unknown());
 
411
      set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
214
412
      goto end;
215
413
    }
216
414
  }
219
417
    result= ((drizzle->packet_length=cli_safe_read(drizzle)) == packet_error ?
220
418
       1 : 0);
221
419
end:
 
420
  reset_sigpipe(drizzle);
222
421
  return(result);
223
422
}
224
423
 
225
424
void free_old_query(DRIZZLE *drizzle)
226
425
{
227
426
  if (drizzle->fields)
228
 
  {
229
 
    /* TODO - we need to de-alloc field storage */
230
 
    free(drizzle->fields->catalog);
231
 
    free(drizzle->fields->db);
232
 
    free(drizzle->fields->table);
233
 
    free(drizzle->fields->org_table);
234
 
    free(drizzle->fields->name);
235
 
    free(drizzle->fields->org_name);
236
 
    free(drizzle->fields->def);
237
 
    free(drizzle->fields);
238
 
 
239
 
  }
240
 
  /* init_alloc_root(&drizzle->field_alloc,8192,0); */ /* Assume rowlength < 8192 */
 
427
    free_root(&drizzle->field_alloc,MYF(0));
 
428
  init_alloc_root(&drizzle->field_alloc,8192,0); /* Assume rowlength < 8192 */
241
429
  drizzle->fields= 0;
242
430
  drizzle->field_count= 0;      /* For API */
243
431
  drizzle->warning_count= 0;
245
433
  return;
246
434
}
247
435
 
248
 
 
249
 
 
 
436
/*
 
437
  Flush result set sent from server
 
438
*/
 
439
 
 
440
static void cli_flush_use_result(DRIZZLE *drizzle)
 
441
{
 
442
  /* Clear the current execution status */
 
443
  for (;;)
 
444
  {
 
445
    uint32_t pkt_len;
 
446
    if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
447
      break;
 
448
    if (pkt_len <= 8 && drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
 
449
    {
 
450
      char *pos= (char*) drizzle->net.read_pos + 1;
 
451
      drizzle->warning_count=uint2korr(pos); pos+=2;
 
452
      drizzle->server_status=uint2korr(pos); pos+=2;
 
453
 
 
454
      break;                            /* End of data */
 
455
    }
 
456
  }
 
457
  return;
 
458
}
 
459
 
 
460
 
 
461
/**************************************************************************
 
462
  Shut down connection
 
463
**************************************************************************/
 
464
 
 
465
void end_server(DRIZZLE *drizzle)
 
466
{
 
467
  int save_errno= errno;
 
468
  if (drizzle->net.vio != 0)
 
469
  {
 
470
    init_sigpipe_variables
 
471
    set_sigpipe(drizzle);
 
472
    vio_delete(drizzle->net.vio);
 
473
    reset_sigpipe(drizzle);
 
474
    drizzle->net.vio= 0;          /* Marker */
 
475
  }
 
476
  net_end(&drizzle->net);
 
477
  free_old_query(drizzle);
 
478
  errno= save_errno;
 
479
}
250
480
 
251
481
 
252
482
void
268
498
      }
269
499
    }
270
500
    free_rows(result->data);
271
 
    /* TODO: free result->fields */
 
501
    if (result->fields)
 
502
      free_root(&result->field_alloc,MYF(0));
272
503
    if (result->row)
273
 
      free((unsigned char*) result->row);
274
 
    free((unsigned char*) result);
275
 
  }
276
 
}
277
 
 
278
 
 
279
 
 
 
504
      my_free((uchar*) result->row,MYF(0));
 
505
    my_free((uchar*) result,MYF(0));
 
506
  }
 
507
}
 
508
 
 
509
/****************************************************************************
 
510
  Get options from my.cnf
 
511
****************************************************************************/
 
512
 
 
513
static const char *default_options[]=
 
514
{
 
515
  "port","socket","compress","password","pipe", "timeout", "user",
 
516
  "init-command", "host", "database", "return-found-rows",
 
517
  "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
 
518
  "character-sets-dir", "default-character-set", "interactive-timeout",
 
519
  "connect-timeout", "local-infile", "disable-local-infile",
 
520
  "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
 
521
  "multi-results", "multi-statements", "multi-queries", "secure-auth",
 
522
  "report-data-truncation",
 
523
  NullS
 
524
};
 
525
 
 
526
static TYPELIB option_types={array_elements(default_options)-1,
 
527
           "options",default_options, NULL};
 
528
 
 
529
const char *sql_protocol_names_lib[] =
 
530
{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
 
531
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
 
532
        sql_protocol_names_lib, NULL};
 
533
 
 
534
static int add_init_command(struct st_drizzle_options *options, const char *cmd)
 
535
{
 
536
  char *tmp;
 
537
 
 
538
  if (!options->init_commands)
 
539
  {
 
540
    options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
 
541
                  MYF(MY_WME));
 
542
    init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
 
543
  }
 
544
 
 
545
  if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
 
546
      insert_dynamic(options->init_commands, (uchar*)&tmp))
 
547
  {
 
548
    my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
 
549
    return 1;
 
550
  }
 
551
 
 
552
  return 0;
 
553
}
 
554
 
 
555
void drizzle_read_default_options(struct st_drizzle_options *options,
 
556
        const char *filename,const char *group)
 
557
{
 
558
  int argc;
 
559
  char *argv_buff[1],**argv;
 
560
  const char *groups[3];
 
561
 
 
562
  argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
 
563
  groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
 
564
 
 
565
  load_defaults(filename, groups, &argc, &argv);
 
566
  if (argc != 1)        /* If some default option */
 
567
  {
 
568
    char **option=argv;
 
569
    while (*++option)
 
570
    {
 
571
      if (option[0][0] == '-' && option[0][1] == '-')
 
572
      {
 
573
        char *end=strrchr(*option,'=');
 
574
        char *opt_arg=0;
 
575
        if (end != NULL)
 
576
        {
 
577
          opt_arg=end+1;
 
578
          *end=0;        /* Remove '=' */
 
579
        }
 
580
        /* Change all '_' in variable name to '-' */
 
581
        for (end= *option ; *(end= strrchr(end,'_')) ; )
 
582
          *end= '-';
 
583
        switch (find_type(*option+2,&option_types,2)) {
 
584
        case 1:        /* port */
 
585
          if (opt_arg)
 
586
            options->port=atoi(opt_arg);
 
587
          break;
 
588
        case 2:        /* socket */
 
589
          if (opt_arg)
 
590
          {
 
591
            my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
 
592
            options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
 
593
          }
 
594
          break;
 
595
        case 3:        /* compress */
 
596
          options->compress=1;
 
597
          options->client_flag|= CLIENT_COMPRESS;
 
598
          break;
 
599
        case 4:        /* password */
 
600
          if (opt_arg)
 
601
          {
 
602
            my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
 
603
            options->password=my_strdup(opt_arg,MYF(MY_WME));
 
604
          }
 
605
          break;
 
606
        case 20:      /* connect_timeout */
 
607
        case 6:        /* timeout */
 
608
          if (opt_arg)
 
609
            options->connect_timeout=atoi(opt_arg);
 
610
          break;
 
611
        case 7:        /* user */
 
612
          if (opt_arg)
 
613
          {
 
614
            my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
 
615
            options->user=my_strdup(opt_arg,MYF(MY_WME));
 
616
          }
 
617
          break;
 
618
        case 8:        /* init-command */
 
619
          add_init_command(options,opt_arg);
 
620
          break;
 
621
        case 9:        /* host */
 
622
          if (opt_arg)
 
623
          {
 
624
            my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
 
625
            options->host=my_strdup(opt_arg,MYF(MY_WME));
 
626
          }
 
627
          break;
 
628
        case 10:      /* database */
 
629
          if (opt_arg)
 
630
          {
 
631
            my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
 
632
            options->db=my_strdup(opt_arg,MYF(MY_WME));
 
633
          }
 
634
          break;
 
635
        case 12:      /* return-found-rows */
 
636
          options->client_flag|=CLIENT_FOUND_ROWS;
 
637
          break;
 
638
        case 13:        /* Ignore SSL options */
 
639
        case 14:
 
640
        case 15:
 
641
        case 16:
 
642
        case 23:
 
643
          break;
 
644
        case 17:      /* charset-lib */
 
645
          my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
646
          options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
 
647
          break;
 
648
        case 18:
 
649
          my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
650
          options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
 
651
          break;
 
652
        case 19:        /* Interactive-timeout */
 
653
          options->client_flag|= CLIENT_INTERACTIVE;
 
654
          break;
 
655
        case 21:
 
656
          if (!opt_arg || atoi(opt_arg) != 0)
 
657
            options->client_flag|= CLIENT_LOCAL_FILES;
 
658
          else
 
659
            options->client_flag&= ~CLIENT_LOCAL_FILES;
 
660
          break;
 
661
        case 22:
 
662
          options->client_flag&= ~CLIENT_LOCAL_FILES;
 
663
          break;
 
664
        case 24: /* max-allowed-packet */
 
665
          if (opt_arg)
 
666
            options->max_allowed_packet= atoi(opt_arg);
 
667
          break;
 
668
        case 25: /* protocol */
 
669
          if ((options->protocol= find_type(opt_arg,
 
670
                                            &sql_protocol_typelib,0)) <= 0)
 
671
          {
 
672
            fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
 
673
            exit(1);
 
674
          }
 
675
          break;
 
676
        case 27: /* multi-results */
 
677
          options->client_flag|= CLIENT_MULTI_RESULTS;
 
678
          break;
 
679
        case 28: /* multi-statements */
 
680
        case 29: /* multi-queries */
 
681
          options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
 
682
          break;
 
683
        case 30: /* secure-auth */
 
684
          options->secure_auth= true;
 
685
          break;
 
686
        case 31: /* report-data-truncation */
 
687
          options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
 
688
          break;
 
689
        default:
 
690
          break;
 
691
        }
 
692
      }
 
693
    }
 
694
  }
 
695
  free_defaults(argv);
 
696
  return;
 
697
}
 
698
 
 
699
 
 
700
/**************************************************************************
 
701
  Get column lengths of the current row
 
702
  If one uses drizzle_use_result, res->lengths contains the length information,
 
703
  else the lengths are calculated from the offset between pointers.
 
704
**************************************************************************/
 
705
 
 
706
static void cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count)
 
707
{
 
708
  uint32_t *prev_length;
 
709
  char *start=0;
 
710
  DRIZZLE_ROW end;
 
711
 
 
712
  prev_length=0;        /* Keep gcc happy */
 
713
  for (end=column + field_count + 1 ; column != end ; column++, to++)
 
714
  {
 
715
    if (!*column)
 
716
    {
 
717
      *to= 0;          /* Null */
 
718
      continue;
 
719
    }
 
720
    if (start)          /* Found end of prev string */
 
721
      *prev_length= (uint32_t) (*column-start-1);
 
722
    start= *column;
 
723
    prev_length= to;
 
724
  }
 
725
}
 
726
 
 
727
/***************************************************************************
 
728
  Change field rows to field structs
 
729
***************************************************************************/
 
730
 
 
731
DRIZZLE_FIELD *
 
732
unpack_fields(DRIZZLE_DATA *data, MEM_ROOT *alloc,uint fields,
 
733
              bool default_value)
 
734
{
 
735
  DRIZZLE_ROWS  *row;
 
736
  DRIZZLE_FIELD  *field,*result;
 
737
  uint32_t lengths[9];        /* Max of fields */
 
738
 
 
739
  field= result= (DRIZZLE_FIELD*) alloc_root(alloc,
 
740
             (uint) sizeof(*field)*fields);
 
741
  if (!result)
 
742
  {
 
743
    free_rows(data);        /* Free old data */
 
744
    return(0);
 
745
  }
 
746
  memset((char*) field, 0, (uint) sizeof(DRIZZLE_FIELD)*fields);
 
747
 
 
748
  for (row= data->data; row ; row = row->next,field++)
 
749
  {
 
750
    uchar *pos;
 
751
    /* fields count may be wrong */
 
752
    assert((uint) (field - result) < fields);
 
753
    cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
 
754
    field->catalog=   strmake_root(alloc,(char*) row->data[0], lengths[0]);
 
755
    field->db=        strmake_root(alloc,(char*) row->data[1], lengths[1]);
 
756
    field->table=     strmake_root(alloc,(char*) row->data[2], lengths[2]);
 
757
    field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
 
758
    field->name=      strmake_root(alloc,(char*) row->data[4], lengths[4]);
 
759
    field->org_name=  strmake_root(alloc,(char*) row->data[5], lengths[5]);
 
760
 
 
761
    field->catalog_length=  lengths[0];
 
762
    field->db_length=    lengths[1];
 
763
    field->table_length=  lengths[2];
 
764
    field->org_table_length=  lengths[3];
 
765
    field->name_length=  lengths[4];
 
766
    field->org_name_length=  lengths[5];
 
767
 
 
768
    /* Unpack fixed length parts */
 
769
    pos= (uchar*) row->data[6];
 
770
    field->charsetnr= uint2korr(pos);
 
771
    field->length=  (uint) uint4korr(pos+2);
 
772
    field->type=  (enum enum_field_types) pos[6];
 
773
    field->flags=  uint2korr(pos+7);
 
774
    field->decimals=  (uint) pos[9];
 
775
 
 
776
    if (INTERNAL_NUM_FIELD(field))
 
777
      field->flags|= NUM_FLAG;
 
778
    if (default_value && row->data[7])
 
779
    {
 
780
      field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
 
781
      field->def_length= lengths[7];
 
782
    }
 
783
    else
 
784
      field->def=0;
 
785
    field->max_length= 0;
 
786
  }
 
787
 
 
788
  free_rows(data);        /* Free old data */
 
789
  return(result);
 
790
}
280
791
 
281
792
/* Read all rows (fields or data) from server */
282
793
 
293
804
 
294
805
  if ((pkt_len= cli_safe_read(drizzle)) == packet_error)
295
806
    return(0);
296
 
  if (!(result=(DRIZZLE_DATA*) malloc(sizeof(DRIZZLE_DATA))))
 
807
  if (!(result=(DRIZZLE_DATA*) my_malloc(sizeof(DRIZZLE_DATA),
 
808
               MYF(MY_WME | MY_ZEROFILL))))
297
809
  {
298
 
    drizzle_set_error(drizzle, CR_OUT_OF_MEMORY,
299
 
                      sqlstate_get_unknown());
 
810
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
300
811
    return(0);
301
812
  }
302
 
  memset(result, 0, sizeof(DRIZZLE_DATA));
 
813
  init_alloc_root(&result->alloc,8192,0);  /* Assume rowlength < 8192 */
 
814
  result->alloc.min_malloc=sizeof(DRIZZLE_ROWS);
303
815
  prev_ptr= &result->data;
304
816
  result->rows=0;
305
817
  result->fields=fields;
314
826
  while (*(cp=net->read_pos) != DRIZZLE_PROTOCOL_NO_MORE_DATA || pkt_len >= 8)
315
827
  {
316
828
    result->rows++;
317
 
    if (!(cur= (DRIZZLE_ROWS*) malloc(sizeof(DRIZZLE_ROWS))) ||
318
 
        !(cur->data= ((DRIZZLE_ROW) malloc((fields+1)*sizeof(char *)+pkt_len))))
 
829
    if (!(cur= (DRIZZLE_ROWS*) alloc_root(&result->alloc,
 
830
          sizeof(DRIZZLE_ROWS))) ||
 
831
  !(cur->data= ((DRIZZLE_ROW)
 
832
          alloc_root(&result->alloc,
 
833
         (fields+1)*sizeof(char *)+pkt_len))))
319
834
    {
320
835
      free_rows(result);
321
 
      drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
 
836
      set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
322
837
      return(0);
323
838
    }
324
839
    *prev_ptr=cur;
337
852
        if (len > (uint32_t) (end_to - to))
338
853
        {
339
854
          free_rows(result);
340
 
          drizzle_set_error(drizzle, CR_MALFORMED_PACKET,
341
 
                            sqlstate_get_unknown());
 
855
          set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
342
856
          return(0);
343
857
        }
344
858
        memcpy(to, cp, len);
377
891
static int32_t
378
892
read_one_row(DRIZZLE *drizzle, uint32_t fields, DRIZZLE_ROW row, uint32_t *lengths)
379
893
{
380
 
  uint32_t field;
 
894
  uint field;
381
895
  uint32_t pkt_len,len;
382
 
  unsigned char *pos, *prev_pos, *end_pos;
 
896
  uchar *pos, *prev_pos, *end_pos;
383
897
  NET *net= &drizzle->net;
384
898
 
385
899
  if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
407
921
    {
408
922
      if (len > (uint32_t) (end_pos - pos))
409
923
      {
410
 
        drizzle_set_error(drizzle, CR_UNKNOWN_ERROR,
411
 
                          sqlstate_get_unknown());
 
924
        set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
412
925
        return -1;
413
926
      }
414
927
      row[field] = (char*) pos;
425
938
}
426
939
 
427
940
 
 
941
/****************************************************************************
 
942
  Init DRIZZLE structure or allocate one
 
943
****************************************************************************/
 
944
 
 
945
DRIZZLE *
 
946
drizzle_create(DRIZZLE *ptr)
 
947
{
 
948
 
 
949
  if (!drizzle_client_init)
 
950
  {
 
951
    drizzle_client_init=true;
 
952
    org_my_init_done=my_init_done;
 
953
 
 
954
    /* Will init threads */
 
955
    if (my_init())
 
956
      return NULL;
 
957
 
 
958
    if (!drizzle_port)
 
959
    {
 
960
      drizzle_port = DRIZZLE_PORT;
 
961
      {
 
962
        struct servent *serv_ptr;
 
963
        char *env;
 
964
 
 
965
        /*
 
966
          if builder specifically requested a default port, use that
 
967
          (even if it coincides with our factory default).
 
968
          only if they didn't do we check /etc/services (and, failing
 
969
          on that, fall back to the factory default of 4427).
 
970
          either default can be overridden by the environment variable
 
971
          DRIZZLE_TCP_PORT, which in turn can be overridden with command
 
972
          line options.
 
973
        */
 
974
 
 
975
#if DRIZZLE_PORT_DEFAULT == 0
 
976
        if ((serv_ptr = getservbyname("drizzle", "tcp")))
 
977
          drizzle_port = (uint) ntohs((ushort) serv_ptr->s_port);
 
978
#endif
 
979
        if ((env = getenv("DRIZZLE_TCP_PORT")))
 
980
          drizzle_port =(uint) atoi(env);
 
981
      }
 
982
    }
 
983
#if defined(SIGPIPE)
 
984
    (void) signal(SIGPIPE, SIG_IGN);
 
985
#endif
 
986
  }
 
987
  else
 
988
    /* Init if new thread */
 
989
    if (my_thread_init())
 
990
      return NULL;
 
991
 
 
992
  if (ptr == NULL)
 
993
  {
 
994
    ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
 
995
 
 
996
    if (ptr == NULL)
 
997
    {
 
998
      set_drizzle_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
999
      return 0;
 
1000
    }
 
1001
    memset(ptr, 0, sizeof(DRIZZLE));
 
1002
    ptr->free_me=1;
 
1003
  }
 
1004
  else
 
1005
  {
 
1006
    memset(ptr, 0, sizeof(DRIZZLE)); 
 
1007
  }
 
1008
 
 
1009
  ptr->options.connect_timeout= CONNECT_TIMEOUT;
 
1010
  ptr->charset=default_client_charset_info;
 
1011
  strcpy(ptr->net.sqlstate, not_error_sqlstate);
 
1012
 
 
1013
  /*
 
1014
    Only enable LOAD DATA INFILE by default if configured with
 
1015
    --enable-local-infile
 
1016
  */
 
1017
 
 
1018
#if defined(ENABLED_LOCAL_INFILE) && !defined(DRIZZLE_SERVER)
 
1019
  ptr->options.client_flag|= CLIENT_LOCAL_FILES;
 
1020
#endif
 
1021
 
 
1022
  ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION;
 
1023
  ptr->options.report_data_truncation= true;  /* default */
 
1024
 
 
1025
  /*
 
1026
    By default we don't reconnect because it could silently corrupt data (after
 
1027
    reconnection you potentially lose table locks, user variables, session
 
1028
    variables (transactions but they are specifically dealt with in
 
1029
    drizzle_reconnect()).
 
1030
    This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
 
1031
    How this change impacts existing apps:
 
1032
    - existing apps which relyed on the default will see a behaviour change;
 
1033
    they will have to set reconnect=1 after drizzle_connect().
 
1034
    - existing apps which explicitely asked for reconnection (the only way they
 
1035
    could do it was by setting drizzle.reconnect to 1 after drizzle_connect())
 
1036
    will not see a behaviour change.
 
1037
    - existing apps which explicitely asked for no reconnection
 
1038
    (drizzle.reconnect=0) will not see a behaviour change.
 
1039
  */
 
1040
  ptr->reconnect= 0;
 
1041
 
 
1042
  return ptr;
 
1043
}
 
1044
 
 
1045
 
 
1046
/*
 
1047
  Free all memory and resources used by the client library
 
1048
 
 
1049
  NOTES
 
1050
    When calling this there should not be any other threads using
 
1051
    the library.
 
1052
 
 
1053
    To make things simpler when used with windows dll's (which calls this
 
1054
    function automaticly), it's safe to call this function multiple times.
 
1055
*/
 
1056
 
 
1057
 
 
1058
void drizzle_server_end()
 
1059
{
 
1060
  if (!drizzle_client_init)
 
1061
    return;
 
1062
 
 
1063
  vio_end();
 
1064
 
 
1065
  /* If library called my_init(), free memory allocated by it */
 
1066
  if (!org_my_init_done)
 
1067
  {
 
1068
    my_end(0);
 
1069
  }
 
1070
  else
 
1071
  {
 
1072
    free_charsets();
 
1073
    drizzle_thread_end();
 
1074
  }
 
1075
 
 
1076
  drizzle_client_init= org_my_init_done= 0;
 
1077
#ifdef EMBEDDED_SERVER
 
1078
  if (stderror_file)
 
1079
  {
 
1080
    fclose(stderror_file);
 
1081
    stderror_file= 0;
 
1082
  }
 
1083
#endif
 
1084
}
 
1085
 
 
1086
 
 
1087
/*
 
1088
  Fill in SSL part of DRIZZLE structure and set 'use_ssl' flag.
 
1089
  NB! Errors are not reported until you do drizzle_connect.
 
1090
*/
 
1091
 
 
1092
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
 
1093
 
 
1094
/*
 
1095
  Note that the drizzle argument must be initialized with drizzle_init()
 
1096
  before calling drizzle_connect !
 
1097
*/
 
1098
 
 
1099
static bool cli_read_query_result(DRIZZLE *drizzle);
 
1100
static DRIZZLE_RES *cli_use_result(DRIZZLE *drizzle);
 
1101
 
 
1102
static DRIZZLE_METHODS client_methods=
 
1103
{
 
1104
  cli_read_query_result,                       /* read_query_result */
 
1105
  cli_advanced_command,                        /* advanced_command */
 
1106
  cli_read_rows,                               /* read_rows */
 
1107
  cli_use_result,                              /* use_result */
 
1108
  cli_fetch_lengths,                           /* fetch_lengths */
 
1109
  cli_flush_use_result,                         /* flush_use_result */
 
1110
#ifndef DRIZZLE_SERVER
 
1111
  cli_list_fields,                            /* list_fields */
 
1112
  cli_unbuffered_fetch,                        /* unbuffered_fetch */
 
1113
  cli_read_statistics,                         /* read_statistics */
 
1114
  cli_read_query_result,                       /* next_result */
 
1115
  cli_read_change_user_result,                 /* read_change_user_result */
 
1116
#else
 
1117
  0,0,0,0,0
 
1118
#endif
 
1119
};
 
1120
 
 
1121
C_MODE_START
 
1122
int drizzle_init_character_set(DRIZZLE *drizzle)
 
1123
{
 
1124
  const char *default_collation_name;
 
1125
 
 
1126
  /* Set character set */
 
1127
  if (!drizzle->options.charset_name)
 
1128
  {
 
1129
    default_collation_name= DRIZZLE_DEFAULT_COLLATION_NAME;
 
1130
    if (!(drizzle->options.charset_name=
 
1131
       my_strdup(DRIZZLE_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
 
1132
    return 1;
 
1133
  }
 
1134
  else
 
1135
    default_collation_name= NULL;
 
1136
 
 
1137
  {
 
1138
    const char *save= charsets_dir;
 
1139
    if (drizzle->options.charset_dir)
 
1140
      charsets_dir=drizzle->options.charset_dir;
 
1141
    drizzle->charset=get_charset_by_csname(drizzle->options.charset_name,
 
1142
                                         MY_CS_PRIMARY, MYF(MY_WME));
 
1143
    if (drizzle->charset && default_collation_name)
 
1144
    {
 
1145
      const CHARSET_INFO *collation;
 
1146
      if ((collation=
 
1147
           get_charset_by_name(default_collation_name, MYF(MY_WME))))
 
1148
      {
 
1149
        if (!my_charset_same(drizzle->charset, collation))
 
1150
        {
 
1151
          my_printf_error(ER_UNKNOWN_ERROR,
 
1152
                         "COLLATION %s is not valid for CHARACTER SET %s",
 
1153
                         MYF(0),
 
1154
                         default_collation_name, drizzle->options.charset_name);
 
1155
          drizzle->charset= NULL;
 
1156
        }
 
1157
        else
 
1158
        {
 
1159
          drizzle->charset= collation;
 
1160
        }
 
1161
      }
 
1162
      else
 
1163
        drizzle->charset= NULL;
 
1164
    }
 
1165
    charsets_dir= save;
 
1166
  }
 
1167
 
 
1168
  if (!drizzle->charset)
 
1169
  {
 
1170
    if (drizzle->options.charset_dir)
 
1171
      set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
1172
                               ER(CR_CANT_READ_CHARSET),
 
1173
                               drizzle->options.charset_name,
 
1174
                               drizzle->options.charset_dir);
 
1175
    else
 
1176
    {
 
1177
      char cs_dir_name[FN_REFLEN];
 
1178
      get_charsets_dir(cs_dir_name);
 
1179
      set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
1180
                               ER(CR_CANT_READ_CHARSET),
 
1181
                               drizzle->options.charset_name,
 
1182
                               cs_dir_name);
 
1183
    }
 
1184
    return 1;
 
1185
  }
 
1186
  return 0;
 
1187
}
 
1188
C_MODE_END
 
1189
 
 
1190
 
 
1191
DRIZZLE *
 
1192
CLI_DRIZZLE_CONNECT(DRIZZLE *drizzle,const char *host, const char *user,
 
1193
                       const char *passwd, const char *db,
 
1194
                       uint32_t port, const char *unix_socket, uint32_t client_flag)
 
1195
{
 
1196
  char          buff[NAME_LEN+USERNAME_LENGTH+100];
 
1197
  char          *end,*host_info=NULL;
 
1198
  uint32_t         pkt_length;
 
1199
  NET           *net= &drizzle->net;
 
1200
  init_sigpipe_variables
 
1201
 
 
1202
  /* Don't give sigpipe errors if the client doesn't want them */
 
1203
  set_sigpipe(drizzle);
 
1204
  drizzle->methods= &client_methods;
 
1205
  net->vio = 0;        /* If something goes wrong */
 
1206
  drizzle->client_flag=0;      /* For handshake */
 
1207
 
 
1208
  /* use default options */
 
1209
  if (drizzle->options.my_cnf_file || drizzle->options.my_cnf_group)
 
1210
  {
 
1211
    drizzle_read_default_options(&drizzle->options,
 
1212
             (drizzle->options.my_cnf_file ?
 
1213
        drizzle->options.my_cnf_file : "my"),
 
1214
             drizzle->options.my_cnf_group);
 
1215
    my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
1216
    my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
1217
    drizzle->options.my_cnf_file=drizzle->options.my_cnf_group=0;
 
1218
  }
 
1219
 
 
1220
  /* Some empty-string-tests are done because of ODBC */
 
1221
  if (!host || !host[0])
 
1222
    host=drizzle->options.host;
 
1223
  if (!user || !user[0])
 
1224
  {
 
1225
    user=drizzle->options.user;
 
1226
    if (!user)
 
1227
      user= "";
 
1228
  }
 
1229
  if (!passwd)
 
1230
  {
 
1231
    passwd=drizzle->options.password;
 
1232
    if (!passwd)
 
1233
      passwd= "";
 
1234
  }
 
1235
  if (!db || !db[0])
 
1236
    db=drizzle->options.db;
 
1237
  if (!port)
 
1238
    port=drizzle->options.port;
 
1239
  if (!unix_socket)
 
1240
    unix_socket=drizzle->options.unix_socket;
 
1241
 
 
1242
  drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
 
1243
 
 
1244
  /*
 
1245
    Part 0: Grab a socket and connect it to the server
 
1246
  */
 
1247
  if (!net->vio &&
 
1248
      (!drizzle->options.protocol ||
 
1249
       drizzle->options.protocol == DRIZZLE_PROTOCOL_TCP))
 
1250
  {
 
1251
    struct addrinfo *res_lst, hints, *t_res;
 
1252
    int gai_errno;
 
1253
    char port_buf[NI_MAXSERV];
 
1254
 
 
1255
    unix_socket=0;        /* This is not used */
 
1256
 
 
1257
    if (!port)
 
1258
      port= drizzle_port;
 
1259
 
 
1260
    if (!host)
 
1261
      host= LOCAL_HOST;
 
1262
 
 
1263
    snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
 
1264
 
 
1265
    memset(&hints, 0, sizeof(hints));
 
1266
    hints.ai_socktype= SOCK_STREAM;
 
1267
 
 
1268
    snprintf(port_buf, NI_MAXSERV, "%d", port);
 
1269
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
 
1270
 
 
1271
    if (gai_errno != 0)
 
1272
    {
 
1273
      set_drizzle_extended_error(drizzle, CR_UNKNOWN_HOST, unknown_sqlstate,
 
1274
                               ER(CR_UNKNOWN_HOST), host, errno);
 
1275
 
 
1276
      goto error;
 
1277
    }
 
1278
 
 
1279
    for (t_res= res_lst; t_res != NULL; t_res= t_res->ai_next)
 
1280
    {
 
1281
      int sock= socket(t_res->ai_family, t_res->ai_socktype,
 
1282
                       t_res->ai_protocol);
 
1283
      if (sock == SOCKET_ERROR)
 
1284
        continue;
 
1285
 
 
1286
      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
 
1287
      if (! net->vio )
 
1288
      {
 
1289
        close(sock);
 
1290
        continue;
 
1291
      }
 
1292
 
 
1293
      if (connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
 
1294
      {
 
1295
        vio_delete(net->vio);
 
1296
        net->vio= 0;
 
1297
        continue;
 
1298
      }
 
1299
      break;
 
1300
    }
 
1301
 
 
1302
    freeaddrinfo(res_lst);
 
1303
  }
 
1304
 
 
1305
  if (!net->vio)
 
1306
  {
 
1307
    set_drizzle_extended_error(drizzle, CR_CONN_HOST_ERROR, unknown_sqlstate,
 
1308
                               ER(CR_CONN_HOST_ERROR), host, socket_errno);
 
1309
    goto error;
 
1310
  }
 
1311
 
 
1312
  if (my_net_init(net, net->vio))
 
1313
  {
 
1314
    vio_delete(net->vio);
 
1315
    net->vio = 0;
 
1316
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1317
    goto error;
 
1318
  }
 
1319
  vio_keepalive(net->vio,true);
 
1320
 
 
1321
  /* If user set read_timeout, let it override the default */
 
1322
  if (drizzle->options.read_timeout)
 
1323
    my_net_set_read_timeout(net, drizzle->options.read_timeout);
 
1324
 
 
1325
  /* If user set write_timeout, let it override the default */
 
1326
  if (drizzle->options.write_timeout)
 
1327
    my_net_set_write_timeout(net, drizzle->options.write_timeout);
 
1328
 
 
1329
  if (drizzle->options.max_allowed_packet)
 
1330
    net->max_packet_size= drizzle->options.max_allowed_packet;
 
1331
 
 
1332
  /* Get version info */
 
1333
  drizzle->protocol_version= PROTOCOL_VERSION;  /* Assume this */
 
1334
  if (drizzle->options.connect_timeout &&
 
1335
      vio_poll_read(net->vio, drizzle->options.connect_timeout))
 
1336
  {
 
1337
    set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1338
                             ER(CR_SERVER_LOST_EXTENDED),
 
1339
                             "waiting for initial communication packet",
 
1340
                             errno);
 
1341
    goto error;
 
1342
  }
 
1343
 
 
1344
  /*
 
1345
    Part 1: Connection established, read and parse first packet
 
1346
  */
 
1347
 
 
1348
  if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
 
1349
  {
 
1350
    if (drizzle->net.last_errno == CR_SERVER_LOST)
 
1351
      set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1352
                               ER(CR_SERVER_LOST_EXTENDED),
 
1353
                               "reading initial communication packet",
 
1354
                               errno);
 
1355
    goto error;
 
1356
  }
 
1357
  /* Check if version of protocol matches current one */
 
1358
 
 
1359
  drizzle->protocol_version= net->read_pos[0];
 
1360
  if (drizzle->protocol_version != PROTOCOL_VERSION)
 
1361
  {
 
1362
    set_drizzle_extended_error(drizzle, CR_VERSION_ERROR, unknown_sqlstate,
 
1363
                             ER(CR_VERSION_ERROR), drizzle->protocol_version,
 
1364
                             PROTOCOL_VERSION);
 
1365
    goto error;
 
1366
  }
 
1367
  end=strend((char*) net->read_pos+1);
 
1368
  drizzle->thread_id=uint4korr(end+1);
 
1369
  end+=5;
 
1370
  /*
 
1371
    Scramble is split into two parts because old clients does not understand
 
1372
    long scrambles; here goes the first part.
 
1373
  */
 
1374
  strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
 
1375
  end+= SCRAMBLE_LENGTH_323+1;
 
1376
 
 
1377
  if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
 
1378
    drizzle->server_capabilities=uint2korr(end);
 
1379
  if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
 
1380
  {
 
1381
    /* New protocol with 16 bytes to describe server characteristics */
 
1382
    drizzle->server_language=end[2];
 
1383
    drizzle->server_status=uint2korr(end+3);
 
1384
  }
 
1385
  end+= 18;
 
1386
  if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
 
1387
                           (char *) net->read_pos))
 
1388
    strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
 
1389
            SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
 
1390
  else
 
1391
    drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
 
1392
 
 
1393
  if (drizzle->options.secure_auth && passwd[0] &&
 
1394
      !(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
 
1395
  {
 
1396
    set_drizzle_error(drizzle, CR_SECURE_AUTH, unknown_sqlstate);
 
1397
    goto error;
 
1398
  }
 
1399
 
 
1400
  if (drizzle_init_character_set(drizzle))
 
1401
    goto error;
 
1402
 
 
1403
  /* Save connection information */
 
1404
  if (!my_multi_malloc(MYF(0),
 
1405
           &drizzle->host_info, (uint) strlen(host_info)+1,
 
1406
           &drizzle->host,      (uint) strlen(host)+1,
 
1407
           &drizzle->unix_socket,unix_socket ?
 
1408
           (uint) strlen(unix_socket)+1 : (uint) 1,
 
1409
           &drizzle->server_version,
 
1410
           (uint) (end - (char*) net->read_pos),
 
1411
           NullS) ||
 
1412
      !(drizzle->user=my_strdup(user,MYF(0))) ||
 
1413
      !(drizzle->passwd=my_strdup(passwd,MYF(0))))
 
1414
  {
 
1415
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1416
    goto error;
 
1417
  }
 
1418
  strcpy(drizzle->host_info,host_info);
 
1419
  strcpy(drizzle->host,host);
 
1420
  if (unix_socket)
 
1421
    strcpy(drizzle->unix_socket,unix_socket);
 
1422
  else
 
1423
    drizzle->unix_socket=0;
 
1424
  strcpy(drizzle->server_version,(char*) net->read_pos+1);
 
1425
  drizzle->port=port;
 
1426
 
 
1427
  /*
 
1428
    Part 2: format and send client info to the server for access check
 
1429
  */
 
1430
 
 
1431
  client_flag|=drizzle->options.client_flag;
 
1432
  client_flag|=CLIENT_CAPABILITIES;
 
1433
  if (client_flag & CLIENT_MULTI_STATEMENTS)
 
1434
    client_flag|= CLIENT_MULTI_RESULTS;
 
1435
 
 
1436
  if (db)
 
1437
    client_flag|=CLIENT_CONNECT_WITH_DB;
 
1438
 
 
1439
  /* Remove options that server doesn't support */
 
1440
  client_flag= ((client_flag &
 
1441
     ~(CLIENT_COMPRESS | CLIENT_SSL)) |
 
1442
    (client_flag & drizzle->server_capabilities));
 
1443
  client_flag&= ~CLIENT_COMPRESS;
 
1444
 
 
1445
  int4store(buff, client_flag);
 
1446
  int4store(buff+4, net->max_packet_size);
 
1447
  buff[8]= (char) drizzle->charset->number;
 
1448
  memset(buff+9, 0, 32-9);
 
1449
  end= buff+32;
 
1450
 
 
1451
  drizzle->client_flag=client_flag;
 
1452
 
 
1453
  /* This needs to be changed as it's not useful with big packets */
 
1454
  if (user && user[0])
 
1455
    strncpy(end,user,USERNAME_LENGTH);          /* Max user name */
 
1456
  else
 
1457
    read_user_name((char*) end);
 
1458
 
 
1459
  /* We have to handle different version of handshake here */
 
1460
  end= strend(end) + 1;
 
1461
  if (passwd[0])
 
1462
  {
 
1463
    {
 
1464
      *end++= SCRAMBLE_LENGTH;
 
1465
      memset(end, 0, SCRAMBLE_LENGTH-1);
 
1466
      memcpy(end, passwd, strlen(passwd));
 
1467
      end+= SCRAMBLE_LENGTH;
 
1468
    }
 
1469
  }
 
1470
  else
 
1471
    *end++= '\0';                               /* empty password */
 
1472
 
 
1473
  /* Add database if needed */
 
1474
  if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
 
1475
  {
 
1476
    end= strncpy(end, db, NAME_LEN) + NAME_LEN + 1;
 
1477
    drizzle->db= my_strdup(db,MYF(MY_WME));
 
1478
    db= 0;
 
1479
  }
 
1480
  /* Write authentication package */
 
1481
  if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
 
1482
  {
 
1483
    set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1484
                             ER(CR_SERVER_LOST_EXTENDED),
 
1485
                             "sending authentication information",
 
1486
                             errno);
 
1487
    goto error;
 
1488
  }
 
1489
 
 
1490
  /*
 
1491
    Part 3: Authorization data's been sent. Now server can reply with
 
1492
    OK-packet, or re-request scrambled password.
 
1493
  */
 
1494
 
 
1495
  if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
 
1496
  {
 
1497
    if (drizzle->net.last_errno == CR_SERVER_LOST)
 
1498
      set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1499
                               ER(CR_SERVER_LOST_EXTENDED),
 
1500
                               "reading authorization packet",
 
1501
                               errno);
 
1502
    goto error;
 
1503
  }
 
1504
 
 
1505
  if (client_flag & CLIENT_COMPRESS)    /* We will use compression */
 
1506
    net->compress=1;
 
1507
 
 
1508
 
 
1509
  if (db && drizzle_select_db(drizzle, db))
 
1510
  {
 
1511
    if (drizzle->net.last_errno == CR_SERVER_LOST)
 
1512
        set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1513
                                 ER(CR_SERVER_LOST_EXTENDED),
 
1514
                                 "Setting intital database",
 
1515
                                 errno);
 
1516
    goto error;
 
1517
  }
 
1518
 
 
1519
  if (drizzle->options.init_commands)
 
1520
  {
 
1521
    DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
 
1522
    char **ptr= (char**)init_commands->buffer;
 
1523
    char **end_command= ptr + init_commands->elements;
 
1524
 
 
1525
    bool reconnect=drizzle->reconnect;
 
1526
    drizzle->reconnect=0;
 
1527
 
 
1528
    for (; ptr < end_command; ptr++)
 
1529
    {
 
1530
      DRIZZLE_RES *res;
 
1531
      if (drizzle_real_query(drizzle,*ptr, (uint32_t) strlen(*ptr)))
 
1532
  goto error;
 
1533
      if (drizzle->fields)
 
1534
      {
 
1535
  if (!(res= cli_use_result(drizzle)))
 
1536
    goto error;
 
1537
  drizzle_free_result(res);
 
1538
      }
 
1539
    }
 
1540
    drizzle->reconnect=reconnect;
 
1541
  }
 
1542
 
 
1543
  reset_sigpipe(drizzle);
 
1544
  return(drizzle);
 
1545
 
 
1546
error:
 
1547
  reset_sigpipe(drizzle);
 
1548
  {
 
1549
    /* Free alloced memory */
 
1550
    end_server(drizzle);
 
1551
    drizzle_close_free(drizzle);
 
1552
    if (!(((uint32_t) client_flag) & CLIENT_REMEMBER_OPTIONS))
 
1553
      drizzle_close_free_options(drizzle);
 
1554
  }
 
1555
  return(0);
 
1556
}
 
1557
 
 
1558
 
 
1559
bool drizzle_reconnect(DRIZZLE *drizzle)
 
1560
{
 
1561
  DRIZZLE tmp_drizzle;
 
1562
  assert(drizzle);
 
1563
 
 
1564
  if (!drizzle->reconnect ||
 
1565
      (drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
 
1566
  {
 
1567
    /* Allow reconnect next time */
 
1568
    drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
 
1569
    set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
 
1570
    return(1);
 
1571
  }
 
1572
  drizzle_create(&tmp_drizzle);
 
1573
  tmp_drizzle.options= drizzle->options;
 
1574
  tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
 
1575
 
 
1576
  if (!drizzle_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
 
1577
        drizzle->db, drizzle->port, drizzle->unix_socket,
 
1578
        drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
 
1579
  {
 
1580
    drizzle->net.last_errno= tmp_drizzle.net.last_errno;
 
1581
    strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
 
1582
    strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
 
1583
    return(1);
 
1584
  }
 
1585
  if (drizzle_set_character_set(&tmp_drizzle, drizzle->charset->csname))
 
1586
  {
 
1587
    memset(&tmp_drizzle.options, 0, sizeof(tmp_drizzle.options));
 
1588
    drizzle_close(&tmp_drizzle);
 
1589
    drizzle->net.last_errno= tmp_drizzle.net.last_errno;
 
1590
    strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
 
1591
    strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
 
1592
    return(1);
 
1593
  }
 
1594
 
 
1595
  tmp_drizzle.reconnect= 1;
 
1596
  tmp_drizzle.free_me= drizzle->free_me;
 
1597
 
 
1598
  /* Don't free options as these are now used in tmp_drizzle */
 
1599
  memset(&drizzle->options, 0, sizeof(drizzle->options));
 
1600
  drizzle->free_me=0;
 
1601
  drizzle_close(drizzle);
 
1602
  *drizzle=tmp_drizzle;
 
1603
  net_clear(&drizzle->net, 1);
 
1604
  drizzle->affected_rows= ~(uint64_t) 0;
 
1605
  return(0);
 
1606
}
 
1607
 
 
1608
 
 
1609
/**************************************************************************
 
1610
  Set current database
 
1611
**************************************************************************/
 
1612
 
 
1613
int
 
1614
drizzle_select_db(DRIZZLE *drizzle, const char *db)
 
1615
{
 
1616
  int error;
 
1617
 
 
1618
  if ((error=simple_command(drizzle,COM_INIT_DB, (const uchar*) db,
 
1619
                            (uint32_t) strlen(db),0)))
 
1620
    return(error);
 
1621
  my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
 
1622
  drizzle->db=my_strdup(db,MYF(MY_WME));
 
1623
  return(0);
 
1624
}
 
1625
 
 
1626
 
 
1627
/*************************************************************************
 
1628
  Send a QUIT to the server and close the connection
 
1629
  If handle is alloced by DRIZZLE connect free it.
 
1630
*************************************************************************/
 
1631
 
 
1632
static void drizzle_close_free_options(DRIZZLE *drizzle)
 
1633
{
 
1634
  my_free(drizzle->options.user,MYF(MY_ALLOW_ZERO_PTR));
 
1635
  my_free(drizzle->options.host,MYF(MY_ALLOW_ZERO_PTR));
 
1636
  my_free(drizzle->options.password,MYF(MY_ALLOW_ZERO_PTR));
 
1637
  my_free(drizzle->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
 
1638
  my_free(drizzle->options.db,MYF(MY_ALLOW_ZERO_PTR));
 
1639
  my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
1640
  my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
1641
  my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
1642
  my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
1643
  my_free(drizzle->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
 
1644
  if (drizzle->options.init_commands)
 
1645
  {
 
1646
    DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
 
1647
    char **ptr= (char**)init_commands->buffer;
 
1648
    char **end= ptr + init_commands->elements;
 
1649
    for (; ptr<end; ptr++)
 
1650
      my_free(*ptr,MYF(MY_WME));
 
1651
    delete_dynamic(init_commands);
 
1652
    my_free((char*)init_commands,MYF(MY_WME));
 
1653
  }
 
1654
  memset(&drizzle->options, 0, sizeof(drizzle->options));
 
1655
  return;
 
1656
}
 
1657
 
 
1658
 
 
1659
static void drizzle_close_free(DRIZZLE *drizzle)
 
1660
{
 
1661
  my_free((uchar*) drizzle->host_info,MYF(MY_ALLOW_ZERO_PTR));
 
1662
  my_free(drizzle->user,MYF(MY_ALLOW_ZERO_PTR));
 
1663
  my_free(drizzle->passwd,MYF(MY_ALLOW_ZERO_PTR));
 
1664
  my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
 
1665
  my_free(drizzle->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
 
1666
  drizzle->info_buffer= 0;
 
1667
 
 
1668
  /* Clear pointers for better safety */
 
1669
  drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
 
1670
}
 
1671
 
 
1672
 
 
1673
void drizzle_close(DRIZZLE *drizzle)
 
1674
{
 
1675
  if (drizzle)          /* Some simple safety */
 
1676
  {
 
1677
    /* If connection is still up, send a QUIT message */
 
1678
    if (drizzle->net.vio != 0)
 
1679
    {
 
1680
      free_old_query(drizzle);
 
1681
      drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
 
1682
      drizzle->reconnect=0;
 
1683
      simple_command(drizzle,COM_QUIT,(uchar*) 0,0,1);
 
1684
      end_server(drizzle);      /* Sets drizzle->net.vio= 0 */
 
1685
    }
 
1686
    drizzle_close_free_options(drizzle);
 
1687
    drizzle_close_free(drizzle);
 
1688
    if (drizzle->free_me)
 
1689
      my_free((uchar*) drizzle,MYF(0));
 
1690
  }
 
1691
  return;
 
1692
}
 
1693
 
 
1694
 
 
1695
static bool cli_read_query_result(DRIZZLE *drizzle)
 
1696
{
 
1697
  uchar *pos;
 
1698
  uint32_t field_count;
 
1699
  DRIZZLE_DATA *fields;
 
1700
  uint32_t length;
 
1701
 
 
1702
  if ((length = cli_safe_read(drizzle)) == packet_error)
 
1703
    return(1);
 
1704
  free_old_query(drizzle);    /* Free old result */
 
1705
#ifdef DRIZZLE_CLIENT      /* Avoid warn of unused labels*/
 
1706
get_info:
 
1707
#endif
 
1708
  pos=(uchar*) drizzle->net.read_pos;
 
1709
  if ((field_count= net_field_length(&pos)) == 0)
 
1710
  {
 
1711
    drizzle->affected_rows= net_field_length_ll(&pos);
 
1712
    drizzle->insert_id=    net_field_length_ll(&pos);
 
1713
 
 
1714
    drizzle->server_status= uint2korr(pos); pos+=2;
 
1715
    drizzle->warning_count= uint2korr(pos); pos+=2;
 
1716
 
 
1717
    if (pos < drizzle->net.read_pos+length && net_field_length(&pos))
 
1718
      drizzle->info=(char*) pos;
 
1719
    return(0);
 
1720
  }
 
1721
#ifdef DRIZZLE_CLIENT
 
1722
  if (field_count == NULL_LENGTH)    /* LOAD DATA LOCAL INFILE */
 
1723
  {
 
1724
    int error;
 
1725
 
 
1726
    if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES))
 
1727
    {
 
1728
      set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
 
1729
      return(1);
 
1730
    }  
 
1731
 
 
1732
    error= handle_local_infile(drizzle,(char*) pos);
 
1733
    if ((length= cli_safe_read(drizzle)) == packet_error || error)
 
1734
      return(1);
 
1735
    goto get_info;        /* Get info packet */
 
1736
  }
 
1737
#endif
 
1738
  if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
 
1739
    drizzle->server_status|= SERVER_STATUS_IN_TRANS;
 
1740
 
 
1741
  if (!(fields=cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, 7)))
 
1742
    return(1);
 
1743
  if (!(drizzle->fields= unpack_fields(fields,&drizzle->field_alloc,
 
1744
            (uint) field_count, 0)))
 
1745
    return(1);
 
1746
  drizzle->status= DRIZZLE_STATUS_GET_RESULT;
 
1747
  drizzle->field_count= (uint) field_count;
 
1748
  return(0);
 
1749
}
 
1750
 
 
1751
 
 
1752
/*
 
1753
  Send the query and return so we can do something else.
 
1754
  Needs to be followed by drizzle_read_query_result() when we want to
 
1755
  finish processing it.
 
1756
*/
 
1757
 
 
1758
int32_t
 
1759
drizzle_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
 
1760
{
 
1761
  return(simple_command(drizzle, COM_QUERY, (uchar*) query, length, 1));
 
1762
}
 
1763
 
 
1764
 
 
1765
int32_t
 
1766
drizzle_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
 
1767
{
 
1768
  if (drizzle_send_query(drizzle,query,length))
 
1769
    return(1);
 
1770
  return((int) (*drizzle->methods->read_query_result)(drizzle));
 
1771
}
 
1772
 
 
1773
 
 
1774
/**************************************************************************
 
1775
  Alloc result struct for buffered results. All rows are read to buffer.
 
1776
  drizzle_data_seek may be used.
 
1777
**************************************************************************/
 
1778
 
 
1779
DRIZZLE_RES * drizzle_store_result(DRIZZLE *drizzle)
 
1780
{
 
1781
  DRIZZLE_RES *result;
 
1782
 
 
1783
  if (!drizzle->fields)
 
1784
    return(0);
 
1785
  if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
 
1786
  {
 
1787
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
1788
    return(0);
 
1789
  }
 
1790
  drizzle->status=DRIZZLE_STATUS_READY;    /* server is ready */
 
1791
  if (!(result=(DRIZZLE_RES*) my_malloc((uint) (sizeof(DRIZZLE_RES)+
 
1792
                sizeof(uint32_t) *
 
1793
                drizzle->field_count),
 
1794
              MYF(MY_WME | MY_ZEROFILL))))
 
1795
  {
 
1796
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1797
    return(0);
 
1798
  }
 
1799
  result->methods= drizzle->methods;
 
1800
  result->eof= 1;        /* Marker for buffered */
 
1801
  result->lengths= (uint32_t*) (result+1);
 
1802
  if (!(result->data=
 
1803
  (*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
 
1804
  {
 
1805
    my_free((uchar*) result,MYF(0));
 
1806
    return(0);
 
1807
  }
 
1808
  drizzle->affected_rows= result->row_count= result->data->rows;
 
1809
  result->data_cursor=  result->data->data;
 
1810
  result->fields=  drizzle->fields;
 
1811
  result->field_alloc=  drizzle->field_alloc;
 
1812
  result->field_count=  drizzle->field_count;
 
1813
  /* The rest of result members is zeroed in malloc */
 
1814
  drizzle->fields=0;        /* fields is now in result */
 
1815
  clear_alloc_root(&drizzle->field_alloc);
 
1816
  /* just in case this was mistakenly called after drizzle_stmt_execute() */
 
1817
  drizzle->unbuffered_fetch_owner= 0;
 
1818
  return(result);        /* Data fetched */
 
1819
}
 
1820
 
 
1821
 
 
1822
/**************************************************************************
 
1823
  Alloc struct for use with unbuffered reads. Data is fetched by domand
 
1824
  when calling to drizzle_fetch_row.
 
1825
  DRIZZLE_DATA_seek is a noop.
 
1826
 
 
1827
  No other queries may be specified with the same DRIZZLE handle.
 
1828
  There shouldn't be much processing per row because DRIZZLE server shouldn't
 
1829
  have to wait for the client (and will not wait more than 30 sec/packet).
 
1830
**************************************************************************/
 
1831
 
 
1832
static DRIZZLE_RES * cli_use_result(DRIZZLE *drizzle)
 
1833
{
 
1834
  DRIZZLE_RES *result;
 
1835
 
 
1836
  if (!drizzle->fields)
 
1837
    return(0);
 
1838
  if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
 
1839
  {
 
1840
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
1841
    return(0);
 
1842
  }
 
1843
  if (!(result=(DRIZZLE_RES*) my_malloc(sizeof(*result)+
 
1844
              sizeof(uint32_t)*drizzle->field_count,
 
1845
              MYF(MY_WME | MY_ZEROFILL))))
 
1846
    return(0);
 
1847
  result->lengths=(uint32_t*) (result+1);
 
1848
  result->methods= drizzle->methods;
 
1849
  if (!(result->row=(DRIZZLE_ROW)
 
1850
  my_malloc(sizeof(result->row[0])*(drizzle->field_count+1), MYF(MY_WME))))
 
1851
  {          /* Ptrs: to one row */
 
1852
    my_free((uchar*) result,MYF(0));
 
1853
    return(0);
 
1854
  }
 
1855
  result->fields=  drizzle->fields;
 
1856
  result->field_alloc=  drizzle->field_alloc;
 
1857
  result->field_count=  drizzle->field_count;
 
1858
  result->current_field=0;
 
1859
  result->handle=  drizzle;
 
1860
  result->current_row=  0;
 
1861
  drizzle->fields=0;      /* fields is now in result */
 
1862
  clear_alloc_root(&drizzle->field_alloc);
 
1863
  drizzle->status=DRIZZLE_STATUS_USE_RESULT;
 
1864
  drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
 
1865
  return(result);      /* Data is read to be fetched */
 
1866
}
 
1867
 
 
1868
 
428
1869
/**************************************************************************
429
1870
  Return next row of the query results
430
1871
**************************************************************************/
439
1880
      DRIZZLE *drizzle= res->handle;
440
1881
      if (drizzle->status != DRIZZLE_STATUS_USE_RESULT)
441
1882
      {
442
 
        drizzle_set_error(drizzle,
443
 
                          res->unbuffered_fetch_cancelled ?
444
 
                          CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
445
 
                          sqlstate_get_unknown());
 
1883
        set_drizzle_error(drizzle,
 
1884
                        res->unbuffered_fetch_cancelled ?
 
1885
                        CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
 
1886
                        unknown_sqlstate);
446
1887
      }
447
1888
      else if (!(read_one_row(drizzle, res->field_count, res->row, res->lengths)))
448
1889
      {
499
1940
{
500
1941
  switch (option) {
501
1942
  case DRIZZLE_OPT_CONNECT_TIMEOUT:
502
 
    drizzle->options.connect_timeout= *(uint32_t*) arg;
 
1943
    drizzle->options.connect_timeout= *(uint*) arg;
503
1944
    break;
504
1945
  case DRIZZLE_OPT_READ_TIMEOUT:
505
 
    drizzle->options.read_timeout= *(uint32_t*) arg;
 
1946
    drizzle->options.read_timeout= *(uint*) arg;
506
1947
    break;
507
1948
  case DRIZZLE_OPT_WRITE_TIMEOUT:
508
 
    drizzle->options.write_timeout= *(uint32_t*) arg;
 
1949
    drizzle->options.write_timeout= *(uint*) arg;
509
1950
    break;
510
1951
  case DRIZZLE_OPT_COMPRESS:
511
1952
    drizzle->options.compress= 1;      /* Remember for connect */
512
1953
    drizzle->options.client_flag|= CLIENT_COMPRESS;
513
1954
    break;
514
1955
  case DRIZZLE_OPT_LOCAL_INFILE:      /* Allow LOAD DATA LOCAL ?*/
515
 
    if (!arg || (*(uint32_t*) arg) ? 1 : 0)
 
1956
    if (!arg || test(*(uint*) arg))
516
1957
      drizzle->options.client_flag|= CLIENT_LOCAL_FILES;
517
1958
    else
518
1959
      drizzle->options.client_flag&= ~CLIENT_LOCAL_FILES;
519
1960
    break;
 
1961
  case DRIZZLE_INIT_COMMAND:
 
1962
    add_init_command(&drizzle->options,arg);
 
1963
    break;
520
1964
  case DRIZZLE_READ_DEFAULT_FILE:
521
 
    if (drizzle->options.my_cnf_file != NULL)
522
 
      free(drizzle->options.my_cnf_file);
523
 
    drizzle->options.my_cnf_file=strdup(arg);
 
1965
    my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
1966
    drizzle->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
524
1967
    break;
525
1968
  case DRIZZLE_READ_DEFAULT_GROUP:
526
 
    if (drizzle->options.my_cnf_group != NULL)
527
 
      free(drizzle->options.my_cnf_group);
528
 
    drizzle->options.my_cnf_group=strdup(arg);
 
1969
    my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
1970
    drizzle->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
 
1971
    break;
 
1972
  case DRIZZLE_SET_CHARSET_DIR:
 
1973
    my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
1974
    drizzle->options.charset_dir=my_strdup(arg,MYF(MY_WME));
 
1975
    break;
 
1976
  case DRIZZLE_SET_CHARSET_NAME:
 
1977
    my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
1978
    drizzle->options.charset_name=my_strdup(arg,MYF(MY_WME));
529
1979
    break;
530
1980
  case DRIZZLE_OPT_PROTOCOL:
 
1981
    drizzle->options.protocol= *(const uint*) arg;
531
1982
    break;
532
1983
  case DRIZZLE_OPT_USE_REMOTE_CONNECTION:
533
1984
  case DRIZZLE_OPT_GUESS_CONNECTION:
534
1985
    drizzle->options.methods_to_use= option;
535
1986
    break;
536
1987
  case DRIZZLE_SET_CLIENT_IP:
537
 
    drizzle->options.client_ip= strdup(arg);
 
1988
    drizzle->options.client_ip= my_strdup(arg, MYF(MY_WME));
538
1989
    break;
539
1990
  case DRIZZLE_SECURE_AUTH:
540
1991
    drizzle->options.secure_auth= *(const bool *) arg;
541
1992
    break;
542
1993
  case DRIZZLE_REPORT_DATA_TRUNCATION:
543
 
    drizzle->options.report_data_truncation= (*(const bool *) arg) ? 1 : 0;
 
1994
    drizzle->options.report_data_truncation= test(*(const bool *) arg);
544
1995
    break;
545
1996
  case DRIZZLE_OPT_RECONNECT:
546
1997
    drizzle->reconnect= *(const bool *) arg;
574
2025
  return res->field_count;
575
2026
}
576
2027
 
 
2028
uint drizzle_errno(const DRIZZLE *drizzle)
 
2029
{
 
2030
  return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno;
 
2031
}
 
2032
 
 
2033
 
 
2034
const char * drizzle_error(const DRIZZLE *drizzle)
 
2035
{
 
2036
  return drizzle ? _(drizzle->net.last_error) : _(drizzle_server_last_error);
 
2037
}
 
2038
 
577
2039
 
578
2040
/*
579
2041
  Get version number for server in a form easy to test on
584
2046
 
585
2047
  EXAMPLE
586
2048
    4.1.0-alfa ->  40100
587
 
 
 
2049
 
588
2050
  NOTES
589
2051
    We will ensure that a newer server always has a bigger number.
590
2052
 
595
2057
uint32_t
596
2058
drizzle_get_server_version(const DRIZZLE *drizzle)
597
2059
{
598
 
  uint32_t major, minor, version;
 
2060
  uint major, minor, version;
599
2061
  char *pos= drizzle->server_version, *end_pos;
600
 
  major=   (uint32_t) strtoul(pos, &end_pos, 10);  pos=end_pos+1;
601
 
  minor=   (uint32_t) strtoul(pos, &end_pos, 10);  pos=end_pos+1;
602
 
  version= (uint32_t) strtoul(pos, &end_pos, 10);
 
2062
  major=   (uint) strtoul(pos, &end_pos, 10);  pos=end_pos+1;
 
2063
  minor=   (uint) strtoul(pos, &end_pos, 10);  pos=end_pos+1;
 
2064
  version= (uint) strtoul(pos, &end_pos, 10);
603
2065
  return (uint32_t) major*10000L+(uint32_t) (minor*100+version);
604
2066
}
605
2067
 
 
2068
 
 
2069
/*
 
2070
   drizzle_set_character_set function sends SET NAMES cs_name to
 
2071
   the server (which changes character_set_client, character_set_result
 
2072
   and character_set_connection) and updates drizzle->charset so other
 
2073
   functions like drizzle_real_escape will work correctly.
 
2074
*/
 
2075
int drizzle_set_character_set(DRIZZLE *drizzle, const char *cs_name)
 
2076
{
 
2077
  const CHARSET_INFO *cs;
 
2078
  const char *save_csdir= charsets_dir;
 
2079
 
 
2080
  if (drizzle->options.charset_dir)
 
2081
    charsets_dir= drizzle->options.charset_dir;
 
2082
 
 
2083
  if (strlen(cs_name) < MY_CS_NAME_SIZE &&
 
2084
      (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
 
2085
  {
 
2086
    char buff[MY_CS_NAME_SIZE + 10];
 
2087
    charsets_dir= save_csdir;
 
2088
    sprintf(buff, "SET NAMES %s", cs_name);
 
2089
    if (!drizzle_real_query(drizzle, buff, strlen(buff)))
 
2090
    {
 
2091
      drizzle->charset= cs;
 
2092
    }
 
2093
  }
 
2094
  else
 
2095
  {
 
2096
    char cs_dir_name[FN_REFLEN];
 
2097
    get_charsets_dir(cs_dir_name);
 
2098
    set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
2099
                             ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
 
2100
  }
 
2101
  charsets_dir= save_csdir;
 
2102
  return drizzle->net.last_errno;
 
2103
}
 
2104
 
 
2105