~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/sql_string.cc

enable remaining subselect tests, merge with latest from the trunk

Show diffs side-by-side

added added

removed removed

Lines of Context:
19
19
#include <mysys/my_sys.h>
20
20
#include <mystrings/m_string.h>
21
21
 
 
22
#include <algorithm>
 
23
 
22
24
/*
23
25
  The following extern declarations are ok as these are interface functions
24
26
  required by the string function
25
27
*/
26
28
 
27
 
extern uchar* sql_alloc(unsigned size);
 
29
extern unsigned char* sql_alloc(unsigned size);
28
30
extern void sql_element_free(void *ptr);
29
31
 
30
32
#include "sql_string.h"
40
42
  if (Alloced_length < arg_length)
41
43
  {
42
44
    free();
43
 
    if (!(Ptr=(char*) my_malloc(arg_length,MYF(MY_WME))))
 
45
    if (!(Ptr=(char*) malloc(arg_length)))
44
46
      return true;
45
47
    Alloced_length=arg_length;
46
48
    alloced=1;
63
65
    char *new_ptr;
64
66
    if (alloced)
65
67
    {
66
 
      if ((new_ptr= (char*) my_realloc(Ptr,len,MYF(MY_WME))))
 
68
      if ((new_ptr= (char*) ::realloc(Ptr,len)))
67
69
      {
68
70
        Ptr=new_ptr;
69
71
        Alloced_length=len;
71
73
      else
72
74
        return true;                            // Signal error
73
75
    }
74
 
    else if ((new_ptr= (char*) my_malloc(len,MYF(MY_WME))))
 
76
    else if ((new_ptr= (char*) malloc(len)))
75
77
    {
76
78
      if (str_length)                           // Avoid bugs in memcpy on AIX
77
79
        memcpy(new_ptr,Ptr,str_length);
89
91
 
90
92
bool String::set_int(int64_t num, bool unsigned_flag, const CHARSET_INFO * const cs)
91
93
{
92
 
  uint l=20*cs->mbmaxlen+1;
 
94
  uint32_t l=20*cs->mbmaxlen+1;
93
95
  int base= unsigned_flag ? 10 : -10;
94
96
 
95
97
  if (alloc(l))
99
101
  return false;
100
102
}
101
103
 
102
 
bool String::set_real(double num,uint decimals, const CHARSET_INFO * const cs)
 
104
bool String::set_real(double num,uint32_t decimals, const CHARSET_INFO * const cs)
103
105
{
104
106
  char buff[FLOATING_POINT_BUFFER];
105
 
  uint dummy_errors;
 
107
  uint32_t dummy_errors;
106
108
  size_t len;
107
109
 
108
110
  str_charset=cs;
109
111
  if (decimals >= NOT_FIXED_DEC)
110
112
  {
111
113
    len= my_gcvt(num, MY_GCVT_ARG_DOUBLE, sizeof(buff) - 1, buff, NULL);
112
 
    return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
 
114
    return copy(buff, len, &my_charset_utf8_general_ci, cs, &dummy_errors);
113
115
  }
114
116
  len= my_fcvt(num, decimals, buff, NULL);
115
 
  return copy(buff, (uint32_t) len, &my_charset_latin1, cs,
 
117
  return copy(buff, (uint32_t) len, &my_charset_utf8_general_ci, cs,
116
118
              &dummy_errors);
117
119
}
118
120
 
179
181
{
180
182
  *offset= 0;
181
183
  if (!to_cs ||
182
 
      (to_cs == &my_charset_bin) || 
 
184
      (to_cs == &my_charset_bin) ||
183
185
      (to_cs == from_cs) ||
184
186
      my_charset_same(from_cs, to_cs) ||
185
187
      ((from_cs == &my_charset_bin) &&
204
206
  NOTES
205
207
    For real multi-byte, ascii incompatible charactser sets,
206
208
    like UCS-2, add leading zeros if we have an incomplete character.
207
 
    Thus, 
208
 
      SELECT _ucs2 0xAA 
 
209
    Thus,
 
210
      SELECT _ucs2 0xAA
209
211
    will automatically be converted into
210
212
      SELECT _ucs2 0x00AA
211
213
 
224
226
  uint32_t aligned_length= arg_length + offset;
225
227
  if (alloc(aligned_length))
226
228
    return true;
227
 
  
 
229
 
228
230
  /*
229
231
    Note, this is only safe for big-endian UCS-2.
230
232
    If we add little-endian UCS-2 sometimes, this code
244
246
                                 const CHARSET_INFO * const cs)
245
247
{
246
248
  /* How many bytes are in incomplete character */
247
 
  uint32_t offset= (arg_length % cs->mbminlen); 
248
 
  
 
249
  uint32_t offset= (arg_length % cs->mbminlen);
 
250
 
249
251
  if (!offset) /* All characters are complete, just copy */
250
252
  {
251
253
    set(str, arg_length, cs);
258
260
 
259
261
bool String::copy(const char *str, uint32_t arg_length,
260
262
                          const CHARSET_INFO * const from_cs,
261
 
                                  const CHARSET_INFO * const to_cs, uint *errors)
 
263
                                  const CHARSET_INFO * const to_cs, uint32_t *errors)
262
264
{
263
265
  uint32_t offset;
264
266
  if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
283
285
 
284
286
/*
285
287
  Set a string to the value of a latin1-string, keeping the original charset
286
 
  
 
288
 
287
289
  SYNOPSIS
288
290
    copy_or_set()
289
291
    str                 String of a simple charset (latin1)
307
309
    set(str, arg_length, str_charset);
308
310
    return 0;
309
311
  }
310
 
  uint dummy_errors;
311
 
  return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
 
312
  uint32_t dummy_errors;
 
313
  return copy(str, arg_length, &my_charset_utf8_general_ci, str_charset, &dummy_errors);
312
314
}
313
315
 
314
316
 
356
358
  if (str_charset->mbminlen > 1)
357
359
  {
358
360
    uint32_t add_length=arg_length * str_charset->mbmaxlen;
359
 
    uint dummy_errors;
 
361
    uint32_t dummy_errors;
360
362
    if (realloc(str_length+ add_length))
361
363
      return true;
362
364
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
363
 
                                  s, arg_length, &my_charset_latin1,
 
365
                                  s, arg_length, &my_charset_utf8_general_ci,
364
366
                                  &dummy_errors);
365
367
    return false;
366
368
  }
394
396
bool String::append(const char *s,uint32_t arg_length, const CHARSET_INFO * const cs)
395
397
{
396
398
  uint32_t dummy_offset;
397
 
  
 
399
 
398
400
  if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
399
401
  {
400
402
    uint32_t add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
401
 
    uint dummy_errors;
402
 
    if (realloc(str_length + add_length)) 
 
403
    uint32_t dummy_errors;
 
404
    if (realloc(str_length + add_length))
403
405
      return true;
404
406
    str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
405
407
                                  s, arg_length, cs, &dummy_errors);
406
408
  }
407
409
  else
408
410
  {
409
 
    if (realloc(str_length + arg_length)) 
 
411
    if (realloc(str_length + arg_length))
410
412
      return true;
411
413
    memcpy(Ptr + str_length, s, arg_length);
412
414
    str_length+= arg_length;
419
421
{
420
422
  if (realloc(str_length+arg_length))
421
423
    return true;
422
 
  if (my_b_read(file, (uchar*) Ptr + str_length, arg_length))
 
424
  if (my_b_read(file, (unsigned char*) Ptr + str_length, arg_length))
423
425
  {
424
426
    shrink(str_length);
425
427
    return true;
535
537
    {
536
538
      if (to_length)
537
539
        memcpy(Ptr+offset,to,to_length);
538
 
      memcpy(Ptr+offset+to_length, Ptr+offset+arg_length,
539
 
             str_length-offset-arg_length);
 
540
      memmove(Ptr+offset+to_length, Ptr+offset+arg_length,
 
541
              str_length-offset-arg_length);
540
542
    }
541
543
    else
542
544
    {
544
546
      {
545
547
        if (realloc(str_length+(uint32_t) diff))
546
548
          return true;
547
 
        bmove_upp((uchar*) Ptr+str_length+diff, (uchar*) Ptr+str_length,
 
549
        bmove_upp((unsigned char*) Ptr+str_length+diff, (unsigned char*) Ptr+str_length,
548
550
                  str_length-offset-arg_length);
549
551
      }
550
552
      if (to_length)
561
563
{
562
564
  if (Alloced_length < str_length + space_needed)
563
565
  {
564
 
    if (realloc(Alloced_length + max(space_needed, grow_by) - 1))
 
566
    if (realloc(Alloced_length + cmax(space_needed, grow_by) - 1))
565
567
      return true;
566
568
  }
567
569
  return false;
593
595
  str_length+= (int) (end-buff);
594
596
}
595
597
 
596
 
void String::qs_append(uint i)
 
598
void String::qs_append(uint32_t i)
597
599
{
598
600
  char *buff= Ptr + str_length;
599
601
  char *end= int10_to_str(i, buff, 10);
622
624
int sortcmp(const String *s,const String *t, const CHARSET_INFO * const cs)
623
625
{
624
626
 return cs->coll->strnncollsp(cs,
625
 
                              (uchar *) s->ptr(),s->length(),
626
 
                              (uchar *) t->ptr(),t->length(), 0);
 
627
                              (unsigned char *) s->ptr(),s->length(),
 
628
                              (unsigned char *) t->ptr(),t->length(), 0);
627
629
}
628
630
 
629
631
 
636
638
    t           Second string
637
639
 
638
640
  NOTE:
639
 
    Strings are compared as a stream of uchars
 
641
    Strings are compared as a stream of unsigned chars
640
642
 
641
643
  RETURN
642
644
  < 0   s < t
647
649
 
648
650
int stringcmp(const String *s,const String *t)
649
651
{
650
 
  uint32_t s_len=s->length(),t_len=t->length(),len=min(s_len,t_len);
 
652
  uint32_t s_len=s->length(),t_len=t->length(),len=cmin(s_len,t_len);
651
653
  int cmp= memcmp(s->ptr(), t->ptr(), len);
652
654
  return (cmp) ? cmp : (int) (s_len - t_len);
653
655
}
664
666
  }
665
667
  if (to->realloc(from_length))
666
668
    return from;                                // Actually an error
667
 
  if ((to->str_length=min(from->str_length,from_length)))
 
669
  if ((to->str_length=cmin(from->str_length,from_length)))
668
670
    memcpy(to->Ptr,from->Ptr,to->str_length);
669
671
  to->str_charset=from->str_charset;
670
672
  return to;
677
679
 
678
680
/*
679
681
  copy a string from one character set to another
680
 
  
 
682
 
681
683
  SYNOPSIS
682
684
    copy_and_convert()
683
685
    to                  Store result here
696
698
 
697
699
static uint32_t
698
700
copy_and_convert_extended(char *to, uint32_t to_length,
699
 
                          const CHARSET_INFO * const to_cs, 
 
701
                          const CHARSET_INFO * const to_cs,
700
702
                          const char *from, uint32_t from_length,
701
703
                          const CHARSET_INFO * const from_cs,
702
 
                          uint *errors)
 
704
                          uint32_t *errors)
703
705
{
704
706
  int         cnvres;
705
707
  my_wc_t     wc;
706
 
  const uchar *from_end= (const uchar*) from+from_length;
 
708
  const unsigned char *from_end= (const unsigned char*) from+from_length;
707
709
  char *to_start= to;
708
 
  uchar *to_end= (uchar*) to+to_length;
 
710
  unsigned char *to_end= (unsigned char*) to+to_length;
709
711
  my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
710
712
  my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
711
 
  uint error_count= 0;
 
713
  uint32_t error_count= 0;
712
714
 
713
715
  while (1)
714
716
  {
715
 
    if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from,
 
717
    if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from,
716
718
                                      from_end)) > 0)
717
719
      from+= cnvres;
718
720
    else if (cnvres == MY_CS_ILSEQ)
735
737
      break;  // Not enough characters
736
738
 
737
739
outp:
738
 
    if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
 
740
    if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
739
741
      to+= cnvres;
740
742
    else if (cnvres == MY_CS_ILUNI && wc != '?')
741
743
    {
755
757
  Optimized for quick copying of ASCII characters in the range 0x00..0x7F.
756
758
*/
757
759
uint32_t
758
 
copy_and_convert(char *to, uint32_t to_length, const CHARSET_INFO * const to_cs, 
 
760
copy_and_convert(char *to, uint32_t to_length, const CHARSET_INFO * const to_cs,
759
761
                 const char *from, uint32_t from_length,
760
 
                                 const CHARSET_INFO * const from_cs, uint *errors)
 
762
                                 const CHARSET_INFO * const from_cs, uint32_t *errors)
761
763
{
762
764
  /*
763
765
    If any of the character sets is not ASCII compatible,
767
769
    return copy_and_convert_extended(to, to_length, to_cs,
768
770
                                     from, from_length, from_cs, errors);
769
771
 
770
 
  uint32_t length= min(to_length, from_length), length2= length;
 
772
  uint32_t length= cmin(to_length, from_length), length2= length;
771
773
 
772
774
#if defined(__i386__)
773
775
  /*
818
820
  are read from "src". Any sequences of bytes representing
819
821
  a not-well-formed substring (according to cs) are hex-encoded,
820
822
  and all well-formed substrings (according to cs) are copied as is.
821
 
  Not more than "dstlen" bytes are written to "dst". The number 
 
823
  Not more than "dstlen" bytes are written to "dst". The number
822
824
  of bytes written to "dst" is returned.
823
 
  
 
825
 
824
826
   @param      cs       character set pointer of the destination string
825
827
   @param[out] dst      destination string
826
828
   @param      dstlen   size of dst
876
878
  copy a string,
877
879
  with optional character set conversion,
878
880
  with optional left padding (for binary -> UCS2 conversion)
879
 
  
 
881
 
880
882
  SYNOPSIS
881
883
    well_formed_copy_nchars()
882
884
    to                       Store result here
901
903
 
902
904
uint32_t
903
905
well_formed_copy_nchars(const CHARSET_INFO * const to_cs,
904
 
                        char *to, uint to_length,
 
906
                        char *to, uint32_t to_length,
905
907
                        const CHARSET_INFO * const from_cs,
906
 
                        const char *from, uint from_length,
907
 
                        uint nchars,
 
908
                        const char *from, uint32_t from_length,
 
909
                        uint32_t nchars,
908
910
                        const char **well_formed_error_pos,
909
911
                        const char **cannot_convert_error_pos,
910
912
                        const char **from_end_pos)
911
913
{
912
 
  uint res;
 
914
  uint32_t res;
913
915
 
914
 
  if ((to_cs == &my_charset_bin) || 
 
916
  if ((to_cs == &my_charset_bin) ||
915
917
      (from_cs == &my_charset_bin) ||
916
918
      (to_cs == from_cs) ||
917
919
      my_charset_same(from_cs, to_cs))
926
928
 
927
929
    if (to_cs == &my_charset_bin)
928
930
    {
929
 
      res= min(min(nchars, to_length), from_length);
 
931
      res= cmin(cmin(nchars, to_length), from_length);
930
932
      memmove(to, from, res);
931
933
      *from_end_pos= from + res;
932
934
      *well_formed_error_pos= NULL;
935
937
    else
936
938
    {
937
939
      int well_formed_error;
938
 
      uint from_offset;
 
940
      uint32_t from_offset;
939
941
 
940
942
      if ((from_offset= (from_length % to_cs->mbminlen)) &&
941
943
          (from_cs == &my_charset_bin))
945
947
          INSERT INTO t1 (ucs2_column) VALUES (0x01);
946
948
          0x01 -> 0x0001
947
949
        */
948
 
        uint pad_length= to_cs->mbminlen - from_offset;
 
950
        uint32_t pad_length= to_cs->mbminlen - from_offset;
949
951
        memset(to, 0, pad_length);
950
952
        memmove(to + pad_length, from, from_offset);
951
953
        nchars--;
972
974
    my_wc_t wc;
973
975
    my_charset_conv_mb_wc mb_wc= from_cs->cset->mb_wc;
974
976
    my_charset_conv_wc_mb wc_mb= to_cs->cset->wc_mb;
975
 
    const uchar *from_end= (const uchar*) from + from_length;
976
 
    uchar *to_end= (uchar*) to + to_length;
 
977
    const unsigned char *from_end= (const unsigned char*) from + from_length;
 
978
    unsigned char *to_end= (unsigned char*) to + to_length;
977
979
    char *to_start= to;
978
980
    *well_formed_error_pos= NULL;
979
981
    *cannot_convert_error_pos= NULL;
981
983
    for ( ; nchars; nchars--)
982
984
    {
983
985
      const char *from_prev= from;
984
 
      if ((cnvres= (*mb_wc)(from_cs, &wc, (uchar*) from, from_end)) > 0)
 
986
      if ((cnvres= (*mb_wc)(from_cs, &wc, (unsigned char*) from, from_end)) > 0)
985
987
        from+= cnvres;
986
988
      else if (cnvres == MY_CS_ILSEQ)
987
989
      {
1005
1007
        break;  // Not enough characters
1006
1008
 
1007
1009
outp:
1008
 
      if ((cnvres= (*wc_mb)(to_cs, wc, (uchar*) to, to_end)) > 0)
 
1010
      if ((cnvres= (*wc_mb)(to_cs, wc, (unsigned char*) to, to_end)) > 0)
1009
1011
        to+= cnvres;
1010
1012
      else if (cnvres == MY_CS_ILUNI && wc != '?')
1011
1013
      {
1034
1036
  char *st= (char*)Ptr, *end= st+str_length;
1035
1037
  for (; st < end; st++)
1036
1038
  {
1037
 
    uchar c= *st;
 
1039
    unsigned char c= *st;
1038
1040
    switch (c)
1039
1041
    {
1040
1042
    case '\\':
1041
 
      str->append(STRING_WITH_LEN("\\\\"));
 
1043
      str->append("\\\\", sizeof("\\\\")-1);
1042
1044
      break;
1043
1045
    case '\0':
1044
 
      str->append(STRING_WITH_LEN("\\0"));
 
1046
      str->append("\\0", sizeof("\\0")-1);
1045
1047
      break;
1046
1048
    case '\'':
1047
 
      str->append(STRING_WITH_LEN("\\'"));
 
1049
      str->append("\\'", sizeof("\\'")-1);
1048
1050
      break;
1049
1051
    case '\n':
1050
 
      str->append(STRING_WITH_LEN("\\n"));
 
1052
      str->append("\\n", sizeof("\\n")-1);
1051
1053
      break;
1052
1054
    case '\r':
1053
 
      str->append(STRING_WITH_LEN("\\r"));
 
1055
      str->append("\\r", sizeof("\\r")-1);
1054
1056
      break;
1055
1057
    case '\032': // Ctrl-Z
1056
 
      str->append(STRING_WITH_LEN("\\Z"));
 
1058
      str->append("\\Z", sizeof("\\Z")-1);
1057
1059
      break;
1058
1060
    default:
1059
1061
      str->append(c);
1074
1076
 
1075
1077
void String::swap(String &s)
1076
1078
{
1077
 
  swap_variables(char *, Ptr, s.Ptr);
1078
 
  swap_variables(uint32_t, str_length, s.str_length);
1079
 
  swap_variables(uint32_t, Alloced_length, s.Alloced_length);
1080
 
  swap_variables(bool, alloced, s.alloced);
1081
 
  swap_variables(const CHARSET_INFO *, str_charset, s.str_charset);
1082
 
}
 
1079
  std::swap(Ptr, s.Ptr);
 
1080
  std::swap(str_length, s.str_length);
 
1081
  std::swap(Alloced_length, s.Alloced_length);
 
1082
  std::swap(alloced, s.alloced);
 
1083
  std::swap(str_charset, s.str_charset);
 
1084
}
 
1085
 
 
1086
 
 
1087
bool operator==(const String &s1, const String &s2)
 
1088
{
 
1089
  return stringcmp(&s1,&s2) == 0;
 
1090
}
 
1091
 
 
1092
bool operator!=(const String &s1, const String &s2)
 
1093
{
 
1094
  return !(s1 == s2);
 
1095
}
 
1096