~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/libdrizzle.c

Cleanup around SAFEMALLOC

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2000-2004 DRIZZLE AB
 
2
 
 
3
   This program is free software; you can redistribute it and/or modify
 
4
   it under the terms of the GNU General Public License as published by
 
5
   the Free Software Foundation.
 
6
 
 
7
   There are special exceptions to the terms and conditions of the GPL as it
 
8
   is applied to this software. View the full text of the exception in file
 
9
   EXCEPTIONS-CLIENT in the directory of this software distribution.
 
10
 
 
11
   This program is distributed in the hope that it will be useful,
 
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
   GNU General Public License for more details.
 
15
 
 
16
   You should have received a copy of the GNU General Public License
 
17
   along with this program; if not, write to the Free Software
 
18
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
19
 
 
20
#include <drizzled/global.h>
 
21
#include <mysys/my_sys.h>
 
22
#include "drizzle.h"
 
23
#include "errmsg.h"
 
24
#include <sys/stat.h>
 
25
#include <signal.h>
 
26
#include <time.h>
 
27
#ifdef   HAVE_PWD_H
 
28
#include <pwd.h>
 
29
#endif
 
30
 
 
31
#include <sys/socket.h>
 
32
#include <netinet/in.h>
 
33
#include <arpa/inet.h>
 
34
#include <netdb.h>
 
35
#ifdef HAVE_SELECT_H
 
36
#include <select.h>
 
37
#endif
 
38
#ifdef HAVE_SYS_SELECT_H
 
39
#include <sys/select.h>
 
40
#endif
 
41
 
 
42
#ifdef HAVE_POLL
 
43
#include <sys/poll.h>
 
44
#endif
 
45
#ifdef HAVE_SYS_UN_H
 
46
#include <sys/un.h>
 
47
#endif
 
48
#ifndef INADDR_NONE
 
49
#define INADDR_NONE  -1
 
50
#endif
 
51
 
 
52
#include <sql_common.h>
 
53
#include "client_settings.h"
 
54
#include <drizzled/version.h>
 
55
 
 
56
#undef net_buffer_length
 
57
#undef max_allowed_packet
 
58
 
 
59
uint32_t     net_buffer_length= 8192;
 
60
uint32_t    max_allowed_packet= 1024L*1024L*1024L;
 
61
 
 
62
#include <errno.h>
 
63
#define SOCKET_ERROR -1
 
64
 
 
65
/*
 
66
  If allowed through some configuration, then this needs to
 
67
  be changed
 
68
*/
 
69
#define MAX_LONG_DATA_LENGTH 8192
 
70
#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
 
71
 
 
72
 
 
73
static DRIZZLE_PARAMETERS drizzle_internal_parameters=
 
74
{&max_allowed_packet, &net_buffer_length, 0};
 
75
 
 
76
const DRIZZLE_PARAMETERS * drizzle_get_parameters(void)
 
77
{
 
78
  return &drizzle_internal_parameters;
 
79
}
 
80
 
 
81
bool drizzle_thread_init()
 
82
{
 
83
  return my_thread_init();
 
84
}
 
85
 
 
86
void drizzle_thread_end()
 
87
{
 
88
  my_thread_end();
 
89
}
 
90
 
 
91
 
 
92
/*
 
93
  Expand wildcard to a sql string
 
94
*/
 
95
 
 
96
static void
 
97
append_wild(char *to, char *end, const char *wild)
 
98
{
 
99
  end-=5;          /* Some extra */
 
100
  if (wild && wild[0])
 
101
  {
 
102
    to= strcpy(to," like '");
 
103
    to+= 7; /* strlen(" like '"); */
 
104
 
 
105
    while (*wild && to < end)
 
106
    {
 
107
      if (*wild == '\\' || *wild == '\'')
 
108
  *to++='\\';
 
109
      *to++= *wild++;
 
110
    }
 
111
    if (*wild)          /* Too small buffer */
 
112
      *to++='%';        /* Nicer this way */
 
113
    to[0]='\'';
 
114
    to[1]=0;
 
115
  }
 
116
}
 
