~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/client.c

  • Committer: Brian Aker
  • Date: 2010-02-07 01:33:54 UTC
  • Revision ID: brian@gaz-20100207013354-d2pg1n68u5c09pgo
Remove giant include header to its own file.

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 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
 
 
59
 
#include <sys/stat.h>
60
 
#include <signal.h>
61
 
#include <time.h>
62
 
#ifdef   HAVE_PWD_H
63
 
#include <pwd.h>
64
 
#endif
65
 
 
66
 
#include <sys/socket.h>
67
 
#include <netinet/in.h>
68
 
#include <arpa/inet.h>
69
 
#include <netdb.h>
70
 
#ifdef HAVE_SELECT_H
71
 
#  include <select.h>
72
 
#endif
73
 
#ifdef HAVE_SYS_SELECT_H
74
 
#include <sys/select.h>
75
 
#endif
76
 
 
77
 
#include <sys/un.h>
78
 
 
79
 
#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
 
 
175
 
 
176
 
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
177
 
struct passwd *getpwuid(uid_t);
178
 
char* getlogin(void);
179
 
#endif
180
 
 
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
 
 
281
 
/*****************************************************************************
282
 
  Read a packet from server. Give error message if socket was down
283
 
  or packet is an error message
284
 
*****************************************************************************/
285
 
 
286
 
uint32_t cli_safe_read(DRIZZLE *drizzle)
287
 
{
288
 
  NET *net= &drizzle->net;
289
 
  uint32_t len=0;
290
 
  init_sigpipe_variables
291
 
 
292
 
  /* Don't give sigpipe errors if the client doesn't want them */
293
 
  set_sigpipe(drizzle);
294
 
  if (net->vio != 0)
295
 
    len=my_net_read(net);
296
 
  reset_sigpipe(drizzle);
297
 
 
298
 
  if (len == packet_error || len == 0)
299
 
  {
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);
307
 
    return (packet_error);
308
 
  }
309
 
  if (net->read_pos[0] == 255)
310
 
  {
311
 
    if (len > 3)
312
 
    {
313
 
      char *pos=(char*) net->read_pos+1;
314
 
      net->last_errno=uint2korr(pos);
315
 
      pos+=2;
316
 
      len-=2;
317
 
      if (pos[0] == '#')
318
 
      {
319
 
        strncpy(net->sqlstate, pos+1, SQLSTATE_LENGTH);
320
 
        pos+= SQLSTATE_LENGTH+1;
321
 
      }
322
 
      else
323
 
      {
324
 
        /*
325
 
          The SQL state hasn't been received -- it should be reset to HY000
326
 
          (unknown error sql state).
327
 
        */
328
 
 
329
 
        strcpy(net->sqlstate, unknown_sqlstate);
330
 
      }
331
 
 
332
 
      strncpy(net->last_error,(char*) pos, min((uint) len,
333
 
              (uint32_t) sizeof(net->last_error)-1));
334
 
    }
335
 
    else
336
 
      set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
337
 
    /*
338
 
      Cover a protocol design error: error packet does not
339
 
      contain the server status. Therefore, the client has no way
340
 
      to find out whether there are more result sets of
341
 
      a multiple-result-set statement pending. Luckily, in 5.0 an
342
 
      error always aborts execution of a statement, wherever it is
343
 
      a multi-statement or a stored procedure, so it should be
344
 
      safe to unconditionally turn off the flag here.
345
 
    */
346
 
    drizzle->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
347
 
 
348
 
    return(packet_error);
349
 
  }
350
 
  return len;
351
 
}
352
 
 
353
 
void free_rows(DRIZZLE_DATA *cur)
354
 
{
355
 
  if (cur)
356
 
  {
357
 
    free_root(&cur->alloc,MYF(0));
358
 
    my_free((uchar*) cur,MYF(0));
359
 
  }
360
 
}
361
 
 
362
 
bool
363
 
cli_advanced_command(DRIZZLE *drizzle, enum enum_server_command command,
364
 
         const unsigned char *header, uint32_t header_length,
365
 
         const unsigned char *arg, uint32_t arg_length, bool skip_check)
366
 
{
367
 
  NET *net= &drizzle->net;
368
 
  bool result= 1;
369
 
  init_sigpipe_variables
370
 
  bool stmt_skip= false;
371
 
 
372
 
  /* Don't give sigpipe errors if the client doesn't want them */
373
 
  set_sigpipe(drizzle);
374
 
 
375
 
  if (drizzle->net.vio == 0)
376
 
  {            /* Do reconnect if possible */
377
 
    if (drizzle_reconnect(drizzle) || stmt_skip)
378
 
      return(1);
379
 
  }
380
 
  if (drizzle->status != DRIZZLE_STATUS_READY ||
381
 
      drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
382
 
  {
383
 
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
384
 
    return(1);
385
 
  }
386
 
 
387
 
  net_clear_error(net);
388
 
  drizzle->info=0;
389
 
  drizzle->affected_rows= ~(uint64_t) 0;
390
 
  /*
391
 
    We don't want to clear the protocol buffer on COM_QUIT, because if
392
 
    the previous command was a shutdown command, we may have the
393
 
    response for the COM_QUIT already in the communication buffer
394
 
  */
395
 
  net_clear(&drizzle->net, (command != COM_QUIT));
396
 
 
397
 
  if (net_write_command(net,(uchar) command, header, header_length,
398
 
      arg, arg_length))
399
 
  {
400
 
    if (net->last_errno == ER_NET_PACKET_TOO_LARGE)
401
 
    {
402
 
      set_drizzle_error(drizzle, CR_NET_PACKET_TOO_LARGE, unknown_sqlstate);
403
 
      goto end;
404
 
    }
405
 
    end_server(drizzle);
406
 
    if (drizzle_reconnect(drizzle) || stmt_skip)
407
 
      goto end;
408
 
    if (net_write_command(net,(uchar) command, header, header_length,
409
 
        arg, arg_length))
410
 
    {
411
 
      set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
412
 
      goto end;
413
 
    }
414
 
  }
415
 
  result=0;
416
 
  if (!skip_check)
417
 
    result= ((drizzle->packet_length=cli_safe_read(drizzle)) == packet_error ?
418
 
       1 : 0);
419
 
end:
420
 
  reset_sigpipe(drizzle);
421
 
  return(result);
422
 
}
423
 
 
424
 
void free_old_query(DRIZZLE *drizzle)
425
 
{
426
 
  if (drizzle->fields)
427
 
    free_root(&drizzle->field_alloc,MYF(0));
428
 
  init_alloc_root(&drizzle->field_alloc,8192,0); /* Assume rowlength < 8192 */
429
 
  drizzle->fields= 0;
430
 
  drizzle->field_count= 0;      /* For API */
431
 
  drizzle->warning_count= 0;
432
 
  drizzle->info= 0;
433
 
  return;
434
 
}
435
 
 
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
 
}
480
 
 
481
 
 
482
 
void
483
 
drizzle_free_result(DRIZZLE_RES *result)
484
 
