Skip to content

Commit

Permalink
SQL: pruning, derived, view fixes [fixes #244]
Browse files Browse the repository at this point in the history
  • Loading branch information
midenok committed Sep 1, 2017
1 parent c2a70c8 commit 88ccf75
Show file tree
Hide file tree
Showing 14 changed files with 97 additions and 83 deletions.
3 changes: 3 additions & 0 deletions mysql-test/suite/versioning/r/partition.result
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,9 @@ x A B
execute select_pn;
x C D
1 1 1
explain partitions select * from t1;
id select_type table partitions type possible_keys key key_len ref rows Extra
1 SIMPLE t1 pn system NULL NULL NULL NULL 1
set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0');
prepare stmt from @str;
execute stmt;
Expand Down
8 changes: 4 additions & 4 deletions mysql-test/suite/versioning/r/view.result
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ x
create or replace view vt1 as select * from t1;
show create view vt1;
View Create View character_set_client collation_connection
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`x` AS `x`,`t1`.`sys_trx_start` AS `sys_trx_start`,`t1`.`sys_trx_end` AS `sys_trx_end` from `t1` FOR SYSTEM_TIME ALL where `t1`.`sys_trx_end` = TIMESTAMP'2038-01-19 03:14:07.999999' latin1 latin1_swedish_ci
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`x` AS `x`,`t1`.`sys_trx_start` AS `sys_trx_start`,`t1`.`sys_trx_end` AS `sys_trx_end` from `t1` FOR SYSTEM_TIME ALL where `t1`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci
drop view vt1;
drop view vt2;
create view vt1 as select * from t1 for system_time all;
Expand Down Expand Up @@ -178,15 +178,15 @@ create or replace table t3 (x int);
create or replace view vt1 as select * from t1, t2, t3;
show create view vt1;
View Create View character_set_client collation_connection
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`a` AS `a`,`t2`.`b` AS `b`,`t3`.`x` AS `x`,`t1`.`sys_trx_start` AS `sys_trx_start`,`t1`.`sys_trx_end` AS `sys_trx_end` from ((`t1` FOR SYSTEM_TIME ALL join `t2` FOR SYSTEM_TIME ALL) join `t3`) where `t1`.`sys_trx_end` = TIMESTAMP'2038-01-19 03:14:07.999999' and `t2`.`sys_trx_end` = TIMESTAMP'2038-01-19 03:14:07.999999' latin1 latin1_swedish_ci
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`a` AS `a`,`t2`.`b` AS `b`,`t3`.`x` AS `x`,`t1`.`sys_trx_start` AS `sys_trx_start`,`t1`.`sys_trx_end` AS `sys_trx_end` from ((`t1` FOR SYSTEM_TIME ALL join `t2` FOR SYSTEM_TIME ALL) join `t3`) where `t1`.`sys_trx_end` = 18446744073709551615 and `t2`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci
create or replace view vt1 as select * from t3, t2, t1;
show create view vt1;
View Create View character_set_client collation_connection
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t3`.`x` AS `x`,`t2`.`b` AS `b`,`t1`.`a` AS `a`,`t2`.`sys_trx_start` AS `sys_trx_start`,`t2`.`sys_trx_end` AS `sys_trx_end` from ((`t3` join `t2` FOR SYSTEM_TIME ALL) join `t1` FOR SYSTEM_TIME ALL) where `t2`.`sys_trx_end` = TIMESTAMP'2038-01-19 03:14:07.999999' and `t1`.`sys_trx_end` = TIMESTAMP'2038-01-19 03:14:07.999999' latin1 latin1_swedish_ci
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t3`.`x` AS `x`,`t2`.`b` AS `b`,`t1`.`a` AS `a`,`t2`.`sys_trx_start` AS `sys_trx_start`,`t2`.`sys_trx_end` AS `sys_trx_end` from ((`t3` join `t2` FOR SYSTEM_TIME ALL) join `t1` FOR SYSTEM_TIME ALL) where `t2`.`sys_trx_end` = 18446744073709551615 and `t1`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci
create or replace view vt1 as select a, t2.sys_trx_end as endo from t3, t1, t2;
show create view vt1;
View Create View character_set_client collation_connection
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`a` AS `a`,`t2`.`sys_trx_end` AS `endo`,`t2`.`sys_trx_start` AS `sys_trx_start` from ((`t3` join `t1` FOR SYSTEM_TIME ALL) join `t2` FOR SYSTEM_TIME ALL) where `t1`.`sys_trx_end` = TIMESTAMP'2038-01-19 03:14:07.999999' and `t2`.`sys_trx_end` = TIMESTAMP'2038-01-19 03:14:07.999999' latin1 latin1_swedish_ci
vt1 CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `vt1` AS select `t1`.`a` AS `a`,`t2`.`sys_trx_end` AS `endo`,`t2`.`sys_trx_start` AS `sys_trx_start` from ((`t3` join `t1` FOR SYSTEM_TIME ALL) join `t2` FOR SYSTEM_TIME ALL) where `t1`.`sys_trx_end` = 18446744073709551615 and `t2`.`sys_trx_end` = 18446744073709551615 latin1 latin1_swedish_ci
create or replace view vvt1 as select * from t1, t2, vt1;
ERROR HY000: Creating VIEW `vvt1` is prohibited: versioned VIEW `vt1` in query!
drop view vt1, vt12;
Expand Down
4 changes: 4 additions & 0 deletions mysql-test/suite/versioning/t/partition.test
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ prepare select_pn from @str;
execute select_p0;
execute select_pn;

# pruning check
--replace_result ALL system "Using where" ""
explain partitions select * from t1;

set @str= concat('select ', @ts_start, ' from t1 partition (pn) into @ts0');
prepare stmt from @str; execute stmt; drop prepare stmt;

Expand Down
9 changes: 7 additions & 2 deletions sql/field.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1999,7 +1999,7 @@ bool Field_num::get_date(MYSQL_TIME *ltime,ulonglong fuzzydate)
}


