~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/oldlibdrizzle/client.cc

  • Committer: Brian Aker
  • Date: 2009-07-11 08:51:36 UTC
  • mfrom: (1089.3.11 merge)
  • Revision ID: brian@gaz-20090711085136-qj01nwm3qynghwtc
Merge Monty

Show diffs side-by-side

added added

removed removed

Lines of Context:
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 */
 
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
 */
15
19
 
16
20
/*
17
 
  This file is included by both libdrizzle.c (the DRIZZLE client C API)
 
21
  This file is included by both libdrizzleclient.c (the DRIZZLE client C API)
18
22
  and the drizzled server to connect to another DRIZZLE server.
19
23
 
20
24
  The differences for the two cases are:
21
25
 
22
26
  - Things that only works for the client:
23
27
  - Trying to automaticly determinate user name if not supplied to
24
 
    drizzle_connect()
 
28
    drizzleclient_connect()
25
29
  - Support for reading local file with LOAD DATA LOCAL
26
30
  - SHARED memory handling
27
 
  - Protection against sigpipe
28
31
  - Prepared statements
29
 
 
 
32
 
30
33
  - Things that only works for the server
31
34
  - Alarm handling on connect
32
 
 
 
35
 
33
36
  In all other cases, the code should be idential for the client and
34
37
  server.
35
38
*/
36
39
 
37
 
#include <drizzled/global.h>
38
 
 
39
 
#include "drizzle.h"
40
 
 
 
40
 
 
41
#include "libdrizzle_priv.h"
 
42
#include "net_serv.h"
 
43
#include "pack.h"
 
44
#include "errmsg.h"
 
45
#include "drizzle_methods.h"
 
46
 
 
47
#include <stdarg.h>
41
48
#include <sys/poll.h>
42
49
#include <sys/ioctl.h>
43
50
 
47
54
#undef max_allowed_packet
48
55
#undef net_buffer_length
49
56
 
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>
58
57
 
59
58
#include <sys/stat.h>
60
59
#include <signal.h>
77
76
#include <sys/un.h>
78
77
 
79
78
#include <errno.h>
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
 
}
174
 
 
 
79
 
 
80
 
 
81
#include <drizzled/gettext.h>
 
82
 
 
83
using namespace std;
175
84
 
176
85
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
177
86
struct passwd *getpwuid(uid_t);
178
87
char* getlogin(void);
179
88
#endif
180
89
 
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
 
}
280
90
 
281
91
/*****************************************************************************
282
92
  Read a packet from server. Give error message if socket was down
283
93
  or packet is an error message
284
94
*****************************************************************************/
285
95
 
286
 
uint32_t cli_safe_read(DRIZZLE *drizzle)
 
96
/* I'm not sure if this is even used anymore, but now that libdrizzleclient is
 
97
   server only, this is safe to set here. */
 
98
extern "C" bool safe_read_error_impl(NET *net);
 
99
 
 
100
bool safe_read_error_impl(NET *net)
 
101
{
 
102
  if (net->vio)
 
103
    return drizzleclient_vio_was_interrupted(net->vio);
 
104
  return false;
 
105
}
 
106
 
 
107
 
 
108
safe_read_error_hook_func safe_read_error_hook= safe_read_error_impl;
 
109
 
 
110
uint32_t drizzleclient_cli_safe_read(DRIZZLE *drizzle)
287
111
{
288
112
  NET *net= &drizzle->net;
289
113
  uint32_t len=0;
290
 
  init_sigpipe_variables
291
114
 
292
 
  /* Don't give sigpipe errors if the client doesn't want them */
293
 
  set_sigpipe(drizzle);
294
115
  if (net->vio != 0)
295
 
    len=my_net_read(net);
296
 
  reset_sigpipe(drizzle);
 
116
    len=drizzleclient_net_read(net);
297
117
 
298
118
  if (len == packet_error || len == 0)
299
119
  {
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);
 
120
    if (safe_read_error_hook != NULL)
 
121
      if (safe_read_error_hook(net))
 
122
        return (packet_error);
 
123
    drizzleclient_disconnect(drizzle);
 
124
    drizzleclient_set_error(drizzle, net->last_errno == CR_NET_PACKET_TOO_LARGE ?
 
125
                      CR_NET_PACKET_TOO_LARGE : CR_SERVER_LOST,
 
126
                      drizzleclient_sqlstate_get_unknown());
307
127
    return (packet_error);
308
128
  }