117
 
 
118
/**************************************************************************
 
119
  Ignore SIGPIPE handler
 
120
   ARGSUSED
 
121
**************************************************************************/
 
122
 
 
123
sig_handler
 
124
my_pipe_sig_handler(int sig __attribute__((unused)))
 
125
{
 
126
#ifdef DONT_REMEMBER_SIGNAL
 
127
  (void) signal(SIGPIPE, my_pipe_sig_handler);
 
128
#endif
 
129
}
 
130
 
 
131
 
 
132
/**************************************************************************
 
133
  Change user and database
 
134
**************************************************************************/
 
135
 
 
136
int cli_read_change_user_result(DRIZZLE *drizzle)
 
137
{
 
138
  uint32_t pkt_length;
 
139
 
 
140
  pkt_length= cli_safe_read(drizzle);
 
141
  
 
142
  if (pkt_length == packet_error)
 
143
    return 1;
 
144
 
 
145
  return 0;
 
146
}
 
147
 
 
148
bool drizzle_change_user(DRIZZLE *drizzle, const char *user,
 
149
                                 const char *passwd, const char *db)
 
150
{
 
151
  char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
 
152
  char *end= buff;
 
153
  int rc;
 
154
  const CHARSET_INFO *saved_cs= drizzle->charset;
 
155
 
 
156
  /* Get the connection-default character set. */
 
157
 
 
158
  if (drizzle_init_character_set(drizzle))
 
159
  {
 
160
    drizzle->charset= saved_cs;
 
161
    return(true);
 
162
  }
 
163
 
 
164
  /* Use an empty string instead of NULL. */
 
165
 
 
166
  if (!user)
 
167
    user="";
 
168
  if (!passwd)
 
169
    passwd="";
 
170
 
 
171
  /* Store user into the buffer */
 
172
  end= strncpy(end, user, USERNAME_LENGTH) + USERNAME_LENGTH + 1;
 
173
 
 
174
  /* write scrambled password according to server capabilities */
 
175
  if (passwd[0])
 
176
  {
 
177
    {
 
178
      *end++= SCRAMBLE_LENGTH;
 
179
      end+= SCRAMBLE_LENGTH;
 
180
    }
 
181
  }
 
182
  else
 
183
    *end++= '\0';                               /* empty password */
 
184
  /* Add database if needed */
 
185
  end= strncpy(end, db ? db : "", NAME_LEN) + NAME_LEN + 1;
 
186
 
 
187
  /* Add character set number. */
 
188
 
 
189
  if (drizzle->server_capabilities & CLIENT_SECURE_CONNECTION)
 
190
  {
 
191
    int2store(end, (ushort) drizzle->charset->number);
 
192
    end+= 2;
 
193
  }
 
194
 
 
195
  /* Write authentication package */
 
196
  (void)simple_command(drizzle,COM_CHANGE_USER, (uchar*) buff, (uint32_t) (end-buff), 1);
 
197
 
 
198
  rc= (*drizzle->methods->read_change_user_result)(drizzle);
 
199
 
 
200
  if (rc == 0)
 
201
  {
 
202
    /* Free old connect information */
 
203
    if(drizzle->user)
 
204
      free(drizzle->user);
 
205
    if(drizzle->passwd)
 
206
      free(drizzle->passwd);
 
207
    if(drizzle->db)
 
208
      free(drizzle->db);
 
209
 
 
210
    /* alloc new connect information */
 
211
    drizzle->user= strdup(user);
 
212
    drizzle->passwd= strdup(passwd);
 
213
    drizzle->db= db ? strdup(db) : 0;
 
214
  }
 
215
  else
 
216
  {
 
217
    drizzle->charset= saved_cs;
 
218
  }
 
219
 
 
220
  return(rc);
 
221
}
 
222
 
 
223
#if defined(HAVE_GETPWUID) && defined(NO_GETPWUID_DECL)
 
224
struct passwd *getpwuid(uid_t);
 
225
char* getlogin(void);
 
226
#endif
 
227
 
 
228
/**************************************************************************
 
229
  Do a query. If query returned rows, free old rows.
 
230
  Read data by drizzle_store_result or by repeat call of drizzle_fetch_row
 
231
**************************************************************************/
 
