~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzleclient/libdrizzle.c

  • Committer: Brian Aker
  • Date: 2009-02-07 21:33:55 UTC
  • Revision ID: brian@tangent.org-20090207213355-j2zrs4f569g0az9m
SmallĀ formattingĀ changes.

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 <drizzled/global.h>
 
21
#include "libdrizzle_priv.h"
 
22
 
 
23
#include "libdrizzle.h"
 
24
#include "errmsg.h"
 
25
#include "pack.h"
 
26
 
 
27
#include <sys/stat.h>
 
28
#include <signal.h>
 
29
#include <time.h>
 
30
#ifdef   HAVE_PWD_H
 
31
#include <pwd.h>
 
32
#endif
 
33
 
 
34
#include <sys/socket.h>
 
35
#include <netinet/in.h>
 
36
#include <arpa/inet.h>
 
37
#include <netdb.h>
 
38
#ifdef HAVE_SELECT_H
 
39
#include <select.h>
 
40
#endif
 
41
#ifdef HAVE_SYS_SELECT_H
 
42
#include <sys/select.h>
 
43
#endif
 
44
 
 
45
#ifdef HAVE_POLL
 
46
#include <sys/poll.h>
 
47
#endif
 
48
#ifdef HAVE_SYS_UN_H
 
49
#include <sys/un.h>
 
50
#endif
 
51
#ifndef INADDR_NONE
 
52
#define INADDR_NONE  -1
 
53
#endif
 
54
 
 
55
#include <stdlib.h>
 
56
#include <string.h>
 
57
#include <mystrings/utf8.h>
 
58
 
 
59
 
 
60
#undef net_buffer_length
 
61
#undef max_allowed_packet
 
62
 
 
63
uint32_t     net_buffer_length= 8192;
 
64
uint32_t    max_allowed_packet= 1024L*1024L*1024L;
 
65
 
 
66
unsigned int drizzle_port=0;
 
67
 
 
68
#include <errno.h>
 
69
 
 
70
 
 
71
static DRIZZLE_PARAMETERS drizzle_internal_parameters=
 
72
{&max_allowed_packet, &net_buffer_length, 0};
 
73
 
 
74
const DRIZZLE_PARAMETERS * drizzle_get_parameters(void)
 
75
{
 
76
  return &drizzle_internal_parameters;
 
77
}
 
78
 
 
79
unsigned int drizzle_get_default_port(void)
 
80
{
 
81
  return drizzle_port;
 
82
}
 
83
 
 
84
void drizzle_set_default_port(unsigned int port)
 
85
{
 
86
  drizzle_port= port;
 
87
}
 
88
 
 
89
/*
 
90
  Expand wildcard to a sql string
 
91
*/
 
92
 
 
93
static void
 
94
append_wild(char *to, char *end, const char *wild)
 
95
{
 
96
  end-=5;          /* Some extra */
 
97
  if (wild && wild[0])
 
98
  {
 
99
    to= strcpy(to," like '");
 
100
    to+= 7; /* strlen(" like '"); */
 
101
 
 
102
    while (*wild && to < end)
 
103
    {
 
104
      if (*wild == '\\' || *wild == '\'')
 
105
  *to++='\\';
 
106
      *to++= *wild++;
 
107
    }
 
108
    if (*wild)          /* Too small buffer */
 
109
      *to++='%';        /* Nicer this way */
 
110
    to[0]='\'';
 
111
    to[1]=0;
 
112
  }
 
113
}
 
114
 
 
115
/**************************************************************************
 
116
  Change user and database
 
117
**************************************************************************/
 
118
 
 
119
int cli_read_change_user_result(DRIZZLE *drizzle)
 
120
{
 
121
  uint32_t pkt_length;
 
122
 
 
123
  pkt_length= cli_safe_read(drizzle);
 
124
 
 
125
  if (pkt_length == packet_error)
 
126
    return 1;
 
127
 
 
128
  return 0;
 
129
}
 
130
 
 
131
bool drizzle_change_user(DRIZZLE *drizzle, const char *user,
 
132
                                 const char *passwd, const char *db)
 
