~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/drizzle.c

Removed dead variable, sorted authors file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* - mode: c; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems, Inc.
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#include <config.h>
21
 
 
22
 
#include <libdrizzle/drizzle_com.h>
23
 
#include <libdrizzle/libdrizzle.h>
24
 
#include <libdrizzle/errmsg.h>
25
 
#include <libdrizzle/drizzle.h>
26
 
#include <libdrizzle/gettext.h>
27
 
#include <libdrizzle/net_serv.h>
28
 
#include <libdrizzle/drizzle_data.h>
29
 
#include <libdrizzle/local_infile.h>
30
 
 
31
 
#include "libdrizzle_priv.h"
32
 
 
33
 
#include <vio/violite.h>
34
 
 
35
 
#include <drizzled/version.h>
36
 
 
37
 
#include <stdio.h>
38
 
#include <stdlib.h>
39
 
#include <stdarg.h>
40
 
#include <string.h>
41
 
#include <netdb.h>
42
 
#include <assert.h>
43
 
#include <pwd.h>
44
 
#include <sys/socket.h>
45
 
 
46
 
 
47
 
#define CONNECT_TIMEOUT 0
48
 
 
49
 
static bool drizzle_client_init= false;
50
 
unsigned int drizzle_server_last_errno;
51
 
 
52
 
/* Server error code and message */
53
 
char drizzle_server_last_error[DRIZZLE_ERRMSG_SIZE];
54
 
 
55
 
/*
56
 
  Note that the drizzle argument must be initialized with drizzle_init()
57
 
  before calling drizzle_connect !
58
 
*/
59
 
 
60
 
 
61
 
 
62
 
static DRIZZLE_METHODS client_methods=
63
 
{
64
 
  cli_read_query_result,                       /* read_query_result */
65
 
  cli_advanced_command,                        /* advanced_command */
66
 
  cli_read_rows,                               /* read_rows */
67
 
  cli_use_result,                              /* use_result */
68
 
  cli_fetch_lengths,                           /* fetch_lengths */
69
 
  cli_flush_use_result,                        /* flush_use_result */
70
 
  cli_list_fields,                             /* list_fields */
71
 
  cli_unbuffered_fetch,                        /* unbuffered_fetch */
72
 
  cli_read_statistics,                         /* read_statistics */
73
 
  cli_read_query_result,                       /* next_result */
74
 
  cli_read_change_user_result,                 /* read_change_user_result */
75
 
};
76
 
 
77
 
 
78
 
 
79
 
/****************************************************************************
80
 
  Init DRIZZLE structure or allocate one
81
 
****************************************************************************/
82
 
 
83
 
DRIZZLE *
84
 
drizzle_create(DRIZZLE *ptr)
85
 
