1
/* - mode: c++ c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 MySQL
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.
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.
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
21
#ifdef USE_PRAGMA_IMPLEMENTATION
22
#pragma implementation // gcc: Class implementation
25
#include <drizzled/server_includes.h>
26
#include <drizzled/field/fdecimal.h>
27
#include <drizzled/drizzled_error_messages.h>
30
/****************************************************************************
32
****************************************************************************/
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,
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)
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);
52
Field_new_decimal::Field_new_decimal(uint32_t len_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)
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);
69
int Field_new_decimal::reset(void)
71
store_value(&decimal_zero);
77
Generate max/min decimal value in case of overflow.
79
@param decimal_value buffer for value
80
@param sign sign of value which caused overflow
83
void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
86
max_my_decimal(decimal_value, precision, decimals());
90
my_decimal_set_zero(decimal_value);
92
decimal_value->sign(true);
99
Store decimal value in the binary buffer.
101
Checks if decimal_value fits into field size.
102
If it does, stores the decimal in the buffer using binary format.
103
Otherwise sets maximal number that can be stored in the field.
105
@param decimal_value my_decimal
113
bool Field_new_decimal::store_value(const my_decimal *decimal_value)
117
/* check that we do not try to write negative value in unsigned field */
118
if (unsigned_flag && decimal_value->sign())
120
set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
122
decimal_value= &decimal_zero;
125
if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
126
decimal_value, ptr, precision, dec)))
129
set_value_on_overflow(&buff, decimal_value->sign());
130
my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec);
137
int Field_new_decimal::store(const char *from, uint32_t length,
138
const CHARSET_INFO * const charset_arg)
141
my_decimal decimal_value;
143
if ((err= str2my_decimal(E_DEC_FATAL_ERROR &
144
~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
145
from, length, charset_arg,
147
table->in_use->abort_on_warning)
149
/* Because "from" is not NUL-terminated and we use %s in the ER() */
151
from_as_str.copy(from, length, &my_charset_bin);
153
push_warning_printf(table->in_use, DRIZZLE_ERROR::WARN_LEVEL_ERROR,
154
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
155
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
156
"decimal", from_as_str.c_ptr(), field_name,
157
(uint32_t) table->in_use->row_count);
163
case E_DEC_TRUNCATED:
164
set_warning(DRIZZLE_ERROR::WARN_LEVEL_NOTE, ER_WARN_DATA_TRUNCATED, 1);
167
set_warning(DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
168
set_value_on_overflow(&decimal_value, decimal_value.sign());
172
/* Because "from" is not NUL-terminated and we use %s in the ER() */
174
from_as_str.copy(from, length, &my_charset_bin);
176
push_warning_printf(table->in_use, DRIZZLE_ERROR::WARN_LEVEL_WARN,
177
ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
178
ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
179
"decimal", from_as_str.c_ptr(), field_name,
180
(uint32_t) table->in_use->row_count);
181
my_decimal_set_zero(&decimal_value);
187
store_value(&decimal_value);
194
Fix following when double2my_decimal when double2decimal
195
will return E_DEC_TRUNCATED always correctly
198
int Field_new_decimal::store(double nr)
200
my_decimal decimal_value;
203
err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
207
if (check_overflow(err))
208
set_value_on_overflow(&decimal_value, decimal_value.sign());
209
/* Only issue a warning if store_value doesn't issue an warning */
210
table->in_use->got_warning= 0;
212
if (store_value(&decimal_value))
214
else if (err && !table->in_use->got_warning)
215
err= warn_if_overflow(err);
220
int Field_new_decimal::store(int64_t nr, bool unsigned_val)
222
my_decimal decimal_value;
225
if ((err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
226
nr, unsigned_val, &decimal_value)))
228
if (check_overflow(err))
229
set_value_on_overflow(&decimal_value, decimal_value.sign());
230
/* Only issue a warning if store_value doesn't issue an warning */
231
table->in_use->got_warning= 0;
233
if (store_value(&decimal_value))
235
else if (err && !table->in_use->got_warning)
236
err= warn_if_overflow(err);
241
int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
243
return store_value(decimal_value);
247
int Field_new_decimal::store_time(DRIZZLE_TIME *ltime,
248
enum enum_drizzle_timestamp_type t_type __attribute__((unused)))
250
my_decimal decimal_value;
251
return store_value(date2my_decimal(ltime, &decimal_value));
255
double Field_new_decimal::val_real(void)
258
my_decimal decimal_value;
259
my_decimal2double(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), &dbl);
264
int64_t Field_new_decimal::val_int(void)
267
my_decimal decimal_value;
268
my_decimal2int(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
274
my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
276
binary2my_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value,
278
return(decimal_value);
282
String *Field_new_decimal::val_str(String *val_buffer,
283
String *val_ptr __attribute__((unused)))
285
my_decimal decimal_value;
286
uint32_t fixed_precision= decimal_precision ? precision : 0;
287
my_decimal2string(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
288
fixed_precision, dec, '0', val_buffer);
293
int Field_new_decimal::cmp(const unsigned char *a,const unsigned char*b)
295
return memcmp(a, b, bin_size);
299
void Field_new_decimal::sort_string(unsigned char *buff,
300
uint32_t length __attribute__((unused)))
302
memcpy(buff, ptr, bin_size);
306
void Field_new_decimal::sql_type(String &str) const
308
const CHARSET_INFO * const cs= str.charset();
309
str.length(cs->cset->snprintf(cs, (char*) str.ptr(), str.alloced_length(),
310
"decimal(%d,%d)", precision, (int)dec));
316
Save the field metadata for new decimal fields.
318
Saves the precision in the first byte and decimals() in the second
319
byte of the field metadata array at index of *metadata_ptr and
322
@param metadata_ptr First byte of field metadata
324
@returns number of bytes written to metadata_ptr
326
int Field_new_decimal::do_save_field_metadata(unsigned char *metadata_ptr)
328
*metadata_ptr= precision;
329
*(metadata_ptr + 1)= decimals();
335
Returns the number of bytes field uses in row-based replication
338
This method is used in row-based replication to determine the number
339
of bytes that the field consumes in the row record format. This is
340
used to skip fields in the master that do not exist on the slave.
342
@param field_metadata Encoded size in field metadata
344
@returns The size of the field based on the field metadata.
346
uint32_t Field_new_decimal::pack_length_from_metadata(uint32_t field_metadata)
348
uint32_t const source_precision= (field_metadata >> 8U) & 0x00ff;
349
uint32_t const source_decimal= field_metadata & 0x00ff;
350
uint32_t const source_size= my_decimal_get_binary_size(source_precision,
352
return (source_size);
357
Check to see if field size is compatible with destination.
359
This method is used in row-based replication to verify that the slave's
360
field size is less than or equal to the master's field size. The
361
encoded field metadata (from the master or source) is decoded and compared
362
to the size of this field (the slave or destination).
364
@param field_metadata Encoded size in field metadata
366
@retval 0 if this field's size is < the source field's size
367
@retval 1 if this field's size is >= the source field's size
369
int Field_new_decimal::compatible_field_size(uint32_t field_metadata)
372
uint32_t const source_precision= (field_metadata >> 8U) & 0x00ff;
373
uint32_t const source_decimal= field_metadata & 0x00ff;
374
uint32_t const source_size= my_decimal_get_binary_size(source_precision,
376
uint32_t const destination_size= row_pack_length();
377
compatible= (source_size <= destination_size);
379
compatible= (source_precision <= precision) &&
380
(source_decimal <= decimals());
385
uint32_t Field_new_decimal::is_equal(Create_field *new_field)
387
return ((new_field->sql_type == real_type()) &&
388
((new_field->flags & UNSIGNED_FLAG) ==
389
(uint) (flags & UNSIGNED_FLAG)) &&
390
((new_field->flags & AUTO_INCREMENT_FLAG) ==
391
(uint) (flags & AUTO_INCREMENT_FLAG)) &&
392
(new_field->length == max_display_length()) &&
393
(new_field->decimals == dec));
398
Unpack a decimal field from row data.
400
This method is used to unpack a decimal or numeric field from a master
401
whose size of the field is less than that of the slave.
403
@param to Destination of the data
404
@param from Source of the data
405
@param param_data Precision (upper) and decimal (lower) values
407
@return New pointer into memory based on from + length of the data
409
const unsigned char *
410
Field_new_decimal::unpack(unsigned char* to,
411
const unsigned char *from,
416
return Field::unpack(to, from, param_data, low_byte_first);
418
uint32_t from_precision= (param_data & 0xff00) >> 8U;
419
uint32_t from_decimal= param_data & 0x00ff;
420
uint32_t length=pack_length();
421
uint32_t from_pack_len= my_decimal_get_binary_size(from_precision, from_decimal);
422
uint32_t len= (param_data && (from_pack_len < length)) ?
423
from_pack_len : length;
424
if ((from_pack_len && (from_pack_len < length)) ||
425
(from_precision < precision) ||
426
(from_decimal < decimals()))
429
If the master's data is smaller than the slave, we need to convert
430
the binary to decimal then resize the decimal converting it back to
431
a decimal and write that to the raw data buffer.
433
decimal_digit_t dec_buf[DECIMAL_MAX_PRECISION];
435
dec.len= from_precision;
438
Note: bin2decimal does not change the length of the field. So it is
439
just the first step the resizing operation. The second step does the
440
resizing using the precision and decimals from the slave.
442
bin2decimal((unsigned char *)from, &dec, from_precision, from_decimal);
443
decimal2bin(&dec, to, precision, decimals());
446
memcpy(to, from, len); // Sizes are the same, just copy the data.