133
{
 
134
  char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
 
135
  char *end= buff;
 
136
  int rc;
 
137
 
 
138
  /* Use an empty string instead of NULL. */
 
139
 
 
140
  if (!user)
 
141
    user="";
 
142
  if (!passwd)
 
143
    passwd="";
 
144
 
 
145
  /* Store user into the buffer */
 
146
  end= strncpy(end, user, USERNAME_LENGTH) + USERNAME_LENGTH + 1;
 
147
 
 
148
  /* write scrambled password according to server capabilities */
 
149
  if (passwd[0])
 
150
  {
 
151
    {
 
152
      *end++= SCRAMBLE_LENGTH;
 
153
      end+= SCRAMBLE_LENGTH;
 
154
    }
 
155
  }
 
156
  else
 
157
    *end++= '\0';                               /* empty password */
 
158
  /* Add database if needed */
 
159
  end= strncpy(end, db ? db : "", NAME_LEN) + NAME_LEN + 1;
 
160
 
 
161
  /* Add character set number. */
 
162
  if (drizzle->server_capabilities & CLIENT_SECURE_CONNECTION)
 
163
  {
 
164
    int2store(end, (uint16_t) 45); // utf8mb4 number from mystrings/ctype-utf8.c
 
165
    end+= 2;
 
166
  }
 
167
 
 
168
  /* Write authentication package */
 
169
  (void)simple_command(drizzle,COM_CHANGE_USER, (unsigned char*) buff, (uint32_t) (end-buff), 1);
 
170
 
 
171
  rc= (*drizzle->methods->read_change_user_result)(drizzle);
 
172
 
 
173
  if (rc == 0)
 
174
  {
 
175
    /* Free old connect information */
 
176
    if(drizzle->user)
 
177
      free(drizzle->user);
 
178
    if(drizzle->passwd)
 
179
      free(drizzle->passwd);
 
180
    if(drizzle->db)
 
181
      free(drizzle->db);
 
182
 
 
183
    /* alloc new connect information */
 
184
    drizzle->user= strdup(user);
 
185
    drizzle->passwd= strdup(passwd);
 
186
    drizzle->db= db ? strdup(db) : 0;
 
187
  }
 
188
 
 
189
  return(rc);
 
190
}
 
191
 
 
192
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
 
193
struct passwd *getpwuid(uid_t);
 
194
char* getlogin(void);
 
195
#endif
 
196
 
 
197
/**************************************************************************
 
198
  Do a query. If query returned rows, free old rows.
 
199
  Read data by drizzle_store_result or by repeat call of drizzle_fetch_row
 
200
**************************************************************************/
 
201
 
 
202
int
 
203
drizzle_query(DRIZZLE *drizzle, const char *query)
 
204
{
 
205
  return drizzle_real_query(drizzle,query, (uint32_t) strlen(query));
 
206
}
 
207
 
 
208
 
 
209
/**************************************************************************
 
210
  Return next field of the query results
 
211
**************************************************************************/
 
212
 
 
213
DRIZZLE_FIELD *
 
214
drizzle_fetch_field(DRIZZLE_RES *result)
 
215
{
 
216
  if (result->current_field >= result->field_count)
 
217
    return(NULL);
 
218
  return &result->fields[result->current_field++];
 
219
}
 
220
 
 
221
 
 
222
/**************************************************************************
 
223
  Move to a specific row and column
 
224
**************************************************************************/
 
225
 
 
226
void
 
227
drizzle_data_seek(DRIZZLE_RES *result, uint64_t row)
 
228
{
 
229
  DRIZZLE_ROWS  *tmp=0;
 
230
  if (result->data)
 
231
    for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
 
232
  result->current_row=0;
 
233
  result->data_cursor = tmp;
 
234
}
 
235
 
 
236
 
 
237
/*************************************************************************
 
238
  put the row or field cursor one a position one got from DRIZZLE_ROW_tell()
 
239
  This doesn't restore any data. The next drizzle_fetch_row or
 
240
  drizzle_fetch_field will return the next row or field after the last used
 
241
*************************************************************************/
 
242
 
 
243
DRIZZLE_ROW_OFFSET
 