{
86
 
 
87
 
  if (!drizzle_client_init)
88
 
  {
89
 
    drizzle_client_init=true;
90
 
 
91
 
    if (!drizzle_get_default_port())
92
 
    {
93
 
      drizzle_set_default_port(DRIZZLE_PORT);
94
 
      {
95
 
        struct servent *serv_ptr;
96
 
        char *env;
97
 
 
98
 
        /*
99
 
          if builder specifically requested a default port, use that
100
 
          (even if it coincides with our factory default).
101
 
          only if they didn't do we check /etc/services (and, failing
102
 
          on that, fall back to the factory default of 4427).
103
 
          either default can be overridden by the environment variable
104
 
          DRIZZLE_TCP_PORT, which in turn can be overridden with command
105
 
          line options.
106
 
        */
107
 
 
108
 
#if DRIZZLE_PORT_DEFAULT == 0
109
 
        if ((serv_ptr = getservbyname("drizzle", "tcp")))
110
 
          drizzle_set_default_port((uint32_t) ntohs((uint16_t) serv_ptr->s_port));
111
 
#endif
112
 
        if ((env = getenv("DRIZZLE_TCP_PORT")))
113
 
          drizzle_set_default_port((uint32_t) atoi(env));
114
 
      }
115
 
    }
116
 
#if defined(SIGPIPE)
117
 
    (void) signal(SIGPIPE, SIG_IGN);
118
 
#endif
119
 
  }
120
 
 
121
 
  if (ptr == NULL)
122
 
  {
123
 
    ptr= (DRIZZLE *) malloc(sizeof(DRIZZLE));
124
 
 
125
 
    if (ptr == NULL)
126
 
    {
127
 
      drizzle_set_error(NULL, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
128
 
      return 0;
129
 
    }
130
 
    memset(ptr, 0, sizeof(DRIZZLE));
131
 
    ptr->free_me=1;
132
 
  }
133
 
  else
134
 
  {
135
 
    memset(ptr, 0, sizeof(DRIZZLE));
136
 
  }
137
 
 
138
 
  ptr->options.connect_timeout= CONNECT_TIMEOUT;
139
 
  strcpy(ptr->net.sqlstate, sqlstate_get_not_error());
140
 
 
141
 
  /*
142
 
    Only enable LOAD DATA INFILE by default if configured with
143
 
    --enable-local-infile
144
 
  */
145
 
 
146
 
#if defined(ENABLED_LOCAL_INFILE)
147
 
  ptr->options.client_flag|= CLIENT_LOCAL_FILES;
148
 
#endif
149
 
 
150
 
  ptr->options.methods_to_use= DRIZZLE_OPT_GUESS_CONNECTION;
151
 
  ptr->options.report_data_truncation= true;  /* default */
152
 
 
153
 
  /*
154
 
    By default we don't reconnect because it could silently corrupt data (after
155
 
    reconnection you potentially lose table locks, user variables, session
156
 
    variables (transactions but they are specifically dealt with in
157
 
    drizzle_reconnect()).
158
 
    This is a change: < 5.0.3 drizzle->reconnect was set to 1 by default.
159
 
    How this change impacts existing apps:
160
 
    - existing apps which relyed on the default will see a behaviour change;
161
 
    they will have to set reconnect=1 after drizzle_connect().
162
 
    - existing apps which explicitely asked for reconnection (the only way they
163
 
    could do it was by setting drizzle.reconnect to 1 after drizzle_connect())
164
 
    will not see a behaviour change.
165
 
    - existing apps which explicitely asked for no reconnection
166
 
    (drizzle.reconnect=0) will not see a behaviour change.
167
 
  */
168
 
  ptr->reconnect= 0;
169
 
 
170
 
  return ptr;
171
 
}
172
 
 
173
 
 
174
 
static void read_user_name(char *name)
175
 
{
176
 
  if (geteuid() == 0)
177
 
    strcpy(name,"root");    /* allow use of surun */
178
 
  else
179
 
  {
180
 
#ifdef HAVE_GETPWUID
181
 
    struct passwd *skr;
182
 
    const char *str;
183
 
    if ((str=getlogin()) == NULL)
184
 
    {
185
 
      if ((skr=getpwuid(geteuid())) != NULL)
186
 
  str=skr->pw_name;
187
 
      else if (!(str=getenv("USER")) && !(str=getenv("LOGNAME")) &&
188
 
         !(str=getenv("LOGIN")))
189
 
  str="UNKNOWN_USER";
190
 
    }
191
 
    strncpy(name,str,USERNAME_LENGTH);
192
 
#elif HAVE_CUSERID
193
 
    (void) cuserid(name);
194
 
#else
195
 
    strcpy(name,"UNKNOWN_USER");
196
 
#endif
197
 
  }
198
 
  return;
199
 
}
200
 
 
201
 
DRIZZLE *
202
 
drizzle_connect(DRIZZLE *drizzle,const char *host, const char *user,
203
 
                const char *passwd, const char *db,
204
 
                uint32_t port,
205
 
                const char * unix_port __attribute__((__unused__)),
206
 
                uint32_t client_flag)
207
 
{
208
 
  char          buff[NAME_LEN+USERNAME_LENGTH+100];
209
 
  char          *end,*host_info=NULL;
210
 
  uint32_t         pkt_length;
211
 
  NET           *net= &drizzle->net;
212
 
 
213
 
  drizzle->methods= &client_methods;
214
 
  net->vio = 0;        /* If something goes wrong */
215
 
  drizzle->client_flag=0;      /* For handshake */
216
 
 
217
 
  /* Some empty-string-tests are done because of ODBC */
218
 
  if (!host || !host[0])
219
 
    host=drizzle->options.host;
220
 
  if (!user || !user[0])
221
 
  {
222
 
    user=drizzle->options.user;
223
 
    if (!user)
224
 
      user= "";
225
 
  }
226
 
  if (!passwd)
227
 
  {
228
 
    passwd=drizzle->options.password;
229
 
    if (!passwd)
230
 
      passwd= "";
231
 
  }
232
 
  if (!db || !db[0])
233
 
    db=drizzle->options.db;
234
 
  if (!port)
235
 
    port=drizzle->options.port;
236
 
 
237
 
  drizzle->server_status=SERVER_STATUS_AUTOCOMMIT;
238
 
 
239
 
  /*
240
 
    Part 0: Grab a socket and connect it to the server
241
 
  */
242
 
  if (!net->vio)
243
 
  {
244
 
    struct addrinfo *res_lst, hints, *t_res;
245
 
    int gai_errno;
246
 
    char port_buf[NI_MAXSERV];
247
 
 
248
 
    if (!port)
249
 
      port= drizzle_port;
250
 
 
251
 
    if (!host)
252
 
      host= LOCAL_HOST;
253
 
 
254
 
    snprintf(host_info=buff, sizeof(buff)-1, ER(CR_TCP_CONNECTION), host);
255
 
 
256
 
    memset(&hints, 0, sizeof(hints));
257
 
    hints.ai_socktype= SOCK_STREAM;
258
 
 
259
 
    snprintf(port_buf, NI_MAXSERV, "%d", port);
260
 
    gai_errno= getaddrinfo(host, port_buf, &hints, &res_lst);
261
 
 
262
 
    if (gai_errno != 0)
263
 
    {
264
 
      drizzle_set_extended_error(drizzle, CR_UNKNOWN_HOST, sqlstate_get_unknown(),
265
 
                                 ER(CR_UNKNOWN_HOST), host, errno);
266
 
 
267
 
      goto error;
268
 
    }
269
 
 
270
 
    for (t_res= res_lst; t_res != NULL; t_res= t_res->ai_next)
271
 
    {
272
 
      int sock= socket(t_res->ai_family, t_res->ai_socktype,
273
 
                       t_res->ai_protocol);
274
 
      if (sock < 0)
275
 
        continue;
276
 
 
277
 
      net->vio= vio_new(sock, VIO_TYPE_TCPIP, VIO_BUFFERED_READ);
278
 
      if (! net->vio )
279
 
      {
280
 
        close(sock);
281
 
        continue;
282
 
      }
283
 
 
284
 
      if (connect_with_timeout(sock, t_res->ai_addr, t_res->ai_addrlen, drizzle->options.connect_timeout))
285
 
      {
286
 
        vio_delete(net->vio);
287
 
        net->vio= 0;
288
 
        continue;
289
 
      }
290
 
      break;
291
 
    }
292
 
 
293
 
    freeaddrinfo(res_lst);
294
 
  }
295
 
 
296
 
  if (!net->vio)
297
 
  {
298
 
    drizzle_set_extended_error(drizzle, CR_CONN_HOST_ERROR, sqlstate_get_unknown(),
299
 
                               ER(CR_CONN_HOST_ERROR), host, errno);
300
 
    goto error;
301
 
  }
302
 
 
303
 
  if (my_net_init(net, net->vio))
304
 
  {
305
 
    vio_delete(net->vio);
306
 
    net->vio = 0;
307
 
    drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
308
 
    goto error;
309
 
  }
310
 
  vio_keepalive(net->vio,true);
311
 
 
312
 
  /* If user set read_timeout, let it override the default */
313
 
  if (drizzle->options.read_timeout)
314
 
    my_net_set_read_timeout(net, drizzle->options.read_timeout);
315
 
 
316
 
  /* If user set write_timeout, let it override the default */
317
 
  if (drizzle->options.write_timeout)
318
 
    my_net_set_write_timeout(net, drizzle->options.write_timeout);
319
 
 
320
 
  if (drizzle->options.max_allowed_packet)
321
 
    net->max_packet_size= drizzle->options.max_allowed_packet;
322
 
 
323
 
  /* Get version info */
324
 
  drizzle->protocol_version= PROTOCOL_VERSION;  /* Assume this */
325
 
  if (drizzle->options.connect_timeout &&
326
 
      vio_poll_read(net->vio, drizzle->options.connect_timeout))
327
 
  {
328
 
    drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
329
 
                               ER(CR_SERVER_LOST_INITIAL_COMM_WAIT),
330
 
                               errno);
331
 
    goto error;
332
 
  }
333
 
 
334
 
  /*
335
 
    Part 1: Connection established, read and parse first packet
336
 
  */
337
 
 
338
 
  if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
339
 
  {
340
 
    if (drizzle->net.last_errno == CR_SERVER_LOST)
341
 
      drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
342
 
                                 ER(CR_SERVER_LOST_INITIAL_COMM_READ),
343
 
                                 errno);
344
 
    goto error;
345
 
  }
