~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/drizzle.c

  • Committer: Monty Taylor
  • Date: 2008-09-16 04:26:53 UTC
  • mto: This revision was merged to the branch mainline in revision 391.
  • Revision ID: monty@inaugust.com-20080916042653-59fgd0y0lbw6ohna
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... 

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
 
20
20
#include <config.h>
21
21
 
 
22
#include <libdrizzle/drizzle_com.h>
22
23
#include <libdrizzle/libdrizzle.h>
23
24
#include <libdrizzle/errmsg.h>
24
25
#include <libdrizzle/drizzle.h>
25
26
#include <libdrizzle/gettext.h>
 
27
#include <libdrizzle/net_serv.h>
 
28
#include <libdrizzle/drizzle_data.h>
 
29
#include <libdrizzle/local_infile.h>
 
30
 
26
31
#include "libdrizzle_priv.h"
27
32
 
28
33
#include <vio/violite.h>
35
40
#include <string.h>
36
41
#include <netdb.h>
37
42
#include <assert.h>
 
43
#include <pwd.h>
 
44
#include <sys/socket.h>
 
45
 
38
46
 
39
47
#define CONNECT_TIMEOUT 0
40
48
 
41
 
const char  *unknown_sqlstate= "HY000";
42
 
const char  *not_error_sqlstate= "00000";
43
 
const char  *cant_connect_sqlstate= "08001";
44
 
 
45
49
static bool drizzle_client_init= false;
46
50
unsigned int drizzle_server_last_errno;
47
51
 
48
52
/* Server error code and message */
49
53
char drizzle_server_last_error[DRIZZLE_ERRMSG_SIZE];
50
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
 
51
79
/****************************************************************************
52
80
  Init DRIZZLE structure or allocate one
53
81
****************************************************************************/
96
124
 
97
125
    if (ptr == NULL)
98
126
    {
99
 
      drizzle_set_error(NULL, CR_OUT_OF_MEMORY, unknown_sqlstate);
 
127
      drizzle_set_error(NULL, CR_OUT_OF_MEMORY, sqlstate_get_unknown());
100
128
      return 0;
101
129
    }
102
130
    memset(ptr, 0, sizeof(DRIZZLE));
108
136
  }
109
137
 
110
138
  ptr->options.connect_timeout= CONNECT_TIMEOUT;
111
 
  strcpy(ptr->net.sqlstate, not_error_sqlstate);
 
139
  strcpy(ptr->net.sqlstate, sqlstate_get_not_error());
112
140
 
113
141
  /*
114
142
    Only enable LOAD DATA INFILE by default if configured with
141
169
 
142
170
  return ptr;
143
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 >= (uint) (end+1 - (char*) net->read_pos))
 
367
    drizzle->server_capabilities=uint2korr(end);
 
368
  if (pkt_length >= (uint) (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 >= (uint) (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
 
144
569
/**************************************************************************
145
570
  Shut down connection
146
571
**************************************************************************/
159
584
}
160
585
 
161
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, (uint) field_count, 0)))
 
699
    return(1);
 
700
  drizzle->status= DRIZZLE_STATUS_GET_RESULT;
 
701
  drizzle->field_count= (uint) 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((uint) (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
 
162
821
/**
163
822
   Set the internal error message to DRIZZLE handler
164
823
 
205
864
 
206
865
   @param drizzle connection handle
207
866
   @param errcode   CR_* errcode, for client errors
208
 
   @param sqlstate  SQL standard sql state, unknown_sqlstate for the
 
867
   @param sqlstate  SQL standard sql state, sqlstate_get_unknown() for the
209
868
   majority of client errors.
210
869
   @param format    error message template, in sprintf format
211
870
   @param ...       variable number of arguments
229
888
 
230
889
  return;
231
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