~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/fdecimal.cc

Removed/replaced DBUG symbols and standardized TRUE/FALSE

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 MySQL
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; either version 2 of the License, or
9
 
 *  (at your option) any later version.
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., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19
 
 */
20
 
 
21
 
 
22
 
#include <drizzled/server_includes.h>
23
 
#include <drizzled/field/fdecimal.h>
24
 
#include <drizzled/drizzled_error_messages.h>
25
 
 
26
 
 
27
 
/****************************************************************************
28
 
** Field_new_decimal
29
 
****************************************************************************/
30
 
 
31
 
Field_new_decimal::Field_new_decimal(unsigned char *ptr_arg,
32
 
                                     uint32_t len_arg, unsigned char *null_ptr_arg,
33
 
                                     unsigned char null_bit_arg,
34
 
                                     enum utype unireg_check_arg,
35
 
                                     const char *field_name_arg,
36
 
                                     uint8_t dec_arg,bool zero_arg,
37
 
                                     bool unsigned_arg)
38
 
  :Field_num(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
39
 
             unireg_check_arg, field_name_arg, dec_arg, zero_arg, unsigned_arg)
40
 
{
41
 
  precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
42
 
  set_if_smaller(precision, DECIMAL_MAX_PRECISION);
43
 
  assert((precision <= DECIMAL_MAX_PRECISION) &&
44
 
              (dec <= DECIMAL_MAX_SCALE));
45
 
  bin_size= my_decimal_get_binary_size(precision, dec);
46
 
}
47
 
 
48
 
 
49
 
Field_new_decimal::Field_new_decimal(uint32_t len_arg,
50
 
                                     bool maybe_null_arg,
51
 
                                     const char *name,
52
 
                                     uint8_t dec_arg,
53
 
                                     bool unsigned_arg)
54
 
  :Field_num((unsigned char*) 0, len_arg,
55
 
             maybe_null_arg ? (unsigned char*) "": 0, 0,
56
 
             NONE, name, dec_arg, 0, unsigned_arg)
57
 
{
58
 
  precision= my_decimal_length_to_precision(len_arg, dec_arg, unsigned_arg);
59
 
  set_if_smaller(precision, DECIMAL_MAX_PRECISION);
60
 
  assert((precision <= DECIMAL_MAX_PRECISION) &&
61
 
              (dec <= DECIMAL_MAX_SCALE));
62
 
  bin_size= my_decimal_get_binary_size(precision, dec);
63
 
}
64
 
 
65
 
 
66
 
int Field_new_decimal::reset(void)
67
 
{
68
 
  store_value(&decimal_zero);
69
 
  return 0;
70
 
}
71
 
 
72
 
 
73
 
/**
74
 
  Generate max/min decimal value in case of overflow.
75
 
 
76
 
  @param decimal_value     buffer for value
77
 
  @param sign              sign of value which caused overflow
78
 
*/
79
 
 
80
 
void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
81
 
                                              bool sign)
82
 
{
83
 
  max_my_decimal(decimal_value, precision, decimals());
84
 
  if (sign)
85
 
    decimal_value->sign(true);
86
 
 
87
 
  return;
88
 
}
89
 
 
90
 
 
91
 
/**
92
 
  Store decimal value in the binary buffer.
93
 
 
94
 
  Checks if decimal_value fits into field size.
95
 
  If it does, stores the decimal in the buffer using binary format.
96
 
  Otherwise sets maximal number that can be stored in the field.
97
 
 
98
 
  @param decimal_value   my_decimal
99
 
 
100
 
  @retval
101
 
    0 ok
102
 
  @retval
103
 
    1 error
104
 
*/
105
 
 
106
 
bool Field_new_decimal::store_value(const my_decimal *decimal_value)
107
 
{
108
 
  int error= 0;
109
 
 
110
 
  if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
111
 
                                         decimal_value, ptr, precision, dec)))
112
 
  {
113
 
    my_decimal buff;
114
 
    set_value_on_overflow(&buff, decimal_value->sign());
115
 
    my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec);
116
 
    error= 1;
117
 
  }
118
 
  return(error);
119
 
}
120
 
 
121
 
 
122
 