309
129
  if (net->read_pos[0] == 255)
316
136
      len-=2;
317
137
      if (pos[0] == '#')
318
138
      {
319
 
        strncpy(net->sqlstate, pos+1, SQLSTATE_LENGTH);
320
 
        pos+= SQLSTATE_LENGTH+1;
 
139
        strncpy(net->sqlstate, pos+1, LIBDRIZZLE_SQLSTATE_LENGTH);
 
140
        pos+= LIBDRIZZLE_SQLSTATE_LENGTH+1;
321
141
      }
322
142
      else
323
143
      {
326
146
          (unknown error sql state).
327
147
        */
328
148
 
329
 
        strcpy(net->sqlstate, unknown_sqlstate);
 
149
        strcpy(net->sqlstate, drizzleclient_sqlstate_get_unknown());
330
150
      }
331
151
 
332
 
      strncpy(net->last_error,(char*) pos, min((uint) len,
 
152
      strncpy(net->last_error,(char*) pos, min((uint32_t) len,
333
153
              (uint32_t) sizeof(net->last_error)-1));
334
154
    }
335
155
    else
336
 
      set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
 
156
      drizzleclient_set_error(drizzle, CR_UNKNOWN_ERROR, drizzleclient_sqlstate_get_unknown());
337
157
    /*
338
158
      Cover a protocol design error: error packet does not
339
159
      contain the server status. Therefore, the client has no way
350
170
  return len;
351
171
}
352
172
 
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
 
 
362
173
bool
363
 
cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
 
174
drizzleclient_cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
364
175
         const unsigned char *header, uint32_t header_length,
365
176
         const unsigned char *arg, uint32_t arg_length, bool skip_check)
366
177
{
367
178
  NET *net= &drizzle->net;
368
179
  bool result= 1;
369
 
  init_sigpipe_variables
370
180
  bool stmt_skip= false;
371
181
 
372
 
  /* Don't give sigpipe errors if the client doesn't want them */
373
 
  set_sigpipe(drizzle);
374
 
 
375
182
  if (drizzle->net.vio == 0)
376
183
  {            /* Do reconnect if possible */
377
 
    if (drizzle_reconnect(drizzle) || stmt_skip)
 
184
    if (drizzleclient_reconnect(drizzle) || stmt_skip)
378
185
      return(1);
379
186
  }
380
187
  if (drizzle->status != DRIZZLE_STATUS_READY ||
381
188
      drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
382
189
  {
383
 
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
190
    drizzleclient_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC,
 
191
                      drizzleclient_sqlstate_get_unknown());
384
192
    return(1);
385
193
  }
386
194
 
387
 
  net_clear_error(net);
 
195
  drizzleclient_drizzleclient_net_clear_error(net);
388
196
  drizzle->info=0;
389
197
  drizzle->affected_rows= ~(uint64_t) 0;
390
198
  /*
392
200
    the previous command was a shutdown command, we may have the
393
201
    response for the COM_QUIT already in the communication buffer
394
202
  */
395
 
  net_clear(&drizzle->net, (command != COM_QUIT));
 
203
  drizzleclient_net_clear(&drizzle->net, (command != COM_QUIT));
396
204
 
397
 
  if (net_write_command(net,(uchar) command, header, header_length,
 
205
  if (drizzleclient_net_write_command(net,(unsigned char) command, header, header_length,
398
206
      arg, arg_length))
399
207
  {
400
 
    if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
 
208
    if (net->last_errno == CR_NET_PACKET_TOO_LARGE)
401
209
    {
402
 
      set_drizzle_error(drizzle, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
 
210
      drizzleclient_set_error(drizzle, CR_NET_PACKET_TOO_LARGE, drizzleclient_sqlstate_get_unknown());
403
211
      goto end;
404
212
    }
405
 
    end_server(drizzle);
406
 
    if (drizzle_reconnect(drizzle) || stmt_skip)
 
213
    drizzleclient_disconnect(drizzle);
 
214
    if (drizzleclient_reconnect(drizzle) || stmt_skip)
407
215
      goto end;
408
 
    if (net_write_command(net,(uchar) command, header, header_length,
 
216
    if (drizzleclient_net_write_command(net,(unsigned char) command, header, header_length,
409
217
        arg, arg_length))
410
218
    {
411
 
      set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
 
219
      drizzleclient_set_error(drizzle, CR_SERVER_GONE_ERROR, drizzleclient_sqlstate_get_unknown());
412
220
      goto end;
413
221
    }
414
222
  }
415
223
  result=0;
416
224
  if (!skip_check)
417
 
    result= ((drizzle->packet_length=cli_safe_read(drizzle)) == packet_error ?
 
225
    result= ((drizzle->packet_length=drizzleclient_cli_safe_read(drizzle)) == packet_error ?
418
226
       1 : 0);
419
227
end:
420
 
  reset_sigpipe(drizzle);
421
228
  return(result);
422
229
}
423
230
 
424
 
void free_old_query(DRIZZLE *drizzle)
 
231
void drizzleclient_free_old_query(DRIZZLE *drizzle)
425
232
{
426
233
  if (drizzle->fields)
427
 
    free_root(&drizzle->field_alloc,MYF(0));
428
 
  init_alloc_root(&drizzle->field_alloc,8192,0); /* Assume rowlength < 8192 */
 
234
  {
 
235
    /* TODO - we need to de-alloc field storage */
 
236
    free(drizzle->fields->catalog);
 
237
    free(drizzle->fields->db);
 
238
    free(drizzle->fields->table);
 
239
    free(drizzle->fields->org_table);
 
240
    free(drizzle->fields->name);
 
241
    free(drizzle->fields->org_name);
 
242
    free(drizzle->fields->def);
 
243
    free(drizzle->fields);
 
244
 
 
245
  }
 
246
  /* init_alloc_root(&drizzle->field_alloc,8192,0); */ /* Assume rowlength < 8192 */
429
247
  drizzle->fields= 0;
430
248
  drizzle->field_count= 0;      /* For API */
431
249
  drizzle->warning_count= 0;
433
251
  return;
434
252
}
435
253
 
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
 
}
 
254
 
 
255
 
480
256
 
481
257
 
482
258
void
483
 
drizzle_free_result(DRIZZLE_RES *result)
 
259
drizzleclient_free_result(DRIZZLE_RES *result)
484
260
{
485
261
  if (result)
486
262
  {
497
273
          *drizzle->unbuffered_fetch_owner= true;
498
274
      }
499
275
    }
500
 
    free_rows(result->data);
501
 
    if (result->fields)
502
 
      free_root(&result->field_alloc,MYF(0));
 
276
    drizzleclient_free_rows(result->data);
 
277
    /* TODO: free result->fields */
503
278
    if (result->row)
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
 
}
 
279
      free((unsigned char*) result->row);
 
280
    free((unsigned char*) result);
 
281
  }
 
282
}
 
283
 
 
284
 
 
285
 
791
286
 
792
287
/* Read all rows (fields or data) from server */
793
288
 
794
 
DRIZZLE_DATA *cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
 
289
DRIZZLE_DATA *drizzleclient_cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
795
290
{
796
291
  uint32_t  field;
797
292
  uint32_t pkt_len;
802
297
  DRIZZLE_ROWS **prev_ptr,*cur;
803
298
  NET *net = &drizzle->net;
804
299
 
805
 
  if ((pkt_len= cli_safe_read(drizzle)) == packet_error)
 
300
  if ((pkt_len= drizzleclient_cli_safe_read(drizzle)) == packet_error)
806
301
    return(0);
807
 
  if (!(result=(DRIZZLE_DATA*) my_malloc(sizeof(DRIZZLE_DATA),
808
 
               MYF(MY_WME | MY_ZEROFILL))))
 
302
  if (!(result=(DRIZZLE_DATA*) malloc(sizeof(DRIZZLE_DATA))))
809
303
  {
810
 
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
304
    drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY,
 
305
                      drizzleclient_sqlstate_get_unknown());
811
306
    return(0);
812
307
  }
813
 
  init_alloc_root(&result->alloc,8192,0);  /* Assume rowlength < 8192 */
814
 
  result->alloc.min_malloc=sizeof(DRIZZLE_ROWS);
 
308
  memset(result, 0, sizeof(DRIZZLE_DATA));
815
309
  prev_ptr= &result->data;
816
310
  result->rows=0;
817
311
  result->fields=fields;
820
314
    The last EOF packet is either a 254 (0xFE) character followed by 1-7 status bytes.
821
315
 
822
316
    This doesn't conflict with normal usage of 254 which stands for a
823
 
    string where the length of the string is 8 bytes. (see net_field_length())
 
317
    string where the length of the string is 8 bytes. (see drizzleclient_net_field_length())
824
318
  */
825
319
 
826
320
  while (*(cp=net->read_pos) != DRIZZLE_PROTOCOL_NO_MORE_DATA || pkt_len >= 8)
827
321
  {
828
322
    result->rows++;
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))))
 