{
485
 
  if (result)
486
 
  {
487
 
    DRIZZLE *drizzle= result->handle;
488
 
    if (drizzle)
489
 
    {
490
 
      if (drizzle->unbuffered_fetch_owner == &result->unbuffered_fetch_cancelled)
491
 
        drizzle->unbuffered_fetch_owner= 0;
492
 
      if (drizzle->status == DRIZZLE_STATUS_USE_RESULT)
493
 
      {
494
 
        (*drizzle->methods->flush_use_result)(drizzle);
495
 
        drizzle->status=DRIZZLE_STATUS_READY;
496
 
        if (drizzle->unbuffered_fetch_owner)
497
 
          *drizzle->unbuffered_fetch_owner= true;
498
 
      }
499
 
    }
500
 
    free_rows(result->data);
501
 
    if (result->fields)
502
 
      free_root(&result->field_alloc,MYF(0));
503
 
    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
 
}
791
 
 
792
 
/* Read all rows (fields or data) from server */
793
 
 
794
 
DRIZZLE_DATA *cli_read_rows(DRIZZLE *drizzle, DRIZZLE_FIELD *DRIZZLE_FIELDs, uint32_t fields)
795
 
{
796
 
  uint32_t  field;
797
 
  uint32_t pkt_len;
798
 
  uint32_t len;
799
 
  unsigned char *cp;
800
 
  char  *to, *end_to;
801
 
  DRIZZLE_DATA *result;
802
 
  DRIZZLE_ROWS **prev_ptr,*cur;
803
 
  NET *net = &drizzle->net;
804
 
 
805
 
  if ((pkt_len= cli_safe_read(drizzle)) == packet_error)
806
 
    return(0);
807
 
  if (!(result=(DRIZZLE_DATA*) my_malloc(sizeof(DRIZZLE_DATA),
808
 
               MYF(MY_WME | MY_ZEROFILL))))
809
 
  {
810
 
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
811
 
    return(0);
812
 
  }
813
 
  init_alloc_root(&result->alloc,8192,0);  /* Assume rowlength < 8192 */
814
 
  result->alloc.min_malloc=sizeof(DRIZZLE_ROWS);
815
 
  prev_ptr= &result->data;
816
 
  result->rows=0;
817
 
  result->fields=fields;
818
 
 
819
 
  /*
820
 
    The last EOF packet is either a 254 (0xFE) character followed by 1-7 status bytes.
821
 
 
822
 
    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())
824
 
  */
825
 
 
826
 
  while (*(cp=net->read_pos) != DRIZZLE_PROTOCOL_NO_MORE_DATA || pkt_len >= 8)
827
 
  {
828
 
    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))))
834
 
    {
835
 
      free_rows(result);
836
 
      set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
837
 
      return(0);
838
 
    }
839
 
    *prev_ptr=cur;
840
 
    prev_ptr= &cur->next;
841
 
    to= (char*) (cur->data+fields+1);
842
 
    end_to=to+pkt_len-1;
843
 
    for (field=0 ; field < fields ; field++)
844
 
    {
845
 
      if ((len= net_field_length(&cp)) == NULL_LENGTH)
846
 
      {            /* null field */
847
 
        cur->data[field] = 0;
848
 
      }
849
 
      else
850
 
      {
851
 
        cur->data[field] = to;
852
 
        if (len > (uint32_t) (end_to - to))
853
 
        {
854
 
          free_rows(result);
855
 
          set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
856
 
          return(0);
857
 
        }
858
 
        memcpy(to, cp, len);
859
 
        to[len]=0;
860
 
        to+=len+1;
861
 
        cp+=len;
862
 
        if (DRIZZLE_FIELDs)
863
 
        {
864
 
          if (DRIZZLE_FIELDs[field].max_length < len)
865
 
            DRIZZLE_FIELDs[field].max_length=len;
866
 
        }
867
 
      }
868
 
    }
869
 
    cur->data[field]=to;      /* End of last field */
870
 
    if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
871
 
    {
872
 
      free_rows(result);
873
 
      return(0);
874
 
    }
875
 
  }
876
 
  *prev_ptr=0;          /* last pointer is null */
877
 
  if (pkt_len > 1)        /* DRIZZLE 4.1 protocol */
878
 
  {
879
 
    drizzle->warning_count= uint2korr(cp+1);
880
 
    drizzle->server_status= uint2korr(cp+3);
881
 
  }
882
 
  return(result);
883
 
}
884
 
 
885
 
/*
886
 
  Read one row. Uses packet buffer as storage for fields.
887
 
  When next packet is read, the previous field values are destroyed
888
 
*/
889
 
 
890
 
 
891
 
static int32_t
892
 
read_one_row(DRIZZLE *drizzle, uint32_t fields, DRIZZLE_ROW row, uint32_t *lengths)
893
 