int Field_new_decimal::store(const char *from, uint32_t length,
123
 
                             const CHARSET_INFO * const charset_arg)
124
 
{
125
 
  int err;
126
 
  my_decimal decimal_value;
127
 
 
128
 
  if ((err= str2my_decimal(E_DEC_FATAL_ERROR &
129
 
                           ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
130
 
                           from, length, charset_arg,
131
 
                           &decimal_value)) &&
132
 
      table->in_use->abort_on_warning)
133
 
  {
134
 
    /* Because "from" is not NUL-terminated and we use %s in the ER() */
135
 
    String from_as_str;
136
 
    from_as_str.copy(from, length, &my_charset_bin);
137
 
 
138
 
    push_warning_printf(table->in_use, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
139
 
                        ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
140
 
                        ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
141
 
                        "decimal", from_as_str.c_ptr(), field_name,
142
 
                        (uint32_t) table->in_use->row_count);
143
 
 
144
 
    return(err);
145
 
  }
146
 
 
147
 
  switch (err) {
148
 
  case E_DEC_TRUNCATED:
149
 
    set_warning(DRIZZLE_ERROR::WARN_LEVEL_NOTE, ER_WARN_DATA_TRUNCATED, 1);
150
 
    break;
151
 
  case E_DEC_OVERFLOW:
152
 
    set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
153
 
    set_value_on_overflow(&decimal_value, decimal_value.sign());
154
 
    break;
155
 
  case E_DEC_BAD_NUM:
156
 
    {
157
 
      /* Because "from" is not NUL-terminated and we use %s in the ER() */
158
 
      String from_as_str;
159
 
      from_as_str.copy(from, length, &my_charset_bin);
160
 
 
161
 
    push_warning_printf(table->in_use, DRIZZLE_ERROR::WARN_LEVEL_WARN,
162
 
                        ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
163
 
                        ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
164
 
                          "decimal", from_as_str.c_ptr(), field_name,
165
 
                        (uint32_t) table->in_use->row_count);
166
 
    my_decimal_set_zero(&decimal_value);
167
 
 
168
 
    break;
169
 
    }
170
 
  }
171
 
 
172
 
  store_value(&decimal_value);
173
 
  return(err);
174
 
}
175
 
 
176
 
 
177
 
/**
178
 
  @todo
179
 
  Fix following when double2my_decimal when double2decimal
180
 
  will return E_DEC_TRUNCATED always correctly
181
 
*/
182
 
 
183
 
int Field_new_decimal::store(double nr)
184
 
{
185
 
  my_decimal decimal_value;
186
 
  int err;
187
 
 
188
 
  err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
189
 
                         &decimal_value);
190
 
  if (err)
191
 
  {
192
 
    if (check_overflow(err))
193
 
      set_value_on_overflow(&decimal_value, decimal_value.sign());
194
 
    /* Only issue a warning if store_value doesn't issue an warning */
195
 
    table->in_use->got_warning= 0;
196
 
  }
197
 
  if (store_value(&decimal_value))
198
 
    err= 1;
199
 
  else if (err && !table->in_use->got_warning)
200
 
    err= warn_if_overflow(err);
201
 
  return(err);
202
 
}
203
 
 
204
 
 
205
 
int Field_new_decimal::store(int64_t nr, bool unsigned_val)
206
 
{
207
 
  my_decimal decimal_value;
208
 
  int err;
209
 
 
210
 
  if ((err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
211
 
                           nr, unsigned_val, &decimal_value)))
212
 
  {
213
 
    if (check_overflow(err))
214
 
      set_value_on_overflow(&decimal_value, decimal_value.sign());
215
 
    /* Only issue a warning if store_value doesn't issue an warning */
216
 
    table->in_use->got_warning= 0;
217
 
  }
218
 
  if (store_value(&decimal_value))
219
 
    err= 1;
220
 
  else if (err && !table->in_use->got_warning)
221
 
    err= warn_if_overflow(err);
222
 
  return err;
223
 
}
224
 
 
225
 
 
226
 
int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
227
 
{
228
 
  return store_value(decimal_value);
229
 
}
230
 
 
231
 
 
232
 
