~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to sql/field.cc

  • Committer: Brian Aker
  • Date: 2008-07-06 15:56:24 UTC
  • Revision ID: brian@tangent.org-20080706155624-pn6a48azmjh6nalx
Most of the removal of dead DECIMAL type

Show diffs side-by-side

added added

removed removed

Lines of Context:
1715
1715
 
1716
1716
 
1717
1717
/****************************************************************************
1718
 
  Functions for the Field_decimal class
1719
 
  This is an number stored as a pre-space (or pre-zero) string
1720
 
****************************************************************************/
1721
 
 
1722
 
int
1723
 
Field_decimal::reset(void)
1724
 
{
1725
 
  Field_decimal::store(STRING_WITH_LEN("0"),&my_charset_bin);
1726
 
  return 0;
1727
 
}
1728
 
 
1729
 
void Field_decimal::overflow(bool negative)
1730
 
{
1731
 
  uint len=field_length;
1732
 
  uchar *to=ptr, filler= '9';
1733
 
 
1734
 
  set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
1735
 
  if (negative)
1736
 
  {
1737
 
    if (!unsigned_flag)
1738
 
    {
1739
 
      /* Put - sign as a first digit so we'll have -999..999 or 999..999 */
1740
 
      *to++ = '-';
1741
 
      len--;
1742
 
    }
1743
 
    else
1744
 
    {
1745
 
      filler= '0';                              // Fill up with 0
1746
 
      if (!zerofill)
1747
 
      {
1748
 
        /*
1749
 
          Handle unsigned integer without zerofill, in which case
1750
 
          the number should be of format '   0' or '   0.000'
1751
 
        */
1752
 
        uint whole_part=field_length- (dec ? dec+2 : 1);
1753
 
        // Fill with spaces up to the first digit
1754
 
        bfill(to, whole_part, ' ');
1755
 
        to+=  whole_part;
1756
 
        len-= whole_part;
1757
 
        // The main code will also handle the 0 before the decimal point
1758
 
      }
1759
 
    }
1760
 
  }
1761
 
  bfill(to, len, filler);
1762
 
  if (dec)
1763
 
    ptr[field_length-dec-1]='.';
1764
 
  return;
1765
 
}
1766
 
 
1767
 
 
1768
 
int Field_decimal::store(const char *from_arg, uint len, CHARSET_INFO *cs)
1769
 