{
894
 
  uint field;
895
 
  uint32_t pkt_len,len;
896
 
  uchar *pos, *prev_pos, *end_pos;
897
 
  NET *net= &drizzle->net;
898
 
 
899
 
  if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
900
 
    return -1;
901
 
  if (pkt_len <= 8 && net->read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
902
 
  {
903
 
    if (pkt_len > 1)        /* DRIZZLE 4.1 protocol */
904
 
    {
905
 
      drizzle->warning_count= uint2korr(net->read_pos+1);
906
 
      drizzle->server_status= uint2korr(net->read_pos+3);
907
 
    }
908
 
    return 1;        /* End of data */
909
 
  }
910
 
  prev_pos= 0;        /* allowed to write at packet[-1] */
911
 
  pos=net->read_pos;
912
 
  end_pos=pos+pkt_len;
913
 
  for (field=0 ; field < fields ; field++)
914
 
  {
915
 
    if ((len= net_field_length(&pos)) == NULL_LENGTH)
916
 
    {            /* null field */
917
 
      row[field] = 0;
918
 
      *lengths++=0;
919
 
    }
920
 
    else
921
 
    {
922
 
      if (len > (uint32_t) (end_pos - pos))
923
 
      {
924
 
        set_drizzle_error(drizzle, CR_UNKNOWN_ERROR, unknown_sqlstate);
925
 
        return -1;
926
 
      }
927
 
      row[field] = (char*) pos;
928
 
      pos+=len;
929
 
      *lengths++=len;
930
 
    }
931
 
    if (prev_pos)
932
 
      *prev_pos=0;        /* Terminate prev field */
933
 
    prev_pos=pos;
934
 
  }
935
 
  row[field]=(char*) prev_pos+1;    /* End of last field */
936
 
  *prev_pos=0;          /* Terminate last field */
937
 
  return 0;
938
 
}
939
 
 
940
 
 
941
 
/****************************************************************************
942
 
  Init DRIZZLE structure or allocate one
943
 
****************************************************************************/
944
 
 
945
 
DRIZZLE *
946
 
drizzle_create(DRIZZLE *ptr)
947
 
{
948
 
 
949
 
  if (!drizzle_client_init)
950
 
  {
951
 
    drizzle_client_init=true;
952
 
    org_my_init_done=my_init_done;
953
 
 
954
 
    /* Will init threads */
955
 
    if (my_init())
956
 
      return NULL;
957
 
 
958
 
    if (!drizzle_port)
959
 
    {
960
 
      drizzle_port = DRIZZLE_PORT;
961
 
      {
962
 
        struct servent *serv_ptr;
963
 
        char *env;
964
 
 
965
 
        /*
966
 
          if builder specifically requested a default port, use that
967
 
          (even if it coincides with our factory default).
968
 
          only if they didn't do we check /etc/services (and, failing
969
 
          on that, fall back to the factory default of 4427).
970
 
          either default can be overridden by the environment variable
971
 
          DRIZZLE_TCP_PORT, which in turn can be overridden with command
972
 
          line options.
973
 
        */
974
 
 
975
 
#if DRIZZLE_PORT_DEFAULT == 0
976
 
        if ((serv_ptr = getservbyname("drizzle", "tcp")))
977
 
          drizzle_port = (uint) ntohs((ushort) serv_ptr->s_port);
978
 
#endif
979
 
        if ((env = getenv("DRIZZLE_TCP_PORT")))
980
 
          drizzle_port =(uint) atoi(env);
981
 
      }
982
 
    }
983
 
#if defined(SIGPIPE)
984
 
    (void) signal(SIGPIPE, SIG_IGN);
985
 
#endif
986
 
  }
987
 
  else
988
 
    /* Init if new thread */
989
 
    if (my_thread_init())
990
 
      return NULL;
991
 
 
992
 
  if (ptr == NULL)
993
 
  {
994
 
    ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
995
 
 
996
 
    if (ptr == NULL)
997
 
    {
998
 
      set_drizzle_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
999
 
      return 0;
1000
 
    }
1001
 
    memset(ptr, 0, sizeof(DRIZZLE));
1002
 
    ptr->free_me=1;
1003
 
  }
1004
 
  else
1005
 
  {
1006
 
    memset(ptr, 0, sizeof(DRIZZLE)); 
1007
 
  }
1008
 
 
1009
 
  ptr->options.connect_timeout= CONNECT_TIMEOUT;
1010
 
  ptr->charset=default_client_charset_info;
1011
 
  strcpy(ptr->net.sqlstate, not_error_sqlstate);
1012
 
 
1013
 
  /*
1014
 
    Only enable LOAD DATA INFILE by default if configured with
1015
 
    --enable-local-infile
1016
 
  */
1017
 
 
1018
 
#if defined(ENABLED_LOCAL_INFILE) && !defined(DRIZZLE_SERVER)
1019
 
  ptr->options.client_flag|= CLIENT_LOCAL_FILES;
1020
 
#endif
1021
 
 
1022
 
  ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION;
1023
 
  ptr->options.report_data_truncation= true;  /* default */
1024
 
 
1025
 
  /*
1026
 
    By default we don't reconnect because it could silently corrupt data (after
1027
 
    reconnection you potentially lose table locks, user variables, session
1028
 
    variables (transactions but they are specifically dealt with in
1029
 
    drizzle_reconnect()).
1030
 
    This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
1031
 
    How this change impacts existing apps:
1032
 
    - existing apps which relyed on the default will see a behaviour change;
1033
 
    they will have to set reconnect=1 after drizzle_connect().
1034
 
    - existing apps which explicitely asked for reconnection (the only way they
1035
 
    could do it was by setting drizzle.reconnect to 1 after drizzle_connect())
1036
 
    will not see a behaviour change.
1037
 
    - existing apps which explicitely asked for no reconnection
1038
 
    (drizzle.reconnect=0) will not see a behaviour change.
1039
 
  */
1040
 
  ptr->reconnect= 0;
1041
 
 
1042
 
  return ptr;
1043
 
}
1044
 
 
1045
 
 
1046
 
/*
1047
 
  Free all memory and resources used by the client library
1048
 
 
1049
 
  NOTES
1050
 
    When calling this there should not be any other threads using
1051
 
    the library.
1052
 
 
1053
 
    To make things simpler when used with windows dll's (which calls this
1054
 
    function automaticly), it's safe to call this function multiple times.
1055
 
*/
1056
 
 
1057
 
 
1058
 
void drizzle_server_end()
1059
 
{
1060
 
  if (!drizzle_client_init)
1061
 
    return;
1062
 
 
1063
 
  vio_end();
1064
 
 
1065
 
  /* If library called my_init(), free memory allocated by it */
1066
 
  if (!org_my_init_done)
1067
 
  {
1068
 
    my_end(0);
1069
 
  }
1070
 
  else
1071
 
  {
1072
 
    free_charsets();
1073
 
    drizzle_thread_end();
1074
 
  }
1075
 
 
1076
 
  drizzle_client_init= org_my_init_done= 0;
1077
 
#ifdef EMBEDDED_SERVER
1078
 
  if (stderror_file)
1079
 
  {
1080
 
    fclose(stderror_file);
1081
 
    stderror_file= 0;
1082
 
  }
1083
 
#endif
1084
 
}
1085
 
 
1086
 
 
1087
 
/*
1088
 
  Fill in SSL part of DRIZZLE structure and set 'use_ssl' flag.
1089
 
  NB! Errors are not reported until you do drizzle_connect.
1090
 
*/
1091
 
 
1092
 
#define strdup_if_not_null(A) (A) == 0 ? 0 : my_strdup((A),MYF(MY_WME))
1093
 
 
1094
 
/*
1095
 
  Note that the drizzle argument must be initialized with drizzle_init()
1096
 
  before calling drizzle_connect !
1097
 
*/
1098
 
 
1099
 
static bool cli_read_query_result(DRIZZLE *drizzle);
1100
 
static DRIZZLE_RES *cli_use_result(DRIZZLE *drizzle);
1101
 
 
1102
 
static DRIZZLE_METHODS client_methods=
1103
 
{
1104
 
  cli_read_query_result,                       /* read_query_result */
1105
 
  cli_advanced_command,                        /* advanced_command */
1106
 
  cli_read_rows,                               /* read_rows */
1107
 
  cli_use_result,                              /* use_result */
1108
 
  cli_fetch_lengths,                           /* fetch_lengths */
1109
 
  cli_flush_use_result,                         /* flush_use_result */
1110
 
#ifndef DRIZZLE_SERVER
1111
 
  cli_list_fields,                            /* list_fields */
1112
 
  cli_unbuffered_fetch,                        /* unbuffered_fetch */
1113
 
  cli_read_statistics,                         /* read_statistics */
1114
 
  cli_read_query_result,                       /* next_result */
1115
 
  cli_read_change_user_result,                 /* read_change_user_result */
1116
 
#else
1117
 
  0,0,0,0,0
1118
 
#endif
1119
 
};
1120
 
 
1121
 
C_MODE_START
1122
 
int drizzle_init_character_set(DRIZZLE *drizzle)
1123
 
{
1124
 
  const char *default_collation_name;
1125
 
 
1126
 
  /* Set character set */
1127
 
  if (!drizzle->options.charset_name)
1128
 
  {
1129
 
    default_collation_name= DRIZZLE_DEFAULT_COLLATION_NAME;
1130
 
    if (!(drizzle->options.charset_name=
1131
 
       my_strdup(DRIZZLE_DEFAULT_CHARSET_NAME,MYF(MY_WME))))
1132
 
    return 1;
1133
 
  }
1134
 
  else
1135
 
    default_collation_name= NULL;
1136
 
 
1137
 
  {
1138
 
    const char *save= charsets_dir;
1139
 
    if (drizzle->options.charset_dir)
1140
 
      charsets_dir=drizzle->options.charset_dir;
1141
 
    drizzle->charset=get_charset_by_csname(drizzle->options.charset_name,
1142
 
                                         MY_CS_PRIMARY, MYF(MY_WME));
1143
 
    if (drizzle->charset && default_collation_name)
1144
 
    {
1145
 
      const CHARSET_INFO *collation;
1146
 
      if ((collation=
1147
 
           get_charset_by_name(default_collation_name, MYF(MY_WME))))
1148
 
      {
1149
 
        if (!my_charset_same(drizzle->charset, collation))
1150
 
        {
1151
 
          my_printf_error(ER_UNKNOWN_ERROR,
1152
 
                         "COLLATION %s is not valid for CHARACTER SET %s",
1153
 
                         MYF(0),
1154
 
                         default_collation_name, drizzle->options.charset_name);
1155
 
          drizzle->charset= NULL;
1156
 
        }
1157
 
        else
1158
 
        {
1159
 
          drizzle->charset= collation;
1160
 
        }
1161
 
      }
1162
 
      else
1163
 
        drizzle->charset= NULL;
1164
 
    }
1165
 
    charsets_dir= save;
1166
 
  }
1167
 
 
1168
 
  if (!drizzle->charset)
1169
 
  {
1170
 
    if (drizzle->options.charset_dir)
1171
 
      set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
1172
 
                               ER(CR_CANT_READ_CHARSET),
1173
 
                               drizzle->options.charset_name,
1174
 
                               drizzle->options.charset_dir);
1175
 
    else
1176
 
    {
1177
 
      char cs_dir_name[FN_REFLEN];
1178
 
      get_charsets_dir(cs_dir_name);
1179
 
      set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
1180
 
                               ER(CR_CANT_READ_CHARSET),
1181
 
                               drizzle->options.charset_name,
1182
 
                               cs_dir_name);
1183
 
    }
1184
 
    return 1;
1185
 
  }
1186
 
  return 0;
1187
 
}
1188
 
C_MODE_END
1189
 
 
1190
 
 
1191
 
DRIZZLE *
1192
 
