~drizzle-trunk/drizzle/development

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