{
1770
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
1771
 
  char buff[STRING_BUFFER_USUAL_SIZE];
1772
 
  String tmp(buff,sizeof(buff), &my_charset_bin);
1773
 
  const uchar *from= (uchar*) from_arg;
1774
 
 
1775
 
  /* Convert character set if the old one is multi uchar */
1776
 
  if (cs->mbmaxlen > 1)
1777
 
  { 
1778
 
    uint dummy_errors;
1779
 
    tmp.copy((char*) from, len, cs, &my_charset_bin, &dummy_errors);
1780
 
    from= (uchar*) tmp.ptr();
1781
 
    len=  tmp.length();
1782
 
  }
1783
 
 
1784
 
  const uchar *end= from+len;
1785
 
  /* The pointer where the field value starts (i.e., "where to write") */
1786
 
  uchar *to= ptr;
1787
 
  uint tmp_dec, tmp_uint;
1788
 
  /*
1789
 
    The sign of the number : will be 0 (means positive but sign not
1790
 
    specified), '+' or '-'
1791
 
  */
1792
 
  uchar sign_char=0;
1793
 
  /* The pointers where prezeros start and stop */
1794
 
  const uchar *pre_zeros_from, *pre_zeros_end;
1795
 
  /* The pointers where digits at the left of '.' start and stop */
1796
 
  const uchar *int_digits_from, *int_digits_end;
1797
 
  /* The pointers where digits at the right of '.' start and stop */
1798
 
  const uchar *frac_digits_from, *frac_digits_end;
1799
 
  /* The sign of the exponent : will be 0 (means no exponent), '+' or '-' */
1800
 
  char expo_sign_char=0;
1801
 
  uint exponent=0;                                // value of the exponent
1802
 
  /*
1803
 
    Pointers used when digits move from the left of the '.' to the
1804
 
    right of the '.' (explained below)
1805
 
  */
1806
 
  const uchar *int_digits_tail_from= NULL;
1807
 
  /* Number of 0 that need to be added at the left of the '.' (1E3: 3 zeros) */
1808
 
  uint int_digits_added_zeros= 0;
1809
 
  /*
1810
 
    Pointer used when digits move from the right of the '.' to the left
1811
 
    of the '.'
1812
 
  */
1813
 
  const uchar *frac_digits_head_end= NULL;
1814
 
  /* Number of 0 that need to be added at the right of the '.' (for 1E-3) */
1815
 
  uint frac_digits_added_zeros= 0;
1816
 
  uchar *pos, *tmp_left_pos, *tmp_right_pos;
1817
 
  /* Pointers that are used as limits (begin and end of the field buffer) */
1818
 
  uchar *left_wall, *right_wall;
1819
 
  uchar tmp_char;
1820
 
  /*
1821
 
    To remember if table->in_use->cuted_fields has already been incremented,
1822
 
    to do that only once
1823
 
  */
1824
 
  bool is_cuted_fields_incr=0;
1825
 
 
1826
 
  /*
1827
 
    There are three steps in this function :
1828
 
    - parse the input string
1829
 
    - modify the position of digits around the decimal dot '.' 
1830
 
      according to the exponent value (if specified)
1831
 
    - write the formatted number
1832
 
  */
1833
 
 
1834
 
  if ((tmp_dec=dec))
1835
 
    tmp_dec++;
1836
 
 
1837
 
  /* skip pre-space */
1838
 
  while (from != end && my_isspace(&my_charset_bin,*from))
1839
 
    from++;
1840
 
  if (from == end)
1841
 
  {
1842
 
    set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
1843
 
    is_cuted_fields_incr=1;
1844
 
  }
1845
 
  else if (*from == '+' || *from == '-')        // Found some sign ?
1846
 
  {
1847
 
    sign_char= *from++;
1848
 
    /*
1849
 
      We allow "+" for unsigned decimal unless defined different
1850
 
      Both options allowed as one may wish not to have "+" for unsigned numbers
1851
 
      because of data processing issues
1852
 
    */ 
1853
 
    if (unsigned_flag)  
1854
 
    { 
1855
 
      if (sign_char=='-')
1856
 
      {
1857
 
        Field_decimal::overflow(1);
1858
 
        return 1;
1859
 
      }
1860
 
      /* 
1861
 
         Defining this will not store "+" for unsigned decimal type even if
1862
 
         it is passed in numeric string. This will make some tests to fail
1863
 
      */         
1864
 
#ifdef DONT_ALLOW_UNSIGNED_PLUS      
1865
 
      else 
1866
 
        sign_char=0;
1867
 
#endif  
1868
 
    }
1869
 
  }
1870
 
 
1871
 
  pre_zeros_from= from;
1872
 
  for (; from!=end && *from == '0'; from++) ;   // Read prezeros
1873
 
  pre_zeros_end=int_digits_from=from;      
1874
 
  /* Read non zero digits at the left of '.'*/
1875
 
  for (; from != end && my_isdigit(&my_charset_bin, *from) ; from++) ;
1876
 
  int_digits_end=from;
1877
 
  if (from!=end && *from == '.')                // Some '.' ?
1878
 
    from++;
1879
 
  frac_digits_from= from;
1880
 
  /* Read digits at the right of '.' */
1881
 
  for (;from!=end && my_isdigit(&my_charset_bin, *from); from++) ;
1882
 
  frac_digits_end=from;
1883
 
  // Some exponentiation symbol ?
1884
 
  if (from != end && (*from == 'e' || *from == 'E'))
1885
 
  {   
1886
 
    from++;
1887
 
    if (from != end && (*from == '+' || *from == '-'))  // Some exponent sign ?
1888
 
      expo_sign_char= *from++;
1889
 
    else
1890
 
      expo_sign_char= '+';
1891
 
    /*
1892
 
      Read digits of the exponent and compute its value.  We must care about
1893
 
      'exponent' overflow, because as unsigned arithmetic is "modulo", big 
1894
 
      exponents will become small (e.g. 1e4294967296 will become 1e0, and the 
1895
 
      field will finally contain 1 instead of its max possible value).
1896
 
    */
1897
 
    for (;from!=end && my_isdigit(&my_charset_bin, *from); from++)
1898
 
    {
1899
 
      exponent=10*exponent+(*from-'0');
1900
 
      if (exponent>MAX_EXPONENT)
1901
 
        break;
1902
 
    }
1903
 
  }
1904
 
  
1905
 
  /*
1906
 
    We only have to generate warnings if count_cuted_fields is set.
1907
 
    This is to avoid extra checks of the number when they are not needed.
1908
 
    Even if this flag is not set, it's OK to increment warnings, if
1909
 
    it makes the code easer to read.
1910
 
  */
1911
 
 
1912
 
  if (table->in_use->count_cuted_fields)
1913
 
  {
1914
 
    // Skip end spaces
1915
 
    for (;from != end && my_isspace(&my_charset_bin, *from); from++) ;
1916
 
    if (from != end)                     // If still something left, warn
1917
 
    {
1918
 
      set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, WARN_DATA_TRUNCATED, 1);
1919
 
      is_cuted_fields_incr=1;
1920
 
    }
1921
 
  }