CLI_DRIZZLE_CONNECT(DRIZZLE *drizzle,const char *host, const char *user,
1193
 
                       const char *passwd, const char *db,
1194
 
                       uint32_t port, const char *unix_socket, uint32_t client_flag)
1195
 
{
1196
 
  char          buff[NAME_LEN+USERNAME_LENGTH+100];
1197
 
  char          *end,*host_info=NULL;
1198
 
  uint32_t         pkt_length;
1199
 
  NET           *net= &drizzle->net;
1200
 
  init_sigpipe_variables
1201
 
 
1202
 
  /* Don't give sigpipe errors if the client doesn't want them */
1203
 
  set_sigpipe(drizzle);
1204
 
  drizzle->methods= &client_methods;
1205
 
  net->vio = 0;        /* If something goes wrong */
1206
 
  drizzle->client_flag=0;      /* For handshake */
1207
 
 
1208
 
  /* use default options */
1209
 
  if (drizzle->options.my_cnf_file || drizzle->options.my_cnf_group)
1210
 
  {
1211
 
    drizzle_read_default_options(&drizzle->options,
1212
 
             (drizzle->options.my_cnf_file ?
1213
 
        drizzle->options.my_cnf_file : "my"),
1214
 
             drizzle->options.my_cnf_group);
1215
 
    my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1216
 
    my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1217
 
    drizzle->options.my_cnf_file=drizzle->options.my_cnf_group=0;
1218
 
  }
1219
 
 
1220
 
  /* Some empty-string-tests are done because of ODBC */
1221
 
  if (!host || !host[0])
1222
 
    host=drizzle->options.host;
1223
 
  if (!user || !user[0])
1224
 
  {
1225
 
    user=drizzle->options.user;
1226
 
    if (!user)
1227
 
      user= "";
1228
 
  }
1229
 
  if (!passwd)
1230
 
  {
1231
 
    passwd=drizzle->options.password;
1232
 
    if (!passwd)
1233
 
      passwd= "";
1234
 
  }
1235
 
  if (!db || !db[0])
1236
 
    db=drizzle->options.db;
1237
 
  if (!port)
1238
 
    port=drizzle->options.port;
1239
 
  if (!unix_socket)
1240
 
    unix_socket=drizzle->options.unix_socket;
1241
 
 
1242
 
  drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
1243
 
 
1244
 
  /*
1245
 
    Part 0: Grab a socket and connect it to the server
1246
 
  */
1247
 
  if (!net->vio &&
1248
 
      (!drizzle->options.protocol ||
1249
 
       drizzle->options.protocol == DRIZZLE_PROTOCOL_TCP))
1250
 
  {
1251
 
    struct addrinfo *res_lst, hints, *t_res;
1252
 
    int gai_errno;
1253
 
    char port_buf[NI_MAXSERV];
1254
 
 
1255
 
    unix_socket=0;        /* This is not used */
1256
 
 
1257
 
    if (!port)
1258
 
      port= drizzle_port;
1259
 
 
1260
 
    if (!host)
1261
 
      host= LOCAL_HOST;
1262
 
 
1263
 
    snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
1264
 
 
1265
 
    memset(&hints, 0, sizeof(hints));
1266
 
    hints.ai_socktype= SOCK_STREAM;
1267
 
 
1268
 
    snprintf(port_buf, NI_MAXSERV, "%d", port);
1269
 
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
1270
 
 
1271
 
    if (gai_errno != 0)
1272
 
    {
1273
 
      set_drizzle_extended_error(drizzle, CR_UNKNOWN_HOST, unknown_sqlstate,
1274
 
                               ER(CR_UNKNOWN_HOST), host, errno);
1275
 
 
1276
 
      goto error;
1277
 
    }
1278
 
 
1279
 
    for (t_res= res_lst; t_res != NULL; t_res= t_res->ai_next)
1280
 
    {
1281
 
      int sock= socket(t_res->ai_family, t_res->ai_socktype,
1282
 
                       t_res->ai_protocol);
1283
 
      if (sock == SOCKET_ERROR)
1284
 
        continue;
1285
 
 
1286
 
      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
1287
 
      if (! net->vio )
1288
 
      {
1289
 
        close(sock);
1290
 
        continue;
1291
 
      }
1292
 
 
1293
 
      if (connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
1294
 
      {
1295
 
        vio_delete(net->vio);
1296
 
        net->vio= 0;
1297
 
        continue;
1298
 
      }
1299
 
      break;
1300
 
    }
1301
 
 
1302
 
    freeaddrinfo(res_lst);
1303
 
  }
1304
 
 
1305
 
  if (!net->vio)
1306
 
  {
1307
 
    set_drizzle_extended_error(drizzle, CR_CONN_HOST_ERROR, unknown_sqlstate,
1308
 
                               ER(CR_CONN_HOST_ERROR), host, socket_errno);
1309
 
    goto error;
1310
 
  }
1311
 
 
1312
 
  if (my_net_init(net, net->vio))
1313
 
  {
1314
 
    vio_delete(net->vio);
1315
 
    net->vio = 0;
1316
 
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1317
 
    goto error;
1318
 
  }
1319
 
  vio_keepalive(net->vio,true);
1320
 
 
1321
 
  /* If user set read_timeout, let it override the default */
1322
 
  if (drizzle->options.read_timeout)
1323
 
    my_net_set_read_timeout(net, drizzle->options.read_timeout);
1324
 
 
1325
 
  /* If user set write_timeout, let it override the default */
1326
 
  if (drizzle->options.write_timeout)
1327
 
    my_net_set_write_timeout(net, drizzle->options.write_timeout);
1328
 
 
1329
 
  if (drizzle->options.max_allowed_packet)
1330
 
    net->max_packet_size= drizzle->options.max_allowed_packet;
1331
 
 
1332
 
  /* Get version info */
1333
 
  drizzle->protocol_version= PROTOCOL_VERSION;  /* Assume this */
1334
 
  if (drizzle->options.connect_timeout &&
1335
 
      vio_poll_read(net->vio, drizzle->options.connect_timeout))
1336
 
  {
1337
 
    set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1338
 
                             ER(CR_SERVER_LOST_EXTENDED),
1339
 
                             "waiting for initial communication packet",
1340
 
                             errno);
1341
 
    goto error;
1342
 
  }
1343
 
 
1344
 
  /*
1345
 
    Part 1: Connection established, read and parse first packet
1346
 
  */
1347
 
 
1348
 
  if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
1349
 
  {
1350
 
    if (drizzle->net.last_errno == CR_SERVER_LOST)
1351
 
      set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1352
 
                               ER(CR_SERVER_LOST_EXTENDED),
1353
 
                               "reading initial communication packet",
1354
 
                               errno);
1355
 
    goto error;
1356
 
  }
1357
 
  /* Check if version of protocol matches current one */
1358
 
 
1359
 
  drizzle->protocol_version= net->read_pos[0];
1360
 
  if (drizzle->protocol_version != PROTOCOL_VERSION)
1361
 
  {
1362
 
    set_drizzle_extended_error(drizzle, CR_VERSION_ERROR, unknown_sqlstate,
1363
 
                             ER(CR_VERSION_ERROR), drizzle->protocol_version,
1364
 
                             PROTOCOL_VERSION);
1365
 
    goto error;
1366
 
  }
1367
 
  end=strend((char*) net->read_pos+1);
1368
 
  drizzle->thread_id=uint4korr(end+1);
1369
 
  end+=5;
1370
 
  /*
1371
 
    Scramble is split into two parts because old clients does not understand
1372
 
    long scrambles; here goes the first part.
1373
 
  */
1374
 
  strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
1375
 
  end+= SCRAMBLE_LENGTH_323+1;
1376
 
 
1377
 
  if (pkt_length >= (uint) (end+1 - (char*) net->read_pos))
1378
 
    drizzle->server_capabilities=uint2korr(end);
1379
 
  if (pkt_length >= (uint) (end+18 - (char*) net->read_pos))
