mirror of
https://github.com/MariaDB/server.git
synced 2025-07-30 16:24:05 +03:00
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
This commit is contained in:
@ -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 @@ private:
|
||||
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
|
||||
TIMESTAMP simple_expr
|
||||
trans_or_timestamp
|
||||
simple_expr
|
||||
AND_SYM
|
||||
TIMESTAMP simple_expr
|
||||
trans_or_timestamp
|
||||
simple_expr
|
||||
{
|
||||
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_BETWEEN, $4, $7);
|
||||
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
|
||||
simple_expr
|
||||
AND_SYM
|
||||
simple_expr
|
||||
{
|
||||
Lex->current_select->vers_conditions.init(FOR_SYSTEM_TIME_BETWEEN, $2, $4, $6);
|
||||
}
|
||||
;
|
||||
|
||||
|
20
sql/table.h
20
sql/table.h
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user