~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/client.c

  • Committer: Monty Taylor
  • Date: 2008-08-05 19:01:20 UTC
  • mto: (266.1.1 codestyle)
  • mto: This revision was merged to the branch mainline in revision 266.
  • Revision ID: monty@inaugust.com-20080805190120-tsuziqz2mfqcw7pe
Removed libmysyslt.la, made mysys a noinst_ and made everything use it. It's
not a standalone lib, there's no reason to pretend otherwise.

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 */
 
15
 
 
16
/*
 
17
  This file is included by both libdrizzle.c (the DRIZZLE client C API)
 
18
  and the drizzled server to connect to another DRIZZLE server.
 
19
 
 
20
  The differences for the two cases are:
 
21
 
 
22
  - Things that only works for the client:
 
23
  - Trying to automaticly determinate user name if not supplied to
 
24
    drizzle_connect()
 
25
  - Support for reading local file with LOAD DATA LOCAL
 
26
  - SHARED memory handling
 
27
  - Protection against sigpipe
 
28
  - Prepared statements
 
29
 
 
30
  - Things that only works for the server
 
31
  - Alarm handling on connect
 
32
 
 
33
  In all other cases, the code should be idential for the client and
 
34
  server.
 
35
*/
 
36
 
 
37
#include <drizzled/global.h>
 
38
 
 
39
#include "drizzle.h"
 
40
 
 
41
#include <sys/poll.h>
 
42
#include <sys/ioctl.h>
 
43
 
 
44
#include <netdb.h>
 
45
 
 
46
/* Remove client convenience wrappers */
 
47
#undef max_allowed_packet
 
48
#undef net_buffer_length
 
49
 
 
50
#define CLI_DRIZZLE_CONNECT STDCALL drizzle_connect
 
51
 
 
52
#include <mysys/my_sys.h>
 
53
#include <mysys/mysys_err.h>
 
54
#include <mystrings/m_string.h>
 
55
#include <mystrings/m_ctype.h>
 
56
#include <drizzled/error.h>
 
57
#include "errmsg.h"
 
58
#include <vio/violite.h>
 
59
#include <mysys/my_pthread.h>        /* because of signal()  */
 
60
 
 
61
#include <sys/stat.h>
 
62
#include <signal.h>
 
63
#include <time.h>
 
64
#ifdef   HAVE_PWD_H
 
65
#include <pwd.h>
 
66
#endif
 
67
 
 
68
#include <sys/socket.h>
 
69
#include <netinet/in.h>
 
70
#include <arpa/inet.h>
 
71
#include <netdb.h>
 
72
#ifdef HAVE_SELECT_H
 
73
#  include <select.h>
 
74
#endif
 
75
#ifdef HAVE_SYS_SELECT_H
 
76
#include <sys/select.h>
 
77
#endif
 
78
 
 
79
#include <sys/un.h>
 
80
 
 
81
#include <errno.h>
 
82
#define SOCKET_ERROR -1
 
83
 
 
84
#define CONNECT_TIMEOUT 0
 
85
 
 
86
#include "client_settings.h"
 
87
#include <libdrizzle/sql_common.h>
 
88
 
 
89
uint    drizzle_port=0;
 
90
char    *drizzle_unix_port= 0;
 
91
const char  *unknown_sqlstate= "HY000";
 
92
const char  *not_error_sqlstate= "00000";
 
93
const char  *cant_connect_sqlstate= "08001";
 
94
 
 
95
static bool drizzle_client_init= false;
 
96
static bool org_my_init_done= false;
 
97
 
 
98
static void drizzle_close_free_options(DRIZZLE *drizzle);
 
99
static void drizzle_close_free(DRIZZLE *drizzle);
 
100
 
 
101
static int wait_for_data(my_socket fd, uint 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().  my_connect() 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
  my_connect() will behave exactly like connect().
 
114
 
 
115
  Base version coded by Steve Bernacki, Jr. <steve@navinet.net>
 
116
*****************************************************************************/
 
117
 
 
118
int my_connect(my_socket fd, const struct sockaddr *name, uint namelen,
 
119
         uint 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
  return wait_for_data(fd, timeout);
 
147
}
 
148
 
 
149
 
 
150
/*
 
151
  Wait up to timeout seconds for a connection to be established.
 
152
 
 
153
  We prefer to do this with poll() as there is no limitations with this.
 
154
  If not, we will use select()
 
155
*/
 
156
 
 
157
static int wait_for_data(my_socket fd, uint timeout)
 
158
{
 
159
#ifdef HAVE_POLL
 
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)))
 
171
    return -1;
 
172
  return 0;
 
173
#else
 
174
  SOCKOPT_OPTLEN_TYPE s_err_size = sizeof(uint);
 
175
  fd_set sfds;
 
176
  struct timeval tv;
 
177
  time_t start_time, now_time;
 
178
  int res, s_err;
 
179
 
 
180
  if (fd >= FD_SETSIZE)        /* Check if wrong error */
 
181
    return 0;          /* Can't use timeout */
 
182
 
 
183
  /*
 
184
    Our connection is "in progress."  We can use the select() call to wait
 
185
    up to a specified period of time for the connection to suceed.
 
186
    If select() returns 0 (after waiting howevermany seconds), our socket
 
187
    never became writable (host is probably unreachable.)  Otherwise, if
 
188
    select() returns 1, then one of two conditions exist:
 
189
  
 
190
    1. An error occured.  We use getsockopt() to check for this.
 
191
    2. The connection was set up sucessfully: getsockopt() will
 
192
    return 0 as an error.
 
193
  
 
194
    Thanks goes to Andrew Gierth <andrew@erlenstar.demon.co.uk>
 
195
    who posted this method of timing out a connect() in
 
196
    comp.unix.programmer on August 15th, 1997.
 
197
  */
 
198
 
 
199
  FD_ZERO(&sfds);
 
200
  FD_SET(fd, &sfds);
 
201
  /*
 
202
    select could be interrupted by a signal, and if it is,
 
203
    the timeout should be adjusted and the select restarted
 
204
    to work around OSes that don't restart select and
 
205
    implementations of select that don't adjust tv upon
 
206
    failure to reflect the time remaining
 
207
   */
 
208
  start_time= my_time(0);
 
209
  for (;;)
 
210
  {
 
211
    tv.tv_sec = (long) timeout;
 
212
    tv.tv_usec = 0;
 
213
#if defined(HPUX10)
 
214
    if ((res = select(fd+1, NULL, (int*) &sfds, NULL, &tv)) > 0)
 
215
      break;
 
216
#else
 
217
    if ((res = select(fd+1, NULL, &sfds, NULL, &tv)) > 0)
 
218
      break;
 
219
#endif
 
220
    if (res == 0)          /* timeout */
 
221
      return -1;
 
222
    now_time= my_time(0);
 
223
    timeout-= (uint) (now_time - start_time);
 
224
    if (errno != EINTR || (int) timeout <= 0)
 
225
      return -1;
 
226
  }
 
227
 
 
228
  /*
 
229
    select() returned something more interesting than zero, let's
 
230
    see if we have any errors.  If the next two statements pass,
 
231
    we've got an open socket!
 
232
  */
 
233
 
 
234
  s_err=0;
 
235
  if (getsockopt(fd, SOL_SOCKET, SO_ERROR, (char*) &s_err, &s_err_size) != 0)
 
236
    return(-1);
 
237
 
 
238
  if (s_err)
 
239
  {            /* getsockopt could succeed */
 
240
    errno = s_err;
 
241
    return(-1);          /* but return an error... */
 
242
  }
 
243
  return (0);          /* ok */
 
244
#endif /* HAVE_POLL */
 
245
}
 
246
 
 
247
 
 
248
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
 
249
struct passwd *getpwuid(uid_t);
 
250
char* getlogin(void);
 
251
#endif
 
252
 
 
253
static void read_user_name(char *name)
 
254
{
 
255
  if (geteuid() == 0)
 
256
    strcpy(name,"root");    /* allow use of surun */
 
257
  else
 
258
  {
 
259
#ifdef HAVE_GETPWUID
 
260
    struct passwd *skr;
 
261
    const char *str;
 
262
    if ((str=getlogin()) == NULL)
 
263
    {
 
264
      if ((skr=getpwuid(geteuid())) != NULL)
 
265
  str=skr->pw_name;
 
266
      else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
 
267
         !(str=getenv("LOGIN")))
 
268
  str="UNKNOWN_USER";
 
269
    }
 
270
    strncpy(name,str,USERNAME_LENGTH);
 
271
#elif HAVE_CUSERID
 
272
    (void) cuserid(name);
 
273
#else
 
274
    strcpy(name,"UNKNOWN_USER");
 
275
#endif
 
276
  }
 
277
  return;
 
278
}
 
279
 
 
280
 
 
281
/**
 
282
  Set the internal error message to DRIZZLE handler
 
283
 
 
284
  @param drizzle connection handle (client side)
 
285
  @param errcode  CR_ error code, passed to ER macro to get
 
286
                  error text
 
287
  @parma sqlstate SQL standard sqlstate
 
288
*/
 
289
 
 
290
void set_drizzle_error(DRIZZLE *drizzle, int errcode, const char *sqlstate)
 
291
{
 
292
  NET *net;
 
293
  assert(drizzle != 0);
 
294
 
 
295
  if (drizzle)
 
296
  {
 
297
    net= &drizzle->net;
 
298
    net->last_errno= errcode;
 
299
    strcpy(net->last_error, ER(errcode));
 
300
    strcpy(net->sqlstate, sqlstate);
 
301
  }
 
302
  else
 
303
  {
 
304
    drizzle_server_last_errno= errcode;
 
305
    strcpy(drizzle_server_last_error, ER(errcode));
 
306
  }
 
307
  return;
 
308
}
 
309
 
 
310
/**
 
311
  Clear possible error state of struct NET
 
312
 
 
313
  @param net  clear the state of the argument
 
314
*/
 
315
 
 
316
void net_clear_error(NET *net)
 
317
{
 
318
  net->last_errno= 0;
 
319
  net->last_error[0]= '\0';
 
320
  strcpy(net->sqlstate, not_error_sqlstate);
 
321
}
 
322
 
 
323
/**
 
324
  Set an error message on the client.
 
325
 
 
326
  @param drizzle connection handle
 
327
  @param errcode   CR_* errcode, for client errors
 
328
  @param sqlstate  SQL standard sql state, unknown_sqlstate for the
 
329
                   majority of client errors.
 
330
  @param format    error message template, in sprintf format
 
331
  @param ...       variable number of arguments
 
332
*/
 
333
 
 
334
static void set_drizzle_extended_error(DRIZZLE *drizzle, int errcode,
 
335
                                     const char *sqlstate,
 
336
                                     const char *format, ...)
 
337
{
 
338
  NET *net;
 
339
  va_list args;
 
340
  assert(drizzle != 0);
 
341
 
 
342
  net= &drizzle->net;
 
343
  net->last_errno= errcode;
 
344
  va_start(args, format);
 
345
  vsnprintf(net->last_error, sizeof(net->last_error)-1,
 
346
               format, args);
 
347
  va_end(args);
 
348
  strcpy(net->sqlstate, sqlstate);
 
349
 
 
350
  return;
 
351
}
 
352
 
 
353
/*****************************************************************************
 
354
  Read a packet from server. Give error message if socket was down
 
355
  or packet is an error message
 
356
*****************************************************************************/
 