1380
 
  {
1381
 
    /* New protocol with 16 bytes to describe server characteristics */
1382
 
    drizzle->server_language=end[2];
1383
 
    drizzle->server_status=uint2korr(end+3);
1384
 
  }
1385
 
  end+= 18;
1386
 
  if (pkt_length >= (uint) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
1387
 
                           (char *) net->read_pos))
1388
 
    strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
1389
 
            SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
1390
 
  else
1391
 
    drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
1392
 
 
1393
 
  if (drizzle->options.secure_auth && passwd[0] &&
1394
 
      !(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
1395
 
  {
1396
 
    set_drizzle_error(drizzle, CR_SECURE_AUTH, unknown_sqlstate);
1397
 
    goto error;
1398
 
  }
1399
 
 
1400
 
  if (drizzle_init_character_set(drizzle))
1401
 
    goto error;
1402
 
 
1403
 
  /* Save connection information */
1404
 
  if (!my_multi_malloc(MYF(0),
1405
 
           &drizzle->host_info, (uint) strlen(host_info)+1,
1406
 
           &drizzle->host,      (uint) strlen(host)+1,
1407
 
           &drizzle->unix_socket,unix_socket ?
1408
 
           (uint) strlen(unix_socket)+1 : (uint) 1,
1409
 
           &drizzle->server_version,
1410
 
           (uint) (end - (char*) net->read_pos),
1411
 
           NullS) ||
1412
 
      !(drizzle->user=my_strdup(user,MYF(0))) ||
1413
 
      !(drizzle->passwd=my_strdup(passwd,MYF(0))))
1414
 
  {
1415
 
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1416
 
    goto error;
1417
 
  }
1418
 
  strcpy(drizzle->host_info,host_info);
1419
 
  strcpy(drizzle->host,host);
1420
 
  if (unix_socket)
1421
 
    strcpy(drizzle->unix_socket,unix_socket);
1422
 
  else
1423
 
    drizzle->unix_socket=0;
1424
 
  strcpy(drizzle->server_version,(char*) net->read_pos+1);
1425
 
  drizzle->port=port;
1426
 
 
1427
 
  /*
1428
 
    Part 2: format and send client info to the server for access check
1429
 
  */
1430
 
 
1431
 
  client_flag|=drizzle->options.client_flag;
1432
 
  client_flag|=CLIENT_CAPABILITIES;
1433
 
  if (client_flag & CLIENT_MULTI_STATEMENTS)
1434
 
    client_flag|= CLIENT_MULTI_RESULTS;
1435
 
 
1436
 
  if (db)
1437
 
    client_flag|=CLIENT_CONNECT_WITH_DB;
1438
 
 
1439
 
  /* Remove options that server doesn't support */
1440
 
  client_flag= ((client_flag &
1441
 
     ~(CLIENT_COMPRESS | CLIENT_SSL)) |
1442
 
    (client_flag & drizzle->server_capabilities));
1443
 
  client_flag&= ~CLIENT_COMPRESS;
1444
 
 
1445
 
  int4store(buff, client_flag);
1446
 
  int4store(buff+4, net->max_packet_size);
1447
 
  buff[8]= (char) drizzle->charset->number;
1448
 
  memset(buff+9, 0, 32-9);
1449
 
  end= buff+32;
1450
 
 
1451
 
  drizzle->client_flag=client_flag;
1452
 
 
1453
 
  /* This needs to be changed as it's not useful with big packets */
1454
 
  if (user && user[0])
1455
 
    strncpy(end,user,USERNAME_LENGTH);          /* Max user name */
1456
 
  else
1457
 
    read_user_name((char*) end);
1458
 
 
1459
 
  /* We have to handle different version of handshake here */
1460
 
  end= strend(end) + 1;
1461
 
  if (passwd[0])
1462
 
  {
1463
 
    {
1464
 
      *end++= SCRAMBLE_LENGTH;
1465
 
      memset(end, 0, SCRAMBLE_LENGTH-1);
1466
 
      memcpy(end, passwd, strlen(passwd));
1467
 
      end+= SCRAMBLE_LENGTH;
1468
 
    }
1469
 
  }
1470
 
  else
1471
 
    *end++= '\0';                               /* empty password */
1472
 
 
1473
 
  /* Add database if needed */
1474
 
  if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
1475
 
  {
1476
 
    end= strncpy(end, db, NAME_LEN) + NAME_LEN + 1;
1477
 
    drizzle->db= my_strdup(db,MYF(MY_WME));
1478
 
    db= 0;
1479
 
  }
1480
 
  /* Write authentication package */
1481
 
  if (my_net_write(net, (uchar*) buff, (size_t) (end-buff)) || net_flush(net))
1482
 
  {
1483
 
    set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1484
 
                             ER(CR_SERVER_LOST_EXTENDED),
1485
 
                             "sending authentication information",
1486
 
                             errno);
1487
 
    goto error;
1488
 
  }
1489
 
 
1490
 
  /*
1491
 
    Part 3: Authorization data's been sent. Now server can reply with
1492
 
    OK-packet, or re-request scrambled password.
1493
 
  */
1494
 
 
1495
 
  if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
1496
 
  {
1497
 
    if (drizzle->net.last_errno == CR_SERVER_LOST)
1498
 
      set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1499
 
                               ER(CR_SERVER_LOST_EXTENDED),
1500
 
                               "reading authorization packet",
1501
 
                               errno);
1502
 
    goto error;
1503
 
  }
1504
 
 
1505
 
  if (client_flag & CLIENT_COMPRESS)    /* We will use compression */
1506
 
    net->compress=1;
1507
 
 
1508
 
 
1509
 
  if (db && drizzle_select_db(drizzle, db))
1510
 
  {
1511
 
    if (drizzle->net.last_errno == CR_SERVER_LOST)
1512
 
        set_drizzle_extended_error(drizzle, CR_SERVER_LOST, unknown_sqlstate,
1513
 
                                 ER(CR_SERVER_LOST_EXTENDED),
1514
 
                                 "Setting intital database",
1515
 
                                 errno);
1516
 
    goto error;
1517
 
  }
1518
 
 
1519
 
  if (drizzle->options.init_commands)
1520
 
  {
1521
 
    DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
1522
 
    char **ptr= (char**)init_commands->buffer;
1523
 
    char **end_command= ptr + init_commands->elements;
1524
 
 
1525
 
    bool reconnect=drizzle->reconnect;
1526
 
    drizzle->reconnect=0;
1527
 
 
1528
 
    for (; ptr < end_command; ptr++)
1529
 
    {
1530
 
      DRIZZLE_RES *res;
1531
 
      if (drizzle_real_query(drizzle,*ptr, (uint32_t) strlen(*ptr)))
1532
 
  goto error;
1533
 
      if (drizzle->fields)
1534
 
      {
1535
 
  if (!(res= cli_use_result(drizzle)))
1536
 
    goto error;
1537
 
  drizzle_free_result(res);
1538
 
      }
1539
 
    }
1540
 
    drizzle->reconnect=reconnect;
1541
 
  }
1542
 
 
1543
 
  reset_sigpipe(drizzle);
1544
 
  return(drizzle);
1545
 
 
1546
 
error:
1547
 
  reset_sigpipe(drizzle);
1548
 
  {
1549
 
    /* Free alloced memory */
1550
 
    end_server(drizzle);
1551
 
    drizzle_close_free(drizzle);
1552
 
    if (!(((uint32_t) client_flag) & CLIENT_REMEMBER_OPTIONS))
1553
 
      drizzle_close_free_options(drizzle);
1554
 
  }
1555
 
  return(0);
1556
 
}
1557
 
 
1558
 
 
1559
 
bool drizzle_reconnect(DRIZZLE *drizzle)
1560
 
