~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/libdrizzle.c

  • Committer: Monty Taylor
  • Date: 2008-08-01 22:33:44 UTC
  • mto: (236.1.42 codestyle)
  • mto: This revision was merged to the branch mainline in revision 261.
  • Revision ID: monty@inaugust.com-20080801223344-vzhlflfmtijp1imv
First pass at gettexizing the error messages.

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