1922
 
  
1923
 
  /*
1924
 
    Now "move" digits around the decimal dot according to the exponent value,
1925
 
    and add necessary zeros.
1926
 
    Examples :
1927
 
    - 1E+3 : needs 3 more zeros at the left of '.' (int_digits_added_zeros=3)
1928
 
    - 1E-3 : '1' moves at the right of '.', and 2 more zeros are needed
1929
 
    between '.' and '1'
1930
 
    - 1234.5E-3 : '234' moves at the right of '.'
1931
 
    These moves are implemented with pointers which point at the begin
1932
 
    and end of each moved segment. Examples :
1933
 
    - 1234.5E-3 : before the code below is executed, the int_digits part is
1934
 
    from '1' to '4' and the frac_digits part from '5' to '5'. After the code
1935
 
    below, the int_digits part is from '1' to '1', the frac_digits_head
1936
 
    part is from '2' to '4', and the frac_digits part from '5' to '5'.
1937
 
    - 1234.5E3 : before the code below is executed, the int_digits part is
1938
 
    from '1' to '4' and the frac_digits part from '5' to '5'. After the code
1939
 
    below, the int_digits part is from '1' to '4', the int_digits_tail
1940
 
    part is from '5' to '5', the frac_digits part is empty, and
1941
 
    int_digits_added_zeros=2 (to make 1234500).
1942
 
  */
1943
 
  
1944
 
  /* 
1945
 
     Below tmp_uint cannot overflow with small enough MAX_EXPONENT setting,
1946
 
     as int_digits_added_zeros<=exponent<4G and 
1947
 
     (int_digits_end-int_digits_from)<=max_allowed_packet<=2G and
1948
 
     (frac_digits_from-int_digits_tail_from)<=max_allowed_packet<=2G
1949
 
  */
1950
 
 
1951
 
  if (!expo_sign_char)
1952
 
    tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);
1953
 
  else if (expo_sign_char == '-') 
1954
 
  {
1955
 
    tmp_uint=min(exponent,(uint)(int_digits_end-int_digits_from));
1956
 
    frac_digits_added_zeros=exponent-tmp_uint;
1957
 
    int_digits_end -= tmp_uint;
1958
 
    frac_digits_head_end=int_digits_end+tmp_uint;
1959
 
    tmp_uint=tmp_dec+(uint)(int_digits_end-int_digits_from);     
1960
 
  }
1961
 
  else // (expo_sign_char=='+') 