357
 
 
358
uint32_t cli_safe_read(DRIZZLE *drizzle)
 
359
{
 
360
  NET *net= &drizzle->net;
 
361
  ulong len=0;
 
362
  init_sigpipe_variables
 
363
 
 
364
  /* Don't give sigpipe errors if the client doesn't want them */
 
365
  set_sigpipe(drizzle);
 
366
  if (net->vio != 0)
 
367
    len=my_net_read(net);
 
368
  reset_sigpipe(drizzle);
 
369
 
 
370
  if (len == packet_error || len == 0)
 
371
  {
 
372
#ifdef MYSQL_SERVER
 
373
    if (net->vio && vio_was_interrupted(net->vio))
 
374
      return (packet_error);
 
375
#endif /*DRIZZLE_SERVER*/
 
376
    end_server(drizzle);
 
377
    set_drizzle_error(drizzle, net->last_errno == ER_NET_PACKET_TOO_LARGE ?
 
378
                    CR_NET_PACKET_TOO_LARGE: CR_SERVER_LOST, unknown_sqlstate);
 
379
    return (packet_error);
 
380
  }
 
381
  if (net->read_pos[0] == 255)
 
382
  {
 
383
    if (len > 3)
 
384
    {
 
385
      char *pos=(char*) net->read_pos+1;
 
386
      net->last_errno=uint2korr(pos);
 
387
      pos+=2;
 
388
      len-=2;
 
389
      if (protocol_41(drizzle) && pos[0] == '#')
 
390
      {
 
391
        strncpy(net->sqlstate, pos+1, SQLSTATE_LENGTH);
 
392
        pos+= SQLSTATE_LENGTH+1;
 
393
      }
 
394
      else
 
395
      {
 
396
        /*
 
397
          The SQL state hasn't been received -- it should be reset to HY000
 
398
          (unknown error sql state).
 
399
        */
 
400
 
 
401
        strcpy(net->sqlstate, unknown_sqlstate);
 
402
      }
 
403
 
 
404
      strncpy(net->last_error,(char*) pos, min((uint) len,
 
405
              (uint32_t) sizeof(net->last_error)-1));
 
406
    }
 
407
    else
 
408
      set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
 
409
    /*
 
410
      Cover a protocol design error: error packet does not
 
411
      contain the server status. Therefore, the client has no way
 
412
      to find out whether there are more result sets of
 
413
      a multiple-result-set statement pending. Luckily, in 5.0 an
 
414
      error always aborts execution of a statement, wherever it is
 
415
      a multi-statement or a stored procedure, so it should be
 
416
      safe to unconditionally turn off the flag here.
 
417
    */
 
418
    drizzle->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
 
419
 
 
420
    return(packet_error);
 
421
  }
 
422
  return len;
 
423
}
 
424
 
 
425
void free_rows(DRIZZLE_DATA *cur)
 
426
{
 
427
  if (cur)
 
428
  {
 
429
    free_root(&cur->alloc,MYF(0));
 
430
    my_free((uchar*) cur,MYF(0));
 
431
  }
 
432
}
 
433
 
 
434
bool
 
435
cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
 
436
         const unsigned char *header, uint32_t header_length,
 
437
         const unsigned char *arg, uint32_t arg_length, bool skip_check)
 