346
 
  /* Check if version of protocol matches current one */
347
 
 
348
 
  drizzle->protocol_version= net->read_pos[0];
349
 
  if (drizzle->protocol_version != PROTOCOL_VERSION)
350
 
  {
351
 
    drizzle_set_extended_error(drizzle, CR_VERSION_ERROR, sqlstate_get_unknown(),
352
 
                               ER(CR_VERSION_ERROR), drizzle->protocol_version,
353
 
                               PROTOCOL_VERSION);
354
 
    goto error;
355
 
  }
356
 
  end= strchr((char*) net->read_pos+1, '\0');
357
 
  drizzle->thread_id=uint4korr(end+1);
358
 
  end+=5;
359
 
  /*
360
 
    Scramble is split into two parts because old clients does not understand
361
 
    long scrambles; here goes the first part.
362
 
  */
363
 
  strncpy(drizzle->scramble, end, SCRAMBLE_LENGTH_323);
364
 
  end+= SCRAMBLE_LENGTH_323+1;
365
 
 
366
 
  if (pkt_length >= (uint32_t) (end+1 - (char*) net->read_pos))
367
 
    drizzle->server_capabilities=uint2korr(end);
368
 
  if (pkt_length >= (uint32_t) (end+18 - (char*) net->read_pos))
369
 
  {
370
 
    /* New protocol with 16 bytes to describe server characteristics */
371
 
    drizzle->server_language=end[2];
372
 
    drizzle->server_status=uint2korr(end+3);
373
 
  }
