~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/libdrizzle.c

  • Committer: Monty Taylor
  • Date: 2008-08-16 21:06:22 UTC
  • Revision ID: monty@inaugust.com-20080816210622-zpnn13unyinqzn72
Updated po files.

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
 
 */
 
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
19
 
20
20
#include <drizzled/global.h>
21
 
#include "libdrizzle_priv.h"
22
 
 
23
 
#include <libdrizzle/libdrizzle.h>
24
 
#include <libdrizzle/pack.h>
25
 
#include <libdrizzle/errmsg.h>
 
21
#include <mysys/my_sys.h>
 
22
#include "my_time.h"
 
23
#include "drizzle.h"
 
24
#include "errmsg.h"
 
25
#include <vio/violite.h>
26
26
#include <sys/stat.h>
27
27
#include <signal.h>
28
28
#include <time.h>
51
51
#define INADDR_NONE  -1
52
52
#endif
53
53
 
54
 
#include <stdlib.h>
55
 
#include <string.h>
56
 
 
57
 
/* Borrowed from libicu header */
58
 
 
59
 
#define U8_IS_SINGLE(c) (((c)&0x80)==0)
60
 
#define U8_LENGTH(c) \
61
 
    ((uint32_t)(c)<=0x7f ? 1 : \
62
 
        ((uint32_t)(c)<=0x7ff ? 2 : \
63
 
            ((uint32_t)(c)<=0xd7ff ? 3 : \
64
 
                ((uint32_t)(c)<=0xdfff || (uint32_t)(c)>0x10ffff ? 0 : \
65
 
                    ((uint32_t)(c)<=0xffff ? 3 : 4)\
66
 
                ) \
67
 
            ) \
68
 
        ) \
69
 
    )
70
 
 
 
54
#include <sql_common.h>
 
55
#include "client_settings.h"
 
56
#include <drizzled/version.h>
71
57
 
72
58
#undef net_buffer_length
73
59
#undef max_allowed_packet
75
61
uint32_t     net_buffer_length= 8192;
76
62
uint32_t    max_allowed_packet= 1024L*1024L*1024L;
77
63
 
78
 
unsigned int drizzle_port=0;
79
 
 
80
64
#include <errno.h>
 
65
#define SOCKET_ERROR -1
 
66
 
 
67
/*
 
68
  If allowed through some configuration, then this needs to
 
69
  be changed
 
70
*/
 
71
#define MAX_LONG_DATA_LENGTH 8192
 
72
#define unsigned_field(A) ((A)->flags & UNSIGNED_FLAG)
81
73
 
82
74
 
83
75
static DRIZZLE_PARAMETERS drizzle_internal_parameters=
88
80
  return &drizzle_internal_parameters;
89
81
}
90
82
 
91
 
unsigned int drizzle_get_default_port(void)
92
 
{
93
 
  return drizzle_port;
94
 
}
95
 
 
96
 
void drizzle_set_default_port(unsigned int port)
97
 
{
98
 
  drizzle_port= port;
99
 
}
 
83
bool drizzle_thread_init()
 
84
{
 
85
  return my_thread_init();
 
86
}
 
87
 
 
88
void drizzle_thread_end()
 
89
{
 
90
  my_thread_end();
 
91
}
 
92
 
100
93
 
101
94
/*
102
95
  Expand wildcard to a sql string
125
118
}
126
119
 
127
120
/**************************************************************************
 
121
  Ignore SIGPIPE handler
 
122
   ARGSUSED
 
123
**************************************************************************/
 
124
 
 
125
sig_handler
 
126
my_pipe_sig_handler(int sig __attribute__((unused)))
 
127
{
 
128
#ifdef DONT_REMEMBER_SIGNAL
 
129
  (void) signal(SIGPIPE, my_pipe_sig_handler);
 
130
#endif
 
131
}
 
132
 
 
133
 
 
134
/**************************************************************************
128
135
  Change user and database
129
136
**************************************************************************/
130
137
 
133
140
  uint32_t pkt_length;