232
 
 
233
int
 
234
drizzle_query(DRIZZLE *drizzle, const char *query)
 
235
{
 
236
  return drizzle_real_query(drizzle,query, (uint) strlen(query));
 
237
}
 
238
 
 
239
 
 
240
/**************************************************************************
 
241
  Return next field of the query results
 
242
**************************************************************************/
 
243
 
 
244
DRIZZLE_FIELD *
 
245
drizzle_fetch_field(DRIZZLE_RES *result)
 
246
{
 
247
  if (result->current_field >= result->field_count)
 
248
    return(NULL);
 
249
  return &result->fields[result->current_field++];
 
250
}
 
251
 
 
252
 
 
253
/**************************************************************************
 
254
  Move to a specific row and column
 
255
**************************************************************************/
 
256
 
 
257
void
 
258
drizzle_data_seek(DRIZZLE_RES *result, uint64_t row)
 
259
{
 
260
  DRIZZLE_ROWS  *tmp=0;
 
261
  if (result->data)
 
262
    for (tmp=result->data->data; row-- && tmp ; tmp = tmp->next) ;
 
263
  result->current_row=0;
 
264
  result->data_cursor = tmp;
 
265
}
 
266
 
 
267
 
 
268
/*************************************************************************
 
269
  put the row or field cursor one a position one got from DRIZZLE_ROW_tell()
 
270
  This doesn't restore any data. The next drizzle_fetch_row or
 
271
  drizzle_fetch_field will return the next row or field after the last used
 
272
*************************************************************************/
 
273
 
 
274
DRIZZLE_ROW_OFFSET
 
275
drizzle_row_seek(DRIZZLE_RES *result, DRIZZLE_ROW_OFFSET row)
 
276
{
 
277
  DRIZZLE_ROW_OFFSET return_value=result->data_cursor;
 
278
  result->current_row= 0;
 
279
  result->data_cursor= row;
 
280
  return return_value;
 
281
}
 
282
 
 
283
 
 
284
DRIZZLE_FIELD_OFFSET
 
285
drizzle_field_seek(DRIZZLE_RES *result, DRIZZLE_FIELD_OFFSET field_offset)
 
286
{
 
287
  DRIZZLE_FIELD_OFFSET return_value=result->current_field;
 
288
  result->current_field=field_offset;
 
289
  return return_value;
 
290
}
 
291
 
 
292
 
 
293
/*****************************************************************************
 
294
  List all tables in a database
 
295
  If wild is given then only the tables matching wild is returned
 
296
*****************************************************************************/
 
297
 
 
298
DRIZZLE_RES *
 
299
drizzle_list_tables(DRIZZLE *drizzle, const char *wild)
 
300
{
 
301
  char buff[255];
 
302
  char *ptr= strcpy(buff, "show tables");
 
303
  ptr+= 11; /* strlen("show tables"); */
 
304
 
 
305
  append_wild(ptr,buff+sizeof(buff),wild);
 
306
  if (drizzle_query(drizzle,buff))
 
307
    return(0);
 
308
  return (drizzle_store_result(drizzle));
 
309
}
 
310
 
 
311
 
 
312
DRIZZLE_FIELD *cli_list_fields(DRIZZLE *drizzle)
 
313
{
 
314
  DRIZZLE_DATA *query;
 
315
  if (!(query= cli_read_rows(drizzle,(DRIZZLE_FIELD*) 0, 8)))
 
316
    return NULL;
 
317
 
 
318
  drizzle->field_count= (uint) query->rows;
 
319
  return unpack_fields(query,&drizzle->field_alloc, drizzle->field_count, 1);
 
320
}
 
321
 
 
322
 
 
323
/**************************************************************************
 
324
  List all fields in a table
 
325
  If wild is given then only the fields matching wild is returned
 
326
  Instead of this use query:
 
327
  show fields in 'table' like "wild"
 
328
**************************************************************************/
 
329
 
 
330
DRIZZLE_RES *
 
331
drizzle_list_fields(DRIZZLE *drizzle, const char *table, const char *wild)
 