1962
 
  {
1963
 
    tmp_uint=min(exponent,(uint)(frac_digits_end-frac_digits_from));
1964
 
    int_digits_added_zeros=exponent-tmp_uint;
1965
 
    int_digits_tail_from=frac_digits_from;
1966
 
    frac_digits_from=frac_digits_from+tmp_uint;
1967
 
    /*
1968
 
      We "eat" the heading zeros of the 
1969
 
      int_digits.int_digits_tail.int_digits_added_zeros concatenation
1970
 
      (for example 0.003e3 must become 3 and not 0003)
1971
 
    */
1972
 
    if (int_digits_from == int_digits_end) 
1973
 
    {
1974
 
      /*
1975
 
        There was nothing in the int_digits part, so continue
1976
 
        eating int_digits_tail zeros
1977
 
      */
1978
 
      for (; int_digits_tail_from != frac_digits_from &&
1979
 
             *int_digits_tail_from == '0'; int_digits_tail_from++) ;
1980
 
      if (int_digits_tail_from == frac_digits_from) 
1981
 
      {
1982
 
        // there were only zeros in int_digits_tail too
1983
 
        int_digits_added_zeros=0;
1984
 
      }
1985
 
    }
1986
 
    tmp_uint= (uint) (tmp_dec+(int_digits_end-int_digits_from)+
1987
 
               (uint)(frac_digits_from-int_digits_tail_from)+
1988
 
               int_digits_added_zeros);
1989
 
  }
1990
 
  
1991
 
  /*
1992
 
    Now write the formated number
1993
 
    
1994
 
    First the digits of the int_% parts.
1995
 
    Do we have enough room to write these digits ?
1996
 
    If the sign is defined and '-', we need one position for it
1997
 
  */
1998
 
 
1999
 
  if (field_length < tmp_uint + (int) (sign_char == '-')) 
2000
 
  {
2001
 
    // too big number, change to max or min number
2002
 
    Field_decimal::overflow(sign_char == '-');
2003
 
    return 1;
2004
 
  }
2005
 
 
2006
 
  /*
2007
 
    Tmp_left_pos is the position where the leftmost digit of
2008
 
    the int_% parts will be written
2009
 
  */
2010
 
  tmp_left_pos=pos=to+(uint)(field_length-tmp_uint);
2011
 
  
2012
 
  // Write all digits of the int_% parts
2013
 
  while (int_digits_from != int_digits_end)
2014
 
    *pos++ = *int_digits_from++ ;
2015
 
 
2016
 
  if (expo_sign_char == '+')
2017
 
  {    
2018
 
    while (int_digits_tail_from != frac_digits_from)
2019
 
      *pos++= *int_digits_tail_from++;
2020
 
    while (int_digits_added_zeros-- >0)
2021
 
      *pos++= '0';  
2022
 
  }
2023
 
  /*
2024
 
    Note the position where the rightmost digit of the int_% parts has been
2025
 
    written (this is to later check if the int_% parts contained nothing,
2026
 
    meaning an extra 0 is needed).
2027
 
  */
2028
 
  tmp_right_pos=pos;
2029
 
 
2030
 
  /*
2031
 
    Step back to the position of the leftmost digit of the int_% parts,
2032
 
    to write sign and fill with zeros or blanks or prezeros.
2033
 
  */
2034
 
  pos=tmp_left_pos-1;
2035
 
  if (zerofill)
2036
 
  {
2037
 
    left_wall=to-1;
2038
 
    while (pos > left_wall)                     // Fill with zeros
2039
 
      *pos--='0';
2040
 
  }
2041
 
  else
2042
 
  {
2043
 
    left_wall=to+(sign_char != 0)-1;
2044
 
    if (!expo_sign_char)        // If exponent was specified, ignore prezeros
2045
 
    {
2046
 
      for (;pos > left_wall && pre_zeros_from !=pre_zeros_end;
2047
 
           pre_zeros_from++)
2048
 
        *pos--= '0';
2049
 
    }
2050
 
    if (pos == tmp_right_pos-1)
2051
 
      *pos--= '0';              // no 0 has ever been written, so write one
2052
 
    left_wall= to-1;
2053
 
    if (sign_char && pos != left_wall)
2054
 
    {
2055
 
      /* Write sign if possible (it is if sign is '-') */
2056
 
      *pos--= sign_char;
2057
 
    }
2058
 
    while (pos != left_wall)
2059
 
      *pos--=' ';  //fill with blanks
2060
 
  }
2061
 
  
2062
 
  /*
2063
 
    Write digits of the frac_% parts ;
2064
 
    Depending on table->in_use->count_cutted_fields, we may also want
2065
 
    to know if some non-zero tail of these parts will
2066
 
    be truncated (for example, 0.002->0.00 will generate a warning,
2067
 
    while 0.000->0.00 will not)
2068
 
    (and 0E1000000000 will not, while 1E-1000000000 will)
2069
 
  */