134
141
 
135
142
  pkt_length= cli_safe_read(drizzle);
136
 
 
 
143
  
137
144
  if (pkt_length == packet_error)
138
145
    return 1;
139
146
 
146
153
  char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
147
154
  char *end= buff;
148
155
  int rc;
 
156
  const CHARSET_INFO *saved_cs= drizzle->charset;
 
157
 
 
158
  /* Get the connection-default character set. */
 
159
 
 
160
  if (drizzle_init_character_set(drizzle))
 
161
  {
 
162
    drizzle->charset= saved_cs;
 
163
    return(true);
 
164
  }
149
165
 
150
166
  /* Use an empty string instead of NULL. */
151
167
 
171
187
  end= strncpy(end, db ? db : "", NAME_LEN) + NAME_LEN + 1;
172
188
 
173
189
  /* Add character set number. */
 
190
 
174
191
  if (drizzle->server_capabilities & CLIENT_SECURE_CONNECTION)
175
192
  {
176
 
    int2store(end, (uint16_t) 45); // utf8mb4 number from mystrings/ctype-utf8.c
 
193
    int2store(end, (ushort) drizzle->charset->number);
177
194
    end+= 2;
178
195
  }
179
196
 
180
197
  /* Write authentication package */
181
 
  (void)simple_command(drizzle,COM_CHANGE_USER, (unsigned char*) buff, (uint32_t) (end-buff), 1);
 
198
  (void)simple_command(drizzle,COM_CHANGE_USER, (uchar*) buff, (uint32_t) (end-buff), 1);
182
199
 
183
200
  rc= (*drizzle->methods->read_change_user_result)(drizzle);
184
201
 
197
214
    drizzle->passwd= strdup(passwd);
198
215
    drizzle->db= db ? strdup(db) : 0;
199
216
  }
 
217
  else
 
218
  {
 
219
    drizzle->charset= saved_cs;
 
220
  }
200
221
 
201
222
  return(rc);
202
223
}
214
235
int
215
236
drizzle_query(DRIZZLE *drizzle, const char *query)
216
237
{
217
 
  return drizzle_real_query(drizzle,query, (uint32_t) strlen(query));
 
238
  return drizzle_real_query(drizzle,query, (uint) strlen(query));
218
239
}
219
240
 
220
241
 
296
317
  if (!(query= cli_read_rows(drizzle,(DRIZZLE_FIELD*) 0, 8)))
297
318
    return NULL;
298
319
 
299
 
  drizzle->field_count= (uint32_t) query->rows;
300
 
  return unpack_fields(query, drizzle->field_count, 1);
 
320
  drizzle->field_count= (uint) query->rows;
 
321
  return unpack_fields(query,&drizzle->field_alloc, drizzle->field_count, 1);
301
322
}
302
323
 
303
324
 
319
340
  end= strncpy(end+1, wild ? wild : "", 128) + 128;
320
341
 
321
342
  free_old_query(drizzle);
322
 
  if (simple_command(drizzle, COM_FIELD_LIST, (unsigned char*) buff,
 
343
  if (simple_command(drizzle, COM_FIELD_LIST, (uchar*) buff,
323
344
                     (uint32_t) (end-buff), 1) ||
324
345
      !(fields= (*drizzle->methods->list_fields)(drizzle)))
325
346
    return(NULL);
330
351
  memset(result, 0, sizeof(DRIZZLE_RES));
331
352
 
332
353
  result->methods= drizzle->methods;
 
354
  result->field_alloc=drizzle->field_alloc;
333
355
  drizzle->fields=0;
334
356
  result->field_count = drizzle->field_count;
335
357
  result->fields= fields;
343
365
drizzle_list_processes(DRIZZLE *drizzle)
344
366
{
345
367
  DRIZZLE_DATA *fields;
346
 
  uint32_t field_count;
347
 
  unsigned char *pos;
 
368
  uint field_count;
 
369
  uchar *pos;
348
370
 
349
371
  if (simple_command(drizzle,COM_PROCESS_INFO,0,0,0))
350
372
    return(0);
351
373
  free_old_query(drizzle);
352
 
  pos=(unsigned char*) drizzle->net.read_pos;
353
 
  field_count=(uint32_t) net_field_length(&pos);
 
374
  pos=(uchar*) drizzle->net.read_pos;
 
375
  field_count=(uint) net_field_length(&pos);
354
376
  if (!(fields = (*drizzle->methods->read_rows)(drizzle,(DRIZZLE_FIELD*) 0, 7)))
355
377
    return(NULL);
356
 
  if (!(drizzle->fields=unpack_fields(fields, field_count, 0)))
 
378
  if (!(drizzle->fields=unpack_fields(fields,&drizzle->field_alloc,field_count,0)))
357
379
    return(0);
358
380
  drizzle->status=DRIZZLE_STATUS_GET_RESULT;
359
381
  drizzle->field_count=field_count;
362
384
 
363
385
 
364
386
int
365
 
drizzle_shutdown(DRIZZLE *drizzle)
 
387
drizzle_shutdown(DRIZZLE *drizzle, enum drizzle_enum_shutdown_level shutdown_level)
366
388
{
367
 
  return(simple_command(drizzle, COM_SHUTDOWN, 0, 0, 0));
 
389
  uchar level[1];
 
390
  level[0]= (uchar) shutdown_level;
 
391
  return(simple_command(drizzle, COM_SHUTDOWN, level, 1, 0));
368
392
}
369
393
 
370
394
 
371
395
int
372
 
drizzle_refresh(DRIZZLE *drizzle, uint32_t options)
 
396
drizzle_refresh(DRIZZLE *drizzle,uint options)
373
397
{
374
 
  unsigned char bits[1];
375
 
  bits[0]= (unsigned char) options;
 
398
  uchar bits[1];
 
399
  bits[0]= (uchar) options;
376
400
  return(simple_command(drizzle, COM_REFRESH, bits, 1, 0));
377
401
}
378
402
 
380
404
int32_t
381
405
drizzle_kill(DRIZZLE *drizzle, uint32_t pid)
382
406
{
383
 
  unsigned char buff[4];
 
407
  uchar buff[4];
384
408
  int4store(buff,pid);
385
409
  return(simple_command(drizzle,COM_PROCESS_KILL,buff,sizeof(buff),0));
386
410
}
389
413
int
390
414
drizzle_set_server_option(DRIZZLE *drizzle, enum enum_drizzle_set_option option)
391
415
{
392
 
  unsigned char buff[2];
393
 
  int2store(buff, (uint32_t) option);
 
416
  uchar buff[2];
 
417
  int2store(buff, (uint) option);
394
418
  return(simple_command(drizzle, COM_SET_OPTION, buff, sizeof(buff), 0));
395
419
}
396
420
 
400
424
  drizzle->net.read_pos[drizzle->packet_length]=0;  /* End of stat string */
401
425
  if (!drizzle->net.read_pos[0])
402
426
  {
403
 
    drizzle_set_error(drizzle, CR_WRONG_HOST_INFO, sqlstate_get_unknown());
 
427
    set_drizzle_error(drizzle, CR_WRONG_HOST_INFO, unknown_sqlstate);
404
428
    return drizzle->net.last_error;
405
429
  }
406
430
  return (char*) drizzle->net.read_pos;
432
456
}
433
457
 
434
458
 
435
 
uint32_t
 
459
uint
436
460
drizzle_get_proto_info(const DRIZZLE *drizzle)
437
461
{
438
462
  return (drizzle->protocol_version);
441
465
const char *
442
466
drizzle_get_client_info(void)
443
467
{
444
 
  return (char*) VERSION;
 
468
  return (char*) DRIZZLE_SERVER_VERSION;
445
469
}
446
470
 
447
471
uint32_t drizzle_get_client_version(void)
493
517
 
494
518
const char * drizzle_sqlstate(const DRIZZLE *drizzle)
495
519
{
496
 
  return drizzle ? drizzle->net.sqlstate : sqlstate_get_cant_connect();
 
520
  return drizzle ? drizzle->net.sqlstate : cant_connect_sqlstate;
497
521
}
498
522
 
499
523
uint32_t drizzle_warning_count(const DRIZZLE *drizzle)
511
535
  return drizzle->thread_id;
512
536
}
513
537
 
 
538
const char * drizzle_character_set_name(const DRIZZLE *drizzle)
 
539
{
 
540
  return drizzle->charset->csname;
 
541
}
 
542
 
 
543
void drizzle_get_character_set_info(const DRIZZLE *drizzle, MY_CHARSET_INFO *csinfo)
 
544
{
 
545
  csinfo->number   = drizzle->charset->number;
 
546
  csinfo->state    = drizzle->charset->state;
 
547
  csinfo->csname   = drizzle->charset->csname;
 
548
  csinfo->name     = drizzle->charset->name;
 
549
  csinfo->comment  = drizzle->charset->comment;
 
550
  csinfo->mbminlen = drizzle->charset->mbminlen;
 
551
  csinfo->mbmaxlen = drizzle->charset->mbmaxlen;
 
552
 
 
553
  if (drizzle->options.charset_dir)
 
554
    csinfo->dir = drizzle->options.charset_dir;
 
555
  else
 
556
    csinfo->dir = charsets_dir;
 
557
}
 
558
 
 
559
uint drizzle_thread_safe(void)
 
560
{
 
561
  return 1;
 
562
}
 
563
 
 
564
 
 
565
bool drizzle_embedded(void)
 
566
{
 
567
#ifdef EMBEDDED_LIBRARY
 
568
  return true;
 
569
#else
 
570
  return false;
 
571
#endif
 
572
}
 
573
 
514
574
/****************************************************************************
515
575
  Some support functions
516
576
****************************************************************************/
521
581
 
522
582
void my_net_local_init(NET *net)
523
583
{
524
 
  net->max_packet=   (uint32_t) net_buffer_length;
 
584
  net->max_packet=   (uint) net_buffer_length;
525
585
  my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
526
586
  my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
527
587
  net->retry_count=  1;
528
 
  net->max_packet_size= (net_buffer_length > max_allowed_packet) ?
529
 
    net_buffer_length : max_allowed_packet;
 
588
  net->max_packet_size= max(net_buffer_length, max_allowed_packet);
 
589
}
 
590
 
 
591
/*
 
592
  This function is used to create HEX string that you
 
593
  can use in a SQL statement in of the either ways:
 
594
    INSERT INTO blob_column VALUES (0xAABBCC);  (any DRIZZLE version)
 
595
    INSERT INTO blob_column VALUES (X'AABBCC'); 
 
596
  
 
597
  The string in "from" is encoded to a HEX string.
 
598
  The result is placed in "to" and a terminating null byte is appended.
 
599
  
 
600
  The string pointed to by "from" must be "length" bytes long.
 
601
  You must allocate the "to" buffer to be at least length*2+1 bytes long.
 
602
  Each character needs two bytes, and you need room for the terminating
 
603
  null byte. When drizzle_hex_string() returns, the contents of "to" will
 
604
  be a null-terminated string. The return value is the length of the
 
605
  encoded string, not including the terminating null character.
 
606
 
 
607
  The return value does not contain any leading 0x or a leading X' and
 
608
  trailing '. The caller must supply whichever of those is desired.
 
609
*/
 
610
 
 
611
uint32_t
 
612
drizzle_hex_string(char *to, const char *from, uint32_t length)
 
613
{
 
614
  char *to0= to;
 
615
  const char *end;
 
616
            
 
617
  for (end= from + length; from < end; from++)
 
618
  {
 
619
    *to++= _dig_vec_upper[((unsigned char) *from) >> 4];
 
620
    *to++= _dig_vec_upper[((unsigned char) *from) & 0x0F];
 
621
  }
 
622
  *to= '\0';
 
623
  return (uint32_t) (to-to0);
530
624
}
531
625
 
532
626
/*
538
632
uint32_t
539
633
drizzle_escape_string(char *to,const char *from, uint32_t length)
540
634
{
541
 
  const char *to_start= to;
542
 
  const char *end, *to_end=to_start + 2*length;
543
 
  bool overflow= false;
544
 
  for (end= from + length; from < end; from++)
 
635
  return escape_string_for_drizzle(default_charset_info, to, 0, from, length);
 
636
}
 
637
 
 
638
uint32_t
 
639
drizzle_real_escape_string(DRIZZLE *drizzle, char *to,const char *from,
 
640
       uint32_t length)
 
641
{
 
642
  if (drizzle->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES)
 
643
    return escape_quotes_for_drizzle(drizzle->charset, to, 0, from, length);
 
644
  return escape_string_for_drizzle(drizzle->charset, to, 0, from, length);
 
645
}
 
646
 
 
647
void
 
648
myodbc_remove_escape(const DRIZZLE *drizzle, char *name)
 
649
{
 
650
  char *to;
 
651
#ifdef USE_MB
 
652
  bool use_mb_flag= use_mb(drizzle->charset);
 
653
  char *end=NULL;
 
654
  if (use_mb_flag)
 
655
    for (end=name; *end ; end++) ;
 
656
#endif
 
657
 
 
658
  for (to=name ; *name ; name++)
545
659
  {
546
 
    uint32_t tmp_length;
547
 
    char escape= 0;
548
 
    if (!U8_IS_SINGLE(*from))
 
660
#ifdef USE_MB
 
661
    int l;
 
662
    if (use_mb_flag && (l = my_ismbchar( drizzle->charset, name , end ) ) )
549
663
    {
550
 
      tmp_length= U8_LENGTH(*from);
551
 
      if (to + tmp_length > to_end)
552
 
      {
553
 
        overflow= true;
554
 
        break;
555
 
      }
556
 
      while (tmp_length--)
557
 
        *to++= *from++;
558
 
      from--;
 
664
      while (l--)
 
665
        *to++ = *name++;
 
666
      name--;
559
667
      continue;
560
668
    }
561
 
    switch (*from) {
562
 
    case 0:                             /* Must be escaped for 'mysql' */
563
 
      escape= '0';
564
 
      break;
565
 
    case '\n':                          /* Must be escaped for logs */
566
 
      escape= 'n';
567
 
      break;
568
 
    case '\r':
569
 
      escape= 'r';
570
 
      break;
571
 
    case '\\':
572
 
      escape= '\\';
573
 
      break;
574
 
    case '\'':
575
 
      escape= '\'';
576
 
      break;
577
 
    case '"':                           /* Better safe than sorry */
578
 
      escape= '"';
579
 
      break;
580
 
    case '\032':                        /* This gives problems on Win32 */
581
 
      escape= 'Z';
582
 
      break;
583
 
    }
584
 
    if (escape)
585
 
    {
586
 
      if (to + 2 > to_end)
587
 
      {
588
 
        overflow= true;
589
 
        break;
590
 
      }
591
 
      *to++= '\\';
592
 
      *to++= escape;
593
 
    }
594
 
    else
595
 
    {
596
 
      if (to + 1 > to_end)
597
 
      {
598
 
        overflow= true;
599
 
        break;
600
 
      }
601
 
      *to++= *from;
602
 
    }
 
669
#endif
 
670
    if (*name == '\\' && name[1])
 
671
      name++;
 
672
    *to++= *name;
603
673
  }
604
 
  *to= 0;
605
 
  return overflow ? (size_t) -1 : (size_t) (to - to_start);
 
674
  *to=0;
606
675
}
607
676
 
608
677
int cli_unbuffered_fetch(DRIZZLE *drizzle, char **row)
672
741
{
673
742
  if (drizzle->status != DRIZZLE_STATUS_READY)
674
743
  {
675
 
    drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown());
 
744
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
676
745
    return(1);
677
746
  }
678
747