374
 
  end+= 18;
375
 
  if (pkt_length >= (uint32_t) (end + SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323 + 1 -
376
 
                            (char *) net->read_pos))
377
 
    strncpy(drizzle->scramble+SCRAMBLE_LENGTH_323, end,
378
 
            SCRAMBLE_LENGTH-SCRAMBLE_LENGTH_323);
379
 
  else
380
 
    drizzle->server_capabilities&= ~CLIENT_SECURE_CONNECTION;
381
 
 
382
 
  if (drizzle->options.secure_auth && passwd[0] &&
383
 
      !(drizzle->server_capabilities & CLIENT_SECURE_CONNECTION))
384
 
  {
385
 
    drizzle_set_error(drizzle, CR_SECURE_AUTH, sqlstate_get_unknown());
386
 
    goto error;
387
 
  }
388
 
 
389
 
  /* Save connection information */
390
 
  if (!(drizzle->host_info= (char *)malloc(strlen(host_info)+1+strlen(host)+1
391
 
                                           +(end - (char*) net->read_pos))) ||
392
 
      !(drizzle->user=strdup(user)) ||
393
 
      !(drizzle->passwd=strdup(passwd)))
394
 
  {
395
 
    drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
396
 
    goto error;
397
 
  }
398
 
  drizzle->host= drizzle->host_info+strlen(host_info)+1;
399
 
  drizzle->server_version= drizzle->host+strlen(host)+1;
400
 
  strcpy(drizzle->host_info,host_info);
401
 
  strcpy(drizzle->host,host);
402
 
  strcpy(drizzle->server_version,(char*) net->read_pos+1);
403
 
  drizzle->port=port;
404
 
 
405
 
  /*
406
 
    Part 2: format and send client info to the server for access check
407
 
  */
408
 
 
409
 
  client_flag|=drizzle->options.client_flag;
410
 
  client_flag|=CLIENT_CAPABILITIES;
411
 
  if (client_flag & CLIENT_MULTI_STATEMENTS)
412
 
    client_flag|= CLIENT_MULTI_RESULTS;
413
 
 
414
 
  if (db)
415
 
    client_flag|=CLIENT_CONNECT_WITH_DB;
416
 
 
417
 
  /* Remove options that server doesn't support */
418
 
  client_flag= ((client_flag &
419
 
                 ~(CLIENT_COMPRESS | CLIENT_SSL)) |
420
 
                (client_flag & drizzle->server_capabilities));
421
 
  client_flag&= ~CLIENT_COMPRESS;
422
 
 
423
 
  int4store(buff, client_flag);
424
 
  int4store(buff+4, net->max_packet_size);
425
 
  buff[8]= (char) 45; // utf8 charset number
426
 
  memset(buff+9, 0, 32-9);
427
 
  end= buff+32;
428
 
 
429
 
  drizzle->client_flag=client_flag;
430
 
 
431
 
  /* This needs to be changed as it's not useful with big packets */
432
 
  if (user && user[0])
433
 
    strncpy(end,user,USERNAME_LENGTH);          /* Max user name */
434
 
  else
435
 
    read_user_name((char*) end);
436
 
 
437
 
  /* We have to handle different version of handshake here */
438
 
  end= strchr(end, '\0') + 1;
439
 
  if (passwd[0])
440
 
  {
441
 
    {
442
 
      *end++= SCRAMBLE_LENGTH;
443
 
      memset(end, 0, SCRAMBLE_LENGTH-1);
444
 
      memcpy(end, passwd, strlen(passwd));
445
 
      end+= SCRAMBLE_LENGTH;
446
 
    }
447
 
  }
448
 
  else
449
 
    *end++= '\0';                               /* empty password */
450
 
 
451
 
  /* Add database if needed */
452
 
  if (db && (drizzle->server_capabilities & CLIENT_CONNECT_WITH_DB))
453
 
  {
454
 
    end= strncpy(end, db, NAME_LEN) + NAME_LEN + 1;
455
 
    drizzle->db= strdup(db);
456
 
    db= 0;
457
 
  }
458
 
  /* Write authentication package */
459
 
  if (my_net_write(net, (unsigned char*) buff, (size_t) (end-buff)) || net_flush(net))
460
 
  {
461
 
    drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
462
 
                               ER(CR_SERVER_LOST_SEND_AUTH),
463
 
                               errno);
464
 
    goto error;
465
 
  }
466
 
 
467
 
  /*
468
 
    Part 3: Authorization data's been sent. Now server can reply with
469
 
    OK-packet, or re-request scrambled password.
470
 
  */
471
 
 
472
 
  if ((pkt_length=cli_safe_read(drizzle)) == packet_error)
473
 
  {
474
 
    if (drizzle->net.last_errno == CR_SERVER_LOST)
475
 
      drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
476
 
                                 ER(CR_SERVER_LOST_READ_AUTH),
477
 
                                 errno);
478
 
    goto error;
479
 
  }