332
{
 
333
  DRIZZLE_RES   *result;
 
334
  DRIZZLE_FIELD *fields;
 
335
  char buff[257], *end;
 
336
 
 
337
  end= strncpy(buff, table, 128) + 128;
 
338
  end= strncpy(end+1, wild ? wild : "", 128) + 128;
 
339
 
 
340
  free_old_query(drizzle);
 
341
  if (simple_command(drizzle, COM_FIELD_LIST, (uchar*) buff,
 
342
                     (uint32_t) (end-buff), 1) ||
 
343
      !(fields= (*drizzle->methods->list_fields)(drizzle)))
 
344
    return(NULL);
 
345
 
 
346
  if (!(result = (DRIZZLE_RES *) malloc(sizeof(DRIZZLE_RES))))
 
347
    return(NULL);
 
348
 
 
349
  memset(result, 0, sizeof(DRIZZLE_RES));
 
350
 
 
351
  result->methods= drizzle->methods;
 
352
  result->field_alloc=drizzle->field_alloc;
 
353
  drizzle->fields=0;
 
354
  result->field_count = drizzle->field_count;
 
355
  result->fields= fields;
 
356
  result->eof=1;
 
357
  return(result);
 
358
}
 
359
 
 
360
/* List all running processes (threads) in server */
 
361
 
 
362
DRIZZLE_RES *
 
363
drizzle_list_processes(DRIZZLE *drizzle)
 
364
{
 
365
  DRIZZLE_DATA *fields;
 
366
  uint field_count;
 
367
  uchar *pos;
 
368
 
 
369
  if (simple_command(drizzle,COM_PROCESS_INFO,0,0,0))
 
370
    return(0);
 
371
  free_old_query(drizzle);
 
372
  pos=(uchar*) drizzle->net.read_pos;
 
373
  field_count=(uint) net_field_length(&pos);
 
374
  if (!(fields = (*drizzle->methods->read_rows)(drizzle,(DRIZZLE_FIELD*) 0, 7)))
 
375
    return(NULL);
 
376
  if (!(drizzle->fields=unpack_fields(fields,&drizzle->field_alloc,field_count,0)))
 
377
    return(0);
 
378
  drizzle->status=DRIZZLE_STATUS_GET_RESULT;
 
379
  drizzle->field_count=field_count;
 
380
  return(drizzle_store_result(drizzle));
 
381
}
 
382
 
 
383
 
 
384
int
 
385
drizzle_shutdown(DRIZZLE *drizzle, enum drizzle_enum_shutdown_level shutdown_level)
 
386
{
 
387
  uchar level[1];
 
388
  level[0]= (uchar) shutdown_level;
 
389
  return(simple_command(drizzle, COM_SHUTDOWN, level, 1, 0));
 
390
}
 
391
 
 
392
 
 
393
int
 
394
drizzle_refresh(DRIZZLE *drizzle,uint options)
 
395
{
 
396
  uchar bits[1];
 
397
  bits[0]= (uchar) options;
 
398
  return(simple_command(drizzle, COM_REFRESH, bits, 1, 0));
 
399
}
 
400
 
 
401
 
 
402
int32_t
 
403
drizzle_kill(DRIZZLE *drizzle, uint32_t pid)
 
404
{
 
405
  uchar buff[4];
 
406
  int4store(buff,pid);
 
407
  return(simple_command(drizzle,COM_PROCESS_KILL,buff,sizeof(buff),0));
 
408
}
 
409
 
 
410
 
 
411
int
 
412
drizzle_set_server_option(DRIZZLE *drizzle, enum enum_drizzle_set_option option)
 
413
{
 
414
  uchar buff[2];
 
415
  int2store(buff, (uint) option);
 
416
  return(simple_command(drizzle, COM_SET_OPTION, buff, sizeof(buff), 0));
 
417
}
 
418
 
 
419
 
 
420
const char *cli_read_statistics(DRIZZLE *drizzle)
 
421
{
 
422
  drizzle->net.read_pos[drizzle->packet_length]=0;  /* End of stat string */
 
423
  if (!drizzle->net.read_pos[0])
 
424
  {
 
425
    set_drizzle_error(drizzle, CR_WRONG_HOST_INFO, unknown_sqlstate);
 
426
    return drizzle->net.last_error;
 
427
  }
 
428
  return (char*) drizzle->net.read_pos;
 
429
}
 