244
drizzle_row_seek(DRIZZLE_RES *result, DRIZZLE_ROW_OFFSET row)
 
245
{
 
246
  DRIZZLE_ROW_OFFSET return_value=result->data_cursor;
 
247
  result->current_row= 0;
 
248
  result->data_cursor= row;
 
249
  return return_value;
 
250
}
 
251
 
 
252
 
 
253
DRIZZLE_FIELD_OFFSET
 
254
drizzle_field_seek(DRIZZLE_RES *result, DRIZZLE_FIELD_OFFSET field_offset)
 
255
{
 
256
  DRIZZLE_FIELD_OFFSET return_value=result->current_field;
 
257
  result->current_field=field_offset;
 
258
  return return_value;
 
259
}
 
260
 
 
261
 
 
262
/*****************************************************************************
 
263
  List all tables in a database
 
264
  If wild is given then only the tables matching wild is returned
 
265
*****************************************************************************/
 
266
 
 
267
DRIZZLE_RES *
 
268
drizzle_list_tables(DRIZZLE *drizzle, const char *wild)
 
269
{
 
270
  char buff[255];
 
271
  char *ptr= strcpy(buff, "show tables");
 
272
  ptr+= 11; /* strlen("show tables"); */
 
273
 
 
274
  append_wild(ptr,buff+sizeof(buff),wild);
 
275
  if (drizzle_query(drizzle,buff))
 
276
    return(0);
 
277
  return (drizzle_store_result(drizzle));
 
278
}
 
279
 
 
280
 
 
281
DRIZZLE_FIELD *cli_list_fields(DRIZZLE *drizzle)
 
282
{
 
283
  DRIZZLE_DATA *query;
 
284
  if (!(query= cli_read_rows(drizzle,(DRIZZLE_FIELD*) 0, 8)))
 
285
    return NULL;
 
286
 
 
287
  drizzle->field_count= (uint32_t) query->rows;
 
288
  return unpack_fields(query, drizzle->field_count, 1);
 
289
}
 
290
 
 
291
 
 
292
/**************************************************************************
 
293
  List all fields in a table
 
294
  If wild is given then only the fields matching wild is returned
 
295
  Instead of this use query:
 
296
  show fields in 'table' like "wild"
 
297
**************************************************************************/
 
298
 
 
299
DRIZZLE_RES *
 
300
drizzle_list_fields(DRIZZLE *drizzle, const char *table, const char *wild)
 
301
{
 
302
  DRIZZLE_RES   *result;
 
303
  DRIZZLE_FIELD *fields;
 
304
  char buff[257], *end;
 
305
 
 
306
  end= strncpy(buff, table, 128) + 128;
 
307
  end= strncpy(end+1, wild ? wild : "", 128) + 128;
 
308
 
 
309
  free_old_query(drizzle);
 
310
  if (simple_command(drizzle, COM_FIELD_LIST, (unsigned char*) buff,
 
311
                     (uint32_t) (end-buff), 1) ||
 
312
      !(fields= (*drizzle->methods->list_fields)(drizzle)))
 
313
    return(NULL);
 
314
 
 
315
  if (!(result = (DRIZZLE_RES *) malloc(sizeof(DRIZZLE_RES))))
 
316
    return(NULL);
 
317
 
 
318
  memset(result, 0, sizeof(DRIZZLE_RES));
 
319
 
 
320
  result->methods= drizzle->methods;
 
321
  drizzle->fields=0;
 
322
  result->field_count = drizzle->field_count;
 
323
  result->fields= fields;
 
324
  result->eof=1;
 
325
  return(result);
 
326
}
 
327
 
 
328
/* List all running processes (threads) in server */
 
329
 
 
330
DRIZZLE_RES *
 
331
drizzle_list_processes(DRIZZLE *drizzle)
 