480
 
 
481
 
  if (client_flag & CLIENT_COMPRESS)    /* We will use compression */
482
 
    net->compress=1;
483
 
 
484
 
 
485
 
  if (db && drizzle_select_db(drizzle, db))
486
 
  {
487
 
    if (drizzle->net.last_errno == CR_SERVER_LOST)
488
 
      drizzle_set_extended_error(drizzle, CR_SERVER_LOST, sqlstate_get_unknown(),
489
 
                                 ER(CR_SERVER_LOST_SETTING_DB),
490
 
                                 errno);
491
 
    goto error;
492
 
  }
493
 
 
494
 
 
495
 
  return(drizzle);
496
 
 
497
 
error:
498
 
  {
499
 
    /* Free alloced memory */
500
 
    drizzle_disconnect(drizzle);
501
 
    drizzle_close_free(drizzle);
502
 
    if (!(((uint32_t) client_flag) & CLIENT_REMEMBER_OPTIONS))
503
 
      drizzle_close_free_options(drizzle);
504
 
  }
505
 
  return(0);
506
 
}
507
 
 
508
 
 
509
 
 
510
 
 
511
 
/**************************************************************************
512
 
  Set current database
513
 
**************************************************************************/
514
 
 
515
 
int
516
 
drizzle_select_db(DRIZZLE *drizzle, const char *db)
517
 
{
518
 
  int error;
519
 
 
520
 
  if ((error=simple_command(drizzle,COM_INIT_DB, (const unsigned char*) db,
521
 
                            (uint32_t) strlen(db),0)))
522
 
    return(error);
523
 
  if (drizzle->db != NULL)
524
 
    free(drizzle->db);
525
 
  drizzle->db=strdup(db);
526
 
  return(0);
527
 
}
528
 
 
529
 
bool drizzle_reconnect(DRIZZLE *drizzle)
530
 
{
531
 
  DRIZZLE tmp_drizzle;
532
 
  assert(drizzle);
533
 
 
534
 
  if (!drizzle->reconnect ||
535
 
      (drizzle->server_status & SERVER_STATUS_IN_TRANS) || !drizzle->host_info)
536
 
  {
537
 
    /* Allow reconnect next time */
538
 
    drizzle->server_status&= ~SERVER_STATUS_IN_TRANS;
539
 
    drizzle_set_error(drizzle, CR_SERVER_GONE_ERROR, sqlstate_get_unknown());
540
 
    return(1);
541
 
  }
542
 
  drizzle_create(&tmp_drizzle);
543
 
  tmp_drizzle.options= drizzle->options;
544
 
  tmp_drizzle.options.my_cnf_file= tmp_drizzle.options.my_cnf_group= 0;
545
 
 
546
 
  if (!drizzle_connect(&tmp_drizzle,drizzle->host,drizzle->user,drizzle->passwd,
547
 
                       drizzle->db, drizzle->port, 0,
548
 
                       drizzle->client_flag | CLIENT_REMEMBER_OPTIONS))
549
 
  {
550
 
    drizzle->net.last_errno= tmp_drizzle.net.last_errno;
551
 
    strcpy(drizzle->net.last_error, tmp_drizzle.net.last_error);
552
 
    strcpy(drizzle->net.sqlstate, tmp_drizzle.net.sqlstate);
553
 
    return(1);
554
 
  }
555
 
 
556
 
  tmp_drizzle.reconnect= 1;
557
 
  tmp_drizzle.free_me= drizzle->free_me;
558
 
 
559
 
  /* Don't free options as these are now used in tmp_drizzle */
560
 
  memset(&drizzle->options, 0, sizeof(drizzle->options));
561
 
  drizzle->free_me=0;
562
 
  drizzle_close(drizzle);
563
 
  *drizzle=tmp_drizzle;
564
 
  net_clear(&drizzle->net, 1);
565
 
  drizzle->affected_rows= ~(uint64_t) 0;
566
 
  return(0);
567
 
}
568
 
 
569
 
/**************************************************************************
570
 
  Shut down connection
571
 
**************************************************************************/
572
 
 
573
 
void drizzle_disconnect(DRIZZLE *drizzle)
574
 
{
575
 
  int save_errno= errno;
576
 
  if (drizzle->net.vio != 0)
577
 
  {
578
 
    vio_delete(drizzle->net.vio);
579
 
    drizzle->net.vio= 0;          /* Marker */
580
 
  }
581
 
  net_end(&drizzle->net);
582
 
  free_old_query(drizzle);
583
 
  errno= save_errno;
584
 
}
585
 
 
586
 
 
587
 
/*************************************************************************
588
 
  Send a QUIT to the server and close the connection
589
 
  If handle is alloced by DRIZZLE connect free it.
590
 
*************************************************************************/
591
 
 
592
 
void drizzle_close_free_options(DRIZZLE *drizzle)
593
 
