~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/decimal.cc

  • Committer: Lee Bieber
  • Date: 2010-11-07 19:34:48 UTC
  • mfrom: (1910.1.2 build)
  • Revision ID: kalebral@gmail.com-20101107193448-64kdu912qej354sh
Merge Stewart - including adapting and expanding the "differences from mysql" page from the wiki.
Merge Stewart - fix bug 668143: drizzleslap with --commit runs second iteration data load in a transaction

Show diffs side-by-side

added added

removed removed

Lines of Context:
108
108
#include "drizzled/definitions.h"
109
109
#include "drizzled/internal/m_string.h"
110
110
#include "drizzled/charset_info.h"
111
 
#include "drizzled/type/decimal.h"
 
111
#include "drizzled/decimal.h"
112
112
 
113
113
#include <plugin/myisam/myisampack.h>
114
114
#include <drizzled/util/test.h>
178
178
/**
179
179
  @brief Converting decimal to string
180
180
 
181
 
  @details Convert given type::Decimal to String; allocate buffer as needed.
 
181
  @details Convert given my_decimal to String; allocate buffer as needed.
182
182
 
183
183
  @param[in]   mask        what problems to warn on (mask of E_DEC_* values)
184
184
  @param[in]   d           the decimal to print
194
194
    @retval E_DEC_OOM
195
195
*/
196
196
 
197
 
int class_decimal2string(const type::Decimal *d,
198
 
                         uint32_t fixed_dec, String *str)
 
197
int my_decimal2string(uint32_t mask, const my_decimal *d,
 
198
                      uint32_t fixed_prec, uint32_t fixed_dec,
 
199
                      char filler, String *str)
199
200
{
200
 
  uint32_t mask= E_DEC_FATAL_ERROR;
201
 
 
202
201
  /*
203
202
    Calculate the size of the string: For DECIMAL(a,b), fixed_prec==a
204
203
    holds true iff the type is also ZEROFILL, which in turn implies
207
206
    one if the user only wanted decimal places, but we force a leading
208
207
    zero on them. Because the type is implicitly UNSIGNED, we do not
209
208
    need to reserve a character for the sign. For all other cases,
210
 
    fixed_prec will be 0, and class_decimal_string_length() will be called
 
209
    fixed_prec will be 0, and my_decimal_string_length() will be called
211
210
    instead to calculate the required size of the buffer.
212
211
  */
213
 
  int length= (int)(0
214
 
                    ? (uint32_t)(((0 == fixed_dec) ? 1 : 0) + 1)
215
 
                    : (uint32_t)d->string_length());
 
212
  int length= (int)(fixed_prec
 
213
                    ? (uint32_t)(fixed_prec + ((fixed_prec == fixed_dec) ? 1 : 0) + 1)
 
214
                    : (uint32_t)my_decimal_string_length(d));
216
215
  int result;
217
216
  if (str->alloc(length))
218
217
    return check_result(mask, E_DEC_OOM);
219
 
 
220
218
  result= decimal2string((decimal_t*) d, (char*) str->ptr(),
221
 
                         &length, (int)0, fixed_dec,
222
 
                         '0');
 
219
                         &length, (int)fixed_prec, fixed_dec,
 
220
                         filler);
223
221
  str->length(length);
224
222
  return check_result(mask, result);
225
223
}
244
242
   @retval E_DEC_OVERFLOW
245
243
*/
246
244
 
247
 
