MDEV-14820 System versioning is applied incorrectly to CTEs
Make sure that SELECT_LEX_UNIT::derived, behaves as documented (points to the "TABLE_LIST representing this union in the embedding select"). For recursive CTE this was not necessarily the case, it could've pointed to the TABLE_LIST inside the CTE, not in the embedding select. To fix: * don't update unit->derived in mysql_derived_prepare(), pass derived as an argument to st_select_lex_unit::prepare() * prefer to set unit->derived in TABLE_LIST::init_derived() to the TABLE_LIST in the embedding select, not to the recursive reference. Fail if there are many TABLE_LISTs in the embedding select with conflicting FOR SYSTEM_TIME clauses. cleanup: * remove redundant THD* argument from st_select_lex_unit::prepare()
This commit is contained in:
parent
0f956a0676
commit
531acda484
@ -9,4 +9,3 @@
|
|||||||
# Do not use any TAB characters for whitespace.
|
# Do not use any TAB characters for whitespace.
|
||||||
#
|
#
|
||||||
##############################################################################
|
##############################################################################
|
||||||
cte: MDEV-14820
|
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
|
set time_zone="+00:00";
|
||||||
set default_storage_engine=innodb;
|
set default_storage_engine=innodb;
|
||||||
create or replace table dept (
|
create or replace table dept (
|
||||||
dept_id int(10) primary key,
|
dept_id int(10) primary key,
|
||||||
name varchar(100)
|
name varchar(100)
|
||||||
)
|
) with system versioning;
|
||||||
with system versioning;
|
|
||||||
create or replace table emp (
|
create or replace table emp (
|
||||||
emp_id int(10) primary key,
|
emp_id int(10) primary key,
|
||||||
dept_id int(10) not null,
|
dept_id int(10) not null,
|
||||||
@ -18,16 +18,51 @@ constraint `mgr-fk`
|
|||||||
foreign key (mgr) references emp (emp_id)
|
foreign key (mgr) references emp (emp_id)
|
||||||
on delete restrict
|
on delete restrict
|
||||||
on update restrict
|
on update restrict
|
||||||
)
|
) with system versioning;
|
||||||
with system versioning;
|
|
||||||
insert into dept (dept_id, name) values (10, "accounting");
|
insert into dept (dept_id, name) values (10, "accounting");
|
||||||
insert into emp (emp_id, name, salary, dept_id, mgr) values
|
insert into emp (emp_id, name, salary, dept_id, mgr) values
|
||||||
(1, "bill", 1000, 10, null),
|
(1, "bill", 1000, 10, null),
|
||||||
(20, "john", 500, 10, 1),
|
(20, "john", 500, 10, 1),
|
||||||
(30, "jane", 750, 10,1 );
|
(30, "jane", 750, 10,1 );
|
||||||
select max(sys_trx_start) into @ts_1 from emp;
|
select row_start into @ts_1 from emp where name="jane";
|
||||||
update emp set mgr=30 where name ="john";
|
update emp set mgr=30 where name ="john";
|
||||||
select sys_trx_start into @ts_2 from emp where name="john";
|
explain extended
|
||||||
|
with ancestors as (
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary from emp as e where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary from emp as e
|
||||||
|
) select * from ancestors for system_time as of @ts_1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 8 100.00
|
||||||
|
2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||||
|
3 UNION e ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||||
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
Warnings:
|
||||||
|
Note 1003 with ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||||
|
select row_start into @ts_2 from emp where name="john";
|
||||||
|
explain extended /* All report to 'Bill' */
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp for system_time as of timestamp @ts_1 as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp for system_time as of timestamp @ts_1 as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
|
||||||
|
2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||||
|
3 RECURSIVE UNION e ALL mgr-fk NULL NULL NULL 4 100.00 Using where
|
||||||
|
3 RECURSIVE UNION <derived2> ref key0 key0 4 test.e.mgr 2 100.00
|
||||||
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
Warnings:
|
||||||
|
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||||
/* All report to 'Bill' */
|
/* All report to 'Bill' */
|
||||||
with recursive
|
with recursive
|
||||||
ancestors
|
ancestors
|
||||||
@ -36,7 +71,7 @@ as
|
|||||||
select e.emp_id, e.name, e.mgr, e.salary
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
from emp for system_time as of timestamp @ts_1 as e
|
from emp for system_time as of timestamp @ts_1 as e
|
||||||
where name = 'bill'
|
where name = 'bill'
|
||||||
union
|
union
|
||||||
select e.emp_id, e.name, e.mgr, e.salary
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
from emp for system_time as of timestamp @ts_1 as e,
|
from emp for system_time as of timestamp @ts_1 as e,
|
||||||
ancestors as a
|
ancestors as a
|
||||||
@ -47,25 +82,186 @@ emp_id name mgr salary
|
|||||||
1 bill NULL 1000
|
1 bill NULL 1000
|
||||||
20 john 1 500
|
20 john 1 500
|
||||||
30 jane 1 750
|
30 jane 1 750
|
||||||
/* Expected 3 rows */
|
explain extended with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of timestamp @ts_1;
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <derived2> ALL NULL NULL NULL NULL 4 100.00
|
||||||
|
2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||||
|
3 RECURSIVE UNION e ALL mgr-fk NULL NULL NULL 4 100.00 Using where
|
||||||
|
3 RECURSIVE UNION <derived2> ref key0 key0 4 test.e.mgr 2 100.00
|
||||||
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
Warnings:
|
||||||
|
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `ancestors`.`emp_id` AS `emp_id`,`ancestors`.`name` AS `name`,`ancestors`.`mgr` AS `mgr`,`ancestors`.`salary` AS `salary` from `ancestors`
|
||||||
with recursive
|
with recursive
|
||||||
ancestors
|
ancestors
|
||||||
as
|
as
|
||||||
(
|
(
|
||||||
select e.emp_id, e.name, e.mgr, e.salary
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
from emp for system_time as of timestamp @ts_2 as e
|
from emp as e
|
||||||
where name = 'bill'
|
where name = 'bill'
|
||||||
union
|
union
|
||||||
select e.emp_id, e.name, e.mgr, e.salary
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
from emp for system_time as of timestamp @ts_2 as e,
|
from emp as e,
|
||||||
ancestors as a
|
ancestors as a
|
||||||
where e.mgr = a.emp_id
|
where e.mgr = a.emp_id
|
||||||
)
|
)
|
||||||
select * from ancestors;
|
select * from ancestors for system_time as of timestamp @ts_1;
|
||||||
emp_id name mgr salary
|
emp_id name mgr salary
|
||||||
1 bill NULL 1000
|
1 bill NULL 1000
|
||||||
|
20 john 1 500
|
||||||
30 jane 1 750
|
30 jane 1 750
|
||||||
20 john 30 500
|
explain extended with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select name from emp where emp_id in (select emp_id from ancestors for system_time as of timestamp @ts_1);
|
||||||
|
id select_type table type possible_keys key key_len ref rows filtered Extra
|
||||||
|
1 PRIMARY <subquery4> ALL distinct_key NULL NULL NULL 4 100.00
|
||||||
|
1 PRIMARY emp ALL PRIMARY NULL NULL NULL 4 75.00 Using where; Using join buffer (flat, BNL join)
|
||||||
|
4 MATERIALIZED <derived2> ALL NULL NULL NULL NULL 4 100.00
|
||||||
|
2 DERIVED e ALL NULL NULL NULL NULL 4 100.00 Using where
|
||||||
|
3 RECURSIVE UNION e ALL mgr-fk NULL NULL NULL 4 100.00 Using where
|
||||||
|
3 RECURSIVE UNION <derived2> ref key0 key0 4 test.e.mgr 2 100.00
|
||||||
|
NULL UNION RESULT <union2,3> ALL NULL NULL NULL NULL NULL NULL
|
||||||
|
Warnings:
|
||||||
|
Note 1003 with recursive ancestors as (/* select#2 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` where `test`.`e`.`name` = 'bill' and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1` union /* select#3 */ select `test`.`e`.`emp_id` AS `emp_id`,`test`.`e`.`name` AS `name`,`test`.`e`.`mgr` AS `mgr`,`test`.`e`.`salary` AS `salary` from `test`.`emp` FOR SYSTEM_TIME ALL `e` join `ancestors` `a` where `a`.`emp_id` = `test`.`e`.`mgr` and `test`.`e`.`row_end` > @`ts_1` and `test`.`e`.`row_start` <= @`ts_1`)/* select#1 */ select `test`.`emp`.`name` AS `name` from `test`.`emp` FOR SYSTEM_TIME ALL semi join (`ancestors`) where `test`.`emp`.`emp_id` = `ancestors`.`emp_id` and `test`.`emp`.`row_end` = TIMESTAMP'2038-01-19 03:14:07.999999'
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select name from emp where emp_id in (select emp_id from ancestors for system_time as of timestamp @ts_1);
|
||||||
|
name
|
||||||
|
bill
|
||||||
|
john
|
||||||
|
jane
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of @ts_2,
|
||||||
|
ancestors for system_time as of @ts_2 a2;
|
||||||
|
emp_id name mgr salary emp_id name mgr salary
|
||||||
|
1 bill NULL 1000 1 bill NULL 1000
|
||||||
|
30 jane 1 750 1 bill NULL 1000
|
||||||
|
20 john 30 500 1 bill NULL 1000
|
||||||
|
1 bill NULL 1000 30 jane 1 750
|
||||||
|
30 jane 1 750 30 jane 1 750
|
||||||
|
20 john 30 500 30 jane 1 750
|
||||||
|
1 bill NULL 1000 20 john 30 500
|
||||||
|
30 jane 1 750 20 john 30 500
|
||||||
|
20 john 30 500 20 john 30 500
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of @ts_2,
|
||||||
|
ancestors for system_time as of now() a2;
|
||||||
|
ERROR HY000: Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors,
|
||||||
|
ancestors for system_time as of @ts_2 a2;
|
||||||
|
ERROR HY000: Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of @ts_2,
|
||||||
|
ancestors a2;
|
||||||
|
ERROR HY000: Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of @ts_2
|
||||||
|
where emp_id in (select * from ancestors);
|
||||||
|
ERROR HY000: Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE
|
||||||
|
# SYSTEM_TIME to internal recursive instance is prohibited
|
||||||
|
with recursive cte as
|
||||||
|
(
|
||||||
|
select * from emp
|
||||||
|
union all
|
||||||
|
select * from cte for system_time as of @ts_1
|
||||||
|
)
|
||||||
|
select * from cte;
|
||||||
|
ERROR HY000: Table `cte` is not system-versioned
|
||||||
create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning;
|
create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning;
|
||||||
create or replace table addr ( emp_id int, address varchar(100)) with system versioning;
|
create or replace table addr ( emp_id int, address varchar(100)) with system versioning;
|
||||||
insert emp values (1, 'bill', 0), (2, 'bill', 1), (3, 'kate', 1);
|
insert emp values (1, 'bill', 0), (2, 'bill', 1), (3, 'kate', 1);
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
-- source include/have_innodb.inc
|
-- source include/have_innodb.inc
|
||||||
|
set time_zone="+00:00";
|
||||||
set default_storage_engine=innodb;
|
set default_storage_engine=innodb;
|
||||||
create or replace table dept (
|
create or replace table dept (
|
||||||
dept_id int(10) primary key,
|
dept_id int(10) primary key,
|
||||||
name varchar(100)
|
name varchar(100)
|
||||||
)
|
) with system versioning;
|
||||||
with system versioning;
|
|
||||||
|
|
||||||
create or replace table emp (
|
create or replace table emp (
|
||||||
emp_id int(10) primary key,
|
emp_id int(10) primary key,
|
||||||
@ -20,21 +20,29 @@ create or replace table emp (
|
|||||||
foreign key (mgr) references emp (emp_id)
|
foreign key (mgr) references emp (emp_id)
|
||||||
on delete restrict
|
on delete restrict
|
||||||
on update restrict
|
on update restrict
|
||||||
)
|
) with system versioning;
|
||||||
with system versioning;
|
|
||||||
|
|
||||||
insert into dept (dept_id, name) values (10, "accounting");
|
insert into dept (dept_id, name) values (10, "accounting");
|
||||||
|
|
||||||
insert into emp (emp_id, name, salary, dept_id, mgr) values
|
insert into emp (emp_id, name, salary, dept_id, mgr) values
|
||||||
(1, "bill", 1000, 10, null),
|
(1, "bill", 1000, 10, null),
|
||||||
(20, "john", 500, 10, 1),
|
(20, "john", 500, 10, 1),
|
||||||
(30, "jane", 750, 10,1 );
|
(30, "jane", 750, 10,1 );
|
||||||
|
|
||||||
select max(sys_trx_start) into @ts_1 from emp;
|
select row_start into @ts_1 from emp where name="jane";
|
||||||
|
|
||||||
update emp set mgr=30 where name ="john";
|
update emp set mgr=30 where name ="john";
|
||||||
select sys_trx_start into @ts_2 from emp where name="john";
|
|
||||||
|
|
||||||
|
explain extended
|
||||||
|
with ancestors as (
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary from emp as e where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary from emp as e
|
||||||
|
) select * from ancestors for system_time as of @ts_1;
|
||||||
|
|
||||||
|
select row_start into @ts_2 from emp where name="john";
|
||||||
|
|
||||||
|
let $q=
|
||||||
/* All report to 'Bill' */
|
/* All report to 'Bill' */
|
||||||
with recursive
|
with recursive
|
||||||
ancestors
|
ancestors
|
||||||
@ -43,7 +51,7 @@ as
|
|||||||
select e.emp_id, e.name, e.mgr, e.salary
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
from emp for system_time as of timestamp @ts_1 as e
|
from emp for system_time as of timestamp @ts_1 as e
|
||||||
where name = 'bill'
|
where name = 'bill'
|
||||||
union
|
union
|
||||||
select e.emp_id, e.name, e.mgr, e.salary
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
from emp for system_time as of timestamp @ts_1 as e,
|
from emp for system_time as of timestamp @ts_1 as e,
|
||||||
ancestors as a
|
ancestors as a
|
||||||
@ -51,21 +59,138 @@ as
|
|||||||
)
|
)
|
||||||
select * from ancestors;
|
select * from ancestors;
|
||||||
|
|
||||||
/* Expected 3 rows */
|
eval explain extended $q;
|
||||||
|
eval $q;
|
||||||
|
|
||||||
|
let $q=with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of timestamp @ts_1;
|
||||||
|
|
||||||
|
eval explain extended $q;
|
||||||
|
eval $q;
|
||||||
|
|
||||||
|
let $q=with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select name from emp where emp_id in (select emp_id from ancestors for system_time as of timestamp @ts_1);
|
||||||
|
|
||||||
|
eval explain extended $q;
|
||||||
|
eval $q;
|
||||||
|
|
||||||
with recursive
|
with recursive
|
||||||
ancestors
|
ancestors
|
||||||
as
|
as
|
||||||
(
|
(
|
||||||
select e.emp_id, e.name, e.mgr, e.salary
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
from emp for system_time as of timestamp @ts_2 as e
|
from emp as e
|
||||||
where name = 'bill'
|
where name = 'bill'
|
||||||
union
|
union
|
||||||
select e.emp_id, e.name, e.mgr, e.salary
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
from emp for system_time as of timestamp @ts_2 as e,
|
from emp as e,
|
||||||
ancestors as a
|
ancestors as a
|
||||||
where e.mgr = a.emp_id
|
where e.mgr = a.emp_id
|
||||||
)
|
)
|
||||||
select * from ancestors;
|
select * from ancestors for system_time as of @ts_2,
|
||||||
|
ancestors for system_time as of @ts_2 a2;
|
||||||
|
|
||||||
|
--error ER_CONFLICTING_FOR_SYSTEM_TIME
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of @ts_2,
|
||||||
|
ancestors for system_time as of now() a2;
|
||||||
|
|
||||||
|
--error ER_CONFLICTING_FOR_SYSTEM_TIME
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors,
|
||||||
|
ancestors for system_time as of @ts_2 a2;
|
||||||
|
|
||||||
|
--error ER_CONFLICTING_FOR_SYSTEM_TIME
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of @ts_2,
|
||||||
|
ancestors a2;
|
||||||
|
|
||||||
|
--error ER_CONFLICTING_FOR_SYSTEM_TIME
|
||||||
|
with recursive
|
||||||
|
ancestors
|
||||||
|
as
|
||||||
|
(
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e
|
||||||
|
where name = 'bill'
|
||||||
|
union
|
||||||
|
select e.emp_id, e.name, e.mgr, e.salary
|
||||||
|
from emp as e,
|
||||||
|
ancestors as a
|
||||||
|
where e.mgr = a.emp_id
|
||||||
|
)
|
||||||
|
select * from ancestors for system_time as of @ts_2
|
||||||
|
where emp_id in (select * from ancestors);
|
||||||
|
|
||||||
|
--echo # SYSTEM_TIME to internal recursive instance is prohibited
|
||||||
|
--error ER_VERS_NOT_VERSIONED
|
||||||
|
with recursive cte as
|
||||||
|
(
|
||||||
|
select * from emp
|
||||||
|
union all
|
||||||
|
select * from cte for system_time as of @ts_1
|
||||||
|
)
|
||||||
|
select * from cte;
|
||||||
|
|
||||||
create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning;
|
create or replace table emp ( emp_id int, name varchar(127), mgr int) with system versioning;
|
||||||
create or replace table addr ( emp_id int, address varchar(100)) with system versioning;
|
create or replace table addr ( emp_id int, address varchar(100)) with system versioning;
|
||||||
|
@ -3674,7 +3674,7 @@ int subselect_single_select_engine::prepare(THD *thd)
|
|||||||
int subselect_union_engine::prepare(THD *thd_arg)
|
int subselect_union_engine::prepare(THD *thd_arg)
|
||||||
{
|
{
|
||||||
set_thd(thd_arg);
|
set_thd(thd_arg);
|
||||||
return unit->prepare(thd, result, SELECT_NO_UNLOCK);
|
return unit->prepare(unit->derived, result, SELECT_NO_UNLOCK);
|
||||||
}
|
}
|
||||||
|
|
||||||
int subselect_uniquesubquery_engine::prepare(THD *)
|
int subselect_uniquesubquery_engine::prepare(THD *)
|
||||||
|
@ -7859,8 +7859,8 @@ ER_VERS_ALTER_ENGINE_PROHIBITED
|
|||||||
ER_VERS_RANGE_PROHIBITED
|
ER_VERS_RANGE_PROHIBITED
|
||||||
eng "SYSTEM_TIME range selector is not allowed"
|
eng "SYSTEM_TIME range selector is not allowed"
|
||||||
|
|
||||||
ER_UNUSED_26
|
ER_CONFLICTING_FOR_SYSTEM_TIME
|
||||||
eng "You should never see it"
|
eng "Conflicting FOR SYSTEM_TIME clauses in WITH RECURSIVE"
|
||||||
|
|
||||||
ER_VERS_TABLE_MUST_HAVE_COLUMNS
|
ER_VERS_TABLE_MUST_HAVE_COLUMNS
|
||||||
eng "Table %`s must have at least one versioned column"
|
eng "Table %`s must have at least one versioned column"
|
||||||
|
@ -978,7 +978,7 @@ bool With_element::prepare_unreferenced(THD *thd)
|
|||||||
|
|
||||||
thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
|
thd->lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
|
||||||
if (!spec->prepared &&
|
if (!spec->prepared &&
|
||||||
(spec->prepare(thd, 0, 0) ||
|
(spec->prepare(spec->derived, 0, 0) ||
|
||||||
rename_columns_of_derived_unit(thd, spec) ||
|
rename_columns_of_derived_unit(thd, spec) ||
|
||||||
check_duplicate_names(thd, first_sl->item_list, 1)))
|
check_duplicate_names(thd, first_sl->item_list, 1)))
|
||||||
rc= true;
|
rc= true;
|
||||||
|
@ -748,8 +748,6 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unit->derived= derived;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Above cascade call of prepare is important for PS protocol, but after it
|
Above cascade call of prepare is important for PS protocol, but after it
|
||||||
is called we can check if we really need prepare for this derived
|
is called we can check if we really need prepare for this derived
|
||||||
@ -767,7 +765,7 @@ bool mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *derived)
|
|||||||
|
|
||||||
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
|
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_DERIVED;
|
||||||
// st_select_lex_unit::prepare correctly work for single select
|
// st_select_lex_unit::prepare correctly work for single select
|
||||||
if ((res= unit->prepare(thd, derived->derived_result, 0)))
|
if ((res= unit->prepare(derived, derived->derived_result, 0)))
|
||||||
goto exit;
|
goto exit;
|
||||||
if (derived->with &&
|
if (derived->with &&
|
||||||
(res= derived->with->rename_columns_of_derived_unit(thd, unit)))
|
(res= derived->with->rename_columns_of_derived_unit(thd, unit)))
|
||||||
|
@ -864,7 +864,8 @@ public:
|
|||||||
bool is_excluded() { return prev == NULL; }
|
bool is_excluded() { return prev == NULL; }
|
||||||
|
|
||||||
/* UNION methods */
|
/* UNION methods */
|
||||||
bool prepare(THD *thd, select_result *result, ulong additional_options);
|
bool prepare(TABLE_LIST *derived_arg, select_result *sel_result,
|
||||||
|
ulong additional_options);
|
||||||
bool optimize();
|
bool optimize();
|
||||||
bool exec();
|
bool exec();
|
||||||
bool exec_recursive();
|
bool exec_recursive();
|
||||||
|
@ -1530,7 +1530,7 @@ static int mysql_test_select(Prepared_statement *stmt,
|
|||||||
It is not SELECT COMMAND for sure, so setup_tables will be called as
|
It is not SELECT COMMAND for sure, so setup_tables will be called as
|
||||||
usual, and we pass 0 as setup_tables_done_option
|
usual, and we pass 0 as setup_tables_done_option
|
||||||
*/
|
*/
|
||||||
if (unit->prepare(thd, 0, 0))
|
if (unit->prepare(unit->derived, 0, 0))
|
||||||
goto error;
|
goto error;
|
||||||
if (!lex->describe && !thd->lex->analyze_stmt && !stmt->is_sql_prepare())
|
if (!lex->describe && !thd->lex->analyze_stmt && !stmt->is_sql_prepare())
|
||||||
{
|
{
|
||||||
@ -1701,7 +1701,7 @@ static bool select_like_stmt_test(Prepared_statement *stmt,
|
|||||||
thd->lex->used_tables= 0; // Updated by setup_fields
|
thd->lex->used_tables= 0; // Updated by setup_fields
|
||||||
|
|
||||||
/* Calls JOIN::prepare */
|
/* Calls JOIN::prepare */
|
||||||
DBUG_RETURN(lex->unit.prepare(thd, 0, setup_tables_done_option));
|
DBUG_RETURN(lex->unit.prepare(lex->unit.derived, 0, setup_tables_done_option));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -25647,7 +25647,8 @@ bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
|
|||||||
unit->fake_select_lex->type= unit_operation_text[unit->common_op()];
|
unit->fake_select_lex->type= unit_operation_text[unit->common_op()];
|
||||||
unit->fake_select_lex->options|= SELECT_DESCRIBE;
|
unit->fake_select_lex->options|= SELECT_DESCRIBE;
|
||||||
}
|
}
|
||||||
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
|
if (!(res= unit->prepare(unit->derived, result,
|
||||||
|
SELECT_NO_UNLOCK | SELECT_DESCRIBE)))
|
||||||
res= unit->exec();
|
res= unit->exec();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -36,7 +36,7 @@ bool mysql_union(THD *thd, LEX *lex, select_result *result,
|
|||||||
{
|
{
|
||||||
DBUG_ENTER("mysql_union");
|
DBUG_ENTER("mysql_union");
|
||||||
bool res;
|
bool res;
|
||||||
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK |
|
if (!(res= unit->prepare(unit->derived, result, SELECT_NO_UNLOCK |
|
||||||
setup_tables_done_option)))
|
setup_tables_done_option)))
|
||||||
res= unit->exec();
|
res= unit->exec();
|
||||||
res|= unit->cleanup();
|
res|= unit->cleanup();
|
||||||
@ -807,10 +807,11 @@ bool st_select_lex_unit::join_union_item_types(THD *thd_arg,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
bool st_select_lex_unit::prepare(TABLE_LIST *derived_arg,
|
||||||
|
select_result *sel_result,
|
||||||
ulong additional_options)
|
ulong additional_options)
|
||||||
{
|
{
|
||||||
SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
|
SELECT_LEX *lex_select_save= thd->lex->current_select;
|
||||||
SELECT_LEX *sl, *first_sl= first_select();
|
SELECT_LEX *sl, *first_sl= first_select();
|
||||||
bool is_recursive= with_element && with_element->is_recursive;
|
bool is_recursive= with_element && with_element->is_recursive;
|
||||||
bool is_rec_result_table_created= false;
|
bool is_rec_result_table_created= false;
|
||||||
@ -821,7 +822,6 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
bool instantiate_tmp_table= false;
|
bool instantiate_tmp_table= false;
|
||||||
bool single_tvc= !first_sl->next_select() && first_sl->tvc;
|
bool single_tvc= !first_sl->next_select() && first_sl->tvc;
|
||||||
DBUG_ENTER("st_select_lex_unit::prepare");
|
DBUG_ENTER("st_select_lex_unit::prepare");
|
||||||
DBUG_ASSERT(thd == thd_arg);
|
|
||||||
DBUG_ASSERT(thd == current_thd);
|
DBUG_ASSERT(thd == current_thd);
|
||||||
|
|
||||||
describe= additional_options & SELECT_DESCRIBE;
|
describe= additional_options & SELECT_DESCRIBE;
|
||||||
@ -873,7 +873,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
prepared= 1;
|
prepared= 1;
|
||||||
saved_error= FALSE;
|
saved_error= FALSE;
|
||||||
|
|
||||||
thd_arg->lex->current_select= sl= first_sl;
|
thd->lex->current_select= sl= first_sl;
|
||||||
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
|
found_rows_for_union= first_sl->options & OPTION_FOUND_ROWS;
|
||||||
is_union_select= is_unit_op() || fake_select_lex || single_tvc;
|
is_union_select= is_unit_op() || fake_select_lex || single_tvc;
|
||||||
|
|
||||||
@ -902,7 +902,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
while (last->next_select())
|
while (last->next_select())
|
||||||
last= last->next_select();
|
last= last->next_select();
|
||||||
if (!(tmp_result= union_result=
|
if (!(tmp_result= union_result=
|
||||||
new (thd_arg->mem_root) select_union_direct(thd_arg, sel_result,
|
new (thd->mem_root) select_union_direct(thd, sel_result,
|
||||||
last)))
|
last)))
|
||||||
goto err; /* purecov: inspected */
|
goto err; /* purecov: inspected */
|
||||||
fake_select_lex= NULL;
|
fake_select_lex= NULL;
|
||||||
@ -911,11 +911,11 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (!is_recursive)
|
if (!is_recursive)
|
||||||
union_result= new (thd_arg->mem_root) select_unit(thd_arg);
|
union_result= new (thd->mem_root) select_unit(thd);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
with_element->rec_result=
|
with_element->rec_result=
|
||||||
new (thd_arg->mem_root) select_union_recursive(thd_arg);
|
new (thd->mem_root) select_union_recursive(thd);
|
||||||
union_result= with_element->rec_result;
|
union_result= with_element->rec_result;
|
||||||
fake_select_lex= NULL;
|
fake_select_lex= NULL;
|
||||||
}
|
}
|
||||||
@ -933,10 +933,10 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
{
|
{
|
||||||
if (sl->tvc)
|
if (sl->tvc)
|
||||||
{
|
{
|
||||||
if (sl->tvc->prepare(thd_arg, sl, tmp_result, this))
|
if (sl->tvc->prepare(thd, sl, tmp_result, this))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
else if (prepare_join(thd_arg, first_sl, tmp_result, additional_options,
|
else if (prepare_join(thd, first_sl, tmp_result, additional_options,
|
||||||
is_union_select))
|
is_union_select))
|
||||||
goto err;
|
goto err;
|
||||||
types= first_sl->item_list;
|
types= first_sl->item_list;
|
||||||
@ -947,10 +947,10 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
{
|
{
|
||||||
if (sl->tvc)
|
if (sl->tvc)
|
||||||
{
|
{
|
||||||
if (sl->tvc->prepare(thd_arg, sl, tmp_result, this))
|
if (sl->tvc->prepare(thd, sl, tmp_result, this))
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
else if (prepare_join(thd_arg, sl, tmp_result, additional_options,
|
else if (prepare_join(thd, sl, tmp_result, additional_options,
|
||||||
is_union_select))
|
is_union_select))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
@ -970,7 +970,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
{
|
{
|
||||||
if (with_element)
|
if (with_element)
|
||||||
{
|
{
|
||||||
if (derived->with->rename_columns_of_derived_unit(thd, this))
|
if (derived_arg->with->rename_columns_of_derived_unit(thd, this))
|
||||||
goto err;
|
goto err;
|
||||||
if (check_duplicate_names(thd, sl->item_list, 0))
|
if (check_duplicate_names(thd, sl->item_list, 0))
|
||||||
goto err;
|
goto err;
|
||||||
@ -981,7 +981,7 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
if (first_sl->item_list.elements != sl->item_list.elements)
|
if (first_sl->item_list.elements != sl->item_list.elements)
|
||||||
{
|
{
|
||||||
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
|
my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
|
||||||
ER_THD(thd_arg, ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),
|
ER_THD(thd, ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT),
|
||||||
MYF(0));
|
MYF(0));
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
@ -995,20 +995,20 @@ bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
|
|||||||
sl->next_select() == with_element->first_recursive))
|
sl->next_select() == with_element->first_recursive))
|
||||||
{
|
{
|
||||||
ulonglong create_options;
|
ulonglong create_options;
|
||||||
create_options= (first_sl->options | thd_arg->variables.option_bits |
|
create_options= (first_sl->options | thd->variables.option_bits |
|
||||||
TMP_TABLE_ALL_COLUMNS);
|
TMP_TABLE_ALL_COLUMNS);
|
||||||
// Join data types for all non-recursive parts of a recursive UNION
|
// Join data types for all non-recursive parts of a recursive UNION
|
||||||
if (join_union_item_types(thd, types, union_part_count + 1))
|
if (join_union_item_types(thd, types, union_part_count + 1))
|
||||||
goto err;
|
goto err;
|
||||||
if (union_result->create_result_table(thd, &types,
|
if (union_result->create_result_table(thd, &types,
|
||||||
MY_TEST(union_distinct),
|
MY_TEST(union_distinct),
|
||||||
create_options, &derived->alias,
|
create_options,
|
||||||
false,
|
&derived_arg->alias, false,
|
||||||
instantiate_tmp_table, false,
|
instantiate_tmp_table, false,
|
||||||
0))
|
0))
|
||||||
goto err;
|
goto err;
|
||||||
if (!derived->table)
|
if (!derived_arg->table)
|
||||||
derived->table= derived->derived_result->table=
|
derived_arg->table= derived_arg->derived_result->table=
|
||||||
with_element->rec_result->rec_tables.head();
|
with_element->rec_result->rec_tables.head();
|
||||||
with_element->mark_as_with_prepared_anchor();
|
with_element->mark_as_with_prepared_anchor();
|
||||||
is_rec_result_table_created= true;
|
is_rec_result_table_created= true;
|
||||||
@ -1079,7 +1079,7 @@ cont:
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
create_options= (first_sl->options | thd_arg->variables.option_bits |
|
create_options= (first_sl->options | thd->variables.option_bits |
|
||||||
TMP_TABLE_ALL_COLUMNS);
|
TMP_TABLE_ALL_COLUMNS);
|
||||||
/*
|
/*
|
||||||
Force the temporary table to be a MyISAM table if we're going to use
|
Force the temporary table to be a MyISAM table if we're going to use
|
||||||
@ -1107,7 +1107,7 @@ cont:
|
|||||||
Query_arena *arena, backup_arena;
|
Query_arena *arena, backup_arena;
|
||||||
arena= thd->activate_stmt_arena_if_needed(&backup_arena);
|
arena= thd->activate_stmt_arena_if_needed(&backup_arena);
|
||||||
|
|
||||||
intersect_mark= new (thd_arg->mem_root) Item_int(thd, 0);
|
intersect_mark= new (thd->mem_root) Item_int(thd, 0);
|
||||||
|
|
||||||
if (arena)
|
if (arena)
|
||||||
thd->restore_active_arena(arena, &backup_arena);
|
thd->restore_active_arena(arena, &backup_arena);
|
||||||
@ -1151,7 +1151,7 @@ cont:
|
|||||||
result_table_list.maybe_null_exec= save_maybe_null;
|
result_table_list.maybe_null_exec= save_maybe_null;
|
||||||
}
|
}
|
||||||
|
|
||||||
thd_arg->lex->current_select= lex_select_save;
|
thd->lex->current_select= lex_select_save;
|
||||||
if (!item_list.elements)
|
if (!item_list.elements)
|
||||||
{
|
{
|
||||||
Query_arena *arena, backup_arena;
|
Query_arena *arena, backup_arena;
|
||||||
@ -1191,7 +1191,7 @@ cont:
|
|||||||
*/
|
*/
|
||||||
fake_select_lex->item_list= item_list;
|
fake_select_lex->item_list= item_list;
|
||||||
|
|
||||||
thd_arg->lex->current_select= fake_select_lex;
|
thd->lex->current_select= fake_select_lex;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
We need to add up n_sum_items in order to make the correct
|
We need to add up n_sum_items in order to make the correct
|
||||||
@ -1219,12 +1219,12 @@ cont:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
thd_arg->lex->current_select= lex_select_save;
|
thd->lex->current_select= lex_select_save;
|
||||||
|
|
||||||
DBUG_RETURN(saved_error || thd_arg->is_fatal_error);
|
DBUG_RETURN(saved_error || thd->is_fatal_error);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
thd_arg->lex->current_select= lex_select_save;
|
thd->lex->current_select= lex_select_save;
|
||||||
(void) cleanup();
|
(void) cleanup();
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
@ -530,7 +530,7 @@ bool mysql_create_view(THD *thd, TABLE_LIST *views,
|
|||||||
|
|
||||||
/* prepare select to resolve all fields */
|
/* prepare select to resolve all fields */
|
||||||
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
|
lex->context_analysis_only|= CONTEXT_ANALYSIS_ONLY_VIEW;
|
||||||
if (unit->prepare(thd, 0, 0))
|
if (unit->prepare(unit->derived, 0, 0))
|
||||||
{
|
{
|
||||||
/*
|
/*
|
||||||
some errors from prepare are reported to user, if is not then
|
some errors from prepare are reported to user, if is not then
|
||||||
|
42
sql/table.cc
42
sql/table.cc
@ -8117,7 +8117,21 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view)
|
|||||||
(first_table && first_table->is_multitable()))
|
(first_table && first_table->is_multitable()))
|
||||||
set_multitable();
|
set_multitable();
|
||||||
|
|
||||||
unit->derived= this;
|
if (!unit->derived)
|
||||||
|
unit->derived= this;
|
||||||
|
else if (!is_with_table_recursive_reference() && unit->derived != this)
|
||||||
|
{
|
||||||
|
if (unit->derived->is_with_table_recursive_reference())
|
||||||
|
unit->derived= this;
|
||||||
|
else if (vers_conditions.eq(unit->derived->vers_conditions))
|
||||||
|
vers_conditions.empty();
|
||||||
|
else
|
||||||
|
{
|
||||||
|
my_error(ER_CONFLICTING_FOR_SYSTEM_TIME, MYF(0));
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (init_view && !view)
|
if (init_view && !view)
|
||||||
{
|
{
|
||||||
/* This is all what we can do for a derived table for now. */
|
/* This is all what we can do for a derived table for now. */
|
||||||
@ -8867,6 +8881,26 @@ void vers_select_conds_t::resolve_units(bool timestamps_only)
|
|||||||
end.resolve_unit(timestamps_only);
|
end.resolve_unit(timestamps_only);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool vers_select_conds_t::eq(const vers_select_conds_t &conds)
|
||||||
|
{
|
||||||
|
if (type != conds.type)
|
||||||
|
return false;
|
||||||
|
switch (type) {
|
||||||
|
case SYSTEM_TIME_UNSPECIFIED:
|
||||||
|
case SYSTEM_TIME_ALL:
|
||||||
|
return true;
|
||||||
|
case SYSTEM_TIME_BEFORE:
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
case SYSTEM_TIME_AS_OF:
|
||||||
|
return start.eq(conds.start);
|
||||||
|
case SYSTEM_TIME_FROM_TO:
|
||||||
|
case SYSTEM_TIME_BETWEEN:
|
||||||
|
return start.eq(conds.start) && end.eq(conds.end);
|
||||||
|
}
|
||||||
|
DBUG_ASSERT(0);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void Vers_history_point::resolve_unit(bool timestamps_only)
|
void Vers_history_point::resolve_unit(bool timestamps_only)
|
||||||
{
|
{
|
||||||
if (item && unit == VERS_UNDEFINED)
|
if (item && unit == VERS_UNDEFINED)
|
||||||
@ -8888,6 +8922,12 @@ void Vers_history_point::fix_item()
|
|||||||
item->decimals= 6;
|
item->decimals= 6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool Vers_history_point::eq(const vers_history_point_t &point)
|
||||||
|
{
|
||||||
|
return unit == point.unit && item->eq(point.item, false);
|
||||||
|
}
|
||||||
|
|
||||||
void Vers_history_point::print(String *str, enum_query_type query_type,
|
void Vers_history_point::print(String *str, enum_query_type query_type,
|
||||||
const char *prefix, size_t plen)
|
const char *prefix, size_t plen)
|
||||||
{
|
{
|
||||||
|
@ -1829,6 +1829,7 @@ public:
|
|||||||
void empty() { unit= VERS_UNDEFINED; item= NULL; }
|
void empty() { unit= VERS_UNDEFINED; item= NULL; }
|
||||||
void print(String *str, enum_query_type, const char *prefix, size_t plen);
|
void print(String *str, enum_query_type, const char *prefix, size_t plen);
|
||||||
void resolve_unit(bool timestamps_only);
|
void resolve_unit(bool timestamps_only);
|
||||||
|
bool eq(const vers_history_point_t &point);
|
||||||
};
|
};
|
||||||
|
|
||||||
struct vers_select_conds_t
|
struct vers_select_conds_t
|
||||||
@ -1878,6 +1879,7 @@ struct vers_select_conds_t
|
|||||||
{
|
{
|
||||||
return !from_query && type != SYSTEM_TIME_UNSPECIFIED;
|
return !from_query && type != SYSTEM_TIME_UNSPECIFIED;
|
||||||
}
|
}
|
||||||
|
bool eq(const vers_select_conds_t &conds);
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
Loading…
x
Reference in New Issue
Block a user