{
594
 
  if (drizzle->options.user != NULL)
595
 
    free(drizzle->options.user);
596
 
  if (drizzle->options.host != NULL)
597
 
    free(drizzle->options.host);
598
 
  if (drizzle->options.password != NULL)
599
 
    free(drizzle->options.password);
600
 
  if (drizzle->options.db != NULL)
601
 
    free(drizzle->options.db);
602
 
  if (drizzle->options.my_cnf_file != NULL)
603
 
    free(drizzle->options.my_cnf_file);
604
 
  if (drizzle->options.my_cnf_group != NULL)
605
 
    free(drizzle->options.my_cnf_group);
606
 
  if (drizzle->options.client_ip != NULL)
607
 
    free(drizzle->options.client_ip);
608
 
  memset(&drizzle->options, 0, sizeof(drizzle->options));
609
 
  return;
610
 
}
611
 
 
612
 
 
613
 
void drizzle_close_free(DRIZZLE *drizzle)
614
 
{
615
 
  if (drizzle->host_info != NULL)
616
 
    free((unsigned char*) drizzle->host_info);
617
 
  if (drizzle->user != NULL)
618
 
    free(drizzle->user);
619
 
  if (drizzle->passwd != NULL)
620
 
    free(drizzle->passwd);
621
 
  if (drizzle->db != NULL)
622
 
    free(drizzle->db);
623
 
  if (drizzle->info_buffer != NULL)
624
 
    free(drizzle->info_buffer);
625
 
  drizzle->info_buffer= 0;
626
 
 
627
 
  /* Clear pointers for better safety */
628
 
  drizzle->host_info= drizzle->user= drizzle->passwd= drizzle->db= 0;
629
 
}
630
 
 
631
 
 
632
 
void drizzle_close(DRIZZLE *drizzle)
633
 
{
634
 
  if (drizzle)          /* Some simple safety */
635
 
  {
636
 
    /* If connection is still up, send a QUIT message */
637
 
    if (drizzle->net.vio != 0)
638
 
    {
639
 
      free_old_query(drizzle);
640
 
      drizzle->status=DRIZZLE_STATUS_READY; /* Force command */
641
 
      drizzle->reconnect=0;
642
 
      simple_command(drizzle,COM_QUIT,(unsigned char*) 0,0,1);
643
 
      drizzle_disconnect(drizzle);      /* Sets drizzle->net.vio= 0 */
644
 
    }
645
 
    drizzle_close_free_options(drizzle);
646
 
    drizzle_close_free(drizzle);
647
 
    if (drizzle->free_me)
648
 
      free((unsigned char*) drizzle);
649
 
  }
650
 
  return;
651
 
}
652
 
 
653
 
 
654
 
bool cli_read_query_result(DRIZZLE *drizzle)
655
 
{
656
 
  unsigned char *pos;
657
 
  uint32_t field_count;
658
 
  DRIZZLE_DATA *fields;
659
 
  uint32_t length;
660
 
 
661
 
  if ((length = cli_safe_read(drizzle)) == packet_error)
662
 
    return(1);
663
 
  free_old_query(drizzle);    /* Free old result */
664
 
get_info:
665
 
  pos=(unsigned char*) drizzle->net.read_pos;
666
 
  if ((field_count= net_field_length(&pos)) == 0)
667
 
  {
668
 
    drizzle->affected_rows= net_field_length_ll(&pos);
669
 
    drizzle->insert_id=    net_field_length_ll(&pos);
670
 
 
671
 
    drizzle->server_status= uint2korr(pos); pos+=2;
672
 
    drizzle->warning_count= uint2korr(pos); pos+=2;
673
 
 
674
 
    if (pos < drizzle->net.read_pos+length && net_field_length(&pos))
675
 
      drizzle->info=(char*) pos;
676
 
    return(0);
677
 
  }
678
 
  if (field_count == NULL_LENGTH)    /* LOAD DATA LOCAL INFILE */
679
 
  {
680
 
    int error;
681
 
 
682
 
    if (!(drizzle->options.client_flag & CLIENT_LOCAL_FILES))
683
 
    {
684
 
      drizzle_set_error(drizzle, CR_MALFORMED_PACKET, sqlstate_get_unknown());
685
 
      return(1);
686
 
    }
687
 
 
688
 
    error= handle_local_infile(drizzle,(char*) pos);
689
 
    if ((length= cli_safe_read(drizzle)) == packet_error || error)
690
 
      return(1);
691
 
    goto get_info;        /* Get info packet */
692
 
  }
693
 
  if (!(drizzle->server_status & SERVER_STATUS_AUTOCOMMIT))
694
 
    drizzle->server_status|= SERVER_STATUS_IN_TRANS;
695
 
 
696
 
  if (!(fields=cli_read_rows(drizzle,(DRIZZLE_FIELD*)0, 7)))
697
 
    return(1);
698
 
  if (!(drizzle->fields= unpack_fields(fields, (uint32_t) field_count, 0)))
699
 
    return(1);
700
 
  drizzle->status= DRIZZLE_STATUS_GET_RESULT;
701
 
  drizzle->field_count= (uint32_t) field_count;
702
 
  return(0);
703
 
}
704
 
 
705
 
 
706
 