323
    if (!(cur= (DRIZZLE_ROWS*) malloc(sizeof(DRIZZLE_ROWS))) ||
 
324
        !(cur->data= ((DRIZZLE_ROW) malloc((fields+1)*sizeof(char *)+pkt_len))))
834
325
    {
835
 
      free_rows(result);
836
 
      set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
326
      drizzleclient_free_rows(result);
 
327
      drizzleclient_set_error(drizzle, CR_OUT_OF_MEMORY, drizzleclient_sqlstate_get_unknown());
837
328
      return(0);
838
329
    }
839
330
    *prev_ptr=cur;
842
333
    end_to=to+pkt_len-1;
843
334
    for (field=0 ; field < fields ; field++)
844
335
    {
845
 
      if ((len= net_field_length(&cp)) == NULL_LENGTH)
 
336
      if ((len= drizzleclient_net_field_length(&cp)) == NULL_LENGTH)
846
337
      {            /* null field */
847
338
        cur->data[field] = 0;
848
339
      }
851
342
        cur->data[field] = to;
852
343
        if (len > (uint32_t) (end_to - to))
853
344
        {
854
 
          free_rows(result);
855
 
          set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
 
345
          drizzleclient_free_rows(result);
 
346
          drizzleclient_set_error(drizzle, CR_MALFORMED_PACKET,
 
347
                            drizzleclient_sqlstate_get_unknown());
856
348
          return(0);
857
349
        }
858
350
        memcpy(to, cp, len);
867
359
      }
