mirror of
https://github.com/MariaDB/server.git
synced 2025-08-01 03:47:19 +03:00
MDEV-9238 Wrap create_virtual_tmp_table() into a class, split into different steps
This commit is contained in:
111
sql/field.cc
111
sql/field.cc
@ -9651,117 +9651,6 @@ void Column_definition::create_length_to_internal_length(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
Init for a tmp table field. To be extended if need be.
|
|
||||||
*/
|
|
||||||
void Column_definition::init_for_tmp_table(enum_field_types sql_type_arg,
|
|
||||||
uint32 length_arg,
|
|
||||||
uint32 decimals_arg,
|
|
||||||
bool maybe_null, bool is_unsigned,
|
|
||||||
uint pack_length_arg)
|
|
||||||
{
|
|
||||||
DBUG_ENTER("Create_field::init_for_tmp_table");
|
|
||||||
|
|
||||||
field_name= "";
|
|
||||||
sql_type= sql_type_arg;
|
|
||||||
char_length= length= length_arg;;
|
|
||||||
unireg_check= Field::NONE;
|
|
||||||
interval= 0;
|
|
||||||
charset= &my_charset_bin;
|
|
||||||
geom_type= Field::GEOM_GEOMETRY;
|
|
||||||
|
|
||||||
DBUG_PRINT("enter", ("sql_type: %d, length: %u, pack_length: %u",
|
|
||||||
sql_type_arg, length_arg, pack_length_arg));
|
|
||||||
|
|
||||||
/*
|
|
||||||
These pack flags are crafted to get it correctly through the
|
|
||||||
branches of make_field().
|
|
||||||
*/
|
|
||||||
switch (sql_type_arg)
|
|
||||||
{
|
|
||||||
case MYSQL_TYPE_VARCHAR:
|
|
||||||
case MYSQL_TYPE_VAR_STRING:
|
|
||||||
case MYSQL_TYPE_STRING:
|
|
||||||
case MYSQL_TYPE_SET:
|
|
||||||
pack_flag= 0;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_GEOMETRY:
|
|
||||||
pack_flag= FIELDFLAG_GEOM;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_ENUM:
|
|
||||||
pack_flag= FIELDFLAG_INTERVAL;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_NEWDECIMAL:
|
|
||||||
DBUG_ASSERT(decimals_arg <= DECIMAL_MAX_SCALE);
|
|
||||||
case MYSQL_TYPE_DECIMAL:
|
|
||||||
case MYSQL_TYPE_FLOAT:
|
|
||||||
case MYSQL_TYPE_DOUBLE:
|
|
||||||
pack_flag= FIELDFLAG_NUMBER |
|
|
||||||
(decimals_arg & FIELDFLAG_MAX_DEC) << FIELDFLAG_DEC_SHIFT;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_TINY_BLOB:
|
|
||||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
|
||||||
case MYSQL_TYPE_LONG_BLOB:
|
|
||||||
case MYSQL_TYPE_BLOB:
|
|
||||||
pack_flag= FIELDFLAG_BLOB;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_BIT:
|
|
||||||
pack_flag= FIELDFLAG_NUMBER | FIELDFLAG_TREAT_BIT_AS_CHAR;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
pack_flag= FIELDFLAG_NUMBER;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
Set the pack flag correctly for the blob-like types. This sets the
|
|
||||||
packtype to something that make_field can use. If the pack type is
|
|
||||||
not set correctly, the packlength will be reeeeally wierd (like
|
|
||||||
129 or so).
|
|
||||||
*/
|
|
||||||
switch (sql_type_arg)
|
|
||||||
{
|
|
||||||
case MYSQL_TYPE_ENUM:
|
|
||||||
case MYSQL_TYPE_SET:
|
|
||||||
case MYSQL_TYPE_TINY_BLOB:
|
|
||||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
|
||||||
case MYSQL_TYPE_LONG_BLOB:
|
|
||||||
case MYSQL_TYPE_BLOB:
|
|
||||||
case MYSQL_TYPE_GEOMETRY:
|
|
||||||
// If you are going to use the above types, you have to pass a
|
|
||||||
// pack_length as parameter. Assert that is really done.
|
|
||||||
DBUG_ASSERT(pack_length_arg != ~0U);
|
|
||||||
pack_flag|= pack_length_to_packflag(pack_length_arg);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
/* Nothing */
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
pack_flag|=
|
|
||||||
(maybe_null ? FIELDFLAG_MAYBE_NULL : 0) |
|
|
||||||
(is_unsigned ? 0 : FIELDFLAG_DECIMAL);
|
|
||||||
|
|
||||||
DBUG_PRINT("debug", ("pack_flag: %s%s%s%s%s%s, pack_type: %d",
|
|
||||||
FLAGSTR(pack_flag, FIELDFLAG_BINARY),
|
|
||||||
FLAGSTR(pack_flag, FIELDFLAG_NUMBER),
|
|
||||||
FLAGSTR(pack_flag, FIELDFLAG_INTERVAL),
|
|
||||||
FLAGSTR(pack_flag, FIELDFLAG_GEOM),
|
|
||||||
FLAGSTR(pack_flag, FIELDFLAG_BLOB),
|
|
||||||
FLAGSTR(pack_flag, FIELDFLAG_DECIMAL),
|
|
||||||
f_packtype(pack_flag)));
|
|
||||||
vcol_info= 0;
|
|
||||||
|
|
||||||
DBUG_VOID_RETURN;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static inline bool is_item_func(Item* x)
|
static inline bool is_item_func(Item* x)
|
||||||
{
|
{
|
||||||
return x != NULL && x->type() == Item::FUNC_ITEM;
|
return x != NULL && x->type() == Item::FUNC_ITEM;
|
||||||
|
@ -3481,12 +3481,6 @@ public:
|
|||||||
Column_definition(THD *thd, Field *field, Field *orig_field);
|
Column_definition(THD *thd, Field *field, Field *orig_field);
|
||||||
void create_length_to_internal_length(void);
|
void create_length_to_internal_length(void);
|
||||||
|
|
||||||
/* Init for a tmp table field. To be extended if need be. */
|
|
||||||
void init_for_tmp_table(enum_field_types sql_type_arg,
|
|
||||||
uint32 max_length, uint32 decimals,
|
|
||||||
bool maybe_null, bool is_unsigned,
|
|
||||||
uint pack_length = ~0U);
|
|
||||||
|
|
||||||
bool check(THD *thd);
|
bool check(THD *thd);
|
||||||
|
|
||||||
bool stored_in_db() const { return !vcol_info || vcol_info->stored_in_db; }
|
bool stored_in_db() const { return !vcol_info || vcol_info->stored_in_db; }
|
||||||
|
11
sql/item.h
11
sql/item.h
@ -759,6 +759,17 @@ public:
|
|||||||
{
|
{
|
||||||
return get_handler_by_field_type(field_type());
|
return get_handler_by_field_type(field_type());
|
||||||
}
|
}
|
||||||
|
Field *make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
|
||||||
|
const Item *item) const
|
||||||
|
{
|
||||||
|
return type_handler()->make_num_distinct_aggregator_field(mem_root, this);
|
||||||
|
}
|
||||||
|
Field *make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata, const Field *target) const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(0); // Should not be called in Item context
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
/* result_type() of an item specifies how the value should be returned */
|
/* result_type() of an item specifies how the value should be returned */
|
||||||
Item_result result_type() const { return type_handler()->result_type(); }
|
Item_result result_type() const { return type_handler()->result_type(); }
|
||||||
/* ... while cmp_type() specifies how it should be compared */
|
/* ... while cmp_type() specifies how it should be compared */
|
||||||
|
@ -684,32 +684,6 @@ int Aggregator_distinct::composite_key_cmp(void* arg, uchar* key1, uchar* key2)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static enum enum_field_types
|
|
||||||
calc_tmp_field_type(enum enum_field_types table_field_type,
|
|
||||||
Item_result result_type)
|
|
||||||
{
|
|
||||||
/* Adjust tmp table type according to the chosen aggregation type */
|
|
||||||
switch (result_type) {
|
|
||||||
case STRING_RESULT:
|
|
||||||
case REAL_RESULT:
|
|
||||||
if (table_field_type != MYSQL_TYPE_FLOAT)
|
|
||||||
table_field_type= MYSQL_TYPE_DOUBLE;
|
|
||||||
break;
|
|
||||||
case INT_RESULT:
|
|
||||||
table_field_type= MYSQL_TYPE_LONGLONG;
|
|
||||||
/* fallthrough */
|
|
||||||
case DECIMAL_RESULT:
|
|
||||||
if (table_field_type != MYSQL_TYPE_LONGLONG)
|
|
||||||
table_field_type= MYSQL_TYPE_NEWDECIMAL;
|
|
||||||
break;
|
|
||||||
case ROW_RESULT:
|
|
||||||
default:
|
|
||||||
DBUG_ASSERT(0);
|
|
||||||
}
|
|
||||||
return table_field_type;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/***************************************************************************/
|
/***************************************************************************/
|
||||||
|
|
||||||
C_MODE_START
|
C_MODE_START
|
||||||
@ -886,8 +860,6 @@ bool Aggregator_distinct::setup(THD *thd)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
List<Column_definition> field_list;
|
|
||||||
Column_definition field_def; /* field definition */
|
|
||||||
Item *arg;
|
Item *arg;
|
||||||
DBUG_ENTER("Aggregator_distinct::setup");
|
DBUG_ENTER("Aggregator_distinct::setup");
|
||||||
/* It's legal to call setup() more than once when in a subquery */
|
/* It's legal to call setup() more than once when in a subquery */
|
||||||
@ -899,8 +871,6 @@ bool Aggregator_distinct::setup(THD *thd)
|
|||||||
PS/SP. Hence all further allocations are performed in the runtime
|
PS/SP. Hence all further allocations are performed in the runtime
|
||||||
mem_root.
|
mem_root.
|
||||||
*/
|
*/
|
||||||
if (field_list.push_back(&field_def, thd->mem_root))
|
|
||||||
DBUG_RETURN(TRUE);
|
|
||||||
|
|
||||||
item_sum->null_value= item_sum->maybe_null= 1;
|
item_sum->null_value= item_sum->maybe_null= 1;
|
||||||
item_sum->quick_group= 0;
|
item_sum->quick_group= 0;
|
||||||
@ -918,17 +888,8 @@ bool Aggregator_distinct::setup(THD *thd)
|
|||||||
if (always_null)
|
if (always_null)
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
|
|
||||||
enum enum_field_types field_type;
|
Field *field= arg->make_num_distinct_aggregator_field(thd->mem_root, arg);
|
||||||
|
if (!field || !(table= create_virtual_tmp_table(thd, field)))
|
||||||
field_type= calc_tmp_field_type(arg->field_type(),
|
|
||||||
arg->result_type());
|
|
||||||
field_def.init_for_tmp_table(field_type,
|
|
||||||
arg->max_length,
|
|
||||||
arg->decimals,
|
|
||||||
arg->maybe_null,
|
|
||||||
arg->unsigned_flag);
|
|
||||||
|
|
||||||
if (! (table= create_virtual_tmp_table(thd, field_list)))
|
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
|
|
||||||
/* XXX: check that the case of CHAR(0) works OK */
|
/* XXX: check that the case of CHAR(0) works OK */
|
||||||
|
@ -922,6 +922,51 @@ table_def::compatible_with(THD *thd, rpl_group_info *rgi,
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
A wrapper to Virtual_tmp_table, to get access to its constructor,
|
||||||
|
which is protected for safety purposes (against illegal use on stack).
|
||||||
|
*/
|
||||||
|
class Virtual_conversion_table: public Virtual_tmp_table
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Virtual_conversion_table(THD *thd) :Virtual_tmp_table(thd) { }
|
||||||
|
/**
|
||||||
|
Add a new field into the virtual table.
|
||||||
|
@param sql_type - The real_type of the field.
|
||||||
|
@param metadata - The RBR binary log metadata for this field.
|
||||||
|
@param target_field - The field from the target table, to get extra
|
||||||
|
attributes from (e.g. typelib in case of ENUM).
|
||||||
|
*/
|
||||||
|
bool add(enum_field_types sql_type,
|
||||||
|
uint16 metadata, const Field *target_field)
|
||||||
|
{
|
||||||
|
const Type_handler *handler= Type_handler::get_handler_by_real_type(sql_type);
|
||||||
|
if (!handler)
|
||||||
|
{
|
||||||
|
sql_print_error("In RBR mode, Slave received unknown field type field %d "
|
||||||
|
" for column Name: %s.%s.%s.",
|
||||||
|
(int) sql_type,
|
||||||
|
target_field->table->s->db.str,
|
||||||
|
target_field->table->s->table_name.str,
|
||||||
|
target_field->field_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Field *tmp= handler->make_conversion_table_field(this, metadata,
|
||||||
|
target_field);
|
||||||
|
if (!tmp)
|
||||||
|
return true;
|
||||||
|
Virtual_tmp_table::add(tmp);
|
||||||
|
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
|
||||||
|
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
|
||||||
|
sql_type, target_field->field_name,
|
||||||
|
tmp->field_length, tmp->decimals(), TRUE,
|
||||||
|
tmp->flags, tmp->pack_length()));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a conversion table.
|
Create a conversion table.
|
||||||
|
|
||||||
@ -937,8 +982,7 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("table_def::create_conversion_table");
|
DBUG_ENTER("table_def::create_conversion_table");
|
||||||
|
|
||||||
List<Column_definition> field_list;
|
Virtual_conversion_table *conv_table;
|
||||||
TABLE *conv_table= NULL;
|
|
||||||
Relay_log_info *rli= rgi->rli;
|
Relay_log_info *rli= rgi->rli;
|
||||||
/*
|
/*
|
||||||
At slave, columns may differ. So we should create
|
At slave, columns may differ. So we should create
|
||||||
@ -946,101 +990,35 @@ TABLE *table_def::create_conversion_table(THD *thd, rpl_group_info *rgi,
|
|||||||
conversion table.
|
conversion table.
|
||||||
*/
|
*/
|
||||||
uint const cols_to_create= MY_MIN(target_table->s->fields, size());
|
uint const cols_to_create= MY_MIN(target_table->s->fields, size());
|
||||||
|
if (!(conv_table= new(thd) Virtual_conversion_table(thd)) ||
|
||||||
|
conv_table->init(cols_to_create))
|
||||||
|
goto err;
|
||||||
for (uint col= 0 ; col < cols_to_create; ++col)
|
for (uint col= 0 ; col < cols_to_create; ++col)
|
||||||
{
|
{
|
||||||
Column_definition *field_def=
|
if (conv_table->add(type(col), field_metadata(col),
|
||||||
(Create_field*) alloc_root(thd->mem_root, sizeof(Create_field));
|
target_table->field[col]))
|
||||||
bool unsigned_flag= 0;
|
{
|
||||||
if (field_list.push_back(field_def, thd->mem_root))
|
DBUG_PRINT("debug", ("binlog_type: %d, metadata: %04X, target_field: '%s'"
|
||||||
DBUG_RETURN(NULL);
|
" make_conversion_table_field() failed",
|
||||||
|
binlog_type(col), field_metadata(col),
|
||||||
uint decimals= 0;
|
target_table->field[col]->field_name));
|
||||||
TYPELIB* interval= NULL;
|
|
||||||
uint pack_length= 0;
|
|
||||||
uint32 max_length=
|
|
||||||
max_display_length_for_field(type(col), field_metadata(col));
|
|
||||||
|
|
||||||
switch(type(col)) {
|
|
||||||
int precision;
|
|
||||||
case MYSQL_TYPE_ENUM:
|
|
||||||
case MYSQL_TYPE_SET:
|
|
||||||
interval= static_cast<Field_enum*>(target_table->field[col])->typelib;
|
|
||||||
pack_length= field_metadata(col) & 0x00ff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_NEWDECIMAL:
|
|
||||||
/*
|
|
||||||
The display length of a DECIMAL type is not the same as the
|
|
||||||
length that should be supplied to make_field, so we correct
|
|
||||||
the length here.
|
|
||||||
*/
|
|
||||||
precision= field_metadata(col) >> 8;
|
|
||||||
decimals= field_metadata(col) & 0x00ff;
|
|
||||||
max_length=
|
|
||||||
my_decimal_precision_to_length(precision, decimals, FALSE);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_DECIMAL:
|
|
||||||
sql_print_error("In RBR mode, Slave received incompatible DECIMAL field "
|
|
||||||
"(old-style decimal field) from Master while creating "
|
|
||||||
"conversion table. Please consider changing datatype on "
|
|
||||||
"Master to new style decimal by executing ALTER command for"
|
|
||||||
" column Name: %s.%s.%s.",
|
|
||||||
target_table->s->db.str,
|
|
||||||
target_table->s->table_name.str,
|
|
||||||
target_table->field[col]->field_name);
|
|
||||||
goto err;
|
goto err;
|
||||||
|
}
|
||||||
case MYSQL_TYPE_TINY_BLOB:
|
|
||||||
case MYSQL_TYPE_MEDIUM_BLOB:
|
|
||||||
case MYSQL_TYPE_LONG_BLOB:
|
|
||||||
case MYSQL_TYPE_BLOB:
|
|
||||||
case MYSQL_TYPE_GEOMETRY:
|
|
||||||
pack_length= field_metadata(col) & 0x00ff;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case MYSQL_TYPE_TINY:
|
|
||||||
case MYSQL_TYPE_SHORT:
|
|
||||||
case MYSQL_TYPE_INT24:
|
|
||||||
case MYSQL_TYPE_LONG:
|
|
||||||
case MYSQL_TYPE_LONGLONG:
|
|
||||||
/*
|
|
||||||
As we don't know if the integer was signed or not on the master,
|
|
||||||
assume we have same sign on master and slave. This is true when not
|
|
||||||
using conversions so it should be true also when using conversions.
|
|
||||||
*/
|
|
||||||
unsigned_flag= ((Field_num*) target_table->field[col])->unsigned_flag;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_PRINT("debug", ("sql_type: %d, target_field: '%s', max_length: %d, decimals: %d,"
|
if (conv_table->open())
|
||||||
" maybe_null: %d, unsigned_flag: %d, pack_length: %u",
|
goto err; // Could not allocate record buffer?
|
||||||
binlog_type(col), target_table->field[col]->field_name,
|
|
||||||
max_length, decimals, TRUE, unsigned_flag,
|
|
||||||
pack_length));
|
|
||||||
field_def->init_for_tmp_table(type(col),
|
|
||||||
max_length,
|
|
||||||
decimals,
|
|
||||||
TRUE, // maybe_null
|
|
||||||
unsigned_flag,
|
|
||||||
pack_length);
|
|
||||||
field_def->charset= target_table->field[col]->charset();
|
|
||||||
field_def->interval= interval;
|
|
||||||
}
|
|
||||||
|
|
||||||
conv_table= create_virtual_tmp_table(thd, field_list);
|
DBUG_RETURN(conv_table);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
if (conv_table == NULL)
|
if (conv_table)
|
||||||
{
|
delete conv_table;
|
||||||
rli->report(ERROR_LEVEL, ER_SLAVE_CANT_CREATE_CONVERSION, rgi->gtid_info(),
|
rli->report(ERROR_LEVEL, ER_SLAVE_CANT_CREATE_CONVERSION, rgi->gtid_info(),
|
||||||
ER_THD(thd, ER_SLAVE_CANT_CREATE_CONVERSION),
|
ER_THD(thd, ER_SLAVE_CANT_CREATE_CONVERSION),
|
||||||
target_table->s->db.str,
|
target_table->s->db.str,
|
||||||
target_table->s->table_name.str);
|
target_table->s->table_name.str);
|
||||||
}
|
DBUG_RETURN(NULL);
|
||||||
DBUG_RETURN(conv_table);
|
|
||||||
}
|
}
|
||||||
#endif /* MYSQL_CLIENT */
|
#endif /* MYSQL_CLIENT */
|
||||||
|
|
||||||
|
@ -16016,9 +16016,9 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
|||||||
a tmp_set bitmap to be used by things like filesort.
|
a tmp_set bitmap to be used by things like filesort.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
|
void
|
||||||
|
setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps, uint field_count)
|
||||||
{
|
{
|
||||||
uint field_count= table->s->fields;
|
|
||||||
uint bitmap_size= bitmap_buffer_size(field_count);
|
uint bitmap_size= bitmap_buffer_size(field_count);
|
||||||
|
|
||||||
DBUG_ASSERT(table->s->vfields == 0 && table->def_vcol_set == 0);
|
DBUG_ASSERT(table->s->vfields == 0 && table->def_vcol_set == 0);
|
||||||
@ -16042,6 +16042,13 @@ void setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void
|
||||||
|
setup_tmp_table_column_bitmaps(TABLE *table, uchar *bitmaps)
|
||||||
|
{
|
||||||
|
setup_tmp_table_column_bitmaps(table, bitmaps, table->s->fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
Create a temp table according to a field list.
|
Create a temp table according to a field list.
|
||||||
|
|
||||||
@ -16926,105 +16933,59 @@ err:
|
|||||||
|
|
||||||
/****************************************************************************/
|
/****************************************************************************/
|
||||||
|
|
||||||
/**
|
void *Virtual_tmp_table::operator new(size_t size, THD *thd) throw()
|
||||||
Create a reduced TABLE object with properly set up Field list from a
|
{
|
||||||
list of field definitions.
|
return (Virtual_tmp_table *) alloc_root(thd->mem_root, size);
|
||||||
|
}
|
||||||
The created table doesn't have a table handler associated with
|
|
||||||
it, has no keys, no group/distinct, no copy_funcs array.
|
|
||||||
The sole purpose of this TABLE object is to use the power of Field
|
bool Virtual_tmp_table::init(uint field_count)
|
||||||
class to read/write data to/from table->record[0]. Then one can store
|
|
||||||
the record in any container (RB tree, hash, etc).
|
|
||||||
The table is created in THD mem_root, so are the table's fields.
|
|
||||||
Consequently, if you don't BLOB fields, you don't need to free it.
|
|
||||||
|
|
||||||
@param thd connection handle
|
|
||||||
@param field_list list of column definitions
|
|
||||||
|
|
||||||
@return
|
|
||||||
0 if out of memory, TABLE object in case of success
|
|
||||||
*/
|
|
||||||
|
|
||||||
TABLE *create_virtual_tmp_table(THD *thd, List<Column_definition> &field_list)
|
|
||||||
{
|
{
|
||||||
uint field_count= field_list.elements;
|
|
||||||
uint blob_count= 0;
|
|
||||||
Field **field;
|
|
||||||
Column_definition *cdef; /* column definition */
|
|
||||||
uint record_length= 0;
|
|
||||||
uint null_count= 0; /* number of columns which may be null */
|
|
||||||
uint null_pack_length; /* NULL representation array length */
|
|
||||||
uint *blob_field;
|
uint *blob_field;
|
||||||
uchar *bitmaps;
|
uchar *bitmaps;
|
||||||
TABLE *table;
|
if (!multi_alloc_root(in_use->mem_root,
|
||||||
TABLE_SHARE *share;
|
&s, sizeof(*s),
|
||||||
|
|
||||||
if (!multi_alloc_root(thd->mem_root,
|
|
||||||
&table, sizeof(*table),
|
|
||||||
&share, sizeof(*share),
|
|
||||||
&field, (field_count + 1) * sizeof(Field*),
|
&field, (field_count + 1) * sizeof(Field*),
|
||||||
&blob_field, (field_count + 1) * sizeof(uint),
|
&blob_field, (field_count + 1) * sizeof(uint),
|
||||||
&bitmaps, bitmap_buffer_size(field_count) * 5,
|
&bitmaps, bitmap_buffer_size(field_count) * 5,
|
||||||
NullS))
|
NullS))
|
||||||
return 0;
|
return true;
|
||||||
|
bzero(s, sizeof(*s));
|
||||||
|
s->blob_field= blob_field;
|
||||||
|
setup_tmp_table_column_bitmaps(this, bitmaps, field_count);
|
||||||
|
m_alloced_field_count= field_count;
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
bzero(table, sizeof(*table));
|
|
||||||
bzero(share, sizeof(*share));
|
|
||||||
table->field= field;
|
|
||||||
table->s= share;
|
|
||||||
table->temp_pool_slot= MY_BIT_NONE;
|
|
||||||
share->blob_field= blob_field;
|
|
||||||
share->fields= field_count;
|
|
||||||
setup_tmp_table_column_bitmaps(table, bitmaps);
|
|
||||||
|
|
||||||
/* Create all fields and calculate the total length of record */
|
bool Virtual_tmp_table::add(List<Column_definition> &field_list)
|
||||||
List_iterator_fast<Column_definition> it(field_list);
|
|
||||||
while ((cdef= it++))
|
|
||||||
{
|
{
|
||||||
*field= cdef->make_field(share, thd->mem_root, 0,
|
/* Create all fields and calculate the total length of record */
|
||||||
|
Column_definition *cdef; /* column definition */
|
||||||
|
List_iterator_fast<Column_definition> it(field_list);
|
||||||
|
for ( ; (cdef= it++); )
|
||||||
|
{
|
||||||
|
Field *tmp;
|
||||||
|
if (!(tmp= cdef->make_field(s, in_use->mem_root, 0,
|
||||||
(uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
|
(uchar*) (f_maybe_null(cdef->pack_flag) ? "" : 0),
|
||||||
f_maybe_null(cdef->pack_flag) ? 1 : 0,
|
f_maybe_null(cdef->pack_flag) ? 1 : 0,
|
||||||
cdef->field_name);
|
cdef->field_name)))
|
||||||
if (!*field)
|
return true;
|
||||||
goto error;
|
add(tmp);
|
||||||
(*field)->init(table);
|
|
||||||
record_length+= (*field)->pack_length();
|
|
||||||
if (! ((*field)->flags & NOT_NULL_FLAG))
|
|
||||||
null_count++;
|
|
||||||
|
|
||||||
if ((*field)->flags & BLOB_FLAG)
|
|
||||||
share->blob_field[blob_count++]= (uint) (field - table->field);
|
|
||||||
|
|
||||||
field++;
|
|
||||||
}
|
}
|
||||||
*field= NULL; /* mark the end of the list */
|
return false;
|
||||||
share->blob_field[blob_count]= 0; /* mark the end of the list */
|
|
||||||
share->blob_fields= blob_count;
|
|
||||||
|
|
||||||
null_pack_length= (null_count + 7)/8;
|
|
||||||
share->reclength= record_length + null_pack_length;
|
|
||||||
share->rec_buff_length= ALIGN_SIZE(share->reclength + 1);
|
|
||||||
table->record[0]= (uchar*) thd->alloc(share->rec_buff_length);
|
|
||||||
if (!table->record[0])
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
if (null_pack_length)
|
|
||||||
{
|
|
||||||
table->null_flags= (uchar*) table->record[0];
|
|
||||||
share->null_fields= null_count;
|
|
||||||
share->null_bytes= share->null_bytes_for_compare= null_pack_length;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
table->in_use= thd; /* field->reset() may access table->in_use */
|
|
||||||
|
void Virtual_tmp_table::setup_field_pointers()
|
||||||
{
|
{
|
||||||
/* Set up field pointers */
|
uchar *null_pos= record[0];
|
||||||
uchar *null_pos= table->record[0];
|
uchar *field_pos= null_pos + s->null_bytes;
|
||||||
uchar *field_pos= null_pos + share->null_bytes;
|
|
||||||
uint null_bit= 1;
|
uint null_bit= 1;
|
||||||
|
|
||||||
for (field= table->field; *field; ++field)
|
for (Field **cur_ptr= field; *cur_ptr; ++cur_ptr)
|
||||||
{
|
{
|
||||||
Field *cur_field= *field;
|
Field *cur_field= *cur_ptr;
|
||||||
if ((cur_field->flags & NOT_NULL_FLAG))
|
if ((cur_field->flags & NOT_NULL_FLAG))
|
||||||
cur_field->move_field(field_pos);
|
cur_field->move_field(field_pos);
|
||||||
else
|
else
|
||||||
@ -17050,15 +17011,30 @@ TABLE *create_virtual_tmp_table(THD *thd, List<Column_definition> &field_list)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cur_field->reset();
|
cur_field->reset();
|
||||||
|
|
||||||
field_pos+= cur_field->pack_length();
|
field_pos+= cur_field->pack_length();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return table;
|
|
||||||
error:
|
|
||||||
for (field= table->field; *field; ++field)
|
bool Virtual_tmp_table::open()
|
||||||
delete *field; /* just invokes field destructor */
|
{
|
||||||
return 0;
|
// Make sure that we added all the fields we planned to:
|
||||||
|
DBUG_ASSERT(s->fields == m_alloced_field_count);
|
||||||
|
field[s->fields]= NULL; // mark the end of the list
|
||||||
|
s->blob_field[s->blob_fields]= 0; // mark the end of the list
|
||||||
|
|
||||||
|
uint null_pack_length= (s->null_fields + 7) / 8; // NULL-bit array length
|
||||||
|
s->reclength+= null_pack_length;
|
||||||
|
s->rec_buff_length= ALIGN_SIZE(s->reclength + 1);
|
||||||
|
if (!(record[0]= (uchar*) in_use->alloc(s->rec_buff_length)))
|
||||||
|
return true;
|
||||||
|
if (null_pack_length)
|
||||||
|
{
|
||||||
|
null_flags= (uchar*) record[0];
|
||||||
|
s->null_bytes= s->null_bytes_for_compare= null_pack_length;
|
||||||
|
}
|
||||||
|
setup_field_pointers();
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
175
sql/sql_select.h
175
sql/sql_select.h
@ -1861,7 +1861,180 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
|
|||||||
All methods presume that there is at least one field to change.
|
All methods presume that there is at least one field to change.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
TABLE *create_virtual_tmp_table(THD *thd, List<Column_definition> &field_list);
|
|
||||||
|
class Virtual_tmp_table: public TABLE
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
Destruct collected fields. This method is called on errors only,
|
||||||
|
when we could not make the virtual temporary table completely,
|
||||||
|
e.g. when some of the fields could not be created or added.
|
||||||
|
|
||||||
|
This is needed to avoid memory leaks, as some fields can be BLOB
|
||||||
|
variants and thus can have String onboard. Strings must be destructed
|
||||||
|
as they store data not the heap (not on MEM_ROOT).
|
||||||
|
*/
|
||||||
|
void destruct_fields()
|
||||||
|
{
|
||||||
|
for (uint i= 0; i < s->fields; i++)
|
||||||
|
delete field[i]; // to invoke the field destructor
|
||||||
|
s->fields= 0; // safety
|
||||||
|
}
|
||||||
|
|
||||||
|
protected:
|
||||||
|
/**
|
||||||
|
The number of the fields that are going to be in the table.
|
||||||
|
We remember the number of the fields at init() time, and
|
||||||
|
at open() we check that all of the fields were really added.
|
||||||
|
*/
|
||||||
|
uint m_alloced_field_count;
|
||||||
|
|
||||||
|
/**
|
||||||
|
Setup field pointers and null-bit pointers.
|
||||||
|
*/
|
||||||
|
void setup_field_pointers();
|
||||||
|
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
Create a new empty virtual temporary table on the thread mem_root.
|
||||||
|
After creation, the caller must:
|
||||||
|
- call init()
|
||||||
|
- populate the table with new fields using add().
|
||||||
|
- call open().
|
||||||
|
@param thd - Current thread.
|
||||||
|
*/
|
||||||
|
static void *operator new(size_t size, THD *thd) throw();
|
||||||
|
|
||||||
|
Virtual_tmp_table(THD *thd)
|
||||||
|
{
|
||||||
|
bzero(this, sizeof(*this));
|
||||||
|
temp_pool_slot= MY_BIT_NONE;
|
||||||
|
in_use= thd;
|
||||||
|
}
|
||||||
|
|
||||||
|
~Virtual_tmp_table()
|
||||||
|
{
|
||||||
|
destruct_fields();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Allocate components for the given number of fields.
|
||||||
|
- fields[]
|
||||||
|
- s->blob_fields[],
|
||||||
|
- bitmaps: def_read_set, def_write_set, tmp_set, eq_join_set, cond_set.
|
||||||
|
@param field_count - The number of fields we plan to add to the table.
|
||||||
|
@returns false - on success.
|
||||||
|
@returns true - on error.
|
||||||
|
*/
|
||||||
|
bool init(uint field_count);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add one Field to the end of the field array, update members:
|
||||||
|
s->reclength, s->fields, s->blob_fields, s->null_fuelds.
|
||||||
|
*/
|
||||||
|
bool add(Field *new_field)
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(s->fields < m_alloced_field_count);
|
||||||
|
new_field->init(this);
|
||||||
|
field[s->fields]= new_field;
|
||||||
|
s->reclength+= new_field->pack_length();
|
||||||
|
if (!(new_field->flags & NOT_NULL_FLAG))
|
||||||
|
s->null_fields++;
|
||||||
|
if (new_field->flags & BLOB_FLAG)
|
||||||
|
{
|
||||||
|
// Note, s->blob_fields was incremented in Field_blob::Field_blob
|
||||||
|
DBUG_ASSERT(s->blob_fields);
|
||||||
|
DBUG_ASSERT(s->blob_fields <= m_alloced_field_count);
|
||||||
|
s->blob_field[s->blob_fields - 1]= s->fields;
|
||||||
|
}
|
||||||
|
s->fields++;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
Add fields from a Column_definition list
|
||||||
|
@returns false - on success.
|
||||||
|
@returns true - on error.
|
||||||
|
*/
|
||||||
|
bool add(List<Column_definition> &field_list);
|
||||||
|
|
||||||
|
/**
|
||||||
|
Open a virtual table for read/write:
|
||||||
|
- Setup end markers in TABLE::field and TABLE_SHARE::blob_fields,
|
||||||
|
- Allocate a buffer in TABLE::record[0].
|
||||||
|
- Set field pointers (Field::ptr, Field::null_pos, Field::null_bit) to
|
||||||
|
the allocated record.
|
||||||
|
This method is called when all of the fields have been added to the table.
|
||||||
|
After calling this method the table is ready for read and write operations.
|
||||||
|
@return false - on success
|
||||||
|
@return true - on error (e.g. could not allocate the record buffer).
|
||||||
|
*/
|
||||||
|
bool open();
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a reduced TABLE object with properly set up Field list from a
|
||||||
|
list of field definitions.
|
||||||
|
|
||||||
|
The created table doesn't have a table handler associated with
|
||||||
|
it, has no keys, no group/distinct, no copy_funcs array.
|
||||||
|
The sole purpose of this TABLE object is to use the power of Field
|
||||||
|
class to read/write data to/from table->record[0]. Then one can store
|
||||||
|
the record in any container (RB tree, hash, etc).
|
||||||
|
The table is created in THD mem_root, so are the table's fields.
|
||||||
|
Consequently, if you don't BLOB fields, you don't need to free it.
|
||||||
|
|
||||||
|
@param thd connection handle
|
||||||
|
@param field_list list of column definitions
|
||||||
|
|
||||||
|
@return
|
||||||
|
0 if out of memory, or a
|
||||||
|
TABLE object ready for read and write in case of success
|
||||||
|
*/
|
||||||
|
|
||||||
|
inline TABLE *
|
||||||
|
create_virtual_tmp_table(THD *thd, List<Column_definition> &field_list)
|
||||||
|
{
|
||||||
|
Virtual_tmp_table *table;
|
||||||
|
if (!(table= new(thd) Virtual_tmp_table(thd)))
|
||||||
|
return NULL;
|
||||||
|
if (table->init(field_list.elements) ||
|
||||||
|
table->add(field_list) ||
|
||||||
|
table->open())
|
||||||
|
{
|
||||||
|
delete table;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a new virtual temporary table consisting of a single field.
|
||||||
|
SUM(DISTINCT expr) and similar numeric aggregate functions use this.
|
||||||
|
@param thd - Current thread
|
||||||
|
@param field - The field that will be added into the table.
|
||||||
|
@return NULL - On error.
|
||||||
|
@return !NULL - A pointer to the created table that is ready
|
||||||
|
for read and write.
|
||||||
|
*/
|
||||||
|
inline TABLE *
|
||||||
|
create_virtual_tmp_table(THD *thd, Field *field)
|
||||||
|
{
|
||||||
|
Virtual_tmp_table *table;
|
||||||
|
DBUG_ASSERT(field);
|
||||||
|
if (!(table= new(thd) Virtual_tmp_table(thd)))
|
||||||
|
return NULL;
|
||||||
|
if (table->init(1) ||
|
||||||
|
table->add(field) ||
|
||||||
|
table->open())
|
||||||
|
{
|
||||||
|
delete table;
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
return table;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int test_if_item_cache_changed(List<Cached_item> &list);
|
int test_if_item_cache_changed(List<Cached_item> &list);
|
||||||
int join_init_read_record(JOIN_TAB *tab);
|
int join_init_read_record(JOIN_TAB *tab);
|
||||||
|
424
sql/sql_type.cc
424
sql/sql_type.cc
@ -16,6 +16,9 @@
|
|||||||
|
|
||||||
#include "sql_type.h"
|
#include "sql_type.h"
|
||||||
#include "sql_const.h"
|
#include "sql_const.h"
|
||||||
|
#include "sql_class.h"
|
||||||
|
#include "item.h"
|
||||||
|
#include "log.h"
|
||||||
|
|
||||||
static Type_handler_tiny type_handler_tiny;
|
static Type_handler_tiny type_handler_tiny;
|
||||||
static Type_handler_short type_handler_short;
|
static Type_handler_short type_handler_short;
|
||||||
@ -220,3 +223,424 @@ Type_handler::get_handler_by_real_type(enum_field_types type)
|
|||||||
return &type_handler_string;
|
return &type_handler_string;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
Create a DOUBLE field by default.
|
||||||
|
*/
|
||||||
|
Field *
|
||||||
|
Type_handler::make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
|
||||||
|
const Item *item) const
|
||||||
|
{
|
||||||
|
return new(mem_root)
|
||||||
|
Field_double(NULL, item->max_length,
|
||||||
|
(uchar *) (item->maybe_null ? "" : 0),
|
||||||
|
item->maybe_null ? 1 : 0, Field::NONE,
|
||||||
|
item->name, item->decimals, 0, item->unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *
|
||||||
|
Type_handler_float::make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
|
||||||
|
const Item *item)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(mem_root)
|
||||||
|
Field_float(NULL, item->max_length,
|
||||||
|
(uchar *) (item->maybe_null ? "" : 0),
|
||||||
|
item->maybe_null ? 1 : 0, Field::NONE,
|
||||||
|
item->name, item->decimals, 0, item->unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *
|
||||||
|
Type_handler_decimal_result::make_num_distinct_aggregator_field(
|
||||||
|
MEM_ROOT *mem_root,
|
||||||
|
const Item *item)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(item->decimals <= DECIMAL_MAX_SCALE);
|
||||||
|
return new (mem_root)
|
||||||
|
Field_new_decimal(NULL, item->max_length,
|
||||||
|
(uchar *) (item->maybe_null ? "" : 0),
|
||||||
|
item->maybe_null ? 1 : 0, Field::NONE,
|
||||||
|
item->name, item->decimals, 0, item->unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *
|
||||||
|
Type_handler_int_result::make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
|
||||||
|
const Item *item)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
Make a longlong field for all INT-alike types. It could create
|
||||||
|
smaller fields for TINYINT, SMALLINT, MEDIUMINT, INT though.
|
||||||
|
*/
|
||||||
|
return new(mem_root)
|
||||||
|
Field_longlong(NULL, item->max_length,
|
||||||
|
(uchar *) (item->maybe_null ? "" : 0),
|
||||||
|
item->maybe_null ? 1 : 0, Field::NONE,
|
||||||
|
item->name, 0, item->unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/***********************************************************************/
|
||||||
|
|
||||||
|
#define TMPNAME ""
|
||||||
|
|
||||||
|
Field *Type_handler_tiny::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
As we don't know if the integer was signed or not on the master,
|
||||||
|
assume we have same sign on master and slave. This is true when not
|
||||||
|
using conversions so it should be true also when using conversions.
|
||||||
|
*/
|
||||||
|
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
|
||||||
|
return new (table->in_use->mem_root)
|
||||||
|
Field_tiny(NULL, 4 /*max_length*/, (uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, 0/*zerofill*/, unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_short::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
|
||||||
|
return new (table->in_use->mem_root)
|
||||||
|
Field_short(NULL, 6 /*max_length*/, (uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, 0/*zerofill*/, unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_int24::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
|
||||||
|
return new (table->in_use->mem_root)
|
||||||
|
Field_medium(NULL, 9 /*max_length*/, (uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, 0/*zerofill*/, unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_long::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
|
||||||
|
return new (table->in_use->mem_root)
|
||||||
|
Field_long(NULL, 11 /*max_length*/, (uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, 0/*zerofill*/, unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_longlong::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
bool unsigned_flag= ((Field_num*) target)->unsigned_flag;
|
||||||
|
return new (table->in_use->mem_root)
|
||||||
|
Field_longlong(NULL, 20 /*max_length*/,(uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, 0/*zerofill*/, unsigned_flag);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_float::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new (table->in_use->mem_root)
|
||||||
|
Field_float(NULL, 12 /*max_length*/, (uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, 0/*dec*/, 0/*zerofill*/, 0/*unsigned_flag*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_double::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new (table->in_use->mem_root)
|
||||||
|
Field_double(NULL, 22 /*max_length*/, (uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, 0/*dec*/, 0/*zerofill*/, 0/*unsigned_flag*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_newdecimal::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
int precision= metadata >> 8;
|
||||||
|
uint decimals= metadata & 0x00ff;
|
||||||
|
uint32 max_length= my_decimal_precision_to_length(precision, decimals, false);
|
||||||
|
DBUG_ASSERT(decimals <= DECIMAL_MAX_SCALE);
|
||||||
|
return new (table->in_use->mem_root)
|
||||||
|
Field_new_decimal(NULL, max_length, (uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, decimals, 0/*zerofill*/, 0/*unsigned*/);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_olddecimal::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
sql_print_error("In RBR mode, Slave received incompatible DECIMAL field "
|
||||||
|
"(old-style decimal field) from Master while creating "
|
||||||
|
"conversion table. Please consider changing datatype on "
|
||||||
|
"Master to new style decimal by executing ALTER command for"
|
||||||
|
" column Name: %s.%s.%s.",
|
||||||
|
target->table->s->db.str,
|
||||||
|
target->table->s->table_name.str,
|
||||||
|
target->field_name);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_year::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_year(NULL, 4, (uchar *) "", 1, Field::NONE, TMPNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_null::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_null(NULL, 0, Field::NONE, TMPNAME, target->charset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_timestamp::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
// We assume TIMESTAMP(0)
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_timestamp(NULL, MAX_DATETIME_WIDTH, (uchar *) "", 1,
|
||||||
|
Field::NONE, TMPNAME, table->s);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_timestamp2::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_timestampf(NULL, (uchar *) "", 1, Field::NONE,
|
||||||
|
TMPNAME, table->s, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_newdate::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_newdate(NULL, (uchar *) "", 1, Field::NONE, TMPNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_date::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_date(NULL, (uchar *) "", 1, Field::NONE, TMPNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_time::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_time(NULL, MAX_TIME_WIDTH, (uchar *) "", 1,
|
||||||
|
Field::NONE, TMPNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_time2::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_timef(NULL, (uchar *) "", 1, Field::NONE, TMPNAME, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_datetime::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_datetime(NULL, MAX_DATETIME_WIDTH, (uchar *) "", 1,
|
||||||
|
Field::NONE, TMPNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_datetime2::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_datetimef(NULL, (uchar *) "", 1,
|
||||||
|
Field::NONE, TMPNAME, metadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_bit::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT((metadata & 0xff) <= 7);
|
||||||
|
uint32 max_length= 8 * (metadata >> 8U) + (metadata & 0x00ff);
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_bit_as_char(NULL, max_length, (uchar *) "", 1,
|
||||||
|
Field::NONE, TMPNAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_string::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
/* This is taken from Field_string::unpack. */
|
||||||
|
uint32 max_length= (((metadata >> 4) & 0x300) ^ 0x300) + (metadata & 0x00ff);
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_string(NULL, max_length, (uchar *) "", 1,
|
||||||
|
Field::NONE, TMPNAME, target->charset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_varchar::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_varstring(NULL, metadata, HA_VARCHAR_PACKLENGTH(metadata),
|
||||||
|
(uchar *) "", 1, Field::NONE, TMPNAME,
|
||||||
|
table->s, target->charset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_tiny_blob::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_blob(NULL, (uchar *) "", 1, Field::NONE, TMPNAME,
|
||||||
|
table->s, 1, target->charset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_blob::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_blob(NULL, (uchar *) "", 1, Field::NONE, TMPNAME,
|
||||||
|
table->s, 2, target->charset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_medium_blob::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_blob(NULL, (uchar *) "", 1, Field::NONE, TMPNAME,
|
||||||
|
table->s, 3, target->charset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_long_blob::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_blob(NULL, (uchar *) "", 1, Field::NONE, TMPNAME,
|
||||||
|
table->s, 4, target->charset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_SPATIAL
|
||||||
|
Field *Type_handler_geometry::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(target->type() == MYSQL_TYPE_GEOMETRY);
|
||||||
|
/*
|
||||||
|
We do not do not update feature_gis statistics here:
|
||||||
|
status_var_increment(target->table->in_use->status_var.feature_gis);
|
||||||
|
as this is only a temporary field.
|
||||||
|
The statistics was already incremented when "target" was created.
|
||||||
|
*/
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_geom(NULL, (uchar *) "", 1, Field::NONE, TMPNAME, table->s, 4,
|
||||||
|
((const Field_geom*) target)->geom_type,
|
||||||
|
((const Field_geom*) target)->srid);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
Field *Type_handler_enum::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(target->type() == MYSQL_TYPE_STRING);
|
||||||
|
DBUG_ASSERT(target->real_type() == MYSQL_TYPE_ENUM);
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_enum(NULL, target->field_length,
|
||||||
|
(uchar *) "", 1, Field::NONE, TMPNAME,
|
||||||
|
metadata & 0x00ff/*pack_length()*/,
|
||||||
|
((const Field_enum*) target)->typelib, target->charset());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Field *Type_handler_set::make_conversion_table_field(TABLE *table,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target)
|
||||||
|
const
|
||||||
|
{
|
||||||
|
DBUG_ASSERT(target->type() == MYSQL_TYPE_STRING);
|
||||||
|
DBUG_ASSERT(target->real_type() == MYSQL_TYPE_SET);
|
||||||
|
return new(table->in_use->mem_root)
|
||||||
|
Field_set(NULL, target->field_length,
|
||||||
|
(uchar *) "", 1, Field::NONE, TMPNAME,
|
||||||
|
metadata & 0x00ff/*pack_length()*/,
|
||||||
|
((const Field_enum*) target)->typelib, target->charset());
|
||||||
|
}
|
||||||
|
114
sql/sql_type.h
114
sql/sql_type.h
@ -23,6 +23,10 @@
|
|||||||
|
|
||||||
#include "mysqld.h"
|
#include "mysqld.h"
|
||||||
|
|
||||||
|
class Field;
|
||||||
|
class Item;
|
||||||
|
struct TABLE;
|
||||||
|
|
||||||
class Type_handler
|
class Type_handler
|
||||||
{
|
{
|
||||||
protected:
|
protected:
|
||||||
@ -39,6 +43,42 @@ public:
|
|||||||
CHARSET_INFO *cs) const
|
CHARSET_INFO *cs) const
|
||||||
{ return this; }
|
{ return this; }
|
||||||
virtual ~Type_handler() {}
|
virtual ~Type_handler() {}
|
||||||
|
/**
|
||||||
|
Makes a temporary table Field to handle numeric aggregate functions,
|
||||||
|
e.g. SUM(DISTINCT expr), AVG(DISTINCT expr), etc.
|
||||||
|
*/
|
||||||
|
virtual Field *make_num_distinct_aggregator_field(MEM_ROOT *,
|
||||||
|
const Item *) const;
|
||||||
|
/**
|
||||||
|
Makes a temporary table Field to handle RBR replication type conversion.
|
||||||
|
@param TABLE - The conversion table the field is going to be added to.
|
||||||
|
It's used to access to table->in_use->mem_root,
|
||||||
|
to create the new field on the table memory root,
|
||||||
|
as well as to increment statistics in table->share
|
||||||
|
(e.g. table->s->blob_count).
|
||||||
|
@param metadata - Metadata from the binary log.
|
||||||
|
@param target - The field in the target table on the slave.
|
||||||
|
|
||||||
|
Note, the data types of "target" and of "this" are not necessarily
|
||||||
|
always the same, in general case it's possible that:
|
||||||
|
this->field_type() != target->field_type()
|
||||||
|
and/or
|
||||||
|
this->real_type( ) != target->real_type()
|
||||||
|
|
||||||
|
This method decodes metadata according to this->real_type()
|
||||||
|
and creates a new field also according to this->real_type().
|
||||||
|
|
||||||
|
In some cases it lurks into "target", to get some extra information, e.g.:
|
||||||
|
- unsigned_flag for numeric fields
|
||||||
|
- charset() for string fields
|
||||||
|
- typelib and field_length for SET and ENUM
|
||||||
|
- geom_type and srid for GEOMETRY
|
||||||
|
This information is not available in the binary log, so
|
||||||
|
we assume that these fields are the same on the master and on the slave.
|
||||||
|
*/
|
||||||
|
virtual Field *make_conversion_table_field(TABLE *TABLE,
|
||||||
|
uint metadata,
|
||||||
|
const Field *target) const= 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -59,6 +99,7 @@ public:
|
|||||||
Item_result result_type() const { return DECIMAL_RESULT; }
|
Item_result result_type() const { return DECIMAL_RESULT; }
|
||||||
Item_result cmp_type() const { return DECIMAL_RESULT; }
|
Item_result cmp_type() const { return DECIMAL_RESULT; }
|
||||||
virtual ~Type_handler_decimal_result() {};
|
virtual ~Type_handler_decimal_result() {};
|
||||||
|
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -68,6 +109,7 @@ public:
|
|||||||
Item_result result_type() const { return INT_RESULT; }
|
Item_result result_type() const { return INT_RESULT; }
|
||||||
Item_result cmp_type() const { return INT_RESULT; }
|
Item_result cmp_type() const { return INT_RESULT; }
|
||||||
virtual ~Type_handler_int_result() {}
|
virtual ~Type_handler_int_result() {}
|
||||||
|
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -117,6 +159,8 @@ class Type_handler_tiny: public Type_handler_int_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_tiny() {}
|
virtual ~Type_handler_tiny() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_TINY; }
|
enum_field_types field_type() const { return MYSQL_TYPE_TINY; }
|
||||||
|
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -125,6 +169,8 @@ class Type_handler_short: public Type_handler_int_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_short() {}
|
virtual ~Type_handler_short() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_SHORT; }
|
enum_field_types field_type() const { return MYSQL_TYPE_SHORT; }
|
||||||
|
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -133,6 +179,8 @@ class Type_handler_long: public Type_handler_int_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_long() {}
|
virtual ~Type_handler_long() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_LONG; }
|
enum_field_types field_type() const { return MYSQL_TYPE_LONG; }
|
||||||
|
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -141,6 +189,8 @@ class Type_handler_longlong: public Type_handler_int_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_longlong() {}
|
virtual ~Type_handler_longlong() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
|
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
|
||||||
|
Field *make_conversion_table_field(TABLE *TABLE, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -149,6 +199,8 @@ class Type_handler_int24: public Type_handler_int_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_int24() {}
|
virtual ~Type_handler_int24() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_INT24; }
|
enum_field_types field_type() const { return MYSQL_TYPE_INT24; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -157,6 +209,8 @@ class Type_handler_year: public Type_handler_int_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_year() {}
|
virtual ~Type_handler_year() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_YEAR; }
|
enum_field_types field_type() const { return MYSQL_TYPE_YEAR; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -165,6 +219,8 @@ class Type_handler_bit: public Type_handler_int_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_bit() {}
|
virtual ~Type_handler_bit() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_BIT; }
|
enum_field_types field_type() const { return MYSQL_TYPE_BIT; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -173,6 +229,9 @@ class Type_handler_float: public Type_handler_real_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_float() {}
|
virtual ~Type_handler_float() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; }
|
enum_field_types field_type() const { return MYSQL_TYPE_FLOAT; }
|
||||||
|
Field *make_num_distinct_aggregator_field(MEM_ROOT *, const Item *) const;
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -181,6 +240,8 @@ class Type_handler_double: public Type_handler_real_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_double() {}
|
virtual ~Type_handler_double() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
|
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -189,6 +250,8 @@ class Type_handler_time: public Type_handler_temporal_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_time() {}
|
virtual ~Type_handler_time() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
|
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -198,6 +261,8 @@ public:
|
|||||||
virtual ~Type_handler_time2() {}
|
virtual ~Type_handler_time2() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
|
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
|
||||||
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
|
enum_field_types real_field_type() const { return MYSQL_TYPE_TIME2; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -206,6 +271,8 @@ class Type_handler_date: public Type_handler_temporal_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_date() {}
|
virtual ~Type_handler_date() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -214,7 +281,8 @@ class Type_handler_newdate: public Type_handler_temporal_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_newdate() {}
|
virtual ~Type_handler_newdate() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
|
||||||
enum_field_types real_field_type() const { return MYSQL_TYPE_NEWDATE; }
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -223,6 +291,8 @@ class Type_handler_datetime: public Type_handler_temporal_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_datetime() {}
|
virtual ~Type_handler_datetime() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
|
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -232,6 +302,8 @@ public:
|
|||||||
virtual ~Type_handler_datetime2() {}
|
virtual ~Type_handler_datetime2() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
|
enum_field_types field_type() const { return MYSQL_TYPE_DATETIME; }
|
||||||
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
|
enum_field_types real_field_type() const { return MYSQL_TYPE_DATETIME2; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -240,6 +312,8 @@ class Type_handler_timestamp: public Type_handler_temporal_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_timestamp() {}
|
virtual ~Type_handler_timestamp() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -249,6 +323,8 @@ public:
|
|||||||
virtual ~Type_handler_timestamp2() {}
|
virtual ~Type_handler_timestamp2() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
enum_field_types field_type() const { return MYSQL_TYPE_TIMESTAMP; }
|
||||||
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
|
enum_field_types real_field_type() const { return MYSQL_TYPE_TIMESTAMP2; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -257,6 +333,8 @@ class Type_handler_olddecimal: public Type_handler_decimal_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_olddecimal() {}
|
virtual ~Type_handler_olddecimal() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
|
enum_field_types field_type() const { return MYSQL_TYPE_DECIMAL; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -265,6 +343,8 @@ class Type_handler_newdecimal: public Type_handler_decimal_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_newdecimal() {}
|
virtual ~Type_handler_newdecimal() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
|
enum_field_types field_type() const { return MYSQL_TYPE_NEWDECIMAL; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -273,6 +353,8 @@ class Type_handler_null: public Type_handler_string_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_null() {}
|
virtual ~Type_handler_null() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
|
enum_field_types field_type() const { return MYSQL_TYPE_NULL; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -281,6 +363,8 @@ class Type_handler_string: public Type_handler_string_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_string() {}
|
virtual ~Type_handler_string() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -289,6 +373,8 @@ class Type_handler_varchar: public Type_handler_string_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_varchar() {}
|
virtual ~Type_handler_varchar() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -297,6 +383,8 @@ class Type_handler_tiny_blob: public Type_handler_string_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_tiny_blob() {}
|
virtual ~Type_handler_tiny_blob() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; }
|
enum_field_types field_type() const { return MYSQL_TYPE_TINY_BLOB; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -305,6 +393,8 @@ class Type_handler_medium_blob: public Type_handler_string_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_medium_blob() {}
|
virtual ~Type_handler_medium_blob() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
|
enum_field_types field_type() const { return MYSQL_TYPE_MEDIUM_BLOB; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -313,6 +403,8 @@ class Type_handler_long_blob: public Type_handler_string_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_long_blob() {}
|
virtual ~Type_handler_long_blob() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
|
enum_field_types field_type() const { return MYSQL_TYPE_LONG_BLOB; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -321,15 +413,21 @@ class Type_handler_blob: public Type_handler_string_result
|
|||||||
public:
|
public:
|
||||||
virtual ~Type_handler_blob() {}
|
virtual ~Type_handler_blob() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
|
enum_field_types field_type() const { return MYSQL_TYPE_BLOB; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef HAVE_SPATIAL
|
||||||
class Type_handler_geometry: public Type_handler_string_result
|
class Type_handler_geometry: public Type_handler_string_result
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
virtual ~Type_handler_geometry() {}
|
virtual ~Type_handler_geometry() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
|
enum_field_types field_type() const { return MYSQL_TYPE_GEOMETRY; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
class Type_handler_enum: public Type_handler_string_result
|
class Type_handler_enum: public Type_handler_string_result
|
||||||
@ -338,6 +436,8 @@ public:
|
|||||||
virtual ~Type_handler_enum() {}
|
virtual ~Type_handler_enum() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
||||||
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
|
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_ENUM; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -347,6 +447,8 @@ public:
|
|||||||
virtual ~Type_handler_set() {}
|
virtual ~Type_handler_set() {}
|
||||||
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
|
||||||
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
|
virtual enum_field_types real_field_type() const { return MYSQL_TYPE_SET; }
|
||||||
|
Field *make_conversion_table_field(TABLE *, uint metadata,
|
||||||
|
const Field *target) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -414,6 +516,16 @@ public:
|
|||||||
m_type_handler->type_handler_adjusted_to_max_octet_length(max_octet_length,
|
m_type_handler->type_handler_adjusted_to_max_octet_length(max_octet_length,
|
||||||
cs);
|
cs);
|
||||||
}
|
}
|
||||||
|
Field *make_num_distinct_aggregator_field(MEM_ROOT *mem_root,
|
||||||
|
const Item *item) const
|
||||||
|
{
|
||||||
|
return m_type_handler->make_num_distinct_aggregator_field(mem_root, item);
|
||||||
|
}
|
||||||
|
Field *make_conversion_table_field(TABLE *table, uint metadata,
|
||||||
|
const Field *target) const
|
||||||
|
{
|
||||||
|
return m_type_handler->make_conversion_table_field(table, metadata, target);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user