/*
707
 
  Send the query and return so we can do something else.
708
 
  Needs to be followed by drizzle_read_query_result() when we want to
709
 
  finish processing it.
710
 
*/
711
 
 
712
 
int32_t
713
 
drizzle_send_query(DRIZZLE *drizzle, const char* query, uint32_t length)
714
 
{
715
 
  return(simple_command(drizzle, COM_QUERY, (unsigned char*) query, length, 1));
716
 
}
717
 
 
718
 
 
719
 
int32_t
720
 
drizzle_real_query(DRIZZLE *drizzle, const char *query, uint32_t length)
721
 
{
722
 
  if (drizzle_send_query(drizzle,query,length))
723
 
    return(1);
724
 
  return((int) (*drizzle->methods->read_query_result)(drizzle));
725
 
}
726
 
 
727
 
 
728
 
/**************************************************************************
729
 
  Alloc result struct for buffered results. All rows are read to buffer.
730
 
  drizzle_data_seek may be used.
731
 
**************************************************************************/
732
 
 
733
 
DRIZZLE_RES * drizzle_store_result(DRIZZLE *drizzle)
734
 
{
735
 
  DRIZZLE_RES *result;
736
 
 
737
 
  if (!drizzle->fields)
738
 
    return(0);
739
 
  if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
740
 
  {
741
 
    drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown());
742
 
    return(0);
743
 
  }
744
 
  drizzle->status=DRIZZLE_STATUS_READY;    /* server is ready */
745
 
  if (!(result=(DRIZZLE_RES*) malloc((uint32_t) (sizeof(DRIZZLE_RES)+
746
 
                sizeof(uint32_t) *
747
 
                drizzle->field_count))))
748
 
  {
749
 
    drizzle_set_error(drizzle, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
750
 
    return(0);
751
 
  }
752
 
  memset(result, 0,(sizeof(DRIZZLE_RES)+ sizeof(uint32_t) *
753
 
                    drizzle->field_count));
754
 
  result->methods= drizzle->methods;
755
 
  result->eof= 1;        /* Marker for buffered */
756
 
  result->lengths= (uint32_t*) (result+1);
757
 
  if (!(result->data=
758
 
  (*drizzle->methods->read_rows)(drizzle,drizzle->fields,drizzle->field_count)))
759
 
  {
760
 
    free((unsigned char*) result);
761
 
    return(0);
762
 
  }
763
 
  drizzle->affected_rows= result->row_count= result->data->rows;
764
 
  result->data_cursor=  result->data->data;
765
 
  result->fields=  drizzle->fields;
766
 
  result->field_count=  drizzle->field_count;
767
 
  /* The rest of result members is zeroed in malloc */
768
 
  drizzle->fields=0;        /* fields is now in result */
769
 
  /* just in case this was mistakenly called after drizzle_stmt_execute() */
770
 
  drizzle->unbuffered_fetch_owner= 0;
771
 
  return(result);        /* Data fetched */
772
 
}
773
 
 
774
 
 
775
 
/**************************************************************************
776
 
  Alloc struct for use with unbuffered reads. Data is fetched by domand
777
 
  when calling to drizzle_fetch_row.
778
 
  DRIZZLE_DATA_seek is a noop.
779
 
 
780
 
  No other queries may be specified with the same DRIZZLE handle.
781
 
  There shouldn't be much processing per row because DRIZZLE server shouldn't
782
 
  have to wait for the client (and will not wait more than 30 sec/packet).
783
 
**************************************************************************/
784
 
 
785
 
DRIZZLE_RES * cli_use_result(DRIZZLE *drizzle)
786
 
{
787
 
  DRIZZLE_RES *result;
788
 
 
789
 
  if (!drizzle->fields)
790
 
    return(0);
791
 
  if (drizzle->status != DRIZZLE_STATUS_GET_RESULT)
792
 
  {
793
 
    drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown());
794
 
    return(0);
795
 
  }
796
 
  if (!(result=(DRIZZLE_RES*) malloc(sizeof(*result)+
797
 
                                     sizeof(uint32_t)*drizzle->field_count)))
798
 
    return(0);
799
 
  memset(result, 0, sizeof(*result)+ sizeof(uint32_t)*drizzle->field_count);
800
 
  result->lengths=(uint32_t*) (result+1);
801
 
  result->methods= drizzle->methods;
802
 
  if (!(result->row=(DRIZZLE_ROW)
803
 
        malloc(sizeof(result->row[0])*(drizzle->field_count+1))))
804
 
  {          /* Ptrs: to one row */
805
 
    free((unsigned char*) result);
806
 
    return(0);
807
 
  }
808
 
  result->fields=  drizzle->fields;
809
 
  result->field_count=  drizzle->field_count;
810
 
  result->current_field=0;
811
 
  result->handle=  drizzle;
