~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/libdrizzle.c

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

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