MDEV-9397 Split field.cc:calc_pack_length() into virtual methods in Type_handler

- Adding new virtual methods in Type_handler:
  * Column_definition_prepare_stage1()
  * Column_definition_prepare_stage2()
  * calc_pack_length()

- Using new methods to remove type specific code in:
  * Global function calc_pack_length()
  * Column_definition::prepare_create_field()
  * The loop body mysql_prepare_create_table()
  * Column_definition::sp_prepare_create_field()
This commit is contained in:
Alexander Barkov 2017-05-17 12:21:39 +04:00
parent f1b729d352
commit fba7fbbc5c
7 changed files with 849 additions and 380 deletions

View File

@ -53,15 +53,6 @@
static const char *zero_timestamp="0000-00-00 00:00:00.000000"; static const char *zero_timestamp="0000-00-00 00:00:00.000000";
LEX_CSTRING temp_lex_str= {"temp", 4}; LEX_CSTRING temp_lex_str= {"temp", 4};
/* number of bytes to store second_part part of the TIMESTAMP(N) */
static uint sec_part_bytes[MAX_DATETIME_PRECISION+1]= { 0, 1, 1, 2, 2, 3, 3 };
/* number of bytes to store DATETIME(N) */
static uint datetime_hires_bytes[MAX_DATETIME_PRECISION+1]= { 5, 6, 6, 7, 7, 7, 8 };
/* number of bytes to store TIME(N) */
static uint time_hires_bytes[MAX_DATETIME_PRECISION+1]= { 3, 4, 4, 5, 5, 5, 6 };
uchar Field_null::null[1]={1}; uchar Field_null::null[1]={1};
const char field_separator=','; const char field_separator=',';
@ -5226,14 +5217,14 @@ static longlong read_bigendian(const uchar *from, uint bytes)
void Field_timestamp_hires::store_TIME(my_time_t timestamp, ulong sec_part) void Field_timestamp_hires::store_TIME(my_time_t timestamp, ulong sec_part)
{ {
mi_int4store(ptr, timestamp); mi_int4store(ptr, timestamp);
store_bigendian(sec_part_shift(sec_part, dec), ptr+4, sec_part_bytes[dec]); store_bigendian(sec_part_shift(sec_part, dec), ptr+4, sec_part_bytes(dec));
} }
my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos, my_time_t Field_timestamp_hires::get_timestamp(const uchar *pos,
ulong *sec_part) const ulong *sec_part) const
{ {
ASSERT_COLUMN_MARKED_FOR_READ; ASSERT_COLUMN_MARKED_FOR_READ;
*sec_part= (long)sec_part_unshift(read_bigendian(pos+4, sec_part_bytes[dec]), dec); *sec_part= (long)sec_part_unshift(read_bigendian(pos+4, sec_part_bytes(dec)), dec);
return mi_uint4korr(pos); return mi_uint4korr(pos);
} }
@ -5300,19 +5291,14 @@ int Field_timestamp_hires::cmp(const uchar *a_ptr, const uchar *b_ptr)
int32 a,b; int32 a,b;
ulong a_sec_part, b_sec_part; ulong a_sec_part, b_sec_part;
a= mi_uint4korr(a_ptr); a= mi_uint4korr(a_ptr);
a_sec_part= (ulong)read_bigendian(a_ptr+4, sec_part_bytes[dec]); a_sec_part= (ulong)read_bigendian(a_ptr+4, sec_part_bytes(dec));
b= mi_uint4korr(b_ptr); b= mi_uint4korr(b_ptr);
b_sec_part= (ulong)read_bigendian(b_ptr+4, sec_part_bytes[dec]); b_sec_part= (ulong)read_bigendian(b_ptr+4, sec_part_bytes(dec));
return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 : return ((uint32) a < (uint32) b) ? -1 : ((uint32) a > (uint32) b) ? 1 :
a_sec_part < b_sec_part ? -1 : a_sec_part > b_sec_part ? 1 : 0; a_sec_part < b_sec_part ? -1 : a_sec_part > b_sec_part ? 1 : 0;
} }
uint32 Field_timestamp_hires::pack_length() const
{
return 4 + sec_part_bytes[dec];
}
void Field_timestamp_with_dec::make_field(Send_field *field) void Field_timestamp_with_dec::make_field(Send_field *field)
{ {
Field::make_field(field); Field::make_field(field);
@ -5951,11 +5937,6 @@ Item *Field_time::get_equal_const_item(THD *thd, const Context &ctx,
} }
uint32 Field_time_hires::pack_length() const
{
return time_hires_bytes[dec];
}
longlong Field_time_with_dec::val_int(void) longlong Field_time_with_dec::val_int(void)
{ {
ASSERT_COLUMN_MARKED_FOR_READ; ASSERT_COLUMN_MARKED_FOR_READ;
@ -6658,11 +6639,6 @@ bool Field_datetime_hires::get_TIME(MYSQL_TIME *ltime, const uchar *pos,
} }
uint32 Field_datetime_hires::pack_length() const
{
return datetime_hires_bytes[dec];
}
int Field_datetime_hires::cmp(const uchar *a_ptr, const uchar *b_ptr) int Field_datetime_hires::cmp(const uchar *a_ptr, const uchar *b_ptr)
{ {
ulonglong a=read_bigendian(a_ptr, Field_datetime_hires::pack_length()); ulonglong a=read_bigendian(a_ptr, Field_datetime_hires::pack_length());
@ -9803,6 +9779,32 @@ void Column_definition::set_attributes(const Lex_field_type_st &type,
} }
void Column_definition::create_length_to_internal_length_bit()
{
if (f_bit_as_char(pack_flag))
{
key_length= pack_length= ((length + 7) & ~7) / 8;
}
else
{
pack_length= length / 8;
/* We need one extra byte to store the bits we save among the null bits */
key_length= pack_length + MY_TEST(length & 7);
}
}
void Column_definition::create_length_to_internal_length_newdecimal()
{
key_length= pack_length=
my_decimal_get_binary_size(my_decimal_length_to_precision(length,
decimals,
flags &
UNSIGNED_FLAG),
decimals);
}
/** /**
Convert create_field::length from number of characters to number of bytes. Convert create_field::length from number of characters to number of bytes.
*/ */
@ -9818,38 +9820,41 @@ void Column_definition::create_length_to_internal_length(void)
case MYSQL_TYPE_VAR_STRING: case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING: case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VARCHAR: case MYSQL_TYPE_VARCHAR:
length*= charset->mbmaxlen; create_length_to_internal_length_string();
key_length= length;
pack_length= calc_pack_length(real_field_type(), length);
break; break;
case MYSQL_TYPE_ENUM: case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET: case MYSQL_TYPE_SET:
/* Pack_length already calculated in sql_parse.cc */ create_length_to_internal_length_typelib();
length*= charset->mbmaxlen;
key_length= pack_length;
break; break;
case MYSQL_TYPE_BIT: case MYSQL_TYPE_BIT:
if (f_bit_as_char(pack_flag)) create_length_to_internal_length_bit();
{
key_length= pack_length= ((length + 7) & ~7) / 8;
}
else
{
pack_length= length / 8;
/* We need one extra byte to store the bits we save among the null bits */
key_length= pack_length + MY_TEST(length & 7);
}
break; break;
case MYSQL_TYPE_NEWDECIMAL: case MYSQL_TYPE_NEWDECIMAL:
key_length= pack_length= create_length_to_internal_length_newdecimal();
my_decimal_get_binary_size(my_decimal_length_to_precision(length,
decimals,
flags &
UNSIGNED_FLAG),
decimals);
break; break;
default:
key_length= pack_length= calc_pack_length(real_field_type(), length); case MYSQL_TYPE_NULL:
create_length_to_internal_length_null();
break;
case MYSQL_TYPE_DECIMAL:
case MYSQL_TYPE_TINY:
case MYSQL_TYPE_SHORT:
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_LONG:
case MYSQL_TYPE_LONGLONG:
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_TIME2:
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_DATETIME2:
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_TIMESTAMP2:
create_length_to_internal_length_simple();
break; break;
} }
} }
@ -10110,64 +10115,6 @@ enum_field_types get_blob_type_from_length(ulong length)
} }
/*
Make a field from the .frm file info
*/
uint32 calc_pack_length(enum_field_types type,uint32 length)
{
switch (type) {
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_DECIMAL: return (length);
case MYSQL_TYPE_VARCHAR: return (length + (length < 256 ? 1: 2));
case MYSQL_TYPE_YEAR:
case MYSQL_TYPE_TINY : return 1;
case MYSQL_TYPE_SHORT : return 2;
case MYSQL_TYPE_INT24:
case MYSQL_TYPE_NEWDATE: return 3;
case MYSQL_TYPE_TIME: return length > MIN_TIME_WIDTH
? time_hires_bytes[length - 1 - MIN_TIME_WIDTH]
: 3;
case MYSQL_TYPE_TIME2:
return length > MIN_TIME_WIDTH ?
my_time_binary_length(length - MIN_TIME_WIDTH - 1) : 3;
case MYSQL_TYPE_TIMESTAMP:
return length > MAX_DATETIME_WIDTH
? 4 + sec_part_bytes[length - 1 - MAX_DATETIME_WIDTH]
: 4;
case MYSQL_TYPE_TIMESTAMP2:
return length > MAX_DATETIME_WIDTH ?
my_timestamp_binary_length(length - MAX_DATETIME_WIDTH - 1) : 4;
case MYSQL_TYPE_DATE:
case MYSQL_TYPE_LONG : return 4;
case MYSQL_TYPE_FLOAT : return sizeof(float);
case MYSQL_TYPE_DOUBLE: return sizeof(double);
case MYSQL_TYPE_DATETIME:
return length > MAX_DATETIME_WIDTH
? datetime_hires_bytes[length - 1 - MAX_DATETIME_WIDTH]
: 8;
case MYSQL_TYPE_DATETIME2:
return length > MAX_DATETIME_WIDTH ?
my_datetime_binary_length(length - MAX_DATETIME_WIDTH - 1) : 5;
case MYSQL_TYPE_LONGLONG: return 8; /* Don't crash if no longlong */
case MYSQL_TYPE_NULL : return 0;
case MYSQL_TYPE_TINY_BLOB: return 1+portable_sizeof_char_ptr;
case MYSQL_TYPE_BLOB: return 2+portable_sizeof_char_ptr;
case MYSQL_TYPE_MEDIUM_BLOB: return 3+portable_sizeof_char_ptr;
case MYSQL_TYPE_LONG_BLOB: return 4+portable_sizeof_char_ptr;
case MYSQL_TYPE_GEOMETRY: return 4+portable_sizeof_char_ptr;
case MYSQL_TYPE_SET:
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_NEWDECIMAL:
abort(); return 0; // This shouldn't happen
case MYSQL_TYPE_BIT: return length / 8;
default:
return 0;
}
}
uint pack_length_to_packflag(uint type) uint pack_length_to_packflag(uint type)
{ {
switch (type) { switch (type) {
@ -10248,9 +10195,12 @@ Field *make_field(TABLE_SHARE *share,
return 0; // Error return 0; // Error
} }
uint pack_length=calc_pack_length((enum_field_types) // MYSQL_TYPE_VAR_STRING is handled above
f_packtype(pack_flag), DBUG_ASSERT(f_packtype(pack_flag) != MYSQL_TYPE_VAR_STRING);
field_length); const Type_handler *tmp;
tmp= Type_handler::get_handler_by_real_type((enum_field_types)
f_packtype(pack_flag));
uint pack_length= tmp->calc_pack_length(field_length);
#ifdef HAVE_SPATIAL #ifdef HAVE_SPATIAL
if (f_is_geom(pack_flag)) if (f_is_geom(pack_flag))

View File

@ -2454,6 +2454,10 @@ public:
class Field_timestamp_hires :public Field_timestamp_with_dec { class Field_timestamp_hires :public Field_timestamp_with_dec {
uint sec_part_bytes(uint dec) const
{
return Type_handler_timestamp::sec_part_bytes(dec);
}
public: public:
Field_timestamp_hires(uchar *ptr_arg, Field_timestamp_hires(uchar *ptr_arg,
uchar *null_ptr_arg, uchar null_bit_arg, uchar *null_ptr_arg, uchar null_bit_arg,
@ -2468,7 +2472,7 @@ public:
my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const; my_time_t get_timestamp(const uchar *pos, ulong *sec_part) const;
void store_TIME(my_time_t timestamp, ulong sec_part); void store_TIME(my_time_t timestamp, ulong sec_part);
int cmp(const uchar *,const uchar *); int cmp(const uchar *,const uchar *);
uint32 pack_length() const; uint32 pack_length() const { return 4 + sec_part_bytes(dec); }
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
}; };
@ -2735,7 +2739,7 @@ public:
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate); bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
int cmp(const uchar *,const uchar *); int cmp(const uchar *,const uchar *);
void sort_string(uchar *buff,uint length); void sort_string(uchar *buff,uint length);
uint32 pack_length() const; uint32 pack_length() const { return Type_handler_time::hires_bytes(dec); }
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
}; };
@ -2894,7 +2898,7 @@ public:
DBUG_ASSERT(dec); DBUG_ASSERT(dec);
} }
int cmp(const uchar *,const uchar *); int cmp(const uchar *,const uchar *);
uint32 pack_length() const; uint32 pack_length() const { return Type_handler_datetime::hires_bytes(dec); }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate) bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{ return Field_datetime_hires::get_TIME(ltime, ptr, fuzzydate); } { return Field_datetime_hires::get_TIME(ltime, ptr, fuzzydate); }
uint size_of() const { return sizeof(*this); } uint size_of() const { return sizeof(*this); }
@ -3831,6 +3835,8 @@ class Column_definition: public Sql_alloc,
set_if_bigger(*max_length, (uint32)length); set_if_bigger(*max_length, (uint32)length);
} }
} }
bool prepare_stage1_check_typelib_default();
bool prepare_stage1_convert_default(THD *, MEM_ROOT *, CHARSET_INFO *to);
const Type_handler *field_type() const; // Prevent using this const Type_handler *field_type() const; // Prevent using this
public: public:
LEX_CSTRING field_name; LEX_CSTRING field_name;
@ -3882,6 +3888,29 @@ public:
Column_definition(THD *thd, Field *field, Field *orig_field); Column_definition(THD *thd, Field *field, Field *orig_field);
void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs); void set_attributes(const Lex_field_type_st &type, CHARSET_INFO *cs);
void create_length_to_internal_length(void); void create_length_to_internal_length(void);
void create_length_to_internal_length_null()
{
DBUG_ASSERT(length == 0);
key_length= pack_length= 0;
}
void create_length_to_internal_length_simple()
{
key_length= pack_length= type_handler()->calc_pack_length(length);
}
void create_length_to_internal_length_string()
{
length*= charset->mbmaxlen;
key_length= length;
pack_length= type_handler()->calc_pack_length(length);
}
void create_length_to_internal_length_typelib()
{
/* Pack_length already calculated in sql_parse.cc */
length*= charset->mbmaxlen;
key_length= pack_length;
}
void create_length_to_internal_length_bit();
void create_length_to_internal_length_newdecimal();
/** /**
Prepare a SET/ENUM field. Prepare a SET/ENUM field.
@ -3917,8 +3946,22 @@ public:
bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root); bool sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root);
bool prepare_create_field(uint *blob_columns, ulonglong table_flags); bool prepare_stage1(THD *thd, MEM_ROOT *mem_root,
handler *file, ulonglong table_flags);
bool prepare_stage1_typelib(THD *thd, MEM_ROOT *mem_root,
handler *file, ulonglong table_flags);
bool prepare_stage1_string(THD *thd, MEM_ROOT *mem_root,
handler *file, ulonglong table_flags);
bool prepare_stage1_bit(THD *thd, MEM_ROOT *mem_root,
handler *file, ulonglong table_flags);
bool prepare_stage2(handler *handler, ulonglong table_flags);
bool prepare_stage2_blob(handler *handler,
ulonglong table_flags, uint field_flags);
bool prepare_stage2_varchar(ulonglong table_flags);
bool prepare_stage2_typelib(const char *type_name, uint field_flags,
uint *dup_val_count);
uint pack_flag_numeric(uint dec) const;
uint sign_length() const { return flags & UNSIGNED_FLAG ? 0 : 1; } uint sign_length() const { return flags & UNSIGNED_FLAG ? 0 : 1; }
bool check_length(uint mysql_errno, uint max_allowed_length) const; bool check_length(uint mysql_errno, uint max_allowed_length) const;
bool fix_attributes_real(uint default_length); bool fix_attributes_real(uint default_length);
@ -4212,7 +4255,6 @@ public:
uint pack_length_to_packflag(uint type); uint pack_length_to_packflag(uint type);
enum_field_types get_blob_type_from_length(ulong length); enum_field_types get_blob_type_from_length(ulong length);
uint32 calc_pack_length(enum_field_types type,uint32 length);
int set_field_to_null(Field *field); int set_field_to_null(Field *field);
int set_field_to_null_with_conversions(Field *field, bool no_conversions); int set_field_to_null_with_conversions(Field *field, bool no_conversions);
int convert_null_to_field_value_or_error(Field *field); int convert_null_to_field_value_or_error(Field *field);

View File

@ -5407,13 +5407,8 @@ sp_variable *LEX::sp_add_for_loop_variable(THD *thd, const LEX_CSTRING *name,
spcont->declare_var_boundary(1); spcont->declare_var_boundary(1);
spvar->field_def.field_name= spvar->name; spvar->field_def.field_name= spvar->name;
spvar->field_def.set_handler(&type_handler_longlong); spvar->field_def.set_handler(&type_handler_longlong);
/* type_handler_longlong.Column_definition_prepare_stage2(&spvar->field_def,
The below is a simplified version of what NULL, HA_CAN_GEOMETRY);
Column_definition::prepare_create_field() does for a LONGLONG field.
*/
spvar->field_def.pack_flag= (FIELDFLAG_NUMBER |
f_settype((uint) MYSQL_TYPE_LONGLONG));
if (!value && !(value= new (thd->mem_root) Item_null(thd))) if (!value && !(value= new (thd->mem_root) Item_null(thd)))
return NULL; return NULL;