int Field_new_decimal::store_time(DRIZZLE_TIME *ltime,
233
 
                                  enum enum_drizzle_timestamp_type t_type __attribute__((unused)))
234
 
{
235
 
    my_decimal decimal_value;
236
 
    return store_value(date2my_decimal(ltime, &decimal_value));
237
 
}
238
 
 
239
 
 
240
 
double Field_new_decimal::val_real(void)
241
 
{
242
 
  double dbl;
243
 
  my_decimal decimal_value;
244
 
  my_decimal2double(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), &dbl);
245
 
  return dbl;
246
 
}
247
 
 
248
 
 
249
 
int64_t Field_new_decimal::val_int(void)
250
 
{
251
 
  int64_t i;
252
 
  my_decimal decimal_value;
253
 
  my_decimal2int(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), false, &i);
254
 
  return i;
255
 
}
256
 
 
257
 
 
258
 
my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
259
 
{
260
 
  binary2my_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value,
261
 
                    precision, dec);
262
 
  return(decimal_value);
263
 
}
264
 
 
265
 
 
266
 
String *Field_new_decimal::val_str(String *val_buffer,
267
 
                                   String *val_ptr __attribute__((unused)))
268
 
{
269
 
  my_decimal decimal_value;
270
 
  uint32_t fixed_precision= decimal_precision ? precision : 0;
271
 
  my_decimal2string(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
272
 
                    fixed_precision, dec, '0', val_buffer);
273
 
  return val_buffer;
274
 
}
275
 
 
276
 
 
277
 
int Field_new_decimal::cmp(const unsigned char *a,const unsigned char*b)
278
 
{
279
 
  return memcmp(a, b, bin_size);
280
 
}
281
 
 
282
 
 
283
 
void Field_new_decimal::sort_string(unsigned char *buff,
284
 
                                    uint32_t length __attribute__((unused)))
285
 
{
286
 
  memcpy(buff, ptr, bin_size);
287
 
}
288
 
 
289
 
 
290
 
void Field_new_decimal::sql_type(String &str) const
291
 
{
292
 
  const CHARSET_INFO * const cs= str.charset();
293
 
  str.length(cs->cset->snprintf(cs, (char*) str.ptr(), str.alloced_length(),
294
 
                                "decimal(%d,%d)", precision, (int)dec));
295
 
}
296
 
 
297
 
 
298
 
/**
299
 
   Save the field metadata for new decimal fields.
300
 
 
301
 
   Saves the precision in the first byte and decimals() in the second
302
 
   byte of the field metadata array at index of *metadata_ptr and 
303
 
   *(metadata_ptr + 1).
304
 
 
305
 
   @param   metadata_ptr   First byte of field metadata
306
 
 
307
 
   @returns number of bytes written to metadata_ptr
308
 
*/
309
 
int Field_new_decimal::do_save_field_metadata(unsigned char *metadata_ptr)
310
 
{
311
 
  *metadata_ptr= precision;
312
 
  *(metadata_ptr + 1)= decimals();
313
 
  return 2;
314
 
}
315
 
 
316
 
 
317
 
/**
318
 
   Returns the number of bytes field uses in row-based replication 
319
 
   row packed size.
320
 
 
321
 
   This method is used in row-based replication to determine the number
322
 
   of bytes that the field consumes in the row record format. This is
323
 
   used to skip fields in the master that do not exist on the slave.
324
 
 
325
 
   @param   field_metadata   Encoded size in field metadata
326
 
 
327
 
   @returns The size of the field based on the field metadata.
328
 
*/
329
 
uint32_t Field_new_decimal::pack_length_from_metadata(uint32_t field_metadata)
330
 
{
331
 
  uint32_t const source_precision= (field_metadata >> 8U) & 0x00ff;
332
 
  uint32_t const source_decimal= field_metadata & 0x00ff; 
333
 
  uint32_t const source_size= my_decimal_get_binary_size(source_precision, 
334
 
                                                     source_decimal);
335
 
  return (source_size);
336
 
}
337
 
 
338
 
 
339
 
