summaryrefslogtreecommitdiff
path: root/sql/field.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/field.cc')
-rw-r--r--sql/field.cc586
1 files changed, 556 insertions, 30 deletions
diff --git a/sql/field.cc b/sql/field.cc
index f95eaaba5df..ad66fec2fc2 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -52,6 +52,25 @@ const char field_separator=',';
Static help functions
*****************************************************************************/
+/*
+ Numeric fields base class constructor
+*/
+Field_num::Field_num(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg,
+ uint8 dec_arg, bool zero_arg, bool unsigned_arg)
+ :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg),
+ dec(dec_arg),zerofill(zero_arg),unsigned_flag(unsigned_arg)
+{
+ if (zerofill)
+ flags|=ZEROFILL_FLAG;
+ if (unsigned_flag)
+ flags|=UNSIGNED_FLAG;
+}
+
+
void Field_num::prepend_zeros(String *value)
{
int diff;
@@ -82,7 +101,7 @@ void Field_num::prepend_zeros(String *value)
Make this multi-byte-character safe
RETURN
- 0 ok
+ 0 OK
1 error. A warning is pushed if field_name != 0
*/
@@ -104,7 +123,7 @@ bool Field::check_int(const char *str, int length, const char *int_end,
}
end= str+length;
if ((str= int_end) == end)
- return 0; // ok; All digits was used
+ return 0; // OK; All digits was used
/* Allow end .0000 */
if (*str == '.')
@@ -125,6 +144,32 @@ bool Field::check_int(const char *str, int length, const char *int_end,
}
+/*
+ Process decimal library return codes and issue warnings for overflow and
+ truncation.
+
+ SYNOPSIS
+ Field::check_overflow()
+ op_result decimal library return code (E_DEC_* see include/decimal.h)
+
+ RETURN
+ 1 there was overflow
+ 0 no error or some other errors except overflow
+*/
+
+int Field::check_overflow(int op_result)
+{
+ if (op_result == E_DEC_OVERFLOW)
+ {
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ return 1;
+ }
+ else if (op_result == E_DEC_TRUNCATED)
+ set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
+ /* we return 1 only in case of EFL */
+ return 0;
+}
+
#ifdef NOT_USED
static bool test_if_real(const char *str,int length, CHARSET_INFO *cs)
{
@@ -191,6 +236,10 @@ static Field::field_cast_enum field_cast_decimal[]=
{Field::FIELD_CAST_DECIMAL,
Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
+static Field::field_cast_enum field_cast_new_decimal[]=
+{Field::FIELD_CAST_NEWDECIMAL,
+ Field::FIELD_CAST_STRING, Field::FIELD_CAST_VARSTRING,
+ Field::FIELD_CAST_BLOB, Field::FIELD_CAST_STOP};
static Field::field_cast_enum field_cast_tiny[]=
{Field::FIELD_CAST_TINY,
Field::FIELD_CAST_SHORT, Field::FIELD_CAST_MEDIUM, Field::FIELD_CAST_LONG,
@@ -283,6 +332,9 @@ static Field::field_cast_enum field_cast_varstring[]=
static Field::field_cast_enum field_cast_blob[]=
{Field::FIELD_CAST_BLOB,
Field::FIELD_CAST_STOP};
+static Field::field_cast_enum field_cast_bit[]=
+{Field::FIELD_CAST_BIT,
+ Field::FIELD_CAST_STOP};
/*
Geometrical, enum and set fields can be casted only to expressions
*/
@@ -302,7 +354,8 @@ static Field::field_cast_enum *field_cast_array[]=
field_cast_timestamp, field_cast_year, field_cast_date, field_cast_newdate,
field_cast_time, field_cast_datetime,
field_cast_string, field_cast_varstring, field_cast_blob,
- field_cast_geom, field_cast_enum, field_cast_set
+ field_cast_geom, field_cast_enum, field_cast_set, field_cast_bit,
+ field_cast_new_decimal
};
@@ -398,6 +451,14 @@ bool Field::send_binary(Protocol *protocol)
}
+my_decimal *Field::val_decimal(my_decimal *decimal)
+{
+ /* This never have to be called */
+ DBUG_ASSERT(0);
+ return 0;
+}
+
+
void Field_num::add_zerofill_and_unsigned(String &res) const
{
if (unsigned_flag)
@@ -406,6 +467,7 @@ void Field_num::add_zerofill_and_unsigned(String &res) const
res.append(" zerofill");
}
+
void Field::make_field(Send_field *field)
{
field->db_name= orig_table->s->table_cache_key;
@@ -420,12 +482,155 @@ void Field::make_field(Send_field *field)
}
+/*
+ Conversion from decimal to longlong with checking overflow and
+ setting correct value (min/max) in case of overflow
+
+ SYNOPSIS
+ Field::convert_decimal2longlong()
+ val value which have to be converted
+ unsigned_flag type of integer in which we convert val
+ err variable to pass error code
+
+ RETURN
+ value converted from val
+*/
+longlong Field::convert_decimal2longlong(const my_decimal *val,
+ bool unsigned_flag, int *err)
+{
+ longlong i;
+ if (unsigned_flag)
+ {
+ if (val->sign())
+ {
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ i= 0;
+ *err= 1;
+ }
+ else if (check_overflow(my_decimal2int(E_DEC_ERROR &
+ ~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED,
+ val, TRUE, &i)))
+ {
+ i= ~(longlong) 0;
+ *err= 1;
+ }
+ }
+ else if (check_overflow(my_decimal2int(E_DEC_ERROR &
+ ~E_DEC_OVERFLOW & ~E_DEC_TRUNCATED,
+ val, FALSE, &i)))
+ {
+ i= (val->sign() ? LONGLONG_MIN : LONGLONG_MAX);
+ *err= 1;
+ }
+ return i;
+}
+
+
+/*
+ Storing decimal in integer fields.
+
+ SYNOPSIS
+ Field_num::store_decimal()
+ val value for storing
+
+ NOTE
+ This method is used by all integer fields, real/decimal redefine it
+
+ RETURN
+ 0 OK
+ != 0 error
+*/
+
+int Field_num::store_decimal(const my_decimal *val)
+{
+ int err= 0;
+ longlong i= convert_decimal2longlong(val, unsigned_flag, &err);
+ return test(err | store(i));
+}
+
+
+/*
+ Return decimal value of integer field
+
+ SYNOPSIS
+ Field_num::val_decimal()
+ decimal_value buffer for storing decimal value
+
+ NOTE
+ This method is used by all integer fields, real/decimal redefine it
+ All longlong values fit in our decimal buffer which cal store 8*9=72
+ digits of integer number
+
+ RETURN
+ pointer to decimal buffer with value of field
+*/
+
+my_decimal* Field_num::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(result_type() == INT_RESULT);
+ longlong nr= val_int();
+ if (!is_null())
+ int2my_decimal(E_DEC_FATAL_ERROR, nr, unsigned_flag, decimal_value);
+ return decimal_value;
+}
+
+
+Field_str::Field_str(char *ptr_arg,uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg, utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg,CHARSET_INFO *charset)
+ :Field(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg)
+{
+ field_charset=charset;
+ if (charset->state & MY_CS_BINSORT)
+ flags|=BINARY_FLAG;
+}
+
+
void Field_num::make_field(Send_field *field)
{
Field::make_field(field);
field->decimals= dec;
}
+/*
+ Decimal representation of Field_str
+
+ SYNOPSIS
+ Field_str::store_decimal()
+ d value for storing
+
+ NOTE
+ Field_str is the base class for fields like Field_date, and some
+ similar. Some dates use fraction and also string value should be
+ converted to floating point value according our rules, so we use double
+ to store value of decimal in string
+
+ RETURN
+ 0 OK
+ != 0 error
+*/
+
+int Field_str::store_decimal(const my_decimal *d)
+{
+ double val;
+ /* TODO: use decimal2string? */
+ int err= check_overflow(my_decimal2double(E_DEC_FATAL_ERROR &
+ ~E_DEC_OVERFLOW, d, &val));
+ return err | store(val);
+}
+
+
+my_decimal *Field_str::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ASSERT(result_type() == INT_RESULT);
+ longlong nr= val_int();
+ if (is_null())
+ int2my_decimal(E_DEC_FATAL_ERROR, nr, 0, decimal_value);
+ return decimal_value;
+}
+
uint Field::fill_cache_field(CACHE_FIELD *copy)
{
@@ -697,7 +902,7 @@ void Field_decimal::overflow(bool negative)
int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
{
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmp(buff,sizeof(buff), &my_charset_bin);
/* Convert character set if the old one is multi byte */
@@ -838,7 +1043,7 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
/*
We only have to generate warnings if count_cuted_fields is set.
This is to avoid extra checks of the number when they are not needed.
- Even if this flag is not set, it's ok to increment warnings, if
+ Even if this flag is not set, it's OK to increment warnings, if
it makes the code easer to read.
*/
@@ -1255,6 +1460,275 @@ void Field_decimal::sql_type(String &res) const
/****************************************************************************
+** Field_new_decimal
+****************************************************************************/
+
+/*
+ Constructors of new decimal field. In case of using NOT_FIXED_DEC it try
+ to use maximally allowed length (DECIMAL_MAX_LENGTH) and number of digits
+ after decimal point maximally close to half of this range
+ (min(DECIMAL_MAX_LENGTH/2, NOT_FIXED_DEC-1))
+*/
+Field_new_decimal::Field_new_decimal(char *ptr_arg,
+ uint32 len_arg, uchar *null_ptr_arg,
+ uchar null_bit_arg,
+ enum utype unireg_check_arg,
+ const char *field_name_arg,
+ struct st_table *table_arg,
+ uint8 dec_arg,bool zero_arg,
+ bool unsigned_arg)
+ :Field_num(ptr_arg,
+ (dec_arg == NOT_FIXED_DEC || len_arg > DECIMAL_MAX_LENGTH ?
+ DECIMAL_MAX_LENGTH : len_arg),
+ null_ptr_arg, null_bit_arg,
+ unireg_check_arg, field_name_arg, table_arg,
+ (dec_arg == NOT_FIXED_DEC ?
+ min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1) :
+ dec_arg),
+ zero_arg, unsigned_arg)
+{
+ bin_size= my_decimal_get_binary_size(field_length, dec);
+}
+
+
+Field_new_decimal::Field_new_decimal(uint32 len_arg,
+ bool maybe_null,
+ const char *name,
+ struct st_table *t_arg,
+ uint8 dec_arg)
+ :Field_num((char*) 0,
+ (dec_arg == NOT_FIXED_DEC|| len_arg > DECIMAL_MAX_LENGTH ?
+ DECIMAL_MAX_LENGTH : len_arg),
+ maybe_null ? (uchar*) "": 0, 0,
+ NONE, name, t_arg,
+ (dec_arg == NOT_FIXED_DEC ?
+ min(DECIMAL_MAX_LENGTH / 2, NOT_FIXED_DEC - 1) :
+ dec_arg),
+ 0, 0)
+{
+ bin_size= my_decimal_get_binary_size(field_length, dec);
+}
+
+
+void Field_new_decimal::reset(void)
+{
+ store_value(&decimal_zero);
+}
+
+
+/*
+ Generate max/min decimal value in case of overflow.
+
+ SYNOPSIS
+ Field_new_decimal::set_value_on_overflow();
+ decimal_value buffer for value
+ sign sign of value which caused overflow
+*/
+
+void Field_new_decimal::set_value_on_overflow(my_decimal *decimal_value,
+ bool sign)
+{
+ DBUG_ENTER("Field_new_decimal::set_value_on_overflow");
+ max_my_decimal(decimal_value, field_length, decimals());
+ if (sign)
+ {
+ if (unsigned_flag)
+ my_decimal_set_zero(decimal_value);
+ else
+ decimal_value->sign(TRUE);
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+/*
+ Store decimal value in the binary buffer
+
+ SYNOPSIS
+ store_value(const my_decimal *decimal_value)
+ decimal_value my_decimal
+
+ DESCRIPTION
+ checks if decimal_value fits into field size.
+ if it does, stores the decimal in the buffer using binary format.
+ Otherwise sets maximal number that can be stored in the field.
+*/
+
+bool Field_new_decimal::store_value(const my_decimal *decimal_value)
+{
+ DBUG_ENTER("Field_new_decimal::store_value");
+ my_decimal *dec= (my_decimal*)decimal_value;
+ DBUG_EXECUTE("enter", print_decimal(dec););
+
+ /* check that we do not try to write negative value in unsigned field */
+ if (unsigned_flag && decimal_value->sign())
+ {
+ DBUG_PRINT("info", ("unsigned overflow"));
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ dec= &decimal_zero;
+ }
+ DBUG_PRINT("info", ("saving with precision %d, scale: %d",
+ (int)field_length, (int)decimals()));
+ DBUG_EXECUTE("info", print_decimal(dec););
+
+ if (check_overflow(my_decimal2binary(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
+ dec, ptr,
+ field_length,
+ decimals())))
+ {
+ my_decimal buff;
+ DBUG_PRINT("info", ("overflow"));
+ set_value_on_overflow(&buff, dec->sign());
+ my_decimal2binary(E_DEC_FATAL_ERROR, &buff, ptr, field_length, decimals());
+ DBUG_EXECUTE("info", print_decimal_buff(&buff, ptr, bin_size););
+ DBUG_RETURN(1);
+ }
+ DBUG_EXECUTE("info", print_decimal_buff(dec, ptr, bin_size););
+ DBUG_RETURN(0);
+}
+
+
+int Field_new_decimal::store(const char *from, uint length,
+ CHARSET_INFO *charset)
+{
+ DBUG_ENTER("Field_new_decimal::store(char*)");
+ int err;
+ my_decimal decimal_value;
+ switch ((err= str2my_decimal(E_DEC_FATAL_ERROR &
+ ~(E_DEC_OVERFLOW | E_DEC_BAD_NUM),
+ from, length, charset, &decimal_value)))
+ {
+ case E_DEC_TRUNCATED:
+ set_warning(MYSQL_ERROR::WARN_LEVEL_NOTE, WARN_DATA_TRUNCATED, 1);
+ break;
+ case E_DEC_OVERFLOW:
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
+ set_value_on_overflow(&decimal_value, decimal_value.sign());
+ break;
+ case E_DEC_BAD_NUM:
+ push_warning_printf(table->in_use, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_TRUNCATED_WRONG_VALUE_FOR_FIELD,
+ ER(ER_TRUNCATED_WRONG_VALUE_FOR_FIELD),
+ "decimal", from, field_name,
+ (ulong) table->in_use->row_count);
+ my_decimal_set_zero(&decimal_value);
+ break;
+ }
+
+ DBUG_EXECUTE("info", print_decimal(&decimal_value););
+ store_value(&decimal_value);
+ DBUG_RETURN(err);
+}
+
+
+int Field_new_decimal::store(double nr)
+{
+ my_decimal decimal_value;
+ int err= double2my_decimal(E_DEC_FATAL_ERROR &
+ ~E_DEC_OVERFLOW, nr,
+ &decimal_value);
+ /*
+ TODO: fix following when double2my_decimal when double2decimal
+ will return E_DEC_TRUNCATED always correctly
+ */
+ if (!err)
+ {
+ double nr2;
+ my_decimal2double(E_DEC_FATAL_ERROR, &decimal_value, &nr2);
+ if (nr2 != nr)
+ err= E_DEC_TRUNCATED;
+ }
+ if (check_overflow(err))
+ set_value_on_overflow(&decimal_value, decimal_value.sign());
+ store_value(&decimal_value);
+ return err;
+}
+
+
+int Field_new_decimal::store(longlong nr)
+{
+ my_decimal decimal_value;
+ int err;
+ if ((err= check_overflow(int2my_decimal(E_DEC_FATAL_ERROR & ~E_DEC_OVERFLOW,
+ nr, unsigned_flag, &decimal_value))))
+ set_value_on_overflow(&decimal_value, decimal_value.sign());
+ store_value(&decimal_value);
+ return err;
+}
+
+
+int Field_new_decimal::store_decimal(const my_decimal *decimal_value)
+{
+ return store_value(decimal_value);
+}
+
+
+double Field_new_decimal::val_real(void)
+{
+ double dbl;
+ my_decimal decimal_value;
+ my_decimal2double(E_DEC_FATAL_ERROR, val_decimal(&decimal_value), &dbl);
+ return dbl;
+}
+
+
+longlong Field_new_decimal::val_int(void)
+{
+ longlong i;
+ my_decimal decimal_value;
+ my_decimal2int(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
+ unsigned_flag, &i);
+ return i;
+}
+
+
+my_decimal* Field_new_decimal::val_decimal(my_decimal *decimal_value)
+{
+ DBUG_ENTER("Field_new_decimal::val_decimal");
+ binary2my_decimal(E_DEC_FATAL_ERROR, ptr, decimal_value,
+ field_length,
+ decimals());
+ DBUG_EXECUTE("info", print_decimal_buff(decimal_value, ptr, bin_size););
+ DBUG_RETURN(decimal_value);
+}
+
+
+String *Field_new_decimal::val_str(String *val_buffer,
+ String *val_ptr __attribute__((unused)))
+{
+ my_decimal decimal_value;
+ int fixed_precision= (zerofill ?
+ (field_length + (decimals() ? 1 : 0)) :
+ 0);
+ my_decimal2string(E_DEC_FATAL_ERROR, val_decimal(&decimal_value),
+ fixed_precision, decimals(), '0',
+ val_buffer);
+ return val_buffer;
+}
+
+
+int Field_new_decimal::cmp(const char *a,const char*b)
+{
+ return memcmp(a, b, bin_size);
+}
+
+
+void Field_new_decimal::sort_string(char *buff,
+ uint length __attribute__((unused)))
+{
+ memcpy(buff, ptr, bin_size);
+}
+
+
+void Field_new_decimal::sql_type(String &str) const
+{
+ CHARSET_INFO *cs= str.charset();
+ str.length(cs->cset->snprintf(cs, (char*) str.ptr(), str.alloced_length(),
+ "decimal(%d,%d)", field_length, (int)dec));
+ add_zerofill_and_unsigned(str);
+}
+
+/****************************************************************************
** tiny int
****************************************************************************/
@@ -2554,7 +3028,6 @@ int Field_float::store(longlong nr)
return store((double)nr);
}
-
double Field_float::val_real(void)
{
float j;
@@ -2835,6 +3308,12 @@ int Field_double::store(longlong nr)
return store((double)nr);
}
+int Field_real::store_decimal(const my_decimal *dm)
+{
+ double dbl;
+ my_decimal2double(E_DEC_FATAL_ERROR, dm, &dbl);
+ return store(dbl);
+}
double Field_double::val_real(void)
{
@@ -2865,6 +3344,13 @@ longlong Field_double::val_int(void)
}
+my_decimal *Field_real::val_decimal(my_decimal *decimal_value)
+{
+ double2my_decimal(E_DEC_FATAL_ERROR, val_real(), decimal_value);
+ return decimal_value;
+}
+
+
String *Field_double::val_str(String *val_buffer,
String *val_ptr __attribute__((unused)))
{
@@ -3032,7 +3518,7 @@ void Field_double::sql_type(String &res) const
TIMESTAMP_OLD_FIELD - old timestamp, if there was not any fields with
auto-set-on-update (or now() as default) in this table before, then this
field has NOW() as default and is updated when row changes, else it is
- field which has 0 as default value and is not automaitcally updated.
+ field which has 0 as default value and is not automatically updated.
TIMESTAMP_DN_FIELD - field with NOW() as default but not set on update
automatically (TIMESTAMP DEFAULT NOW())
TIMESTAMP_UN_FIELD - field which is set on update automatically but has not
@@ -3094,7 +3580,7 @@ timestamp_auto_set_type Field_timestamp::get_auto_set_type() const
return TIMESTAMP_AUTO_SET_ON_UPDATE;
case TIMESTAMP_OLD_FIELD:
/*
- Altough we can have several such columns in legacy tables this
+ Although we can have several such columns in legacy tables this
function should be called only for first of them (i.e. the one
having auto-set property).
*/
@@ -3598,7 +4084,7 @@ String *Field_time::val_str(String *val_buffer,
/*
- Normally we would not consider 'time' as a vaild date, but we allow
+ Normally we would not consider 'time' as a valid date, but we allow
get_date() here to be able to do things like
DATE_FORMAT(time, "%l.%i %p")
*/
@@ -4319,7 +4805,7 @@ String *Field_datetime::val_str(String *val_buffer,
longlongget(tmp,ptr);
/*
- Avoid problem with slow longlong aritmetic and sprintf
+ Avoid problem with slow longlong arithmetic and sprintf
*/
part1=(long) (tmp/LL(1000000));
@@ -4437,14 +4923,14 @@ int Field_string::store(const char *from,uint length,CHARSET_INFO *cs)
{
int error= 0;
uint32 not_used;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
uint copy_length;
/* See the comment for Field_long::store(long long) */
DBUG_ASSERT(table->in_use == current_thd);
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used))
{
uint conv_errors;
@@ -4542,6 +5028,16 @@ int Field_string::store(longlong nr)
return Field_string::store(buff,(uint)l,cs);
}
+int Field_longstr::store_decimal(const my_decimal *d)
+{
+ uint buf_size= my_decimal_string_length(d);
+ char *buff= (char *)my_alloca(buf_size);
+ String str(buff, buf_size, &my_charset_bin);
+ my_decimal2string(E_DEC_FATAL_ERROR, d, 0, 0, 0, &str);
+ int result= store(str.ptr(), str.length(), str.charset());
+ my_afree(buff);
+ return result;
+}
double Field_string::val_real(void)
{
@@ -4561,6 +5057,14 @@ longlong Field_string::val_int(void)
}
+my_decimal *Field_longstr::val_decimal(my_decimal *decimal_value)
+{
+ str2my_decimal(E_DEC_FATAL_ERROR, ptr, field_length, charset(),
+ decimal_value);
+ return decimal_value;
+}
+
+
String *Field_string::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
@@ -4792,11 +5296,11 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
int error= 0;
uint32 not_used, copy_length;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
enum MYSQL_ERROR::enum_warning_level level= MYSQL_ERROR::WARN_LEVEL_WARN;
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used))
{
uint conv_errors;
@@ -4872,7 +5376,6 @@ longlong Field_varstring::val_int(void)
&end_not_used, &not_used);
}
-
String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
@@ -5273,7 +5776,7 @@ Field_blob::Field_blob(char *ptr_arg, uchar *null_ptr_arg, uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg,uint blob_pack_length,
CHARSET_INFO *cs)
- :Field_str(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L,
+ :Field_longstr(ptr_arg, (1L << min(blob_pack_length,3)*8)-1L,
null_ptr_arg, null_bit_arg, unireg_check_arg, field_name_arg,
table_arg, cs),
packlength(blob_pack_length)
@@ -5396,12 +5899,12 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
else
{
bool was_conversion;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
uint copy_length;
uint32 not_used;
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if ((was_conversion= String::needs_conversion(length, cs, field_charset,
&not_used)))
{
@@ -5415,7 +5918,7 @@ int Field_blob::store(const char *from,uint length,CHARSET_INFO *cs)
copy_length= max_data_length();
/*
- copy_length is ok as last argument to well_formed_len as this is never
+ copy_length is OK as last argument to well_formed_len as this is never
used to limit the length of the data. The cut of long data is done with
the 'min()' call below.
*/
@@ -5457,7 +5960,6 @@ int Field_blob::store(longlong nr)
return Field_blob::store(value.ptr(), (uint) value.length(), cs);
}
-
double Field_blob::val_real(void)
{
int not_used;
@@ -5485,7 +5987,6 @@ longlong Field_blob::val_int(void)
return my_strntoll(charset(),blob,length,10,NULL,&not_used);
}
-
String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
@@ -5998,10 +6499,10 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
{
int err= 0;
uint32 not_used;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used))
{
uint dummy_errors;
@@ -6182,10 +6683,10 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
char *not_used;
uint not_used2;
uint32 not_used_offset;
- char buff[80];
+ char buff[STRING_BUFFER_USUAL_SIZE];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
- /* Convert character set if nesessary */
+ /* Convert character set if necessary */
if (String::needs_conversion(length, cs, field_charset, &not_used_offset))
{
uint dummy_errors;
@@ -6444,6 +6945,14 @@ int Field_bit::store(longlong nr)
}
+int Field_bit::store_decimal(const my_decimal *val)
+{
+ int err= 0;
+ longlong i= convert_decimal2longlong(val, 1, &err);
+ return test(err | store(i));
+}
+
+
double Field_bit::val_real(void)
{
return (double) Field_bit::val_int();
@@ -6487,6 +6996,13 @@ String *Field_bit::val_str(String *val_buffer,
}
+my_decimal *Field_bit::val_decimal(my_decimal *deciaml_value)
+{
+ int2my_decimal(E_DEC_FATAL_ERROR, val_int(), 1, deciaml_value);
+ return deciaml_value;
+}
+
+
int Field_bit::key_cmp(const byte *str, uint length)
{
if (bit_len)
@@ -6593,6 +7109,9 @@ void create_field::create_length_to_internal_length(void)
/* We need one extra byte to store the bits we save among the null bits */
key_length= pack_length+ test(length & 7);
break;
+ case MYSQL_TYPE_NEWDECIMAL:
+ key_length= pack_length= my_decimal_get_binary_size(length, decimals);
+ break;
default:
key_length= pack_length= calc_pack_length(sql_type, length);
break;
@@ -6646,7 +7165,8 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
case FIELD_TYPE_LONG_BLOB: return 4+portable_sizeof_char_ptr;
case FIELD_TYPE_GEOMETRY: return 4+portable_sizeof_char_ptr;
case FIELD_TYPE_SET:
- case FIELD_TYPE_ENUM: abort(); return 0; // This shouldn't happen
+ case FIELD_TYPE_ENUM:
+ case FIELD_TYPE_NEWDECIMAL: abort(); return 0; // This shouldn't happen
case FIELD_TYPE_BIT: return length / 8;
default: return 0;
}
@@ -6767,6 +7287,12 @@ Field *make_field(char *ptr, uint32 field_length,
f_decimals(pack_flag),
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
+ case FIELD_TYPE_NEWDECIMAL:
+ return new Field_new_decimal(ptr,field_length,null_pos,null_bit,
+ unireg_check, field_name, table,
+ f_decimals(pack_flag),
+ f_is_zerofill(pack_flag) != 0,
+ f_is_dec(pack_flag) == 0);
case FIELD_TYPE_FLOAT:
return new Field_float(ptr,field_length,null_pos,null_bit,
unireg_check, field_name, table,
@@ -6959,7 +7485,7 @@ create_field::create_field(Field *old_field,Field *orig_field)
/*
Produce warning or note about data saved into field
- SYNOPSYS
+ SYNOPSIS
set_warning()
level - level of message (Note/Warning/Error)
code - error code of message to be produced
@@ -6991,7 +7517,7 @@ Field::set_warning(const uint level, const uint code, int cuted_increment)
/*
Produce warning or note about datetime string data saved into field
- SYNOPSYS
+ SYNOPSIS
set_datime_warning()
level - level of message (Note/Warning/Error)
code - error code of message to be produced
@@ -7020,7 +7546,7 @@ Field::set_datetime_warning(const uint level, const uint code,
/*
Produce warning or note about integer datetime value saved into field
- SYNOPSYS
+ SYNOPSIS
set_warning()
level - level of message (Note/Warning/Error)
code - error code of message to be produced
@@ -7052,7 +7578,7 @@ Field::set_datetime_warning(const uint level, const uint code,
/*
Produce warning or note about double datetime data saved into field
- SYNOPSYS
+ SYNOPSIS
set_warning()
level - level of message (Note/Warning/Error)
code - error code of message to be produced