812
 
  result->current_row=  0;
813
 
  drizzle->fields=0;      /* fields is now in result */
814
 
  drizzle->status=DRIZZLE_STATUS_USE_RESULT;
815
 
  drizzle->unbuffered_fetch_owner= &result->unbuffered_fetch_cancelled;
816
 
  return(result);      /* Data is read to be fetched */
817
 
}
818
 
 
819
 
 
820
 
 
821
 
/**
822
 
   Set the internal error message to DRIZZLE handler
823
 
 
824
 
   @param drizzle connection handle (client side)
825
 
   @param errcode  CR_ error code, passed to ER macro to get
826
 
   error text
827
 
   @parma sqlstate SQL standard sqlstate
828
 
*/
829
 
 
830
 
void drizzle_set_error(DRIZZLE *drizzle, int errcode, const char *sqlstate)
831
 
{
832
 
  NET *net;
833
 
  assert(drizzle != 0);
834
 
 
835
 
  if (drizzle)
836
 
  {
837
 
    net= &drizzle->net;
838
 
    net->last_errno= errcode;
839
 
    strcpy(net->last_error, ER(errcode));
840
 
    strcpy(net->sqlstate, sqlstate);
841
 
  }
842
 
  else
843
 
  {
844
 
    drizzle_server_last_errno= errcode;
845
 
    strcpy(drizzle_server_last_error, ER(errcode));
846
 
  }
847
 
  return;
848
 
}
849
 
 
850
 
 
851
 
unsigned int drizzle_errno(const DRIZZLE *drizzle)
852
 
{
853
 
  return drizzle ? drizzle->net.last_errno : drizzle_server_last_errno;
854
 
}
855
 
 
856
 
 
857
 
const char * drizzle_error(const DRIZZLE *drizzle)
858
 
{
859
 
  return drizzle ? _(drizzle->net.last_error) : _(drizzle_server_last_error);
860
 
}
861
 
 
862
 
/**
863
 
   Set an error message on the client.
864
 
 
865
 
   @param drizzle connection handle
866
 
   @param errcode   CR_* errcode, for client errors
867
 
   @param sqlstate  SQL standard sql state, sqlstate_get_unknown() for the
868
 
   majority of client errors.
869
 
   @param format    error message template, in sprintf format
870
 
   @param ...       variable number of arguments
871
 
*/
872
 
 
873
 
void drizzle_set_extended_error(DRIZZLE *drizzle, int errcode,
874
 
                                const char *sqlstate,
875
 
                                const char *format, ...)
876
 
{
877
 
  NET *net;
878
 
  va_list args;
879
 
  assert(drizzle != 0);
880
 
 
881
 
  net= &drizzle->net;
882
 
  net->last_errno= errcode;
883
 
  va_start(args, format);
884
 
  vsnprintf(net->last_error, sizeof(net->last_error)-1,
885
 
            format, args);
886
 
  va_end(args);
887
 
  strcpy(net->sqlstate, sqlstate);
888
 
 
889
 
  return;
890
 
}
891
 
 
892
 
 
893
 
 
894
 
/*
895
 
  Flush result set sent from server
896
 
*/
897
 
 
898
 
void cli_flush_use_result(DRIZZLE *drizzle)
899
 
{
900
 
  /* Clear the current execution status */
901
 
  for (;;)
902
 
  {
903
 
    uint32_t pkt_len;
904
 
    if ((pkt_len=cli_safe_read(drizzle)) == packet_error)
905
 
      break;
906
 
    if (pkt_len <= 8 && drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA)
907
 
    {
908
 
      char *pos= (char*) drizzle->net.read_pos + 1;
909
 
      drizzle->warning_count=uint2korr(pos); pos+=2;
910
 
      drizzle->server_status=uint2korr(pos); pos+=2;
911
 
 
912
 
      break;                            /* End of data */
913
 
    }
914
 
  }
915
 
  return;
916
 
}
917
 
 
918
 
/**************************************************************************
919
 
  Get column lengths of the current row
920
 
  If one uses drizzle_use_result, res->lengths contains the length information,
921
 
  else the lengths are calculated from the offset between pointers.
922
 
**************************************************************************/
923
 
 
924
 
void cli_fetch_lengths(uint32_t *to, DRIZZLE_ROW column, uint32_t field_count)
925
 
{
926
 
  uint32_t *prev_length;
927
 
  char *start=0;
928
 
  DRIZZLE_ROW end;
929
 
 
930
 
  prev_length=0;        /* Keep gcc happy */
931
 
  for (end=column + field_count + 1 ; column != end ; column++, to++)
932
 
  {
933
 
    if (!*column)
934
 
    {
935
 
      *to= 0;          /* Null */
936
 
      continue;
937
 
    }
938
 
    if (start)          /* Found end of prev string */
939
 
      *prev_length= (uint32_t) (*column-start-1);
940
 
    start= *column;
941
 
    prev_length= to;
942
 
  }
943
 
}
944