Commit f5845574 authored by Alexander Barkov's avatar Alexander Barkov

MDEV-9216 Split field.cc:make_field() into virtual methods in Type_handler

parent dc580225
......@@ -10529,21 +10529,32 @@ uint pack_length_to_packflag(uint type)
}
Field *make_field(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const Record_addr *rec,
uint32 field_length,
uint pack_flag,
const Type_handler *handler,
CHARSET_INFO *field_charset,
Field::geometry_type geom_type, uint srid,
Field::utype unireg_check,
TYPELIB *interval,
const LEX_CSTRING *field_name,
uint32 flags)
uint Column_definition_attributes::pack_flag_to_pack_length() const
{
uint type= f_packtype(pack_flag); // 0..15
DBUG_ASSERT(type < 16);
switch (type) {
case MYSQL_TYPE_TINY: return 1;
case MYSQL_TYPE_SHORT: return 2;
case MYSQL_TYPE_LONG: return 4;
case MYSQL_TYPE_LONGLONG: return 8;
case MYSQL_TYPE_INT24: return 3;
}
return 0; // This should not happen
}
Field *Column_definition_attributes::make_field(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const Record_addr *rec,
const Type_handler *handler,
const LEX_CSTRING *field_name,
uint32 flags)
const
{
DBUG_ASSERT(length <= UINT_MAX32);
DBUG_PRINT("debug", ("field_type: %s, field_length: %u, interval: %p, pack_flag: %s%s%s%s%s",
handler->name().ptr(), field_length, interval,
handler->name().ptr(), (uint) length, interval,
FLAGSTR(pack_flag, FIELDFLAG_BINARY),
FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
......@@ -10552,288 +10563,51 @@ Field *make_field(TABLE_SHARE *share,
Record_addr addr(rec->ptr(), f_maybe_null(pack_flag) ? rec->null() :
Bit_addr());
if (handler == &type_handler_row)
{
DBUG_ASSERT(field_length == 0);
DBUG_ASSERT(f_maybe_null(pack_flag));
return new (mem_root) Field_row(addr.ptr(), field_name);
}
if (f_is_alpha(pack_flag))
{
if (!f_is_packed(pack_flag))
{
enum_field_types field_type= handler->real_field_type();
if (field_type == MYSQL_TYPE_STRING ||
field_type == MYSQL_TYPE_DECIMAL || // 3.23 or 4.0 string
field_type == MYSQL_TYPE_VAR_STRING)
return new (mem_root)
Field_string(addr.ptr(), field_length,
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
field_charset);
if (field_type == MYSQL_TYPE_VARCHAR)
{
if (unireg_check == Field::TMYSQL_COMPRESSED)
return new (mem_root)
Field_varstring_compressed(
addr.ptr(), field_length,
HA_VARCHAR_PACKLENGTH(field_length),
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
share, field_charset, zlib_compression_method);
return new (mem_root)
Field_varstring(addr.ptr(), field_length,
HA_VARCHAR_PACKLENGTH(field_length),
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
share,
field_charset);
}
return 0; // Error
}
// MYSQL_TYPE_VAR_STRING is handled above
DBUG_ASSERT(f_packtype(pack_flag) != MYSQL_TYPE_VAR_STRING);
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
if (f_is_geom(pack_flag))
{
status_var_increment(current_thd->status_var.feature_gis);
return new (mem_root)
Field_geom(addr.ptr(), addr.null_ptr(), addr.null_bit(),
unireg_check, field_name, share,
pack_length, geom_type, srid);
}
#endif
if (f_is_blob(pack_flag))
{
if (unireg_check == Field::TMYSQL_COMPRESSED)
return new (mem_root)
Field_blob_compressed(addr.ptr(), addr.null_ptr(), addr.null_bit(),
unireg_check, field_name, share,
pack_length, field_charset, zlib_compression_method);
return new (mem_root)
Field_blob(addr.ptr(), addr.null_ptr(), addr.null_bit(),
unireg_check, field_name, share,
pack_length, field_charset);
}
if (interval)
{
if (f_is_enum(pack_flag))
return new (mem_root)
Field_enum(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
pack_length, interval, field_charset);
else
return new (mem_root)
Field_set(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
pack_length, interval, field_charset);
}
}
switch (handler->real_field_type()) {
case MYSQL_TYPE_DECIMAL:
return new (mem_root)
Field_decimal(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
f_decimals(pack_flag),
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
case MYSQL_TYPE_NEWDECIMAL:
return new (mem_root)
Field_new_decimal(addr.ptr(), field_length,
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
f_decimals(pack_flag),
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
case MYSQL_TYPE_FLOAT:
{
int decimals= f_decimals(pack_flag);
if (decimals == FLOATING_POINT_DECIMALS)
decimals= NOT_FIXED_DEC;
return new (mem_root)
Field_float(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
decimals,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag)== 0);
}
case MYSQL_TYPE_DOUBLE:
{
int decimals= f_decimals(pack_flag);
if (decimals == FLOATING_POINT_DECIMALS)
decimals= NOT_FIXED_DEC;
return new (mem_root)
Field_double(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
decimals,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag)== 0);
}
case MYSQL_TYPE_TINY:
return new (mem_root)
Field_tiny(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
case MYSQL_TYPE_SHORT:
return new (mem_root)
Field_short(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
case MYSQL_TYPE_INT24:
return new (mem_root)
Field_medium(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
case MYSQL_TYPE_LONG:
return new (mem_root)
Field_long(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
case MYSQL_TYPE_LONGLONG:
if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG))
{
return new (mem_root)
Field_vers_trx_id(addr.ptr(), field_length,
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
}
else
{
return new (mem_root)
Field_longlong(addr.ptr(), field_length,
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
}
case MYSQL_TYPE_TIMESTAMP:
{
uint dec= field_length > MAX_DATETIME_WIDTH ?
field_length - MAX_DATETIME_WIDTH - 1: 0;
return new_Field_timestamp(mem_root, addr.ptr(),
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name, share, dec);
}
case MYSQL_TYPE_TIMESTAMP2:
{
uint dec= field_length > MAX_DATETIME_WIDTH ?
field_length - MAX_DATETIME_WIDTH - 1: 0;
return new (mem_root)
Field_timestampf(addr.ptr(), addr.null_ptr(), addr.null_bit(),
unireg_check, field_name, share, dec);
}
case MYSQL_TYPE_YEAR:
return new (mem_root)
Field_year(addr.ptr(), field_length, addr.null_ptr(), addr.null_bit(),
unireg_check, field_name);
case MYSQL_TYPE_DATE:
return new (mem_root)
Field_date(addr.ptr(), addr.null_ptr(), addr.null_bit(),
unireg_check, field_name);
case MYSQL_TYPE_NEWDATE:
return new (mem_root)
Field_newdate(addr.ptr(), addr.null_ptr(), addr.null_bit(),
unireg_check, field_name);
case MYSQL_TYPE_TIME:
{
uint dec= field_length > MIN_TIME_WIDTH ?
field_length - MIN_TIME_WIDTH - 1: 0;
return new_Field_time(mem_root, addr.ptr(),
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name, dec);
}
case MYSQL_TYPE_TIME2:
{
uint dec= field_length > MIN_TIME_WIDTH ?
field_length - MIN_TIME_WIDTH - 1: 0;
return new (mem_root)
Field_timef(addr.ptr(), addr.null_ptr(), addr.null_bit(), unireg_check,
field_name, dec);
}
case MYSQL_TYPE_DATETIME:
{
uint dec= field_length > MAX_DATETIME_WIDTH ?
field_length - MAX_DATETIME_WIDTH - 1: 0;
return new_Field_datetime(mem_root, addr.ptr(),
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name, dec);
}
case MYSQL_TYPE_DATETIME2:
{
uint dec= field_length > MAX_DATETIME_WIDTH ?
field_length - MAX_DATETIME_WIDTH - 1: 0;
return new (mem_root)
Field_datetimef(addr.ptr(), addr.null_ptr(), addr.null_bit(),
unireg_check, field_name, dec);
}
case MYSQL_TYPE_NULL:
return new (mem_root)
Field_null(addr.ptr(), field_length, unireg_check, field_name,
field_charset);
case MYSQL_TYPE_BIT:
{
Bit_addr bit(rec->null());
if (!f_bit_as_char(pack_flag) && f_maybe_null(pack_flag))
bit.inc();
return (f_bit_as_char(pack_flag) ?
new (mem_root)
Field_bit_as_char(addr.ptr(), field_length,
addr.null_ptr(), addr.null_bit(),
unireg_check, field_name) :
new (mem_root)
Field_bit(addr.ptr(), field_length,
addr.null_ptr(), addr.null_bit(),
bit.ptr(), bit.offs(), unireg_check, field_name));
}
default: // Impossible (Wrong version)
break;
}
return 0;
/*
Special code for the BIT-alike data types
who store data bits together with NULL-bits.
*/
Bit_addr bit(rec->null());
if (f_maybe_null(pack_flag))
bit.inc();
return handler->make_table_field_from_def(share, mem_root, field_name,
addr, bit, this, flags);
}
bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item) const
{
return item->type() == Item::DATE_ITEM;
}
Column_definition_attributes::Column_definition_attributes(const Field *field)
:length(field->field_length),
unireg_check(field->unireg_check),
interval(NULL),
charset(field->charset()), // May be NULL ptr
srid(0),
geom_type(Field::GEOM_GEOMETRY),
pack_flag(0)
{}
/** Create a field suitable for create of table. */
Column_definition::Column_definition(THD *thd, Field *old_field,
Field *orig_field)
:Column_definition_attributes(old_field)
{
on_update= NULL;
field_name= old_field->field_name;
length= old_field->field_length;
flags= old_field->flags;
unireg_check=old_field->unireg_check;
pack_length=old_field->pack_length();
key_length= old_field->key_length();
set_handler(old_field->type_handler());
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
decimals= old_field->decimals();
vcol_info= old_field->vcol_info;
option_list= old_field->option_list;
pack_flag= 0;
compression_method_ptr= 0;
versioning= VERSIONING_NOT_SET;
invisible= old_field->invisible;
......
......@@ -4072,21 +4072,53 @@ class Field_row: public Field_null
extern const LEX_CSTRING null_clex_str;
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
const Record_addr *rec,
uint32 field_length,
uint pack_flag, const Type_handler *handler,
CHARSET_INFO *cs,
Field::geometry_type geom_type, uint srid,
Field::utype unireg_check,
TYPELIB *interval, const LEX_CSTRING *field_name,
uint32 flags);
class Column_definition_attributes
{
public:
/*
At various stages in execution this can be length of field in bytes or
max number of characters.
*/
ulonglong length;
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
CHARSET_INFO *charset;
uint32 srid;
Field::geometry_type geom_type;
uint pack_flag;
Column_definition_attributes()
:length(0),
unireg_check(Field::NONE),
interval(NULL),
charset(&my_charset_bin),
srid(0),
geom_type(Field::GEOM_GEOMETRY),
pack_flag(0)
{ }
Column_definition_attributes(const Field *field);
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
const Record_addr *rec,
const Type_handler *handler,
const LEX_CSTRING *field_name,
uint32 flags) const;
uint temporal_dec(uint intlen) const
{
return (uint) (length > intlen ? length - intlen - 1 : 0);
}
uint pack_flag_to_pack_length() const;
void frm_pack_basic(uchar *buff) const;
void frm_pack_charset(uchar *buff) const;
void frm_unpack_basic(const uchar *buff);
bool frm_unpack_charset(TABLE_SHARE *share, const uchar *buff);
};
/*
Create field class for CREATE TABLE
*/
class Column_definition: public Sql_alloc,
public Type_handler_hybrid_field_type
public Type_handler_hybrid_field_type,
public Column_definition_attributes
{
/**
Create "interval" from "interval_list".
......@@ -4141,11 +4173,6 @@ class Column_definition: public Sql_alloc,
WITHOUT_VERSIONING
};
Item *on_update; // ON UPDATE NOW()
/*
At various stages in execution this can be length of field in bytes or
max number of characters.
*/
ulonglong length;
field_visibility_t invisible;
/*
The value of `length' as set by parser: is the number of characters
......@@ -4153,15 +4180,9 @@ class Column_definition: public Sql_alloc,
*/
uint32 char_length;
uint decimals, flags, pack_length, key_length;
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
List<String> interval_list;
CHARSET_INFO *charset;
uint32 srid;
Field::geometry_type geom_type;
engine_option_value *option_list;
uint pack_flag;
/*
This is additinal data provided for any computed(virtual) field.
......@@ -4179,11 +4200,9 @@ class Column_definition: public Sql_alloc,
:Type_handler_hybrid_field_type(&type_handler_null),
compression_method_ptr(0),
comment(null_clex_str),
on_update(NULL), length(0), invisible(VISIBLE), decimals(0),
flags(0), pack_length(0), key_length(0), unireg_check(Field::NONE),
interval(0), charset(&my_charset_bin),
srid(0), geom_type(Field::GEOM_GEOMETRY),
option_list(NULL), pack_flag(0),
on_update(NULL), invisible(VISIBLE), decimals(0),
flags(0), pack_length(0), key_length(0),
option_list(NULL),
vcol_info(0), default_value(0), check_constraint(0),
versioning(VERSIONING_NOT_SET)
{
......@@ -4316,10 +4335,9 @@ class Column_definition: public Sql_alloc,
const Record_addr *addr,
const LEX_CSTRING *field_name_arg) const
{
return ::make_field(share, mem_root, addr, (uint32) length,
pack_flag, type_handler(), charset,
geom_type, srid, unireg_check, interval,
field_name_arg, flags);
return Column_definition_attributes::make_field(share, mem_root, addr,
type_handler(),
field_name_arg, flags);
}
Field *make_field(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *field_name_arg) const
......@@ -4647,7 +4665,7 @@ bool check_expression(Virtual_column_info *vcol, LEX_CSTRING *name,
#define FIELDFLAG_DEC_SHIFT 8
#define FIELDFLAG_MAX_DEC 63U
#define MTYP_TYPENR(type) (type & 127U) /* Remove bits from type */
#define MTYP_TYPENR(type) ((type) & 127U) // Remove bits from type
#define f_is_dec(x) ((x) & FIELDFLAG_DECIMAL)
#define f_is_num(x) ((x) & FIELDFLAG_NUMBER)
......
......@@ -5780,3 +5780,487 @@ void Type_handler_geometry::Item_param_set_param_func(Item_param *param,
#endif
/***************************************************************************/
Field *Type_handler_row::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
DBUG_ASSERT(attr->length == 0);
DBUG_ASSERT(f_maybe_null(attr->pack_flag));
return new (mem_root) Field_row(rec.ptr(), name);
}
Field *Type_handler_olddecimal::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_decimal(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
f_decimals(attr->pack_flag),
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag) == 0);
}
Field *Type_handler_newdecimal::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_new_decimal(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
f_decimals(attr->pack_flag),
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag) == 0);
}
Field *Type_handler_float::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
int decimals= f_decimals(attr->pack_flag);
if (decimals == FLOATING_POINT_DECIMALS)
decimals= NOT_FIXED_DEC;
return new (mem_root)
Field_float(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, decimals,
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag)== 0);
}
Field *Type_handler_double::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
int decimals= f_decimals(attr->pack_flag);
if (decimals == FLOATING_POINT_DECIMALS)
decimals= NOT_FIXED_DEC;
return new (mem_root)
Field_double(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, decimals,
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag)== 0);
}
Field *Type_handler_tiny::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_tiny(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag) == 0);
}
Field *Type_handler_short::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_short(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag) == 0);
}
Field *Type_handler_int24::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_medium(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag) == 0);
}
Field *Type_handler_long::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_long(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag) == 0);
}
Field *Type_handler_longlong::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG))
return new (mem_root)
Field_vers_trx_id(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag) == 0);
return new (mem_root)
Field_longlong(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
f_is_zerofill(attr->pack_flag) != 0,
f_is_dec(attr->pack_flag) == 0);
}
Field *Type_handler_timestamp::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new_Field_timestamp(mem_root,
rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, share,
attr->temporal_dec(MAX_DATETIME_WIDTH));
}
Field *Type_handler_timestamp2::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_timestampf(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check,
name, share, attr->temporal_dec(MAX_DATETIME_WIDTH));
}
Field *Type_handler_year::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_year(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name);
}
Field *Type_handler_date::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_date(rec.ptr(),rec.null_ptr(),rec.null_bit(),
attr->unireg_check, name);
}
Field *Type_handler_newdate::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_newdate(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name);
}
Field *Type_handler_time::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new_Field_time(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
attr->temporal_dec(MIN_TIME_WIDTH));
}
Field *Type_handler_time2::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_timef(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
attr->temporal_dec(MIN_TIME_WIDTH));
}
Field *Type_handler_datetime::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new_Field_datetime(mem_root, rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
attr->temporal_dec(MAX_DATETIME_WIDTH));
}
Field *Type_handler_datetime2::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_datetimef(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name,
attr->temporal_dec(MAX_DATETIME_WIDTH));
}
Field *Type_handler_null::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_null(rec.ptr(), (uint32) attr->length, attr->unireg_check,
name, attr->charset);
}
Field *Type_handler_bit::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return f_bit_as_char(attr->pack_flag) ?
new (mem_root) Field_bit_as_char(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name) :
new (mem_root) Field_bit(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
bit.ptr(), bit.offs(), attr->unireg_check, name);
}
#ifdef HAVE_SPATIAL
Field *Type_handler_geometry::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
status_var_increment(current_thd->status_var.feature_gis);
return new (mem_root)
Field_geom(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, share,
attr->pack_flag_to_pack_length(), attr->geom_type, attr->srid);
}
#endif
Field *Type_handler_string::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_string(rec.ptr(), (uint32) attr->length,
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, attr->charset);
}
Field *Type_handler_varchar::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
if (attr->unireg_check == Field::TMYSQL_COMPRESSED)
return new (mem_root)
Field_varstring_compressed(rec.ptr(), (uint32) attr->length,
HA_VARCHAR_PACKLENGTH((uint32) attr->length),
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, share, attr->charset,
zlib_compression_method);
return new (mem_root)
Field_varstring(rec.ptr(), (uint32) attr->length,
HA_VARCHAR_PACKLENGTH((uint32) attr->length),
rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, share, attr->charset);
}
Field *Type_handler_blob_common::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
if (attr->unireg_check == Field::TMYSQL_COMPRESSED)
return new (mem_root)
Field_blob_compressed(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, share,
attr->pack_flag_to_pack_length(), attr->charset,
zlib_compression_method);
return new (mem_root)
Field_blob(rec.ptr(), rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, share,
attr->pack_flag_to_pack_length(), attr->charset);
}
Field *Type_handler_enum::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_enum(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, attr->pack_flag_to_pack_length(),
attr->interval, attr->charset);
}
Field *Type_handler_set::
make_table_field_from_def(TABLE_SHARE *share, MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &rec, const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const
{
return new (mem_root)
Field_set(rec.ptr(), (uint32) attr->length, rec.null_ptr(), rec.null_bit(),
attr->unireg_check, name, attr->pack_flag_to_pack_length(),
attr->interval, attr->charset);
}
/***************************************************************************/
void Type_handler::
Column_definition_attributes_frm_pack(const Column_definition_attributes *def,
uchar *buff) const
{
def->frm_pack_basic(buff);
def->frm_pack_charset(buff);
}
#ifdef HAVE_SPATIAL
void Type_handler_geometry::
Column_definition_attributes_frm_pack(const Column_definition_attributes *def,
uchar *buff) const
{
def->frm_pack_basic(buff);
buff[11]= 0;
buff[14]= (uchar) def->geom_type;
}
#endif
/***************************************************************************/
bool Type_handler::
Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
TABLE_SHARE *share,
const uchar *buffer,
LEX_CUSTRING *gis_options)
const
{
attr->frm_unpack_basic(buffer);
return attr->frm_unpack_charset(share, buffer);
}
#ifdef HAVE_SPATIAL
bool Type_handler_geometry::
Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
TABLE_SHARE *share,
const uchar *buffer,
LEX_CUSTRING *gis_options)
const
{
uint gis_opt_read, gis_length, gis_decimals;
Field_geom::storage_type st_type;
attr->frm_unpack_basic(buffer);
// charset and geometry_type share the same byte in frm
attr->geom_type= (Field::geometry_type) buffer[14];
gis_opt_read= gis_field_options_read(gis_options->str,
gis_options->length,
&st_type, &gis_length,
&gis_decimals, &attr->srid);
gis_options->str+= gis_opt_read;
gis_options->length-= gis_opt_read;
return false;
}
#endif
/***************************************************************************/
......@@ -28,6 +28,7 @@
class Field;
class Column_definition;
class Column_definition_attributes;
class Item;
class Item_param;
class Item_cache;
......@@ -1179,6 +1180,23 @@ class Type_handler
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
virtual Field *
make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const= 0;
virtual void
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
uchar *buff) const;
virtual bool
Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
TABLE_SHARE *share,
const uchar *buffer,
LEX_CUSTRING *gis_options) const;
virtual void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const= 0;
......@@ -1465,6 +1483,13 @@ class Type_handler_row: public Type_handler
DBUG_ASSERT(0);
return NULL;
}
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
void make_sort_key(uchar *to, Item *item,
const SORT_FIELD_ATTR *sort_field,
Sort_param *param) const
......@@ -2189,6 +2214,13 @@ class Type_handler_tiny: public Type_handler_general_purpose_int
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
......@@ -2218,6 +2250,13 @@ class Type_handler_short: public Type_handler_general_purpose_int
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
......@@ -2250,6 +2289,13 @@ class Type_handler_long: public Type_handler_general_purpose_int
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
......@@ -2283,6 +2329,13 @@ class Type_handler_longlong: public Type_handler_general_purpose_int
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
......@@ -2323,6 +2376,13 @@ class Type_handler_int24: public Type_handler_general_purpose_int
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2350,6 +2410,13 @@ class Type_handler_year: public Type_handler_int_result
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
Item_cache *Item_get_cache(THD *thd, const Item *item) const;
bool Item_get_date(Item *item, MYSQL_TIME *ltime, ulonglong fuzzydate) const;
};
......@@ -2392,6 +2459,13 @@ class Type_handler_bit: public Type_handler_int_result
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2421,6 +2495,13 @@ class Type_handler_float: public Type_handler_real_result
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
......@@ -2453,6 +2534,13 @@ class Type_handler_double: public Type_handler_real_result
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
void Item_param_set_param_func(Item_param *param,
uchar **pos, ulong len) const;
};
......@@ -2536,6 +2624,13 @@ class Type_handler_time: public Type_handler_time_common
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2555,6 +2650,13 @@ class Type_handler_time2: public Type_handler_time_common
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2617,6 +2719,13 @@ class Type_handler_date: public Type_handler_date_common
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2636,6 +2745,13 @@ class Type_handler_newdate: public Type_handler_date_common
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2697,6 +2813,13 @@ class Type_handler_datetime: public Type_handler_datetime_common
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2716,6 +2839,13 @@ class Type_handler_datetime2: public Type_handler_datetime_common
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2779,6 +2909,13 @@ class Type_handler_timestamp: public Type_handler_timestamp_common
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2800,6 +2937,13 @@ class Type_handler_timestamp2: public Type_handler_timestamp_common
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2824,6 +2968,13 @@ class Type_handler_olddecimal: public Type_handler_decimal_result
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2855,6 +3006,13 @@ class Type_handler_newdecimal: public Type_handler_decimal_result
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2893,6 +3051,13 @@ class Type_handler_null: public Type_handler_general_purpose_string
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2929,6 +3094,13 @@ class Type_handler_string: public Type_handler_longstr
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -2987,6 +3159,13 @@ class Type_handler_varchar: public Type_handler_longstr
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
bool adjust_spparam_type(Spvar_definition *def, Item *from) const;
};
......@@ -3030,6 +3209,13 @@ class Type_handler_blob_common: public Type_handler_longstr
Item **items, uint nitems) const;
void Item_param_setup_conversion(THD *thd, Item_param *) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -3131,6 +3317,14 @@ class Type_handler_geometry: public Type_handler_string_result
const st_value *value) const;
Field *make_conversion_table_field(TABLE *, uint metadata,
const Field *target) const;
void
Column_definition_attributes_frm_pack(const Column_definition_attributes *at,
uchar *buff) const;
bool
Column_definition_attributes_frm_unpack(Column_definition_attributes *attr,
TABLE_SHARE *share,
const uchar *buffer,
LEX_CUSTRING *gis_options) const;
bool Column_definition_fix_attributes(Column_definition *c) const;
bool Column_definition_prepare_stage1(THD *thd,
MEM_ROOT *mem_root,
......@@ -3145,6 +3339,14 @@ class Type_handler_geometry: public Type_handler_string_result
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
bool can_return_int() const { return false; }
bool can_return_decimal() const { return false; }
bool can_return_real() const { return false; }
......@@ -3227,6 +3429,13 @@ class Type_handler_enum: public Type_handler_typelib
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......@@ -3248,6 +3457,13 @@ class Type_handler_set: public Type_handler_typelib
const Record_addr &addr,
const Type_all_attributes &attr,
TABLE *table) const;
Field *make_table_field_from_def(TABLE_SHARE *share,
MEM_ROOT *mem_root,
const LEX_CSTRING *name,
const Record_addr &addr,
const Bit_addr &bit,
const Column_definition_attributes *attr,
uint32 flags) const;
};
......
......@@ -915,6 +915,54 @@ static uint upgrade_collation(ulong mysql_version, uint cs_number)
}
void Column_definition_attributes::frm_pack_basic(uchar *buff) const
{
int2store(buff + 3, length);
int2store(buff + 8, pack_flag);
buff[10]= (uchar) unireg_check;
}
void Column_definition_attributes::frm_unpack_basic(const uchar *buff)
{
length= uint2korr(buff + 3);
pack_flag= uint2korr(buff + 8);
unireg_check= (Field::utype) MTYP_TYPENR((uint) buff[10]);
}
void Column_definition_attributes::frm_pack_charset(uchar *buff) const
{
buff[11]= (uchar) (charset->number >> 8);
buff[14]= (uchar) charset->number;
}
bool Column_definition_attributes::frm_unpack_charset(TABLE_SHARE *share,
const uchar *buff)
{
uint cs_org= buff[14] + (((uint) buff[11]) << 8);
uint cs_new= upgrade_collation(share->mysql_version, cs_org);
if (cs_org != cs_new)
share->incompatible_version|= HA_CREATE_USED_CHARSET;
if (cs_new && !(charset= get_charset(cs_new, MYF(0))))
{
const char *csname= get_charset_name((uint) cs_new);
char tmp[10];
if (!csname || csname[0] =='?')
{
my_snprintf(tmp, sizeof(tmp), "#%u", cs_new);
csname= tmp;
}
my_printf_error(ER_UNKNOWN_COLLATION,
"Unknown collation '%s' in table '%-.64s' definition",
MYF(0), csname, share->table_name.str);
return true;
}
return false;
}
/*
In MySQL 5.7 the null bits for not stored virtual fields are last.
Calculate the position for these bits
......@@ -1145,6 +1193,38 @@ bool parse_vcol_defs(THD *thd, MEM_ROOT *mem_root, TABLE *table,
DBUG_RETURN(res);
}
static const Type_handler *old_frm_type_handler(uint pack_flag,
uint interval_nr)
{
enum_field_types field_type= (enum_field_types) f_packtype(pack_flag);
DBUG_ASSERT(field_type < 16);
if (!f_is_alpha(pack_flag))
return Type_handler::get_handler_by_real_type(field_type);
if (!f_is_packed(pack_flag))
{
if (field_type == MYSQL_TYPE_DECIMAL) // 3.23 or 4.0 string
return &type_handler_string;
if (field_type == MYSQL_TYPE_VARCHAR) // Since mysql-5.0
return &type_handler_varchar;
return NULL; // Error (bad frm?)
}
if (f_is_blob(pack_flag))
return &type_handler_blob; // QQ: exact type??
if (interval_nr)
{
if (f_is_enum(pack_flag))
return &type_handler_enum;
return &type_handler_set;
}
return Type_handler::get_handler_by_real_type(field_type);
}
/**
Read data from a binary .frm file image into a TABLE_SHARE
......@@ -1191,8 +1271,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
size_t UNINIT_VAR(options_len);
uchar *vcol_screen_pos;
const uchar *options= 0;
size_t UNINIT_VAR(gis_options_len);
const uchar *gis_options= 0;
LEX_CUSTRING gis_options= { NULL, 0};
KEY first_keyinfo;
uint len;
uint ext_key_parts= 0;
......@@ -1288,10 +1367,10 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
case EXTRA2_GIS:
#ifdef HAVE_SPATIAL
{
if (gis_options)
if (gis_options.str)
goto err;
gis_options= extra2;
gis_options_len= length;
gis_options.str= extra2;
gis_options.length= length;
}
#endif /*HAVE_SPATIAL*/
break;
......@@ -1781,82 +1860,19 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
for (i=0 ; i < share->fields; i++, strpos+=field_pack_length, field_ptr++)
{
uint pack_flag, interval_nr, unireg_type, recpos, field_length;
uint vcol_info_length=0;
uint vcol_expr_length=0;
enum_field_types field_type;
CHARSET_INFO *charset=NULL;
Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
uint interval_nr= 0, recpos;
LEX_CSTRING comment;
LEX_CSTRING name;
Virtual_column_info *vcol_info= 0;
uint gis_length, gis_decimals, srid= 0;
Field::utype unireg_check;
const Type_handler *handler;
uint32 flags= 0;
Column_definition_attributes attr;
if (new_frm_ver >= 3)
{
/* new frm file in 4.1 */
field_length= uint2korr(strpos+3);
recpos= uint3korr(strpos+5);
pack_flag= uint2korr(strpos+8);
unireg_type= (uint) strpos[10];
interval_nr= (uint) strpos[12];
uint comment_length=uint2korr(strpos+15);
field_type=(enum_field_types) (uint) strpos[13];
/* charset and geometry_type share the same byte in frm */
if (field_type == MYSQL_TYPE_GEOMETRY)
{
#ifdef HAVE_SPATIAL
uint gis_opt_read;
Field_geom::storage_type st_type;
geom_type= (Field::geometry_type) strpos[14];
charset= &my_charset_bin;
gis_opt_read= gis_field_options_read(gis_options, gis_options_len,
&st_type, &gis_length, &gis_decimals, &srid);
gis_options+= gis_opt_read;
gis_options_len-= gis_opt_read;
#else
goto err;
#endif
}
else
{
uint cs_org= strpos[14] + (((uint) strpos[11]) << 8);
uint cs_new= upgrade_collation(share->mysql_version, cs_org);
if (cs_org != cs_new)
share->incompatible_version|= HA_CREATE_USED_CHARSET;
if (!cs_new)
charset= &my_charset_bin;
else if (!(charset= get_charset(cs_new, MYF(0))))
{
const char *csname= get_charset_name((uint) cs_new);
char tmp[10];
if (!csname || csname[0] =='?')
{
my_snprintf(tmp, sizeof(tmp), "#%u", cs_new);
csname= tmp;
}
my_printf_error(ER_UNKNOWN_COLLATION,
"Unknown collation '%s' in table '%-.64s' definition",
MYF(0), csname, share->table_name.str);
goto err;
}
}
if ((uchar)field_type == (uchar)MYSQL_TYPE_VIRTUAL)
{
DBUG_ASSERT(interval_nr); // Expect non-null expression
/*
MariaDB version 10.0 version.
The interval_id byte in the .frm file stores the length of the
expression statement for a virtual column.
*/
vcol_info_length= interval_nr;
interval_nr= 0;
}
if (!comment_length)
{
......@@ -1870,32 +1886,20 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
comment_pos+= comment_length;
}
if (unireg_type & MYSQL57_GENERATED_FIELD)
if ((uchar) strpos[13] == (uchar) MYSQL_TYPE_VIRTUAL)
{
unireg_type&= MYSQL57_GENERATED_FIELD;
/*
MySQL 5.7 generated fields
byte 1 = 1
byte 2,3 = expr length
byte 4 = stored_in_db
byte 5.. = expr
MariaDB version 10.0 version.
The interval_id byte in the .frm file stores the length of the
expression statement for a virtual column.
*/
if ((uint)(vcol_screen_pos)[0] != 1)
goto err;
vcol_info= new (&share->mem_root) Virtual_column_info();
vcol_info_length= uint2korr(vcol_screen_pos + 1);
DBUG_ASSERT(vcol_info_length);
vcol_info->stored_in_db= vcol_screen_pos[3];
vcol_info->utf8= 0;
vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;;
share->virtual_fields++;
vcol_info_length= 0;
}
uint vcol_info_length= (uint) strpos[12];
if (vcol_info_length)
{
DBUG_ASSERT(vcol_info_length); // Expect non-null expression
attr.frm_unpack_basic(strpos);
if (attr.frm_unpack_charset(share, strpos))
goto err;
/*
Old virtual field information before 10.2
......@@ -1909,7 +1913,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
vcol_info= new (&share->mem_root) Virtual_column_info();
bool opt_interval_id= (uint)vcol_screen_pos[0] == 2;
field_type= (enum_field_types) (uchar) vcol_screen_pos[1];
enum_field_types ftype= (enum_field_types) (uchar) vcol_screen_pos[1];
if (!(handler= Type_handler::get_handler_by_real_type(ftype)))
goto err;
if (opt_interval_id)
interval_nr= (uint)vcol_screen_pos[3];
else if ((uint)vcol_screen_pos[0] != 1)
......@@ -1917,26 +1923,63 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
bool stored= vcol_screen_pos[2] & 1;
vcol_info->stored_in_db= stored;
vcol_info->set_vcol_type(stored ? VCOL_GENERATED_STORED : VCOL_GENERATED_VIRTUAL);
vcol_expr_length= vcol_info_length -
(uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id));
uint vcol_expr_length= vcol_info_length -
(uint)(FRM_VCOL_OLD_HEADER_SIZE(opt_interval_id));
vcol_info->utf8= 0; // before 10.2.1 the charset was unknown
int2store(vcol_screen_pos+1, vcol_expr_length); // for parse_vcol_defs()
vcol_screen_pos+= vcol_info_length;
share->virtual_fields++;
}
else
{
interval_nr= (uint) strpos[12];
enum_field_types field_type= (enum_field_types) strpos[13];
if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
goto err; // Not supported field type
if (handler->Column_definition_attributes_frm_unpack(&attr, share,
strpos,
&gis_options))
goto err;
}
if (((uint) strpos[10]) & MYSQL57_GENERATED_FIELD)
{
attr.unireg_check= Field::NONE;
/*
MySQL 5.7 generated fields
byte 1 = 1
byte 2,3 = expr length
byte 4 = stored_in_db
byte 5.. = expr
*/
if ((uint)(vcol_screen_pos)[0] != 1)
goto err;
vcol_info= new (&share->mem_root) Virtual_column_info();
uint vcol_info_length= uint2korr(vcol_screen_pos + 1);
DBUG_ASSERT(vcol_info_length);
vcol_info->stored_in_db= vcol_screen_pos[3];
vcol_info->utf8= 0;
vcol_screen_pos+= vcol_info_length + MYSQL57_GCOL_HEADER_SIZE;;
share->virtual_fields++;
}
}
else
{
field_length= (uint) strpos[3];
attr.length= (uint) strpos[3];
recpos= uint2korr(strpos+4),
pack_flag= uint2korr(strpos+6);
pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
unireg_type= (uint) strpos[8];
attr.pack_flag= uint2korr(strpos+6);
attr.pack_flag&= ~FIELDFLAG_NO_DEFAULT; // Safety for old files
attr.unireg_check= (Field::utype) MTYP_TYPENR((uint) strpos[8]);
interval_nr= (uint) strpos[10];
/* old frm file */
field_type= (enum_field_types) f_packtype(pack_flag);
if (f_is_binary(pack_flag))
enum_field_types ftype= (enum_field_types) f_packtype(attr.pack_flag);
if (!(handler= Type_handler::get_handler_by_real_type(ftype)))
goto err; // Not supported field type
if (f_is_binary(attr.pack_flag))
{
/*
Try to choose the best 4.1 type:
......@@ -1944,26 +1987,26 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
try to find a binary collation for character set.
- for other types (e.g. BLOB) just use my_charset_bin.
*/
if (!f_is_blob(pack_flag))
if (!f_is_blob(attr.pack_flag))
{
// 3.23 or 4.0 string
if (!(charset= get_charset_by_csname(share->table_charset->csname,
MY_CS_BINSORT, MYF(0))))
charset= &my_charset_bin;
if (!(attr.charset= get_charset_by_csname(share->table_charset->csname,
MY_CS_BINSORT, MYF(0))))
attr.charset= &my_charset_bin;
}
else
charset= &my_charset_bin;
}
else
charset= share->table_charset;
attr.charset= share->table_charset;
bzero((char*) &comment, sizeof(comment));
if ((!(handler= old_frm_type_handler(attr.pack_flag, interval_nr))))
goto err; // Not supported field type
}
/* Remove >32 decimals from old files */
if (share->mysql_version < 100200)
pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
attr.pack_flag&= ~FIELDFLAG_LONG_DECIMAL;
if (interval_nr && charset->mbminlen > 1)
if (interval_nr && attr.charset->mbminlen > 1)
{
/* Unescape UCS2 intervals from HEX notation */
TYPELIB *interval= share->intervals + interval_nr - 1;
......@@ -1971,17 +2014,18 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
#ifndef TO_BE_DELETED_ON_PRODUCTION
if (field_type == MYSQL_TYPE_NEWDECIMAL && !share->mysql_version)
if (handler->real_field_type() == MYSQL_TYPE_NEWDECIMAL &&
!share->mysql_version)
{
/*
Fix pack length of old decimal values from 5.0.3 -> 5.0.4
The difference is that in the old version we stored precision
in the .frm table while we now store the display_length
*/
uint decimals= f_decimals(pack_flag);
field_length= my_decimal_precision_to_length(field_length,
decimals,
f_is_dec(pack_flag) == 0);
uint decimals= f_decimals(attr.pack_flag);
attr.length=
my_decimal_precision_to_length((uint) attr.length, decimals,
f_is_dec(attr.pack_flag) == 0);
sql_print_error("Found incompatible DECIMAL field '%s' in %s; "
"Please do \"ALTER TABLE '%s' FORCE\" to fix it!",
share->fieldnames.type_names[i], share->table_name.str,
......@@ -2012,7 +2056,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
if (flags & VERS_SYSTEM_FIELD)
{
switch (field_type)
switch (handler->real_field_type())
{
case MYSQL_TYPE_TIMESTAMP2:
case MYSQL_TYPE_DATETIME2:
......@@ -2034,23 +2078,17 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
/* Convert pre-10.2.2 timestamps to use Field::default_value */
unireg_check= (Field::utype) MTYP_TYPENR(unireg_type);
name.str= fieldnames.type_names[i];
name.length= strlen(name.str);
if (!(handler= Type_handler::get_handler_by_real_type(field_type)))
goto err; // Not supported field type
attr.interval= interval_nr ? share->intervals + interval_nr - 1 : NULL;
Record_addr addr(record + recpos, null_pos, null_bit_pos);
*field_ptr= reg_field=
make_field(share, &share->mem_root, &addr,
(uint32) field_length, pack_flag, handler, charset,
geom_type, srid, unireg_check,
(interval_nr ? share->intervals + interval_nr - 1 : NULL),
&name, flags);
attr.make_field(share, &share->mem_root, &addr, handler, &name, flags);
if (!reg_field) // Not supported field type
goto err;
if (unireg_check == Field::TIMESTAMP_DNUN_FIELD ||
unireg_check == Field::TIMESTAMP_DN_FIELD)
if (attr.unireg_check == Field::TIMESTAMP_DNUN_FIELD ||
attr.unireg_check == Field::TIMESTAMP_DN_FIELD)
{
reg_field->default_value= new (&share->mem_root) Virtual_column_info();
reg_field->default_value->set_vcol_type(VCOL_DEFAULT);
......@@ -2074,10 +2112,11 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
status_var_increment(thd->status_var.feature_invisible_columns);
if (!reg_field->invisible)
share->visible_fields++;
if (field_type == MYSQL_TYPE_BIT && !f_bit_as_char(pack_flag))
if (handler->real_field_type() == MYSQL_TYPE_BIT &&
!f_bit_as_char(attr.pack_flag))
{
null_bits_are_used= 1;
if ((null_bit_pos+= field_length & 7) > 7)
if ((null_bit_pos+= (uint) (attr.length & 7)) > 7)
{
null_pos++;
null_bit_pos-= 8;
......@@ -2100,7 +2139,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write,
}
}
if (f_no_default(pack_flag))
if (f_no_default(attr.pack_flag))
reg_field->flags|= NO_DEFAULT_VALUE_FLAG;
if (reg_field->unireg_check == Field::NEXT_NUMBER)
......
......@@ -897,32 +897,12 @@ static bool pack_fields(uchar **buff_arg, List<Create_field> &create_fields,
while ((field=it++))
{
uint recpos;
int2store(buff+3, field->length);
/* The +1 is here becasue the col offset in .frm file have offset 1 */
recpos= field->offset+1 + (uint) data_offset;
int3store(buff+5,recpos);
int2store(buff+8,field->pack_flag);
buff[10]= (uchar) field->unireg_check;
buff[12]= (uchar) field->interval_id;
buff[13]= (uchar) field->real_field_type();
if (field->real_field_type() == MYSQL_TYPE_GEOMETRY)
{
buff[11]= 0;
buff[14]= (uchar) field->geom_type;
#ifndef HAVE_SPATIAL
DBUG_ASSERT(0); // Should newer happen
#endif
}
else if (field->charset)
{
buff[11]= (uchar) (field->charset->number >> 8);
buff[14]= (uchar) field->charset->number;
}
else
{
buff[11]= buff[14]= 0; // Numerical
}
buff[13]= (uchar) field->type_handler()->real_field_type();
field->type_handler()->Column_definition_attributes_frm_pack(field, buff);
int2store(buff+15, field->comment.length);
comment_length+= field->comment.length;
set_if_bigger(int_count,field->interval_id);
......@@ -1045,18 +1025,14 @@ static bool make_empty_rec(THD *thd, uchar *buff, uint table_options,
{
Record_addr addr(buff + field->offset + data_offset,
null_pos + null_count / 8, null_count & 7);
Column_definition_attributes tmp(*field);
tmp.interval= field->save_interval ?
field->save_interval : field->interval;
/* regfield don't have to be deleted as it's allocated on THD::mem_root */
Field *regfield= make_field(&share, thd->mem_root, &addr,
(uint32) field->length,
field->pack_flag,
field->type_handler(),
field->charset,
field->geom_type, field->srid,
field->unireg_check,
field->save_interval ? field->save_interval
: field->interval,
&field->field_name,
field->flags);
Field *regfield= tmp.make_field(&share, thd->mem_root, &addr,
field->type_handler(),
&field->field_name,
field->flags);
if (!regfield)
{
error= 1;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment