~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to libdrizzle/libdrizzle.c

Merged in changes from Andrey.

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"
 
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 "libdrizzle.h"
 
21
#include "libdrizzle_priv.h"
23
22
#include "errmsg.h"
24
23
#include <sys/stat.h>
25
24
#include <signal.h>
49
48
#define INADDR_NONE  -1
50
49
#endif
51
50
 
 
51
#include <stdlib.h>
 
52
#include <string.h>
 
53
 
52
54
#include <sql_common.h>
53
 
#include "client_settings.h"
54
55
#include <drizzled/version.h>
55
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
 
 
71
 
56
72
#undef net_buffer_length
57
73
#undef max_allowed_packet
58
74
 
59
75
uint32_t     net_buffer_length= 8192;
60
76
uint32_t    max_allowed_packet= 1024L*1024L*1024L;
61
77
 
 
78
unsigned int drizzle_port=0;
 
79
 
62
80
#include <errno.h>
63
81
#define SOCKET_ERROR -1
64
82
 
78
96
  return &drizzle_internal_parameters;
79
97
}
80
98
 
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
 
 
 
99
unsigned int drizzle_get_default_port(void)
 
100
{
 
101
  return drizzle_port;
 
102
}
 
103
 
 
104
void drizzle_set_default_port(unsigned int port)
 
105
{
 
106
  drizzle_port= port;
 
107
}
91
108
 
92
109
/*
93
110
  Expand wildcard to a sql string
116
133
}
117
134
 
118
135
/**************************************************************************
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
136
  Change user and database
134
137
**************************************************************************/
135
138
 
151
154
  char buff[USERNAME_LENGTH+SCRAMBLED_PASSWORD_CHAR_LENGTH+NAME_LEN+2];
152
155
  char *end= buff;
153
156
  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
157
 
164
158
  /* Use an empty string instead of NULL. */
165
159
 
185
179
  end= strncpy(end, db ? db : "", NAME_LEN) + NAME_LEN + 1;
186
180
 
187
181
  /* Add character set number. */
188
 
 
189
182
  if (drizzle->server_capabilities & CLIENT_SECURE_CONNECTION)
190
183
  {
191
 
    int2store(end, (ushort) drizzle->charset->number);
 
184
    int2store(end, (uint16_t) 45); // utf8mb4 number from mystrings/ctype-utf8.c
192
185
    end+= 2;
193
186
  }
194
187
 
195
188
  /* Write authentication package */
196
 
  (void)simple_command(drizzle,COM_CHANGE_USER, (uchar*) buff, (uint32_t) (end-buff), 1);
 
189
  (void)simple_command(drizzle,COM_CHANGE_USER, (unsigned char*) buff, (uint32_t) (end-buff), 1);
197
190
 
198
191
  rc= (*drizzle->methods->read_change_user_result)(drizzle);
199
192
 
212
205
    drizzle->passwd= strdup(passwd);
213
206
    drizzle->db= db ? strdup(db) : 0;
214
207
  }
215
 
  else
216
 
  {
217
 
    drizzle->charset= saved_cs;
218
 
  }
219
208
 
220
209
  return(rc);
221
210
}
233
222
int
234
223
drizzle_query(DRIZZLE *drizzle, const char *query)
235
224
{
236
 
  return drizzle_real_query(drizzle,query, (uint) strlen(query));
 
225
  return drizzle_real_query(drizzle,query, (uint32_t) strlen(query));
237
226
}
238
227
 
239
228
 
315
304
  if (!(query= cli_read_rows(drizzle,(DRIZZLE_FIELD*) 0, 8)))
316
305
    return NULL;
317
306
 
318
 
  drizzle->field_count= (uint) query->rows;
319
 
  return unpack_fields(query,&drizzle->field_alloc, drizzle->field_count, 1);
 
307
  drizzle->field_count= (uint32_t) query->rows;
 
308
  return unpack_fields(query, drizzle->field_count, 1);
320
309
}
321
310
 
322
311
 
338
327
  end= strncpy(end+1, wild ? wild : "", 128) + 128;
339
328
 
340
329
  free_old_query(drizzle);
341
 
  if (simple_command(drizzle, COM_FIELD_LIST, (uchar*) buff,
 
330
  if (simple_command(drizzle, COM_FIELD_LIST, (unsigned char*) buff,
342
331
                     (uint32_t) (end-buff), 1) ||
343
332
      !(fields= (*drizzle->methods->list_fields)(drizzle)))
344
333
    return(NULL);
349
338
  memset(result, 0, sizeof(DRIZZLE_RES));
350
339
 
351
340
  result->methods= drizzle->methods;
352
 
  result->field_alloc=drizzle->field_alloc;
353
341
  drizzle->fields=0;
354
342
  result->field_count = drizzle->field_count;
355
343
  result->fields= fields;
363
351
drizzle_list_processes(DRIZZLE *drizzle)
364
352
{
365
353
  DRIZZLE_DATA *fields;
366
 
  uint field_count;
367
 
  uchar *pos;
 
354
  uint32_t field_count;
 
355
  unsigned char *pos;
368
356
 
369
357
  if (simple_command(drizzle,COM_PROCESS_INFO,0,0,0))
370
358
    return(0);
371
359
  free_old_query(drizzle);
372
 
  pos=(uchar*) drizzle->net.read_pos;
373
 
  field_count=(uint) net_field_length(&pos);
 
360
  pos=(unsigned char*) drizzle->net.read_pos;
 
361
  field_count=(uint32_t) net_field_length(&pos);
374
362
  if (!(fields = (*drizzle->methods->read_rows)(drizzle,(DRIZZLE_FIELD*) 0, 7)))
375
363
    return(NULL);
376
 
  if (!(drizzle->fields=unpack_fields(fields,&drizzle->field_alloc,field_count,0)))
 
364
  if (!(drizzle->fields=unpack_fields(fields, field_count, 0)))
377
365
    return(0);
378
366
  drizzle->status=DRIZZLE_STATUS_GET_RESULT;
379
367
  drizzle->field_count=field_count;
382
370
 
383
371
 
384
372
int
385
 
drizzle_shutdown(DRIZZLE *drizzle, enum drizzle_enum_shutdown_level shutdown_level)
 
373
drizzle_shutdown(DRIZZLE *drizzle)
386
374
{
387
 
  uchar level[1];
388
 
  level[0]= (uchar) shutdown_level;
389
 
  return(simple_command(drizzle, COM_SHUTDOWN, level, 1, 0));
 
375
  return(simple_command(drizzle, COM_SHUTDOWN, 0, 0, 0));
390
376
}
391
377
 
392
378
 
393
379
int
394
 
drizzle_refresh(DRIZZLE *drizzle,uint options)
 
380
drizzle_refresh(DRIZZLE *drizzle, uint32_t options)
395
381
{
396
 
  uchar bits[1];
397
 
  bits[0]= (uchar) options;
 
382
  unsigned char bits[1];
 
383
  bits[0]= (unsigned char) options;
398
384
  return(simple_command(drizzle, COM_REFRESH, bits, 1, 0));
399
385
}
400
386
 
402
388
int32_t
403
389
drizzle_kill(DRIZZLE *drizzle, uint32_t pid)
404
390
{
405
 
  uchar buff[4];
 
391
  unsigned char buff[4];
406
392
  int4store(buff,pid);
407
393
  return(simple_command(drizzle,COM_PROCESS_KILL,buff,sizeof(buff),0));
408
394
}
411
397
int
412
398
drizzle_set_server_option(DRIZZLE *drizzle, enum enum_drizzle_set_option option)
413
399
{
414
 
  uchar buff[2];
415
 
  int2store(buff, (uint) option);
 
400
  unsigned char buff[2];
 
401
  int2store(buff, (uint32_t) option);
416
402
  return(simple_command(drizzle, COM_SET_OPTION, buff, sizeof(buff), 0));
417
403
}
418
404
 
422
408
  drizzle->net.read_pos[drizzle->packet_length]=0;  /* End of stat string */
423
409
  if (!drizzle->net.read_pos[0])
424
410
  {
425
 
    set_drizzle_error(drizzle, CR_WRONG_HOST_INFO, unknown_sqlstate);
 
411
    drizzle_set_error(drizzle, CR_WRONG_HOST_INFO, sqlstate_get_unknown());
426
412
    return drizzle->net.last_error;
427
413
  }
428
414
  return (char*) drizzle->net.read_pos;
454
440
}
455
441
 
456
442
 
457
 
uint
 
443
uint32_t
458
444
drizzle_get_proto_info(const DRIZZLE *drizzle)
459
445
{
460
446
  return (drizzle->protocol_version);
515
501
 
516
502
const char * drizzle_sqlstate(const DRIZZLE *drizzle)
517
503
{
518
 
  return drizzle ? drizzle->net.sqlstate : cant_connect_sqlstate;
 
504
  return drizzle ? drizzle->net.sqlstate : sqlstate_get_cant_connect();
519
505
}
520
506
 
521
507
uint32_t drizzle_warning_count(const DRIZZLE *drizzle)
533
519
  return drizzle->thread_id;
534
520
}
535
521
 
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
522
/****************************************************************************
569
523
  Some support functions
570
524
****************************************************************************/
575
529
 
576
530
void my_net_local_init(NET *net)
577
531
{
578
 
  net->max_packet=   (uint) net_buffer_length;
 
532
  net->max_packet=   (uint32_t) net_buffer_length;
579
533
  my_net_set_read_timeout(net, CLIENT_NET_READ_TIMEOUT);
580
534
  my_net_set_write_timeout(net, CLIENT_NET_WRITE_TIMEOUT);
581
535
  net->retry_count=  1;
582
 
  net->max_packet_size= max(net_buffer_length, max_allowed_packet);
 
536
  net->max_packet_size= (net_buffer_length > max_allowed_packet) ?
 
537
    net_buffer_length : max_allowed_packet;
583
538
}
584
539
 
585
540
/*
596
551
  Each character needs two bytes, and you need room for the terminating
597
552
  null byte. When drizzle_hex_string() returns, the contents of "to" will
598
553
  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
 
554
  encoded string, not including the terminating null character.  The return value does not contain any leading 0x or a leading X' and
602
555
  trailing '. The caller must supply whichever of those is desired.
603
556
*/
604
557
 
626
579
uint32_t
627
580
drizzle_escape_string(char *to,const char *from, uint32_t length)
628
581
{
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++)
 
582
  const char *to_start= to;
 
583
  const char *end, *to_end=to_start + 2*length;
 
584
  bool overflow= false;
 
585
  for (end= from + length; from < end; from++)
653
586
  {
654
 
#ifdef USE_MB
655
 
    int l;
656
 
    if (use_mb_flag && (l = my_ismbchar( drizzle->charset, name , end ) ) )
 
587
    uint32_t tmp_length;
 
588
    char escape= 0;
 
589
    if (!U8_IS_SINGLE(*from))
657
590
    {
658
 
      while (l--)
659
 
        *to++ = *name++;
660
 
      name--;
 
591
      tmp_length= U8_LENGTH(*from);
 
592
      if (to + tmp_length > to_end)
 
593
      {
 
594
        overflow= true;
 
595
        break;
 
596
      }
 
597
      while (tmp_length--)
 
598
        *to++= *from++;
 
599
      from--;
661
600
      continue;
662
601
    }
663
 
#endif
664
 
    if (*name == '\\' && name[1])
665
 
      name++;
666
 
    *to++= *name;
 
602
    switch (*from) {
 
603
    case 0:                             /* Must be escaped for 'mysql' */
 
604
      escape= '0';
 
605
      break;
 
606
    case '\n':                          /* Must be escaped for logs */
 
607
      escape= 'n';
 
608
      break;
 
609
    case '\r':
 
610
      escape= 'r';
 
611
      break;
 
612
    case '\\':
 
613
      escape= '\\';
 
614
      break;
 
615
    case '\'':
 
616
      escape= '\'';
 
617
      break;
 
618
    case '"':                           /* Better safe than sorry */
 
619
      escape= '"';
 
620
      break;
 
621
    case '\032':                        /* This gives problems on Win32 */
 
622
      escape= 'Z';
 
623
      break;
 
624
    }
 
625
    if (escape)
 
626
    {
 
627
      if (to + 2 > to_end)
 
628
      {
 
629
        overflow= true;
 
630
        break;
 
631
      }
 
632
      *to++= '\\';
 
633
      *to++= escape;
 
634
    }
 
635
    else
 
636
    {
 
637
      if (to + 1 > to_end)
 
638
      {
 
639
        overflow= true;
 
640
        break;
 
641
      }
 
642
      *to++= *from;
 
643
    }
667
644
  }
668
 
  *to=0;
 
645
  *to= 0;
 
646
  return overflow ? (size_t) -1 : (size_t) (to - to_start);
669
647
}
670
648
 
671
649
int cli_unbuffered_fetch(DRIZZLE *drizzle, char **row)
735
713
{
736
714
  if (drizzle->status != DRIZZLE_STATUS_READY)
737
715
  {
738
 
    set_drizzle_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, unknown_sqlstate);
 
716
    drizzle_set_error(drizzle, CR_COMMANDS_OUT_OF_SYNC, sqlstate_get_unknown());
739
717
    return(1);
740
718
  }
741
719