View File

@ -2845,23 +2845,82 @@ bool check_duplicates_in_interval(const char *set_or_name,
} }
bool Column_definition::prepare_stage2_blob(handler *file,
ulonglong table_flags,
uint field_flags)
{
if (table_flags & HA_NO_BLOBS)
{
my_error(ER_TABLE_CANT_HANDLE_BLOB, MYF(0), file->table_type());
return true;
}
pack_flag= field_flags |
pack_length_to_packflag(pack_length - portable_sizeof_char_ptr);
if (charset->state & MY_CS_BINSORT)
pack_flag|= FIELDFLAG_BINARY;
length= 8; // Unireg field length
return false;
}
bool Column_definition::prepare_stage2_typelib(const char *type_name,
uint field_flags,
uint *dup_val_count)
{
pack_flag= pack_length_to_packflag(pack_length) | field_flags;
if (charset->state & MY_CS_BINSORT)
pack_flag|= FIELDFLAG_BINARY;
return check_duplicates_in_interval(type_name, field_name.str, interval,
charset, dup_val_count);
}
uint Column_definition::pack_flag_numeric(uint dec) const
{
return (FIELDFLAG_NUMBER |
(flags & UNSIGNED_FLAG ? 0 : FIELDFLAG_DECIMAL) |
(flags & ZEROFILL_FLAG ? FIELDFLAG_ZEROFILL : 0) |
(dec << FIELDFLAG_DEC_SHIFT));
}
bool Column_definition::prepare_stage2_varchar(ulonglong table_flags)
{
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
if (table_flags & HA_NO_VARCHAR)
{
/* convert VARCHAR to CHAR because handler is not yet up to date */
set_handler(&type_handler_var_string);
pack_length= type_handler()->calc_pack_length((uint) length);
if ((length / charset->mbmaxlen) > MAX_FIELD_CHARLENGTH)
{
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str,
static_cast<ulong>(MAX_FIELD_CHARLENGTH));
return true;
}
}
#endif
pack_flag= (charset->state & MY_CS_BINSORT) ? FIELDFLAG_BINARY : 0;
return false;
}
/* /*
Prepare a Column_definition instance for packing Prepare a Column_definition instance for packing
Members such as pack_flag are valid after this call. Members such as pack_flag are valid after this call.
@param IN/OUT blob_columns - count for BLOBs @param IN handler - storage engine handler,
or NULL if preparing for an SP variable
@param IN table_flags - table flags @param IN table_flags - table flags
@retval false - ok @retval false - ok
@retval true - error (not supported type, bad definition, etc) @retval true - error (not supported type, bad definition, etc)
*/ */
bool Column_definition::prepare_create_field(uint *blob_columns, bool Column_definition::prepare_stage2(handler *file,
ulonglong table_flags) ulonglong table_flags)
{ {
uint dup_val_count; DBUG_ENTER("Column_definition::prepare_stage2");
uint decimals_orig= decimals;
DBUG_ENTER("Column_definition::prepare_create_field");
/* /*
This code came from mysql_prepare_create_table. This code came from mysql_prepare_create_table.
@ -2869,122 +2928,9 @@ bool Column_definition::prepare_create_field(uint *blob_columns,
*/ */
DBUG_ASSERT(charset); DBUG_ASSERT(charset);
switch (real_field_type()) { if (type_handler()->Column_definition_prepare_stage2(this, file, table_flags))
case MYSQL_TYPE_BLOB:
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_TINY_BLOB:
case MYSQL_TYPE_LONG_BLOB:
pack_flag= FIELDFLAG_BLOB |
pack_length_to_packflag(pack_length - portable_sizeof_char_ptr);
if (charset->state & MY_CS_BINSORT)
pack_flag|= FIELDFLAG_BINARY;
length= 8; // Unireg field length
(*blob_columns)++;
break;
case MYSQL_TYPE_GEOMETRY:
#ifdef HAVE_SPATIAL
if (!(table_flags & HA_CAN_GEOMETRY))
{
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
DBUG_RETURN(1);
}
pack_flag= FIELDFLAG_GEOM |
pack_length_to_packflag(pack_length - portable_sizeof_char_ptr);
if (charset->state & MY_CS_BINSORT)
pack_flag|= FIELDFLAG_BINARY;
length= 8; // Unireg field length
(*blob_columns)++;
break;
#else
my_error(ER_FEATURE_DISABLED, MYF(0),
sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(true); DBUG_RETURN(true);
#endif /*HAVE_SPATIAL*/
case MYSQL_TYPE_VARCHAR:
#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
if (table_flags & HA_NO_VARCHAR)
{
/* convert VARCHAR to CHAR because handler is not yet up to date */
set_handler(&type_handler_var_string);
pack_length= calc_pack_length(real_field_type(), (uint) length);
if ((length / charset->mbmaxlen) > MAX_FIELD_CHARLENGTH)
{
my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), field_name.str,
static_cast<ulong>(MAX_FIELD_CHARLENGTH));
DBUG_RETURN(true);
}
}
#endif
/* fall through */
case MYSQL_TYPE_STRING:
pack_flag= 0;
if (charset->state & MY_CS_BINSORT)
pack_flag|= FIELDFLAG_BINARY;
break;
case MYSQL_TYPE_ENUM:
pack_flag= pack_length_to_packflag(pack_length) | FIELDFLAG_INTERVAL;
if (charset->state & MY_CS_BINSORT)
pack_flag|= FIELDFLAG_BINARY;
if (check_duplicates_in_interval("ENUM", field_name.str, interval,
charset, &dup_val_count))
DBUG_RETURN(true);
break;
case MYSQL_TYPE_SET:
pack_flag= pack_length_to_packflag(pack_length) | FIELDFLAG_BITFIELD;
if (charset->state & MY_CS_BINSORT)
pack_flag|= FIELDFLAG_BINARY;
if (check_duplicates_in_interval("SET", field_name.str, interval,
charset, &dup_val_count))
DBUG_RETURN(true);
/* Check that count of unique members is not more then 64 */
if (interval->count - dup_val_count > sizeof(longlong)*8)
{
my_error(ER_TOO_BIG_SET, MYF(0), field_name.str);
DBUG_RETURN(true);
}
break;
case MYSQL_TYPE_DATE: // Rest of string types
case MYSQL_TYPE_NEWDATE:
case MYSQL_TYPE_TIME:
case MYSQL_TYPE_DATETIME:
case MYSQL_TYPE_TIME2:
case MYSQL_TYPE_DATETIME2:
case MYSQL_TYPE_NULL:
pack_flag= f_settype((uint) real_field_type());
break;
case MYSQL_TYPE_BIT:
/*
We have sql_field->pack_flag already set here, see
mysql_prepare_create_table().
*/
break;
case MYSQL_TYPE_NEWDECIMAL:
pack_flag= (FIELDFLAG_NUMBER |
(flags & UNSIGNED_FLAG ? 0 : FIELDFLAG_DECIMAL) |
(flags & ZEROFILL_FLAG ? FIELDFLAG_ZEROFILL : 0) |
(decimals_orig << FIELDFLAG_DEC_SHIFT));
break;
case MYSQL_TYPE_FLOAT:
case MYSQL_TYPE_DOUBLE:
/*
User specified FLOAT() or DOUBLE() without precision. Change to
FLOATING_POINT_DECIMALS to keep things compatible with earlier MariaDB
versions.
*/
if (decimals_orig >= FLOATING_POINT_DECIMALS)
decimals_orig= FLOATING_POINT_DECIMALS;
/* fall-trough */
case MYSQL_TYPE_TIMESTAMP:
case MYSQL_TYPE_TIMESTAMP2:
/* fall-through */
default:
pack_flag= (FIELDFLAG_NUMBER |
(flags & UNSIGNED_FLAG ? 0 : FIELDFLAG_DECIMAL) |
(flags & ZEROFILL_FLAG ? FIELDFLAG_ZEROFILL : 0) |
f_settype((uint) real_field_type()) |
(decimals_orig << FIELDFLAG_DEC_SHIFT));
break;
}
if (!(flags & NOT_NULL_FLAG) || if (!(flags & NOT_NULL_FLAG) ||
(vcol_info)) /* Make virtual columns allow NULL values */ (vcol_info)) /* Make virtual columns allow NULL values */
pack_flag|= FIELDFLAG_MAYBE_NULL; pack_flag|= FIELDFLAG_MAYBE_NULL;
@ -3007,7 +2953,7 @@ bool Column_definition::prepare_create_field(uint *blob_columns,
cs Character set cs Character set
*/ */
CHARSET_INFO* get_sql_field_charset(Create_field *sql_field, CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field,
HA_CREATE_INFO *create_info) HA_CREATE_INFO *create_info)
{ {
CHARSET_INFO *cs= sql_field->charset; CHARSET_INFO *cs= sql_field->charset;
@ -3146,6 +3092,143 @@ static void check_duplicate_key(THD *thd, Key *key, KEY *key_info,
} }
bool Column_definition::prepare_stage1_typelib(THD *thd,
MEM_ROOT *mem_root,
handler *file,
ulonglong table_flags)
{
/*
Pass the last parameter to prepare_interval_field() as follows:
- If we are preparing for an SP variable (file is NULL), we pass "false",
to force allocation and full copying of TYPELIB values on the given
mem_root, even if no character set conversion is needed. This is needed
because a life cycle of an SP variable is longer than the current query.
- If we are preparing for a CREATE TABLE, (file != NULL), we pass "true".
This will create the typelib in runtime memory - we will free the
occupied memory at the same time when we free this
sql_field -- at the end of execution.
Pass "true" as the last argument to reuse "interval_list"
values in "interval" in cases when no character conversion is needed,
to avoid extra copying.
*/
if (prepare_interval_field(mem_root, file != NULL))
return true; // E.g. wrong values with commas: SET('a,b')
create_length_to_internal_length_typelib();
DBUG_ASSERT(file || !default_value); // SP variables have no default_value
if (default_value && default_value->expr->basic_const_item())
{
if ((charset != default_value->expr->collation.collation &&
prepare_stage1_convert_default(thd, mem_root, charset)) ||
prepare_stage1_check_typelib_default())
return true;
}
return false;
}
bool Column_definition::prepare_stage1_string(THD *thd,
MEM_ROOT *mem_root,
handler *file,
ulonglong table_flags)
{
create_length_to_internal_length_string();
if (prepare_blob_field(thd))
return true;
DBUG_ASSERT(file || !default_value); // SP variables have no default_value
/*
Convert the default value from client character
set into the column character set if necessary.
We can only do this for constants as we have not yet run fix_fields.
*/
if (default_value &&
default_value->expr->basic_const_item() &&
charset != default_value->expr->collation.collation)
{
if (prepare_stage1_convert_default(thd, mem_root, charset))
return true;
}
return false;
}
bool Column_definition::prepare_stage1_bit(THD *thd,
MEM_ROOT *mem_root,
handler *file,
ulonglong table_flags)
{
pack_flag= FIELDFLAG_NUMBER;
if (!(table_flags & HA_CAN_BIT_FIELD))
pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
create_length_to_internal_length_bit();
return false;
}
bool Column_definition::prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
handler *file,
ulonglong table_flags)
{
return type_handler()->Column_definition_prepare_stage1(thd, mem_root,
this, file,
table_flags);
}
bool Column_definition::prepare_stage1_convert_default(THD *thd,
MEM_ROOT *mem_root,
CHARSET_INFO *cs)
{
DBUG_ASSERT(thd->mem_root == mem_root);
Item *item;
if (!(item= default_value->expr->safe_charset_converter(thd, cs)))
{
my_error(ER_INVALID_DEFAULT, MYF(0), field_name.str);
return true; // Could not convert
}
/* Fix for prepare statement */
thd->change_item_tree(&default_value->expr, item);
return false;
}
bool Column_definition::prepare_stage1_check_typelib_default()
{
StringBuffer<MAX_FIELD_WIDTH> str;
String *def= default_value->expr->val_str(&str);
bool not_found;
if (def == NULL) /* SQL "NULL" maps to NULL */
{
not_found= flags & NOT_NULL_FLAG;
}
else
{
not_found= false;
if (real_field_type() == MYSQL_TYPE_SET)
{
char *not_used;
uint not_used2;
find_set(interval, def->ptr(), def->length(),
charset, &not_used, &not_used2, &not_found);
}
else /* MYSQL_TYPE_ENUM */
{
def->length(charset->cset->lengthsp(charset,
def->ptr(), def->length()));
not_found= !find_type2(interval, def->ptr(), def->length(), charset);
}
}
if (not_found)
{
my_error(ER_INVALID_DEFAULT, MYF(0), field_name.str);
return true;
}
return false;
}
/* /*
Preparation for table creation Preparation for table creation
@ -3180,7 +3263,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{ {
const char *key_name; const char *key_name;
Create_field *sql_field,*dup_field; Create_field *sql_field,*dup_field;
uint field,null_fields,blob_columns,max_key_length; uint field,null_fields,max_key_length;
ulong record_offset= 0; ulong record_offset= 0;
KEY *key_info; KEY *key_info;
KEY_PART_INFO *key_part_info; KEY_PART_INFO *key_part_info;
@ -3193,7 +3276,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
bool tmp_table= create_table_mode == C_ALTER_TABLE; bool tmp_table= create_table_mode == C_ALTER_TABLE;
DBUG_ENTER("mysql_prepare_create_table"); DBUG_ENTER("mysql_prepare_create_table");
null_fields=blob_columns=0; null_fields= 0;
create_info->varchar= 0; create_info->varchar= 0;
max_key_length= file->max_key_length(); max_key_length= file->max_key_length();
@ -3215,8 +3298,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
select_field_pos= alter_info->create_list.elements - select_field_count; select_field_pos= alter_info->create_list.elements - select_field_count;
for (field_no=0; (sql_field=it++) ; field_no++) for (field_no=0; (sql_field=it++) ; field_no++)
{ {
CHARSET_INFO *save_cs;
/* /*
Initialize length from its original value (number of characters), Initialize length from its original value (number of characters),
which was set in the parser. This is necessary if we're which was set in the parser. This is necessary if we're
@ -3224,105 +3305,18 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
*/ */
sql_field->length= sql_field->char_length; sql_field->length= sql_field->char_length;
/* Set field charset. */ /* Set field charset. */
save_cs= sql_field->charset= get_sql_field_charset(sql_field, create_info); sql_field->charset= get_sql_field_charset(sql_field, create_info);
if ((sql_field->flags & BINCMP_FLAG) && if ((sql_field->flags & BINCMP_FLAG) &&
!(sql_field->charset= find_bin_collation(sql_field->charset))) !(sql_field->charset= find_bin_collation(sql_field->charset)))
DBUG_RETURN(TRUE); DBUG_RETURN(true);
if (sql_field->real_field_type() == MYSQL_TYPE_SET || if (sql_field->prepare_stage1(thd, thd->mem_root,
sql_field->real_field_type() == MYSQL_TYPE_ENUM) file, file->ha_table_flags()))
{ DBUG_RETURN(true);
/*
Create the typelib in runtime memory - we will free the
occupied memory at the same time when we free this
sql_field -- at the end of execution.
Pass "true" as the last argument to reuse "interval_list"
values in "interval" in cases when no character conversion is needed,
to avoid extra copying.
*/
if (sql_field->prepare_interval_field(thd->mem_root, true))
DBUG_RETURN(true); // E.g. wrong values with commas: SET('a,b')
}
if (sql_field->real_field_type() == MYSQL_TYPE_BIT) if (sql_field->real_field_type() == MYSQL_TYPE_BIT &&
{ file->ha_table_flags() & HA_CAN_BIT_FIELD)
sql_field->pack_flag= FIELDFLAG_NUMBER; total_uneven_bit_length+= sql_field->length & 7;
if (file->ha_table_flags() & HA_CAN_BIT_FIELD)
total_uneven_bit_length+= sql_field->length & 7;
else
sql_field->pack_flag|= FIELDFLAG_TREAT_BIT_AS_CHAR;
}
sql_field->create_length_to_internal_length();
if (sql_field->prepare_blob_field(thd))
DBUG_RETURN(TRUE);
/*
Convert the default value from client character
set into the column character set if necessary.
We can only do this for constants as we have not yet run fix_fields.
*/
if (sql_field->default_value &&
sql_field->default_value->expr->basic_const_item() &&
save_cs != sql_field->default_value->expr->collation.collation &&
(sql_field->real_field_type() == MYSQL_TYPE_VAR_STRING ||
sql_field->real_field_type() == MYSQL_TYPE_STRING ||
sql_field->real_field_type() == MYSQL_TYPE_SET ||
sql_field->real_field_type() == MYSQL_TYPE_TINY_BLOB ||
sql_field->real_field_type() == MYSQL_TYPE_MEDIUM_BLOB ||
sql_field->real_field_type() == MYSQL_TYPE_LONG_BLOB ||
sql_field->real_field_type() == MYSQL_TYPE_BLOB ||
sql_field->real_field_type() == MYSQL_TYPE_ENUM))
{
Item *item;
if (!(item= sql_field->default_value->expr->
safe_charset_converter(thd, save_cs)))
{
/* Could not convert */
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name.str);
DBUG_RETURN(TRUE);
}
/* Fix for prepare statement */
thd->change_item_tree(&sql_field->default_value->expr, item);
}
if (sql_field->default_value &&
sql_field->default_value->expr->basic_const_item() &&
(sql_field->real_field_type() == MYSQL_TYPE_SET ||
sql_field->real_field_type() == MYSQL_TYPE_ENUM))
{
StringBuffer<MAX_FIELD_WIDTH> str;
String *def= sql_field->default_value->expr->val_str(&str);
bool not_found;
if (def == NULL) /* SQL "NULL" maps to NULL */
{
not_found= sql_field->flags & NOT_NULL_FLAG;
}
else
{
not_found= false;
if (sql_field->real_field_type() == MYSQL_TYPE_SET)
{
char *not_used;
uint not_used2;
find_set(sql_field->interval, def->ptr(), def->length(),
sql_field->charset, &not_used, &not_used2, &not_found);
}
else /* MYSQL_TYPE_ENUM */
{
def->length(sql_field->charset->cset->lengthsp(sql_field->charset,
def->ptr(), def->length()));
not_found= !find_type2(sql_field->interval, def->ptr(),
def->length(), sql_field->charset);
}
}
if (not_found)
{
my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name.str);
DBUG_RETURN(TRUE);
}
}
if (!(sql_field->flags & NOT_NULL_FLAG)) if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++; null_fields++;
@ -3419,7 +3413,7 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
{ {
DBUG_ASSERT(sql_field->charset != 0); DBUG_ASSERT(sql_field->charset != 0);
if (sql_field->prepare_create_field(&blob_columns, file->ha_table_flags())) if (sql_field->prepare_stage2(file, file->ha_table_flags()))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
if (sql_field->real_field_type() == MYSQL_TYPE_VARCHAR) if (sql_field->real_field_type() == MYSQL_TYPE_VARCHAR)
create_info->varchar= TRUE; create_info->varchar= TRUE;
@ -3461,12 +3455,6 @@ mysql_prepare_create_table(THD *thd, HA_CREATE_INFO *create_info,
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
} }
if (blob_columns && (file->ha_table_flags() & HA_NO_BLOBS))
{
my_error(ER_TABLE_CANT_HANDLE_BLOB, MYF(0), file->table_type());
DBUG_RETURN(TRUE);
}
/* /*
CREATE TABLE[with auto_increment column] SELECT is unsafe as the rows CREATE TABLE[with auto_increment column] SELECT is unsafe as the rows
inserted in the created table depends on the order of the rows fetched inserted in the created table depends on the order of the rows fetched
@ -4237,7 +4225,7 @@ bool Column_definition::prepare_blob_field(THD *thd)
{ {
/* The user has given a length to the blob column */ /* The user has given a length to the blob column */
set_handler(Type_handler::blob_type_handler(length)); set_handler(Type_handler::blob_type_handler(length));
pack_length= calc_pack_length(real_field_type(), 0); pack_length= type_handler()->calc_pack_length(0);
} }
length= 0; length= 0;
} }
@ -4262,30 +4250,8 @@ bool Column_definition::prepare_blob_field(THD *thd)
bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root) bool Column_definition::sp_prepare_create_field(THD *thd, MEM_ROOT *mem_root)
{ {
if (real_field_type() == MYSQL_TYPE_SET || return prepare_stage1(thd, mem_root, NULL, HA_CAN_GEOMETRY) ||
real_field_type() == MYSQL_TYPE_ENUM) prepare_stage2(NULL, HA_CAN_GEOMETRY);
{
/*
Pass "false" as the last argument to allocate TYPELIB values on mem_root,
even if no character set conversion is needed.
*/
if (prepare_interval_field(mem_root, false))
return true; // E.g. wrong values with commas: SET('a,b')
}
if (real_field_type() == MYSQL_TYPE_BIT)
pack_flag= FIELDFLAG_NUMBER | FIELDFLAG_TREAT_BIT_AS_CHAR;
create_length_to_internal_length();
DBUG_ASSERT(default_value == 0);
/*
prepare_blob_field() can return an error on attempt to create a too long
VARCHAR/VARBINARY field when the current sql_mode does not allow automatic
conversion to TEXT/BLOB.
*/
if (prepare_blob_field(thd))
return true;
uint unused1;
return prepare_create_field(&unused1, HA_CAN_GEOMETRY);
} }