namespace type {
248
 
 
249
 
int Decimal::val_binary(uint32_t mask, unsigned char *bin, int prec, int scale) const
 
245
int my_decimal2binary(uint32_t mask, const my_decimal *d, unsigned char *bin, int prec,
 
246
                      int scale)
250
247
{
251
248
  int err1= E_DEC_OK, err2;
252
 
  type::Decimal rounded;
253
 
  class_decimal2decimal(this, &rounded);
 
249
  my_decimal rounded;
 
250
  my_decimal2decimal(d, &rounded);
254
251
  rounded.frac= decimal_actual_fraction(&rounded);
255
252
  if (scale < rounded.frac)
256
253
  {
264
261
  return check_result(mask, err2);
265
262
}
266
263
 
267
 
} // namespace type
268
 
 
269
264
 
270
265
/**
271
266
  @brief Convert string for decimal when string can be in some multibyte charset
274
269
  @param  from            string to process
275
270
  @param  length          length of given string
276
271
  @param  charset         charset of given string
 
272
  @param  decimal_value   buffer for result storing
277
273
 
278
274
  @return Error code
279
275
   @retval E_DEC_OK
283
279
   @retval E_DEC_OOM
284
280
*/
285
281
 
286
 
int type::Decimal::store(uint32_t mask, const char *from, uint32_t length, const CHARSET_INFO * charset)
 
282
int str2my_decimal(uint32_t mask, const char *from, uint32_t length,
 
283
                   const CHARSET_INFO * charset, my_decimal *decimal_value)
287
284
{
288
285
  char *end, *from_end;
289
286
  int err;
298
295
    charset= &my_charset_bin;
299
296
  }
300
297
  from_end= end= (char*) from+length;
301
 
  err= string2decimal((char *)from, (decimal_t*) this, &end);
 
298
  err= string2decimal((char *)from, (decimal_t*) decimal_value, &end);
302
299
  if (end != from_end && !err)
303
300
  {
304
301
    /* Give warning if there is something other than end space */
311
308
      }
312
309
    }
313
310
  }
314
 
  check_result_and_overflow(mask, err);
 
311
  check_result_and_overflow(mask, err, decimal_value);
315
312
  return err;
316
313
}
317
314
 
318
 
void type::Decimal::convert(double &result) const
319
 
{
320
 
  decimal2double(static_cast<const decimal_t*>(this), &result);
321
 
}
322
315
 
323
 
type::Decimal *date2_class_decimal(type::Time *ltime, type::Decimal *dec)
 
316
my_decimal *date2my_decimal(DRIZZLE_TIME *ltime, my_decimal *dec)
324
317
{
325
318
  int64_t date;
326
319
  date = (ltime->year*100L + ltime->month)*100L + ltime->day;
327
 
  if (ltime->time_type > type::DRIZZLE_TIMESTAMP_DATE)
 
320
  if (ltime->time_type > DRIZZLE_TIMESTAMP_DATE)
328
321
    date= ((date*100L + ltime->hour)*100L+ ltime->minute)*100L + ltime->second;
329
 
 
330
 
  if (int2_class_decimal(E_DEC_FATAL_ERROR, date, false, dec))
 
322
  if (int2my_decimal(E_DEC_FATAL_ERROR, date, false, dec))
331
323
    return dec;
332
 
 
333
324
  if (ltime->second_part)
334
325
  {
335
326
    dec->buf[(dec->intg-1) / 9 + 1]= ltime->second_part * 1000;
336
327
    dec->frac= 6;
337
328
  }
338
 
 
339
329
  return dec;
340
330
}
341
331
 
342
332
 
343
 
void class_decimal_trim(uint32_t *precision, uint32_t *scale)
 
333
void my_decimal_trim(uint32_t *precision, uint32_t *scale)
344
334
{
345
335
  if (!(*precision) && !(*scale))
346
336
  {
837
827
 
838
828
  if (beg == end)
839
829
  {
840
 
    dec->set_zero();
 
830
    decimal_make_zero(dec);
841
831
    return E_DEC_OK;
842
832
  }
843
833
 
870
860
        we lost all digits (they will be shifted out of buffer), so we can
871
861
        just return 0
872
862
      */
873
 
      dec->set_zero();
874
 
 
 
863
      decimal_make_zero(dec);
875
864
      return E_DEC_TRUNCATED;
876
865
    }
877
866
  }
1163
1152
  return error;
1164
1153
 
1165
1154
fatal_error:
1166
 
  to->set_zero();
 
1155
  decimal_make_zero(to);
1167
1156
  return error;
1168
1157
}
1169
1158
 
1632
1621
  return error;
