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
22
#include <drizzled/server_includes.h>
23
#include <drizzled/field/fdecimal.h>
24
#include <drizzled/drizzled_error_messages.h>
27
/****************************************************************************
29
****************************************************************************/
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,
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)
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);
49
Field_new_decimal::Field_new_decimal(uint32_t len_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)
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);
66
int Field_new_decimal::reset(void)
68
store_value(&decimal_zero);
74
Generate max/min decimal value in case of overflow.
76
@param decimal_value buffer for value
77
@param sign sign of value which caused overflow
80
void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
83
max_my_decimal(decimal_value, precision, decimals());
85
decimal_value->sign(true);
92
Store decimal value in the binary buffer.
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.
98
@param decimal_value my_decimal
106
bool Field_new_decimal::store_value(const my_decimal *decimal_value)
110
if (warn_if_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
111
decimal_value, ptr, precision, dec)))
114
set_value_on_overflow(&buff, decimal_value->sign());
115
my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, precision, dec);
122
int Field_new_decimal::store(const char *from, uint32_t length,
123
const CHARSET_INFO * const charset_arg)
126
my_decimal decimal_value;
128
if ((err= str2my_decimal(E_DEC_FATAL_ERROR &
129
~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
130
from, length, charset_arg,
132
table->in_use->abort_on_warning)
134
/* Because "from" is not NUL-terminated and we use %s in the ER() */
136
from_as_str.copy(from, length, &my_charset_bin);
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);
148
case E_DEC_TRUNCATED:
149
set_warning(DRIZZLE_ERROR::WARN_LEVEL_NOTE, ER_WARN_DATA_TRUNCATED, 1);
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());
157
/* Because "from" is not NUL-terminated and we use %s in the ER() */
159
from_as_str.copy(from, length, &my_charset_bin);
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);
172
store_value(&decimal_value);
179
Fix following when double2my_decimal when double2decimal
180
will return E_DEC_TRUNCATED always correctly
183
int Field_new_decimal::store(double nr)
185
my_decimal decimal_value;
188
err= double2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW, nr,
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;
197
if (store_value(&decimal_value))
199
else if (err && !table->in_use->got_warning)
200
err= warn_if_overflow(err);
205
int Field_new_decimal::store(int64_t nr, bool unsigned_val)
207
my_decimal decimal_value;
210
if ((err= int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
211
nr, unsigned_val, &decimal_value)))
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;
218
if (store_value(&decimal_value))
220
else if (err && !table->in_use->got_warning)
221
err= warn_if_overflow(err);
226
int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
228
return store_value(decimal_value);
232
int Field_new_decimal::store_time(DRIZZLE_TIME *ltime,
233
enum enum_drizzle_timestamp_type t_type __attribute__((unused)))
235
my_decimal decimal_value;
236
return store_value(date2my_decimal(ltime, &decimal_value));
240
double Field_new_decimal::val_real(void)
243
my_decimal decimal_value;
244
my_decimal2double(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), &dbl);
249
int64_t Field_new_decimal::val_int(void)
252
my_decimal decimal_value;
253
my_decimal2int(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), false, &i);
258
my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
260
binary2my_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value,
262
return(decimal_value);
266
String *Field_new_decimal::val_str(String *val_buffer,
267
String *val_ptr __attribute__((unused)))
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);
277
int Field_new_decimal::cmp(const unsigned char *a,const unsigned char*b)
279
return memcmp(a, b, bin_size);
283
void Field_new_decimal::sort_string(unsigned char *buff,
284
uint32_t length __attribute__((unused)))
286
memcpy(buff, ptr, bin_size);
290
void Field_new_decimal::sql_type(String &str) const
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));
299
Save the field metadata for new decimal fields.
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
305
@param metadata_ptr First byte of field metadata
307
@returns number of bytes written to metadata_ptr
309
int Field_new_decimal::do_save_field_metadata(unsigned char *metadata_ptr)
311
*metadata_ptr= precision;
312
*(metadata_ptr + 1)= decimals();
318
Returns the number of bytes field uses in row-based replication
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.
325
@param field_metadata Encoded size in field metadata
327
@returns The size of the field based on the field metadata.
329
uint32_t Field_new_decimal::pack_length_from_metadata(uint32_t field_metadata)
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,
335
return (source_size);
340
Check to see if field size is compatible with destination.
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).
347
@param field_metadata Encoded size in field metadata
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
352
int Field_new_decimal::compatible_field_size(uint32_t field_metadata)
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,
359
uint32_t const destination_size= row_pack_length();
360
compatible= (source_size <= destination_size);
362
compatible= (source_precision <= precision) &&
363
(source_decimal <= decimals());
368
uint32_t Field_new_decimal::is_equal(Create_field *new_field)
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));
381
Unpack a decimal field from row data.
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.
386
@param to Destination of the data
387
@param from Source of the data
388
@param param_data Precision (upper) and decimal (lower) values
390
@return New pointer into memory based on from + length of the data
392
const unsigned char *
393
Field_new_decimal::unpack(unsigned char* to,
394
const unsigned char *from,
399
return Field::unpack(to, from, param_data, low_byte_first);
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()))
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.
416
decimal_digit_t dec_buf[DECIMAL_MAX_PRECISION];
418
dec.len= from_precision;
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.
425
bin2decimal((unsigned char *)from, &dec, from_precision, from_decimal);
426
decimal2bin(&dec, to, precision, decimals());
429
memcpy(to, from, len); // Sizes are the same, just copy the data.