Commit 98260750 authored by unknown's avatar unknown

MDEV-4309: DBT-3 Q1 benchmark: Benchmark + profile a patch

Removed repetative calls of virtual functions.
Removed check of posibility just copy field for every record.
parent 9d918f41
......@@ -75,6 +75,8 @@ struct ha_field_option_struct;
struct st_cache_field;
int field_conv(Field *to,Field *from);
int field_conv_incompatible(Field *to,Field *from);
bool memcpy_field_possible(Field *to, Field *from);
int truncate_double(double *nr, uint field_length, uint dec,
bool unsigned_flag, double max_value);
longlong double_to_longlong(double nr, bool unsigned_flag, bool *error);
......@@ -2463,7 +2465,7 @@ public:
uint max_packed_col_length(uint max_length);
void free() { value.free(); }
inline void clear_temporary() { bzero((uchar*) &value,sizeof(value)); }
friend int field_conv(Field *to,Field *from);
friend int field_conv_incompatible(Field *to,Field *from);
uint size_of() const { return sizeof(*this); }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
......
......@@ -823,40 +823,76 @@ Copy_field::get_copy_func(Field *to,Field *from)
return do_field_eq;
}
/**
Check if it is possible just copy value of the fields
@param to The field to copy to
@param from The field to copy from
@retval TRUE - it is possible to just copy value of 'from' to 'to'.
@retval FALSE - conversion is needed
*/
bool memcpy_field_possible(Field *to,Field *from)
{
const enum_field_types to_real_type= to->real_type();
const enum_field_types from_real_type= from->real_type();
const enum_field_types to_type= from->type();
return (to_real_type == from_real_type &&
!(to->flags & BLOB_FLAG && to->table->copy_blobs) &&
to->pack_length() == from->pack_length() &&
!(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) &&
to->decimals() == from->decimals() &&
to_real_type != MYSQL_TYPE_ENUM &&
to_real_type != MYSQL_TYPE_SET &&
to_real_type != MYSQL_TYPE_BIT &&
(to_real_type != MYSQL_TYPE_NEWDECIMAL ||
to->field_length == from->field_length) &&
from->charset() == to->charset() &&
(!sql_mode_for_dates(to->table->in_use) ||
(to_type != MYSQL_TYPE_DATE &&
to_type != MYSQL_TYPE_DATETIME)) &&
(from_real_type != MYSQL_TYPE_VARCHAR ||
((Field_varstring*)from)->length_bytes ==
((Field_varstring*)to)->length_bytes));
}
/** Simple quick field convert that is called on insert. */
int field_conv(Field *to,Field *from)
{
if (to->real_type() == from->real_type() &&
!(to->flags & BLOB_FLAG && to->table->copy_blobs))
{
if (to->pack_length() == from->pack_length() &&
!(to->flags & UNSIGNED_FLAG && !(from->flags & UNSIGNED_FLAG)) &&
to->decimals() == from->decimals() &&
to->real_type() != MYSQL_TYPE_ENUM &&
to->real_type() != MYSQL_TYPE_SET &&
to->real_type() != MYSQL_TYPE_BIT &&
(to->real_type() != MYSQL_TYPE_NEWDECIMAL ||
to->field_length == from->field_length) &&
from->charset() == to->charset() &&
(!sql_mode_for_dates(to->table->in_use) ||
(to->type() != MYSQL_TYPE_DATE &&
to->type() != MYSQL_TYPE_DATETIME)) &&
(from->real_type() != MYSQL_TYPE_VARCHAR ||
((Field_varstring*)from)->length_bytes ==
((Field_varstring*)to)->length_bytes))
{ // Identical fields
/*
This may happen if one does 'UPDATE ... SET x=x'
The test is here mostly for valgrind, but can also be relevant
if memcpy() is implemented with prefetch-write
*/
if (to->ptr != from->ptr)
memcpy(to->ptr,from->ptr,to->pack_length());
return 0;
}
if (memcpy_field_possible(to, from))
{ // Identical fields
/*
This may happen if one does 'UPDATE ... SET x=x'
The test is here mostly for valgrind, but can also be relevant
if memcpy() is implemented with prefetch-write
*/
if (to->ptr != from->ptr)
memcpy(to->ptr, from->ptr, to->pack_length());
return 0;
}
return field_conv_incompatible(to, from);
}
/**
Copy value of the field with conversion.
@note Impossibility of simple copy should be checked before this call.
@param to The field to copy to
@param from The field to copy from
@retval TRUE ERROR
@retval FALSE OK
*/
int field_conv_incompatible(Field *to, Field *from)
{
const enum_field_types to_real_type= to->real_type();
const enum_field_types from_real_type= from->real_type();
if (to->flags & BLOB_FLAG)
{ // Be sure the value is stored
Field_blob *blob=(Field_blob*) to;
......@@ -867,21 +903,22 @@ int field_conv(Field *to,Field *from)
*/
if (to->table->copy_blobs ||
(!blob->value.is_alloced() &&
from->real_type() != MYSQL_TYPE_STRING &&
from->real_type() != MYSQL_TYPE_VARCHAR))
from_real_type != MYSQL_TYPE_STRING &&
from_real_type != MYSQL_TYPE_VARCHAR))
blob->value.copy();
return blob->store(blob->value.ptr(),blob->value.length(),from->charset());
}
if (from->real_type() == MYSQL_TYPE_ENUM &&
to->real_type() == MYSQL_TYPE_ENUM &&
if (from_real_type == MYSQL_TYPE_ENUM &&
to_real_type == MYSQL_TYPE_ENUM &&
from->val_int() == 0)
{
((Field_enum *)(to))->store_type(0);
return 0;
}
if (from->result_type() == REAL_RESULT)
Item_result from_result_type= from->result_type();
if (from_result_type == REAL_RESULT)
return to->store(from->val_real());
if (from->result_type() == DECIMAL_RESULT)
if (from_result_type == DECIMAL_RESULT)
{
my_decimal buff;
return to->store_decimal(from->val_decimal(&buff));
......@@ -894,10 +931,10 @@ int field_conv(Field *to,Field *from)
else
return to->store_time_dec(&ltime, from->decimals());
}
if ((from->result_type() == STRING_RESULT &&
if ((from_result_type == STRING_RESULT &&
(to->result_type() == STRING_RESULT ||
(from->real_type() != MYSQL_TYPE_ENUM &&
from->real_type() != MYSQL_TYPE_SET))) ||
(from_real_type != MYSQL_TYPE_ENUM &&
from_real_type != MYSQL_TYPE_SET))) ||
to->type() == MYSQL_TYPE_DECIMAL)
{
char buff[MAX_FIELD_WIDTH];
......
......@@ -5903,13 +5903,51 @@ static int save_field_in_field(Field *from, bool *null_value,
}
static int memcpy_field_value(Field *to, Field *from)
{
if (to->ptr != from->ptr)
memcpy(to->ptr,from->ptr, to->pack_length());
return 0;
}
fast_field_copier Item_field::setup_fast_field_copier(Field *to)
{
DBUG_ENTER("Item_field::setup_fast_field_copier");
DBUG_RETURN(memcpy_field_possible(to, field) ?
&memcpy_field_value :
&field_conv_incompatible);
}
/**
Set a field's value from a item.
*/
void Item_field::save_org_in_field(Field *to)
void Item_field::save_org_in_field(Field *to,
fast_field_copier fast_field_copier_func)
{
save_field_in_field(field, &null_value, to, TRUE);
DBUG_ENTER("Item_field::save_org_in_field");
DBUG_PRINT("enter", ("setup: 0x%lx data: 0x%lx",
(ulong) to, (ulong) fast_field_copier_func));
if (fast_field_copier_func)
{
if (field->is_null())
{
null_value= TRUE;
set_field_to_null_with_conversions(to, TRUE);
DBUG_VOID_RETURN;
}
to->set_notnull();
if (to == field)
{
null_value= 0;
DBUG_VOID_RETURN;
}
(*fast_field_copier_func)(to, field);
}
else
save_field_in_field(field, &null_value, to, TRUE);
DBUG_VOID_RETURN;
}
......@@ -7430,9 +7468,9 @@ int Item_ref::save_in_field(Field *to, bool no_conversions)
}
void Item_ref::save_org_in_field(Field *field)
void Item_ref::save_org_in_field(Field *field, fast_field_copier optimizer_data)
{
(*ref)->save_org_in_field(field);
(*ref)->save_org_in_field(field, optimizer_data);
}
......
......@@ -709,8 +709,12 @@ public:
/* Function returns 1 on overflow and -1 on fatal errors */
int save_in_field_no_warnings(Field *field, bool no_conversions);
virtual int save_in_field(Field *field, bool no_conversions);
virtual void save_org_in_field(Field *field)
virtual void save_org_in_field(Field *field,
fast_field_copier data
__attribute__ ((__unused__)))
{ (void) save_in_field(field, 1); }
virtual fast_field_copier setup_fast_field_copier(Field *field)
{ return NULL; }
virtual int save_safe_in_field(Field *field)
{ return save_in_field(field, 1); }
virtual bool send(Protocol *protocol, String *str);
......@@ -946,7 +950,7 @@ public:
save_val() is method of val_* family which stores value in the given
field.
*/
virtual void save_val(Field *to) { save_org_in_field(to); }
virtual void save_val(Field *to) { save_org_in_field(to, NULL); }
/*
save_result() is method of val*result() family which stores value in
the given field.
......@@ -2070,7 +2074,8 @@ public:
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
void make_field(Send_field *tmp_field);
int save_in_field(Field *field,bool no_conversions);
void save_org_in_field(Field *field);
void save_org_in_field(Field *field, fast_field_copier optimizer_data);
fast_field_copier setup_fast_field_copier(Field *field);
table_map used_tables() const;
table_map all_used_tables() const;
enum Item_result result_type () const
......@@ -3099,7 +3104,9 @@ public:
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
int save_in_field(Field *field, bool no_conversions);
void save_org_in_field(Field *field);
void save_org_in_field(Field *field, fast_field_copier optimizer_data);
fast_field_copier setup_fast_field_copier(Field *field)
{ return (*ref)->setup_fast_field_copier(field); }
enum Item_result result_type () const { return (*ref)->result_type(); }
enum_field_types field_type() const { return (*ref)->field_type(); }
Field *get_tmp_table_field()
......@@ -3328,7 +3335,8 @@ public:
bool is_null();
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate);
bool send(Protocol *protocol, String *buffer);
void save_org_in_field(Field *field)
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{
save_val(field);
}
......@@ -3525,7 +3533,8 @@ public:
return Item_direct_ref::get_date(ltime, fuzzydate);
}
bool send(Protocol *protocol, String *buffer);
void save_org_in_field(Field *field)
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{
if (check_null_ref())
field->set_null();
......@@ -3591,7 +3600,7 @@ public:
{}
void save_in_result_field(bool no_conversions)
{
outer_ref->save_org_in_field(result_field);
outer_ref->save_org_in_field(result_field, NULL);
}
bool fix_fields(THD *, Item **);
void fix_after_pullout(st_select_lex *new_parent, Item **ref);
......
......@@ -1740,7 +1740,9 @@ public:
{
return save_in_field(field, no_conversions, 1);
}
void save_org_in_field(Field *field) { (void)save_in_field(field, 1, 0); }
void save_org_in_field(Field *field,
fast_field_copier data __attribute__ ((__unused__)))
{ (void)save_in_field(field, 1, 0); }
bool register_field_in_read_map(uchar *arg);
bool register_field_in_bitmap(uchar *arg);
bool set_entry(THD *thd, bool create_if_not_exists);
......
......@@ -18804,7 +18804,16 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
for (group=table->group ; group ; group=group->next)
{
Item *item= *group->item;
item->save_org_in_field(group->field);
if (group->fast_field_copier_setup != group->field)
{
DBUG_PRINT("info", ("new setup 0x%lx -> 0x%lx",
(ulong)group->fast_field_copier_setup,
(ulong)group->field));
group->fast_field_copier_setup= group->field;
group->fast_field_copier_func=
item->setup_fast_field_copier(group->field);
}
item->save_org_in_field(group->field, group->fast_field_copier_func);
/* Store in the used key if the field was 0 */
if (item->maybe_null)
group->buff[-1]= (char) group->field->is_null();
......
......@@ -194,10 +194,20 @@ private:
/* Order clause list element */
typedef int (*fast_field_copier)(Field *to, Field *from);
typedef struct st_order {
struct st_order *next;
Item **item; /* Point at item in select fields */
Item *item_ptr; /* Storage for initial item */
/*
Reference to the function we are trying to optimize copy to
a temporary table
*/
fast_field_copier fast_field_copier_func;
/* Field for which above optimizer function setup */
Field *fast_field_copier_setup;
int counter; /* position in SELECT list, correct
only if counter_used is true*/
bool asc; /* true if ascending */
......
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