868
360
    }
869
361
    cur->data[field]=to;      /* End of last field */
870
 
    if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
362
    if ((pkt_len=drizzleclient_cli_safe_read(drizzle)) == packet_error)
871
363
    {
872
 
      free_rows(result);
 
364
      drizzleclient_free_rows(result);
873
365
      return(0);
874
366
    }
875
367
  }
891
383
static int32_t
892
384
read_one_row(DRIZZLE *drizzle, uint32_t fields, DRIZZLE_ROW row, uint32_t *lengths)
893
385
{
894
 
  uint field;
 
386
  uint32_t field;
895
387
  uint32_t pkt_len,len;
896
 
  uchar *pos, *prev_pos, *end_pos;
 
388
  unsigned char *pos, *prev_pos, *end_pos;
897
389
  NET *net= &drizzle->net;
898
390
 
899
 
  if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
391
  if ((pkt_len=drizzleclient_cli_safe_read(drizzle)) == packet_error)
900
392
    return -1;
901
393
  if (pkt_len <= 8 && net->read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
902
394
  {
912
404
  end_pos=pos+pkt_len;
913
405
  for (field=0 ; field < fields ; field++)
914
406
  {
915
 
    if ((len= net_field_length(&pos)) == NULL_LENGTH)
 
407
    if ((len= drizzleclient_net_field_length(&pos)) == NULL_LENGTH)
916
408
    {            /* null field */
917
409
      row[field] = 0;
918
410
      *lengths++=0;
921
413
    {
922
414
      if (len > (uint32_t) (end_pos - pos))
923
415
      {
924
 
        set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
 
416
        drizzleclient_set_error(drizzle, CR_UNKNOWN_ERROR,
 
417
                          drizzleclient_sqlstate_get_unknown());
925
418
        return -1;
926
419
      }
927
420
      row[field] = (char*) pos;
938
431
}
939
432
 
940
433
 
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
 
 
1869
434
/**************************************************************************
1870
435
  Return next row of the query results
1871
436
**************************************************************************/
1872
437
 
1873
438
DRIZZLE_ROW
1874
 
drizzle_fetch_row(DRIZZLE_RES *res)
 
439
drizzleclient_fetch_row(DRIZZLE_RES *res)
1875
440
{
1876
441
  if (!res->data)
1877
442
  {            /* Unbufferred fetch */
1880
445
      DRIZZLE *drizzle= res->handle;
1881
446
      if (drizzle->status != DRIZZLE_STATUS_USE_RESULT)
1882
447
      {
1883
 
        set_drizzle_error(drizzle,
1884
 
                        res->unbuffered_fetch_cancelled ?
1885
 
                        CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
1886
 
                        unknown_sqlstate);
 
448
        drizzleclient_set_error(drizzle,
 
449
                          res->unbuffered_fetch_cancelled ?
 
450
                          CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
 
451
                          drizzleclient_sqlstate_get_unknown());
1887
452
      }
1888
453
      else if (!(read_one_row(drizzle, res->field_count, res->row, res->lengths)))
1889
454
      {
1898
463
      */
1899
464
      if (drizzle->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
1900
465
        drizzle->unbuffered_fetch_owner= 0;
1901
 
      /* Don't clear handle in drizzle_free_result */
 
466
      /* Don't clear handle in drizzleclient_free_result */
1902
467
      res->handle=0;
1903
468
    }
1904
469
    return((DRIZZLE_ROW) NULL);
1918
483
 
1919
484
/**************************************************************************
1920
485
  Get column lengths of the current row
1921
 
  If one uses drizzle_use_result, res->lengths contains the length information,
 
486
  If one uses drizzleclient_use_result, res->lengths contains the length information,
1922
487
  else the lengths are calculated from the offset between pointers.
1923
488
**************************************************************************/
1924
489
 
1925
490
uint32_t *
1926
 
drizzle_fetch_lengths(DRIZZLE_RES *res)
 
491
drizzleclient_fetch_lengths(DRIZZLE_RES *res)
1927
492
{
1928
493
  DRIZZLE_ROW column;
1929
494
 
1936
501
 
1937
502
 
1938
503
int
1939
 
drizzle_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
 
504
drizzleclient_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
1940
505
{
1941
506
  switch (option) {
1942
507
  case DRIZZLE_OPT_CONNECT_TIMEOUT:
1943
 
    drizzle->options.connect_timeout= *(uint*) arg;
 
508
    drizzle->options.connect_timeout= *(uint32_t*) arg;
1944
509
    break;
1945
510
  case DRIZZLE_OPT_READ_TIMEOUT:
1946
 
    drizzle->options.read_timeout= *(uint*) arg;
 
511
    drizzle->options.read_timeout= *(uint32_t*) arg;
1947
512
    break;
1948
513
  case DRIZZLE_OPT_WRITE_TIMEOUT:
1949
 
    drizzle->options.write_timeout= *(uint*) arg;
 
514
    drizzle->options.write_timeout= *(uint32_t*) arg;
1950
515
    break;
1951
516
  case DRIZZLE_OPT_COMPRESS:
1952
517
    drizzle->options.compress= 1;      /* Remember for connect */
1953
518
    drizzle->options.client_flag|= CLIENT_COMPRESS;
1954
519
    break;
1955
 
  case DRIZZLE_OPT_LOCAL_INFILE:      /* Allow LOAD DATA LOCAL ?*/
1956
 
    if (!arg || test(*(uint*) arg))
1957
 
      drizzle->options.client_flag|= CLIENT_LOCAL_FILES;
1958
 
    else
1959
 
      drizzle->options.client_flag&= ~CLIENT_LOCAL_FILES;
1960
 
    break;
1961
 
  case DRIZZLE_INIT_COMMAND:
1962
 
    add_init_command(&drizzle->options,arg);
1963
 
    break;
1964
520
  case DRIZZLE_READ_DEFAULT_FILE:
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));
 
521
    if (drizzle->options.my_cnf_file != NULL)
 
522
      free(drizzle->options.my_cnf_file);
 
523
    drizzle->options.my_cnf_file=strdup((char *)arg);
1967
524
    break;
1968
525
  case DRIZZLE_READ_DEFAULT_GROUP:
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));
 
526
    if (drizzle->options.my_cnf_group != NULL)
 
527
      free(drizzle->options.my_cnf_group);
 
528
    drizzle->options.my_cnf_group=strdup((char *)arg);
1979
529
    break;
1980
530
  case DRIZZLE_OPT_PROTOCOL:
1981
 
    drizzle->options.protocol= *(const uint*) arg;
1982
531
    break;
1983
532
  case DRIZZLE_OPT_USE_REMOTE_CONNECTION:
1984
533
  case DRIZZLE_OPT_GUESS_CONNECTION:
1985
534
    drizzle->options.methods_to_use= option;
1986
535
    break;
1987
536
  case DRIZZLE_SET_CLIENT_IP:
1988
 
    drizzle->options.client_ip= my_strdup(arg, MYF(MY_WME));
 
537
    drizzle->options.client_ip= strdup((char *)arg);
1989
538
    break;
1990
539
  case DRIZZLE_SECURE_AUTH:
1991
540
    drizzle->options.secure_auth= *(const bool *) arg;
1992
541
    break;
1993
542
  case DRIZZLE_REPORT_DATA_TRUNCATION:
1994
 
    drizzle->options.report_data_truncation= test(*(const bool *) arg);
 
543
    drizzle->options.report_data_truncation= (*(const bool *) arg) ? 1 : 0;
1995
544
    break;
1996
545
  case DRIZZLE_OPT_RECONNECT:
1997
546
    drizzle->reconnect= *(const bool *) arg;
2015
564
****************************************************************************/
2016
565
 
2017
566
/* DRIZZLE_RES */
2018
 
uint64_t drizzle_num_rows(const DRIZZLE_RES *res)
 
567
uint64_t drizzleclient_num_rows(const DRIZZLE_RES *res)
2019
568
{
2020
569
  return res->row_count;
2021
570
}
2022
571
 
2023
 
unsigned int drizzle_num_fields(const DRIZZLE_RES *res)
 
572
unsigned int drizzleclient_num_fields(const DRIZZLE_RES *res)
2024
573
{
2025
574
  return res->field_count;
2026
575
}
2027
576
 
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
 
 
2039
577
 
2040
578
/*
2041
579
  Get version number for server in a form easy to test on
2042
580
 
2043
581
  SYNOPSIS
2044
 
    drizzle_get_server_version()
 
582
    drizzleclient_get_server_version()
2045
583
    drizzle Connection
2046
584
 
2047
585
  EXAMPLE
2048
586
    4.1.0-alfa ->  40100
2049
 
 
 
587
 
2050
588
  NOTES
2051
589
    We will ensure that a newer server always has a bigger number.
2052
590
 
2055
593
*/
2056
594
 
2057
595
uint32_t
2058
 
drizzle_get_server_version(const DRIZZLE *drizzle)
 
596
drizzleclient_get_server_version(const DRIZZLE *drizzle)
2059
597
{
2060
 
  uint major, minor, version;
 
598
  uint32_t major, minor, version;
2061
599
  char *pos= drizzle->server_version, *end_pos;
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);
 
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);
2065
603
  return (uint32_t) major*10000L+(uint32_t) (minor*100+version);
2066
604
}
2067
605
 
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