View File

@ -253,7 +253,7 @@ bool quick_rm_table(THD *thd, handlerton *base, const char *db,
const char *table_path=0); const char *table_path=0);
void close_cached_table(THD *thd, TABLE *table); void close_cached_table(THD *thd, TABLE *table);
void sp_prepare_create_field(THD *thd, Column_definition *sql_field); void sp_prepare_create_field(THD *thd, Column_definition *sql_field);
CHARSET_INFO* get_sql_field_charset(Create_field *sql_field, CHARSET_INFO* get_sql_field_charset(Column_definition *sql_field,
HA_CREATE_INFO *create_info); HA_CREATE_INFO *create_info);
bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags); bool mysql_write_frm(ALTER_PARTITION_PARAM_TYPE *lpt, uint flags);
int write_bin_log(THD *thd, bool clear_error, int write_bin_log(THD *thd, bool clear_error,

View File

@ -379,6 +379,20 @@ Type_handler_hybrid_field_type::Type_handler_hybrid_field_type()
} }
/***************************************************************************/
/* number of bytes to store second_part part of the TIMESTAMP(N) */
uint Type_handler_timestamp::m_sec_part_bytes[MAX_DATETIME_PRECISION + 1]=
{ 0, 1, 1, 2, 2, 3, 3 };
/* number of bytes to store DATETIME(N) */
uint Type_handler_datetime::m_hires_bytes[MAX_DATETIME_PRECISION + 1]=
{ 5, 6, 6, 7, 7, 7, 8 };
/* number of bytes to store TIME(N) */
uint Type_handler_time::m_hires_bytes[MAX_DATETIME_PRECISION + 1]=
{ 3, 4, 4, 5, 5, 5, 6 };
/***************************************************************************/ /***************************************************************************/
const Name Type_handler_row::m_name_row(C_STRING_WITH_LEN("row")); const Name Type_handler_row::m_name_row(C_STRING_WITH_LEN("row"));
@ -1539,6 +1553,293 @@ bool Type_handler_bit::
return def->fix_attributes_bit(); return def->fix_attributes_bit();
} }
/*************************************************************************/
bool Type_handler::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags) const
{
def->create_length_to_internal_length_simple();
return false;
}
bool Type_handler_null::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags) const
{
def->create_length_to_internal_length_null();
return false;
}
bool Type_handler_newdecimal::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags) const
{
def->create_length_to_internal_length_newdecimal();
return false;
}
bool Type_handler_bit::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags) const
{
return def->prepare_stage1_bit(thd, mem_root, file, table_flags);
}
bool Type_handler_typelib::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags) const
{
return def->prepare_stage1_typelib(thd, mem_root, file, table_flags);
}
bool Type_handler_string_result::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags) const
{
return def->prepare_stage1_string(thd, mem_root, file, table_flags);
}
#ifdef HAVE_SPATIAL
bool Type_handler_geometry::
Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *def,
handler *file,
ulonglong table_flags) const
{
def->create_length_to_internal_length_string();
return def->prepare_blob_field(thd);
}
#endif
/*************************************************************************/
bool Type_handler::
Column_definition_prepare_stage2_legacy(Column_definition *def,
enum_field_types type) const
{
def->pack_flag= f_settype((uint) type);
return false;
}
bool Type_handler::
Column_definition_prepare_stage2_legacy_num(Column_definition *def,
enum_field_types type) const
{
def->pack_flag= def->pack_flag_numeric(def->decimals) |
f_settype((uint) type);
return false;
}
bool Type_handler::
Column_definition_prepare_stage2_legacy_real(Column_definition *def,
enum_field_types type) const
{
uint dec= def->decimals;
/*
User specified FLOAT() or DOUBLE() without precision. Change to
FLOATING_POINT_DECIMALS to keep things compatible with earlier MariaDB
versions.
*/
if (dec >= FLOATING_POINT_DECIMALS)
dec= FLOATING_POINT_DECIMALS;
def->pack_flag= def->pack_flag_numeric(dec) | f_settype((uint) type);
return false;
}
bool Type_handler_newdecimal::
Column_definition_prepare_stage2(Column_definition *def,
handler *file,
ulonglong table_flags) const
{
def->pack_flag= def->pack_flag_numeric(def->decimals);
return false;
}
bool Type_handler_blob_common::
Column_definition_prepare_stage2(Column_definition *def,
handler *file,
ulonglong table_flags) const
{
return def->prepare_stage2_blob(file, table_flags, FIELDFLAG_BLOB);
}
#ifdef HAVE_SPATIAL
bool Type_handler_geometry::
Column_definition_prepare_stage2(Column_definition *def,
handler *file,
ulonglong table_flags) const
{
if (!(table_flags & HA_CAN_GEOMETRY))
{
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
return true;
}
return def->prepare_stage2_blob(file, table_flags, FIELDFLAG_GEOM);
}
#endif
bool Type_handler_varchar::
Column_definition_prepare_stage2(Column_definition *def,
handler *file,
ulonglong table_flags) const
{
return def->prepare_stage2_varchar(table_flags);
}
bool Type_handler_string::
Column_definition_prepare_stage2(Column_definition *def,
handler *file,
ulonglong table_flags) const
{
def->pack_flag= (def->charset->state & MY_CS_BINSORT) ? FIELDFLAG_BINARY : 0;
return false;
}
bool Type_handler_enum::
Column_definition_prepare_stage2(Column_definition *def,
handler *file,
ulonglong table_flags) const
{
uint dummy;
return def->prepare_stage2_typelib("ENUM", FIELDFLAG_INTERVAL, &dummy);
}
bool Type_handler_set::
Column_definition_prepare_stage2(Column_definition *def,
handler *file,
ulonglong table_flags) const
{
uint dup_count;
if (def->prepare_stage2_typelib("SET", FIELDFLAG_BITFIELD, &dup_count))
return true;
/* Check that count of unique members is not more then 64 */
if (def->interval->count - dup_count > sizeof(longlong)*8)
{
my_error(ER_TOO_BIG_SET, MYF(0), def->field_name.str);
return true;
}
return false;
}
bool Type_handler_bit::
Column_definition_prepare_stage2(Column_definition *def,
handler *file,
ulonglong table_flags) const
{
/*
We have sql_field->pack_flag already set here, see
mysql_prepare_create_table().
*/
return false;
}
/*************************************************************************/
uint32 Type_handler_time::calc_pack_length(uint32 length) const
{
return length > MIN_TIME_WIDTH ?
hires_bytes(length - 1 - MIN_TIME_WIDTH) : 3;
}
uint32 Type_handler_time2::calc_pack_length(uint32 length) const
{
return length > MIN_TIME_WIDTH ?
my_time_binary_length(length - MIN_TIME_WIDTH - 1) : 3;
}
uint32 Type_handler_timestamp::calc_pack_length(uint32 length) const
{
return length > MAX_DATETIME_WIDTH ?
4 + sec_part_bytes(length - 1 - MAX_DATETIME_WIDTH) : 4;
}
uint32 Type_handler_timestamp2::calc_pack_length(uint32 length) const
{
return length > MAX_DATETIME_WIDTH ?
my_timestamp_binary_length(length - MAX_DATETIME_WIDTH - 1) : 4;
}
uint32 Type_handler_datetime::calc_pack_length(uint32 length) const
{
return length > MAX_DATETIME_WIDTH ?
hires_bytes(length - 1 - MAX_DATETIME_WIDTH) : 8;
}
uint32 Type_handler_datetime2::calc_pack_length(uint32 length) const
{
return length > MAX_DATETIME_WIDTH ?
my_datetime_binary_length(length - MAX_DATETIME_WIDTH - 1) : 5;
}
uint32 Type_handler_tiny_blob::calc_pack_length(uint32 length) const
{
return 1 + portable_sizeof_char_ptr;
}
uint32 Type_handler_blob::calc_pack_length(uint32 length) const
{
return 2 + portable_sizeof_char_ptr;
}
uint32 Type_handler_medium_blob::calc_pack_length(uint32 length) const
{
return 3 + portable_sizeof_char_ptr;
}
uint32 Type_handler_long_blob::calc_pack_length(uint32 length) const
{
return 4 + portable_sizeof_char_ptr;
}
#ifdef HAVE_SPATIAL
uint32 Type_handler_geometry::calc_pack_length(uint32 length) const
{
return 4 + portable_sizeof_char_ptr;
}
#endif
uint32 Type_handler_newdecimal::calc_pack_length(uint32 length) const
{
abort(); // This shouldn't happen
return 0;
}
uint32 Type_handler_set::calc_pack_length(uint32 length) const
{
abort(); // This shouldn't happen
return 0;
}
uint32 Type_handler_enum::calc_pack_length(uint32 length) const
{
abort(); // This shouldn't happen
return 0;
}
/*************************************************************************/ /*************************************************************************/
Field *Type_handler::make_and_init_table_field(const LEX_CSTRING *name, Field *Type_handler::make_and_init_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,

View File

@ -67,6 +67,7 @@ class Sort_param;
class Arg_comparator; class Arg_comparator;
struct st_value; struct st_value;
class Protocol; class Protocol;
class handler;
struct TABLE; struct TABLE;
struct SORT_FIELD_ATTR; struct SORT_FIELD_ATTR;
@ -549,6 +550,15 @@ protected:
bool Item_send_time(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_time(Item *item, Protocol *protocol, st_value *buf) const;
bool Item_send_date(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_date(Item *item, Protocol *protocol, st_value *buf) const;
bool Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send_datetime(Item *item, Protocol *protocol, st_value *buf) const;
bool Column_definition_prepare_stage2_legacy(Column_definition *c,
enum_field_types type)
const;
bool Column_definition_prepare_stage2_legacy_num(Column_definition *c,
enum_field_types type)
const;
bool Column_definition_prepare_stage2_legacy_real(Column_definition *c,
enum_field_types type)
const;
public: public:
static const Type_handler *blob_type_handler(uint max_octet_length); static const Type_handler *blob_type_handler(uint max_octet_length);
static const Type_handler *string_type_handler(uint max_octet_length); static const Type_handler *string_type_handler(uint max_octet_length);
@ -692,6 +702,14 @@ public:
uint metadata, uint metadata,
const Field *target) const= 0; const Field *target) const= 0;
virtual bool Column_definition_fix_attributes(Column_definition *c) const= 0; virtual bool Column_definition_fix_attributes(Column_definition *c) const= 0;
virtual bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
ulonglong table_flags) const;
virtual bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const= 0;
virtual Field *make_table_field(const LEX_CSTRING *name, virtual Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -708,6 +726,7 @@ public:
SORT_FIELD_ATTR *attr) const= 0; SORT_FIELD_ATTR *attr) const= 0;
virtual uint32 max_display_length(const Item *item) const= 0; virtual uint32 max_display_length(const Item *item) const= 0;
virtual uint32 calc_pack_length(uint32 length) const= 0;
virtual bool Item_save_in_value(Item *item, st_value *value) const= 0; virtual bool Item_save_in_value(Item *item, st_value *value) const= 0;
virtual bool Item_param_set_from_value(THD *thd, virtual bool Item_param_set_from_value(THD *thd,
Item_param *param, Item_param *param,
@ -935,6 +954,22 @@ public:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return true; return true;
} }
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
ulonglong table_flags) const
{
DBUG_ASSERT(0);
return true;
}
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{
DBUG_ASSERT(0);
return true;
}
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -959,6 +994,11 @@ public:
DBUG_ASSERT(0); DBUG_ASSERT(0);
return 0; return 0;
} }
uint32 calc_pack_length(uint32 length) const
{
DBUG_ASSERT(0);
return 0;
}
uint Item_decimal_precision(const Item *item) const uint Item_decimal_precision(const Item *item) const
{ {
DBUG_ASSERT(0); DBUG_ASSERT(0);
@ -1470,6 +1510,11 @@ public:
void sortlength(THD *thd, void sortlength(THD *thd,
const Type_std_attributes *item, const Type_std_attributes *item,
SORT_FIELD_ATTR *attr) const; SORT_FIELD_ATTR *attr) const;
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
ulonglong table_flags) const;
uint32 max_display_length(const Item *item) const; uint32 max_display_length(const Item *item) const;
uint Item_time_precision(Item *item) const uint Item_time_precision(Item *item) const
{ {
@ -1578,6 +1623,7 @@ public:
const Name name() const { return m_name_tiny; } const Name name() const { return m_name_tiny; }
enum_field_types field_type() const { return MYSQL_TYPE_TINY; } enum_field_types field_type() const { return MYSQL_TYPE_TINY; }
uint32 max_display_length(const Item *item) const { return 4; } uint32 max_display_length(const Item *item) const { return 4; }
uint32 calc_pack_length(uint32 length) const { return 1; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
return Item_send_tiny(item, protocol, buf); return Item_send_tiny(item, protocol, buf);
@ -1585,6 +1631,10 @@ public:
Field *make_conversion_table_field(TABLE *TABLE, uint metadata, Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TINY); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1604,9 +1654,14 @@ public:
return Item_send_short(item, protocol, buf); return Item_send_short(item, protocol, buf);
} }
uint32 max_display_length(const Item *item) const { return 6; } uint32 max_display_length(const Item *item) const { return 6; }
uint32 calc_pack_length(uint32 length) const { return 2; }
Field *make_conversion_table_field(TABLE *TABLE, uint metadata, Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_SHORT); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1625,6 +1680,7 @@ public:
{ {
return MY_INT32_NUM_DECIMAL_DIGITS; return MY_INT32_NUM_DECIMAL_DIGITS;
} }
uint32 calc_pack_length(uint32 length) const { return 4; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
return Item_send_long(item, protocol, buf); return Item_send_long(item, protocol, buf);
@ -1632,6 +1688,10 @@ public:
Field *make_conversion_table_field(TABLE *TABLE, uint metadata, Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_LONG); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1647,6 +1707,7 @@ public:
const Name name() const { return m_name_longlong; } const Name name() const { return m_name_longlong; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; } enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
uint32 max_display_length(const Item *item) const { return 20; } uint32 max_display_length(const Item *item) const { return 20; }
uint32 calc_pack_length(uint32 length) const { return 8; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
return Item_send_longlong(item, protocol, buf); return Item_send_longlong(item, protocol, buf);
@ -1654,6 +1715,12 @@ public:
Field *make_conversion_table_field(TABLE *TABLE, uint metadata, Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{
return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_LONGLONG);
}
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1673,9 +1740,14 @@ public:
return Item_send_long(item, protocol, buf); return Item_send_long(item, protocol, buf);
} }
uint32 max_display_length(const Item *item) const { return 8; } uint32 max_display_length(const Item *item) const { return 8; }
uint32 calc_pack_length(uint32 length) const { return 3; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_INT24); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1691,6 +1763,7 @@ public:
const Name name() const { return m_name_year; } const Name name() const { return m_name_year; }
enum_field_types field_type() const { return MYSQL_TYPE_YEAR; } enum_field_types field_type() const { return MYSQL_TYPE_YEAR; }
uint32 max_display_length(const Item *item) const; uint32 max_display_length(const Item *item) const;
uint32 calc_pack_length(uint32 length) const { return 1; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
return Item_send_short(item, protocol, buf); return Item_send_short(item, protocol, buf);
@ -1698,6 +1771,10 @@ public:
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_YEAR); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1713,6 +1790,7 @@ public:
const Name name() const { return m_name_bit; } const Name name() const { return m_name_bit; }
enum_field_types field_type() const { return MYSQL_TYPE_BIT; } enum_field_types field_type() const { return MYSQL_TYPE_BIT; }
uint32 max_display_length(const Item *item) const; uint32 max_display_length(const Item *item) const;
uint32 calc_pack_length(uint32 length) const { return length / 8; }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
return Item_send_str(item, protocol, buf); return Item_send_str(item, protocol, buf);
@ -1724,6 +1802,14 @@ public:
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
ulonglong table_flags) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1740,6 +1826,7 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; } enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; }
bool type_can_have_auto_increment_attribute() const { return true; } bool type_can_have_auto_increment_attribute() const { return true; }
uint32 max_display_length(const Item *item) const { return 25; } uint32 max_display_length(const Item *item) const { return 25; }
uint32 calc_pack_length(uint32 length) const { return sizeof(float); }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
return Item_send_float(item, protocol, buf); return Item_send_float(item, protocol, buf);
@ -1748,6 +1835,10 @@ public:
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_real(c, MYSQL_TYPE_FLOAT); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1764,6 +1855,7 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; } enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
bool type_can_have_auto_increment_attribute() const { return true; } bool type_can_have_auto_increment_attribute() const { return true; }
uint32 max_display_length(const Item *item) const { return 53; } uint32 max_display_length(const Item *item) const { return 53; }
uint32 calc_pack_length(uint32 length) const { return sizeof(double); }
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const bool Item_send(Item *item, Protocol *protocol, st_value *buf) const
{ {
return Item_send_double(item, protocol, buf); return Item_send_double(item, protocol, buf);
@ -1771,6 +1863,10 @@ public:
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_real(c, MYSQL_TYPE_DOUBLE); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1821,10 +1917,18 @@ public:
class Type_handler_time: public Type_handler_time_common class Type_handler_time: public Type_handler_time_common
{ {
/* number of bytes to store TIME(N) */
static uint m_hires_bytes[MAX_DATETIME_PRECISION+1];
public: public:
static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; }
virtual ~Type_handler_time() {} virtual ~Type_handler_time() {}
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_TIME); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1837,8 +1941,13 @@ class Type_handler_time2: public Type_handler_time_common
public: public:
virtual ~Type_handler_time2() {} virtual ~Type_handler_time2() {}
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; } enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_TIME2); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1889,8 +1998,13 @@ class Type_handler_date: public Type_handler_date_common
{ {
public: public:
virtual ~Type_handler_date() {} virtual ~Type_handler_date() {}
uint32 calc_pack_length(uint32 length) const { return 4; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATE); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1903,8 +2017,13 @@ class Type_handler_newdate: public Type_handler_date_common
public: public:
virtual ~Type_handler_newdate() {} virtual ~Type_handler_newdate() {}
enum_field_types real_field_type() const { return MYSQL_TYPE_NEWDATE; } enum_field_types real_field_type() const { return MYSQL_TYPE_NEWDATE; }
uint32 calc_pack_length(uint32 length) const { return 3; }
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_NEWDATE); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1949,10 +2068,18 @@ public:
class Type_handler_datetime: public Type_handler_datetime_common class Type_handler_datetime: public Type_handler_datetime_common
{ {
/* number of bytes to store DATETIME(N) */
static uint m_hires_bytes[MAX_DATETIME_PRECISION + 1];
public: public:
static uint hires_bytes(uint dec) { return m_hires_bytes[dec]; }
virtual ~Type_handler_datetime() {} virtual ~Type_handler_datetime() {}
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATETIME); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -1965,8 +2092,13 @@ class Type_handler_datetime2: public Type_handler_datetime_common
public: public:
virtual ~Type_handler_datetime2() {} virtual ~Type_handler_datetime2() {}
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; } enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_DATETIME2); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2015,10 +2147,18 @@ public:
class Type_handler_timestamp: public Type_handler_timestamp_common class Type_handler_timestamp: public Type_handler_timestamp_common
{ {
/* number of bytes to store second_part part of the TIMESTAMP(N) */
static uint m_sec_part_bytes[MAX_DATETIME_PRECISION + 1];
public: public:
static uint sec_part_bytes(uint dec) { return m_sec_part_bytes[dec]; }
virtual ~Type_handler_timestamp() {} virtual ~Type_handler_timestamp() {}
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TIMESTAMP); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2031,8 +2171,15 @@ class Type_handler_timestamp2: public Type_handler_timestamp_common
public: public:
virtual ~Type_handler_timestamp2() {} virtual ~Type_handler_timestamp2() {}
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; } enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{
return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_TIMESTAMP2);
}
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2047,11 +2194,16 @@ public:
virtual ~Type_handler_olddecimal() {} virtual ~Type_handler_olddecimal() {}
const Name name() const { return m_name_decimal; } const Name name() const { return m_name_decimal; }
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; } enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
uint32 calc_pack_length(uint32 length) const { return length; }
const Type_handler *type_handler_for_tmp_table(const Item *item) const; const Type_handler *type_handler_for_tmp_table(const Item *item) const;
const Type_handler *type_handler_for_union(const Item *item) const; const Type_handler *type_handler_for_union(const Item *item) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_DECIMAL); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2066,9 +2218,18 @@ public:
virtual ~Type_handler_newdecimal() {} virtual ~Type_handler_newdecimal() {}
const Name name() const { return m_name_decimal; } const Name name() const { return m_name_decimal; }
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; } enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
ulonglong table_flags) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2087,11 +2248,21 @@ public:
const Type_handler *type_handler_for_tmp_table(const Item *item) const; const Type_handler *type_handler_for_tmp_table(const Item *item) const;
const Type_handler *type_handler_for_union(const Item *) const; const Type_handler *type_handler_for_union(const Item *) const;
uint32 max_display_length(const Item *item) const { return 0; } uint32 max_display_length(const Item *item) const { return 0; }
uint32 calc_pack_length(uint32 length) const { return 0; }
bool Item_save_in_value(Item *item, st_value *value) const; bool Item_save_in_value(Item *item, st_value *value) const;
bool Item_send(Item *item, Protocol *protocol, st_value *buf) const; bool Item_send(Item *item, Protocol *protocol, st_value *buf) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
ulonglong table_flags) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy(c, MYSQL_TYPE_NULL); }
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2117,6 +2288,7 @@ public:
const Name name() const { return m_name_char; } const Name name() const { return m_name_char; }
enum_field_types field_type() const { return MYSQL_TYPE_STRING; } enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
bool is_param_long_data_type() const { return true; } bool is_param_long_data_type() const { return true; }
uint32 calc_pack_length(uint32 length) const { return length; }
const Type_handler *type_handler_for_tmp_table(const Item *item) const const Type_handler *type_handler_for_tmp_table(const Item *item) const
{ {
return varstring_type_handler(item); return varstring_type_handler(item);
@ -2124,6 +2296,9 @@ public:
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2145,6 +2320,10 @@ public:
return varstring_type_handler(item); return varstring_type_handler(item);
} }
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const
{ return Column_definition_prepare_stage2_legacy_num(c, MYSQL_TYPE_STRING); }
const Type_handler *type_handler_for_union(const Item *item) const const Type_handler *type_handler_for_union(const Item *item) const
{ {
return varstring_type_handler(item); return varstring_type_handler(item);
@ -2159,6 +2338,10 @@ public:
virtual ~Type_handler_varchar() {} virtual ~Type_handler_varchar() {}
const Name name() const { return m_name_varchar; } const Name name() const { return m_name_varchar; }
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; } enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
uint32 calc_pack_length(uint32 length) const
{
return (length + (length < 256 ? 1: 2));
}
const Type_handler *type_handler_for_tmp_table(const Item *item) const const Type_handler *type_handler_for_tmp_table(const Item *item) const
{ {
return varstring_type_handler(item); return varstring_type_handler(item);
@ -2171,6 +2354,9 @@ public:
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2197,6 +2383,9 @@ public:
} }
bool is_param_long_data_type() const { return true; } bool is_param_long_data_type() const { return true; }
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
bool Item_hybrid_func_fix_attributes(THD *thd, bool Item_hybrid_func_fix_attributes(THD *thd,
const char *name, const char *name,
Type_handler_hybrid_field_type *, Type_handler_hybrid_field_type *,
@ -2212,6 +2401,7 @@ public:
virtual ~Type_handler_tiny_blob() {} virtual ~Type_handler_tiny_blob() {}
const Name name() const { return m_name_tinyblob; } const Name name() const { return m_name_tinyblob; }
enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; } enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
@ -2228,6 +2418,7 @@ public:
virtual ~Type_handler_medium_blob() {} virtual ~Type_handler_medium_blob() {}
const Name name() const { return m_name_mediumblob; } const Name name() const { return m_name_mediumblob; }
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; } enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
@ -2244,6 +2435,7 @@ public:
virtual ~Type_handler_long_blob() {} virtual ~Type_handler_long_blob() {}
const Name name() const { return m_name_longblob; } const Name name() const { return m_name_longblob; }
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; } enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
@ -2260,6 +2452,7 @@ public:
virtual ~Type_handler_blob() {} virtual ~Type_handler_blob() {}
const Name name() const { return m_name_blob; } const Name name() const { return m_name_blob; }
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; } enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
@ -2278,6 +2471,7 @@ public:
const Name name() const { return m_name_geometry; } const Name name() const { return m_name_geometry; }
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; } enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
bool is_param_long_data_type() const { return true; } bool is_param_long_data_type() const { return true; }
uint32 calc_pack_length(uint32 length) const;
const Type_handler *type_handler_for_comparison() const; const Type_handler *type_handler_for_comparison() const;
bool type_can_have_key_part() const bool type_can_have_key_part() const
{ {
@ -2295,6 +2489,14 @@ public:
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
ulonglong table_flags) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2343,6 +2545,11 @@ public:
Type_handler_hybrid_field_type *, Type_handler_hybrid_field_type *,
Type_all_attributes *atrr, Type_all_attributes *atrr,
Item **items, uint nitems) const; Item **items, uint nitems) const;
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
Column_definition *c,
handler *file,
ulonglong table_flags) const;
}; };
@ -2353,9 +2560,13 @@ public:
virtual ~Type_handler_enum() {} virtual ~Type_handler_enum() {}
const Name name() const { return m_name_enum; } const Name name() const { return m_name_enum; }
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; } virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,
@ -2370,9 +2581,13 @@ public:
virtual ~Type_handler_set() {} virtual ~Type_handler_set() {}
const Name name() const { return m_name_set; } const Name name() const { return m_name_set; }
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; } virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
uint32 calc_pack_length(uint32 length) const;
Field *make_conversion_table_field(TABLE *, uint metadata, Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const; const Field *target) const;
bool Column_definition_fix_attributes(Column_definition *c) const; bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage2(Column_definition *c,
handler *file,
ulonglong table_flags) const;
Field *make_table_field(const LEX_CSTRING *name, Field *make_table_field(const LEX_CSTRING *name,
const Record_addr &addr, const Record_addr &addr,
const Type_all_attributes &attr, const Type_all_attributes &attr,