2070
 
      
2071
 
  pos=to+(uint)(field_length-tmp_dec);  // Calculate post to '.'
2072
 
  right_wall=to+field_length;
2073
 
  if (pos != right_wall) 
2074
 
    *pos++='.';
2075
 
 
2076
 
  if (expo_sign_char == '-')
2077
 
  {
2078
 
    while (frac_digits_added_zeros-- > 0)
2079
 
    {
2080
 
      if (pos == right_wall) 
2081
 
      {
2082
 
        if (table->in_use->count_cuted_fields && !is_cuted_fields_incr) 
2083
 
          break; // Go on below to see if we lose non zero digits
2084
 
        return 0;
2085
 
      }
2086
 
      *pos++='0';
2087
 
    }
2088
 
    while (int_digits_end != frac_digits_head_end)
2089
 
    {
2090
 
      tmp_char= *int_digits_end++;
2091
 
      if (pos == right_wall)
2092
 
      {
2093
 
        if (tmp_char != '0')                    // Losing a non zero digit ?
2094
 
        {
2095
 
          if (!is_cuted_fields_incr)
2096
 
            set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, 
2097
 
                        WARN_DATA_TRUNCATED, 1);
2098
 
          return 0;
2099
 
        }
2100
 
        continue;
2101
 
      }
2102
 
      *pos++= tmp_char;
2103
 
    }
2104
 
  }
2105
 
 
2106
 
  for (;frac_digits_from!=frac_digits_end;) 
2107
 
  {
2108
 
    tmp_char= *frac_digits_from++;
2109
 
    if (pos == right_wall)
2110
 
    {
2111
 
      if (tmp_char != '0')                      // Losing a non zero digit ?
2112
 
      {
2113
 
        if (!is_cuted_fields_incr)
2114
 
        {
2115
 
          /*
2116
 
            This is a note, not a warning, as we don't want to abort
2117
 
            when we cut decimals in strict mode
2118
 
          */
2119
 
          set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
2120
 
        }
2121
 
        return 0;
2122
 
      }
2123
 
      continue;
2124
 
    }
2125
 
    *pos++= tmp_char;
2126
 
  }
2127
 
      
2128
 
  while (pos != right_wall)
2129
 
   *pos++='0';                  // Fill with zeros at right of '.'
2130
 
  return 0;
2131
 
}
2132
 
 
2133
 
 
2134
 
int Field_decimal::store(double nr)
2135
 
{
2136
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
2137
 
  if (unsigned_flag && nr < 0)
2138
 
  {
2139
 
    overflow(1);
2140
 
    return 1;
2141
 
  }
2142
 
  
2143
 
  if (!isfinite(nr)) // Handle infinity as special case
2144
 
  {
2145
 
    overflow(nr < 0.0);
2146
 
    return 1;
2147
 
  }
2148
 
 
2149
 
  register uint i;
2150
 
  size_t length;
2151
 
  uchar fyllchar,*to;
2152
 
  char buff[DOUBLE_TO_STRING_CONVERSION_BUFFER_SIZE];
2153
 
 
2154
 
  fyllchar = zerofill ? (char) '0' : (char) ' ';
2155
 
  length= my_fcvt(nr, dec, buff, NULL);
2156
 
 
2157
 
  if (length > field_length)
2158
 
  {
2159
 
    overflow(nr < 0.0);
2160
 
    return 1;
2161
 
  }
2162
 
  else
2163
 
  {
2164
 
    to=ptr;
2165
 
    for (i=field_length-length ; i-- > 0 ;)
2166
 
      *to++ = fyllchar;
2167
 
    memcpy(to,buff,length);
2168
 
    return 0;
2169
 
  }
2170
 
}
2171
 
 
2172
 
 
2173
 
int Field_decimal::store(longlong nr, bool unsigned_val)
2174
 