438
{
 
439
  NET *net= &drizzle->net;
 
440
  my_bool result= 1;
 
441
  init_sigpipe_variables
 
442
  my_bool stmt_skip= false;
 
443
 
 
444
  /* Don't give sigpipe errors if the client doesn't want them */
 
445
  set_sigpipe(drizzle);
 
446
 
 
447
  if (drizzle->net.vio == 0)
 
448
  {            /* Do reconnect if possible */
 
449
    if (drizzle_reconnect(drizzle) || stmt_skip)
 
450
      return(1);
 
451
  }
 
452
  if (drizzle->status != DRIZZLE_STATUS_READY ||
 
453
      drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
 
454
  {
 
455
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
456
    return(1);
 
457
  }
 
458
 
 
459
  net_clear_error(net);
 
460
  drizzle->info=0;
 
461
  drizzle->affected_rows= ~(uint64_t) 0;
 
462
  /*
 
463
    We don't want to clear the protocol buffer on COM_QUIT, because if
 
464
    the previous command was a shutdown command, we may have the
 
465
    response for the COM_QUIT already in the communication buffer
 
466
  */
 
467
  net_clear(&drizzle->net, (command != COM_QUIT));
 
468
 
 
469
  if (net_write_command(net,(uchar) command, header, header_length,
 
470
      arg, arg_length))
 
471
  {
 
472
    if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
 
473
    {
 
474
      set_drizzle_error(drizzle, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
 
475
      goto end;
 
476
    }
 
477
    end_server(drizzle);
 
478
    if (drizzle_reconnect(drizzle) || stmt_skip)
 
479
      goto end;
 
480
    if (net_write_command(net,(uchar) command, header, header_length,
 
481
        arg, arg_length))
 
482
    {
 
483
      set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
 
484
      goto end;
 
485
    }
 
486
  }
 
487
  result=0;
 
488
  if (!skip_check)
 
489
    result= ((drizzle->packet_length=cli_safe_read(drizzle)) == packet_error ?
 
490
       1 : 0);
 
491
end:
 
492
  reset_sigpipe(drizzle);
 
493
  return(result);
 
494
}
 
495
 
 
496
void free_old_query(DRIZZLE *drizzle)
 
497
{
 
498
  if (drizzle->fields)
 
499
    free_root(&drizzle->field_alloc,MYF(0));
 
500
  init_alloc_root(&drizzle->field_alloc,8192,0); /* Assume rowlength < 8192 */
 
501
  drizzle->fields= 0;
 
502
  drizzle->field_count= 0;      /* For API */
 
503
  drizzle->warning_count= 0;
 
504
  drizzle->info= 0;
 
505
  return;
 
506
}
 
507
 
 
508
/*
 
509
  Flush result set sent from server
 
510
*/
 
511
 
 
512
static void cli_flush_use_result(DRIZZLE *drizzle)
 
513
{
 
514
  /* Clear the current execution status */
 
515
  for (;;)
 
516
  {
 
517
    ulong pkt_len;
 
518
    if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
519
      break;
 
520
    if (pkt_len <= 8 && drizzle->net.read_pos[0] == 254)
 
521
    {
 
522
      if (protocol_41(drizzle))
 
523
      {
 
524
        char *pos= (char*) drizzle->net.read_pos + 1;
 
525
        drizzle->warning_count=uint2korr(pos); pos+=2;
 
526
        drizzle->server_status=uint2korr(pos); pos+=2;
 
527
      }
 
528
      break;                            /* End of data */
 
529
    }
 
530
  }
 
531
  return;
 
532
}
 
533
 
 
534
 
 
535
/**************************************************************************
 
536
  Shut down connection
 
537
**************************************************************************/
 
538
 
 
539
void end_server(DRIZZLE *drizzle)
 
540
{
 
541
  int save_errno= errno;
 
542
  if (drizzle->net.vio != 0)
 
543
  {
 
544
    init_sigpipe_variables
 
545
    set_sigpipe(drizzle);
 
546
    vio_delete(drizzle->net.vio);
 
547
    reset_sigpipe(drizzle);
 
548
    drizzle->net.vio= 0;          /* Marker */
 
549
  }
 
550
  net_end(&drizzle->net);
 
551
  free_old_query(drizzle);
 
552
  errno= save_errno;
 
553
  return;
 
554
}
 
555
 
 
556
 
 
557
void STDCALL
 
558
drizzle_free_result(DRIZZLE_RES *result)
 
559
{
 
560
  if (result)
 
561
  {
 
562
    DRIZZLE *drizzle= result->handle;
 
563
    if (drizzle)
 
564
    {
 
565
      if (drizzle->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
 
566
        drizzle->unbuffered_fetch_owner= 0;
 
567
      if (drizzle->status == DRIZZLE_STATUS_USE_RESULT)
 
568
      {
 
569
        (*drizzle->methods->flush_use_result)(drizzle);
 
570
        drizzle->status=DRIZZLE_STATUS_READY;
 
571
        if (drizzle->unbuffered_fetch_owner)
 
572
          *drizzle->unbuffered_fetch_owner= true;
 
573
      }
 
574
    }
 
575
    free_rows(result->data);
 
576
    if (result->fields)
 
577
      free_root(&result->field_alloc,MYF(0));
 
578
    if (result->row)
 
579
      my_free((uchar*) result->row,MYF(0));
 
580
    my_free((uchar*) result,MYF(0));
 
581
  }
 
582
  return;
 
583
}
 
584
 
 
585
/****************************************************************************
 
586
  Get options from my.cnf
 
587
****************************************************************************/
 
588
 
 
589
static const char *default_options[]=
 
590
{
 
591
  "port","socket","compress","password","pipe", "timeout", "user",
 
592
  "init-command", "host", "database", "return-found-rows",
 
593
  "ssl-key" ,"ssl-cert" ,"ssl-ca" ,"ssl-capath",
 
594
  "character-sets-dir", "default-character-set", "interactive-timeout",
 
595
  "connect-timeout", "local-infile", "disable-local-infile",
 
596
  "ssl-cipher", "max-allowed-packet", "protocol", "shared-memory-base-name",
 
597
  "multi-results", "multi-statements", "multi-queries", "secure-auth",
 
598
  "report-data-truncation",
 
599
  NullS
 
600
};
 
601
 
 
602
static TYPELIB option_types={array_elements(default_options)-1,
 
603
           "options",default_options, NULL};
 
604
 
 
605
const char *sql_protocol_names_lib[] =
 
606
{ "TCP", "SOCKET", "PIPE", "MEMORY", NullS };
 
607
TYPELIB sql_protocol_typelib = {array_elements(sql_protocol_names_lib)-1,"",
 
608
        sql_protocol_names_lib, NULL};
 
609
 
 
610
static int add_init_command(struct st_drizzle_options *options, const char *cmd)
 
611
{
 
612
  char *tmp;
 
613
 
 
614
  if (!options->init_commands)
 
615
  {
 
616
    options->init_commands= (DYNAMIC_ARRAY*)my_malloc(sizeof(DYNAMIC_ARRAY),
 
617
                  MYF(MY_WME));
 
618
    init_dynamic_array(options->init_commands,sizeof(char*),0,5 CALLER_INFO);
 
619
  }
 
620
 
 
621
  if (!(tmp= my_strdup(cmd,MYF(MY_WME))) ||
 
622
      insert_dynamic(options->init_commands, (uchar*)&tmp))
 
623
  {
 
624
    my_free(tmp, MYF(MY_ALLOW_ZERO_PTR));
 
625
    return 1;
 
626
  }
 
627
 
 
628
  return 0;
 
629
}
 
630
 
 
631
void drizzle_read_default_options(struct st_drizzle_options *options,
 
632
        const char *filename,const char *group)
 
633
{
 
634
  int argc;
 
635
  char *argv_buff[1],**argv;
 
636
  const char *groups[3];
 
637
 
 
638
  argc=1; argv=argv_buff; argv_buff[0]= (char*) "client";
 
639
  groups[0]= (char*) "client"; groups[1]= (char*) group; groups[2]=0;
 
640
 
 
641
  load_defaults(filename, groups, &argc, &argv);
 
642
  if (argc != 1)        /* If some default option */
 
643
  {
 
644
    char **option=argv;
 
645
    while (*++option)
 
646
    {
 
647
      if (option[0][0] == '-' && option[0][1] == '-')
 
648
      {
 
649
  char *end=strcend(*option,'=');
 
650
  char *opt_arg=0;
 
651
  if (*end)
 
652
  {
 
653
    opt_arg=end+1;
 
654
    *end=0;        /* Remove '=' */
 
655
  }
 
656
  /* Change all '_' in variable name to '-' */
 
657
  for (end= *option ; *(end= strcend(end,'_')) ; )
 
658
    *end= '-';
 
659
  switch (find_type(*option+2,&option_types,2)) {
 
660
  case 1:        /* port */
 
661
    if (opt_arg)
 
662
      options->port=atoi(opt_arg);
 
663
    break;
 
664
  case 2:        /* socket */
 
665
    if (opt_arg)
 
666
    {
 
667
      my_free(options->unix_socket,MYF(MY_ALLOW_ZERO_PTR));
 
668
      options->unix_socket=my_strdup(opt_arg,MYF(MY_WME));
 
669
    }
 
670
    break;
 
671
  case 3:        /* compress */
 
672
    options->compress=1;
 
673
    options->client_flag|= CLIENT_COMPRESS;
 
674
    break;
 
675
  case 4:        /* password */
 
676
    if (opt_arg)
 
677
    {
 
678
      my_free(options->password,MYF(MY_ALLOW_ZERO_PTR));
 
679
      options->password=my_strdup(opt_arg,MYF(MY_WME));
 
680
    }
 
681
    break;
 
682
  case 20:      /* connect_timeout */
 
683
  case 6:        /* timeout */
 
684
    if (opt_arg)
 
685
      options->connect_timeout=atoi(opt_arg);
 
686
    break;
 
687
  case 7:        /* user */
 
688
    if (opt_arg)
 
689
    {
 
690
      my_free(options->user,MYF(MY_ALLOW_ZERO_PTR));
 
691
      options->user=my_strdup(opt_arg,MYF(MY_WME));
 
692
    }
 
693
    break;
 
694
  case 8:        /* init-command */
 
695
    add_init_command(options,opt_arg);
 
696
    break;
 
697
  case 9:        /* host */
 
698
    if (opt_arg)
 
699
    {
 
700
      my_free(options->host,MYF(MY_ALLOW_ZERO_PTR));
 
701
      options->host=my_strdup(opt_arg,MYF(MY_WME));
 
702
    }
 
703
    break;
 
704
  case 10:      /* database */
 
705
    if (opt_arg)
 
706
    {
 
707
      my_free(options->db,MYF(MY_ALLOW_ZERO_PTR));
 
708
      options->db=my_strdup(opt_arg,MYF(MY_WME));
 
709
    }
 
710
    break;
 
711
  case 12:      /* return-found-rows */
 
712
    options->client_flag|=CLIENT_FOUND_ROWS;
 
713
    break;
 
714
  case 13:        /* Ignore SSL options */
 
715
  case 14:
 
716
  case 15:
 
717
  case 16:
 
718
        case 23:
 
719
    break;
 
720
  case 17:      /* charset-lib */
 
721
    my_free(options->charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
722
          options->charset_dir = my_strdup(opt_arg, MYF(MY_WME));
 
723
    break;
 
724
  case 18:
 
725
    my_free(options->charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
726
          options->charset_name = my_strdup(opt_arg, MYF(MY_WME));
 
727
    break;
 
728
  case 19:        /* Interactive-timeout */
 
729
    options->client_flag|= CLIENT_INTERACTIVE;
 
730
    break;
 
731
  case 21:
 
732
    if (!opt_arg || atoi(opt_arg) != 0)
 
733
      options->client_flag|= CLIENT_LOCAL_FILES;
 
734
    else
 
735
      options->client_flag&= ~CLIENT_LOCAL_FILES;
 
736
    break;
 
737
  case 22:
 
738
    options->client_flag&= ~CLIENT_LOCAL_FILES;
 
739
          break;
 
740
  case 24: /* max-allowed-packet */
 
741
          if (opt_arg)
 
742
      options->max_allowed_packet= atoi(opt_arg);
 
743
    break;
 
744
        case 25: /* protocol */
 
745
          if ((options->protocol= find_type(opt_arg,
 
746
              &sql_protocol_typelib,0)) <= 0)
 
747
          {
 
748
            fprintf(stderr, "Unknown option to protocol: %s\n", opt_arg);
 
749
            exit(1);
 
750
          }
 
751
          break;
 
752
  case 27: /* multi-results */
 
753
    options->client_flag|= CLIENT_MULTI_RESULTS;
 
754
    break;
 
755
  case 28: /* multi-statements */
 
756
  case 29: /* multi-queries */
 
757
    options->client_flag|= CLIENT_MULTI_STATEMENTS | CLIENT_MULTI_RESULTS;
 
758
    break;
 
759
        case 30: /* secure-auth */
 
760
          options->secure_auth= true;
 
761
          break;
 
762
        case 31: /* report-data-truncation */
 
763
          options->report_data_truncation= opt_arg ? test(atoi(opt_arg)) : 1;
 
764
          break;
 
765
  default:
 
766
          break;
 
767
  }
 
768
      }
 
769
    }
 
770
  }
 
771
  free_defaults(argv);
 
772
  return;
 
773
}
 
774
 
 
775
 
 
776
/**************************************************************************
 
777
  Get column lengths of the current row
 
778
  If one uses drizzle_use_result, res->lengths contains the length information,
 
779
  else the lengths are calculated from the offset between pointers.
 
780
**************************************************************************/
 
781
 
 
782
static void cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count)
 
783
{
 
784
  uint32_t *prev_length;
 
785
  char *start=0;
 
786
  DRIZZLE_ROW end;
 
787
 
 
788
  prev_length=0;        /* Keep gcc happy */
 
789
  for (end=column + field_count + 1 ; column != end ; column++, to++)
 
790
  {
 
791
    if (!*column)
 
792
    {
 
793
      *to= 0;          /* Null */
 
794
      continue;
 
795
    }
 
796
    if (start)          /* Found end of prev string */
 
797
      *prev_length= (ulong) (*column-start-1);
 
798
    start= *column;
 
799
    prev_length= to;
 
800
  }
 
801
}
 
802
 
 
803
/***************************************************************************
 
804
  Change field rows to field structs
 
805
***************************************************************************/
 
806
 
 
807
DRIZZLE_FIELD *
 
808
unpack_fields(DRIZZLE_DATA *data,MEM_ROOT *alloc,uint fields,
 
809
        my_bool default_value, uint server_capabilities)
 
810
{
 
811
  DRIZZLE_ROWS  *row;
 
812
  DRIZZLE_FIELD  *field,*result;
 
813
  uint32_t lengths[9];        /* Max of fields */
 
814
 
 
815
  field= result= (DRIZZLE_FIELD*) alloc_root(alloc,
 
816
             (uint) sizeof(*field)*fields);
 
817
  if (!result)
 
818
  {
 
819
    free_rows(data);        /* Free old data */
 
820
    return(0);
 
821
  }
 
822
  memset((char*) field, 0, (uint) sizeof(DRIZZLE_FIELD)*fields);
 
823
  if (server_capabilities & CLIENT_PROTOCOL_41)
 
824
  {
 
825
    /* server is 4.1, and returns the new field result format */
 
826
    for (row=data->data; row ; row = row->next,field++)
 
827
    {
 
828
      uchar *pos;
 
829
      /* fields count may be wrong */
 
830
      assert((uint) (field - result) < fields);
 
831
      cli_fetch_lengths(&lengths[0], row->data, default_value ? 8 : 7);
 
832
      field->catalog=   strmake_root(alloc,(char*) row->data[0], lengths[0]);
 
833
      field->db=        strmake_root(alloc,(char*) row->data[1], lengths[1]);
 
834
      field->table=     strmake_root(alloc,(char*) row->data[2], lengths[2]);
 
835
      field->org_table= strmake_root(alloc,(char*) row->data[3], lengths[3]);
 
836
      field->name=      strmake_root(alloc,(char*) row->data[4], lengths[4]);
 
837
      field->org_name=  strmake_root(alloc,(char*) row->data[5], lengths[5]);
 
838
 
 
839
      field->catalog_length=  lengths[0];
 
840
      field->db_length=    lengths[1];
 
841
      field->table_length=  lengths[2];
 
842
      field->org_table_length=  lengths[3];
 
843
      field->name_length=  lengths[4];
 
844
      field->org_name_length=  lengths[5];
 
845
 
 
846
      /* Unpack fixed length parts */
 
847
      pos= (uchar*) row->data[6];
 
848
      field->charsetnr= uint2korr(pos);
 
849
      field->length=  (uint) uint4korr(pos+2);
 
850
      field->type=  (enum enum_field_types) pos[6];
 
851
      field->flags=  uint2korr(pos+7);
 
852
      field->decimals=  (uint) pos[9];
 
853
 
 
854
      if (INTERNAL_NUM_FIELD(field))
 
855
        field->flags|= NUM_FLAG;
 
856
      if (default_value && row->data[7])
 
857
      {
 
858
        field->def=strmake_root(alloc,(char*) row->data[7], lengths[7]);
 
859
  field->def_length= lengths[7];
 
860
      }
 
861
      else
 
862
        field->def=0;
 
863
      field->max_length= 0;
 
864
    }
 
865
  }
 
866
#ifndef DELETE_SUPPORT_OF_4_0_PROTOCOL
 
867
  else
 
868
  {
 
869
    /* old protocol, for backward compatibility */
 
870
    for (row=data->data; row ; row = row->next,field++)
 
871
    {
 
872
      cli_fetch_lengths(&lengths[0], row->data, default_value ? 6 : 5);
 
873
      field->org_table= field->table=  strdup_root(alloc,(char*) row->data[0]);
 
874
      field->name=   strdup_root(alloc,(char*) row->data[1]);
 
875
      field->length= (uint) uint3korr(row->data[2]);
 
876
      field->type=   (enum enum_field_types) (uchar) row->data[3][0];
 
877
 
 
878
      field->catalog=(char*)  "";
 
879
      field->db=     (char*)  "";
 
880
      field->catalog_length= 0;
 
881
      field->db_length= 0;
 
882
      field->org_table_length=  field->table_length=  lengths[0];
 
883
      field->name_length=  lengths[1];
 
884
 
 
885
      if (server_capabilities & CLIENT_LONG_FLAG)
 
886
      {
 
887
        field->flags=   uint2korr(row->data[4]);
 
888
        field->decimals=(uint) (uchar) row->data[4][2];
 
889
      }
 
890
      else
 
891
      {
 
892
        field->flags=   (uint) (uchar) row->data[4][0];
 
893
        field->decimals=(uint) (uchar) row->data[4][1];
 
894
      }
 
895
      if (INTERNAL_NUM_FIELD(field))
 
896
        field->flags|= NUM_FLAG;
 
897
      if (default_value && row->data[5])
 
898
      {
 
899
        field->def=strdup_root(alloc,(char*) row->data[5]);
 
900
  field->def_length= lengths[5];
 
901
      }
 
902
      else
 
903
        field->def=0;
 
904
      field->max_length= 0;
 
905
    }
 
906
  }
 
907
#endif /* DELETE_SUPPORT_OF_4_0_PROTOCOL */
 
908
  free_rows(data);        /* Free old data */
 
909
  return(result);
 
910
}
 
911
 
 
912
/* Read all rows (fields or data) from server */
 
913
 
 
914
DRIZZLE_DATA *cli_read_rows(DRIZZLE *drizzle,DRIZZLE_FIELD *DRIZZLE_FIELDs,
 
915
        unsigned int fields)
 
916
{
 
917
  uint  field;
 
918
  ulong pkt_len;
 
919
  ulong len;
 
920
  uchar *cp;
 
921
  char  *to, *end_to;
 
922
  DRIZZLE_DATA *result;
 
923
  DRIZZLE_ROWS **prev_ptr,*cur;
 
924
  NET *net = &drizzle->net;
 
925
 
 
926
  if ((pkt_len= cli_safe_read(drizzle)) == packet_error)
 
927
    return(0);
 
928
  if (!(result=(DRIZZLE_DATA*) my_malloc(sizeof(DRIZZLE_DATA),
 
929
               MYF(MY_WME | MY_ZEROFILL))))
 
930
  {
 
931
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
932
    return(0);
 
933
  }
 
934
  init_alloc_root(&result->alloc,8192,0);  /* Assume rowlength < 8192 */
 
935
  result->alloc.min_malloc=sizeof(DRIZZLE_ROWS);
 
936
  prev_ptr= &result->data;
 
937
  result->rows=0;
 
938
  result->fields=fields;
 
939
 
 
940
  /*
 
941
    The last EOF packet is either a single 254 character or (in DRIZZLE 4.1)
 
942
    254 followed by 1-7 status bytes.
 
943
 
 
944
    This doesn't conflict with normal usage of 254 which stands for a
 
945
    string where the length of the string is 8 bytes. (see net_field_length())
 
946
  */
 
947
 
 
948
  while (*(cp=net->read_pos) != 254 || pkt_len >= 8)
 
949
  {
 
950
    result->rows++;
 
951
    if (!(cur= (DRIZZLE_ROWS*) alloc_root(&result->alloc,
 
952
          sizeof(DRIZZLE_ROWS))) ||
 
953
  !(cur->data= ((DRIZZLE_ROW)
 
954
          alloc_root(&result->alloc,
 
955
         (fields+1)*sizeof(char *)+pkt_len))))
 
956
    {
 
957
      free_rows(result);
 
958
      set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
959
      return(0);
 
960
    }
 
961
    *prev_ptr=cur;
 
962
    prev_ptr= &cur->next;
 
963
    to= (char*) (cur->data+fields+1);
 
964
    end_to=to+pkt_len-1;
 
965
    for (field=0 ; field < fields ; field++)
 
966
    {
 
967
      if ((len=(ulong) net_field_length(&cp)) == NULL_LENGTH)
 
968
      {            /* null field */
 
969
  cur->data[field] = 0;
 
970
      }
 
971
      else
 
972
      {
 
973
  cur->data[field] = to;
 
974
        if (len > (ulong) (end_to - to))
 
975
        {
 
976
          free_rows(result);
 
977
          set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
 
978
          return(0);
 
979
        }
 
980
  memcpy(to,(char*) cp,len); to[len]=0;
 
981
  to+=len+1;
 
982
  cp+=len;
 
983
  if (DRIZZLE_FIELDs)
 
984
  {
 
985
    if (DRIZZLE_FIELDs[field].max_length < len)
 
986
      DRIZZLE_FIELDs[field].max_length=len;
 
987
  }
 
988
      }
 
989
    }
 
990
    cur->data[field]=to;      /* End of last field */
 
991
    if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
992
    {
 
993
      free_rows(result);
 
994
      return(0);
 
995
    }
 
996
  }
 
997
  *prev_ptr=0;          /* last pointer is null */
 
998
  if (pkt_len > 1)        /* DRIZZLE 4.1 protocol */
 
999
  {
 
1000
    drizzle->warning_count= uint2korr(cp+1);
 
1001
    drizzle->server_status= uint2korr(cp+3);
 
1002
  }
 
1003
  return(result);
 
1004
}
 
1005
 
 
1006
/*
 
1007
  Read one row. Uses packet buffer as storage for fields.
 
1008
  When next packet is read, the previous field values are destroyed
 
1009
*/
 
1010
 
 
1011
 
 
1012
static int32_t
 
1013
read_one_row(DRIZZLE *drizzle, uint32_t fields, DRIZZLE_ROW row, uint32_t *lengths)
 
1014
{
 
1015
  uint field;
 
1016
  ulong pkt_len,len;
 
1017
  uchar *pos, *prev_pos, *end_pos;
 
1018
  NET *net= &drizzle->net;
 
1019
 
 
1020
  if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
 
1021
    return -1;
 
1022
  if (pkt_len <= 8 && net->read_pos[0] == 254)
 
1023
  {
 
1024
    if (pkt_len > 1)        /* DRIZZLE 4.1 protocol */
 
1025
    {
 
1026
      drizzle->warning_count= uint2korr(net->read_pos+1);
 
1027
      drizzle->server_status= uint2korr(net->read_pos+3);
 
1028
    }
 
1029
    return 1;        /* End of data */
 
1030
  }
 
1031
  prev_pos= 0;        /* allowed to write at packet[-1] */
 
1032
  pos=net->read_pos;
 
1033
  end_pos=pos+pkt_len;
 
1034
  for (field=0 ; field < fields ; field++)
 
1035
  {
 
1036
    if ((len=(ulong) net_field_length(&pos)) == NULL_LENGTH)
 
1037
    {            /* null field */
 
1038
      row[field] = 0;
 
1039
      *lengths++=0;
 
1040
    }
 
1041
    else
 
1042
    {
 
1043
      if (len > (ulong) (end_pos - pos))
 
1044
      {
 
1045
        set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
 
1046
        return -1;
 
1047
      }
 
1048
      row[field] = (char*) pos;
 
1049
      pos+=len;
 
1050
      *lengths++=len;
 
1051
    }
 
1052
    if (prev_pos)
 
1053
      *prev_pos=0;        /* Terminate prev field */
 
1054
    prev_pos=pos;
 
1055
  }
 
1056
  row[field]=(char*) prev_pos+1;    /* End of last field */
 
1057
  *prev_pos=0;          /* Terminate last field */
 
1058
  return 0;
 
1059
}
 
1060
 
 
1061
 
 
1062
/****************************************************************************
 
1063
  Init DRIZZLE structure or allocate one
 
1064
****************************************************************************/
 
1065
 
 
1066
DRIZZLE *
 
1067
drizzle_create(DRIZZLE *ptr)
 
1068
{
 
1069
 
 
1070
  if (!drizzle_client_init)
 
1071
  {
 
1072
    drizzle_client_init=true;
 
1073
    org_my_init_done=my_init_done;
 
1074
 
 
1075
    /* Will init threads */
 
1076
    if (my_init())
 
1077
      return NULL;
 
1078
 
 
1079
    init_client_errs();
 
1080
 
 
1081
    if (!drizzle_port)
 
1082
    {
 
1083
      drizzle_port = MYSQL_PORT;
 
1084
      {
 
1085
        struct servent *serv_ptr;
 
1086
        char *env;
 
1087
 
 
1088
        /*
 
1089
          if builder specifically requested a default port, use that
 
1090
          (even if it coincides with our factory default).
 
1091
          only if they didn't do we check /etc/services (and, failing
 
1092
          on that, fall back to the factory default of 4427).
 
1093
          either default can be overridden by the environment variable
 
1094
          MYSQL_TCP_PORT, which in turn can be overridden with command
 
1095
          line options.
 
1096
        */
 
1097
 
 
1098
#if MYSQL_PORT_DEFAULT == 0
 
1099
        if ((serv_ptr = getservbyname("drizzle", "tcp")))
 
1100
          drizzle_port = (uint) ntohs((ushort) serv_ptr->s_port);
 
1101
#endif
 
1102
        if ((env = getenv("DRIZZLE_TCP_PORT")))
 
1103
          drizzle_port =(uint) atoi(env);
 
1104
      }
 
1105
    }
 
1106
#if defined(SIGPIPE)
 
1107
    (void) signal(SIGPIPE, SIG_IGN);
 
1108
#endif
 
1109
  }
 
1110
  else
 
1111
    /* Init if new thread */
 
1112
    if (my_thread_init())
 
1113
      return NULL;
 
1114
 
 
1115
  if (ptr == NULL)
 
1116
  {
 
1117
    ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
 
1118
 
 
1119
    if (ptr == NULL)
 
1120
    {
 
1121
      set_drizzle_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1122
      return 0;
 
1123
    }
 
1124
    memset(ptr, 0, sizeof(DRIZZLE));
 
1125
    ptr->free_me=1;
 
1126
  }
 
1127
  else
 
1128
  {
 
1129
    memset(ptr, 0, sizeof(DRIZZLE)); 
 
1130
  }
 
1131
 
 
1132
  ptr->options.connect_timeout= CONNECT_TIMEOUT;
 
1133
  ptr->charset=default_client_charset_info;
 
1134
  strcpy(ptr->net.sqlstate, not_error_sqlstate);
 
1135
 
 
1136
  /*
 
1137
    Only enable LOAD DATA INFILE by default if configured with
 
1138
    --enable-local-infile
 
1139
  */
 
1140
 
 
1141
#if defined(ENABLED_LOCAL_INFILE) && !defined(DRIZZLE_SERVER)
 
1142
  ptr->options.client_flag|= CLIENT_LOCAL_FILES;
 
1143
#endif
 
1144
 
 
1145
  ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION;
 
1146
  ptr->options.report_data_truncation= true;  /* default */
 
1147
 
 
1148
  /*
 
1149
    By default we don't reconnect because it could silently corrupt data (after
 
1150
    reconnection you potentially lose table locks, user variables, session
 
1151
    variables (transactions but they are specifically dealt with in
 
1152
    drizzle_reconnect()).
 
1153
    This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
 
1154
    How this change impacts existing apps:
 
1155
    - existing apps which relyed on the default will see a behaviour change;
 
1156
    they will have to set reconnect=1 after drizzle_connect().
 
1157
    - existing apps which explicitely asked for reconnection (the only way they
 
1158
    could do it was by setting drizzle.reconnect to 1 after drizzle_connect())
 
1159
    will not see a behaviour change.
 
1160
    - existing apps which explicitely asked for no reconnection
 
1161
    (drizzle.reconnect=0) will not see a behaviour change.
 
1162
  */
 
1163
  ptr->reconnect= 0;
 
1164
 
 
1165
  return ptr;
 
1166
}
 
1167
 
 
1168
 
 
1169
/*
 
1170
  Free all memory and resources used by the client library
 
1171
 
 
1172
  NOTES
 
1173
    When calling this there should not be any other threads using
 
1174
    the library.
 
1175
 
 
1176
    To make things simpler when used with windows dll's (which calls this
 
1177
    function automaticly), it's safe to call this function multiple times.
 
1178
*/
 
1179
 
 
1180
 
 
1181
void STDCALL drizzle_server_end()
 
1182
{
 
1183
  if (!drizzle_client_init)
 
1184
    return;
 
1185
 
 
1186
  finish_client_errs();
 
1187
  vio_end();
 
1188
 
 
1189
  /* If library called my_init(), free memory allocated by it */
 
1190
  if (!org_my_init_done)
 
1191
  {
 
1192
    my_end(0);
 
1193
  }
 
1194
  else
 
1195
  {
 
1196
    free_charsets();
 
1197
    drizzle_thread_end();
 
1198
  }
 
1199
 
 
1200
  drizzle_client_init= org_my_init_done= 0;
 
1201
#ifdef EMBEDDED_SERVER
 
1202
  if (stderror_file)
 
1203
  {
 
1204
    fclose(stderror_file);
 
1205
    stderror_file= 0;
 
1206
  }
 
1207
#endif
 
1208
}
 
1209
 
 
1210
 
 
1211
/*
 
1212
  Fill in SSL part of DRIZZLE structure and set 'use_ssl' flag.
 
1213
  NB! Errors are not reported until you do drizzle_connect.
 
1214
*/
 
1215
 
 
1216
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
 
1217
 
 
1218
/*
 
1219
  Note that the drizzle argument must be initialized with drizzle_init()
 
1220
  before calling drizzle_connect !
 
1221
*/
 
1222
 
 
1223
static bool cli_read_query_result(DRIZZLE *drizzle);
 
1224
static DRIZZLE_RES *cli_use_result(DRIZZLE *drizzle);
 
1225
 
 
1226
static DRIZZLE_METHODS client_methods=
 
1227
{
 
1228
  cli_read_query_result,                       /* read_query_result */
 
1229
  cli_advanced_command,                        /* advanced_command */
 
1230
  cli_read_rows,                               /* read_rows */
 
1231
  cli_use_result,                              /* use_result */
 
1232
  cli_fetch_lengths,                           /* fetch_lengths */
 
1233
  cli_flush_use_result,                         /* flush_use_result */
 
1234
#ifndef MYSQL_SERVER
 
1235
  cli_list_fields,                            /* list_fields */
 
1236
  cli_unbuffered_fetch,                        /* unbuffered_fetch */
 
1237
  cli_read_statistics,                         /* read_statistics */
 
1238
  cli_read_query_result,                       /* next_result */
 
1239
  cli_read_change_user_result,                 /* read_change_user_result */
 
1240
#else
 
1241
  0,0,0,0,0
 
1242
#endif
 
1243
};
 
1244
 
 
1245
C_MODE_START
 
1246
int drizzle_init_character_set(DRIZZLE *drizzle)
 
1247
{
 
1248
  const char *default_collation_name;
 
1249
 
 
1250
  /* Set character set */
 
1251
  if (!drizzle->options.charset_name)
 
1252
  {
 
1253
    default_collation_name= MYSQL_DEFAULT_COLLATION_NAME;
 
1254
    if (!(drizzle->options.charset_name=
 
1255
       my_strdup(MYSQL_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
 
1256
    return 1;
 
1257
  }
 
1258
  else
 
1259
    default_collation_name= NULL;
 
1260
 
 
1261
  {
 
1262
    const char *save= charsets_dir;
 
1263
    if (drizzle->options.charset_dir)
 
1264
      charsets_dir=drizzle->options.charset_dir;
 
1265
    drizzle->charset=get_charset_by_csname(drizzle->options.charset_name,
 
1266
                                         MY_CS_PRIMARY, MYF(MY_WME));
 
1267
    if (drizzle->charset && default_collation_name)
 
1268
    {
 
1269
      CHARSET_INFO *collation;
 
1270
      if ((collation=
 
1271
           get_charset_by_name(default_collation_name, MYF(MY_WME))))
 
1272
      {
 
1273
        if (!my_charset_same(drizzle->charset, collation))
 
1274
        {
 
1275
          my_printf_error(ER_UNKNOWN_ERROR,
 
1276
                         "COLLATION %s is not valid for CHARACTER SET %s",
 
1277
                         MYF(0),
 
1278
                         default_collation_name, drizzle->options.charset_name);
 
1279
          drizzle->charset= NULL;
 
1280
        }
 
1281
        else
 
1282
        {
 
1283
          drizzle->charset= collation;
 
1284
        }
 
1285
      }
 
1286
      else
 
1287
        drizzle->charset= NULL;
 
1288
    }
 
1289
    charsets_dir= save;
 
1290
  }
 
1291
 
 
1292
  if (!drizzle->charset)
 
1293
  {
 
1294
    if (drizzle->options.charset_dir)
 
1295
      set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
1296
                               ER(CR_CANT_READ_CHARSET),
 
1297
                               drizzle->options.charset_name,
 
1298
                               drizzle->options.charset_dir);
 
1299
    else
 
1300
    {
 
1301
      char cs_dir_name[FN_REFLEN];
 
1302
      get_charsets_dir(cs_dir_name);
 
1303
      set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
1304
                               ER(CR_CANT_READ_CHARSET),
 
1305
                               drizzle->options.charset_name,
 
1306
                               cs_dir_name);
 
1307
    }
 
1308
    return 1;
 
1309
  }
 
1310
  return 0;
 
1311
}
 
1312
C_MODE_END
 
1313
 
 
1314
 
 
1315
DRIZZLE * STDCALL
 
1316
CLI_DRIZZLE_CONNECT(DRIZZLE *drizzle,const char *host, const char *user,
 
1317
                       const char *passwd, const char *db,
 
1318
                       uint32_t port, const char *unix_socket, uint32_t client_flag)
 
1319
{
 
1320
  char          buff[NAME_LEN+USERNAME_LENGTH+100];
 
1321
  char          *end,*host_info=NULL;
 
1322
  uint32_t         pkt_length;
 
1323
  NET           *net= &drizzle->net;
 
1324
  init_sigpipe_variables
 
1325
 
 
1326
  /* Don't give sigpipe errors if the client doesn't want them */
 
1327
  set_sigpipe(drizzle);
 
1328
  drizzle->methods= &client_methods;
 
1329
  net->vio = 0;        /* If something goes wrong */
 
1330
  drizzle->client_flag=0;      /* For handshake */
 
1331
 
 
1332
  /* use default options */
 
1333
  if (drizzle->options.my_cnf_file || drizzle->options.my_cnf_group)
 
1334
  {
 
1335
    drizzle_read_default_options(&drizzle->options,
 
1336
             (drizzle->options.my_cnf_file ?
 
1337
        drizzle->options.my_cnf_file : "my"),
 
1338
             drizzle->options.my_cnf_group);
 
1339
    my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
1340
    my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
1341
    drizzle->options.my_cnf_file=drizzle->options.my_cnf_group=0;
 
1342
  }
 
1343
 
 
1344
  /* Some empty-string-tests are done because of ODBC */
 
1345
  if (!host || !host[0])
 
1346
    host=drizzle->options.host;
 
1347
  if (!user || !user[0])
 
1348
  {
 
1349
    user=drizzle->options.user;
 
1350
    if (!user)
 
1351
      user= "";
 
1352
  }
 
1353
  if (!passwd)
 
1354
  {
 
1355
    passwd=drizzle->options.password;
 
1356
    if (!passwd)
 
1357
      passwd= "";
 
1358
  }
 
1359
  if (!db || !db[0])
 
1360
    db=drizzle->options.db;
 
1361
  if (!port)
 
1362
    port=drizzle->options.port;
 
1363
  if (!unix_socket)
 
1364
    unix_socket=drizzle->options.unix_socket;
 
1365
 
 
1366
  drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
 
1367
 
 
1368
  /*
 
1369
    Part 0: Grab a socket and connect it to the server
 
1370
  */
 
1371
  if (!net->vio &&
 
1372
      (!drizzle->options.protocol ||
 
1373
       drizzle->options.protocol == DRIZZLE_PROTOCOL_TCP))
 
1374
  {
 
1375
    struct addrinfo *res_lst, hints, *t_res;
 
1376
    int gai_errno;
 
1377
    char port_buf[NI_MAXSERV];
 
1378
 
 
1379
    unix_socket=0;        /* This is not used */
 
1380
 
 
1381
    if (!port)
 
1382
      port= drizzle_port;
 
1383
 
 
1384
    if (!host)
 
1385
      host= LOCAL_HOST;
 
1386
 
 
1387
    snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
 
1388
 
 
1389
    memset(&hints, 0, sizeof(hints));
 
1390
    hints.ai_socktype= SOCK_STREAM;
 
1391
    hints.ai_protocol= IPPROTO_TCP;
 
1392
    hints.ai_family= AF_UNSPEC;
 
1393
 
 
1394
    snprintf(port_buf, NI_MAXSERV, "%d", port);
 
1395
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
 
1396
 
 
1397
    if (gai_errno != 0)
 
1398
    {
 
1399
      set_drizzle_extended_error(drizzle, CR_UNKNOWN_HOST, unknown_sqlstate,
 
1400
                               ER(CR_UNKNOWN_HOST), host, errno);
 
1401
 
 
1402
      goto error;
 
1403
    }
 
1404
 
 
1405
    /* We only look at the first item (something to think about changing in the future) */
 
1406
    t_res= res_lst;
 
1407
    {
 
1408
      my_socket sock= socket(t_res->ai_family, t_res->ai_socktype,
 
1409
                             t_res->ai_protocol);
 
1410
      if (sock == SOCKET_ERROR)
 
1411
      {
 
1412
        set_drizzle_extended_error(drizzle, CR_IPSOCK_ERROR, unknown_sqlstate,
 
1413
                                 ER(CR_IPSOCK_ERROR), socket_errno);
 
1414
        freeaddrinfo(res_lst);
 
1415
        goto error;
 
1416
      }
 
1417
 
 
1418
      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
 
1419
      if (! net->vio )
 
1420
      {
 
1421
        set_drizzle_error(drizzle, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
 
1422
        closesocket(sock);
 
1423
        freeaddrinfo(res_lst);
 
1424
        goto error;
 
1425
      }
 
1426
 
 
1427
      if (my_connect(sock, t_res->ai_addr, t_res->ai_addrlen,
 
1428
                     drizzle->options.connect_timeout))
 
1429
      {
 
1430
        set_drizzle_extended_error(drizzle, CR_CONN_HOST_ERROR, unknown_sqlstate,
 
1431
                                 ER(CR_CONN_HOST_ERROR), host, socket_errno);
 
1432
        vio_delete(net->vio);
 
1433
        net->vio= 0;
 
1434
        freeaddrinfo(res_lst);
 
1435
        goto error;
 
1436
      }
 
1437
    }
 
1438
 
 
1439
    freeaddrinfo(res_lst);
 
1440
  }
 
1441
 
 
1442
  if (!net->vio)
 
1443
  {
 
1444
    set_drizzle_error(drizzle, CR_CONN_UNKNOW_PROTOCOL, unknown_sqlstate);
 
1445
    goto error;
 
1446
  }
 
1447
 
 
1448
  if (my_net_init(net, net->vio))
 
1449
  {
 
1450
    vio_delete(net->vio);
 
1451
    net->vio = 0;
 
1452
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1453
    goto error;
 
1454
  }
 
1455
  vio_keepalive(net->vio,true);
 
1456
 
 
1457
  /* If user set read_timeout, let it override the default */
 
1458
  if (drizzle->options.read_timeout)
 
1459
    my_net_set_read_timeout(net, drizzle->options.read_timeout);
 
1460
 
 
1461
  /* If user set write_timeout, let it override the default */
 
1462
  if (drizzle->options.write_timeout)
 
1463
    my_net_set_write_timeout(net, drizzle->options.write_timeout);
 
1464
 
 
1465
  if (drizzle->options.max_allowed_packet)
 
1466
    net->max_packet_size= drizzle->options.max_allowed_packet;
 
1467
 
 
1468
  /* Get version info */
 
1469
  drizzle->protocol_version= PROTOCOL_VERSION;  /* Assume this */
 
1470
  if (drizzle->options.connect_timeout &&
 
1471
      vio_poll_read(net->vio, drizzle->options.connect_timeout))
 
1472
  {
 
1473
    set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1474
                             ER(CR_SERVER_LOST_EXTENDED),
 
1475
                             "waiting for initial communication packet",
 
1476
                             errno);
 
1477
    goto error;
 
1478
  }
 
1479
 
 
1480
  /*
 
1481
    Part 1: Connection established, read and parse first packet
 
1482
  */
 
1483
 
 
1484
  if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
 
1485
  {
 
1486
    if (drizzle->net.last_errno == CR_SERVER_LOST)
 
1487
      set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1488
                               ER(CR_SERVER_LOST_EXTENDED),
 
1489
                               "reading initial communication packet",
 
1490
                               errno);
 
1491
    goto error;
 
1492
  }
 
1493
  /* Check if version of protocol matches current one */
 
1494
 
 
1495
  drizzle->protocol_version= net->read_pos[0];
 
1496
  if (drizzle->protocol_version != PROTOCOL_VERSION)
 
1497
  {
 
1498
    set_drizzle_extended_error(drizzle, CR_VERSION_ERROR, unknown_sqlstate,
 
1499
                             ER(CR_VERSION_ERROR), drizzle->protocol_version,
 
1500
                             PROTOCOL_VERSION);
 
1501
    goto error;
 
1502
  }
 
1503
  end=strend((char*) net->read_pos+1);
 
1504
  drizzle->thread_id=uint4korr(end+1);
 
1505
  end+=5;
 
1506
  /*
 
1507
    Scramble is split into two parts because old clients does not understand
 
1508
    long scrambles; here goes the first part.
 
1509
  */
 
1510
  strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
 
1511
  end+= SCRAMBLE_LENGTH_323+1;
 
1512
 
 
1513
  if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
 
1514
    drizzle->server_capabilities=uint2korr(end);
 
1515
  if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
 
1516
  {
 
1517
    /* New protocol with 16 bytes to describe server characteristics */
 
1518
    drizzle->server_language=end[2];
 
1519
    drizzle->server_status=uint2korr(end+3);
 
1520
  }
 
1521
  end+= 18;
 
1522
  if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
 
1523
                           (char *) net->read_pos))
 
1524
    strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
 
1525
            SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
 
1526
  else
 
1527
    drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
 
1528
 
 
1529
  if (drizzle->options.secure_auth && passwd[0] &&
 
1530
      !(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
 
1531
  {
 
1532
    set_drizzle_error(drizzle, CR_SECURE_AUTH, unknown_sqlstate);
 
1533
    goto error;
 
1534
  }
 
1535
 
 
1536
  if (drizzle_init_character_set(drizzle))
 
1537
    goto error;
 
1538
 
 
1539
  /* Save connection information */
 
1540
  if (!my_multi_malloc(MYF(0),
 
1541
           &drizzle->host_info, (uint) strlen(host_info)+1,
 
1542
           &drizzle->host,      (uint) strlen(host)+1,
 
1543
           &drizzle->unix_socket,unix_socket ?
 
1544
           (uint) strlen(unix_socket)+1 : (uint) 1,
 
1545
           &drizzle->server_version,
 
1546
           (uint) (end - (char*) net->read_pos),
 
1547
           NullS) ||
 
1548
      !(drizzle->user=my_strdup(user,MYF(0))) ||
 
1549
      !(drizzle->passwd=my_strdup(passwd,MYF(0))))
 
1550
  {
 
1551
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1552
    goto error;
 
1553
  }
 
1554
  strcpy(drizzle->host_info,host_info);
 
1555
  strcpy(drizzle->host,host);
 
1556
  if (unix_socket)
 
1557
    strcpy(drizzle->unix_socket,unix_socket);
 
1558
  else
 
1559
    drizzle->unix_socket=0;
 
1560
  strcpy(drizzle->server_version,(char*) net->read_pos+1);
 
1561
  drizzle->port=port;
 
1562
 
 
1563
  /*
 
1564
    Part 2: format and send client info to the server for access check
 
1565
  */
 
1566
 
 
1567
  client_flag|=drizzle->options.client_flag;
 
1568
  client_flag|=CLIENT_CAPABILITIES;
 
1569
  if (client_flag & CLIENT_MULTI_STATEMENTS)
 
1570
    client_flag|= CLIENT_MULTI_RESULTS;
 
1571
 
 
1572
  if (db)
 
1573
    client_flag|=CLIENT_CONNECT_WITH_DB;
 
1574
 
 
1575
  /* Remove options that server doesn't support */
 
1576
  client_flag= ((client_flag &
 
1577
     ~(CLIENT_COMPRESS | CLIENT_SSL | CLIENT_PROTOCOL_41)) |
 
1578
    (client_flag & drizzle->server_capabilities));
 
1579
  client_flag&= ~CLIENT_COMPRESS;
 
1580
 
 
1581
  if (client_flag & CLIENT_PROTOCOL_41)
 
1582
  {
 
1583
    /* 4.1 server and 4.1 client has a 32 byte option flag */
 
1584
    int4store(buff,client_flag);
 
1585
    int4store(buff+4, net->max_packet_size);
 
1586
    buff[8]= (char) drizzle->charset->number;
 
1587
    memset(buff+9, 0, 32-9);
 
1588
    end= buff+32;
 
1589
  }
 
1590
  else
 
1591
  {
 
1592
    int2store(buff,client_flag);
 
1593
    int3store(buff+2,net->max_packet_size);
 
1594
    end= buff+5;
 
1595
  }
 
1596
  drizzle->client_flag=client_flag;
 
1597
 
 
1598
  /* This needs to be changed as it's not useful with big packets */
 
1599
  if (user && user[0])
 
1600
    strncpy(end,user,USERNAME_LENGTH);          /* Max user name */
 
1601
  else
 
1602
    read_user_name((char*) end);
 
1603
 
 
1604
  /* We have to handle different version of handshake here */
 
1605
  end= strend(end) + 1;
 
1606
  if (passwd[0])
 
1607
  {
 
1608
    {
 
1609
      *end++= SCRAMBLE_LENGTH;
 
1610
      memset(end, 0, SCRAMBLE_LENGTH-1);
 
1611
      memcpy(end, passwd, strlen(passwd));
 
1612
      end+= SCRAMBLE_LENGTH;
 
1613
    }
 
1614
  }
 
1615
  else
 
1616
    *end++= '\0';                               /* empty password */
 
1617
 
 
1618
  /* Add database if needed */
 
1619
  if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
 
1620
  {
 
1621
    end= strncpy(end, db, NAME_LEN) + NAME_LEN + 1;
 
1622
    drizzle->db= my_strdup(db,MYF(MY_WME));
 
1623
    db= 0;
 
1624
  }
 
1625
  /* Write authentication package */
 
1626
  if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
 
1627
  {
 
1628
    set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1629
                             ER(CR_SERVER_LOST_EXTENDED),
 
1630
                             "sending authentication information",
 
1631
                             errno);
 
1632
    goto error;
 
1633
  }
 
1634
 
 
1635
  /*
 
1636
    Part 3: Authorization data's been sent. Now server can reply with
 
1637
    OK-packet, or re-request scrambled password.
 
1638
  */
 
1639
 
 
1640
  if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
 
1641
  {
 
1642
    if (drizzle->net.last_errno == CR_SERVER_LOST)
 
1643
      set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1644
                               ER(CR_SERVER_LOST_EXTENDED),
 
1645
                               "reading authorization packet",
 
1646
                               errno);
 
1647
    goto error;
 
1648
  }
 
1649
 
 
1650
  if (client_flag & CLIENT_COMPRESS)    /* We will use compression */
 
1651
    net->compress=1;
 
1652
 
 
1653
 
 
1654
  if (db && drizzle_select_db(drizzle, db))
 
1655
  {
 
1656
    if (drizzle->net.last_errno == CR_SERVER_LOST)
 
1657
        set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
 
1658
                                 ER(CR_SERVER_LOST_EXTENDED),
 
1659
                                 "Setting intital database",
 
1660
                                 errno);
 
1661
    goto error;
 
1662
  }
 
1663
 
 
1664
  if (drizzle->options.init_commands)
 
1665
  {
 
1666
    DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
 
1667
    char **ptr= (char**)init_commands->buffer;
 
1668
    char **end_command= ptr + init_commands->elements;
 
1669
 
 
1670
    my_bool reconnect=drizzle->reconnect;
 
1671
    drizzle->reconnect=0;
 
1672
 
 
1673
    for (; ptr < end_command; ptr++)
 
1674
    {
 
1675
      DRIZZLE_RES *res;
 
1676
      if (drizzle_real_query(drizzle,*ptr, (ulong) strlen(*ptr)))
 
1677
  goto error;
 
1678
      if (drizzle->fields)
 
1679
      {
 
1680
  if (!(res= cli_use_result(drizzle)))
 
1681
    goto error;
 
1682
  drizzle_free_result(res);
 
1683
      }
 
1684
    }
 
1685
    drizzle->reconnect=reconnect;
 
1686
  }
 
1687
 
 
1688
  reset_sigpipe(drizzle);
 
1689
  return(drizzle);
 
1690
 
 
1691
error:
 
1692
  reset_sigpipe(drizzle);
 
1693
  {
 
1694
    /* Free alloced memory */
 
1695
    end_server(drizzle);
 
1696
    drizzle_close_free(drizzle);
 
1697
    if (!(((ulong) client_flag) & CLIENT_REMEMBER_OPTIONS))
 
1698
      drizzle_close_free_options(drizzle);
 
1699
  }
 
1700
  return(0);
 
1701
}
 
1702
 
 
1703
 
 
1704
my_bool drizzle_reconnect(DRIZZLE *drizzle)
 
1705
{
 
1706
  DRIZZLE tmp_drizzle;
 
1707
  assert(drizzle);
 
1708
 
 
1709
  if (!drizzle->reconnect ||
 
1710
      (drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
 
1711
  {
 
1712
    /* Allow reconnect next time */
 
1713
    drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
 
1714
    set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
 
1715
    return(1);
 
1716
  }
 
1717
  drizzle_create(&tmp_drizzle);
 
1718
  tmp_drizzle.options= drizzle->options;
 
1719
  tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
 
1720
 
 
1721
  if (!drizzle_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
 
1722
        drizzle->db, drizzle->port, drizzle->unix_socket,
 
1723
        drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
 
1724
  {
 
1725
    drizzle->net.last_errno= tmp_drizzle.net.last_errno;
 
1726
    strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
 
1727
    strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
 
1728
    return(1);
 
1729
  }
 
1730
  if (drizzle_set_character_set(&tmp_drizzle, drizzle->charset->csname))
 
1731
  {
 
1732
    memset((char*) &tmp_drizzle.options, 0, sizeof(tmp_drizzle.options));
 
1733
    drizzle_close(&tmp_drizzle);
 
1734
    drizzle->net.last_errno= tmp_drizzle.net.last_errno;
 
1735
    strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
 
1736
    strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
 
1737
    return(1);
 
1738
  }
 
1739
 
 
1740
  tmp_drizzle.reconnect= 1;
 
1741
  tmp_drizzle.free_me= drizzle->free_me;
 
1742
 
 
1743
  /* Don't free options as these are now used in tmp_drizzle */
 
1744
  memset((char*) &drizzle->options, 0, sizeof(drizzle->options));
 
1745
  drizzle->free_me=0;
 
1746
  drizzle_close(drizzle);
 
1747
  *drizzle=tmp_drizzle;
 
1748
  net_clear(&drizzle->net, 1);
 
1749
  drizzle->affected_rows= ~(uint64_t) 0;
 
1750
  return(0);
 
1751
}
 
1752
 
 
1753
 
 
1754
/**************************************************************************
 
1755
  Set current database
 
1756
**************************************************************************/
 
1757
 
 
1758
int STDCALL
 
1759
drizzle_select_db(DRIZZLE *drizzle, const char *db)
 
1760
{
 
1761
  int error;
 
1762
 
 
1763
  if ((error=simple_command(drizzle,COM_INIT_DB, (const uchar*) db,
 
1764
                            (ulong) strlen(db),0)))
 
1765
    return(error);
 
1766
  my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
 
1767
  drizzle->db=my_strdup(db,MYF(MY_WME));
 
1768
  return(0);
 
1769
}
 
1770
 
 
1771
 
 
1772
/*************************************************************************
 
1773
  Send a QUIT to the server and close the connection
 
1774
  If handle is alloced by DRIZZLE connect free it.
 
1775
*************************************************************************/
 
1776
 
 
1777
static void drizzle_close_free_options(DRIZZLE *drizzle)
 
1778
{
 
1779
  my_free(drizzle->options.user,MYF(MY_ALLOW_ZERO_PTR));
 
1780
  my_free(drizzle->options.host,MYF(MY_ALLOW_ZERO_PTR));
 
1781
  my_free(drizzle->options.password,MYF(MY_ALLOW_ZERO_PTR));
 
1782
  my_free(drizzle->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
 
1783
  my_free(drizzle->options.db,MYF(MY_ALLOW_ZERO_PTR));
 
1784
  my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
1785
  my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
1786
  my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
1787
  my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
1788
  my_free(drizzle->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
 
1789
  if (drizzle->options.init_commands)
 
1790
  {
 
1791
    DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
 
1792
    char **ptr= (char**)init_commands->buffer;
 
1793
    char **end= ptr + init_commands->elements;
 
1794
    for (; ptr<end; ptr++)
 
1795
      my_free(*ptr,MYF(MY_WME));
 
1796
    delete_dynamic(init_commands);
 
1797
    my_free((char*)init_commands,MYF(MY_WME));
 
1798
  }
 
1799
  memset((char*) &drizzle->options, 0, sizeof(drizzle->options));
 
1800
  return;
 
1801
}
 
1802
 
 
1803
 
 
1804
static void drizzle_close_free(DRIZZLE *drizzle)
 
1805
{
 
1806
  my_free((uchar*) drizzle->host_info,MYF(MY_ALLOW_ZERO_PTR));
 
1807
  my_free(drizzle->user,MYF(MY_ALLOW_ZERO_PTR));
 
1808
  my_free(drizzle->passwd,MYF(MY_ALLOW_ZERO_PTR));
 
1809
  my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
 
1810
  my_free(drizzle->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
 
1811
  drizzle->info_buffer= 0;
 
1812
 
 
1813
  /* Clear pointers for better safety */
 
1814
  drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
 
1815
}
 
1816
 
 
1817
 
 
1818
void STDCALL drizzle_close(DRIZZLE *drizzle)
 
1819
{
 
1820
  if (drizzle)          /* Some simple safety */
 
1821
  {
 
1822
    /* If connection is still up, send a QUIT message */
 
1823
    if (drizzle->net.vio != 0)
 
1824
    {
 
1825
      free_old_query(drizzle);
 
1826
      drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
 
1827
      drizzle->reconnect=0;
 
1828
      simple_command(drizzle,COM_QUIT,(uchar*) 0,0,1);
 
1829
      end_server(drizzle);      /* Sets drizzle->net.vio= 0 */
 
1830
    }
 
1831
    drizzle_close_free_options(drizzle);
 
1832
    drizzle_close_free(drizzle);
 
1833
    if (drizzle->free_me)
 
1834
      my_free((uchar*) drizzle,MYF(0));
 
1835
  }
 
1836
  return;
 
1837
}
 
1838
 
 
1839
 
 
1840
static bool cli_read_query_result(DRIZZLE *drizzle)
 
1841
{
 
1842
  uchar *pos;
 
1843
  ulong field_count;
 
1844
  DRIZZLE_DATA *fields;
 
1845
  ulong length;
 
1846
 
 
1847
  if ((length = cli_safe_read(drizzle)) == packet_error)
 
1848
    return(1);
 
1849
  free_old_query(drizzle);    /* Free old result */
 
1850
#ifdef MYSQL_CLIENT      /* Avoid warn of unused labels*/
 
1851
get_info:
 
1852
#endif
 
1853
  pos=(uchar*) drizzle->net.read_pos;
 
1854
  if ((field_count= net_field_length(&pos)) == 0)
 
1855
  {
 
1856
    drizzle->affected_rows= net_field_length_ll(&pos);
 
1857
    drizzle->insert_id=    net_field_length_ll(&pos);
 
1858
    if (protocol_41(drizzle))
 
1859
    {
 
1860
      drizzle->server_status=uint2korr(pos); pos+=2;
 
1861
      drizzle->warning_count=uint2korr(pos); pos+=2;
 
1862
    }
 
1863
    else if (drizzle->server_capabilities & CLIENT_TRANSACTIONS)
 
1864
    {
 
1865
      /* DRIZZLE 4.0 protocol */
 
1866
      drizzle->server_status=uint2korr(pos); pos+=2;
 
1867
      drizzle->warning_count= 0;
 
1868
    }
 
1869
    if (pos < drizzle->net.read_pos+length && net_field_length(&pos))
 
1870
      drizzle->info=(char*) pos;
 
1871
    return(0);
 
1872
  }
 
1873
#ifdef MYSQL_CLIENT
 
1874
  if (field_count == NULL_LENGTH)    /* LOAD DATA LOCAL INFILE */
 
1875
  {
 
1876
    int error;
 
1877
 
 
1878
    if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES))
 
1879
    {
 
1880
      set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
 
1881
      return(1);
 
1882
    }  
 
1883
 
 
1884
    error= handle_local_infile(drizzle,(char*) pos);
 
1885
    if ((length= cli_safe_read(drizzle)) == packet_error || error)
 
1886
      return(1);
 
1887
    goto get_info;        /* Get info packet */
 
1888
  }
 
1889
#endif
 
1890
  if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
 
1891
    drizzle->server_status|= SERVER_STATUS_IN_TRANS;
 
1892
 
 
1893
  if (!(fields=cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, protocol_41(drizzle) ? 7:5)))
 
1894
    return(1);
 
1895
  if (!(drizzle->fields=unpack_fields(fields,&drizzle->field_alloc,
 
1896
            (uint) field_count,0,
 
1897
            drizzle->server_capabilities)))
 
1898
    return(1);
 
1899
  drizzle->status= DRIZZLE_STATUS_GET_RESULT;
 
1900
  drizzle->field_count= (uint) field_count;
 
1901
  return(0);
 
1902
}
 
1903
 
 
1904
 
 
1905
/*
 
1906
  Send the query and return so we can do something else.
 
1907
  Needs to be followed by drizzle_read_query_result() when we want to
 
1908
  finish processing it.
 
1909
*/
 
1910
 
 
1911
int32_t STDCALL
 
1912
drizzle_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
 
1913
{
 
1914
  return(simple_command(drizzle, COM_QUERY, (uchar*) query, length, 1));
 
1915
}
 
1916
 
 
1917
 
 
1918
int32_t STDCALL
 
1919
drizzle_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
 
1920
{
 
1921
  if (drizzle_send_query(drizzle,query,length))
 
1922
    return(1);
 
1923
  return((int) (*drizzle->methods->read_query_result)(drizzle));
 
1924
}
 
1925
 
 
1926
 
 
1927
/**************************************************************************
 
1928
  Alloc result struct for buffered results. All rows are read to buffer.
 
1929
  drizzle_data_seek may be used.
 
1930
**************************************************************************/
 
1931
 
 
1932
DRIZZLE_RES * STDCALL drizzle_store_result(DRIZZLE *drizzle)
 
1933
{
 
1934
  DRIZZLE_RES *result;
 
1935
 
 
1936
  if (!drizzle->fields)
 
1937
    return(0);
 
1938
  if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
 
1939
  {
 
1940
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
1941
    return(0);
 
1942
  }
 
1943
  drizzle->status=DRIZZLE_STATUS_READY;    /* server is ready */
 
1944
  if (!(result=(DRIZZLE_RES*) my_malloc((uint) (sizeof(DRIZZLE_RES)+
 
1945
                sizeof(ulong) *
 
1946
                drizzle->field_count),
 
1947
              MYF(MY_WME | MY_ZEROFILL))))
 
1948
  {
 
1949
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
1950
    return(0);
 
1951
  }
 
1952
  result->methods= drizzle->methods;
 
1953
  result->eof= 1;        /* Marker for buffered */
 
1954
  result->lengths= (uint32_t*) (result+1);
 
1955
  if (!(result->data=
 
1956
  (*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
 
1957
  {
 
1958
    my_free((uchar*) result,MYF(0));
 
1959
    return(0);
 
1960
  }
 
1961
  drizzle->affected_rows= result->row_count= result->data->rows;
 
1962
  result->data_cursor=  result->data->data;
 
1963
  result->fields=  drizzle->fields;
 
1964
  result->field_alloc=  drizzle->field_alloc;
 
1965
  result->field_count=  drizzle->field_count;
 
1966
  /* The rest of result members is zeroed in malloc */
 
1967
  drizzle->fields=0;        /* fields is now in result */
 
1968
  clear_alloc_root(&drizzle->field_alloc);
 
1969
  /* just in case this was mistakenly called after drizzle_stmt_execute() */
 
1970
  drizzle->unbuffered_fetch_owner= 0;
 
1971
  return(result);        /* Data fetched */
 
1972
}
 
1973
 
 
1974
 
 
1975
/**************************************************************************
 
1976
  Alloc struct for use with unbuffered reads. Data is fetched by domand
 
1977
  when calling to drizzle_fetch_row.
 
1978
  DRIZZLE_DATA_seek is a noop.
 
1979
 
 
1980
  No other queries may be specified with the same DRIZZLE handle.
 
1981
  There shouldn't be much processing per row because DRIZZLE server shouldn't
 
1982
  have to wait for the client (and will not wait more than 30 sec/packet).
 
1983
**************************************************************************/
 
1984
 
 
1985
static DRIZZLE_RES * cli_use_result(DRIZZLE *drizzle)
 
1986
{
 
1987
  DRIZZLE_RES *result;
 
1988
 
 
1989
  if (!drizzle->fields)
 
1990
    return(0);
 
1991
  if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
 
1992
  {
 
1993
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
1994
    return(0);
 
1995
  }
 
1996
  if (!(result=(DRIZZLE_RES*) my_malloc(sizeof(*result)+
 
1997
              sizeof(ulong)*drizzle->field_count,
 
1998
              MYF(MY_WME | MY_ZEROFILL))))
 
1999
    return(0);
 
2000
  result->lengths=(uint32_t*) (result+1);
 
2001
  result->methods= drizzle->methods;
 
2002
  if (!(result->row=(DRIZZLE_ROW)
 
2003
  my_malloc(sizeof(result->row[0])*(drizzle->field_count+1), MYF(MY_WME))))
 
2004
  {          /* Ptrs: to one row */
 
2005
    my_free((uchar*) result,MYF(0));
 
2006
    return(0);
 
2007
  }
 
2008
  result->fields=  drizzle->fields;
 
2009
  result->field_alloc=  drizzle->field_alloc;
 
2010
  result->field_count=  drizzle->field_count;
 
2011
  result->current_field=0;
 
2012
  result->handle=  drizzle;
 
2013
  result->current_row=  0;
 
2014
  drizzle->fields=0;      /* fields is now in result */
 
2015
  clear_alloc_root(&drizzle->field_alloc);
 
2016
  drizzle->status=DRIZZLE_STATUS_USE_RESULT;
 
2017
  drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
 
2018
  return(result);      /* Data is read to be fetched */
 
2019
}
 
2020
 
 
2021
 
 
2022
/**************************************************************************
 
2023
  Return next row of the query results
 
2024
**************************************************************************/
 
2025
 
 
2026
DRIZZLE_ROW STDCALL
 
2027
drizzle_fetch_row(DRIZZLE_RES *res)
 
2028
{
 
2029
  if (!res->data)
 
2030
  {            /* Unbufferred fetch */
 
2031
    if (!res->eof)
 
2032
    {
 
2033
      DRIZZLE *drizzle= res->handle;
 
2034
      if (drizzle->status != DRIZZLE_STATUS_USE_RESULT)
 
2035
      {
 
2036
        set_drizzle_error(drizzle,
 
2037
                        res->unbuffered_fetch_cancelled ?
 
2038
                        CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
 
2039
                        unknown_sqlstate);
 
2040
      }
 
2041
      else if (!(read_one_row(drizzle, res->field_count, res->row, res->lengths)))
 
2042
      {
 
2043
  res->row_count++;
 
2044
  return(res->current_row=res->row);
 
2045
      }
 
2046
      res->eof=1;
 
2047
      drizzle->status=DRIZZLE_STATUS_READY;
 
2048
      /*
 
2049
        Reset only if owner points to us: there is a chance that somebody
 
2050
        started new query after drizzle_stmt_close():
 
2051
      */
 
2052
      if (drizzle->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
 
2053
        drizzle->unbuffered_fetch_owner= 0;
 
2054
      /* Don't clear handle in drizzle_free_result */
 
2055
      res->handle=0;
 
2056
    }
 
2057
    return((DRIZZLE_ROW) NULL);
 
2058
  }
 
2059
  {
 
2060
    DRIZZLE_ROW tmp;
 
2061
    if (!res->data_cursor)
 
2062
    {
 
2063
      return(res->current_row=(DRIZZLE_ROW) NULL);
 
2064
    }
 
2065
    tmp = res->data_cursor->data;
 
2066
    res->data_cursor = res->data_cursor->next;
 
2067
    return(res->current_row=tmp);
 
2068
  }
 
2069
}
 
2070
 
 
2071
 
 
2072
/**************************************************************************
 
2073
  Get column lengths of the current row
 
2074
  If one uses drizzle_use_result, res->lengths contains the length information,
 
2075
  else the lengths are calculated from the offset between pointers.
 
2076
**************************************************************************/
 
2077
 
 
2078
uint32_t * STDCALL
 
2079
drizzle_fetch_lengths(DRIZZLE_RES *res)
 
2080
{
 
2081
  DRIZZLE_ROW column;
 
2082
 
 
2083
  if (!(column=res->current_row))
 
2084
    return 0;          /* Something is wrong */
 
2085
  if (res->data)
 
2086
    (*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
 
2087
  return res->lengths;
 
2088
}
 
2089
 
 
2090
 
 
2091
int STDCALL
 
2092
drizzle_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
 
2093
{
 
2094
  switch (option) {
 
2095
  case DRIZZLE_OPT_CONNECT_TIMEOUT:
 
2096
    drizzle->options.connect_timeout= *(uint*) arg;
 
2097
    break;
 
2098
  case DRIZZLE_OPT_READ_TIMEOUT:
 
2099
    drizzle->options.read_timeout= *(uint*) arg;
 
2100
    break;
 
2101
  case DRIZZLE_OPT_WRITE_TIMEOUT:
 
2102
    drizzle->options.write_timeout= *(uint*) arg;
 
2103
    break;
 
2104
  case DRIZZLE_OPT_COMPRESS:
 
2105
    drizzle->options.compress= 1;      /* Remember for connect */
 
2106
    drizzle->options.client_flag|= CLIENT_COMPRESS;
 
2107
    break;
 
2108
  case DRIZZLE_OPT_LOCAL_INFILE:      /* Allow LOAD DATA LOCAL ?*/
 
2109
    if (!arg || test(*(uint*) arg))
 
2110
      drizzle->options.client_flag|= CLIENT_LOCAL_FILES;
 
2111
    else
 
2112
      drizzle->options.client_flag&= ~CLIENT_LOCAL_FILES;
 
2113
    break;
 
2114
  case DRIZZLE_INIT_COMMAND:
 
2115
    add_init_command(&drizzle->options,arg);
 
2116
    break;
 
2117
  case DRIZZLE_READ_DEFAULT_FILE:
 
2118
    my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
 
2119
    drizzle->options.my_cnf_file=my_strdup(arg,MYF(MY_WME));
 
2120
    break;
 
2121
  case DRIZZLE_READ_DEFAULT_GROUP:
 
2122
    my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
 
2123
    drizzle->options.my_cnf_group=my_strdup(arg,MYF(MY_WME));
 
2124
    break;
 
2125
  case DRIZZLE_SET_CHARSET_DIR:
 
2126
    my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
 
2127
    drizzle->options.charset_dir=my_strdup(arg,MYF(MY_WME));
 
2128
    break;
 
2129
  case DRIZZLE_SET_CHARSET_NAME:
 
2130
    my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
 
2131
    drizzle->options.charset_name=my_strdup(arg,MYF(MY_WME));
 
2132
    break;
 
2133
  case DRIZZLE_OPT_PROTOCOL:
 
2134
    drizzle->options.protocol= *(uint*) arg;
 
2135
    break;
 
2136
  case DRIZZLE_OPT_USE_REMOTE_CONNECTION:
 
2137
  case DRIZZLE_OPT_GUESS_CONNECTION:
 
2138
    drizzle->options.methods_to_use= option;
 
2139
    break;
 
2140
  case DRIZZLE_SET_CLIENT_IP:
 
2141
    drizzle->options.client_ip= my_strdup(arg, MYF(MY_WME));
 
2142
    break;
 
2143
  case DRIZZLE_SECURE_AUTH:
 
2144
    drizzle->options.secure_auth= *(my_bool *) arg;
 
2145
    break;
 
2146
  case DRIZZLE_REPORT_DATA_TRUNCATION:
 
2147
    drizzle->options.report_data_truncation= test(*(my_bool *) arg);
 
2148
    break;
 
2149
  case DRIZZLE_OPT_RECONNECT:
 
2150
    drizzle->reconnect= *(my_bool *) arg;
 
2151
    break;
 
2152
  case DRIZZLE_OPT_SSL_VERIFY_SERVER_CERT:
 
2153
    if (*(my_bool*) arg)
 
2154
      drizzle->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;
 
2155
    else
 
2156
      drizzle->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
 
2157
    break;
 
2158
  default:
 
2159
    return(1);
 
2160
  }
 
2161
  return(0);
 
2162
}
 
2163
 
 
2164
 
 
2165
/****************************************************************************
 
2166
  Functions to get information from the DRIZZLE structure
 
2167
  These are functions to make shared libraries more usable.
 
2168
****************************************************************************/
 
2169
 
 
2170
/* DRIZZLE_RES */
 
2171
uint64_t STDCALL drizzle_num_rows(const DRIZZLE_RES *res)
 
2172
{
 
2173
  return res->row_count;
 
2174
}
 
2175
 
 
2176
unsigned int STDCALL drizzle_num_fields(const DRIZZLE_RES *res)
 
2177
{
 
2178
  return res->field_count;
 
2179
}
 
2180
 
 
2181
uint STDCALL drizzle_errno(const DRIZZLE *drizzle)
 
2182
{
 
2183
  return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno;
 
2184
}
 
2185
 
 
2186
 
 
2187
const char * STDCALL drizzle_error(const DRIZZLE *drizzle)
 
2188
{
 
2189
  return drizzle ? drizzle->net.last_error : drizzle_server_last_error;
 
2190
}
 
2191
 
 
2192
 
 
2193
/*
 
2194
  Get version number for server in a form easy to test on
 
2195
 
 
2196
  SYNOPSIS
 
2197
    drizzle_get_server_version()
 
2198
    drizzle Connection
 
2199
 
 
2200
  EXAMPLE
 
2201
    4.1.0-alfa ->  40100
 
2202
 
 
2203
  NOTES
 
2204
    We will ensure that a newer server always has a bigger number.
 
2205
 
 
2206
  RETURN
 
2207
   Signed number > 323000
 
2208
*/
 
2209
 
 
2210
uint32_t STDCALL
 
2211
drizzle_get_server_version(const DRIZZLE *drizzle)
 
2212
{
 
2213
  uint major, minor, version;
 
2214
  char *pos= drizzle->server_version, *end_pos;
 
2215
  major=   (uint) strtoul(pos, &end_pos, 10);  pos=end_pos+1;
 
2216
  minor=   (uint) strtoul(pos, &end_pos, 10);  pos=end_pos+1;
 
2217
  version= (uint) strtoul(pos, &end_pos, 10);
 
2218
  return (ulong) major*10000L+(ulong) (minor*100+version);
 
2219
}
 
2220
 
 
2221
 
 
2222
/*
 
2223
   drizzle_set_character_set function sends SET NAMES cs_name to
 
2224
   the server (which changes character_set_client, character_set_result
 
2225
   and character_set_connection) and updates drizzle->charset so other
 
2226
   functions like drizzle_real_escape will work correctly.
 
2227
*/
 
2228
int STDCALL drizzle_set_character_set(DRIZZLE *drizzle, const char *cs_name)
 
2229
{
 
2230
  struct charset_info_st *cs;
 
2231
  const char *save_csdir= charsets_dir;
 
2232
 
 
2233
  if (drizzle->options.charset_dir)
 
2234
    charsets_dir= drizzle->options.charset_dir;
 
2235
 
 
2236
  if (strlen(cs_name) < MY_CS_NAME_SIZE &&
 
2237
     (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
 
2238
  {
 
2239
    char buff[MY_CS_NAME_SIZE + 10];
 
2240
    charsets_dir= save_csdir;
 
2241
    /* Skip execution of "SET NAMES" for pre-4.1 servers */
 
2242
    if (drizzle_get_server_version(drizzle) < 40100)
 
2243
      return 0;
 
2244
    sprintf(buff, "SET NAMES %s", cs_name);
 
2245
    if (!drizzle_real_query(drizzle, buff, strlen(buff)))
 
2246
    {
 
2247
      drizzle->charset= cs;
 
2248
    }
 
2249
  }
 
2250
  else
 
2251
  {
 
2252
    char cs_dir_name[FN_REFLEN];
 
2253
    get_charsets_dir(cs_dir_name);
 
2254
    set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
 
2255
                             ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
 
2256
  }
 
2257
  charsets_dir= save_csdir;
 
2258
  return drizzle->net.last_errno;
 
2259
}
 
2260
 
 
2261