~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/field/decimal.cc

  • Committer: Monty Taylor
  • Date: 2009-03-04 02:48:12 UTC
  • mto: (917.1.2 mordred)
  • mto: This revision was merged to the branch mainline in revision 918.
  • Revision ID: mordred@inaugust.com-20090304024812-5wb6wpye5c1iitbq
Applied atomic patch to current tree.

Show diffs side-by-side

added added

removed removed

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