332
{
 
333
  DRIZZLE_DATA *fields;
 
334
  uint32_t field_count;
 
335
  unsigned char *pos;
 
336
 
 
337
  if (simple_command(drizzle,COM_PROCESS_INFO,0,0,0))
 
338
    return(0);
 
339
  free_old_query(drizzle);
 
340
  pos=(unsigned char*) drizzle->net.read_pos;
 
341
  field_count=(uint32_t) net_field_length(&pos);
 
342
  if (!(fields = (*drizzle->methods->read_rows)(drizzle,(DRIZZLE_FIELD*) 0, 7)))
 
343
    return(NULL);
 
344
  if (!(drizzle->fields=unpack_fields(fields, field_count, 0)))
 
345
    return(0);
 
346
  drizzle->status=DRIZZLE_STATUS_GET_RESULT;
 
347
  drizzle->field_count=field_count;
 
348
  return(drizzle_store_result(drizzle));
 
349
}
 
350
 
 
351
 
 
352
int
 
353
drizzle_shutdown(DRIZZLE *drizzle)
 
354
{
 
355
  return(simple_command(drizzle, COM_SHUTDOWN, 0, 0, 0));
 
356
}
 
357
 
 
358
 
 
359
int
 
360
drizzle_refresh(DRIZZLE *drizzle, uint32_t options)
 
361
{
 
362
  unsigned char bits[1];
 
363
  bits[0]= (unsigned char) options;
 
364
  return(simple_command(drizzle, COM_REFRESH, bits, 1, 0));
 
365
}
 
366
 
 
367
 
 
368
int32_t
 
369
drizzle_kill(DRIZZLE *drizzle, uint32_t pid)
 
370
{
 
371
  unsigned char buff[4];
 
372
  int4store(buff,pid);
 
373
  return(simple_command(drizzle,COM_PROCESS_KILL,buff,sizeof(buff),0));
 
374
}
 
375
 
 
376
 
 
377
int
 
378
drizzle_set_server_option(DRIZZLE *drizzle, enum enum_drizzle_set_option option)
 
379
{
 
380
  unsigned char buff[2];
 
381
  int2store(buff, (uint32_t) option);
 
382
  return(simple_command(drizzle, COM_SET_OPTION, buff, sizeof(buff), 0));
 
383
}
 
384
 
 
385
 
 
386
const char *cli_read_statistics(DRIZZLE *drizzle)
 
387
{
 
388
  drizzle->net.read_pos[drizzle->packet_length]=0;  /* End of stat string */
 
389
  if (!drizzle->net.read_pos[0])
 
390
  {
 
391
    drizzle_set_error(drizzle, CR_WRONG_HOST_INFO, sqlstate_get_unknown());
 
392
    return drizzle->net.last_error;
 
393
  }
 
394
  return (char*) drizzle->net.read_pos;
 
395
}
 
396
 
 
397
 
 
398
int
 
399
drizzle_ping(DRIZZLE *drizzle)
 
400
{
 
401
  int res;
 
402
  res= simple_command(drizzle,COM_PING,0,0,0);
 
403
  if (res == CR_SERVER_LOST && drizzle->reconnect)
 
404
    res= simple_command(drizzle,COM_PING,0,0,0);
 
405
  return(res);
 
406
}
 
407
 
 
408
 
 
409
const char *
 
410
drizzle_get_server_info(const DRIZZLE *drizzle)
 
411
{
 
412
  return((char*) drizzle->server_version);
 
413
}
 
414
 
 
415
 
 
416
const char *
 
417
drizzle_get_host_info(const DRIZZLE *drizzle)
 
418
{
 
419
  return(drizzle->host_info);
 
420
}
 
421
 
 
422
 
 
423
uint32_t
 
424
drizzle_get_proto_info(const DRIZZLE *drizzle)
 
425
{
 
426
  return (drizzle->protocol_version);
 
427
}
 
428
 
 
429
const char *
 
430
drizzle_get_client_info(void)
 
431
{
 
432
  return (char*) VERSION;
 
433
}
 
434
 
 
435
uint32_t drizzle_get_client_version(void)
 
436
{
 
437
  return DRIZZLE_VERSION_ID;
 
438
}
 
439
 
 
440
bool drizzle_eof(const DRIZZLE_RES *res)
 
441
{
 
442
  return res->eof;
 
443
}
 
444
 
 
445
const DRIZZLE_FIELD * drizzle_fetch_field_direct(const DRIZZLE_RES *res, unsigned int fieldnr)
 