/**
340
 
   Check to see if field size is compatible with destination.
341
 
 
342
 
   This method is used in row-based replication to verify that the slave's
343
 
   field size is less than or equal to the master's field size. The 
344
 
   encoded field metadata (from the master or source) is decoded and compared
345
 
   to the size of this field (the slave or destination). 
346
 
 
347
 
   @param   field_metadata   Encoded size in field metadata
348
 
 
349
 
   @retval 0 if this field's size is < the source field's size
350
 
   @retval 1 if this field's size is >= the source field's size
351
 
*/
352
 
int Field_new_decimal::compatible_field_size(uint32_t field_metadata)
353
 
{
354
 
  int compatible= 0;
355
 
  uint32_t const source_precision= (field_metadata >> 8U) & 0x00ff;
356
 
  uint32_t const source_decimal= field_metadata & 0x00ff; 
357
 
  uint32_t const source_size= my_decimal_get_binary_size(source_precision, 
358
 
                                                     source_decimal);
359
 
  uint32_t const destination_size= row_pack_length();
360
 
  compatible= (source_size <= destination_size);
361
 
  if (compatible)
362
 
    compatible= (source_precision <= precision) &&
363
 
                (source_decimal <= decimals());
364
 
  return (compatible);
365
 
}
366
 
 
367
 
 
368
 
uint32_t Field_new_decimal::is_equal(Create_field *new_field)
369
 
{
370
 
  return ((new_field->sql_type == real_type()) &&
371
 
          ((new_field->flags & UNSIGNED_FLAG) == 
372
 
           (uint) (flags & UNSIGNED_FLAG)) &&
373
 
          ((new_field->flags & AUTO_INCREMENT_FLAG) ==
374
 
           (uint) (flags & AUTO_INCREMENT_FLAG)) &&
375
 
          (new_field->length == max_display_length()) &&
376
 
          (new_field->decimals == dec));
377
 
}
378
 
 
379
 
 
380
 
/**
381
 
   Unpack a decimal field from row data.
382
 
 
383
 
   This method is used to unpack a decimal or numeric field from a master
384
 
   whose size of the field is less than that of the slave.
385
 
  
386
 
   @param   to         Destination of the data
387
 
   @param   from       Source of the data
388
 
   @param   param_data Precision (upper) and decimal (lower) values
389
 
 
390
 
   @return  New pointer into memory based on from + length of the data
391
 
*/
392
 
const unsigned char *
393
 
Field_new_decimal::unpack(unsigned char* to,
394
 
                          const unsigned char *from,
395
 
                          uint32_t param_data,
396
 
                          bool low_byte_first)
397
 
{
398
 
  if (param_data == 0)
399
 
    return Field::unpack(to, from, param_data, low_byte_first);
400
 
 
401
 
  uint32_t from_precision= (param_data & 0xff00) >> 8U;
402
 
  uint32_t from_decimal= param_data & 0x00ff;
403
 
  uint32_t length=pack_length();
404
 
  uint32_t from_pack_len= my_decimal_get_binary_size(from_precision, from_decimal);
405
 
  uint32_t len= (param_data && (from_pack_len < length)) ?
406
 
            from_pack_len : length;
407
 
  if ((from_pack_len && (from_pack_len < length)) ||
408
 
      (from_precision < precision) ||
409
 
      (from_decimal < decimals()))
410
 
  {
411
 
    /*
412
 
      If the master's data is smaller than the slave, we need to convert
413
 
      the binary to decimal then resize the decimal converting it back to
414
 
      a decimal and write that to the raw data buffer.
415
 
    */
416
 
    decimal_digit_t dec_buf[DECIMAL_MAX_PRECISION];
417
 
    decimal_t dec;
418
 
    dec.len= from_precision;
419
 
    dec.buf= dec_buf;
420
 
    /*
421
 
      Note: bin2decimal does not change the length of the field. So it is
422
 
      just the first step the resizing operation. The second step does the
423
 
      resizing using the precision and decimals from the slave.
424
 
    */
425
 
    bin2decimal((unsigned char *)from, &dec, from_precision, from_decimal);
426
 
    decimal2bin(&dec, to, precision, decimals());
427
 
  }
428
 
  else
429
 
    memcpy(to, from, len); // Sizes are the same, just copy the data.
430
 
  return from+len;
431
 
}
432