{
1561
 
  DRIZZLE tmp_drizzle;
1562
 
  assert(drizzle);
1563
 
 
1564
 
  if (!drizzle->reconnect ||
1565
 
      (drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
1566
 
  {
1567
 
    /* Allow reconnect next time */
1568
 
    drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
1569
 
    set_drizzle_error(drizzle, CR_SERVER_GONE_ERROR, unknown_sqlstate);
1570
 
    return(1);
1571
 
  }
1572
 
  drizzle_create(&tmp_drizzle);
1573
 
  tmp_drizzle.options= drizzle->options;
1574
 
  tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
1575
 
 
1576
 
  if (!drizzle_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
1577
 
        drizzle->db, drizzle->port, drizzle->unix_socket,
1578
 
        drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
1579
 
  {
1580
 
    drizzle->net.last_errno= tmp_drizzle.net.last_errno;
1581
 
    strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
1582
 
    strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
1583
 
    return(1);
1584
 
  }
1585
 
  if (drizzle_set_character_set(&tmp_drizzle, drizzle->charset->csname))
1586
 
  {
1587
 
    memset(&tmp_drizzle.options, 0, sizeof(tmp_drizzle.options));
1588
 
    drizzle_close(&tmp_drizzle);
1589
 
    drizzle->net.last_errno= tmp_drizzle.net.last_errno;
1590
 
    strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
1591
 
    strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
1592
 
    return(1);
1593
 
  }
1594
 
 
1595
 
  tmp_drizzle.reconnect= 1;
1596
 
  tmp_drizzle.free_me= drizzle->free_me;
1597
 
 
1598
 
  /* Don't free options as these are now used in tmp_drizzle */
1599
 
  memset(&drizzle->options, 0, sizeof(drizzle->options));
1600
 
  drizzle->free_me=0;
1601
 
  drizzle_close(drizzle);
1602
 
  *drizzle=tmp_drizzle;
1603
 
  net_clear(&drizzle->net, 1);
1604
 
  drizzle->affected_rows= ~(uint64_t) 0;
1605
 
  return(0);
1606
 
}
1607
 
 
1608
 
 
1609
 
/**************************************************************************
1610
 
  Set current database
1611
 
**************************************************************************/
1612
 
 
1613
 
int
1614
 
drizzle_select_db(DRIZZLE *drizzle, const char *db)
1615
 
{
1616
 
  int error;
1617
 
 
1618
 
  if ((error=simple_command(drizzle,COM_INIT_DB, (const uchar*) db,
1619
 
                            (uint32_t) strlen(db),0)))
1620
 
    return(error);
1621
 
  my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
1622
 
  drizzle->db=my_strdup(db,MYF(MY_WME));
1623
 
  return(0);
1624
 
}
1625
 
 
1626
 
 
1627
 
/*************************************************************************
1628
 
  Send a QUIT to the server and close the connection
1629
 
  If handle is alloced by DRIZZLE connect free it.
1630
 
*************************************************************************/
1631
 
 
1632
 
static void drizzle_close_free_options(DRIZZLE *drizzle)
1633
 
{
1634
 
  my_free(drizzle->options.user,MYF(MY_ALLOW_ZERO_PTR));
1635
 
  my_free(drizzle->options.host,MYF(MY_ALLOW_ZERO_PTR));
1636
 
  my_free(drizzle->options.password,MYF(MY_ALLOW_ZERO_PTR));
1637
 
  my_free(drizzle->options.unix_socket,MYF(MY_ALLOW_ZERO_PTR));
1638
 
  my_free(drizzle->options.db,MYF(MY_ALLOW_ZERO_PTR));
1639
 
  my_free(drizzle->options.my_cnf_file,MYF(MY_ALLOW_ZERO_PTR));
1640
 
  my_free(drizzle->options.my_cnf_group,MYF(MY_ALLOW_ZERO_PTR));
1641
 
  my_free(drizzle->options.charset_dir,MYF(MY_ALLOW_ZERO_PTR));
1642
 
  my_free(drizzle->options.charset_name,MYF(MY_ALLOW_ZERO_PTR));
1643
 
  my_free(drizzle->options.client_ip,MYF(MY_ALLOW_ZERO_PTR));
1644
 
  if (drizzle->options.init_commands)
1645
 
  {
1646
 
    DYNAMIC_ARRAY *init_commands= drizzle->options.init_commands;
1647
 
    char **ptr= (char**)init_commands->buffer;
1648
 
    char **end= ptr + init_commands->elements;
1649
 
    for (; ptr<end; ptr++)
1650
 
      my_free(*ptr,MYF(MY_WME));
1651
 
    delete_dynamic(init_commands);
1652
 
    my_free((char*)init_commands,MYF(MY_WME));
1653
 
  }
1654
 
  memset(&drizzle->options, 0, sizeof(drizzle->options));
1655
 
  return;
1656
 
}
1657
 
 
1658
 
 
1659
 
static void drizzle_close_free(DRIZZLE *drizzle)
1660
 
{
1661
 
  my_free((uchar*) drizzle->host_info,MYF(MY_ALLOW_ZERO_PTR));
1662
 
  my_free(drizzle->user,MYF(MY_ALLOW_ZERO_PTR));
1663
 
  my_free(drizzle->passwd,MYF(MY_ALLOW_ZERO_PTR));
1664
 
  my_free(drizzle->db,MYF(MY_ALLOW_ZERO_PTR));
1665
 
  my_free(drizzle->info_buffer,MYF(MY_ALLOW_ZERO_PTR));
1666
 
  drizzle->info_buffer= 0;
1667
 
 
1668
 
  /* Clear pointers for better safety */
1669
 
  drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
1670
 
}
1671
 
 
1672
 
 
1673
 
void drizzle_close(DRIZZLE *drizzle)
1674
 
{
1675
 
  if (drizzle)          /* Some simple safety */
1676
 
  {
1677
 
    /* If connection is still up, send a QUIT message */
1678
 
    if (drizzle->net.vio != 0)
1679
 
    {
1680
 
      free_old_query(drizzle);
1681
 
      drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
1682
 
      drizzle->reconnect=0;
1683
 
      simple_command(drizzle,COM_QUIT,(uchar*) 0,0,1);
1684
 
      end_server(drizzle);      /* Sets drizzle->net.vio= 0 */
1685
 
    }
1686
 
    drizzle_close_free_options(drizzle);
1687
 
    drizzle_close_free(drizzle);
1688
 
    if (drizzle->free_me)
1689
 
      my_free((uchar*) drizzle,MYF(0));
1690
 
  }
1691
 
  return;
1692
 
}
1693
 
 
1694
 
 
1695
 
static bool cli_read_query_result(DRIZZLE *drizzle)
1696
 
{
1697
 
  uchar *pos;
1698
 
  uint32_t field_count;
1699
 
  DRIZZLE_DATA *fields;
1700
 
  uint32_t length;
1701
 
 
1702
 
  if ((length = cli_safe_read(drizzle)) == packet_error)
1703
 
    return(1);
1704
 
  free_old_query(drizzle);    /* Free old result */
1705
 
#ifdef DRIZZLE_CLIENT      /* Avoid warn of unused labels*/
1706
 
get_info:
1707
 
#endif
1708
 
  pos=(uchar*) drizzle->net.read_pos;
1709
 
  if ((field_count= net_field_length(&pos)) == 0)
1710
 
  {
1711
 
    drizzle->affected_rows= net_field_length_ll(&pos);
1712
 
    drizzle->insert_id=    net_field_length_ll(&pos);
1713
 
 
1714
 
    drizzle->server_status= uint2korr(pos); pos+=2;
1715
 
    drizzle->warning_count= uint2korr(pos); pos+=2;
1716
 
 
1717
 
    if (pos < drizzle->net.read_pos+length && net_field_length(&pos))
1718
 
      drizzle->info=(char*) pos;
1719
 
    return(0);
1720
 
  }
1721
 
#ifdef DRIZZLE_CLIENT
1722
 
  if (field_count == NULL_LENGTH)    /* LOAD DATA LOCAL INFILE */
1723
 
  {
1724
 
    int error;
1725
 
 
1726
 
    if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES))
1727
 
    {
1728
 
      set_drizzle_error(drizzle, CR_MALFORMED_PACKET, unknown_sqlstate);
1729
 
      return(1);
1730
 
    }  
1731
 
 
1732
 
    error= handle_local_infile(drizzle,(char*) pos);
1733
 
    if ((length= cli_safe_read(drizzle)) == packet_error || error)
1734
 
      return(1);
1735
 
    goto get_info;        /* Get info packet */
1736
 
  }
1737
 
#endif
1738
 
  if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
1739
 
    drizzle->server_status|= SERVER_STATUS_IN_TRANS;
1740
 
 
1741
 
  if (!(fields=cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, 7)))
1742
 
    return(1);
1743
 
  if (!(drizzle->fields= unpack_fields(fields,&drizzle->field_alloc,
1744
 
            (uint) field_count, 0)))
1745
 
    return(1);
1746
 
  drizzle->status= DRIZZLE_STATUS_GET_RESULT;
1747
 
  drizzle->field_count= (uint) field_count;
1748
 
  return(0);
1749
 
}
1750
 
 
1751
 
 
1752
 
