Vers SQL: Refactoring: better init of vers_conditions

Unit-based history point (vers_history_point_t; Vers_history_point).
This commit is contained in:
Aleksey Midenkov 2018-01-27 13:44:34 +03:00 committed by Sergei Golubchik
parent df0e1817c7
commit e2f70d6e10
4 changed files with 196 additions and 201 deletions

View file

@ -677,53 +677,37 @@ bool vers_select_conds_t::init_from_sysvar(THD *thd)
{
vers_asof_timestamp_t &in= thd->variables.vers_asof_timestamp;
type= (vers_system_time_t) in.type;
unit_start= VERS_TIMESTAMP;
start.unit= VERS_TIMESTAMP;
from_query= false;
if (type != SYSTEM_TIME_UNSPECIFIED && type != SYSTEM_TIME_ALL)
{
DBUG_ASSERT(type == SYSTEM_TIME_AS_OF);
start= new (thd->mem_root)
start.item= new (thd->mem_root)
Item_datetime_literal(thd, &in.ltime, TIME_SECOND_PART_DIGITS);
if (!start)
if (!start.item)
return true;
}
else
start= NULL;
end= NULL;
start.item= NULL;
end.empty();
return false;
}
void vers_select_conds_t::print(String *str, enum_query_type query_type)
{
const static LEX_CSTRING unit_type[]=
{
{ STRING_WITH_LEN("") },
{ STRING_WITH_LEN("TIMESTAMP ") },
{ STRING_WITH_LEN("TRANSACTION ") }
};
switch (type) {
case SYSTEM_TIME_UNSPECIFIED:
break;
case SYSTEM_TIME_AS_OF:
str->append(STRING_WITH_LEN(" FOR SYSTEM_TIME AS OF "));
str->append(unit_type + unit_start);
start->print(str, query_type);
start.print(str, query_type, STRING_WITH_LEN(" FOR SYSTEM_TIME AS OF "));
break;
case SYSTEM_TIME_FROM_TO:
str->append(STRING_WITH_LEN(" FOR SYSTEM_TIME FROM "));
str->append(unit_type + unit_start);
start->print(str, query_type);
str->append(STRING_WITH_LEN(" TO "));
str->append(unit_type + unit_end);
end->print(str, query_type);
start.print(str, query_type, STRING_WITH_LEN(" FOR SYSTEM_TIME FROM "));
end.print(str, query_type, STRING_WITH_LEN(" TO "));
break;
case SYSTEM_TIME_BETWEEN:
str->append(STRING_WITH_LEN(" FOR SYSTEM_TIME BETWEEN "));
str->append(unit_type + unit_start);
start->print(str, query_type);
str->append(STRING_WITH_LEN(" AND "));
str->append(unit_type + unit_end);
end->print(str, query_type);
start.print(str, query_type, STRING_WITH_LEN(" FOR SYSTEM_TIME BETWEEN "));
end.print(str, query_type, STRING_WITH_LEN(" AND "));
break;
case SYSTEM_TIME_BEFORE:
DBUG_ASSERT(0);
@ -871,8 +855,8 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
vers_system_time_t/VERS_TRX_ID at stage of fix_fields()
(this is large refactoring). */
vers_conditions.resolve_units(timestamps_only);
if (timestamps_only && (vers_conditions.unit_start == VERS_TRX_ID ||
vers_conditions.unit_end == VERS_TRX_ID))
if (timestamps_only && (vers_conditions.start.unit == VERS_TRX_ID ||
vers_conditions.end.unit == VERS_TRX_ID))
{
my_error(ER_VERS_ENGINE_UNSUPPORTED, MYF(0), table->table_name.str);
DBUG_RETURN(-1);
@ -889,53 +873,8 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
{
if (vers_conditions)
{
if (vers_conditions.start)
{
if (!vers_conditions.unit_start)
vers_conditions.unit_start= t->s->versioned;
switch (vers_conditions.unit_start)
{
case VERS_TIMESTAMP:
{
vers_conditions.start= newx Item_datetime_from_unixtime_typecast(
thd, vers_conditions.start, 6);
break;
}
case VERS_TRX_ID:
{
vers_conditions.start= newx Item_longlong_typecast(
thd, vers_conditions.start);
break;
}
default:
DBUG_ASSERT(0);
break;
}
}
if (vers_conditions.end)
{
if (!vers_conditions.unit_end)
vers_conditions.unit_end= t->s->versioned;
switch (vers_conditions.unit_end)
{
case VERS_TIMESTAMP:
{
vers_conditions.end= newx Item_datetime_from_unixtime_typecast(
thd, vers_conditions.end, 6);
break;
}
case VERS_TRX_ID:
{
vers_conditions.end= newx Item_longlong_typecast(
thd, vers_conditions.end);
break;
}
default:
DBUG_ASSERT(0);
break;
}
}
vers_conditions.start.add_typecast(thd, t->s->versioned);
vers_conditions.end.add_typecast(thd, t->s->versioned);
}
switch (vers_conditions.type)
{
@ -957,26 +896,19 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
cond1= or_items(thd, cond1, newx Item_func_isnull(thd, row_end));
break;
case SYSTEM_TIME_AS_OF:
cond1= newx Item_func_le(thd, row_start,
vers_conditions.start);
cond2= newx Item_func_gt(thd, row_end,
vers_conditions.start);
cond1= newx Item_func_le(thd, row_start, vers_conditions.start.item);
cond2= newx Item_func_gt(thd, row_end, vers_conditions.start.item);
break;
case SYSTEM_TIME_FROM_TO:
cond1= newx Item_func_lt(thd, row_start,
vers_conditions.end);
cond2= newx Item_func_ge(thd, row_end,
vers_conditions.start);
cond1= newx Item_func_lt(thd, row_start, vers_conditions.end.item);
cond2= newx Item_func_ge(thd, row_end, vers_conditions.start.item);
break;
case SYSTEM_TIME_BETWEEN:
cond1= newx Item_func_le(thd, row_start,
vers_conditions.end);
cond2= newx Item_func_ge(thd, row_end,
vers_conditions.start);
cond1= newx Item_func_le(thd, row_start, vers_conditions.end.item);
cond2= newx Item_func_ge(thd, row_end, vers_conditions.start.item);
break;
case SYSTEM_TIME_BEFORE:
cond1= newx Item_func_lt(thd, row_end,
vers_conditions.start);
cond1= newx Item_func_lt(thd, row_end, vers_conditions.start.item);
break;
default:
DBUG_ASSERT(0);
@ -995,29 +927,29 @@ int SELECT_LEX::vers_setup_conds(THD *thd, TABLE_LIST *tables, COND **where_expr
cond1= newx Item_func_eq(thd, row_end, curr);
break;
case SYSTEM_TIME_AS_OF:
trx_id0= vers_conditions.unit_start == VERS_TIMESTAMP ?
newx Item_func_vtq_id(thd, vers_conditions.start, TR_table::FLD_TRX_ID) :
vers_conditions.start;
trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
? newx Item_func_vtq_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID)
: vers_conditions.start.item;
cond1= newx Item_func_vtq_trx_sees_eq(thd, trx_id0, row_start);
cond2= newx Item_func_vtq_trx_sees(thd, row_end, trx_id0);
break;
case SYSTEM_TIME_FROM_TO:
case SYSTEM_TIME_BETWEEN:
trx_id0= vers_conditions.unit_start == VERS_TIMESTAMP ?
newx Item_func_vtq_id(thd, vers_conditions.start, TR_table::FLD_TRX_ID, true) :
vers_conditions.start;
trx_id1= vers_conditions.unit_end == VERS_TIMESTAMP ?
newx Item_func_vtq_id(thd, vers_conditions.end, TR_table::FLD_TRX_ID, false) :
vers_conditions.end;
cond1= vers_conditions.type == SYSTEM_TIME_FROM_TO ?
newx Item_func_vtq_trx_sees(thd, trx_id1, row_start) :
newx Item_func_vtq_trx_sees_eq(thd, trx_id1, row_start);
trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
? newx Item_func_vtq_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID, true)
: vers_conditions.start.item;
trx_id1= vers_conditions.end.unit == VERS_TIMESTAMP
? newx Item_func_vtq_id(thd, vers_conditions.end.item, TR_table::FLD_TRX_ID, false)
: vers_conditions.end.item;
cond1= vers_conditions.type == SYSTEM_TIME_FROM_TO
? newx Item_func_vtq_trx_sees(thd, trx_id1, row_start)
: newx Item_func_vtq_trx_sees_eq(thd, trx_id1, row_start);
cond2= newx Item_func_vtq_trx_sees_eq(thd, row_end, trx_id0);
break;
case SYSTEM_TIME_BEFORE:
trx_id0= vers_conditions.unit_start == VERS_TIMESTAMP ?
newx Item_func_vtq_id(thd, vers_conditions.start, TR_table::FLD_TRX_ID) :
vers_conditions.start;
trx_id0= vers_conditions.start.unit == VERS_TIMESTAMP
? newx Item_func_vtq_id(thd, vers_conditions.start.item, TR_table::FLD_TRX_ID)
: vers_conditions.start.item;
cond1= newx Item_func_lt(thd, row_end, trx_id0);
break;
default:

View file

@ -752,27 +752,6 @@ bool LEX::set_bincmp(CHARSET_INFO *cs, bool bin)
} while(0)
void vers_select_conds_t::init(vers_system_time_t t, vers_sys_type_t u_start,
Item *s, vers_sys_type_t u_end, Item *e)
{
type= t;
unit_start= u_start;
unit_end= u_end;
start= fix_dec(s);
end= fix_dec(e);
used= from_query= false;
}
Item *vers_select_conds_t::fix_dec(Item *item)
{
if (item && item->decimals == 0 && item->type() == Item::FUNC_ITEM &&
((Item_func*)item)->functype() == Item_func::NOW_FUNC)
item->decimals= 6;
return item;
}
Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
{
Virtual_column_info *v= new (thd->mem_root) Virtual_column_info();
@ -813,6 +792,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
LEX_CSTRING name;
uint offset;
} sp_cursor_name_and_offset;
vers_history_point_t vers_history_point;
/* pointers */
Create_field *create_field;
@ -2046,7 +2026,8 @@ END_OF_INPUT
%type <lex_str_list> opt_with_column_list
%type <vers_range_unit> opt_trans_or_timestamp
%type <vers_range_unit> opt_history_unit
%type <vers_history_point> history_point
%type <vers_column_versioning> with_or_without_system
%%
@ -9203,18 +9184,25 @@ select_options:
}
;
opt_trans_or_timestamp:
/* empty */
opt_history_unit:
/* empty*/
{
$$ = VERS_UNDEFINED;
$$= VERS_UNDEFINED;
}
| TRANSACTION_SYM
{
$$ = VERS_TRX_ID;
$$= VERS_TRX_ID;
}
| TIMESTAMP
{
$$ = VERS_TIMESTAMP;
$$= VERS_TIMESTAMP;
}
;
history_point:
opt_history_unit simple_expr
{
$$= Vers_history_point($1, $2);
}
;
@ -9230,23 +9218,23 @@ opt_for_system_time_clause:
;
system_time_expr:
AS OF_SYM opt_trans_or_timestamp simple_expr
AS OF_SYM history_point
{
Lex->vers_conditions.init(SYSTEM_TIME_AS_OF, $3, $4);
Lex->vers_conditions.init(SYSTEM_TIME_AS_OF, $3);
}
| ALL
{
Lex->vers_conditions.init(SYSTEM_TIME_ALL);
}
| FROM opt_trans_or_timestamp simple_expr
TO_SYM opt_trans_or_timestamp simple_expr
| FROM history_point
TO_SYM history_point
{
Lex->vers_conditions.init(SYSTEM_TIME_FROM_TO, $2, $3, $5, $6);
Lex->vers_conditions.init(SYSTEM_TIME_FROM_TO, $2, $4);
}
| BETWEEN_SYM opt_trans_or_timestamp simple_expr
AND_SYM opt_trans_or_timestamp simple_expr
| BETWEEN_SYM history_point
AND_SYM history_point
{
Lex->vers_conditions.init(SYSTEM_TIME_BETWEEN, $2, $3, $5, $6);
Lex->vers_conditions.init(SYSTEM_TIME_BETWEEN, $2, $4);
}
;
@ -13447,9 +13435,9 @@ opt_delete_system_time:
{
Lex->vers_conditions.init(SYSTEM_TIME_ALL);
}
| BEFORE_SYM SYSTEM_TIME_SYM opt_trans_or_timestamp simple_expr
| BEFORE_SYM SYSTEM_TIME_SYM history_point
{
Lex->vers_conditions.init(SYSTEM_TIME_BEFORE, $3, $4);
Lex->vers_conditions.init(SYSTEM_TIME_BEFORE, $3);
}
;

View file

@ -8920,27 +8920,67 @@ bool TR_table::check(bool error)
void vers_select_conds_t::resolve_units(bool timestamps_only)
{
DBUG_ASSERT(type != SYSTEM_TIME_UNSPECIFIED);
DBUG_ASSERT(start);
if (unit_start == VERS_UNDEFINED)
DBUG_ASSERT(start.item);
start.resolve_unit(timestamps_only);
end.resolve_unit(timestamps_only);
}
void Vers_history_point::resolve_unit(bool timestamps_only)
{
if (item && unit == VERS_UNDEFINED)
{
if (start->type() == Item::FIELD_ITEM)
unit_start= VERS_TIMESTAMP;
if (item->type() == Item::FIELD_ITEM || timestamps_only)
unit= VERS_TIMESTAMP;
else if (item->result_type() == INT_RESULT ||
item->result_type() == REAL_RESULT)
unit= VERS_TRX_ID;
else
unit_start= (!timestamps_only && (start->result_type() == INT_RESULT ||
start->result_type() == REAL_RESULT)) ?
VERS_TRX_ID : VERS_TIMESTAMP;
}
if (end && unit_end == VERS_UNDEFINED)
{
if (start->type() == Item::FIELD_ITEM)
unit_start= VERS_TIMESTAMP;
else
unit_end= (!timestamps_only && (end->result_type() == INT_RESULT ||
end->result_type() == REAL_RESULT)) ?
VERS_TRX_ID : VERS_TIMESTAMP;
unit= VERS_TIMESTAMP;
}
}
void Vers_history_point::fix_item()
{
if (item && item->decimals == 0 && item->type() == Item::FUNC_ITEM &&
((Item_func*)item)->functype() == Item_func::NOW_FUNC)
item->decimals= 6;
}
void Vers_history_point::add_typecast(THD *thd, enum vers_sys_type_t defunit)
{
if (item)
{
if (!unit)
unit= defunit;
switch (unit)
{
case VERS_TIMESTAMP:
item= new (thd->mem_root) Item_datetime_from_unixtime_typecast(
thd, item, MAX_DATETIME_PRECISION);
break;
case VERS_TRX_ID:
item= new (thd->mem_root) Item_longlong_typecast(thd, item);
break;
default:
DBUG_ASSERT(0);
break;
}
}
}
void Vers_history_point::print(String *str, enum_query_type query_type,
const char *prefix, size_t plen)
{
const static LEX_CSTRING unit_type[]=
{
{ STRING_WITH_LEN("") },
{ STRING_WITH_LEN("TIMESTAMP ") },
{ STRING_WITH_LEN("TRANSACTION ") }
};
str->append(prefix, plen);
str->append(unit_type + unit);
item->print(str, query_type);
}
Field *TABLE::find_field_by_name(LEX_CSTRING *str) const
{

View file

@ -1841,6 +1841,85 @@ class SJ_MATERIALIZATION_INFO;
class Index_hint;
class Item_in_subselect;
/* trivial class, for %union in sql_yacc.yy */
struct vers_history_point_t
{
vers_sys_type_t unit;
Item *item;
};
class Vers_history_point : public vers_history_point_t
{
void fix_item();
public:
Vers_history_point() { empty(); }
Vers_history_point(vers_sys_type_t unit_arg, Item *item_arg)
{
unit= unit_arg;
item= item_arg;
fix_item();
}
Vers_history_point(vers_history_point_t p)
{
unit= p.unit;
item= p.item;
fix_item();
}
void empty() { unit= VERS_UNDEFINED; item= NULL; }
void print(String *str, enum_query_type, const char *prefix, size_t plen);
void resolve_unit(bool timestamps_only);
void add_typecast(THD *thd, enum vers_sys_type_t defunit);
};
struct vers_select_conds_t
{
vers_system_time_t type;
bool from_query:1;
bool used:1;
Vers_history_point start;
Vers_history_point end;
void empty()
{
type= SYSTEM_TIME_UNSPECIFIED;
used= from_query= false;
start.empty();
end.empty();
}
void init(vers_system_time_t _type,
Vers_history_point _start= Vers_history_point(),
Vers_history_point _end= Vers_history_point())
{
type= _type;
used= from_query= false;
start= _start;
end= _end;
}
void print(String *str, enum_query_type query_type);
bool init_from_sysvar(THD *thd);
bool operator== (vers_system_time_t b)
{
return type == b;
}
bool operator!= (vers_system_time_t b)
{
return type != b;
}
operator bool() const
{
return type != SYSTEM_TIME_UNSPECIFIED;
}
void resolve_units(bool timestamps_only);
bool user_defined() const
{
return !from_query && type != SYSTEM_TIME_UNSPECIFIED;
}
};
/*
Table reference in the FROM clause.
@ -1878,50 +1957,6 @@ class Item_in_subselect;
*/
/** last_leaf_for_name_resolutioning support. */
struct vers_select_conds_t
{
vers_system_time_t type;
vers_sys_type_t unit_start, unit_end;
bool from_query:1;
bool used:1;
Item *start, *end;
void empty()
{
type= SYSTEM_TIME_UNSPECIFIED;
unit_start= unit_end= VERS_UNDEFINED;
used= from_query= false;
start= end= NULL;
}
Item *fix_dec(Item *item);
void init(vers_system_time_t t, vers_sys_type_t u_start= VERS_UNDEFINED,
Item * s= NULL, vers_sys_type_t u_end= VERS_UNDEFINED,
Item * e= NULL);
void print(String *str, enum_query_type query_type);
bool init_from_sysvar(THD *thd);
bool operator== (vers_system_time_t b)
{
return type == b;
}
bool operator!= (vers_system_time_t b)
{
return type != b;
}
operator bool() const
{
return type != SYSTEM_TIME_UNSPECIFIED;
}
void resolve_units(bool timestamps_only);
bool user_defined() const
{
return !from_query && type != SYSTEM_TIME_UNSPECIFIED;
}
};
struct LEX;
class Index_hint;