446
{
 
447
  return &(res)->fields[fieldnr];
 
448
}
 
449
 
 
450
const DRIZZLE_FIELD * drizzle_fetch_fields(const DRIZZLE_RES *res)
 
451
{
 
452
  return res->fields;
 
453
}
 
454
 
 
455
DRIZZLE_ROW_OFFSET drizzle_row_tell(const DRIZZLE_RES *res)
 
456
{
 
457
  return res->data_cursor;
 
458
}
 
459
 
 
460
DRIZZLE_FIELD_OFFSET drizzle_field_tell(const DRIZZLE_RES *res)
 
461
{
 
462
  return res->current_field;
 
463
}
 
464
 
 
465
/* DRIZZLE */
 
466
 
 
467
unsigned int drizzle_field_count(const DRIZZLE *drizzle)
 
468
{
 
469
  return drizzle->field_count;
 
470
}
 
471
 
 
472
uint64_t drizzle_affected_rows(const DRIZZLE *drizzle)
 
473
{
 
474
  return drizzle->affected_rows;
 
475
}
 
476
 
 
477
uint64_t drizzle_insert_id(const DRIZZLE *drizzle)
 
478
{
 
479
  return drizzle->insert_id;
 
480
}
 
481
 
 
482
const char * drizzle_sqlstate(const DRIZZLE *drizzle)
 
483
{
 
484
  return drizzle ? drizzle->net.sqlstate : sqlstate_get_cant_connect();
 
485
}
 
486
 
 
487
uint32_t drizzle_warning_count(const DRIZZLE *drizzle)
 
488
{
 
489
  return drizzle->warning_count;
 
490
}
 
491
 
 
492
const char * drizzle_info(const DRIZZLE *drizzle)
 
493
{
 
494
  return drizzle->info;
 
495
}
 
496
 
 
497
uint32_t drizzle_thread_id(const DRIZZLE *drizzle)
 
498
{
 
499
  return drizzle->thread_id;
 
500
}
 
501
 
 
502
/****************************************************************************
 
503
  Some support functions
 
504
****************************************************************************/
 
505
 
 
506
/*
 
507
  Functions called my my_net_init() to set some application specific variables
 
508
*/
 
509
 
 
510
void my_net_local_init(NET *net)
 
511
{
 
512
  net->max_packet=   (uint32_t) net_buffer_length;
 
513
  my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
 
514
  my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
 
515
  net->retry_count=  1;
 
516
  net->max_packet_size= (net_buffer_length > max_allowed_packet) ?
 
517
    net_buffer_length : max_allowed_packet;
 
518
}
 
519
 
 
520
/*
 
521
  Add escape characters to a string (blob?) to make it suitable for a insert
 
522
  to should at least have place for length*2+1 chars
 
523
  Returns the length of the to string
 
524
*/
 
525
 
 
526
uint32_t
 
527
drizzle_escape_string(char *to,const char *from, uint32_t length)
 
528
{
 
529
  const char *to_start= to;
 
530
  const char *end, *to_end=to_start + 2*length;
 
531
  bool overflow= false;
 
532
  for (end= from + length; from < end; from++)
 
533
  {
 
534
    uint32_t tmp_length;
 
535
    char escape= 0;
 
536
    if (!U8_IS_SINGLE(*from))
 
537
    {
 
538
      tmp_length= U8_LENGTH(*(uint32_t*)from);
 
539
      if (to + tmp_length > to_end)
 
540
      {
 
541
        overflow= true;
 
542
        break;
 
543
      }
 
544
      while (tmp_length--)
 
545
        *to++= *from++;
 
546
      from--;
 
547
      continue;
 
548
    }
 
549
    switch (*from) {
 
550
    case 0:                             /* Must be escaped for 'mysql' */
 
551
      escape= '0';
 
552
      break;
 
553
    case '\n':                          /* Must be escaped for logs */
 
554
      escape= 'n';
 
555
      break;
 
556
    case '\r':
 
557
      escape= 'r';
 
558
      break;
 
559
    case '\\':
 
560
      escape= '\\';
 
561
      break;
 
562
    case '\'':
 
563
      escape= '\'';
 
564
      break;
 
565
    case '"':                           /* Better safe than sorry */
 
566
      escape= '"';
 
567
      break;
 
568
    case '\032':                        /* This gives problems on Win32 */
 
569
      escape= 'Z';
 
570
      break;
 
571
    }
 
572
    if (escape)
 
573
    {
 
574
      if (to + 2 > to_end)
 
575
      {
 
576
        overflow= true;
 
577
        break;
 
578
      }
 
579
      *to++= '\\';
 
580
      *to++= escape;
 
581
    }
 
582
    else
 
583
    {
 
584
      if (to + 1 > to_end)
 
585
      {
 
586
        overflow= true;
 
587
        break;
 
588
      }
 
589
      *to++= *from;
 
590
    }
 
591
  }
 
592
  *to= 0;
 
593
  return overflow ? (size_t) -1 : (size_t) (to - to_start);
 
594
}
 