bool Field_vers_system::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate, ulonglong trx_id)
bool Field_vers_trx_id::get_date(MYSQL_TIME *ltime, ulonglong fuzzydate, ulonglong trx_id)
{
ASSERT_COLUMN_MARKED_FOR_READ;
DBUG_ASSERT(ltime);
Expand Down Expand Up @@ -10568,7 +10568,7 @@ Field *make_field(TABLE_SHARE *share,
if (flags & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG))
{
return new (mem_root)
Field_vers_system(ptr, field_length, null_pos, null_bit,
Field_vers_trx_id(ptr, field_length, null_pos, null_bit,
unireg_check, field_name,
f_is_zerofill(pack_flag) != 0,
f_is_dec(pack_flag) == 0);
Expand Down Expand Up @@ -10657,6 +10657,11 @@ Field *make_field(TABLE_SHARE *share,
return 0;
}

bool Field_vers_trx_id::test_if_equality_guarantees_uniqueness(const Item* item) const
{
return item->type() == Item::DATE_ITEM;
}


/** Create a field suitable for create of table. */

Expand Down
35 changes: 32 additions & 3 deletions sql/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -1407,6 +1407,11 @@ class Field: public Value_source
return flags & (VERS_SYS_START_FLAG | VERS_SYS_END_FLAG);
}

virtual bool vers_trx_id() const
{
return false;
}

/*
Validate a non-null field value stored in the given record
according to the current thread settings, e.g. sql_mode.
Expand Down Expand Up @@ -2130,11 +2135,11 @@ class Field_longlong :public Field_num {
};


class Field_vers_system :public Field_longlong {
class Field_vers_trx_id :public Field_longlong {
MYSQL_TIME cache;
ulonglong cached;
public:
Field_vers_system(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
Field_vers_trx_id(uchar *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
bool zero_arg, bool unsigned_arg)
Expand All @@ -2143,13 +2148,37 @@ class Field_vers_system :public Field_longlong {
cached(0)
{}
enum_field_types real_type() const { return MYSQL_TYPE_LONGLONG; }
enum_field_types type() const { return MYSQL_TYPE_DATETIME;}
enum_field_types type() const { return MYSQL_TYPE_LONGLONG;}
uint size_of() const { return sizeof(*this); }
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate, ulonglong trx_id);
bool get_date(MYSQL_TIME *ltime, ulonglong fuzzydate)
{
return get_date(ltime, fuzzydate, (ulonglong) val_int());
}
bool test_if_equality_guarantees_uniqueness(const Item *item) const;
bool can_optimize_keypart_ref(const Item_bool_func *cond,
const Item *item) const
{
return true;
}

bool can_optimize_group_min_max(const Item_bool_func *cond,
const Item *const_item) const
{
return true;
}
bool can_optimize_range(const Item_bool_func *cond,
const Item *item,
bool is_eq_func) const
{
return true;
}
/* cmp_type() cannot be TIME_RESULT, because we want to compare this field against
integers. But in all other cases we treat it as TIME_RESULT! */
bool vers_trx_id() const
{
return true;
}
};


Expand Down
10 changes: 8 additions & 2 deletions sql/item.cc
Original file line number Diff line number Diff line change
Expand Up @@ -6328,7 +6328,7 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table,
if (field_flags() & (VERS_SYS_START_FLAG|VERS_SYS_END_FLAG))
{
field= new (mem_root)
Field_vers_system((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
Field_vers_trx_id((uchar*) 0, max_length, null_ptr, 0, Field::NONE,
name, 0, unsigned_flag);
}
else
Expand Down Expand Up @@ -6671,7 +6671,7 @@ int Item_int::save_in_field(Field *field, bool no_conversions)

Item *Item_int::clone_item(THD *thd)
{
return new (thd->mem_root) Item_int(thd, name, value, max_length);
return new (thd->mem_root) Item_int(thd, name, value, max_length, unsigned_flag);
}


Expand Down Expand Up @@ -10775,6 +10775,12 @@ Item *Item_field::vers_optimized_fields_transformer(THD *thd, uchar *)
return this;
}

bool Item_field::vers_trx_id() const
{
DBUG_ASSERT(field);
return field->vers_trx_id();
}

void Item::register_in(THD *thd)
{
next= thd->free_list;
Expand Down
8 changes: 8 additions & 0 deletions sql/item.h
Original file line number Diff line number Diff line change
Expand Up @@ -1337,6 +1337,8 @@ class Item: public Value_source,
{
if (other->cmp_type() == TIME_RESULT)
return other->field_type();
if (vers_trx_id() || other->vers_trx_id())
return MYSQL_TYPE_DATETIME;
DBUG_ASSERT(0); // Two non-temporal data types, we should not get to here
return MYSQL_TYPE_DATETIME;
}
Expand Down Expand Up @@ -1649,6 +1651,8 @@ class Item: public Value_source,

virtual Item *vers_optimized_fields_transformer(THD *thd, uchar *)
{ return this; }
virtual bool vers_trx_id() const
{ return false; }
virtual Item *neg_transformer(THD *thd) { return NULL; }
virtual Item *update_value_transformer(THD *thd, uchar *select_arg)
{ return this; }
Expand Down Expand Up @@ -2751,6 +2755,7 @@ class Item_field :public Item_ident
Item_field *field_for_view_update() { return this; }
int fix_outer_field(THD *thd, Field **field, Item **reference);
virtual Item *vers_optimized_fields_transformer(THD *thd, uchar *);
virtual bool vers_trx_id() const;
virtual Item *update_value_transformer(THD *thd, uchar *select_arg);
Item *derived_field_transformer_for_having(THD *thd, uchar *arg);
Item *derived_field_transformer_for_where(THD *thd, uchar *arg);
Expand Down Expand Up @@ -3188,6 +3193,9 @@ class Item_int :public Item_num
Item_int(THD *thd, const char *str_arg,longlong i,uint length):
Item_num(thd), value(i)
{ max_length=length; name=(char*) str_arg; fixed= 1; }
Item_int(THD *thd, const char *str_arg,longlong i,uint length, bool flag):
Item_num(thd), value(i)
{ max_length=length; name=(char*) str_arg; fixed= 1; unsigned_flag= flag; }
Item_int(THD *thd, const char *str_arg, uint length=64);
enum Type type() const { return INT_ITEM; }
enum Item_result result_type () const { return INT_RESULT; }
Expand Down
58 changes: 4 additions & 54 deletions sql/item_cmpfunc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,9 +127,12 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const char *funcname,
many cases.
*/
set_handler(items[0]->type_handler()->type_handler_for_comparison());
m_vers_trx_id= items[0]->vers_trx_id();
for (uint i= 1 ; i < nitems ; i++)
{
unsigned_count+= items[i]->unsigned_flag;
if (!m_vers_trx_id)
m_vers_trx_id= items[i]->vers_trx_id();
if (aggregate_for_comparison(items[i]->type_handler()->
type_handler_for_comparison()))
{
Expand Down Expand Up @@ -421,7 +424,7 @@ void Item_func::convert_const_compared_to_int_field(THD *thd)
args[field= 1]->real_item()->type() == FIELD_ITEM)
{
Item_field *field_item= (Item_field*) (args[field]->real_item());
if ((field_item->field_type() == MYSQL_TYPE_LONGLONG ||
if (((field_item->field_type() == MYSQL_TYPE_LONGLONG && !field_item->vers_trx_id()) ||
field_item->field_type() == MYSQL_TYPE_YEAR))
convert_const_to_int(thd, field_item, &args[!field]);
}
Expand Down Expand Up @@ -5218,59 +5221,6 @@ bool fix_escape_item(THD *thd, Item *escape_item, String *tmp_str,
return FALSE;
}

bool Item_bool_func2::fix_fields(THD* thd, Item** ref)
{
if (Item_bool_func::fix_fields(thd, ref))
return true;

// System Versioning: convert TRX_ID to DATETIME
Item *trx_id= NULL;
int arg_idx= -1;
Field_vers_system *sys_field= NULL;
DBUG_ASSERT(arg_count == 2);
// find trx_id and sys_field
for (int i= 0; i < 2; ++i)
{
Item *arg= args[i];
if (arg->result_type() != INT_RESULT)
continue;
DBUG_ASSERT(arg);
if (arg->type() == Item::FIELD_ITEM)
{
Field *f= static_cast<Item_field *>(arg)->field;
DBUG_ASSERT(f);
if (f->vers_sys_field() && f->real_type() == MYSQL_TYPE_LONGLONG)
{
if (sys_field)
return false;
sys_field= static_cast<Field_vers_system *>(f);
continue;
}
}
if (trx_id)
return false;
trx_id= arg;
arg_idx= i;
}
if (!trx_id || !sys_field)
return false;
MYSQL_TIME ltime;
ulonglong trx_id_val= (ulonglong) trx_id->val_int();
if (sys_field->get_date(&ltime, false, trx_id_val))
{
my_error(ER_VERS_NO_TRX_ID, MYF(0), trx_id_val);
return true;
}
Query_arena_stmt on_stmt_arena(thd);
Item *datetime= new (thd->mem_root) Item_datetime_literal(thd, &ltime, 6);
if (!datetime)
return true;
DBUG_ASSERT(arg_idx > -1);
args[arg_idx]= datetime;
return false;
}


bool Item_func_like::fix_fields(THD *thd, Item **ref)
{
DBUG_ASSERT(fixed == 0);
Expand Down
1 change: 0 additions & 1 deletion sql/item_cmpfunc.h
Original file line number Diff line number Diff line change
Expand Up @@ -410,7 +410,6 @@ class Item_bool_func2 :public Item_bool_func
ftree= Item_func::get_mm_tree(param, cond_ptr);
DBUG_RETURN(ftree);
}
bool fix_fields(THD *thd, Item **ref);
};


Expand Down
12 changes: 6 additions & 6 deletions sql/sql_select.cc
Original file line number Diff line number Diff line change
Expand Up @@ -918,7 +918,7 @@ int vers_setup_select(THD *thd, TABLE_LIST *tables, COND **where_expr,
switch (vers_conditions.type)
{
case FOR_SYSTEM_TIME_UNSPECIFIED:
if (!tmp_from_ib)
if (t->vers_start_field()->real_type() != MYSQL_TYPE_LONGLONG)
{
MYSQL_TIME max_time;
thd->variables.time_zone->gmt_sec_to_TIME(&max_time, TIMESTAMP_MAX_VALUE);
Expand Down Expand Up @@ -25555,6 +25555,11 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,
}
#endif /* WITH_PARTITION_STORAGE_ENGINE */
}
if (table && table->versioned())
{
// versioning conditions are already unwrapped to WHERE clause
str->append(" FOR SYSTEM_TIME ALL");
}
if (my_strcasecmp(table_alias_charset, cmp_name, alias))
{
char t_alias_buff[MAX_ALIAS_NAME];
Expand All @@ -25573,11 +25578,6 @@ void TABLE_LIST::print(THD *thd, table_map eliminated_tables, String *str,

append_identifier(thd, str, t_alias, strlen(t_alias));
}
if (table && table->versioned())
{
// versioning conditions are already unwrapped to WHERE clause
str->append(" FOR SYSTEM_TIME ALL");
}

if (index_hints)
{
Expand Down
4 changes: 3 additions & 1 deletion sql/sql_type.cc
Original file line number Diff line number Diff line change
Expand Up @@ -428,7 +428,9 @@ Type_handler_hybrid_field_type::aggregate_for_comparison(const Type_handler *h)

Item_result a= cmp_type();
Item_result b= h->cmp_type();
if (a == STRING_RESULT && b == STRING_RESULT)
if (m_vers_trx_id && (a == STRING_RESULT || b == STRING_RESULT))
m_type_handler= &type_handler_datetime;
else if (a == STRING_RESULT && b == STRING_RESULT)
m_type_handler= &type_handler_long_blob;
else if (a == INT_RESULT && b == INT_RESULT)
m_type_handler= &type_handler_longlong;
Expand Down
7 changes: 4 additions & 3 deletions sql/sql_type.h
Original file line number Diff line number Diff line change
Expand Up @@ -1473,16 +1473,17 @@ class Type_handler_set: public Type_handler_string_result
class Type_handler_hybrid_field_type
{
const Type_handler *m_type_handler;
bool m_vers_trx_id;
public:
Type_handler_hybrid_field_type();
Type_handler_hybrid_field_type(const Type_handler *handler)
:m_type_handler(handler)
:m_type_handler(handler), m_vers_trx_id(false)
{ }
Type_handler_hybrid_field_type(enum_field_types type)
:m_type_handler(Type_handler::get_handler_by_field_type(type))
:m_type_handler(Type_handler::get_handler_by_field_type(type)), m_vers_trx_id(false)
{ }
Type_handler_hybrid_field_type(const Type_handler_hybrid_field_type *other)
:m_type_handler(other->m_type_handler)
:m_type_handler(other->m_type_handler), m_vers_trx_id(other->m_vers_trx_id)
{ }
const Type_handler *type_handler() const { return m_type_handler; }
enum_field_types field_type() const { return m_type_handler->field_type(); }
Expand Down
Loading

0 comments on commit 88ccf75

Please sign in to comment.