{
2175
 
  ASSERT_COLUMN_MARKED_FOR_WRITE;
2176
 
  char buff[22];
2177
 
  uint length, int_part;
2178
 
  char fyllchar;
2179
 
  uchar *to;
2180
 
 
2181
 
  if (nr < 0 && unsigned_flag && !unsigned_val)
2182
 
  {
2183
 
    overflow(1);
2184
 
    return 1;
2185
 
  }
2186
 
  length= (uint) (longlong10_to_str(nr,buff,unsigned_val ? 10 : -10) - buff);
2187
 
  int_part= field_length- (dec  ? dec+1 : 0);
2188
 
 
2189
 
  if (length > int_part)
2190
 
  {
2191
 
    overflow(!unsigned_val && nr < 0L);         /* purecov: inspected */
2192
 
    return 1;
2193
 
  }
2194
 
 
2195
 
  fyllchar = zerofill ? (char) '0' : (char) ' ';
2196
 
  to= ptr;
2197
 
  for (uint i=int_part-length ; i-- > 0 ;)
2198
 
    *to++ = fyllchar;
2199
 
  memcpy(to,buff,length);
2200
 
  if (dec)
2201
 
  {
2202
 
    to[length]='.';
2203
 
    bfill(to+length+1,dec,'0');
2204
 
  }
2205
 
  return 0;
2206
 
}
2207
 
 
2208
 
 
2209
 
double Field_decimal::val_real(void)
2210
 
{
2211
 
  ASSERT_COLUMN_MARKED_FOR_READ;
2212
 
  int not_used;
2213
 
  char *end_not_used;
2214
 
  return my_strntod(&my_charset_bin, (char*) ptr, field_length, &end_not_used,
2215
 
                    &not_used);
2216
 
}
2217
 
 
2218
 
longlong Field_decimal::val_int(void)
2219
 
{
2220
 
  ASSERT_COLUMN_MARKED_FOR_READ;
2221
 
  int not_used;
2222
 
  if (unsigned_flag)
2223
 
    return my_strntoull(&my_charset_bin, (char*) ptr, field_length, 10, NULL,
2224
 
                        &not_used);
2225
 
  return my_strntoll(&my_charset_bin, (char*) ptr, field_length, 10, NULL,
2226
 
                     &not_used);
2227
 
}
2228
 
 
2229
 
 
2230
 
String *Field_decimal::val_str(String *val_buffer __attribute__((unused)),
2231
 
                               String *val_ptr)
2232
 
{
2233
 
  ASSERT_COLUMN_MARKED_FOR_READ;
2234
 
  uchar *str;
2235
 
  size_t tmp_length;
2236
 
 
2237
 
  for (str=ptr ; *str == ' ' ; str++) ;
2238
 
  val_ptr->set_charset(&my_charset_bin);
2239
 
  tmp_length= (size_t) (str-ptr);
2240
 
  if (field_length < tmp_length)                // Error in data
2241
 
    val_ptr->length(0);
2242
 
  else
2243
 
    val_ptr->set_ascii((const char*) str, field_length-tmp_length);
2244
 
  return val_ptr;
2245
 
}
2246
 
 
2247
 
/**
2248
 
  Should be able to handle at least the following fixed decimal formats:
2249
 
  5.00 , -1.0,  05,  -05, +5 with optional pre/end space
2250
 
*/
2251
 
 
2252
 
int Field_decimal::cmp(const uchar *a_ptr,const uchar *b_ptr)
2253
 
{
2254
 
  const uchar *end;
2255
 
  int swap=0;
2256
 
  /* First remove prefixes '0', ' ', and '-' */
2257
 
  for (end=a_ptr+field_length;
2258
 
       a_ptr != end &&
2259
 
         (*a_ptr == *b_ptr ||
2260
 
          ((my_isspace(&my_charset_bin,*a_ptr)  || *a_ptr == '+' || 
2261
 
            *a_ptr == '0') &&
2262
 
           (my_isspace(&my_charset_bin,*b_ptr) || *b_ptr == '+' || 
2263
 
            *b_ptr == '0')));
2264
 
       a_ptr++,b_ptr++)
2265
 
  {
2266
 
    if (*a_ptr == '-')                          // If both numbers are negative
2267
 
      swap= -1 ^ 1;                             // Swap result      
2268
 
  }
2269
 
  if (a_ptr == end)
2270
 
    return 0;
2271
 
  if (*a_ptr == '-')
2272
 
    return -1;
2273
 
  if (*b_ptr == '-')
2274
 
    return 1;
2275
 
 
2276
 
  while (a_ptr != end)
2277
 
  {
2278
 
    if (*a_ptr++ != *b_ptr++)
2279
 
      return swap ^ (a_ptr[-1] < b_ptr[-1] ? -1 : 1); // compare digits
2280
 
  }
2281
 
  return 0;
2282
 
}
2283
 
 
2284
 
 
2285
 