430
 
 
431
 
 
432
int
 
433
drizzle_ping(DRIZZLE *drizzle)
 
434
{
 
435
  int res;
 
436
  res= simple_command(drizzle,COM_PING,0,0,0);
 
437
  if (res == CR_SERVER_LOST && drizzle->reconnect)
 
438
    res= simple_command(drizzle,COM_PING,0,0,0);
 
439
  return(res);
 
440
}
 
441
 
 
442
 
 
443
const char *
 
444
drizzle_get_server_info(const DRIZZLE *drizzle)
 
445
{
 
446
  return((char*) drizzle->server_version);
 
447
}
 
448
 
 
449
 
 
450
const char *
 
451
drizzle_get_host_info(const DRIZZLE *drizzle)
 
452
{
 
453
  return(drizzle->host_info);
 
454
}
 
455
 
 
456
 
 
457
uint
 
458
drizzle_get_proto_info(const DRIZZLE *drizzle)
 
459
{
 
460
  return (drizzle->protocol_version);
 
461
}
 
462
 
 
463
const char *
 
464
drizzle_get_client_info(void)
 
465
{
 
466
  return (char*) DRIZZLE_SERVER_VERSION;
 
467
}
 
468
 
 
469
uint32_t drizzle_get_client_version(void)
 
470
{
 
471
  return DRIZZLE_VERSION_ID;
 
472
}
 
473
 
 
474
bool drizzle_eof(const DRIZZLE_RES *res)
 
475
{
 
476
  return res->eof;
 
477
}
 
478
 
 
479
const DRIZZLE_FIELD * drizzle_fetch_field_direct(const DRIZZLE_RES *res, unsigned int fieldnr)
 
480
{
 
481
  return &(res)->fields[fieldnr];
 
482
}
 
483
 
 
484
const DRIZZLE_FIELD * drizzle_fetch_fields(const DRIZZLE_RES *res)
 
485
{
 
486
  return res->fields;
 
487
}
 
488
 
 
489
DRIZZLE_ROW_OFFSET drizzle_row_tell(const DRIZZLE_RES *res)
 
490
{
 
491
  return res->data_cursor;
 
492
}
 
493
 
 
494
DRIZZLE_FIELD_OFFSET drizzle_field_tell(const DRIZZLE_RES *res)
 
495
{
 
496
  return res->current_field;
 
497
}
 
498
 
 
499
/* DRIZZLE */
 
500
 
 
501
unsigned int drizzle_field_count(const DRIZZLE *drizzle)
 
502
{
 
503
  return drizzle->field_count;
 
504
}
 
505
 
 
506
uint64_t drizzle_affected_rows(const DRIZZLE *drizzle)
 
507
{
 
508
  return drizzle->affected_rows;
 
509
}
 
510
 
 
511
uint64_t drizzle_insert_id(const DRIZZLE *drizzle)
 
512
{
 
513
  return drizzle->insert_id;
 
514
}
 
515
 
 
516
const char * drizzle_sqlstate(const DRIZZLE *drizzle)
 
517
{
 
518
  return drizzle ? drizzle->net.sqlstate : cant_connect_sqlstate;
 
519
}
 
520
 
 
521
uint32_t drizzle_warning_count(const DRIZZLE *drizzle)
 
522
{
 
523
  return drizzle->warning_count;
 
524
}
 
525
 
 
526
const char * drizzle_info(const DRIZZLE *drizzle)
 
527
{
 
528
  return drizzle->info;
 
529
}
 
530
 
 
531
uint32_t drizzle_thread_id(const DRIZZLE *drizzle)
 
532
{
 
533
  return drizzle->thread_id;
 
534
}
 
535
 
 
536
const char * drizzle_character_set_name(const DRIZZLE *drizzle)
 
537
{
 
538
  return drizzle->charset->csname;
 
539
}
 
540
 
 
541
void drizzle_get_character_set_info(const DRIZZLE *drizzle, MY_CHARSET_INFO *csinfo)
 