/*
1753
 
  Send the query and return so we can do something else.
1754
 
  Needs to be followed by drizzle_read_query_result() when we want to
1755
 
  finish processing it.
1756
 
*/
1757
 
 
1758
 
int32_t
1759
 
drizzle_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
1760
 
{
1761
 
  return(simple_command(drizzle, COM_QUERY, (uchar*) query, length, 1));
1762
 
}
1763
 
 
1764
 
 
1765
 
int32_t
1766
 
drizzle_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
1767
 
{
1768
 
  if (drizzle_send_query(drizzle,query,length))
1769
 
    return(1);
1770
 
  return((int) (*drizzle->methods->read_query_result)(drizzle));
1771
 
}
1772
 
 
1773
 
 
1774
 
/**************************************************************************
1775
 
  Alloc result struct for buffered results. All rows are read to buffer.
1776
 
  drizzle_data_seek may be used.
1777
 
**************************************************************************/
1778
 
 
1779
 
DRIZZLE_RES * drizzle_store_result(DRIZZLE *drizzle)
1780
 
{
1781
 
  DRIZZLE_RES *result;
1782
 
 
1783
 
  if (!drizzle->fields)
1784
 
    return(0);
1785
 
  if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
1786
 
  {
1787
 
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
1788
 
    return(0);
1789
 
  }
1790
 
  drizzle->status=DRIZZLE_STATUS_READY;    /* server is ready */
1791
 
  if (!(result=(DRIZZLE_RES*) my_malloc((uint) (sizeof(DRIZZLE_RES)+
1792
 
                sizeof(uint32_t) *
1793
 
                drizzle->field_count),
1794
 
              MYF(MY_WME | MY_ZEROFILL))))
1795
 
  {
1796
 
    set_drizzle_error(drizzle, CR_OUT_OF_MEMORY, unknown_sqlstate);
1797
 
    return(0);
1798
 
  }
1799
 
  result->methods= drizzle->methods;
1800
 
  result->eof= 1;        /* Marker for buffered */
1801
 
  result->lengths= (uint32_t*) (result+1);
1802
 
  if (!(result->data=
1803
 
  (*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
1804
 
  {
1805
 
    my_free((uchar*) result,MYF(0));
1806
 
    return(0);
1807
 
  }
1808
 
  drizzle->affected_rows= result->row_count= result->data->rows;
1809
 
  result->data_cursor=  result->data->data;
1810
 
  result->fields=  drizzle->fields;
1811
 
  result->field_alloc=  drizzle->field_alloc;
1812
 
  result->field_count=  drizzle->field_count;
1813
 
  /* The rest of result members is zeroed in malloc */
1814
 
  drizzle->fields=0;        /* fields is now in result */
1815
 
  clear_alloc_root(&drizzle->field_alloc);
1816
 
  /* just in case this was mistakenly called after drizzle_stmt_execute() */
1817
 
  drizzle->unbuffered_fetch_owner= 0;
1818
 
  return(result);        /* Data fetched */
1819
 
}
1820
 
 
1821
 
 
1822
 
/**************************************************************************
1823
 
  Alloc struct for use with unbuffered reads. Data is fetched by domand
1824
 
  when calling to drizzle_fetch_row.
1825
 
  DRIZZLE_DATA_seek is a noop.
1826
 
 
1827
 
  No other queries may be specified with the same DRIZZLE handle.
1828
 
  There shouldn't be much processing per row because DRIZZLE server shouldn't
1829
 
  have to wait for the client (and will not wait more than 30 sec/packet).
1830
 
**************************************************************************/
1831
 
 
1832
 
static DRIZZLE_RES * cli_use_result(DRIZZLE *drizzle)
1833
 
{
1834
 
  DRIZZLE_RES *result;
1835
 
 
1836
 
  if (!drizzle->fields)
1837
 
    return(0);
1838
 
  if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
1839
 
  {
1840
 
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
1841
 
    return(0);
1842
 
  }
1843
 
  if (!(result=(DRIZZLE_RES*) my_malloc(sizeof(*result)+
1844
 
              sizeof(uint32_t)*drizzle->field_count,
1845
 
              MYF(MY_WME | MY_ZEROFILL))))
1846
 
    return(0);
1847
 
  result->lengths=(uint32_t*) (result+1);
1848
 
  result->methods= drizzle->methods;
1849
 
  if (!(result->row=(DRIZZLE_ROW)
1850
 
  my_malloc(sizeof(result->row[0])*(drizzle->field_count+1), MYF(MY_WME))))
1851
 
  {          /* Ptrs: to one row */
1852
 
    my_free((uchar*) result,MYF(0));
1853
 
    return(0);
1854
 
  }
1855
 
  result->fields=  drizzle->fields;
1856
 
  result->field_alloc=  drizzle->field_alloc;
1857
 
  result->field_count=  drizzle->field_count;
1858
 
  result->current_field=0;
1859
 
  result->handle=  drizzle;
1860
 
  result->current_row=  0;
1861
 
  drizzle->fields=0;      /* fields is now in result */
1862
 
  clear_alloc_root(&drizzle->field_alloc);
1863
 
  drizzle->status=DRIZZLE_STATUS_USE_RESULT;
1864
 
  drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
1865
 
  return(result);      /* Data is read to be fetched */
1866
 
}
1867
 
 
1868
 
 
1869
 
/**************************************************************************
1870
 
  Return next row of the query results
1871
 
**************************************************************************/
1872
 
 
1873
 
DRIZZLE_ROW
1874
 
drizzle_fetch_row(DRIZZLE_RES *res)
1875
 
{
1876
 
  if (!res->data)
1877
 
  {            /* Unbufferred fetch */
1878
 
    if (!res->eof)
1879
 
    {
1880
 
      DRIZZLE *drizzle= res->handle;
1881
 
      if (drizzle->status != DRIZZLE_STATUS_USE_RESULT)
1882
 
      {
1883
 
        set_drizzle_error(drizzle,
1884
 
                        res->unbuffered_fetch_cancelled ?
1885
 
                        CR_FETCH_CANCELED : CR_COMMANDS_OUT_OF_SYNC,
1886
 
                        unknown_sqlstate);
1887
 
      }
1888
 
      else if (!(read_one_row(drizzle, res->field_count, res->row, res->lengths)))
1889
 
      {
1890
 
  res->row_count++;
1891
 
  return(res->current_row=res->row);
1892
 
      }
1893
 
      res->eof=1;
1894
 
      drizzle->status=DRIZZLE_STATUS_READY;
1895
 
      /*
1896
 
        Reset only if owner points to us: there is a chance that somebody
1897
 
        started new query after drizzle_stmt_close():
1898
 
      */
1899
 
      if (drizzle->unbuffered_fetch_owner == &res->unbuffered_fetch_cancelled)
1900
 
        drizzle->unbuffered_fetch_owner= 0;
1901
 
      /* Don't clear handle in drizzle_free_result */
1902
 
      res->handle=0;
1903
 
    }
1904
 
    return((DRIZZLE_ROW) NULL);
1905
 
  }
1906
 
  {
1907
 
    DRIZZLE_ROW tmp;
1908
 
    if (!res->data_cursor)
1909
 
    {
1910
 
      return(res->current_row=(DRIZZLE_ROW) NULL);
1911
 
    }
1912
 
    tmp = res->data_cursor->data;
1913
 
    res->data_cursor = res->data_cursor->next;
1914
 
    return(res->current_row=tmp);
1915
 
  }
1916
 
}
1917
 
 
1918
 
 
1919
 
/**************************************************************************
1920
 
  Get column lengths of the current row
1921
 
  If one uses drizzle_use_result, res->lengths contains the length information,
1922
 
  else the lengths are calculated from the offset between pointers.
1923
 
**************************************************************************/
1924
 
 
1925
 
uint32_t *
1926
 
drizzle_fetch_lengths(DRIZZLE_RES *res)
1927
 
{
1928
 
  DRIZZLE_ROW column;
1929
 
 
1930
 
  if (!(column=res->current_row))
1931
 
    return 0;          /* Something is wrong */
1932
 
  if (res->data)
1933
 
    (*res->methods->fetch_lengths)(res->lengths, column, res->field_count);
1934
 
  return res->lengths;
1935
 
}
1936
 
 
1937
 
 
1938
 
int
1939
 
drizzle_options(DRIZZLE *drizzle,enum drizzle_option option, const void *arg)
1940
 
{
1941
 
  switch (option) {
1942
 
  case DRIZZLE_OPT_CONNECT_TIMEOUT:
1943
 
    drizzle->options.connect_timeout= *(uint*) arg;
1944
 
    break;
1945
 
  case DRIZZLE_OPT_READ_TIMEOUT:
1946
 
    drizzle->options.read_timeout= *(uint*) arg;
1947
 
    break;
1948
 
  case DRIZZLE_OPT_WRITE_TIMEOUT:
1949
 
    drizzle->options.write_timeout= *(uint*) arg;
1950
 
    break;
1951
 
  case DRIZZLE_OPT_COMPRESS:
1952
 
    drizzle->options.compress= 1;      /* Remember for connect */
1953
 
    drizzle->options.client_flag|= CLIENT_COMPRESS;
1954
 
    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
 
  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));
1967
 
    break;
1968
 
  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));
1979
 
    break;
1980
 
  case DRIZZLE_OPT_PROTOCOL:
1981
 
    drizzle->options.protocol= *(const uint*) arg;
1982
 
    break;
1983
 
  case DRIZZLE_OPT_USE_REMOTE_CONNECTION:
1984
 
  case DRIZZLE_OPT_GUESS_CONNECTION:
1985
 
    drizzle->options.methods_to_use= option;
1986
 
    break;
1987
 
  case DRIZZLE_SET_CLIENT_IP:
1988
 
    drizzle->options.client_ip= my_strdup(arg, MYF(MY_WME));
1989
 
    break;
1990
 
  case DRIZZLE_SECURE_AUTH:
1991
 
    drizzle->options.secure_auth= *(const bool *) arg;
1992
 
    break;
1993
 
  case DRIZZLE_REPORT_DATA_TRUNCATION:
1994
 
    drizzle->options.report_data_truncation= test(*(const bool *) arg);
1995
 
    break;
1996
 
  case DRIZZLE_OPT_RECONNECT:
1997
 
    drizzle->reconnect= *(const bool *) arg;
1998
 
    break;
1999
 
  case DRIZZLE_OPT_SSL_VERIFY_SERVER_CERT:
2000
 
    if (*(const bool*) arg)
2001
 
      drizzle->options.client_flag|= CLIENT_SSL_VERIFY_SERVER_CERT;
2002
 
    else
2003
 
      drizzle->options.client_flag&= ~CLIENT_SSL_VERIFY_SERVER_CERT;
2004
 
    break;
2005
 
  default:
2006
 
    return(1);
2007
 
  }