595
 
 
596
int cli_unbuffered_fetch(DRIZZLE *drizzle, char **row)
 
597
{
 
598
  if (packet_error == cli_safe_read(drizzle))
 
599
    return 1;
 
600
 
 
601
  *row= ((drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA) ? NULL :
 
602
   (char*) (drizzle->net.read_pos+1));
 
603
  return 0;
 
604
}
 
605
 
 
606
/********************************************************************
 
607
 Transactional APIs
 
608
*********************************************************************/
 
609
 
 
610
/*
 
611
  Commit the current transaction
 
612
*/
 
613
 
 
614
bool drizzle_commit(DRIZZLE *drizzle)
 
615
{
 
616
  return((bool) drizzle_real_query(drizzle, "commit", 6));
 
617
}
 
618
 
 
619
/*
 
620
  Rollback the current transaction
 
621
*/
 
622
 
 
623
bool drizzle_rollback(DRIZZLE *drizzle)
 
624
{
 
625
  return((bool) drizzle_real_query(drizzle, "rollback", 8));
 
626
}
 
627
 
 
628
 
 
629
/*
 
630
  Set autocommit to either true or false
 
631
*/
 
632
 
 
633
bool drizzle_autocommit(DRIZZLE *drizzle, bool auto_mode)
 
634
{
 
635
  return((bool) drizzle_real_query(drizzle, auto_mode ?
 
636
                                         "set autocommit=1":"set autocommit=0",
 
637
                                         16));
 
638
}
 
639
 
 
640
 
 
641
/********************************************************************
 
642
 Multi query execution + SPs APIs
 
643
*********************************************************************/
 
644
 
 
645
/*
 
646
  Returns true/false to indicate whether any more query results exist
 
647
  to be read using drizzle_next_result()
 
648
*/
 
649
 
 
650
bool drizzle_more_results(const DRIZZLE *drizzle)
 
651
{
 
652
  return (drizzle->server_status & SERVER_MORE_RESULTS_EXISTS) ? true:false;
 
653
}
 
654
 
 
655
 
 
656
/*
 
657
  Reads and returns the next query results
 
658
*/
 
659
int drizzle_next_result(DRIZZLE *drizzle)
 
660
{
 
661
  if (drizzle->status != DRIZZLE_STATUS_READY)
 
662
  {
 
663
    drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown());
 
664
    return(1);
 
665
  }
 
666
 
 
667
  net_clear_error(&drizzle->net);
 
668
  drizzle->affected_rows= ~(uint64_t) 0;
 
669
 
 
670
  if (drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
 
671
    return((*drizzle->methods->next_result)(drizzle));
 
672
 
 
673
  return(-1);        /* No more results */
 
674
}
 
675
 
 
676
 
 
677
DRIZZLE_RES * drizzle_use_result(DRIZZLE *drizzle)
 
678
{
 
679
  return (*drizzle->methods->use_result)(drizzle);
 
680
}
 
681
 
 
682
bool drizzle_read_query_result(DRIZZLE *drizzle)
 
683
{
 
684
  return (*drizzle->methods->read_query_result)(drizzle);
 
685
}
 
686