542
{
 
543
  csinfo->number   = drizzle->charset->number;
 
544
  csinfo->state    = drizzle->charset->state;
 
545
  csinfo->csname   = drizzle->charset->csname;
 
546
  csinfo->name     = drizzle->charset->name;
 
547
  csinfo->comment  = drizzle->charset->comment;
 
548
  csinfo->mbminlen = drizzle->charset->mbminlen;
 
549
  csinfo->mbmaxlen = drizzle->charset->mbmaxlen;
 
550
 
 
551
  if (drizzle->options.charset_dir)
 
552
    csinfo->dir = drizzle->options.charset_dir;
 
553
  else
 
554
    csinfo->dir = charsets_dir;
 
555
}
 
556
 
 
557
uint drizzle_thread_safe(void)
 
558
{
 
559
  return 1;
 
560
}
 
561
 
 
562
 
 
563
bool drizzle_embedded(void)
 
564
{
 
565
  return false;
 
566
}
 
567
 
 
568
/****************************************************************************
 
569
  Some support functions
 
570
****************************************************************************/
 
571
 
 
572
/*
 
573
  Functions called my my_net_init() to set some application specific variables
 
574
*/
 
575
 
 
576
void my_net_local_init(NET *net)
 
577
{
 
578
  net->max_packet=   (uint) net_buffer_length;
 
579
  my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
 
580
  my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
 
581
  net->retry_count=  1;
 
582
  net->max_packet_size= max(net_buffer_length, max_allowed_packet);
 
583
}
 
584
 
 
585
/*
 
586
  This function is used to create HEX string that you
 
587
  can use in a SQL statement in of the either ways:
 
588
    INSERT INTO blob_column VALUES (0xAABBCC);  (any DRIZZLE version)
 
589
    INSERT INTO blob_column VALUES (X'AABBCC'); 
 
590
  
 
591
  The string in "from" is encoded to a HEX string.
 
592
  The result is placed in "to" and a terminating null byte is appended.
 
593
  
 
594
  The string pointed to by "from" must be "length" bytes long.
 
595
  You must allocate the "to" buffer to be at least length*2+1 bytes long.
 
596
  Each character needs two bytes, and you need room for the terminating
 
597
  null byte. When drizzle_hex_string() returns, the contents of "to" will
 
598
  be a null-terminated string. The return value is the length of the
 
599
  encoded string, not including the terminating null character.
 
600
 
 
601
  The return value does not contain any leading 0x or a leading X' and
 
602
  trailing '. The caller must supply whichever of those is desired.
 
603
*/
 
604
 
 
605
uint32_t
 
606
drizzle_hex_string(char *to, const char *from, uint32_t length)
 
607
{
 
608
  char *to0= to;
 
609
  const char *end;
 
610
            
 
611
  for (end= from + length; from < end; from++)
 
612
  {
 
613
    *to++= _dig_vec_upper[((unsigned char) *from) >> 4];
 
614
    *to++= _dig_vec_upper[((unsigned char) *from) & 0x0F];
 
615
  }
 
616
  *to= '\0';
 
617
  return (uint32_t) (to-to0);
 
618
}
 
619
 
 
620
/*
 
621
  Add escape characters to a string (blob?) to make it suitable for a insert
 
622
  to should at least have place for length*2+1 chars
 
623
  Returns the length of the to string
 
624
*/
 
625
 
 
626
uint32_t
 
627
drizzle_escape_string(char *to,const char *from, uint32_t length)
 
628
{
 
629
  return escape_string_for_drizzle(default_charset_info, to, 0, from, length);
 
630
}
 
631
 
 
632
uint32_t
 
633
drizzle_real_escape_string(DRIZZLE *drizzle, char *to,const char *from,
 
634
       uint32_t length)
 