2008
 
  return(0);
2009
 
}
2010
 
 
2011
 
 
2012
 
/****************************************************************************
2013
 
  Functions to get information from the DRIZZLE structure
2014
 
  These are functions to make shared libraries more usable.
2015
 
****************************************************************************/
2016
 
 
2017
 
/* DRIZZLE_RES */
2018
 
uint64_t drizzle_num_rows(const DRIZZLE_RES *res)
2019
 
{
2020
 
  return res->row_count;
2021
 
}
2022
 
 
2023
 
unsigned int drizzle_num_fields(const DRIZZLE_RES *res)
2024
 
{
2025
 
  return res->field_count;
2026
 
}
2027
 
 
2028
 
uint drizzle_errno(const DRIZZLE *drizzle)
2029
 
{
2030
 
  return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno;
2031
 
}
2032
 
 
2033
 
 
2034
 
const char * drizzle_error(const DRIZZLE *drizzle)
2035
 
{
2036
 
  return drizzle ? _(drizzle->net.last_error) : _(drizzle_server_last_error);
2037
 
}
2038
 
 
2039
 
 
2040
 
/*
2041
 
  Get version number for server in a form easy to test on
2042
 
 
2043
 
  SYNOPSIS
2044
 
    drizzle_get_server_version()
2045
 
    drizzle Connection
2046
 
 
2047
 
  EXAMPLE
2048
 
    4.1.0-alfa ->  40100
2049
 
 
2050
 
  NOTES
2051
 
    We will ensure that a newer server always has a bigger number.
2052
 
 
2053
 
  RETURN
2054
 
   Signed number > 323000
2055
 
*/
2056
 
 
2057
 
uint32_t
2058
 
drizzle_get_server_version(const DRIZZLE *drizzle)
2059
 
{
2060
 
  uint major, minor, version;
2061
 
  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);
2065
 
  return (uint32_t) major*10000L+(uint32_t) (minor*100+version);
2066
 
}
2067
 
 
2068
 
 
2069
 
/*
2070
 
   drizzle_set_character_set function sends SET NAMES cs_name to
2071
 
   the server (which changes character_set_client, character_set_result
2072
 
   and character_set_connection) and updates drizzle->charset so other
2073
 
   functions like drizzle_real_escape will work correctly.
2074
 
*/
2075
 
int drizzle_set_character_set(DRIZZLE *drizzle, const char *cs_name)
2076
 
{
2077
 
  const CHARSET_INFO *cs;
2078
 
  const char *save_csdir= charsets_dir;
2079
 
 
2080
 
  if (drizzle->options.charset_dir)
2081
 
    charsets_dir= drizzle->options.charset_dir;
2082
 
 
2083
 
  if (strlen(cs_name) < MY_CS_NAME_SIZE &&
2084
 
      (cs= get_charset_by_csname(cs_name, MY_CS_PRIMARY, MYF(0))))
2085
 
  {
2086
 
    char buff[MY_CS_NAME_SIZE + 10];
2087
 
    charsets_dir= save_csdir;
2088
 
    sprintf(buff, "SET NAMES %s", cs_name);
2089
 
    if (!drizzle_real_query(drizzle, buff, strlen(buff)))
2090
 
    {
2091
 
      drizzle->charset= cs;
2092
 
    }
2093
 
  }
2094
 
  else
2095
 
  {
2096
 
    char cs_dir_name[FN_REFLEN];
2097
 
    get_charsets_dir(cs_dir_name);
2098
 
    set_drizzle_extended_error(drizzle, CR_CANT_READ_CHARSET, unknown_sqlstate,
2099
 
                             ER(CR_CANT_READ_CHARSET), cs_name, cs_dir_name);
2100
 
  }
2101
 
  charsets_dir= save_csdir;
2102
 
  return drizzle->net.last_errno;
2103
 
}
2104
 
 
2105