void Field_decimal::sort_string(uchar *to,uint length)
2286
 
{
2287
 
  uchar *str,*end;
2288
 
  for (str=ptr,end=ptr+length;
2289
 
       str != end &&
2290
 
         ((my_isspace(&my_charset_bin,*str) || *str == '+' ||
2291
 
           *str == '0')) ;
2292
 
       str++)
2293
 
    *to++=' ';
2294
 
  if (str == end)
2295
 
    return;                                     /* purecov: inspected */
2296
 
 
2297
 
  if (*str == '-')
2298
 
  {
2299
 
    *to++=1;                                    // Smaller than any number
2300
 
    str++;
2301
 
    while (str != end)
2302
 
      if (my_isdigit(&my_charset_bin,*str))
2303
 
        *to++= (char) ('9' - *str++);
2304
 
      else
2305
 
        *to++= *str++;
2306
 
  }
2307
 
  else memcpy(to,str,(uint) (end-str));
2308
 
}
2309
 
 
2310
 
 
2311
 
void Field_decimal::sql_type(String &res) const
2312
 
{
2313
 
  CHARSET_INFO *cs=res.charset();
2314
 
  uint tmp=field_length;
2315
 
  if (!unsigned_flag)
2316
 
    tmp--;
2317
 
  if (dec)
2318
 
    tmp--;
2319
 
  res.length(cs->cset->snprintf(cs,(char*) res.ptr(),res.alloced_length(),
2320
 
                          "decimal(%d,%d)",tmp,dec));
2321
 
  add_zerofill_and_unsigned(res);
2322
 
}
2323
 
 
2324
 
 
2325
 
/****************************************************************************
2326
1718
** Field_new_decimal
2327
1719
****************************************************************************/
2328
1720
 
8697
8089
  case MYSQL_TYPE_VAR_STRING:
8698
8090
    DBUG_ASSERT(0);  /* Impossible. */
8699
8091
    break;
8700
 
  case MYSQL_TYPE_DECIMAL:
8701
 
    DBUG_ASSERT(0); /* Was obsolete */
8702
8092
  }
8703
8093
  /* Remember the value of length */
8704
8094
  char_length= length;
8754
8144
  switch (type) {
8755
8145
  case MYSQL_TYPE_VAR_STRING:
8756
8146
  case MYSQL_TYPE_STRING:
8757
 
  case MYSQL_TYPE_DECIMAL:     return (length);
8758
8147
  case MYSQL_TYPE_VARCHAR:     return (length + (length < 256 ? 1: 2));
8759
8148
  case MYSQL_TYPE_YEAR:
8760
8149
  case MYSQL_TYPE_TINY  : return 1;
8831
8220
    if (!f_is_packed(pack_flag))
8832
8221
    {
8833
8222
      if (field_type == MYSQL_TYPE_STRING ||
8834
 
          field_type == MYSQL_TYPE_DECIMAL ||   // 3.23 or 4.0 string
8835
8223
          field_type == MYSQL_TYPE_VAR_STRING)
8836
8224
        return new Field_string(ptr,field_length,null_pos,null_bit,
8837
8225
                                unireg_check, field_name,
8868
8256
  }
8869
8257
 
8870
8258
  switch (field_type) {
8871
 
  case MYSQL_TYPE_DECIMAL:
8872
 
    return new Field_decimal(ptr,field_length,null_pos,null_bit,
8873
 
                             unireg_check, field_name,
8874
 
                             f_decimals(pack_flag),
8875
 
                             f_is_zerofill(pack_flag) != 0,
8876
 
                             f_is_dec(pack_flag) == 0);
8877
8259
  case MYSQL_TYPE_NEWDECIMAL:
8878
8260
    return new Field_new_decimal(ptr,field_length,null_pos,null_bit,
8879
8261
                                 unireg_check, field_name,