635
{
 
636
  if (drizzle->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
 
637
    return escape_quotes_for_drizzle(drizzle->charset, to, 0, from, length);
 
638
  return escape_string_for_drizzle(drizzle->charset, to, 0, from, length);
 
639
}
 
640
 
 
641
void
 
642
myodbc_remove_escape(const DRIZZLE *drizzle, char *name)
 
643
{
 
644
  char *to;
 
645
#ifdef USE_MB
 
646
  bool use_mb_flag= use_mb(drizzle->charset);
 
647
  char *end=NULL;
 
648
  if (use_mb_flag)
 
649
    for (end=name; *end ; end++) ;
 
650
#endif
 
651
 
 
652
  for (to=name ; *name ; name++)
 
653
  {
 
654
#ifdef USE_MB
 
655
    int l;
 
656
    if (use_mb_flag && (l = my_ismbchar( drizzle->charset, name , end ) ) )
 
657
    {
 
658
      while (l--)
 
659
        *to++ = *name++;
 
660
      name--;
 
661
      continue;
 
662
    }
 
663
#endif
 
664
    if (*name == '\\' && name[1])
 
665
      name++;
 
666
    *to++= *name;
 
667
  }
 
668
  *to=0;
 
669
}
 
670
 
 
671
int cli_unbuffered_fetch(DRIZZLE *drizzle, char **row)
 
672
{
 
673
  if (packet_error == cli_safe_read(drizzle))
 
674
    return 1;
 
675
 
 
676
  *row= ((drizzle->net.read_pos[0] == DRIZZLE_PROTOCOL_NO_MORE_DATA) ? NULL :
 
677
   (char*) (drizzle->net.read_pos+1));
 
678
  return 0;
 
679
}
 
680
 
 
681
/********************************************************************
 
682
 Transactional APIs
 
683
*********************************************************************/
 
684
 
 
685
/*
 
686
  Commit the current transaction
 
687
*/
 
688
 
 
689
bool drizzle_commit(DRIZZLE *drizzle)
 
690
{
 
691
  return((bool) drizzle_real_query(drizzle, "commit", 6));
 
692
}
 
693
 
 
694
/*
 
695
  Rollback the current transaction
 
696
*/
 
697
 
 
698
bool drizzle_rollback(DRIZZLE *drizzle)
 
699
{
 
700
  return((bool) drizzle_real_query(drizzle, "rollback", 8));
 
701
}
 
702
 
 
703
 
 
704
/*
 
705
  Set autocommit to either true or false
 
706
*/
 
707
 
 
708
bool drizzle_autocommit(DRIZZLE *drizzle, bool auto_mode)
 
709
{
 
710
  return((bool) drizzle_real_query(drizzle, auto_mode ?
 
711
                                         "set autocommit=1":"set autocommit=0",
 
712
                                         16));
 
713
}
 
714
 
 
715
 
 
716
/********************************************************************
 
717
 Multi query execution + SPs APIs
 
718
*********************************************************************/
 
719
 
 
720
/*
 
721
  Returns true/false to indicate whether any more query results exist
 
722
  to be read using drizzle_next_result()
 
723
*/
 
724
 
 
725
bool drizzle_more_results(const DRIZZLE *drizzle)
 
726
{
 
727
  return (drizzle->server_status & SERVER_MORE_RESULTS_EXISTS) ? true:false;
 
728
}
 
729
 
 
730
 
 
731
/*
 
732
  Reads and returns the next query results
 
733
*/
 
734
int drizzle_next_result(DRIZZLE *drizzle)
 
735
{
 
736
  if (drizzle->status != DRIZZLE_STATUS_READY)
 
737
  {
 
738
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
739
    return(1);
 
740
  }
 
741
 
 
742
  net_clear_error(&drizzle->net);
 
743
  drizzle->affected_rows= ~(uint64_t) 0;
 
744
 
 
745
  if (drizzle->server_status & SERVER_MORE_RESULTS_EXISTS)
 
746
    return((*drizzle->methods->next_result)(drizzle));
 
747
 
 
748
  return(-1);        /* No more results */
 
749
}
 
750
 
 
751
 
 
752
DRIZZLE_RES * drizzle_use_result(DRIZZLE *drizzle)
 
753
{
 
754
  return (*drizzle->methods->use_result)(drizzle);
 
755
}
 
756
 
 
757
bool drizzle_read_query_result(DRIZZLE *drizzle)
 
758
{
 
759
  return (*drizzle->methods->read_query_result)(drizzle);
 
760
}
 
761