Commit 6d89a4a4 authored by Aleksey Midenkov's avatar Aleksey Midenkov

Parser, SQL: (0.4) TRANSACTION support in queries

Syntax extension: TIMESTAMP/TRANSACTION keyword can be used before FROM ... TO, BETWEEN ... AND.
Example:
    SELECT * FROM t1 FOR SYSTEM_TIME TIMESTAMP FROM '1-1-1' TO NOW();

Closes #27
parent a22cbc45
......@@ -7537,3 +7537,9 @@ ER_SYS_END_FIELD_MUST_BE_BIGINT
ER_NO_VERSIONED_FIELDS_IN_VERSIONED_TABLE
eng "Every field specified unversioned in versioned table"
ER_VERS_TRX_ID_UNSUPPORTED
eng "Engine does not support versioned TRX_ID"
ER_VERS_RANGE_UNITS_MISMATCH
eng "Range units mismatch"
......@@ -33,9 +33,9 @@
#include "sql_signal.h"
void LEX::parse_error()
void LEX::parse_error(uint err_number)
{
thd->parse_error();
thd->parse_error(err_number);
}
......
......@@ -2649,7 +2649,6 @@ struct LEX: public Query_tables_list
private:
Query_arena_memroot *arena_for_set_stmt;
MEM_ROOT *mem_root_for_set_stmt;
void parse_error();
bool sp_block_finalize(THD *thd, const Lex_spblock_st spblock,
class sp_label **splabel);
bool sp_change_context(THD *thd, const sp_pcontext *ctx, bool exclusive);
......@@ -2663,6 +2662,7 @@ struct LEX: public Query_tables_list
bool sp_for_loop_increment(THD *thd, const Lex_for_loop_st &loop);
public:
void parse_error(uint err_number= ER_SYNTAX_ERROR);
inline bool is_arena_for_set_stmt() {return arena_for_set_stmt != 0;}
bool set_arena_for_set_stmt(Query_arena *backup);
void reset_arena_for_set_stmt(Query_arena *backup);
......
......@@ -668,7 +668,7 @@ setup_without_group(THD *thd, Ref_ptr_array ref_pointer_array,
}
static int
setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LEX *select_lex)
setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LEX *slex)
{
DBUG_ENTER("setup_for_system_time");
......@@ -698,11 +698,11 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE
because they must outlive execution phase for multiple executions. */
arena= thd->activate_stmt_arena_if_needed(&backup);
if (select_lex->saved_where)
if (slex->saved_where)
{
DBUG_ASSERT(thd->stmt_arena->is_sp_execute());
/* 2. this copy_andor_structure() is also required by the same reason */
*where_expr= select_lex->saved_where->copy_andor_structure(thd);
*where_expr= slex->saved_where->copy_andor_structure(thd);
}
else if (thd->stmt_arena->is_sp_execute())
{
......@@ -711,7 +711,7 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE
else if (*where_expr) // SP executed first time (STMT_INITIALIZED_FOR_SP)
/* 1. copy_andor_structure() is required since this andor tree
is modified later (and on shorter arena) */
select_lex->saved_where= (*where_expr)->copy_andor_structure(thd);
slex->saved_where= (*where_expr)->copy_andor_structure(thd);
}
/* We have to save also non-versioned on_expr since we may have
......@@ -754,15 +754,23 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE
Field *fstart= table->table->vers_start_field();
Field *fend= table->table->vers_end_field();
DBUG_ASSERT(select_lex->parent_lex);
Name_resolution_context *context= select_lex->parent_lex->current_context();
DBUG_ASSERT(slex->parent_lex);
Name_resolution_context *context= slex->parent_lex->current_context();
DBUG_ASSERT(context);
Item *row_start= new (thd->mem_root) Item_field(thd, context, fstart);
Item *row_end= new (thd->mem_root) Item_field(thd, context, fend);
Item *row_end2= row_end;
if (!table->table->versioned_by_sql())
if (table->table->versioned_by_sql())
{
if (slex->vers_conditions.unit == UNIT_TRX_ID)
{
my_error(ER_VERS_TRX_ID_UNSUPPORTED, MYF(0), table->table_name);
DBUG_RETURN(-1);
}
}
else if (slex->vers_conditions.unit == UNIT_TIMESTAMP)
{
DBUG_ASSERT(table->table->s && table->table->s->db_plugin);
row_start= new (thd->mem_root) Item_func_vtq_ts(
......@@ -778,7 +786,7 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE
}
Item *cond1= 0, *cond2= 0, *curr= 0;
switch (select_lex->vers_conditions.type)
switch (slex->vers_conditions.type)
{
case FOR_SYSTEM_TIME_UNSPECIFIED:
if (table->table->versioned_by_sql())
......@@ -796,21 +804,21 @@ setup_for_system_time(THD *thd, TABLE_LIST *tables, COND **where_expr, SELECT_LE
break;
case FOR_SYSTEM_TIME_AS_OF:
cond1= new (thd->mem_root) Item_func_le(thd, row_start,
select_lex->vers_conditions.start);
slex->vers_conditions.start);
cond2= new (thd->mem_root) Item_func_gt(thd, row_end,
select_lex->vers_conditions.start);
slex->vers_conditions.start);
break;
case FOR_SYSTEM_TIME_FROM_TO:
cond1= new (thd->mem_root) Item_func_lt(thd, row_start,
select_lex->vers_conditions.end);
slex->vers_conditions.end);
cond2= new (thd->mem_root) Item_func_ge(thd, row_end,
select_lex->vers_conditions.start);
slex->vers_conditions.start);
break;
case FOR_SYSTEM_TIME_BETWEEN:
cond1= new (thd->mem_root) Item_func_le(thd, row_start,
select_lex->vers_conditions.end);
slex->vers_conditions.end);
cond2= new (thd->mem_root) Item_func_ge(thd, row_end,
select_lex->vers_conditions.start);
slex->vers_conditions.start);
break;
default:
DBUG_ASSERT(0);
......
......@@ -849,6 +849,7 @@ Virtual_column_info *add_virtual_expression(THD *thd, Item *expr)
enum Window_frame::Frame_exclusion frame_exclusion;
enum trigger_order_type trigger_action_order_type;
DDL_options_st object_ddl_options;
enum vers_range_unit_t vers_range_unit;
}
%{
......@@ -1968,6 +1969,8 @@ END_OF_INPUT
%type <lex_str_list> opt_with_column_list
%type <vers_range_unit> trans_or_timestamp
%%
......@@ -8673,14 +8676,25 @@ select_options:
}
;
trans_or_timestamp:
TRANSACTION_SYM
{
$$ = UNIT_TRX_ID;
}
| TIMESTAMP
{
$$ = UNIT_TIMESTAMP;
}
;
opt_for_system_time_clause:
/* empty */
{}
| FOR_SYSTEM_TIME_SYM
AS OF_SYM
TIMESTAMP simple_expr
trans_or_timestamp simple_expr
{
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_AS_OF, $5);
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_AS_OF, $4, $5);
}
| FOR_SYSTEM_TIME_SYM
AS OF_SYM
......@@ -8689,23 +8703,55 @@ opt_for_system_time_clause:
Item *item= new (thd->mem_root) Item_func_now_local(thd, 6);
if (item == NULL)
MYSQL_YYABORT;
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_AS_OF, item);
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_AS_OF, UNIT_TIMESTAMP, item);
}
| FOR_SYSTEM_TIME_SYM
FROM
TIMESTAMP simple_expr
trans_or_timestamp
simple_expr
TO_SYM
TIMESTAMP simple_expr
trans_or_timestamp
simple_expr
{
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_FROM_TO, $4, $7);
if ($3 != $6)
{
Lex->parse_error(ER_VERS_RANGE_UNITS_MISMATCH);
MYSQL_YYABORT;
}
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_FROM_TO, $3, $4, $7);
}
| FOR_SYSTEM_TIME_SYM
trans_or_timestamp
FROM
simple_expr
TO_SYM
simple_expr
{
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_FROM_TO, $2, $4, $6);
}
| FOR_SYSTEM_TIME_SYM
BETWEEN_SYM
trans_or_timestamp
simple_expr
AND_SYM
trans_or_timestamp
simple_expr
{
if ($3 != $6)
{
Lex->parse_error(ER_VERS_RANGE_UNITS_MISMATCH);
MYSQL_YYABORT;
}
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_BETWEEN, $3, $4, $7);
}
| FOR_SYSTEM_TIME_SYM
trans_or_timestamp
BETWEEN_SYM
TIMESTAMP simple_expr
simple_expr
AND_SYM
TIMESTAMP simple_expr
simple_expr
{
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_BETWEEN, $4, $7);
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_BETWEEN, $2, $4, $6);
}
;
......
......@@ -1812,7 +1812,7 @@ class Item_in_subselect;
4) jtbm semi-join (jtbm_subselect != NULL)
*/
enum for_system_time_type
enum vers_range_type_t
{
FOR_SYSTEM_TIME_UNSPECIFIED = 0,
FOR_SYSTEM_TIME_AS_OF,
......@@ -1820,24 +1820,34 @@ enum for_system_time_type
FOR_SYSTEM_TIME_BETWEEN
};
enum vers_range_unit_t
{
UNIT_TIMESTAMP = 0,
UNIT_TRX_ID
};
/** System versioning support. */
struct vers_select_conds_t
{
enum for_system_time_type type;
vers_range_type_t type;
vers_range_unit_t unit;
Item *start, *end;
void empty()
{
type= FOR_SYSTEM_TIME_UNSPECIFIED;
unit= UNIT_TIMESTAMP;
start= end= NULL;
}
void init(
const enum for_system_time_type t,
Item * const s,
Item * const e= NULL)
vers_range_type_t t,
vers_range_unit_t u,
Item * s,
Item * e= NULL)
{
type= t;
unit= u;
start= s;
end= e;
}
......
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