1633
1622
 
1634
1623
err:
1635
 
  to->set_zero();
 
1624
  decimal_make_zero(((decimal_t*) to));
1636
1625
  return(E_DEC_BAD_NUM);
1637
1626
}
1638
1627
 
1699
1688
 
1700
1689
  if (scale+from->intg < 0)
1701
1690
  {
1702
 
    to->set_zero();
 
1691
    decimal_make_zero(to);
1703
1692
    return E_DEC_OK;
1704
1693
  }
1705
1694
 
1770
1759
    }
1771
1760
    else if (frac0+intg0==0)
1772
1761
    {
1773
 
      to->set_zero();
 
1762
      decimal_make_zero(to);
1774
1763
      return E_DEC_OK;
1775
1764
    }
1776
1765
  }
1995
1984
      {
1996
1985
        if (to == 0) /* decimal_cmp() */
1997
1986
          return 0;
1998
 
 
1999
 
        to->set_zero();
2000
 
 
 
1987
        decimal_make_zero(to);
2001
1988
        return E_DEC_OK;
2002
1989
      }
2003
1990
    }
2108
2095
  return from1->sign > from2->sign ? -1 : 1;
2109
2096
}
2110
2097
 
2111
 
int decimal_t::isZero() const
 
2098
int decimal_is_zero(const decimal_t *from)
2112
2099
{
2113
 
  dec1 *buf1= buf,
2114
 
       *end= buf1 +round_up(intg) +round_up(frac);
2115
 
 
 
2100
  dec1 *buf1=from->buf,
 
2101
       *end=buf1+round_up(from->intg)+round_up(from->frac);
2116
2102
  while (buf1 < end)
2117
 
  {
2118
2103
    if (*buf1++)
2119
 
    {
2120
2104
      return 0;
2121
 
    }
2122
 
  }
2123
 
 
2124
2105
  return 1;
2125
2106
}
2126
2107
 
2228
2209
      if (++buf == end)
2229
2210
      {
2230
2211
        /* We got decimal zero */
2231
 
        to->set_zero();
 
2212
        decimal_make_zero(to);
2232
2213
        break;
2233
2214
      }
2234
2215
    }
2298
2279
  }
2299
2280
  if (prec1 <= 0)
2300
2281
  { /* short-circuit everything: from1 == 0 */
2301
 
    to->set_zero();
 
2282
    decimal_make_zero(to);
2302
2283
    return E_DEC_OK;
2303
2284
  }
2304
2285
  for (i=(prec1-1) % DIG_PER_DEC1; *buf1 < powers10[i--]; prec1--) ;
2458
2439
    error=E_DEC_OK;
2459
2440
    if (unlikely(frac0==0 && intg0==0))
2460
2441
    {
2461
 
      to->set_zero();
 
2442
      decimal_make_zero(to);
2462
2443
      goto done;
2463
2444
    }
2464
2445
    if (intg0<=0)
2465
2446
    {
2466
2447
      if (unlikely(-intg0 >= to->len))
2467
2448
      {
2468
 
        to->set_zero();
 
2449
        decimal_make_zero(to);
2469
2450
        error=E_DEC_TRUNCATED;
2470
2451
        goto done;
2471
2452
      }
2552
2533
  return do_div_mod(from1, from2, 0, to, 0);
2553
2534
}
2554
2535
 
2555
 
std::ostream& operator<<(std::ostream& output, const type::Decimal &dec)
2556
 
{
2557
 
  drizzled::String str;
2558
 
 
2559
 
  class_decimal2string(&dec, 0, &str);
2560
 
 
2561
 
  output << "type::Decimal:(";
2562
 
  output <<  str.c_ptr();
2563
 
  output << ")";
2564
 
 
2565
 
  return output;  // for multiple << operators.
2566
 
}
2567
 
 
2568
2536
} /* namespace drizzled */
2569
2537
 
2570
2538
#ifdef MAIN
3298
3266
 
3299
3267
  return 0;
3300
3268
}
3301
 
 
3302
3269
#endif