[Feat](Nereids) join hint support stage one (#27378)
support view as a independent unit of leading hint add random test check of leading hint query add more test with data of leading hint query add random test check of distribute hint
This commit is contained in:
622
docs/en/docs/query-acceleration/hint/joinHint.md
Normal file
622
docs/en/docs/query-acceleration/hint/joinHint.md
Normal file
@ -0,0 +1,622 @@
|
||||
# join hint using document
|
||||
|
||||
In the database, "Hint" is an instruction that instructs the query optimizer to execute a plan. By embedding hints in SQL statements, you can influence the optimizer's decision to select the desired execution path. Here is a background example using Hint:
|
||||
|
||||
Suppose you have a table that contains a large amount of data, and you know that in some specific circumstances, the join order of the tables in a query may affect query performance. Leading Hint allows you to specify the order of table joins that you want the optimizer to follow.
|
||||
|
||||
For example, consider the following SQL query:
|
||||
```sql
|
||||
mysql> explain shape plan select * from t1 join t2 on t1.c1 = c2;
|
||||
+-------------------------------------------+
|
||||
| Explain String |
|
||||
+-------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| --------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
+-------------------------------------------+
|
||||
7 rows in set (0.06 sec)
|
||||
```
|
||||
|
||||
In the above example, when the execution efficiency is not ideal, we want to adjust the join order without changing the original sql so as to avoid affecting the user's original scene and achieve the purpose of tuning. We can use leading to arbitrarily change the join order of tableA and tableB. For example, it could be written like:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t2 t1) */ * from t1 join t2 on c1 = c2;
|
||||
+-----------------------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+-----------------------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() build RFs:RF0 c1->[c2] |
|
||||
| --------PhysicalOlapScan[t2] apply RFs: RF0 |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t2 t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+-----------------------------------------------------------------------------------------------------+
|
||||
12 rows in set (0.06 sec)
|
||||
```
|
||||
In this example, the Hint /*+ leading(t2 t1) */ is used. This Hint tells the optimizer to use the specified table (t2) as the driver table in the execution plan, before (t1).
|
||||
|
||||
This document mainly describes how to use join related hints in Doris: leading hint, ordered hint and distribute hint
|
||||
# Leading hint
|
||||
Leading Hint is used to guide the optimizer in determining the join order of the query plan. In a query, the join order of the tables can affect query performance. Leading Hint allows you to specify the order of table joins that you want the optimizer to follow.
|
||||
|
||||
In doris, the syntax is /*+LEADING(tablespec [tablespec]... ) */,leading is surrounded by "/*+" and "*/" and placed directly behind the select in the select statement. Note that the '/' after leading and the selectlist need to be separated by at least one separator such as a space. At least two more tables need to be written before the leadinghint is justified. And any join can be bracketed to explicitly specify the shape of the joinTree. Example:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t2 t1) */ * from t1 join t2 on c1 = c2;
|
||||
+------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| --------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t2 t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+------------------------------------------------------------------------------+
|
||||
12 rows in set (0.01 sec)
|
||||
```
|
||||
- If the leadinghint fails to take effect, the explain process will be used to generate the leadinghint. The EXPLAIN process will display whether the Leadinghint takes effect. There are three types of hints:
|
||||
|
||||
- Used: leading hint takes effect normally
|
||||
|
||||
- Unused: Unsupported cases include the feature that the leading specified join order is not equivalent to the original sql or is not supported in this version (see restrictions).
|
||||
|
||||
- SyntaxError: indicates leading hint syntax errors, such as failure to find the corresponding table
|
||||
|
||||
- The leading hint syntax creates a left deep tree by default. For example, select /*+ leading(t1 t2 t3) */ * from t1 join t2 on... Specify by default
|
||||
```sql
|
||||
join
|
||||
/ \
|
||||
join t3
|
||||
/ \
|
||||
t1 t2
|
||||
|
||||
mysql> explain shape plan select /*+ leading(t1 t2 t3) */ * from t1 join t2 on c1 = c2 join t3 on c2=c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t1 t2 t3) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
15 rows in set (0.00 sec)
|
||||
```
|
||||
The join tree shape is also allowed to be specified using braces. For example: /*+ leading(t1 {t2 t3}) */
|
||||
```sql
|
||||
join
|
||||
/ \
|
||||
t1 join
|
||||
/ \
|
||||
t2 t3
|
||||
|
||||
mysql> explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 join t2 on c1 = c2 join t3 on c2=c3;
|
||||
+----------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+----------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| --------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t1 { t2 t3 }) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+----------------------------------------------------------------------------------+
|
||||
15 rows in set (0.02 sec)
|
||||
```
|
||||
|
||||
- When a view is used as an alias in joinReorder, the corresponding view can be specified as the leading parameter. Example:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(alias t1) */ count(*) from t1 join (select c2 from t2 join t3 on t2.c2 = t3.c3) as alias on t1.c1 = alias.c2;
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = alias.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ----------------PhysicalProject |
|
||||
| ------------------PhysicalOlapScan[t2] |
|
||||
| ----------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------------PhysicalProject |
|
||||
| --------------------PhysicalOlapScan[t3] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(alias t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
21 rows in set (0.06 sec)
|
||||
```
|
||||
## Basic cases
|
||||
(Note that the column name is related to the table name, for example: only t1 has c1 field, the following example will write t1.c1 directly to c1 for simplicity)
|
||||
```sql
|
||||
CREATE DATABASE testleading;
|
||||
USE testleading;
|
||||
|
||||
create table t1 (c1 int, c11 int) distributed by hash(c1) buckets 3 properties('replication_num' = '1');
|
||||
create table t2 (c2 int, c22 int) distributed by hash(c2) buckets 3 properties('replication_num' = '1');
|
||||
create table t3 (c3 int, c33 int) distributed by hash(c3) buckets 3 properties('replication_num' = '1');
|
||||
create table t4 (c4 int, c44 int) distributed by hash(c4) buckets 3 properties('replication_num' = '1');
|
||||
|
||||
```
|
||||
For a simple example, when we need to exchange the join order of t1 and t2, we only need to add leading(t2 t1) before it, which will be used in the explain
|
||||
Shows whether the hint is used.
|
||||
original plan
|
||||
```sql
|
||||
mysql> explain shape plan select * from t1 join t2 on t1.c1 = c2;
|
||||
+-------------------------------------------+
|
||||
| Explain String |
|
||||
+-------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| --------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
+-------------------------------------------+
|
||||
7 rows in set (0.06 sec)
|
||||
```
|
||||
Leading plan
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t2 t1) */ * from t1 join t2 on c1 = c2;
|
||||
+------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| --------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t2 t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+------------------------------------------------------------------------------+
|
||||
12 rows in set (0.00 sec)
|
||||
```
|
||||
hint effect display
|
||||
(Used unused)
|
||||
If the leading hint has a syntax error, the corresponding information is displayed in the syntax Error when explaining, but the plan is generated as usual, just without leading
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t2 t3) */ * from t1 join t2 on t1.c1 = c2;
|
||||
+--------------------------------------------------------+
|
||||
| Explain String |
|
||||
+--------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| --------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------PhysicalOlapScan[t2] |
|
||||
| |
|
||||
| Used: |
|
||||
| UnUsed: |
|
||||
| SyntaxError: leading(t2 t3) Msg:can not find table: t3 |
|
||||
+--------------------------------------------------------+
|
||||
11 rows in set (0.01 sec)
|
||||
```
|
||||
## more cases
|
||||
### Left deep tree
|
||||
leading generates a left deep tree by default when we don't use any parentheses
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 t2 t3) */ * from t1 join t2 on t1.c1 = c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t1 t2 t3) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
15 rows in set (0.10 sec)
|
||||
```
|
||||
### Right deep tree
|
||||
When we want to make the shape of the plan into a right deep tree, bushy tree or zigzag tree, we only need to add curly brackets to limit the shape of the plan, instead of using swap to adjust from the left deep tree step by step like oracle.
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 join t2 on t1.c1 = c2 join t3 on c2 = c3;
|
||||
+-----------------------------------------------+
|
||||
| Explain String |
|
||||
+-----------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| --------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------hashJoin[INNER_JOIN](t2.c2 = t3.c3) |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ------------PhysicalDistribute |
|
||||
| --------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Used: leading(t1 { t2 t3 }) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+-----------------------------------------------+
|
||||
14 rows in set (0.02 sec)
|
||||
```
|
||||
### Bushy tree
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading({t1 t2} {t3 t4}) */ * from t1 join t2 on t1.c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;
|
||||
+-----------------------------------------------+
|
||||
| Explain String |
|
||||
+-----------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t2.c2 = t3.c3) |
|
||||
| --------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| ----------PhysicalDistribute |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------hashJoin[INNER_JOIN](t3.c3 = t4.c4) |
|
||||
| ------------PhysicalOlapScan[t3] |
|
||||
| ------------PhysicalDistribute |
|
||||
| --------------PhysicalOlapScan[t4] |
|
||||
| |
|
||||
| Used: leading({ t1 t2 } { t3 t4 }) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+-----------------------------------------------+
|
||||
17 rows in set (0.02 sec)
|
||||
```
|
||||
### zig-zag tree
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 {t2 t3} t4) */ * from t1 join t2 on t1.c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t3.c3 = t4.c4)) otherCondition=() |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ------------PhysicalOlapScan[t1] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ----------------PhysicalOlapScan[t2] |
|
||||
| ----------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------------PhysicalOlapScan[t3] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t4] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t1 { t2 t3 } t4) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
19 rows in set (0.02 sec)
|
||||
```
|
||||
## Non-inner join:
|
||||
When non-inner-joins are encountered, such as Outer join or semi/anti join, leading hint automatically deduces the join mode of each join according to the original sql semantics. If leading hints that differ from the original sql semantics or cannot be generated, they are placed in unused, but do not affect the generation of the normal flow of the plan.
|
||||
|
||||
Here are examples of things that can't be exchanged:
|
||||
-------- test outer join which can not swap
|
||||
-- t1 leftjoin (t2 join t3 on (P23)) on (P12) != (t1 leftjoin t2 on (P12)) join t3 on (P23)
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: |
|
||||
| UnUsed: leading(t1 { t2 t3 }) |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
15 rows in set (0.01 sec)
|
||||
```
|
||||
Below are some examples that can be exchanged and examples that cannot be exchanged, which readers can verify for themselves
|
||||
```sql
|
||||
-------- test outer join which can swap
|
||||
-- (t1 leftjoin t2 on (P12)) innerjoin t3 on (P13) = (t1 innerjoin t3 on (P13)) leftjoin t2 on (P12)
|
||||
explain shape plan select * from t1 left join t2 on c1 = c2 join t3 on c1 = c3;
|
||||
explain shape plan select /*+ leading(t1 t3 t2) */ * from t1 left join t2 on c1 = c2 join t3 on c1 = c3;
|
||||
|
||||
-- (t1 leftjoin t2 on (P12)) leftjoin t3 on (P13) = (t1 leftjoin t3 on (P13)) leftjoin t2 on (P12)
|
||||
explain shape plan select * from t1 left join t2 on c1 = c2 left join t3 on c1 = c3;
|
||||
explain shape plan select /*+ leading(t1 t3 t2) */ * from t1 left join t2 on c1 = c2 left join t3 on c1 = c3;
|
||||
|
||||
-- (t1 leftjoin t2 on (P12)) leftjoin t3 on (P23) = t1 leftjoin (t2 leftjoin t3 on (P23)) on (P12)
|
||||
select /*+ leading(t2 t3 t1) SWAP_INPUT(t1) */ * from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;
|
||||
explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;
|
||||
explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;
|
||||
|
||||
-------- test outer join which can not swap
|
||||
-- t1 leftjoin (t2 join t3 on (P23)) on (P12) != (t1 leftjoin t2 on (P12)) join t3 on (P23)
|
||||
-- eliminated to inner join
|
||||
explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 join t3 on c2 = c3;
|
||||
explain graph select /*+ leading(t1 t2 t3) */ * from t1 left join (select * from t2 join t3 on c2 = c3) on c1 = c2;
|
||||
|
||||
-- test semi join
|
||||
explain shape plan select * from t1 where c1 in (select c2 from t2);
|
||||
explain shape plan select /*+ leading(t2 t1) */ * from t1 where c1 in (select c2 from t2);
|
||||
|
||||
-- test anti join
|
||||
explain shape plan select * from t1 where exists (select c2 from t2);
|
||||
```
|
||||
## View
|
||||
In the case of aliases, you can specify the alias as a complete subtree with joinOrder generated from text order.
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(alias t1) */ count(*) from t1 join (select c2 from t2 join t3 on t2.c2 = t3.c3) as alias on t1.c1 = alias.c2;
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = alias.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ----------------PhysicalProject |
|
||||
| ------------------PhysicalOlapScan[t2] |
|
||||
| ----------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------------PhysicalProject |
|
||||
| --------------------PhysicalOlapScan[t3] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(alias t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
21 rows in set (0.02 sec)
|
||||
```
|
||||
## mixed with ordered hint
|
||||
When ordered hint is used together with ordered hint, ordered hint takes effect with a higher priority than leading hint. Example:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ ORDERED LEADING(t1 t2 t3) */ t1.c1 from t2 join t1 on t1.c1 = t2.c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: ORDERED |
|
||||
| UnUsed: leading(t1 t2 t3) |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
18 rows in set (0.02 sec)
|
||||
```
|
||||
## Limitation
|
||||
- The current version supports only one leadingHint. If leadinghint is used with a subquery, the query will report an error. Example (This example explain will report an error, but will follow the normal path generation plan) :
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(alias t1) */ count(*) from t1 join (select /*+ leading(t3 t2) */ c2 from t2 join t3 on t2.c2 = t3.c3) as alias on t1.c1 = alias.c2;
|
||||
+----------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+----------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = alias.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ------------------PhysicalProject |
|
||||
| --------------------PhysicalOlapScan[t2] |
|
||||
| ------------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------------PhysicalProject |
|
||||
| ----------------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: |
|
||||
| UnUsed: leading(alias t1) |
|
||||
| SyntaxError: leading(t3 t2) Msg:one query block can only have one leading clause |
|
||||
+----------------------------------------------------------------------------------------+
|
||||
21 rows in set (0.01 sec)
|
||||
```
|
||||
# OrderedHint
|
||||
- Using ordered hint causes the join tree to be fixed in shape and displayed in text order
|
||||
- The syntax is /*+ ORDERED */,leading is surrounded by "/*+" and "*/" and placed directly behind the select in the select statement, for example:
|
||||
```sql
|
||||
explain shape plan select /*+ ORDERED */ t1.c1 from t2 join t1 on t1.c1 = t2.c2 join t3 on c2 = c3;
|
||||
join
|
||||
/ \
|
||||
join t3
|
||||
/ \
|
||||
t2 t1
|
||||
|
||||
mysql> explain shape plan select /*+ ORDERED */ t1.c1 from t2 join t1 on t1.c1 = t2.c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: ORDERED |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
18 rows in set (0.02 sec)
|
||||
```
|
||||
- When ordered hint and leading hint are used at the same time, the ordered hint prevails and the leading hint becomes invalid
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ ORDERED LEADING(t1 t2 t3) */ t1.c1 from t2 join t1 on t1.c1 = t2.c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: ORDERED |
|
||||
| UnUsed: leading(t1 t2 t3) |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
18 rows in set (0.02 sec)
|
||||
```
|
||||
# DistributeHint
|
||||
- Currently, only the distribute Type of the right table can be specified, and only two types are available: [shuffle] and [broadcast]. They are written before the right join table. Brackets and /*+ */ are allowed
|
||||
|
||||
- Currently you can use any DistributeHint
|
||||
|
||||
- When a DistributeHint whose plan cannot be correctly generated is not displayed, it takes effect based on maximum effort. Finally, the distribute mode that is displayed is mainly explained
|
||||
|
||||
- The current distribute version is not combined with leading. It takes effect only when the table specified in DISTRIBUTE is on the right of join.
|
||||
|
||||
- Mixed with ordered, the text order is used to set the join order and then specify the expected distribute mode in the corresponding join. Example:
|
||||
|
||||
Before use distribute hint:
|
||||
```sql
|
||||
mysql> explain shape plan select count(*) from t1 join t2 on t1.c1 = t2.c2;
|
||||
+----------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+----------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------PhysicalOlapScan[t2] |
|
||||
+----------------------------------------------------------------------------------+
|
||||
11 rows in set (0.01 sec)
|
||||
```
|
||||
|
||||
after use distribute hint:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ ordered */ count(*) from t2 join[broadcast] t1 on t1.c1 = t2.c2;
|
||||
+----------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+----------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t2] |
|
||||
| ------------PhysicalDistribute[DistributionSpecReplicated] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: ORDERED |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+----------------------------------------------------------------------------------+
|
||||
16 rows in set (0.01 sec)
|
||||
```
|
||||
- the Explain shape plan will display inside distribute operator related information, including DistributionSpecReplicated said the operator will be corresponding data into a copy of all be node, DistributionSpecGather indicates that data is gathered to fe nodes, and DistributionSpecHash indicates that data is dispersed to different be nodes according to a specific hashKey and algorithm.
|
||||
# To be supported
|
||||
- leadingHint indicates that the current query cannot be mixed with the subquery after it is promoted. A hint is required to control whether the subquery can be unnested
|
||||
|
||||
- A new distributeHint is needed for better and more complete control of the distribute operator
|
||||
|
||||
- Use leadingHint and distributeHint together to determine the shape of a join
|
||||
@ -39,6 +39,7 @@ grammar:
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
[hint_statement, ...]
|
||||
[ALL | DISTINCT | DISTINCTROW | ALL EXCEPT ( col_name1 [, col_name2, col_name3, ...] )]
|
||||
select_expr [, select_expr ...]
|
||||
[FROM table_references
|
||||
@ -86,6 +87,8 @@ SELECT
|
||||
11. SELECT supports explicit partition selection using PARTITION containing a list of partitions or subpartitions (or both) following the name of the table in `table_reference`
|
||||
|
||||
12. `[TABLET tids] TABLESAMPLE n [ROWS | PERCENT] [REPEATABLE seek]`: Limit the number of rows read from the table in the FROM clause, select a number of Tablets pseudo-randomly from the table according to the specified number of rows or percentages, and specify the number of seeds in REPEATABLE to return the selected samples again. In addition, you can also manually specify the TableID, Note that this can only be used for OLAP tables.
|
||||
|
||||
13. `hint_statement`: hint in front of the selectlist indicates that hints can be used to influence the behavior of the optimizer in order to obtain the desired execution plan. Details refer to [joinHint using document] (https://doris.apache.org/en/docs/query-acceleration/hint/joinHint.md)
|
||||
|
||||
**Syntax constraints:**
|
||||
|
||||
|
||||
607
docs/zh-CN/docs/query-acceleration/hint/joinHint.md
Normal file
607
docs/zh-CN/docs/query-acceleration/hint/joinHint.md
Normal file
@ -0,0 +1,607 @@
|
||||
# join hint 使用文档
|
||||
# 背景
|
||||
在数据库中,"Hint" 是一种用于指导查询优化器执行计划的指令。通过在SQL语句中嵌入Hint,可以影响优化器的决策,以选中期望的执行路径。以下是一个使用Hint的背景示例:
|
||||
假设有一个包含大量数据的表,而你知道在某些特定情况下,在一个查询中,表的连接顺序可能会影响查询性能。Leading Hint允许你指定希望优化器遵循的表连接的顺序。
|
||||
例如,考虑以下SQL查询:
|
||||
```sql
|
||||
mysql> explain shape plan select * from t1 join t2 on t1.c1 = c2;
|
||||
+-------------------------------------------+
|
||||
| Explain String |
|
||||
+-------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| --------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
+-------------------------------------------+
|
||||
7 rows in set (0.06 sec)
|
||||
```
|
||||
|
||||
在上述例子里面,在执行效率不理想的时候,我们希望调整下join顺序而不改变原始sql以免影响到用户原始场景且能达到调优的目的。我们可以使用leading任意改变tableA和tableB的join顺序。例如可以写成:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t2 t1) */ * from t1 join t2 on c1 = c2;
|
||||
+-----------------------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+-----------------------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() build RFs:RF0 c1->[c2] |
|
||||
| --------PhysicalOlapScan[t2] apply RFs: RF0 |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t2 t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+-----------------------------------------------------------------------------------------------------+
|
||||
12 rows in set (0.06 sec)
|
||||
```
|
||||
在这个例子中,使用了 /*+ leading(t2 t1) */ 这个Hint。这个Hint告诉优化器在执行计划中使用指定表(t2)作为驱动表,并置于(t1)之前。
|
||||
本文主要阐述如何在Doris里面使用join相关的hint:leading hint、ordered hint 和 distribute hint
|
||||
# Leading hint使用说明
|
||||
Leading Hint 用于指导优化器确定查询计划的连接顺序。在一个查询中,表的连接顺序可能会影响查询性能。Leading Hint允许你指定希望优化器遵循的表连接的顺序。
|
||||
在doris里面,其语法为 /*+LEADING( tablespec [ tablespec ]... ) */,leading由"/*+"和"*/"包围并置于select语句里面 select的正后方。注意,leading 后方的 '/' 和selectlist需要隔开至少一个分割符例如空格。至少需要写两个以上的表才认为这个leadinghint是合理的。且任意的join里面可以用大括号括号起来,来显式地指定joinTree的形状。例:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t2 t1) */ * from t1 join t2 on c1 = c2;
|
||||
+------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| --------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t2 t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+------------------------------------------------------------------------------+
|
||||
12 rows in set (0.01 sec)
|
||||
```
|
||||
- 当leadinghint不生效的时候会走正常的流程生成计划,explain会显示使用的hint是否生效,主要分三种来显示:
|
||||
- Used:leading hint正常生效
|
||||
- Unused: 这里不支持的情况包含leading指定的join order与原sql不等价或本版本暂不支持特性(详见限制)
|
||||
- SyntaxError: 指leading hint语法错误,如找不到对应的表等
|
||||
- leading hint语法默认造出来左深树,例:select /*+ leading(t1 t2 t3) */ * from t1 join t2 on...默认指定出来
|
||||
```sql
|
||||
join
|
||||
/ \
|
||||
join t3
|
||||
/ \
|
||||
t1 t2
|
||||
|
||||
mysql> explain shape plan select /*+ leading(t1 t2 t3) */ * from t1 join t2 on c1 = c2 join t3 on c2=c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t1 t2 t3) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
15 rows in set (0.00 sec)
|
||||
```
|
||||
|
||||
- 同时允许使用大括号指定join树形状。例:/*+ leading(t1 {t2 t3}) */
|
||||
join
|
||||
/ \
|
||||
t1 join
|
||||
/ \
|
||||
t2 t3
|
||||
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 join t2 on c1 = c2 join t3 on c2=c3;
|
||||
+----------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+----------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| --------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t1 { t2 t3 }) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+----------------------------------------------------------------------------------+
|
||||
15 rows in set (0.02 sec)
|
||||
```
|
||||
|
||||
- 当有view作为别名参与joinReorder的时候可以指定对应的view作为leading的参数。例:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(alias t1) */ count(*) from t1 join (select c2 from t2 join t3 on t2.c2 = t3.c3) as alias on t1.c1 = alias.c2;
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = alias.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ----------------PhysicalProject |
|
||||
| ------------------PhysicalOlapScan[t2] |
|
||||
| ----------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------------PhysicalProject |
|
||||
| --------------------PhysicalOlapScan[t3] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(alias t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
21 rows in set (0.06 sec)
|
||||
```
|
||||
## 基本用例
|
||||
(注意这里列命名和表命名相关,例:只有t1中有c1字段,后续例子为了简化会将 t1.c1 直接写成 c1)
|
||||
```sql
|
||||
CREATE DATABASE testleading;
|
||||
USE testleading;
|
||||
|
||||
create table t1 (c1 int, c11 int) distributed by hash(c1) buckets 3 properties('replication_num' = '1');
|
||||
create table t2 (c2 int, c22 int) distributed by hash(c2) buckets 3 properties('replication_num' = '1');
|
||||
create table t3 (c3 int, c33 int) distributed by hash(c3) buckets 3 properties('replication_num' = '1');
|
||||
create table t4 (c4 int, c44 int) distributed by hash(c4) buckets 3 properties('replication_num' = '1');
|
||||
|
||||
```
|
||||
举个简单的例子,当我们需要交换t1和t2的join顺序的时候只需要在前面加上leading(t2 t1)即可,explain的时候会
|
||||
显示是否用上了这个hint。
|
||||
原始plan
|
||||
```sql
|
||||
mysql> explain shape plan select * from t1 join t2 on t1.c1 = c2;
|
||||
+-------------------------------------------+
|
||||
| Explain String |
|
||||
+-------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| --------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
+-------------------------------------------+
|
||||
7 rows in set (0.06 sec)
|
||||
```
|
||||
Leading plan
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t2 t1) */ * from t1 join t2 on c1 = c2;
|
||||
+------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| --------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t2 t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+------------------------------------------------------------------------------+
|
||||
12 rows in set (0.00 sec)
|
||||
```
|
||||
hint 效果展示
|
||||
(Used unused)
|
||||
若leading hint有语法错误,explain的时候会在syntax error里面显示相应的信息,但是计划能照常生成,只不过没有使用leading而已
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t2 t3) */ * from t1 join t2 on t1.c1 = c2;
|
||||
+--------------------------------------------------------+
|
||||
| Explain String |
|
||||
+--------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| --------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------PhysicalOlapScan[t2] |
|
||||
| |
|
||||
| Used: |
|
||||
| UnUsed: |
|
||||
| SyntaxError: leading(t2 t3) Msg:can not find table: t3 |
|
||||
+--------------------------------------------------------+
|
||||
11 rows in set (0.01 sec)
|
||||
```
|
||||
## 扩展场景
|
||||
### 左深树
|
||||
当我们不使用任何括号的情况下leading会默认生成左深树
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 t2 t3) */ * from t1 join t2 on t1.c1 = c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t1 t2 t3) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
15 rows in set (0.10 sec)
|
||||
```
|
||||
### 右深树
|
||||
当我们想将计划的形状做成右深树或者bushy树或者zigzag树的时候,只需要加上大括号来限制plan的形状即可,不需要像oracle一样用swap从左深树一步步调整。
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 join t2 on t1.c1 = c2 join t3 on c2 = c3;
|
||||
+-----------------------------------------------+
|
||||
| Explain String |
|
||||
+-----------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| --------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------hashJoin[INNER_JOIN](t2.c2 = t3.c3) |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ------------PhysicalDistribute |
|
||||
| --------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Used: leading(t1 { t2 t3 }) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+-----------------------------------------------+
|
||||
14 rows in set (0.02 sec)
|
||||
```
|
||||
### Bushy 树
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading({t1 t2} {t3 t4}) */ * from t1 join t2 on t1.c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;
|
||||
+-----------------------------------------------+
|
||||
| Explain String |
|
||||
+-----------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN](t2.c2 = t3.c3) |
|
||||
| --------hashJoin[INNER_JOIN](t1.c1 = t2.c2) |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| ----------PhysicalDistribute |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute |
|
||||
| ----------hashJoin[INNER_JOIN](t3.c3 = t4.c4) |
|
||||
| ------------PhysicalOlapScan[t3] |
|
||||
| ------------PhysicalDistribute |
|
||||
| --------------PhysicalOlapScan[t4] |
|
||||
| |
|
||||
| Used: leading({ t1 t2 } { t3 t4 }) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+-----------------------------------------------+
|
||||
17 rows in set (0.02 sec)
|
||||
```
|
||||
### zig-zag 树
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 {t2 t3} t4) */ * from t1 join t2 on t1.c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t3.c3 = t4.c4)) otherCondition=() |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ------------PhysicalOlapScan[t1] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ----------------PhysicalOlapScan[t2] |
|
||||
| ----------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------------PhysicalOlapScan[t3] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t4] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(t1 { t2 t3 } t4) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
19 rows in set (0.02 sec)
|
||||
```
|
||||
## Non-inner join:
|
||||
当遇到非inner-join的时候,例如Outer join或者semi/anti join的时候,leading hint会根据原始sql语义自动推导各个join的join方式。若遇到与原始sql语义不同的leading hint或者生成不了的情况则会放到unused里面,但是不影响计划正常流程的生成。
|
||||
下面是不能交换的例子:
|
||||
-------- test outer join which can not swap
|
||||
-- t1 leftjoin (t2 join t3 on (P23)) on (P12) != (t1 leftjoin t2 on (P12)) join t3 on (P23)
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalOlapScan[t1] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: |
|
||||
| UnUsed: leading(t1 { t2 t3 }) |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
15 rows in set (0.01 sec)
|
||||
```
|
||||
下面是一些可以交换的例子和不能交换的例子,读者可自行验证
|
||||
```sql
|
||||
-------- test outer join which can swap
|
||||
-- (t1 leftjoin t2 on (P12)) innerjoin t3 on (P13) = (t1 innerjoin t3 on (P13)) leftjoin t2 on (P12)
|
||||
explain shape plan select * from t1 left join t2 on c1 = c2 join t3 on c1 = c3;
|
||||
explain shape plan select /*+ leading(t1 t3 t2) */ * from t1 left join t2 on c1 = c2 join t3 on c1 = c3;
|
||||
|
||||
-- (t1 leftjoin t2 on (P12)) leftjoin t3 on (P13) = (t1 leftjoin t3 on (P13)) leftjoin t2 on (P12)
|
||||
explain shape plan select * from t1 left join t2 on c1 = c2 left join t3 on c1 = c3;
|
||||
explain shape plan select /*+ leading(t1 t3 t2) */ * from t1 left join t2 on c1 = c2 left join t3 on c1 = c3;
|
||||
|
||||
-- (t1 leftjoin t2 on (P12)) leftjoin t3 on (P23) = t1 leftjoin (t2 leftjoin t3 on (P23)) on (P12)
|
||||
select /*+ leading(t2 t3 t1) SWAP_INPUT(t1) */ * from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;
|
||||
explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;
|
||||
explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;
|
||||
|
||||
-------- test outer join which can not swap
|
||||
-- t1 leftjoin (t2 join t3 on (P23)) on (P12) != (t1 leftjoin t2 on (P12)) join t3 on (P23)
|
||||
-- eliminated to inner join
|
||||
explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 join t3 on c2 = c3;
|
||||
explain graph select /*+ leading(t1 t2 t3) */ * from t1 left join (select * from t2 join t3 on c2 = c3) on c1 = c2;
|
||||
|
||||
-- test semi join
|
||||
explain shape plan select * from t1 where c1 in (select c2 from t2);
|
||||
explain shape plan select /*+ leading(t2 t1) */ * from t1 where c1 in (select c2 from t2);
|
||||
|
||||
-- test anti join
|
||||
explain shape plan select * from t1 where exists (select c2 from t2);
|
||||
```
|
||||
## View
|
||||
遇到别名的情况,可以将别名作为一个完整的子树进行指定,子树里面的joinOrder由文本序生成。
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(alias t1) */ count(*) from t1 join (select c2 from t2 join t3 on t2.c2 = t3.c3) as alias on t1.c1 = alias.c2;
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = alias.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ----------------PhysicalProject |
|
||||
| ------------------PhysicalOlapScan[t2] |
|
||||
| ----------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------------PhysicalProject |
|
||||
| --------------------PhysicalOlapScan[t3] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: leading(alias t1) |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------------+
|
||||
21 rows in set (0.02 sec)
|
||||
```
|
||||
## 与ordered混合使用
|
||||
当与ordered hint混合使用的时候以ordered hint为主,即ordered hint生效优先级高于leading hint。例:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ ORDERED LEADING(t1 t2 t3) */ t1.c1 from t2 join t1 on t1.c1 = t2.c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: ORDERED |
|
||||
| UnUsed: leading(t1 t2 t3) |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
18 rows in set (0.02 sec)
|
||||
```
|
||||
## 使用限制
|
||||
- 当前版本只支持使用一个leadingHint。若和子查询同时使用leadinghint的话则查询会报错。例(这个例子explain会报错,但是会走正常的路径生成计划):
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ leading(alias t1) */ count(*) from t1 join (select /*+ leading(t3 t2) */ c2 from t2 join t3 on t2.c2 = t3.c3) as alias on t1.c1 = alias.c2;
|
||||
+----------------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+----------------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = alias.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| ------------------PhysicalProject |
|
||||
| --------------------PhysicalOlapScan[t2] |
|
||||
| ------------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------------PhysicalProject |
|
||||
| ----------------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: |
|
||||
| UnUsed: leading(alias t1) |
|
||||
| SyntaxError: leading(t3 t2) Msg:one query block can only have one leading clause |
|
||||
+----------------------------------------------------------------------------------------+
|
||||
21 rows in set (0.01 sec)
|
||||
```
|
||||
# OrderedHint 使用说明
|
||||
- 使用ordered hint会让join tree的形状固定下来,按照文本序来显示
|
||||
- 语法为 /*+ ORDERED */,leading由"/*+"和"*/"包围并置于select语句里面 select的正后方,例:
|
||||
explain shape plan select /*+ ORDERED */ t1.c1 from t2 join t1 on t1.c1 = t2.c2 join t3 on c2 = c3;
|
||||
join
|
||||
/ \
|
||||
join t3
|
||||
/ \
|
||||
t2 t1
|
||||
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ ORDERED */ t1.c1 from t2 join t1 on t1.c1 = t2.c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: ORDERED |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
18 rows in set (0.02 sec)
|
||||
```
|
||||
- 当ordered hint和leading hint同时使用时以ordered hint为准,leading hint会失效
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ ORDERED LEADING(t1 t2 t3) */ t1.c1 from t2 join t1 on t1.c1 = t2.c2 join t3 on c2 = c3;
|
||||
+--------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+--------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --PhysicalDistribute[DistributionSpecGather] |
|
||||
| ----PhysicalProject |
|
||||
| ------hashJoin[INNER_JOIN] hashCondition=((t2.c2 = t3.c3)) otherCondition=() |
|
||||
| --------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t2] |
|
||||
| ----------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| --------PhysicalDistribute[DistributionSpecHash] |
|
||||
| ----------PhysicalProject |
|
||||
| ------------PhysicalOlapScan[t3] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: ORDERED |
|
||||
| UnUsed: leading(t1 t2 t3) |
|
||||
| SyntaxError: |
|
||||
+--------------------------------------------------------------------------------+
|
||||
18 rows in set (0.02 sec)
|
||||
```
|
||||
# DistributeHint 使用说明
|
||||
- 目前只能指定右表的distribute Type 而且只有[shuffle] 和 [broadcast]两种,写在join右表前面且允许中括号和/*+ */两种写法
|
||||
- 目前能使用任意个DistributeHint
|
||||
- 当遇到无法正确生成计划的 DistributeHint,没有显示,按最大努力生效,最后以explain显示的distribute方式为主
|
||||
- 当前版本暂不与leading混用,且当distribute指定的表位于join右边才可生效。
|
||||
- 多与ordered混用,利用文本序把join顺序固定下来,然后再指定相应的join里面我们预期使用什么样的distribute方式。例:
|
||||
使用前:
|
||||
```sql
|
||||
mysql> explain shape plan select count(*) from t1 join t2 on t1.c1 = t2.c2;
|
||||
+----------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+----------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t1] |
|
||||
| ------------PhysicalDistribute[DistributionSpecHash] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------PhysicalOlapScan[t2] |
|
||||
+----------------------------------------------------------------------------------+
|
||||
11 rows in set (0.01 sec)
|
||||
```
|
||||
|
||||
使用后:
|
||||
```sql
|
||||
mysql> explain shape plan select /*+ ordered */ count(*) from t2 join[broadcast] t1 on t1.c1 = t2.c2;
|
||||
+----------------------------------------------------------------------------------+
|
||||
| Explain String(Nereids Planner) |
|
||||
+----------------------------------------------------------------------------------+
|
||||
| PhysicalResultSink |
|
||||
| --hashAgg[GLOBAL] |
|
||||
| ----PhysicalDistribute[DistributionSpecGather] |
|
||||
| ------hashAgg[LOCAL] |
|
||||
| --------PhysicalProject |
|
||||
| ----------hashJoin[INNER_JOIN] hashCondition=((t1.c1 = t2.c2)) otherCondition=() |
|
||||
| ------------PhysicalProject |
|
||||
| --------------PhysicalOlapScan[t2] |
|
||||
| ------------PhysicalDistribute[DistributionSpecReplicated] |
|
||||
| --------------PhysicalProject |
|
||||
| ----------------PhysicalOlapScan[t1] |
|
||||
| |
|
||||
| Hint log: |
|
||||
| Used: ORDERED |
|
||||
| UnUsed: |
|
||||
| SyntaxError: |
|
||||
+----------------------------------------------------------------------------------+
|
||||
16 rows in set (0.01 sec)
|
||||
```
|
||||
- Explain shape plan里面会显示distribute算子相关的信息,其中DistributionSpecReplicated表示该算子将对应的数据变成所有be节点复制一份,DistributionSpecGather表示将数据gather到fe节点,DistributionSpecHash表示将数据按照特定的hashKey以及算法打散到不同的be节点。
|
||||
# 待支持
|
||||
- leadingHint待支持子查询解嵌套指定,当前和子查询提升以后不能混用,需要有hint来控制是否可以解嵌套
|
||||
- 需要新的distributeHint来更好且更全面地控制distribute算子
|
||||
- 混合使用leadingHint与distributeHint来共同确定join的形状
|
||||
@ -39,6 +39,7 @@ SELECT
|
||||
|
||||
```sql
|
||||
SELECT
|
||||
[hint_statement, ...]
|
||||
[ALL | DISTINCT | DISTINCTROW | ALL EXCEPT ( col_name1 [, col_name2, col_name3, ...] )]
|
||||
select_expr [, select_expr ...]
|
||||
[FROM table_references
|
||||
@ -87,6 +88,8 @@ SELECT
|
||||
|
||||
12. `[TABLET tids] TABLESAMPLE n [ROWS | PERCENT] [REPEATABLE seek]`: 在FROM子句中限制表的读取行数,根据指定的行数或百分比从表中伪随机的选择数个Tablet,REPEATABLE指定种子数可使选择的样本再次返回,此外也可手动指定TableID,注意这只能用于OLAP表。
|
||||
|
||||
13. `hint_statement`: 在selectlist前面使用hint表示可以通过hint去影响优化器的行为以期得到想要的执行计划,详情可参考[joinHint 使用文档](https://doris.apache.org/zh-CN/docs/query-acceleration/hint/joinHint.md)
|
||||
|
||||
**语法约束:**
|
||||
|
||||
1. SELECT也可用于检索计算的行而不引用任何表。
|
||||
|
||||
@ -27,6 +27,7 @@ import org.apache.doris.nereids.analyzer.UnboundOlapTableSink;
|
||||
import org.apache.doris.nereids.analyzer.UnboundOneRowRelation;
|
||||
import org.apache.doris.nereids.analyzer.UnboundRelation;
|
||||
import org.apache.doris.nereids.exceptions.AnalysisException;
|
||||
import org.apache.doris.nereids.hint.Hint;
|
||||
import org.apache.doris.nereids.jobs.Job;
|
||||
import org.apache.doris.nereids.jobs.JobContext;
|
||||
import org.apache.doris.nereids.jobs.executor.Analyzer;
|
||||
@ -114,6 +115,9 @@ public class CascadesContext implements ScheduleContext {
|
||||
private final Optional<CascadesContext> parent;
|
||||
|
||||
private final List<MaterializationContext> materializationContexts;
|
||||
private boolean isLeadingJoin = false;
|
||||
|
||||
private final Map<String, Hint> hintMap = Maps.newLinkedHashMap();
|
||||
|
||||
/**
|
||||
* Constructor of OptimizerContext.
|
||||
@ -615,4 +619,16 @@ public class CascadesContext implements ScheduleContext {
|
||||
p.value().setStatistics(updatedConsumerStats);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isLeadingJoin() {
|
||||
return isLeadingJoin;
|
||||
}
|
||||
|
||||
public void setLeadingJoin(boolean leadingJoin) {
|
||||
isLeadingJoin = leadingJoin;
|
||||
}
|
||||
|
||||
public Map<String, Hint> getHintMap() {
|
||||
return hintMap;
|
||||
}
|
||||
}
|
||||
|
||||
@ -68,7 +68,6 @@ import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@ -353,30 +352,30 @@ public class NereidsPlanner extends Planner {
|
||||
|
||||
/**
|
||||
* getting hints explain string, which specified by enumerate and show in lists
|
||||
* @param hintMap hint map recorded in statement context
|
||||
* @param hints hint map recorded in statement context
|
||||
* @return explain string shows using of hint
|
||||
*/
|
||||
public String getHintExplainString(Map<String, Hint> hintMap) {
|
||||
public String getHintExplainString(List<Hint> hints) {
|
||||
String used = "";
|
||||
String unUsed = "";
|
||||
String syntaxError = "";
|
||||
for (Map.Entry<String, Hint> entry : hintMap.entrySet()) {
|
||||
switch (entry.getValue().getStatus()) {
|
||||
for (Hint hint : hints) {
|
||||
switch (hint.getStatus()) {
|
||||
case UNUSED:
|
||||
unUsed = unUsed + " " + entry.getValue().getExplainString();
|
||||
unUsed = unUsed + " " + hint.getExplainString();
|
||||
break;
|
||||
case SYNTAX_ERROR:
|
||||
syntaxError = syntaxError + " " + entry.getValue().getExplainString()
|
||||
+ " Msg:" + entry.getValue().getErrorMessage();
|
||||
syntaxError = syntaxError + " " + hint.getExplainString()
|
||||
+ " Msg:" + hint.getErrorMessage();
|
||||
break;
|
||||
case SUCCESS:
|
||||
used = used + " " + entry.getValue().getExplainString();
|
||||
used = used + " " + hint.getExplainString();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return "\nUsed:" + used + "\nUnUsed:" + unUsed + "\nSyntaxError:" + syntaxError;
|
||||
return "\nHint log:" + "\nUsed:" + used + "\nUnUsed:" + unUsed + "\nSyntaxError:" + syntaxError;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -417,8 +416,8 @@ public class NereidsPlanner extends Planner {
|
||||
default:
|
||||
plan = super.getExplainString(explainOptions);
|
||||
}
|
||||
if (!statementContext.getHintMap().isEmpty()) {
|
||||
String hint = getHintExplainString(cascadesContext.getStatementContext().getHintMap());
|
||||
if (statementContext != null && !statementContext.getHints().isEmpty()) {
|
||||
String hint = getHintExplainString(statementContext.getHints());
|
||||
return plan + hint;
|
||||
}
|
||||
return plan;
|
||||
|
||||
@ -42,6 +42,7 @@ import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Sets;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -72,8 +73,6 @@ public class StatementContext {
|
||||
private boolean isDpHyp = false;
|
||||
private boolean isOtherJoinReorder = false;
|
||||
|
||||
private boolean isLeadingJoin = false;
|
||||
|
||||
private final IdGenerator<ExprId> exprIdGenerator = ExprId.createGenerator();
|
||||
private final IdGenerator<ObjectId> objectIdGenerator = ObjectId.createGenerator();
|
||||
private final IdGenerator<RelationId> relationIdGenerator = RelationId.createGenerator();
|
||||
@ -87,9 +86,10 @@ public class StatementContext {
|
||||
private final Map<CTEId, List<Pair<Map<Slot, Slot>, Group>>> cteIdToConsumerGroup = new HashMap<>();
|
||||
private final Map<CTEId, LogicalPlan> rewrittenCteProducer = new HashMap<>();
|
||||
private final Map<CTEId, LogicalPlan> rewrittenCteConsumer = new HashMap<>();
|
||||
private final Map<String, Hint> hintMap = Maps.newLinkedHashMap();
|
||||
private final Set<String> viewDdlSqlSet = Sets.newHashSet();
|
||||
|
||||
private final List<Hint> hints = new ArrayList<>();
|
||||
|
||||
public StatementContext() {
|
||||
this.connectContext = ConnectContext.get();
|
||||
}
|
||||
@ -147,14 +147,6 @@ public class StatementContext {
|
||||
isDpHyp = dpHyp;
|
||||
}
|
||||
|
||||
public boolean isLeadingJoin() {
|
||||
return isLeadingJoin;
|
||||
}
|
||||
|
||||
public void setLeadingJoin(boolean leadingJoin) {
|
||||
isLeadingJoin = leadingJoin;
|
||||
}
|
||||
|
||||
public boolean isOtherJoinReorder() {
|
||||
return isOtherJoinReorder;
|
||||
}
|
||||
@ -193,10 +185,6 @@ public class StatementContext {
|
||||
return supplier.get();
|
||||
}
|
||||
|
||||
public Map<String, Hint> getHintMap() {
|
||||
return hintMap;
|
||||
}
|
||||
|
||||
public ColumnAliasGenerator getColumnAliasGenerator() {
|
||||
return columnAliasGenerator == null
|
||||
? columnAliasGenerator = new ColumnAliasGenerator()
|
||||
@ -246,4 +234,12 @@ public class StatementContext {
|
||||
public List<String> getViewDdlSqls() {
|
||||
return ImmutableList.copyOf(viewDdlSqlSet);
|
||||
}
|
||||
|
||||
public void addHint(Hint hint) {
|
||||
this.hints.add(hint);
|
||||
}
|
||||
|
||||
public List<Hint> getHints() {
|
||||
return ImmutableList.copyOf(hints);
|
||||
}
|
||||
}
|
||||
|
||||
@ -31,6 +31,7 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalRelation;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalSubQueryAlias;
|
||||
import org.apache.doris.nereids.util.JoinUtils;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
@ -61,10 +62,14 @@ public class LeadingHint extends Hint {
|
||||
|
||||
private final List<Pair<Long, Expression>> filters = new ArrayList<>();
|
||||
|
||||
private final Map<Expression, JoinType> conditionJoinType = Maps.newLinkedHashMap();
|
||||
|
||||
private final List<JoinConstraint> joinConstraintList = new ArrayList<>();
|
||||
|
||||
private Long innerJoinBitmap = 0L;
|
||||
|
||||
private Long totalBitmap = 0L;
|
||||
|
||||
public LeadingHint(String hintName) {
|
||||
super(hintName);
|
||||
}
|
||||
@ -191,6 +196,30 @@ public class LeadingHint extends Hint {
|
||||
return filters;
|
||||
}
|
||||
|
||||
public void putConditionJoinType(Expression filter, JoinType joinType) {
|
||||
conditionJoinType.put(filter, joinType);
|
||||
}
|
||||
|
||||
/**
|
||||
* find out whether conditions can match original joinType
|
||||
* @param conditions conditions needs to put on this join
|
||||
* @param joinType join type computed by join constraint
|
||||
* @return can conditions matched
|
||||
*/
|
||||
public boolean isConditionJoinTypeMatched(List<Expression> conditions, JoinType joinType) {
|
||||
for (Expression condition : conditions) {
|
||||
JoinType originalJoinType = conditionJoinType.get(condition);
|
||||
if (originalJoinType.equals(joinType)
|
||||
|| originalJoinType.isOneSideOuterJoin() && joinType.isOneSideOuterJoin()
|
||||
|| originalJoinType.isSemiJoin() && joinType.isSemiJoin()
|
||||
|| originalJoinType.isAntiJoin() && joinType.isAntiJoin()) {
|
||||
continue;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public List<JoinConstraint> getJoinConstraintList() {
|
||||
return joinConstraintList;
|
||||
}
|
||||
@ -203,6 +232,31 @@ public class LeadingHint extends Hint {
|
||||
this.innerJoinBitmap = innerJoinBitmap;
|
||||
}
|
||||
|
||||
public Long getTotalBitmap() {
|
||||
return totalBitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* set total bitmap used in leading before we get into leading join
|
||||
*/
|
||||
public void setTotalBitmap() {
|
||||
Long totalBitmap = 0L;
|
||||
if (hasSameName()) {
|
||||
this.setStatus(HintStatus.SYNTAX_ERROR);
|
||||
this.setErrorMessage("duplicated table");
|
||||
}
|
||||
for (int index = 0; index < getTablelist().size(); index++) {
|
||||
RelationId id = findRelationIdAndTableName(getTablelist().get(index));
|
||||
if (id == null) {
|
||||
this.setStatus(HintStatus.SYNTAX_ERROR);
|
||||
this.setErrorMessage("can not find table: " + getTablelist().get(index));
|
||||
return;
|
||||
}
|
||||
totalBitmap = LongBitmap.set(totalBitmap, id.asInt());
|
||||
}
|
||||
this.totalBitmap = totalBitmap;
|
||||
}
|
||||
|
||||
/**
|
||||
* try to get join constraint, if can not get, it means join is inner join,
|
||||
* @param joinTableBitmap table bitmap below this join
|
||||
@ -218,6 +272,22 @@ public class LeadingHint extends Hint {
|
||||
JoinConstraint matchedJoinConstraint = null;
|
||||
|
||||
for (JoinConstraint joinConstraint : joinConstraintList) {
|
||||
if (joinConstraint.getJoinType().isFullOuterJoin()) {
|
||||
if (leftTableBitmap.equals(joinConstraint.getLeftHand())
|
||||
&& rightTableBitmap.equals(joinConstraint.getRightHand())
|
||||
|| rightTableBitmap.equals(joinConstraint.getLeftHand())
|
||||
&& leftTableBitmap.equals(joinConstraint.getRightHand())) {
|
||||
if (matchedJoinConstraint != null) {
|
||||
return Pair.of(null, false);
|
||||
}
|
||||
matchedJoinConstraint = joinConstraint;
|
||||
reversed = false;
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (!LongBitmap.isOverlap(joinConstraint.getMinRightHand(), joinTableBitmap)) {
|
||||
continue;
|
||||
}
|
||||
@ -337,7 +407,6 @@ public class LeadingHint extends Hint {
|
||||
* @return plan
|
||||
*/
|
||||
public Plan generateLeadingJoinPlan() {
|
||||
this.setStatus(HintStatus.SUCCESS);
|
||||
Stack<Pair<Integer, LogicalPlan>> stack = new Stack<>();
|
||||
int index = 0;
|
||||
LogicalPlan logicalPlan = getLogicalPlanByName(getTablelist().get(index));
|
||||
@ -365,8 +434,16 @@ public class LeadingHint extends Hint {
|
||||
getFilters(), newStackTop.second, logicalPlan);
|
||||
Pair<List<Expression>, List<Expression>> pair = JoinUtils.extractExpressionForHashTable(
|
||||
newStackTop.second.getOutput(), logicalPlan.getOutput(), conditions);
|
||||
// leading hint would set status inside if not success
|
||||
JoinType joinType = computeJoinType(getBitmap(newStackTop.second),
|
||||
getBitmap(logicalPlan), conditions);
|
||||
if (joinType == null) {
|
||||
this.setStatus(HintStatus.SYNTAX_ERROR);
|
||||
this.setErrorMessage("JoinType can not be null");
|
||||
} else if (!isConditionJoinTypeMatched(conditions, joinType)) {
|
||||
this.setStatus(HintStatus.UNUSED);
|
||||
this.setErrorMessage("condition does not matched joinType");
|
||||
}
|
||||
if (!this.isSuccess()) {
|
||||
return null;
|
||||
}
|
||||
@ -379,7 +456,13 @@ public class LeadingHint extends Hint {
|
||||
logicalPlan);
|
||||
logicalJoin.setBitmap(LongBitmap.or(getBitmap(newStackTop.second), getBitmap(logicalPlan)));
|
||||
if (stackTopLevel > 0) {
|
||||
stackTopLevel--;
|
||||
if (index < getTablelist().size()) {
|
||||
if (stackTopLevel > getLevellist().get(index)) {
|
||||
stackTopLevel--;
|
||||
}
|
||||
} else {
|
||||
stackTopLevel--;
|
||||
}
|
||||
}
|
||||
if (!stack.isEmpty()) {
|
||||
newStackTop = stack.peek();
|
||||
@ -401,17 +484,7 @@ public class LeadingHint extends Hint {
|
||||
|
||||
LogicalJoin finalJoin = (LogicalJoin) stack.pop().second;
|
||||
// we want all filters been remove
|
||||
if (!getFilters().isEmpty()) {
|
||||
List<Expression> conditions = getLastConditions(getFilters());
|
||||
Pair<List<Expression>, List<Expression>> pair = JoinUtils.extractExpressionForHashTable(
|
||||
finalJoin.left().getOutput(), finalJoin.right().getOutput(), conditions);
|
||||
finalJoin = new LogicalJoin<>(finalJoin.getJoinType(), pair.first,
|
||||
pair.second,
|
||||
JoinHint.NONE,
|
||||
Optional.empty(),
|
||||
finalJoin.left(),
|
||||
finalJoin.right());
|
||||
}
|
||||
assert (filters.isEmpty());
|
||||
if (finalJoin != null) {
|
||||
this.setStatus(HintStatus.SUCCESS);
|
||||
}
|
||||
@ -468,6 +541,8 @@ public class LeadingHint extends Hint {
|
||||
return getBitmap((LogicalPlan) root.child(0));
|
||||
} else if (root instanceof LogicalProject) {
|
||||
return getBitmap((LogicalPlan) root.child(0));
|
||||
} else if (root instanceof LogicalSubQueryAlias) {
|
||||
return LongBitmap.set(0L, (((LogicalSubQueryAlias) root).getRelationId().asInt()));
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
@ -484,11 +559,6 @@ public class LeadingHint extends Hint {
|
||||
this.setErrorMessage("duplicated table");
|
||||
return totalBitmap;
|
||||
}
|
||||
if (tables != null && getTablelist().size() != tables.size()) {
|
||||
this.setStatus(HintStatus.SYNTAX_ERROR);
|
||||
this.setErrorMessage("tables should be same as join tables");
|
||||
return totalBitmap;
|
||||
}
|
||||
for (int index = 0; index < getTablelist().size(); index++) {
|
||||
RelationId id = findRelationIdAndTableName(getTablelist().get(index));
|
||||
if (id == null) {
|
||||
|
||||
@ -0,0 +1,35 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.hint;
|
||||
|
||||
/**
|
||||
* ordered hint.
|
||||
*/
|
||||
public class OrderedHint extends Hint {
|
||||
|
||||
public OrderedHint(String hintName) {
|
||||
super(hintName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getExplainString() {
|
||||
StringBuilder out = new StringBuilder();
|
||||
out.append("ORDERED");
|
||||
return out.toString();
|
||||
}
|
||||
}
|
||||
@ -19,8 +19,6 @@ package org.apache.doris.nereids.jobs.executor;
|
||||
|
||||
import org.apache.doris.nereids.CascadesContext;
|
||||
import org.apache.doris.nereids.jobs.rewrite.RewriteJob;
|
||||
import org.apache.doris.nereids.processor.pre.EliminateLogicalSelectHint;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.analysis.AdjustAggregateNullableForEmptySet;
|
||||
import org.apache.doris.nereids.rules.analysis.AnalyzeCTE;
|
||||
import org.apache.doris.nereids.rules.analysis.BindExpression;
|
||||
@ -30,8 +28,12 @@ import org.apache.doris.nereids.rules.analysis.BindSink;
|
||||
import org.apache.doris.nereids.rules.analysis.CheckAfterBind;
|
||||
import org.apache.doris.nereids.rules.analysis.CheckAnalysis;
|
||||
import org.apache.doris.nereids.rules.analysis.CheckPolicy;
|
||||
import org.apache.doris.nereids.rules.analysis.CollectJoinConstraint;
|
||||
import org.apache.doris.nereids.rules.analysis.CollectSubQueryAlias;
|
||||
import org.apache.doris.nereids.rules.analysis.EliminateGroupByConstant;
|
||||
import org.apache.doris.nereids.rules.analysis.EliminateLogicalSelectHint;
|
||||
import org.apache.doris.nereids.rules.analysis.FillUpMissingSlots;
|
||||
import org.apache.doris.nereids.rules.analysis.LeadingJoin;
|
||||
import org.apache.doris.nereids.rules.analysis.NormalizeAggregate;
|
||||
import org.apache.doris.nereids.rules.analysis.NormalizeRepeat;
|
||||
import org.apache.doris.nereids.rules.analysis.OneRowRelationExtractAggregate;
|
||||
@ -41,6 +43,7 @@ import org.apache.doris.nereids.rules.analysis.ReplaceExpressionByChildOutput;
|
||||
import org.apache.doris.nereids.rules.analysis.ResolveOrdinalInOrderByAndGroupBy;
|
||||
import org.apache.doris.nereids.rules.analysis.SubqueryToApply;
|
||||
import org.apache.doris.nereids.rules.analysis.UserAuthentication;
|
||||
import org.apache.doris.nereids.rules.rewrite.JoinCommute;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
@ -84,9 +87,9 @@ public class Analyzer extends AbstractBatchJobExecutor {
|
||||
|
||||
private static List<RewriteJob> buildAnalyzeJobs(Optional<CustomTableResolver> customTableResolver) {
|
||||
return jobs(
|
||||
// we should eliminate hint after "Subquery unnesting" because some hint maybe exist in the CTE or subquery.
|
||||
custom(RuleType.ELIMINATE_HINT, EliminateLogicalSelectHint::new),
|
||||
// we should eliminate hint before "Subquery unnesting".
|
||||
topDown(new AnalyzeCTE()),
|
||||
topDown(new EliminateLogicalSelectHint()),
|
||||
bottomUp(
|
||||
new BindRelation(customTableResolver),
|
||||
new CheckPolicy(),
|
||||
@ -121,6 +124,12 @@ public class Analyzer extends AbstractBatchJobExecutor {
|
||||
bottomUp(new CheckAnalysis()),
|
||||
topDown(new EliminateGroupByConstant()),
|
||||
topDown(new NormalizeAggregate()),
|
||||
bottomUp(new JoinCommute()),
|
||||
bottomUp(
|
||||
new CollectSubQueryAlias(),
|
||||
new CollectJoinConstraint()
|
||||
),
|
||||
topDown(new LeadingJoin()),
|
||||
bottomUp(new SubqueryToApply())
|
||||
);
|
||||
}
|
||||
|
||||
@ -43,7 +43,6 @@ import org.apache.doris.nereids.rules.rewrite.CheckDataTypes;
|
||||
import org.apache.doris.nereids.rules.rewrite.CheckMatchExpression;
|
||||
import org.apache.doris.nereids.rules.rewrite.CheckMultiDistinct;
|
||||
import org.apache.doris.nereids.rules.rewrite.CollectFilterAboveConsumer;
|
||||
import org.apache.doris.nereids.rules.rewrite.CollectJoinConstraint;
|
||||
import org.apache.doris.nereids.rules.rewrite.CollectProjectAboveConsumer;
|
||||
import org.apache.doris.nereids.rules.rewrite.ColumnPruning;
|
||||
import org.apache.doris.nereids.rules.rewrite.ConvertInnerOrCrossJoin;
|
||||
@ -74,7 +73,7 @@ import org.apache.doris.nereids.rules.rewrite.InferFilterNotNull;
|
||||
import org.apache.doris.nereids.rules.rewrite.InferJoinNotNull;
|
||||
import org.apache.doris.nereids.rules.rewrite.InferPredicates;
|
||||
import org.apache.doris.nereids.rules.rewrite.InferSetOperatorDistinct;
|
||||
import org.apache.doris.nereids.rules.rewrite.LeadingJoin;
|
||||
import org.apache.doris.nereids.rules.rewrite.JoinCommute;
|
||||
import org.apache.doris.nereids.rules.rewrite.LimitSortToTopN;
|
||||
import org.apache.doris.nereids.rules.rewrite.MergeFilters;
|
||||
import org.apache.doris.nereids.rules.rewrite.MergeOneRowRelationIntoUnion;
|
||||
@ -106,7 +105,6 @@ import org.apache.doris.nereids.rules.rewrite.PushProjectIntoOneRowRelation;
|
||||
import org.apache.doris.nereids.rules.rewrite.PushProjectThroughUnion;
|
||||
import org.apache.doris.nereids.rules.rewrite.ReorderJoin;
|
||||
import org.apache.doris.nereids.rules.rewrite.RewriteCteChildren;
|
||||
import org.apache.doris.nereids.rules.rewrite.SemiJoinCommute;
|
||||
import org.apache.doris.nereids.rules.rewrite.SimplifyAggGroupBy;
|
||||
import org.apache.doris.nereids.rules.rewrite.SplitLimit;
|
||||
import org.apache.doris.nereids.rules.rewrite.TransposeSemiJoinAgg;
|
||||
@ -226,7 +224,7 @@ public class Rewriter extends AbstractBatchJobExecutor {
|
||||
),
|
||||
// push down SEMI Join
|
||||
bottomUp(
|
||||
new SemiJoinCommute(),
|
||||
new JoinCommute(),
|
||||
new TransposeSemiJoinLogicalJoin(),
|
||||
new TransposeSemiJoinLogicalJoinProject(),
|
||||
new TransposeSemiJoinAgg(),
|
||||
@ -240,15 +238,6 @@ public class Rewriter extends AbstractBatchJobExecutor {
|
||||
bottomUp(new EliminateNotNull()),
|
||||
topDown(new ConvertInnerOrCrossJoin())
|
||||
),
|
||||
topic("LEADING JOIN",
|
||||
bottomUp(
|
||||
new CollectJoinConstraint()
|
||||
),
|
||||
custom(RuleType.LEADING_JOIN, LeadingJoin::new),
|
||||
bottomUp(
|
||||
new ExpressionRewrite(CheckLegalityAfterRewrite.INSTANCE)
|
||||
)
|
||||
),
|
||||
topic("Column pruning and infer predicate",
|
||||
custom(RuleType.COLUMN_PRUNING, ColumnPruning::new),
|
||||
custom(RuleType.INFER_PREDICATES, InferPredicates::new),
|
||||
|
||||
@ -150,9 +150,17 @@ public class LongBitmap {
|
||||
return Long.numberOfTrailingZeros(bitmap);
|
||||
}
|
||||
|
||||
/**
|
||||
* use to calculate table bitmap
|
||||
* @param relationIdSet relationIds
|
||||
* @return bitmap
|
||||
*/
|
||||
public static Long computeTableBitmap(Set<RelationId> relationIdSet) {
|
||||
Long totalBitmap = 0L;
|
||||
for (RelationId id : relationIdSet) {
|
||||
if (id == null) {
|
||||
continue;
|
||||
}
|
||||
totalBitmap = LongBitmap.set(totalBitmap, (id.asInt()));
|
||||
}
|
||||
return totalBitmap;
|
||||
|
||||
@ -193,6 +193,7 @@ import org.apache.doris.nereids.exceptions.ParseException;
|
||||
import org.apache.doris.nereids.properties.OrderKey;
|
||||
import org.apache.doris.nereids.properties.SelectHint;
|
||||
import org.apache.doris.nereids.properties.SelectHintLeading;
|
||||
import org.apache.doris.nereids.properties.SelectHintOrdered;
|
||||
import org.apache.doris.nereids.properties.SelectHintSetVar;
|
||||
import org.apache.doris.nereids.trees.TableSample;
|
||||
import org.apache.doris.nereids.trees.expressions.Add;
|
||||
@ -2556,6 +2557,9 @@ public class LogicalPlanBuilder extends DorisParserBaseVisitor<Object> {
|
||||
}
|
||||
hints.put(hintName, new SelectHintLeading(hintName, leadingParameters));
|
||||
break;
|
||||
case "ordered":
|
||||
hints.put(hintName, new SelectHintOrdered(hintName));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -46,7 +46,6 @@ public class PlanPreprocessors {
|
||||
public List<PlanPreprocessor> getProcessors() {
|
||||
// add processor if we need
|
||||
return ImmutableList.of(
|
||||
new EliminateLogicalSelectHint(),
|
||||
new TurnOffPipelineForDml()
|
||||
);
|
||||
}
|
||||
|
||||
@ -0,0 +1,32 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.properties;
|
||||
|
||||
/**
|
||||
* select hint.
|
||||
*/
|
||||
public class SelectHintOrdered extends SelectHint {
|
||||
public SelectHintOrdered(String hintName) {
|
||||
super(hintName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return super.getHintName();
|
||||
}
|
||||
}
|
||||
@ -108,7 +108,10 @@ public enum RuleType {
|
||||
SIMPLIFY_AGG_GROUP_BY(RuleTypeClass.REWRITE),
|
||||
DISTINCT_AGGREGATE_DISASSEMBLE(RuleTypeClass.REWRITE),
|
||||
LOGICAL_SUB_QUERY_ALIAS_TO_LOGICAL_PROJECT(RuleTypeClass.REWRITE),
|
||||
COLLECT_SUB_QUERY_ALIAS(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_GROUP_BY_CONSTANT(RuleTypeClass.REWRITE),
|
||||
|
||||
ELIMINATE_LOGICAL_SELECT_HINT(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_ORDER_BY_CONSTANT(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_HINT(RuleTypeClass.REWRITE),
|
||||
ELIMINATE_JOIN_ON_EMPTYRELATION(RuleTypeClass.REWRITE),
|
||||
|
||||
@ -128,9 +128,8 @@ public class BindRelation extends OneAnalysisRuleFactory {
|
||||
if (analyzedCte.isPresent()) {
|
||||
LogicalCTEConsumer consumer = new LogicalCTEConsumer(unboundRelation.getRelationId(),
|
||||
cteContext.getCteId(), tableName, analyzedCte.get());
|
||||
if (cascadesContext.getStatementContext().isLeadingJoin()) {
|
||||
LeadingHint leading = (LeadingHint) cascadesContext.getStatementContext()
|
||||
.getHintMap().get("Leading");
|
||||
if (cascadesContext.isLeadingJoin()) {
|
||||
LeadingHint leading = (LeadingHint) cascadesContext.getHintMap().get("Leading");
|
||||
leading.putRelationIdAndTableName(Pair.of(consumer.getRelationId(), tableName));
|
||||
leading.getRelationIdToScanMap().put(consumer.getRelationId(), consumer);
|
||||
}
|
||||
@ -156,8 +155,8 @@ public class BindRelation extends OneAnalysisRuleFactory {
|
||||
|
||||
// TODO: should generate different Scan sub class according to table's type
|
||||
LogicalPlan scan = getLogicalPlan(table, unboundRelation, tableQualifier, cascadesContext);
|
||||
if (cascadesContext.getStatementContext().isLeadingJoin()) {
|
||||
LeadingHint leading = (LeadingHint) cascadesContext.getStatementContext().getHintMap().get("Leading");
|
||||
if (cascadesContext.isLeadingJoin()) {
|
||||
LeadingHint leading = (LeadingHint) cascadesContext.getHintMap().get("Leading");
|
||||
leading.putRelationIdAndTableName(Pair.of(unboundRelation.getRelationId(), tableName));
|
||||
leading.getRelationIdToScanMap().put(unboundRelation.getRelationId(), scan);
|
||||
}
|
||||
|
||||
@ -15,7 +15,7 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.rewrite;
|
||||
package org.apache.doris.nereids.rules.analysis;
|
||||
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.nereids.hint.Hint;
|
||||
@ -24,11 +24,11 @@ import org.apache.doris.nereids.hint.LeadingHint;
|
||||
import org.apache.doris.nereids.jobs.joinorder.hypergraph.bitmap.LongBitmap;
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.rewrite.RewriteRuleFactory;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.RelationId;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalFilter;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalOlapScan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
|
||||
@ -47,24 +47,17 @@ public class CollectJoinConstraint implements RewriteRuleFactory {
|
||||
@Override
|
||||
public List<Rule> buildRules() {
|
||||
return ImmutableList.of(
|
||||
logicalRelation().thenApply(ctx -> {
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext
|
||||
.getStatementContext().getHintMap().get("Leading");
|
||||
if (leading == null) {
|
||||
return ctx.root;
|
||||
} else if (leading.isSyntaxError()) {
|
||||
return ctx.root;
|
||||
}
|
||||
return ctx.root;
|
||||
}).toRule(RuleType.COLLECT_JOIN_CONSTRAINT),
|
||||
|
||||
logicalJoin().thenApply(ctx -> {
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext
|
||||
.getStatementContext().getHintMap().get("Leading");
|
||||
if (leading == null) {
|
||||
if (!ctx.cascadesContext.isLeadingJoin()) {
|
||||
return ctx.root;
|
||||
}
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext
|
||||
.getHintMap().get("Leading");
|
||||
LogicalJoin join = ctx.root;
|
||||
if (join.getJoinType().isNullAwareLeftAntiJoin()) {
|
||||
leading.setStatus(Hint.HintStatus.UNUSED);
|
||||
leading.setErrorMessage("condition does not matched joinType");
|
||||
}
|
||||
List<Expression> expressions = join.getHashJoinConjuncts();
|
||||
Long totalFilterBitMap = 0L;
|
||||
Long nonNullableSlotBitMap = 0L;
|
||||
@ -74,6 +67,7 @@ public class CollectJoinConstraint implements RewriteRuleFactory {
|
||||
Long filterBitMap = calSlotsTableBitMap(leading, expression.getInputSlots(), false);
|
||||
totalFilterBitMap = LongBitmap.or(totalFilterBitMap, filterBitMap);
|
||||
leading.getFilters().add(Pair.of(filterBitMap, expression));
|
||||
leading.putConditionJoinType(expression, join.getJoinType());
|
||||
}
|
||||
expressions = join.getOtherJoinConjuncts();
|
||||
for (Expression expression : expressions) {
|
||||
@ -82,6 +76,7 @@ public class CollectJoinConstraint implements RewriteRuleFactory {
|
||||
Long filterBitMap = calSlotsTableBitMap(leading, expression.getInputSlots(), false);
|
||||
totalFilterBitMap = LongBitmap.or(totalFilterBitMap, filterBitMap);
|
||||
leading.getFilters().add(Pair.of(filterBitMap, expression));
|
||||
leading.putConditionJoinType(expression, join.getJoinType());
|
||||
}
|
||||
Long leftHand = LongBitmap.computeTableBitmap(join.left().getInputRelations());
|
||||
Long rightHand = LongBitmap.computeTableBitmap(join.right().getInputRelations());
|
||||
@ -91,28 +86,13 @@ public class CollectJoinConstraint implements RewriteRuleFactory {
|
||||
return ctx.root;
|
||||
}).toRule(RuleType.COLLECT_JOIN_CONSTRAINT),
|
||||
|
||||
logicalFilter().thenApply(ctx -> {
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext
|
||||
.getStatementContext().getHintMap().get("Leading");
|
||||
if (leading == null) {
|
||||
return ctx.root;
|
||||
}
|
||||
LogicalFilter filter = ctx.root;
|
||||
Set<Expression> expressions = filter.getConjuncts();
|
||||
for (Expression expression : expressions) {
|
||||
Long filterBitMap = calSlotsTableBitMap(leading, expression.getInputSlots(), false);
|
||||
leading.getFilters().add(Pair.of(filterBitMap, expression));
|
||||
}
|
||||
return ctx.root;
|
||||
}).toRule(RuleType.COLLECT_JOIN_CONSTRAINT),
|
||||
|
||||
logicalProject(logicalOlapScan()).thenApply(
|
||||
ctx -> {
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext
|
||||
.getStatementContext().getHintMap().get("Leading");
|
||||
if (leading == null) {
|
||||
if (!ctx.cascadesContext.isLeadingJoin()) {
|
||||
return ctx.root;
|
||||
}
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext
|
||||
.getHintMap().get("Leading");
|
||||
LogicalProject<LogicalOlapScan> project = ctx.root;
|
||||
LogicalOlapScan scan = project.child();
|
||||
leading.getRelationIdToScanMap().put(scan.getRelationId(), project);
|
||||
@ -195,15 +175,11 @@ public class CollectJoinConstraint implements RewriteRuleFactory {
|
||||
if (getNotNullable && slot.nullable()) {
|
||||
continue;
|
||||
}
|
||||
if (!slot.isColumnFromTable()) {
|
||||
if (!slot.isColumnFromTable() && (slot.getQualifier() == null || slot.getQualifier().isEmpty())) {
|
||||
// we can not get info from column not from table
|
||||
continue;
|
||||
}
|
||||
String tableName = leading.getExprIdToTableNameMap().get(slot.getExprId());
|
||||
if (tableName == null) {
|
||||
tableName = slot.getQualifier().get(slot.getQualifier().size() - 1);
|
||||
leading.getExprIdToTableNameMap().put(slot.getExprId(), tableName);
|
||||
}
|
||||
String tableName = slot.getQualifier().get(slot.getQualifier().size() - 1);
|
||||
RelationId id = leading.findRelationIdAndTableName(tableName);
|
||||
if (id == null) {
|
||||
leading.setStatus(Hint.HintStatus.SYNTAX_ERROR);
|
||||
@ -0,0 +1,69 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.analysis;
|
||||
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.nereids.hint.LeadingHint;
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.rewrite.RewriteRuleFactory;
|
||||
import org.apache.doris.nereids.trees.plans.RelationId;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalCatalogRelation;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalRelation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Eliminate the logical sub query and alias node after analyze and before rewrite
|
||||
* If we match the alias node and return its child node, in the execute() of the job
|
||||
* <p>
|
||||
* TODO: refactor group merge strategy to support the feature above
|
||||
*/
|
||||
public class CollectSubQueryAlias implements RewriteRuleFactory {
|
||||
@Override
|
||||
public List<Rule> buildRules() {
|
||||
return ImmutableList.of(
|
||||
logicalSubQueryAlias().thenApply(ctx -> {
|
||||
if (ctx.cascadesContext.isLeadingJoin()) {
|
||||
String aliasName = ctx.root.getAlias();
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext.getHintMap().get("Leading");
|
||||
RelationId newId = ctx.statementContext.getNextRelationId();
|
||||
leading.putRelationIdAndTableName(Pair.of(newId, aliasName));
|
||||
leading.getRelationIdToScanMap().put(newId, ctx.root);
|
||||
ctx.root.setRelationId(newId);
|
||||
}
|
||||
return ctx.root;
|
||||
}).toRule(RuleType.COLLECT_JOIN_CONSTRAINT),
|
||||
logicalRelation().thenApply(ctx -> {
|
||||
if (ctx.cascadesContext.isLeadingJoin()) {
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext.getHintMap().get("Leading");
|
||||
LogicalRelation relation = (LogicalRelation) ctx.root;
|
||||
RelationId relationId = relation.getRelationId();
|
||||
if (ctx.root instanceof LogicalCatalogRelation) {
|
||||
String relationName = ((LogicalCatalogRelation) ctx.root).getTable().getName();
|
||||
leading.putRelationIdAndTableName(Pair.of(relationId, relationName));
|
||||
}
|
||||
leading.getRelationIdToScanMap().put(relationId, ctx.root);
|
||||
}
|
||||
return ctx.root;
|
||||
}).toRule(RuleType.COLLECT_JOIN_CONSTRAINT)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -15,22 +15,25 @@
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.processor.pre;
|
||||
package org.apache.doris.nereids.rules.analysis;
|
||||
|
||||
import org.apache.doris.analysis.SetVar;
|
||||
import org.apache.doris.analysis.StringLiteral;
|
||||
import org.apache.doris.common.DdlException;
|
||||
import org.apache.doris.nereids.CascadesContext;
|
||||
import org.apache.doris.nereids.StatementContext;
|
||||
import org.apache.doris.nereids.exceptions.AnalysisException;
|
||||
import org.apache.doris.nereids.hint.Hint;
|
||||
import org.apache.doris.nereids.hint.LeadingHint;
|
||||
import org.apache.doris.nereids.jobs.JobContext;
|
||||
import org.apache.doris.nereids.hint.OrderedHint;
|
||||
import org.apache.doris.nereids.properties.SelectHint;
|
||||
import org.apache.doris.nereids.properties.SelectHintLeading;
|
||||
import org.apache.doris.nereids.properties.SelectHintSetVar;
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalSelectHint;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.CustomRewriter;
|
||||
import org.apache.doris.qe.ConnectContext;
|
||||
import org.apache.doris.qe.SessionVariable;
|
||||
import org.apache.doris.qe.VariableMgr;
|
||||
@ -38,38 +41,44 @@ import org.apache.doris.qe.VariableMgr;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* eliminate set var hint, and set var to session variables.
|
||||
* eliminate logical select hint and set them to cascade context
|
||||
*/
|
||||
public class EliminateLogicalSelectHint extends PlanPreprocessor implements CustomRewriter {
|
||||
public class EliminateLogicalSelectHint extends OneRewriteRuleFactory {
|
||||
private Logger logger = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@Override
|
||||
public Plan rewriteRoot(Plan plan, JobContext jobContext) {
|
||||
return plan.accept(this, jobContext.getCascadesContext().getStatementContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public LogicalPlan visitLogicalSelectHint(
|
||||
LogicalSelectHint<? extends Plan> selectHintPlan,
|
||||
StatementContext context) {
|
||||
for (Entry<String, SelectHint> hint : selectHintPlan.getHints().entrySet()) {
|
||||
String hintName = hint.getKey();
|
||||
if (hintName.equalsIgnoreCase("SET_VAR")) {
|
||||
setVar((SelectHintSetVar) hint.getValue(), context);
|
||||
} else if (hintName.equalsIgnoreCase("ORDERED")) {
|
||||
ConnectContext.get().getSessionVariable().setDisableJoinReorder(true);
|
||||
} else if (hintName.equalsIgnoreCase("LEADING")) {
|
||||
extractLeading((SelectHintLeading) hint.getValue(), context);
|
||||
} else {
|
||||
logger.warn("Can not process select hint '{}' and skip it", hint.getKey());
|
||||
public Rule build() {
|
||||
return logicalSelectHint().thenApply(ctx -> {
|
||||
LogicalSelectHint<Plan> selectHintPlan = ctx.root;
|
||||
for (Entry<String, SelectHint> hint : selectHintPlan.getHints().entrySet()) {
|
||||
String hintName = hint.getKey();
|
||||
if (hintName.equalsIgnoreCase("SET_VAR")) {
|
||||
setVar((SelectHintSetVar) hint.getValue(), ctx.statementContext);
|
||||
} else if (hintName.equalsIgnoreCase("ORDERED")) {
|
||||
try {
|
||||
ctx.cascadesContext.getConnectContext().getSessionVariable()
|
||||
.disableNereidsJoinReorderOnce();
|
||||
} catch (DdlException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
OrderedHint ordered = new OrderedHint("Ordered");
|
||||
ordered.setStatus(Hint.HintStatus.SUCCESS);
|
||||
ctx.cascadesContext.getHintMap().put("Ordered", ordered);
|
||||
ctx.statementContext.addHint(ordered);
|
||||
} else if (hintName.equalsIgnoreCase("LEADING")) {
|
||||
extractLeading((SelectHintLeading) hint.getValue(), ctx.cascadesContext,
|
||||
ctx.statementContext, selectHintPlan.getHints());
|
||||
} else {
|
||||
logger.warn("Can not process select hint '{}' and skip it", hint.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (LogicalPlan) selectHintPlan.child();
|
||||
return selectHintPlan.child();
|
||||
}).toRule(RuleType.ELIMINATE_LOGICAL_SELECT_HINT);
|
||||
}
|
||||
|
||||
private void setVar(SelectHintSetVar selectHint, StatementContext context) {
|
||||
@ -84,7 +93,7 @@ public class EliminateLogicalSelectHint extends PlanPreprocessor implements Cust
|
||||
VariableMgr.setVar(sessionVariable, new SetVar(key, new StringLiteral(value.get())));
|
||||
} catch (Throwable t) {
|
||||
throw new AnalysisException("Can not set session variable '"
|
||||
+ key + "' = '" + value.get() + "'", t);
|
||||
+ key + "' = '" + value.get() + "'", t);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -101,15 +110,28 @@ public class EliminateLogicalSelectHint extends PlanPreprocessor implements Cust
|
||||
}
|
||||
}
|
||||
|
||||
private void extractLeading(SelectHintLeading selectHint, StatementContext context) {
|
||||
private void extractLeading(SelectHintLeading selectHint, CascadesContext context,
|
||||
StatementContext statementContext, Map<String, SelectHint> hints) {
|
||||
LeadingHint hint = new LeadingHint("Leading", selectHint.getParameters(), selectHint.toString());
|
||||
if (context.getHintMap().get("Leading") != null) {
|
||||
hint.setStatus(Hint.HintStatus.SYNTAX_ERROR);
|
||||
hint.setErrorMessage("can only have one leading clause");
|
||||
context.getHintMap().get("Leading").setStatus(Hint.HintStatus.UNUSED);
|
||||
hint.setErrorMessage("one query block can only have one leading clause");
|
||||
statementContext.addHint(hint);
|
||||
context.setLeadingJoin(false);
|
||||
return;
|
||||
}
|
||||
hint.setStatus(Hint.HintStatus.SUCCESS);
|
||||
statementContext.addHint(hint);
|
||||
context.getHintMap().put("Leading", hint);
|
||||
context.setLeadingJoin(true);
|
||||
if (hints.get("ordered") != null || ConnectContext.get().getSessionVariable().isDisableJoinReorder()) {
|
||||
context.setLeadingJoin(false);
|
||||
hint.setStatus(Hint.HintStatus.UNUSED);
|
||||
} else {
|
||||
context.setLeadingJoin(true);
|
||||
}
|
||||
assert (selectHint != null);
|
||||
assert (context != null);
|
||||
}
|
||||
|
||||
}
|
||||
@ -0,0 +1,69 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.analysis;
|
||||
|
||||
import org.apache.doris.common.DdlException;
|
||||
import org.apache.doris.nereids.hint.Hint;
|
||||
import org.apache.doris.nereids.hint.LeadingHint;
|
||||
import org.apache.doris.nereids.jobs.joinorder.hypergraph.bitmap.LongBitmap;
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.rewrite.RewriteRuleFactory;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.qe.ConnectContext;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Leading join is used to generate leading join and replace original logical join
|
||||
*/
|
||||
public class LeadingJoin implements RewriteRuleFactory {
|
||||
|
||||
@Override
|
||||
public List<Rule> buildRules() {
|
||||
return ImmutableList.of(
|
||||
logicalJoin()
|
||||
.whenNot(join -> ConnectContext.get().getSessionVariable().isDisableJoinReorder())
|
||||
.thenApply(ctx -> {
|
||||
if (!ctx.cascadesContext.isLeadingJoin()) {
|
||||
return ctx.root;
|
||||
}
|
||||
Hint leadingHint = ctx.cascadesContext.getHintMap().get("Leading");
|
||||
((LeadingHint) leadingHint).setTotalBitmap();
|
||||
Long currentBitMap = LongBitmap.computeTableBitmap(ctx.root.getInputRelations());
|
||||
if (((LeadingHint) leadingHint).getTotalBitmap().equals(currentBitMap)
|
||||
&& leadingHint.isSuccess()) {
|
||||
Plan leadingJoin = ((LeadingHint) leadingHint).generateLeadingJoinPlan();
|
||||
if (leadingHint.isSuccess() && leadingJoin != null) {
|
||||
try {
|
||||
ctx.cascadesContext.getConnectContext().getSessionVariable()
|
||||
.disableNereidsJoinReorderOnce();
|
||||
ctx.cascadesContext.setLeadingJoin(false);
|
||||
} catch (DdlException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
return leadingJoin;
|
||||
}
|
||||
}
|
||||
return ctx.root;
|
||||
}).toRule(RuleType.LEADING_JOIN)
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -17,15 +17,10 @@
|
||||
|
||||
package org.apache.doris.nereids.rules.analysis;
|
||||
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.nereids.hint.Hint;
|
||||
import org.apache.doris.nereids.hint.LeadingHint;
|
||||
import org.apache.doris.nereids.rules.Rule;
|
||||
import org.apache.doris.nereids.rules.RuleType;
|
||||
import org.apache.doris.nereids.rules.rewrite.OneRewriteRuleFactory;
|
||||
import org.apache.doris.nereids.trees.plans.RelationId;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalRelation;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
@ -42,24 +37,6 @@ public class LogicalSubQueryAliasToLogicalProject extends OneRewriteRuleFactory
|
||||
logicalSubQueryAlias().thenApply(ctx -> {
|
||||
LogicalProject project = new LogicalProject<>(
|
||||
ImmutableList.copyOf(ctx.root.getOutput()), ctx.root.child());
|
||||
if (ctx.cascadesContext.getStatementContext().isLeadingJoin()) {
|
||||
String aliasName = ctx.root.getAlias();
|
||||
LeadingHint leading = (LeadingHint) ctx.cascadesContext.getStatementContext()
|
||||
.getHintMap().get("Leading");
|
||||
if (!(project.child() instanceof LogicalRelation)) {
|
||||
if (leading.getTablelist().contains(aliasName)) {
|
||||
leading.setStatus(Hint.HintStatus.SYNTAX_ERROR);
|
||||
leading.setErrorMessage("Leading alias can only be table name alias");
|
||||
}
|
||||
} else {
|
||||
RelationId id = leading.findRelationIdAndTableName(aliasName);
|
||||
if (id == null) {
|
||||
id = ((LogicalRelation) project.child()).getRelationId();
|
||||
}
|
||||
leading.putRelationIdAndTableName(Pair.of(id, aliasName));
|
||||
leading.getRelationIdToScanMap().put(id, project);
|
||||
}
|
||||
}
|
||||
return project;
|
||||
})
|
||||
);
|
||||
|
||||
@ -24,8 +24,10 @@ import org.apache.doris.qe.ConnectContext;
|
||||
|
||||
/**
|
||||
* RightSemiJoin -> LeftSemiJoin
|
||||
* RightAntiJoin -> LeftAntiJoin
|
||||
* RightOuterJoin -> LeftOuterJoin
|
||||
*/
|
||||
public class SemiJoinCommute extends OneRewriteRuleFactory {
|
||||
public class JoinCommute extends OneRewriteRuleFactory {
|
||||
@Override
|
||||
public Rule build() {
|
||||
return logicalJoin()
|
||||
@ -1,84 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.rules.rewrite;
|
||||
|
||||
import org.apache.doris.common.DdlException;
|
||||
import org.apache.doris.nereids.hint.Hint;
|
||||
import org.apache.doris.nereids.hint.LeadingHint;
|
||||
import org.apache.doris.nereids.jobs.JobContext;
|
||||
import org.apache.doris.nereids.jobs.joinorder.hypergraph.bitmap.LongBitmap;
|
||||
import org.apache.doris.nereids.rules.rewrite.LeadingJoin.LeadingContext;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalPlan;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.CustomRewriter;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanRewriter;
|
||||
|
||||
/**
|
||||
* Leading join is used to generate leading join and replace original logical join
|
||||
*/
|
||||
public class LeadingJoin extends DefaultPlanRewriter<LeadingContext> implements CustomRewriter {
|
||||
|
||||
@Override
|
||||
public Plan rewriteRoot(Plan plan, JobContext jobContext) {
|
||||
if (jobContext.getCascadesContext().getStatementContext().isLeadingJoin()) {
|
||||
Hint leadingHint = jobContext.getCascadesContext().getStatementContext().getHintMap().get("Leading");
|
||||
Plan leadingPlan = plan.accept(this, new LeadingContext(
|
||||
(LeadingHint) leadingHint, ((LeadingHint) leadingHint)
|
||||
.getLeadingTableBitmap(jobContext.getCascadesContext().getTables())));
|
||||
if (leadingHint.isSuccess()) {
|
||||
try {
|
||||
jobContext.getCascadesContext().getConnectContext().getSessionVariable()
|
||||
.disableNereidsJoinReorderOnce();
|
||||
} catch (DdlException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
return plan;
|
||||
}
|
||||
return leadingPlan;
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Plan visit(Plan plan, LeadingContext context) {
|
||||
Long currentBitMap = LongBitmap.computeTableBitmap(plan.getInputRelations());
|
||||
if (LongBitmap.isSubset(currentBitMap, context.totalBitmap)
|
||||
&& plan instanceof LogicalJoin && !context.leading.isSyntaxError()) {
|
||||
Plan leadingJoin = context.leading.generateLeadingJoinPlan();
|
||||
if (context.leading.isSuccess() && leadingJoin != null) {
|
||||
return leadingJoin;
|
||||
}
|
||||
} else {
|
||||
return (LogicalPlan) super.visit(plan, context);
|
||||
}
|
||||
return plan;
|
||||
}
|
||||
|
||||
/** LeadingContext */
|
||||
public static class LeadingContext {
|
||||
public LeadingHint leading;
|
||||
public Long totalBitmap;
|
||||
|
||||
public LeadingContext(LeadingHint leading, Long totalBitmap) {
|
||||
this.leading = leading;
|
||||
this.totalBitmap = totalBitmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -17,10 +17,7 @@
|
||||
|
||||
package org.apache.doris.nereids.trees.copier;
|
||||
|
||||
import org.apache.doris.common.Pair;
|
||||
import org.apache.doris.nereids.exceptions.AnalysisException;
|
||||
import org.apache.doris.nereids.hint.Hint;
|
||||
import org.apache.doris.nereids.hint.LeadingHint;
|
||||
import org.apache.doris.nereids.properties.OrderKey;
|
||||
import org.apache.doris.nereids.trees.expressions.ExprId;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
@ -33,7 +30,6 @@ import org.apache.doris.nereids.trees.expressions.StatementScopeIdGenerator;
|
||||
import org.apache.doris.nereids.trees.expressions.SubqueryExpr;
|
||||
import org.apache.doris.nereids.trees.expressions.functions.Function;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.RelationId;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalAggregate;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalApply;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalAssertNumRows;
|
||||
@ -67,7 +63,6 @@ import org.apache.doris.nereids.trees.plans.logical.LogicalTopN;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalUnion;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalWindow;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.DefaultPlanRewriter;
|
||||
import org.apache.doris.qe.ConnectContext;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
@ -173,7 +168,6 @@ public class LogicalPlanDeepCopier extends DefaultPlanRewriter<DeepCopierContext
|
||||
olapScan.getManuallySpecifiedPartitions(), olapScan.getSelectedTabletIds(),
|
||||
olapScan.getHints(), olapScan.getTableSample());
|
||||
}
|
||||
updateLeadingRelationIdMap(newOlapScan.getRelationId(), newOlapScan.getTable().getName(), newOlapScan);
|
||||
newOlapScan.getOutput();
|
||||
context.putRelation(olapScan.getRelationId(), newOlapScan);
|
||||
updateReplaceMapWithOutput(olapScan, newOlapScan, context.exprIdReplaceMap);
|
||||
@ -200,7 +194,6 @@ public class LogicalPlanDeepCopier extends DefaultPlanRewriter<DeepCopierContext
|
||||
}
|
||||
LogicalSchemaScan newSchemaScan = new LogicalSchemaScan(StatementScopeIdGenerator.newRelationId(),
|
||||
schemaScan.getTable(), schemaScan.getQualifier());
|
||||
updateLeadingRelationIdMap(newSchemaScan.getRelationId(), newSchemaScan.getTable().getName(), newSchemaScan);
|
||||
updateReplaceMapWithOutput(schemaScan, newSchemaScan, context.exprIdReplaceMap);
|
||||
context.putRelation(schemaScan.getRelationId(), newSchemaScan);
|
||||
return newSchemaScan;
|
||||
@ -213,7 +206,6 @@ public class LogicalPlanDeepCopier extends DefaultPlanRewriter<DeepCopierContext
|
||||
}
|
||||
LogicalFileScan newFileScan = new LogicalFileScan(StatementScopeIdGenerator.newRelationId(),
|
||||
fileScan.getTable(), fileScan.getQualifier(), fileScan.getTableSample());
|
||||
updateLeadingRelationIdMap(newFileScan.getRelationId(), fileScan.getTable().getName(), newFileScan);
|
||||
updateReplaceMapWithOutput(fileScan, newFileScan, context.exprIdReplaceMap);
|
||||
context.putRelation(fileScan.getRelationId(), newFileScan);
|
||||
Set<Expression> conjuncts = fileScan.getConjuncts().stream()
|
||||
@ -241,7 +233,6 @@ public class LogicalPlanDeepCopier extends DefaultPlanRewriter<DeepCopierContext
|
||||
}
|
||||
LogicalJdbcScan newJdbcScan = new LogicalJdbcScan(StatementScopeIdGenerator.newRelationId(),
|
||||
jdbcScan.getTable(), jdbcScan.getQualifier());
|
||||
updateLeadingRelationIdMap(newJdbcScan.getRelationId(), jdbcScan.getTable().getName(), newJdbcScan);
|
||||
updateReplaceMapWithOutput(jdbcScan, newJdbcScan, context.exprIdReplaceMap);
|
||||
context.putRelation(jdbcScan.getRelationId(), newJdbcScan);
|
||||
return newJdbcScan;
|
||||
@ -255,7 +246,6 @@ public class LogicalPlanDeepCopier extends DefaultPlanRewriter<DeepCopierContext
|
||||
LogicalEsScan newEsScan = new LogicalEsScan(StatementScopeIdGenerator.newRelationId(),
|
||||
esScan.getTable(), esScan.getQualifier());
|
||||
updateReplaceMapWithOutput(esScan, newEsScan, context.exprIdReplaceMap);
|
||||
updateLeadingRelationIdMap(newEsScan.getRelationId(), esScan.getTable().getName(), newEsScan);
|
||||
context.putRelation(esScan.getRelationId(), newEsScan);
|
||||
return newEsScan;
|
||||
}
|
||||
@ -455,7 +445,6 @@ public class LogicalPlanDeepCopier extends DefaultPlanRewriter<DeepCopierContext
|
||||
StatementScopeIdGenerator.newRelationId(),
|
||||
cteConsumer.getCteId(), cteConsumer.getName(),
|
||||
consumerToProducerOutputMap, producerToConsumerOutputMap);
|
||||
updateLeadingRelationIdMap(newCTEConsumer.getRelationId(), cteConsumer.getName(), newCTEConsumer);
|
||||
context.putRelation(cteConsumer.getRelationId(), newCTEConsumer);
|
||||
return newCTEConsumer;
|
||||
}
|
||||
@ -474,12 +463,4 @@ public class LogicalPlanDeepCopier extends DefaultPlanRewriter<DeepCopierContext
|
||||
}
|
||||
}
|
||||
|
||||
private void updateLeadingRelationIdMap(RelationId id, String tableName, LogicalPlan plan) {
|
||||
if (!ConnectContext.get().getStatementContext().isLeadingJoin()) {
|
||||
return;
|
||||
}
|
||||
Hint leading = ConnectContext.get().getStatementContext().getHintMap().get("Leading");
|
||||
((LeadingHint) leading).updateRelationIdByTableName(Pair.of(id, tableName));
|
||||
((LeadingHint) leading).getRelationIdToScanMap().put(id, plan);
|
||||
}
|
||||
}
|
||||
|
||||
@ -185,10 +185,18 @@ public enum JoinType {
|
||||
return this == LEFT_SEMI_JOIN || this == RIGHT_SEMI_JOIN;
|
||||
}
|
||||
|
||||
public final boolean isAntiJoin() {
|
||||
return this == LEFT_ANTI_JOIN || this == RIGHT_ANTI_JOIN;
|
||||
}
|
||||
|
||||
public final boolean isOuterJoin() {
|
||||
return this == LEFT_OUTER_JOIN || this == RIGHT_OUTER_JOIN || this == FULL_OUTER_JOIN;
|
||||
}
|
||||
|
||||
public final boolean isOneSideOuterJoin() {
|
||||
return this == LEFT_OUTER_JOIN || this == RIGHT_OUTER_JOIN;
|
||||
}
|
||||
|
||||
public final boolean isRemainLeftJoin() {
|
||||
return this != RIGHT_SEMI_JOIN && this != RIGHT_ANTI_JOIN;
|
||||
}
|
||||
|
||||
@ -64,7 +64,6 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE extends
|
||||
private final JoinType joinType;
|
||||
private final List<Expression> otherJoinConjuncts;
|
||||
private final List<Expression> hashJoinConjuncts;
|
||||
private final JoinHint hint;
|
||||
|
||||
// When the predicate condition contains subqueries and disjunctions, the join will be marked as MarkJoin.
|
||||
private final Optional<MarkJoinSlotReference> markJoinSlotReference;
|
||||
@ -74,6 +73,8 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE extends
|
||||
// Table bitmap for tables below this join
|
||||
private long bitmap = LongBitmap.newBitmap();
|
||||
|
||||
private JoinHint hint;
|
||||
|
||||
public LogicalJoin(JoinType joinType, LEFT_CHILD_TYPE leftChild, RIGHT_CHILD_TYPE rightChild) {
|
||||
this(joinType, ExpressionUtils.EMPTY_CONDITION, ExpressionUtils.EMPTY_CONDITION, JoinHint.NONE,
|
||||
Optional.empty(), Optional.empty(), Optional.empty(), leftChild, rightChild);
|
||||
@ -216,6 +217,10 @@ public class LogicalJoin<LEFT_CHILD_TYPE extends Plan, RIGHT_CHILD_TYPE extends
|
||||
return hint;
|
||||
}
|
||||
|
||||
public void setHint(JoinHint hint) {
|
||||
this.hint = hint;
|
||||
}
|
||||
|
||||
public boolean isMarkJoin() {
|
||||
return markJoinSlotReference.isPresent();
|
||||
}
|
||||
|
||||
@ -24,11 +24,13 @@ import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.PlanType;
|
||||
import org.apache.doris.nereids.trees.plans.RelationId;
|
||||
import org.apache.doris.nereids.trees.plans.visitor.PlanVisitor;
|
||||
import org.apache.doris.nereids.util.Utils;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Sets;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
@ -36,6 +38,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
/**
|
||||
@ -45,6 +48,7 @@ import java.util.function.Supplier;
|
||||
*/
|
||||
public class LogicalSubQueryAlias<CHILD_TYPE extends Plan> extends LogicalUnary<CHILD_TYPE> {
|
||||
|
||||
protected RelationId relationId;
|
||||
private final List<String> qualifier;
|
||||
private final Optional<List<String>> columnAliases;
|
||||
|
||||
@ -170,4 +174,19 @@ public class LogicalSubQueryAlias<CHILD_TYPE extends Plan> extends LogicalUnary<
|
||||
builder.replace(replaceMap);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public void setRelationId(RelationId relationId) {
|
||||
this.relationId = relationId;
|
||||
}
|
||||
|
||||
public RelationId getRelationId() {
|
||||
return relationId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<RelationId> getInputRelations() {
|
||||
Set<RelationId> relationIdSet = Sets.newHashSet();
|
||||
relationIdSet.add(relationId);
|
||||
return relationIdSet;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,153 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
package org.apache.doris.nereids.jobs.joinorder.joinhint;
|
||||
|
||||
import org.apache.doris.nereids.CascadesContext;
|
||||
import org.apache.doris.nereids.datasets.tpch.TPCHTestBase;
|
||||
import org.apache.doris.nereids.properties.SelectHint;
|
||||
import org.apache.doris.nereids.properties.SelectHintLeading;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalProject;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalSelectHint;
|
||||
import org.apache.doris.nereids.util.HyperGraphBuilder;
|
||||
import org.apache.doris.nereids.util.MemoTestUtils;
|
||||
import org.apache.doris.nereids.util.PlanChecker;
|
||||
|
||||
import com.google.common.collect.Maps;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
public class JoinHintTest extends TPCHTestBase {
|
||||
|
||||
private int used = 0;
|
||||
private int unused = 0;
|
||||
|
||||
private int syntaxError = 0;
|
||||
|
||||
private int successCases = 0;
|
||||
|
||||
private int unsuccessCases = 0;
|
||||
|
||||
private List<String> failCases = new ArrayList<>();
|
||||
|
||||
@Test
|
||||
public void testLeading() {
|
||||
for (int t = 3; t < 10; t++) {
|
||||
for (int e = t - 1; e <= (t * (t - 1)) / 2; e++) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.out.println("TableNumber: " + String.valueOf(t) + " EdgeNumber: " + e + " Iteration: " + i);
|
||||
randomTest(t, e, false, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
int totalCases = successCases + unsuccessCases;
|
||||
System.out.println("TotalCases: " + totalCases + "\tSuccessCases: " + successCases + unsuccessCases + "\tUnSuccessCases: " + 0);
|
||||
for (String treePlan : failCases) {
|
||||
System.out.println(treePlan);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHintJoin() {
|
||||
for (int t = 3; t < 10; t++) {
|
||||
for (int e = t - 1; e <= (t * (t - 1)) / 2; e++) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
System.out.println("TableNumber: " + String.valueOf(t) + " EdgeNumber: " + e + " Iteration: " + i);
|
||||
randomTest(t, e, true, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
int totalCases = successCases + unsuccessCases;
|
||||
System.out.println("TotalCases: " + totalCases + "\tSuccessCases: " + successCases + "\tUnSuccessCases: " + unsuccessCases);
|
||||
for (String treePlan : failCases) {
|
||||
System.out.println(treePlan);
|
||||
}
|
||||
}
|
||||
|
||||
private Plan generateLeadingHintPlan(int tableNum, Plan childPlan) {
|
||||
Map<String, SelectHint> hints = Maps.newLinkedHashMap();
|
||||
List<String> leadingParameters = new ArrayList<String>();
|
||||
for (int i = 0; i < tableNum; i++) {
|
||||
leadingParameters.add(String.valueOf(i));
|
||||
}
|
||||
Collections.shuffle(leadingParameters);
|
||||
System.out.println("LeadingHint: " + leadingParameters.toString());
|
||||
hints.put("leading", new SelectHintLeading("leading", leadingParameters));
|
||||
return new LogicalSelectHint<>(hints, childPlan);
|
||||
}
|
||||
|
||||
private void randomTest(int tableNum, int edgeNum, boolean withJoinHint, boolean withLeading) {
|
||||
HyperGraphBuilder hyperGraphBuilder = new HyperGraphBuilder();
|
||||
Plan plan = withJoinHint ? hyperGraphBuilder.buildJoinPlanWithJoinHint(tableNum, edgeNum) :
|
||||
hyperGraphBuilder.randomBuildPlanWith(tableNum, edgeNum);
|
||||
plan = new LogicalProject(plan.getOutput(), plan);
|
||||
Set<List<String>> res1 = hyperGraphBuilder.evaluate(plan);
|
||||
if (!withLeading) {
|
||||
CascadesContext cascadesContext = MemoTestUtils.createCascadesContext(connectContext, plan);
|
||||
hyperGraphBuilder.initStats(cascadesContext);
|
||||
Plan optimizedPlan = PlanChecker.from(cascadesContext)
|
||||
.analyze()
|
||||
.optimize()
|
||||
.getBestPlanTree();
|
||||
|
||||
Set<List<String>> res2 = hyperGraphBuilder.evaluate(optimizedPlan);
|
||||
if (!res1.equals(res2)) {
|
||||
System.out.println(plan.treeString());
|
||||
System.out.println(optimizedPlan.treeString());
|
||||
cascadesContext = MemoTestUtils.createCascadesContext(connectContext, plan);
|
||||
PlanChecker.from(cascadesContext).dpHypOptimize().getBestPlanTree();
|
||||
System.out.println(res1);
|
||||
System.out.println(res2);
|
||||
unsuccessCases++;
|
||||
failCases.add(plan.treeString());
|
||||
failCases.add(optimizedPlan.treeString());
|
||||
}
|
||||
successCases++;
|
||||
} else {
|
||||
// generate select hint
|
||||
for (int i = 0; i < (tableNum * tableNum - 1); i++) {
|
||||
Plan leadingPlan = generateLeadingHintPlan(tableNum, plan);
|
||||
CascadesContext cascadesContext = MemoTestUtils.createCascadesContext(connectContext, leadingPlan);
|
||||
hyperGraphBuilder.initStats(cascadesContext);
|
||||
Plan optimizedPlan = PlanChecker.from(cascadesContext)
|
||||
.analyze()
|
||||
.optimize()
|
||||
.getBestPlanTree();
|
||||
|
||||
Set<List<String>> res2 = hyperGraphBuilder.evaluate(optimizedPlan);
|
||||
if (!res1.equals(res2)) {
|
||||
System.out.println(leadingPlan.treeString());
|
||||
System.out.println(optimizedPlan.treeString());
|
||||
cascadesContext = MemoTestUtils.createCascadesContext(connectContext, plan);
|
||||
PlanChecker.from(cascadesContext).dpHypOptimize().getBestPlanTree();
|
||||
System.out.println(res1);
|
||||
System.out.println(res2);
|
||||
unsuccessCases++;
|
||||
failCases.add(leadingPlan.treeString());
|
||||
failCases.add(optimizedPlan.treeString());
|
||||
}
|
||||
successCases++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -137,8 +137,10 @@ class PushDownLimitTest extends TestWithFeService implements MemoPatternMatchSup
|
||||
|
||||
@Test
|
||||
void testPushLimitThroughRightJoin() {
|
||||
ConnectContext context = MemoTestUtils.createConnectContext();
|
||||
context.getSessionVariable().setDisableJoinReorder(true);
|
||||
// after use RelationUtil to allocate relation id, the id will increase when getNextId() called.
|
||||
test(JoinType.RIGHT_OUTER_JOIN, true,
|
||||
testWithContext(context, JoinType.RIGHT_OUTER_JOIN, true,
|
||||
logicalLimit(
|
||||
logicalProject(
|
||||
rightOuterLogicalJoin(
|
||||
@ -148,7 +150,7 @@ class PushDownLimitTest extends TestWithFeService implements MemoPatternMatchSup
|
||||
)
|
||||
)
|
||||
);
|
||||
test(JoinType.RIGHT_OUTER_JOIN, false,
|
||||
testWithContext(context, JoinType.RIGHT_OUTER_JOIN, false,
|
||||
logicalLimit(
|
||||
rightOuterLogicalJoin(
|
||||
logicalOlapScan().when(s -> s.getTable().getName().equals("score")),
|
||||
@ -355,6 +357,15 @@ class PushDownLimitTest extends TestWithFeService implements MemoPatternMatchSup
|
||||
.matchesFromRoot(pattern);
|
||||
}
|
||||
|
||||
private void testWithContext(ConnectContext context, JoinType joinType, boolean hasProject, PatternDescriptor<? extends Plan> pattern) {
|
||||
Plan plan = generatePlan(joinType, hasProject);
|
||||
PlanChecker.from(context)
|
||||
.analyze(plan)
|
||||
.applyTopDown(new ConvertInnerOrCrossJoin())
|
||||
.applyTopDown(new PushDownLimit())
|
||||
.matchesFromRoot(pattern);
|
||||
}
|
||||
|
||||
private Plan generatePlan(JoinType joinType, boolean hasProject) {
|
||||
ImmutableList<Expression> joinConditions =
|
||||
joinType == JoinType.CROSS_JOIN || joinType == JoinType.INNER_JOIN
|
||||
|
||||
@ -50,9 +50,9 @@ public class InferTest extends SqlTestBase {
|
||||
.matches(
|
||||
logicalProject(
|
||||
innerLogicalJoin(
|
||||
logicalOlapScan(),
|
||||
logicalFilter().when(
|
||||
f -> f.getPredicate().toString().equals("((id#0 = 4) OR (id#0 > 4))")),
|
||||
logicalOlapScan()
|
||||
f -> f.getPredicate().toString().equals("((id#0 = 4) OR (id#0 > 4))"))
|
||||
)
|
||||
)
|
||||
);
|
||||
@ -89,8 +89,8 @@ public class InferTest extends SqlTestBase {
|
||||
.rewrite()
|
||||
.matches(
|
||||
innerLogicalJoin(
|
||||
leftSemiLogicalJoin(),
|
||||
logicalProject()
|
||||
logicalProject(),
|
||||
leftSemiLogicalJoin()
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@ -27,6 +27,7 @@ import org.apache.doris.nereids.trees.expressions.EqualTo;
|
||||
import org.apache.doris.nereids.trees.expressions.Expression;
|
||||
import org.apache.doris.nereids.trees.expressions.Slot;
|
||||
import org.apache.doris.nereids.trees.expressions.SlotReference;
|
||||
import org.apache.doris.nereids.trees.plans.JoinHint;
|
||||
import org.apache.doris.nereids.trees.plans.JoinType;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalJoin;
|
||||
@ -50,6 +51,7 @@ import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@ -115,7 +117,7 @@ public class HyperGraphBuilder {
|
||||
public Plan buildJoinPlan() {
|
||||
assert plans.size() == 1 : "there are cross join";
|
||||
Plan plan = plans.values().iterator().next();
|
||||
return buildPlanWithJoinType(plan, new BitSet());
|
||||
return buildPlanWithJoinType(plan, new BitSet(), false);
|
||||
}
|
||||
|
||||
public Plan randomBuildPlanWith(int tableNum, int edgeNum) {
|
||||
@ -128,6 +130,13 @@ public class HyperGraphBuilder {
|
||||
return this.build();
|
||||
}
|
||||
|
||||
public Plan buildJoinPlanWithJoinHint(int tableNum, int edgeNum) {
|
||||
randomBuildInit(tableNum, edgeNum);
|
||||
assert plans.size() == 1 : "there are cross join";
|
||||
Plan plan = plans.values().iterator().next();
|
||||
return buildPlanWithJoinType(plan, new BitSet(), true);
|
||||
}
|
||||
|
||||
private void randomBuildInit(int tableNum, int edgeNum) {
|
||||
Preconditions.checkArgument(edgeNum >= tableNum - 1,
|
||||
"We can't build a connected graph with %s tables %s edges", tableNum, edgeNum);
|
||||
@ -242,7 +251,7 @@ public class HyperGraphBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
private Plan buildPlanWithJoinType(Plan plan, BitSet requireTable) {
|
||||
private Plan buildPlanWithJoinType(Plan plan, BitSet requireTable, boolean withJoinHint) {
|
||||
if (!(plan instanceof LogicalJoin)) {
|
||||
return plan;
|
||||
}
|
||||
@ -269,11 +278,20 @@ public class HyperGraphBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
Plan left = buildPlanWithJoinType(join.left(), requireTable);
|
||||
Plan right = buildPlanWithJoinType(join.right(), requireTable);
|
||||
Plan left = buildPlanWithJoinType(join.left(), requireTable, withJoinHint);
|
||||
Plan right = buildPlanWithJoinType(join.right(), requireTable, withJoinHint);
|
||||
Set<Slot> outputs = Stream.concat(left.getOutput().stream(), right.getOutput().stream())
|
||||
.collect(Collectors.toSet());
|
||||
assert outputs.containsAll(requireSlots);
|
||||
if (withJoinHint) {
|
||||
JoinHint[] values = JoinHint.values();
|
||||
Random random = new Random();
|
||||
int randomIndex = random.nextInt(values.length);
|
||||
JoinHint hint = values[randomIndex];
|
||||
Plan hintJoin = ((LogicalJoin) join.withChildren(left, right)).withJoinType(joinType);
|
||||
((LogicalJoin) hintJoin).setHint(hint);
|
||||
return hintJoin;
|
||||
}
|
||||
return ((LogicalJoin) join.withChildren(left, right)).withJoinType(joinType);
|
||||
}
|
||||
|
||||
@ -528,6 +546,8 @@ public class HyperGraphBuilder {
|
||||
matchPair.stream().map(p -> Pair.of(p.second, p.first)).collect(Collectors.toList()));
|
||||
case NULL_AWARE_LEFT_ANTI_JOIN:
|
||||
return calLNAAJ(left, right, matchPair);
|
||||
case CROSS_JOIN:
|
||||
return calFOJ(left, right, matchPair);
|
||||
default:
|
||||
assert false;
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ import org.apache.doris.nereids.memo.GroupExpression;
|
||||
import org.apache.doris.nereids.memo.GroupId;
|
||||
import org.apache.doris.nereids.memo.Memo;
|
||||
import org.apache.doris.nereids.trees.plans.Plan;
|
||||
import org.apache.doris.nereids.trees.plans.logical.LogicalSelectHint;
|
||||
|
||||
import com.google.common.collect.Sets;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
@ -52,7 +53,7 @@ public class MemoValidator {
|
||||
|
||||
MemoValidator validator = validate(memo);
|
||||
if (initPlan != null) {
|
||||
if (initPlan instanceof UnboundResultSink) {
|
||||
if (initPlan instanceof UnboundResultSink || initPlan instanceof LogicalSelectHint) {
|
||||
return validator;
|
||||
}
|
||||
Assertions.assertEquals(initPlan, memo.getRoot().getLogicalExpression().getPlan());
|
||||
|
||||
1000
regression-test/data/nereids_p0/hint/t1.csv
Normal file
1000
regression-test/data/nereids_p0/hint/t1.csv
Normal file
File diff suppressed because it is too large
Load Diff
1000
regression-test/data/nereids_p0/hint/t2.csv
Normal file
1000
regression-test/data/nereids_p0/hint/t2.csv
Normal file
File diff suppressed because it is too large
Load Diff
1000
regression-test/data/nereids_p0/hint/t3.csv
Normal file
1000
regression-test/data/nereids_p0/hint/t3.csv
Normal file
File diff suppressed because it is too large
Load Diff
1000
regression-test/data/nereids_p0/hint/t4.csv
Normal file
1000
regression-test/data/nereids_p0/hint/t4.csv
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -1,223 +0,0 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you under the Apache License, Version 2.0 (the
|
||||
// "License"); you may not use this file except in compliance
|
||||
// with the License. You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing,
|
||||
// software distributed under the License is distributed on an
|
||||
// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
// KIND, either express or implied. See the License for the
|
||||
// specific language governing permissions and limitations
|
||||
// under the License.
|
||||
|
||||
suite("load") {
|
||||
String database = context.config.getDbNameByFile(context.file)
|
||||
sql "drop database if exists ${database}"
|
||||
sql "create database ${database}"
|
||||
sql "use ${database}"
|
||||
sql """
|
||||
drop table if exists lineitem;
|
||||
"""
|
||||
sql """
|
||||
CREATE TABLE lineitem (
|
||||
l_shipdate DATEV2 NOT NULL,
|
||||
l_orderkey bigint NOT NULL,
|
||||
l_linenumber int not null,
|
||||
l_partkey int NOT NULL,
|
||||
l_suppkey int not null,
|
||||
l_quantity decimal(15, 2) NOT NULL,
|
||||
l_extendedprice decimal(15, 2) NOT NULL,
|
||||
l_discount decimal(15, 2) NOT NULL,
|
||||
l_tax decimal(15, 2) NOT NULL,
|
||||
l_returnflag VARCHAR(1) NOT NULL,
|
||||
l_linestatus VARCHAR(1) NOT NULL,
|
||||
l_commitdate DATEV2 NOT NULL,
|
||||
l_receiptdate DATEV2 NOT NULL,
|
||||
l_shipinstruct VARCHAR(25) NOT NULL,
|
||||
l_shipmode VARCHAR(10) NOT NULL,
|
||||
l_comment VARCHAR(44) NOT NULL
|
||||
)ENGINE=OLAP
|
||||
DUPLICATE KEY(`l_shipdate`, `l_orderkey`)
|
||||
COMMENT "OLAP"
|
||||
DISTRIBUTED BY HASH(`l_orderkey`) BUCKETS 96
|
||||
PROPERTIES (
|
||||
"replication_num" = "1",
|
||||
"colocate_with" = "lineitem_orders"
|
||||
);
|
||||
"""
|
||||
|
||||
sql """
|
||||
drop table if exists orders;
|
||||
"""
|
||||
|
||||
sql '''
|
||||
CREATE TABLE orders (
|
||||
o_orderkey bigint NOT NULL,
|
||||
o_orderdate DATEV2 NOT NULL,
|
||||
o_custkey int NOT NULL,
|
||||
o_orderstatus VARCHAR(1) NOT NULL,
|
||||
o_totalprice decimal(15, 2) NOT NULL,
|
||||
o_orderpriority VARCHAR(15) NOT NULL,
|
||||
o_clerk VARCHAR(15) NOT NULL,
|
||||
o_shippriority int NOT NULL,
|
||||
o_comment VARCHAR(79) NOT NULL
|
||||
)ENGINE=OLAP
|
||||
DUPLICATE KEY(`o_orderkey`, `o_orderdate`)
|
||||
COMMENT "OLAP"
|
||||
DISTRIBUTED BY HASH(`o_orderkey`) BUCKETS 96
|
||||
PROPERTIES (
|
||||
"replication_num" = "1",
|
||||
"colocate_with" = "lineitem_orders"
|
||||
); '''
|
||||
|
||||
sql '''
|
||||
drop table if exists partsupp;
|
||||
'''
|
||||
|
||||
sql '''
|
||||
CREATE TABLE partsupp (
|
||||
ps_partkey int NOT NULL,
|
||||
ps_suppkey int NOT NULL,
|
||||
ps_availqty int NOT NULL,
|
||||
ps_supplycost decimal(15, 2) NOT NULL,
|
||||
ps_comment VARCHAR(199) NOT NULL
|
||||
)ENGINE=OLAP
|
||||
DUPLICATE KEY(`ps_partkey`)
|
||||
COMMENT "OLAP"
|
||||
DISTRIBUTED BY HASH(`ps_partkey`) BUCKETS 24
|
||||
PROPERTIES (
|
||||
"replication_num" = "1",
|
||||
"colocate_with" = "part_partsupp"
|
||||
);
|
||||
'''
|
||||
|
||||
sql '''
|
||||
drop table if exists part;
|
||||
'''
|
||||
|
||||
sql '''
|
||||
CREATE TABLE part (
|
||||
p_partkey int NOT NULL,
|
||||
p_name VARCHAR(55) NOT NULL,
|
||||
p_mfgr VARCHAR(25) NOT NULL,
|
||||
p_brand VARCHAR(10) NOT NULL,
|
||||
p_type VARCHAR(25) NOT NULL,
|
||||
p_size int NOT NULL,
|
||||
p_container VARCHAR(10) NOT NULL,
|
||||
p_retailprice decimal(15, 2) NOT NULL,
|
||||
p_comment VARCHAR(23) NOT NULL
|
||||
)ENGINE=OLAP
|
||||
DUPLICATE KEY(`p_partkey`)
|
||||
COMMENT "OLAP"
|
||||
DISTRIBUTED BY HASH(`p_partkey`) BUCKETS 24
|
||||
PROPERTIES (
|
||||
"replication_num" = "1",
|
||||
"colocate_with" = "part_partsupp"
|
||||
);
|
||||
'''
|
||||
|
||||
sql '''
|
||||
drop table if exists customer;
|
||||
'''
|
||||
|
||||
sql '''
|
||||
CREATE TABLE customer (
|
||||
c_custkey int NOT NULL,
|
||||
c_name VARCHAR(25) NOT NULL,
|
||||
c_address VARCHAR(40) NOT NULL,
|
||||
c_nationkey int NOT NULL,
|
||||
c_phone VARCHAR(15) NOT NULL,
|
||||
c_acctbal decimal(15, 2) NOT NULL,
|
||||
c_mktsegment VARCHAR(10) NOT NULL,
|
||||
c_comment VARCHAR(117) NOT NULL
|
||||
)ENGINE=OLAP
|
||||
DUPLICATE KEY(`c_custkey`)
|
||||
COMMENT "OLAP"
|
||||
DISTRIBUTED BY HASH(`c_custkey`) BUCKETS 24
|
||||
PROPERTIES (
|
||||
"replication_num" = "1"
|
||||
);
|
||||
'''
|
||||
|
||||
sql '''
|
||||
drop table if exists supplier
|
||||
'''
|
||||
|
||||
sql '''
|
||||
CREATE TABLE supplier (
|
||||
s_suppkey int NOT NULL,
|
||||
s_name VARCHAR(25) NOT NULL,
|
||||
s_address VARCHAR(40) NOT NULL,
|
||||
s_nationkey int NOT NULL,
|
||||
s_phone VARCHAR(15) NOT NULL,
|
||||
s_acctbal decimal(15, 2) NOT NULL,
|
||||
s_comment VARCHAR(101) NOT NULL
|
||||
)ENGINE=OLAP
|
||||
DUPLICATE KEY(`s_suppkey`)
|
||||
COMMENT "OLAP"
|
||||
DISTRIBUTED BY HASH(`s_suppkey`) BUCKETS 12
|
||||
PROPERTIES (
|
||||
"replication_num" = "1"
|
||||
);
|
||||
'''
|
||||
|
||||
sql '''
|
||||
drop table if exists nation;
|
||||
'''
|
||||
|
||||
sql '''
|
||||
CREATE TABLE `nation` (
|
||||
`n_nationkey` int(11) NOT NULL,
|
||||
`n_name` varchar(25) NOT NULL,
|
||||
`n_regionkey` int(11) NOT NULL,
|
||||
`n_comment` varchar(152) NULL
|
||||
) ENGINE=OLAP
|
||||
DUPLICATE KEY(`N_NATIONKEY`)
|
||||
COMMENT "OLAP"
|
||||
DISTRIBUTED BY HASH(`N_NATIONKEY`) BUCKETS 1
|
||||
PROPERTIES (
|
||||
"replication_num" = "1"
|
||||
);
|
||||
'''
|
||||
|
||||
sql '''
|
||||
drop table if exists region;
|
||||
'''
|
||||
|
||||
sql '''
|
||||
CREATE TABLE region (
|
||||
r_regionkey int NOT NULL,
|
||||
r_name VARCHAR(25) NOT NULL,
|
||||
r_comment VARCHAR(152)
|
||||
)ENGINE=OLAP
|
||||
DUPLICATE KEY(`r_regionkey`)
|
||||
COMMENT "OLAP"
|
||||
DISTRIBUTED BY HASH(`r_regionkey`) BUCKETS 1
|
||||
PROPERTIES (
|
||||
"replication_num" = "1"
|
||||
);
|
||||
'''
|
||||
|
||||
sql '''
|
||||
drop view if exists revenue0;
|
||||
'''
|
||||
|
||||
sql '''
|
||||
create view revenue0 (supplier_no, total_revenue) as
|
||||
select
|
||||
l_suppkey,
|
||||
sum(l_extendedprice * (1 - l_discount))
|
||||
from
|
||||
lineitem
|
||||
where
|
||||
l_shipdate >= date '1996-01-01'
|
||||
and l_shipdate < date '1996-01-01' + interval '3' month
|
||||
group by
|
||||
l_suppkey;
|
||||
'''
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q1") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
l_returnflag,
|
||||
l_linestatus,
|
||||
sum(l_quantity) as sum_qty,
|
||||
sum(l_extendedprice) as sum_base_price,
|
||||
sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
|
||||
sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
|
||||
avg(l_quantity) as avg_qty,
|
||||
avg(l_extendedprice) as avg_price,
|
||||
avg(l_discount) as avg_disc,
|
||||
count(*) as count_order
|
||||
from
|
||||
lineitem
|
||||
where
|
||||
l_shipdate <= date '1998-12-01' - interval '90' day
|
||||
group by
|
||||
l_returnflag,
|
||||
l_linestatus
|
||||
order by
|
||||
l_returnflag,
|
||||
l_linestatus;
|
||||
"""
|
||||
}
|
||||
@ -1,72 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q10") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
|
||||
|
||||
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(lineitem {{customer orders} nation}) */
|
||||
c_custkey,
|
||||
c_name,
|
||||
sum(l_extendedprice * (1 - l_discount)) as revenue,
|
||||
c_acctbal,
|
||||
n_name,
|
||||
c_address,
|
||||
c_phone,
|
||||
c_comment
|
||||
from
|
||||
customer,
|
||||
orders,
|
||||
lineitem,
|
||||
nation
|
||||
where
|
||||
c_custkey = o_custkey
|
||||
and l_orderkey = o_orderkey
|
||||
and o_orderdate >= date '1993-10-01'
|
||||
and o_orderdate < date '1993-10-01' + interval '3' month
|
||||
and l_returnflag = 'R'
|
||||
and c_nationkey = n_nationkey
|
||||
group by
|
||||
c_custkey,
|
||||
c_name,
|
||||
c_acctbal,
|
||||
c_phone,
|
||||
n_name,
|
||||
c_address,
|
||||
c_comment
|
||||
order by
|
||||
revenue desc
|
||||
limit 20;
|
||||
"""
|
||||
}
|
||||
@ -1,68 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q12") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
|
||||
|
||||
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(orders lineitem) */
|
||||
l_shipmode,
|
||||
sum(case
|
||||
when o_orderpriority = '1-URGENT'
|
||||
or o_orderpriority = '2-HIGH'
|
||||
then 1
|
||||
else 0
|
||||
end) as high_line_count,
|
||||
sum(case
|
||||
when o_orderpriority <> '1-URGENT'
|
||||
and o_orderpriority <> '2-HIGH'
|
||||
then 1
|
||||
else 0
|
||||
end) as low_line_count
|
||||
from
|
||||
orders,
|
||||
lineitem
|
||||
where
|
||||
o_orderkey = l_orderkey
|
||||
and l_shipmode in ('MAIL', 'SHIP')
|
||||
and l_commitdate < l_receiptdate
|
||||
and l_shipdate < l_commitdate
|
||||
and l_receiptdate >= date '1994-01-01'
|
||||
and l_receiptdate < date '1994-01-01' + interval '1' year
|
||||
group by
|
||||
l_shipmode
|
||||
order by
|
||||
l_shipmode;
|
||||
"""
|
||||
}
|
||||
@ -1,57 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q13") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(orders customer) */
|
||||
c_count,
|
||||
count(*) as custdist
|
||||
from
|
||||
(
|
||||
select
|
||||
c_custkey,
|
||||
count(o_orderkey) as c_count
|
||||
from
|
||||
customer left outer join orders on
|
||||
c_custkey = o_custkey
|
||||
and o_comment not like '%special%requests%'
|
||||
group by
|
||||
c_custkey
|
||||
) as c_orders
|
||||
group by
|
||||
c_count
|
||||
order by
|
||||
custdist desc,
|
||||
c_count desc;
|
||||
"""
|
||||
}
|
||||
@ -1,50 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q14") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(part lineitem) */
|
||||
100.00 * sum(case
|
||||
when p_type like 'PROMO%'
|
||||
then l_extendedprice * (1 - l_discount)
|
||||
else 0
|
||||
end) / sum(l_extendedprice * (1 - l_discount)) as promo_revenue
|
||||
from
|
||||
lineitem,
|
||||
part
|
||||
where
|
||||
l_partkey = p_partkey
|
||||
and l_shipdate >= date '1995-09-01'
|
||||
and l_shipdate < date '1995-09-01' + interval '1' month;
|
||||
"""
|
||||
}
|
||||
@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q16") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
|
||||
|
||||
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(partsupp part supplier) */
|
||||
p_brand,
|
||||
p_type,
|
||||
p_size,
|
||||
count(distinct ps_suppkey) as supplier_cnt
|
||||
from
|
||||
partsupp,
|
||||
part
|
||||
where
|
||||
p_partkey = ps_partkey
|
||||
and p_brand <> 'Brand#45'
|
||||
and p_type not like 'MEDIUM POLISHED%'
|
||||
and p_size in (49, 14, 23, 45, 19, 3, 36, 9)
|
||||
and ps_suppkey not in (
|
||||
select
|
||||
s_suppkey
|
||||
from
|
||||
supplier
|
||||
where
|
||||
s_comment like '%Customer%Complaints%'
|
||||
)
|
||||
group by
|
||||
p_brand,
|
||||
p_type,
|
||||
p_size
|
||||
order by
|
||||
supplier_cnt desc,
|
||||
p_brand,
|
||||
p_type,
|
||||
p_size;
|
||||
"""
|
||||
}
|
||||
@ -1,77 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q19") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
|
||||
|
||||
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(lineitem part) */
|
||||
sum(l_extendedprice* (1 - l_discount)) as revenue
|
||||
from
|
||||
lineitem,
|
||||
part
|
||||
where
|
||||
(
|
||||
p_partkey = l_partkey
|
||||
and p_brand = 'Brand#12'
|
||||
and p_container in ('SM CASE', 'SM BOX', 'SM PACK', 'SM PKG')
|
||||
and l_quantity >= 1 and l_quantity <= 1 + 10
|
||||
and p_size between 1 and 5
|
||||
and l_shipmode in ('AIR', 'AIR REG')
|
||||
and l_shipinstruct = 'DELIVER IN PERSON'
|
||||
)
|
||||
or
|
||||
(
|
||||
p_partkey = l_partkey
|
||||
and p_brand = 'Brand#23'
|
||||
and p_container in ('MED BAG', 'MED BOX', 'MED PKG', 'MED PACK')
|
||||
and l_quantity >= 10 and l_quantity <= 10 + 10
|
||||
and p_size between 1 and 10
|
||||
and l_shipmode in ('AIR', 'AIR REG')
|
||||
and l_shipinstruct = 'DELIVER IN PERSON'
|
||||
)
|
||||
or
|
||||
(
|
||||
p_partkey = l_partkey
|
||||
and p_brand = 'Brand#34'
|
||||
and p_container in ('LG CASE', 'LG BOX', 'LG PACK', 'LG PKG')
|
||||
and l_quantity >= 20 and l_quantity <= 20 + 10
|
||||
and p_size between 1 and 15
|
||||
and l_shipmode in ('AIR', 'AIR REG')
|
||||
and l_shipinstruct = 'DELIVER IN PERSON'
|
||||
);
|
||||
|
||||
"""
|
||||
}
|
||||
@ -1,67 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q3") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
// db = "tpch"
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(lineitem {orders customer}) */
|
||||
l_orderkey,
|
||||
sum(l_extendedprice * (1 - l_discount)) as revenue,
|
||||
o_orderdate,
|
||||
o_shippriority
|
||||
from
|
||||
customer,
|
||||
orders,
|
||||
lineitem
|
||||
where
|
||||
c_mktsegment = 'BUILDING'
|
||||
and c_custkey = o_custkey
|
||||
and l_orderkey = o_orderkey
|
||||
and o_orderdate < date '1995-03-15'
|
||||
and l_shipdate > date '1995-03-15'
|
||||
group by
|
||||
l_orderkey,
|
||||
o_orderdate,
|
||||
o_shippriority
|
||||
order by
|
||||
revenue desc,
|
||||
o_orderdate
|
||||
limit 10;
|
||||
"""
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q4") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
|
||||
|
||||
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(lineitem orders) */
|
||||
o_orderpriority,
|
||||
count(*) as order_count
|
||||
from
|
||||
orders
|
||||
where
|
||||
o_orderdate >= date '1993-07-01'
|
||||
and o_orderdate < date '1993-07-01' + interval '3' month
|
||||
and exists (
|
||||
select
|
||||
*
|
||||
from
|
||||
lineitem
|
||||
where
|
||||
l_orderkey = o_orderkey
|
||||
and l_commitdate < l_receiptdate
|
||||
)
|
||||
group by
|
||||
o_orderpriority
|
||||
order by
|
||||
o_orderpriority;
|
||||
"""
|
||||
}
|
||||
@ -1,63 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q5") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
sql "set ignore_shape_nodes='PhysicalDistribute,PhysicalProject'"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(lineitem {supplier {nation region}} orders customer) */
|
||||
n_name,
|
||||
sum(l_extendedprice * (1 - l_discount)) as revenue
|
||||
from
|
||||
customer,
|
||||
orders,
|
||||
lineitem,
|
||||
supplier,
|
||||
nation,
|
||||
region
|
||||
where
|
||||
c_custkey = o_custkey
|
||||
and l_orderkey = o_orderkey
|
||||
and l_suppkey = s_suppkey
|
||||
and c_nationkey = s_nationkey
|
||||
and s_nationkey = n_nationkey
|
||||
and n_regionkey = r_regionkey
|
||||
and r_name = 'ASIA'
|
||||
and o_orderdate >= date '1994-01-01'
|
||||
and o_orderdate < date '1994-01-01' + interval '1' year
|
||||
group by
|
||||
n_name
|
||||
order by
|
||||
revenue desc;
|
||||
"""
|
||||
}
|
||||
@ -1,45 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q6") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
|
||||
sql 'set global exec_mem_limit = 21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
sum(l_extendedprice * l_discount) as revenue
|
||||
from
|
||||
lineitem
|
||||
where
|
||||
l_shipdate >= date '1994-01-01'
|
||||
and l_shipdate < date '1994-01-01' + interval '1' year
|
||||
and l_discount between .06 - 0.01 and .06 + 0.01
|
||||
and l_quantity < 24;
|
||||
"""
|
||||
}
|
||||
@ -1,69 +0,0 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
suite("q9") {
|
||||
String db = context.config.getDbNameByFile(new File(context.file.parent))
|
||||
sql "use ${db}"
|
||||
sql 'set enable_nereids_planner=true'
|
||||
sql 'set enable_fallback_to_original_planner=false'
|
||||
sql "set runtime_filter_mode='GLOBAL'"
|
||||
sql 'set parallel_pipeline_task_num=8'
|
||||
sql 'set exec_mem_limit=21G'
|
||||
sql 'SET enable_pipeline_engine = true'
|
||||
|
||||
sql 'set be_number_for_test=3'
|
||||
sql "set enable_runtime_filter_prune=false"
|
||||
|
||||
qt_select """
|
||||
explain shape plan
|
||||
select
|
||||
/*+ leading(orders {{lineitem part} {supplier nation}} partsupp) */
|
||||
nation,
|
||||
o_year,
|
||||
sum(amount) as sum_profit
|
||||
from
|
||||
(
|
||||
select
|
||||
n_name as nation,
|
||||
extract(year from o_orderdate) as o_year,
|
||||
l_extendedprice * (1 - l_discount) - ps_supplycost * l_quantity as amount
|
||||
from
|
||||
part,
|
||||
supplier,
|
||||
lineitem,
|
||||
partsupp,
|
||||
orders,
|
||||
nation
|
||||
where
|
||||
s_suppkey = l_suppkey
|
||||
and ps_suppkey = l_suppkey
|
||||
and ps_partkey = l_partkey
|
||||
and p_partkey = l_partkey
|
||||
and o_orderkey = l_orderkey
|
||||
and s_nationkey = n_nationkey
|
||||
and p_name like '%green%'
|
||||
) as profit
|
||||
group by
|
||||
nation,
|
||||
o_year
|
||||
order by
|
||||
nation,
|
||||
o_year desc;
|
||||
"""
|
||||
}
|
||||
@ -38,80 +38,895 @@ suite("test_leading") {
|
||||
sql """create table t3 (c3 int, c33 int) distributed by hash(c3) buckets 3 properties('replication_num' = '1');"""
|
||||
sql """create table t4 (c4 int, c44 int) distributed by hash(c4) buckets 3 properties('replication_num' = '1');"""
|
||||
|
||||
sql '''
|
||||
alter table t1 modify column c1 set stats ('ndv'='1', 'avg_size'='1', 'max_size'='1', 'num_nulls'='0', 'min_value'='1', 'max_value'='1', 'row_count'='10000')
|
||||
'''
|
||||
sql '''
|
||||
alter table t2 modify column c2 set stats ('ndv'='1', 'avg_size'='1', 'max_size'='1', 'num_nulls'='0', 'min_value'='1', 'max_value'='1', 'row_count'='10000')
|
||||
'''
|
||||
sql '''
|
||||
alter table t3 modify column c3 set stats ('ndv'='1', 'avg_size'='1', 'max_size'='1', 'num_nulls'='0', 'min_value'='1', 'max_value'='1', 'row_count'='10000')
|
||||
'''
|
||||
sql '''
|
||||
alter table t4 modify column c4 set stats ('ndv'='1', 'avg_size'='1', 'max_size'='1', 'num_nulls'='0', 'min_value'='1', 'max_value'='1', 'row_count'='10000')
|
||||
'''
|
||||
streamLoad {
|
||||
table "t1"
|
||||
db "test_leading"
|
||||
set 'column_separator', '|'
|
||||
set 'format', 'csv'
|
||||
file 't1.csv'
|
||||
time 10000
|
||||
}
|
||||
|
||||
streamLoad {
|
||||
table "t2"
|
||||
db "test_leading"
|
||||
set 'column_separator', '|'
|
||||
set 'format', 'csv'
|
||||
file 't2.csv'
|
||||
time 10000
|
||||
}
|
||||
|
||||
streamLoad {
|
||||
table "t3"
|
||||
db "test_leading"
|
||||
set 'column_separator', '|'
|
||||
set 'format', 'csv'
|
||||
file 't3.csv'
|
||||
time 10000
|
||||
}
|
||||
|
||||
streamLoad {
|
||||
table "t4"
|
||||
db "test_leading"
|
||||
set 'column_separator', '|'
|
||||
set 'format', 'csv'
|
||||
file 't4.csv'
|
||||
time 10000
|
||||
}
|
||||
|
||||
//// check table count
|
||||
qt_select1_1 """select count(*) from t1;"""
|
||||
qt_select1_2 """select count(*) from t2;"""
|
||||
qt_select1_3 """select count(*) from t3;"""
|
||||
qt_select1_4 """select count(*) from t4;"""
|
||||
|
||||
//// test inner join with all edge and vertax is complete and equal predicates
|
||||
qt_select1 """explain shape plan select /*+ leading(t2 t1) */ * from t1 join t2 on c1 = c2;"""
|
||||
qt_select2 """explain shape plan select /*+ leading(t1 t2) */ * from t1 join t2 on c1 = c2;"""
|
||||
qt_select3 """explain shape plan select /*+ leading(t1 t2 t3) */ * from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select4 """explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select5 """explain shape plan select /*+ leading(t1 {t2 t3} t4) */ * from t1 join t2 on c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select6 """explain shape plan select /*+ leading({t1 t2} {t3 t4}) */ * from t1 join t2 on c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select2_1 """select count(*) from t1 join t2 on c1 = c2;"""
|
||||
qt_select2_2 """select /*+ leading(t2 t1) */ count(*) from t1 join t2 on c1 = c2;"""
|
||||
qt_select2_3 """select /*+ leading(t1 t2) */ count(*) from t1 join t2 on c1 = c2;"""
|
||||
|
||||
// test inner join with part of edge and need cross join
|
||||
qt_select7 """explain shape plan select /*+ leading({t1 t2} {t3 t4}) */ * from t1 join t2 on c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select3_1 """select count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_5 """select /*+ leading(t1 {t3 t2}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_6 """select /*+ leading(t2 t3 t1) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_7 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_8 """select /*+ leading(t2 t1 t3) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_9 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select3_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
|
||||
//// test outer join which can swap
|
||||
// (A leftjoin B on (Pab)) innerjoin C on (Pac) = (A innerjoin C on (Pac)) leftjoin B on (Pab)
|
||||
qt_select8 """explain shape plan select * from t1 left join t2 on c1 = c2 join t3 on c1 = c3;"""
|
||||
qt_select9 """explain shape plan select /*+ leading(t1 t3 t2) */ * from t1 left join t2 on c1 = c2 join t3 on c1 = c3;"""
|
||||
|
||||
// (A leftjoin B on (Pab)) leftjoin C on (Pac) = (A leftjoin C on (Pac)) leftjoin B on (Pab)
|
||||
qt_select10 """explain shape plan select * from t1 left join t2 on c1 = c2 left join t3 on c1 = c3;"""
|
||||
qt_select11 """explain shape plan select /*+ leading(t1 t3 t2) */ * from t1 left join t2 on c1 = c2 left join t3 on c1 = c3;"""
|
||||
qt_select4_1 """select count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select4_2 """select /*+ leading(t1 {t2 t3} t4) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select4_3 """select /*+ leading({t1 t2} {t3 t4}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select4_4 """select /*+ leading(t1 {t2 t3 t4}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select4_5 """select /*+ leading(t1 {t2 {t3 t4}}) */ count(*) from t1 join t2 on c1 = c2 join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
|
||||
qt_select5_1 """select count(*) from t1 join t2 on c1 > c2;"""
|
||||
qt_select5_2 """select /*+ leading(t2 t1) */ count(*) from t1 join t2 on c1 > c2;"""
|
||||
|
||||
qt_select6_1 """select count(*) from t1 join t2 on c1 > c2 join t3 on c2 > c3 where c1 < 100;"""
|
||||
qt_select6_2 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 > c2 join t3 on c2 > c3 where c1 < 100;"""
|
||||
|
||||
// (A leftjoin B on (Pab)) leftjoin C on (Pac) = (A leftjoin C on (Pac)) leftjoin B on (Pab)
|
||||
qt_select7_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 = c3;"""
|
||||
qt_select7_2 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 = c3;"""
|
||||
|
||||
qt_select8_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 = c3 where c1 between 100 and 300;"""
|
||||
qt_select8_2 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 = c3 where c1 between 100 and 300;"""
|
||||
|
||||
qt_select9_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 = c3 where c3 between 100 and 300;"""
|
||||
qt_select9_2 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 = c3 where c3 between 100 and 300;"""
|
||||
|
||||
qt_select10_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 = c3 where c2 between 100 and 300;"""
|
||||
qt_select10_2 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 = c3 where c2 between 100 and 300;"""
|
||||
|
||||
qt_select11_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 > c3 where c3 between 100 and 300;"""
|
||||
qt_select11_2 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c1 > c3 where c3 between 100 and 300;"""
|
||||
|
||||
// (A leftjoin B on (Pab)) leftjoin C on (Pbc) = A leftjoin (B leftjoin C on (Pbc)) on (Pab)
|
||||
qt_select12 """explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
|
||||
//// test outer join which can not swap
|
||||
qt_select12_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select12_2 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
|
||||
qt_select13_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 between 100 and 300;"""
|
||||
qt_select13_2 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 between 100 and 300;"""
|
||||
|
||||
qt_select14_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c2 between 100 and 300;"""
|
||||
qt_select14_2 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c2 between 100 and 300;"""
|
||||
|
||||
qt_select15_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c3 between 100 and 300;"""
|
||||
qt_select15_2 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c3 between 100 and 300;"""
|
||||
|
||||
//// test outer join which can not swap
|
||||
// A leftjoin (B join C on (Pbc)) on (Pab) != (A leftjoin B on (Pab)) join C on (Pbc) output should be unused when explain
|
||||
// this can be done because left join can be eliminated to inner join
|
||||
qt_select13 """explain shape plan select /*+ leading(t1 {t2 t3}) */ * from t1 left join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select16_1 """select count(*) from t1 left join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
qt_select16_2 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
|
||||
// this can not be done, expect not success but return right deep tree
|
||||
qt_select14 """explain shape plan select * from t1 left join (select * from t2 join t3 on c2 = c3) as tmp on c1 = c2;"""
|
||||
qt_select15 """explain shape plan select /*+ leading(t1 t2 t3) */ * from t1 left join (select * from t2 join t3 on c2 = c3) as tmp on c1 = c2;"""
|
||||
// inner join + full outer join
|
||||
qt_select17_1 """select count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
qt_select17_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 join t2 on c1 = c2 full join t3 on c2 = c3;"""
|
||||
|
||||
//// test semi join
|
||||
qt_select16 """explain shape plan select * from t1 where c1 in (select c2 from t2);"""
|
||||
qt_select17 """explain shape plan select /*+ leading(t2 t1) */ * from t1 where c1 in (select c2 from t2);"""
|
||||
// inner join + left outer join
|
||||
qt_select18_1 """select count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select18_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
|
||||
//// test anti join
|
||||
qt_select18 """explain shape plan select * from t1 where exists (select 1 from t2);"""
|
||||
qt_select19 """explain shape plan select /*+ leading (t2 t1) */ * from t1 where exists (select 1 from t2);"""
|
||||
// inner join + right outer join
|
||||
qt_select19_1 """select count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select19_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
|
||||
//// test cte
|
||||
// inline cte, change join order of tables inside cte
|
||||
qt_select20 """explain shape plan with cte as (select * from t1 join t2 on c1 = c2) select * from cte, t2;"""
|
||||
qt_select21 """explain shape plan with cte as (select * from t1 join t2 on c1 = c2) select /*+ leading(t2 t1 t3) */ * from cte, t3;"""
|
||||
// outside cte
|
||||
// inside and outside together (after unnest subquery)
|
||||
// inner join + semi join
|
||||
qt_select20_1 """select count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select20_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
|
||||
//// test syntax error and unsupported feature
|
||||
// not exist tables in leading: syntax error
|
||||
qt_select22 """explain shape plan select /*+ leading(t66 t1) */ * from t1 join t2 on c1 = c2;"""
|
||||
qt_select23 """explain shape plan select /*+ leading(t3 t1) */ * from t1 join t2 on c1 = c2;"""
|
||||
// subquery alias as leading table
|
||||
qt_select24 """explain shape plan with cte as (select * from t1 join t2 on c1 = c2) select /*+ leading(t2 cte t1) */ * from cte, t2;"""
|
||||
// do not have all tables inside hint
|
||||
qt_select25 """explain shape plan select /*+ leading(t1 t2) */ * from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
// duplicated table
|
||||
qt_select26 """explain shape plan select /*+ leading(t1 t1 t2 t3) */ * from t1 join t2 on c1 = c2 join t3 on c2 = c3;"""
|
||||
// inner join + anti join
|
||||
qt_select21_1 """select count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select21_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
|
||||
//// test table alias
|
||||
qt_select27 """explain shape plan select /*+ leading(t1 t_2) */ * from t1 join t2 t_2 on c1 = c2;"""
|
||||
qt_select28 """explain shape plan select /*+ leading(t1 t2) */ * from t1 join t2 t_2 on c1 = c2;"""
|
||||
qt_select29 """explain shape plan select /*+ leading(t1 t_1) */ * from t1 join t1 t_1 on t1.c1 = t_1.c1;"""
|
||||
// left join + left join
|
||||
qt_select22_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
qt_select22_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3;"""
|
||||
|
||||
// left join + right join
|
||||
qt_select23_1 """select count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
qt_select23_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3;"""
|
||||
|
||||
// left join + semi join
|
||||
qt_select24_1 """select count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select24_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
|
||||
// left join + anti join
|
||||
qt_select25_1 """select count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select25_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
|
||||
// right join + semi join
|
||||
qt_select26_1 """select count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
qt_select26_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3;"""
|
||||
|
||||
// right join + anti join
|
||||
qt_select27_1 """select count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
qt_select27_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3;"""
|
||||
|
||||
// semi join + anti join
|
||||
qt_select28_1 """select count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
qt_select28_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3;"""
|
||||
|
||||
// left join + left join + inner join
|
||||
qt_select32_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_2 """select /*+ leading(t1 t2 t3 t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_3 """select /*+ leading(t1 {t2 t3} t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_4 """select /*+ leading(t1 t3 t2 t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_5 """select /*+ leading(t1 {t2 t2} t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_6 """select /*+ leading(t2 t1 t3 t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_7 """select /*+ leading(t2 {t1 t3} t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_8 """select /*+ leading(t2 t3 t1 t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_9 """select /*+ leading(t2 {t3 t1} t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_10 """select /*+ leading(t3 t1 t2 t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_11 """select /*+ leading(t3 {t1 t2} t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_12 """select /*+ leading(t3 t2 t1 t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select32_13 """select /*+ leading(t3 {t2 t1} t4) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
|
||||
// left join + right join + inner join
|
||||
qt_select33_1 """select count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_2 """select /*+ leading(t1 t2 t3 t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_3 """select /*+ leading(t1 {t2 t3} t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_4 """select /*+ leading(t1 t3 t2 t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_5 """select /*+ leading(t1 {t2 t2} t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_6 """select /*+ leading(t2 t1 t3 t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_7 """select /*+ leading(t2 {t1 t3} t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_8 """select /*+ leading(t2 t3 t1 t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_9 """select /*+ leading(t2 {t3 t1} t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_10 """select /*+ leading(t3 t1 t2 t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_11 """select /*+ leading(t3 {t1 t2} t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_12 """select /*+ leading(t3 t2 t1 t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select33_13 """select /*+ leading(t3 {t2 t1} t4) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
|
||||
// left join + semi join + inner join
|
||||
qt_select34_1 """select count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_2 """select /*+ leading(t1 t2 t3 t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_3 """select /*+ leading(t1 {t2 t3} t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_4 """select /*+ leading(t1 t3 t2 t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_5 """select /*+ leading(t1 {t2 t2} t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_6 """select /*+ leading(t2 t1 t3 t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_7 """select /*+ leading(t2 {t1 t3} t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_8 """select /*+ leading(t2 t3 t1 t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_9 """select /*+ leading(t2 {t3 t1} t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_10 """select /*+ leading(t3 t1 t2 t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_11 """select /*+ leading(t3 {t1 t2} t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_12 """select /*+ leading(t3 t2 t1 t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select34_13 """select /*+ leading(t3 {t2 t1} t4) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// left join + anti join + inner join
|
||||
qt_select35_1 """select count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_2 """select /*+ leading(t1 t2 t3 t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_3 """select /*+ leading(t1 {t2 t3} t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_4 """select /*+ leading(t1 t3 t2 t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_5 """select /*+ leading(t1 {t2 t2} t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_6 """select /*+ leading(t2 t1 t3 t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_7 """select /*+ leading(t2 {t1 t3} t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_8 """select /*+ leading(t2 t3 t1 t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_9 """select /*+ leading(t2 {t3 t1} t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_10 """select /*+ leading(t3 t1 t2 t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_11 """select /*+ leading(t3 {t1 t2} t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_12 """select /*+ leading(t3 t2 t1 t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select35_13 """select /*+ leading(t3 {t2 t1} t4) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// right join + semi join + inner join
|
||||
qt_select36_1 """select count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_2 """select /*+ leading(t1 t2 t3 t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_3 """select /*+ leading(t1 {t2 t3} t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_4 """select /*+ leading(t1 t3 t2 t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_5 """select /*+ leading(t1 {t2 t2} t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_6 """select /*+ leading(t2 t1 t3 t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_7 """select /*+ leading(t2 {t1 t3} t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_8 """select /*+ leading(t2 t3 t1 t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_9 """select /*+ leading(t2 {t3 t1} t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_10 """select /*+ leading(t3 t1 t2 t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_11 """select /*+ leading(t3 {t1 t2} t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_12 """select /*+ leading(t3 t2 t1 t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select36_13 """select /*+ leading(t3 {t2 t1} t4) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// right join + anti join + inner join
|
||||
qt_select37_1 """select count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_2 """select /*+ leading(t1 t2 t3 t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_3 """select /*+ leading(t1 {t2 t3} t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_4 """select /*+ leading(t1 t3 t2 t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_5 """select /*+ leading(t1 {t2 t2} t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_6 """select /*+ leading(t2 t1 t3 t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_7 """select /*+ leading(t2 {t1 t3} t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_8 """select /*+ leading(t2 t3 t1 t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_9 """select /*+ leading(t2 {t3 t1} t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_10 """select /*+ leading(t3 t1 t2 t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_11 """select /*+ leading(t3 {t1 t2} t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_12 """select /*+ leading(t3 t2 t1 t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select37_13 """select /*+ leading(t3 {t2 t1} t4) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// semi join + anti join + inner join
|
||||
qt_select38_1 """select count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_2 """select /*+ leading(t1 t2 t3 t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_3 """select /*+ leading(t1 {t2 t3} t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_4 """select /*+ leading(t1 t3 t2 t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_5 """select /*+ leading(t1 {t2 t2} t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_6 """select /*+ leading(t2 t1 t3 t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_7 """select /*+ leading(t2 {t1 t3} t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_8 """select /*+ leading(t2 t3 t1 t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_9 """select /*+ leading(t2 {t3 t1} t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_10 """select /*+ leading(t3 t1 t2 t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_11 """select /*+ leading(t3 {t1 t2} t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_12 """select /*+ leading(t3 t2 t1 t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select38_13 """select /*+ leading(t3 {t2 t1} t4) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// left join + left join + inner join
|
||||
qt_select42_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_2 """select /*+ leading(t1 t2 t4 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_3 """select /*+ leading(t1 {t2 t4} t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_4 """select /*+ leading(t1 t4 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_5 """select /*+ leading(t1 {t4 t2} t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_6 """select /*+ leading(t2 t1 t4 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_7 """select /*+ leading(t2 {t1 t4} t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_8 """select /*+ leading(t2 t4 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_9 """select /*+ leading(t2 {t4 t1} t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_10 """select /*+ leading(t4 t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_11 """select /*+ leading(t4 {t1 t2} t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_12 """select /*+ leading(t4 t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select42_13 """select /*+ leading(t4 {t2 t1} t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
|
||||
// left join + right join + inner join
|
||||
qt_select43_1 """select count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_2 """select /*+ leading(t1 t2 t4 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_3 """select /*+ leading(t1 {t2 t4} t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_4 """select /*+ leading(t1 t4 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_5 """select /*+ leading(t1 {t4 t2} t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_6 """select /*+ leading(t2 t1 t4 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_7 """select /*+ leading(t2 {t1 t4} t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_8 """select /*+ leading(t2 t4 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_9 """select /*+ leading(t2 {t4 t1} t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_10 """select /*+ leading(t4 t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_11 """select /*+ leading(t4 {t1 t2} t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_12 """select /*+ leading(t4 t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
qt_select43_13 """select /*+ leading(t4 {t2 t1} t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 join t4 on c3 = c4;"""
|
||||
|
||||
// left join + semi join + inner join
|
||||
qt_select44_1 """select count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_2 """select /*+ leading(t1 t2 t4 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_3 """select /*+ leading(t1 {t2 t4} t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_4 """select /*+ leading(t1 t4 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_5 """select /*+ leading(t1 {t4 t2} t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_6 """select /*+ leading(t2 t1 t4 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_7 """select /*+ leading(t2 {t1 t4} t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_8 """select /*+ leading(t2 t4 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_9 """select /*+ leading(t2 {t4 t1} t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_10 """select /*+ leading(t4 t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_11 """select /*+ leading(t4 {t1 t2} t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_12 """select /*+ leading(t4 t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select44_13 """select /*+ leading(t4 {t2 t1} t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// left join + anti join + inner join
|
||||
qt_select45_1 """select count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_2 """select /*+ leading(t1 t2 t4 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_3 """select /*+ leading(t1 {t2 t4} t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_4 """select /*+ leading(t1 t4 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_5 """select /*+ leading(t1 {t4 t2} t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_6 """select /*+ leading(t2 t1 t4 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_7 """select /*+ leading(t2 {t1 t4} t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_8 """select /*+ leading(t2 t4 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_9 """select /*+ leading(t2 {t4 t1} t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_10 """select /*+ leading(t4 t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_11 """select /*+ leading(t4 {t1 t2} t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_12 """select /*+ leading(t4 t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select45_13 """select /*+ leading(t4 {t2 t1} t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// right join + semi join + inner join
|
||||
qt_select46_1 """select count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_2 """select /*+ leading(t1 t2 t4 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_3 """select /*+ leading(t1 {t2 t4} t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_4 """select /*+ leading(t1 t4 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_5 """select /*+ leading(t1 {t4 t2} t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_6 """select /*+ leading(t2 t1 t4 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_7 """select /*+ leading(t2 {t1 t4} t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_8 """select /*+ leading(t2 t4 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_9 """select /*+ leading(t2 {t4 t1} t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_10 """select /*+ leading(t4 t1 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_11 """select /*+ leading(t4 {t1 t2} t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_12 """select /*+ leading(t4 t2 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select46_13 """select /*+ leading(t4 {t2 t1} t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// right join + anti join + inner join
|
||||
qt_select47_1 """select count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_2 """select /*+ leading(t1 t2 t4 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_3 """select /*+ leading(t1 {t2 t4} t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_4 """select /*+ leading(t1 t4 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_5 """select /*+ leading(t1 {t4 t2} t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_6 """select /*+ leading(t2 t1 t4 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_7 """select /*+ leading(t2 {t1 t4} t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_8 """select /*+ leading(t2 t4 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_9 """select /*+ leading(t2 {t4 t1} t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_10 """select /*+ leading(t4 t1 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_11 """select /*+ leading(t4 {t1 t2} t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_12 """select /*+ leading(t4 t2 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
qt_select47_13 """select /*+ leading(t4 {t2 t1} t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// semi join + anti join + inner join
|
||||
qt_select48_1 """select count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_2 """select /*+ leading(t1 t2 t4 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_3 """select /*+ leading(t1 {t2 t4} t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_4 """select /*+ leading(t1 t4 t2 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_5 """select /*+ leading(t1 {t4 t2} t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_6 """select /*+ leading(t2 t1 t4 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_7 """select /*+ leading(t2 {t1 t4} t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_8 """select /*+ leading(t2 t4 t1 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_9 """select /*+ leading(t2 {t4 t1} t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_10 """select /*+ leading(t4 t1 t2 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_11 """select /*+ leading(t4 {t1 t2} t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_12 """select /*+ leading(t4 t2 t1 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
qt_select48_13 """select /*+ leading(t4 {t2 t1} t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 join t4 on c1 = c4;"""
|
||||
|
||||
// left join + left join + inner join
|
||||
qt_select49_1 """select count(*) from t1 left join t2 on c1 = c2 join t3 on c2 = c3 left join t4 on t3.c3 = t4.c4;"""
|
||||
qt_select49_2 """select /*+ leading(t1 t2 {t3 t4}) */ count(*) from t1 left join t2 on c1 = c2 join t3 on c2 = c3 left join t4 on t3.c3 = t4.c4;"""
|
||||
qt_select49_3 """select /*+ leading({t1 t2} t3 t4) */ count(*) from t1 left join t2 on c1 = c2 join t3 on c2 = c3 left join t4 on t3.c3 = t4.c4;"""
|
||||
qt_select49_4 """select /*+ leading({t1 t3} t2 t4) */ count(*) from t1 left join t2 on c1 = c2 join t3 on c2 = c3 left join t4 on t3.c3 = t4.c4;"""
|
||||
qt_select49_5 """select /*+ leading(t1 {t3 t4} t2) */ count(*) from t1 left join t2 on c1 = c2 join t3 on c2 = c3 left join t4 on t3.c3 = t4.c4;"""
|
||||
qt_select49_6 """select /*+ leading({t1 t3} t4 t2) */ count(*) from t1 left join t2 on c1 = c2 join t3 on c2 = c3 left join t4 on t3.c3 = t4.c4;"""
|
||||
|
||||
// cte
|
||||
qt_select50_1 """with cte as (select * from t1 join t2 on c1 = c2) select count(*) from cte, t2;"""
|
||||
qt_select50_2 """with cte as (select /*+ leading(t2 t1) */* from t1 join t2 on c1 = c2) select /*+ leading(cte t3) */ count(*) from cte, t3;"""
|
||||
qt_select50_3 """with cte as (select /*+ leading(t2 t1) */* from t1 join t2 on c1 = c2) select count(*) from cte, t3;"""
|
||||
qt_select50_4 """with cte as (select * from t1 join t2 on c1 = c2) select /*+ leading(cte t3) */ count(*) from cte, t3;"""
|
||||
|
||||
// in subquery +
|
||||
// inner join + anti join
|
||||
qt_select51_1 """select count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select51_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
|
||||
// left join + left join
|
||||
qt_select52_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select52_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
|
||||
// left join + right join
|
||||
qt_select53_1 """select count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select53_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
|
||||
// left join + semi join
|
||||
qt_select54_1 """select count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select54_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
|
||||
// left join + anti join
|
||||
qt_select55_1 """select count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select55_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
|
||||
// right join + semi join
|
||||
qt_select56_1 """select count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select56_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
|
||||
// right join + anti join
|
||||
qt_select57_1 """select count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select57_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where c1 in (select c4 from t4);"""
|
||||
|
||||
// semi join + anti join
|
||||
qt_select58_1 """select count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
qt_select58_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where c1 in (select c4 from t4);"""
|
||||
|
||||
// exists subquery +
|
||||
// inner join + anti join
|
||||
qt_select61_1 """select count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select61_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// left join + left join
|
||||
qt_select62_1 """select count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select62_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// left join + right join
|
||||
qt_select63_1 """select count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select63_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// left join + semi join
|
||||
qt_select64_1 """select count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select64_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// left join + anti join
|
||||
qt_select65_1 """select count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select65_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// right join + semi join
|
||||
qt_select66_1 """select count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select66_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 right join t2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// right join + anti join
|
||||
qt_select67_1 """select count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select67_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 right join t2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// semi join + anti join
|
||||
qt_select68_1 """select count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_2 """select /*+ leading(t1 t2 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_3 """select /*+ leading(t1 {t2 t3}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_5 """select /*+ leading(t1 {t2 t2}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_6 """select /*+ leading(t2 t1 t3) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_7 """select /*+ leading(t2 {t1 t3}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_8 """select /*+ leading(t2 t3 t1) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_9 """select /*+ leading(t2 {t3 t1}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_12 """select /*+ leading(t3 t2 t1) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select68_13 """select /*+ leading(t3 {t2 t1}) */ count(*) from t1 left semi join t2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// wrong table name
|
||||
qt_select70_1 """explain shape plan select /*+ leading(t1 t3) */ count(*) from t1 join t2 on c1 = c2;"""
|
||||
qt_select70_2 """explain shape plan select /*+ leading(t1 t5) */ count(*) from t1 join t2 on c1 = c2;"""
|
||||
|
||||
// duplicate table name
|
||||
qt_select71_1 """explain shape plan select /*+ leading(t1 t1 t2) */ count(*) from t1 join t2 on c1 = c2;"""
|
||||
qt_select71_2 """explain shape plan select /*+ leading(t1 t2 t2) */ count(*) from t1 join t2 on c1 = c2;"""
|
||||
|
||||
// different scope
|
||||
qt_select72_1 """explain shape plan select count(*) from t1 join t2 on c1 = c2 where c2 in (select /*+ leading(t4 t3) */ c3 from t3 join t4 on c3 = c4);"""
|
||||
qt_select72_2 """explain shape plan select /*+ leading(t1 t2) */ count(*) from t1 join t2 on c1 = c2 where c2 in (select c3 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// multi leading hint
|
||||
qt_select73_1 """explain shape plan select /*+ leading(t1 t2) */ count(*) from t1 join t2 on c1 = c2 where c2 in (select /*+ leading(t4 t3) */ c3 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// alias
|
||||
// inner join + anti join
|
||||
qt_select81_1 """select count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_2 """select /*+ leading(t1 alias2 t3) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_3 """select /*+ leading(t1 {alias2 t3}) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_5 """select /*+ leading(t1 {alias2 t2}) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_6 """select /*+ leading(alias2 t1 t3) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_7 """select /*+ leading(alias2 {t1 t3}) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_8 """select /*+ leading(alias2 t3 t1) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_9 """select /*+ leading(alias2 {t3 t1}) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_12 """select /*+ leading(t3 alias2 t1) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select81_13 """select /*+ leading(t3 {alias2 t1}) */ count(*) from t1 join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// left join + left join
|
||||
qt_select82_1 """select count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_2 """select /*+ leading(t1 alias2 t3) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_3 """select /*+ leading(t1 {alias2 t3}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_5 """select /*+ leading(t1 {alias2 t2}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_6 """select /*+ leading(alias2 t1 t3) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_7 """select /*+ leading(alias2 {t1 t3}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_8 """select /*+ leading(alias2 t3 t1) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_9 """select /*+ leading(alias2 {t3 t1}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_12 """select /*+ leading(t3 alias2 t1) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select82_13 """select /*+ leading(t3 {alias2 t1}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// left join + right join
|
||||
qt_select83_1 """select count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_2 """select /*+ leading(t1 alias2 t3) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_3 """select /*+ leading(t1 {alias2 t3}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_5 """select /*+ leading(t1 {alias2 t2}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_6 """select /*+ leading(alias2 t1 t3) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_7 """select /*+ leading(alias2 {t1 t3}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_8 """select /*+ leading(alias2 t3 t1) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_9 """select /*+ leading(alias2 {t3 t1}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_12 """select /*+ leading(t3 alias2 t1) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select83_13 """select /*+ leading(t3 {alias2 t1}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 right join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// left join + semi join
|
||||
qt_select84_1 """select count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_2 """select /*+ leading(t1 alias2 t3) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_3 """select /*+ leading(t1 {alias2 t3}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_5 """select /*+ leading(t1 {alias2 t2}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_6 """select /*+ leading(alias2 t1 t3) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_7 """select /*+ leading(alias2 {t1 t3}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_8 """select /*+ leading(alias2 t3 t1) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_9 """select /*+ leading(alias2 {t3 t1}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_12 """select /*+ leading(t3 alias2 t1) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select84_13 """select /*+ leading(t3 {alias2 t1}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// left join + anti join
|
||||
qt_select85_1 """select count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_2 """select /*+ leading(t1 alias2 t3) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_3 """select /*+ leading(t1 {alias2 t3}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_5 """select /*+ leading(t1 {alias2 t2}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_6 """select /*+ leading(alias2 t1 t3) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_7 """select /*+ leading(alias2 {t1 t3}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_8 """select /*+ leading(alias2 t3 t1) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_9 """select /*+ leading(alias2 {t3 t1}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_12 """select /*+ leading(t3 alias2 t1) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select85_13 """select /*+ leading(t3 {alias2 t1}) */ count(*) from t1 left join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// right join + semi join
|
||||
qt_select86_1 """select count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_2 """select /*+ leading(t1 alias2 t3) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_3 """select /*+ leading(t1 {alias2 t3}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_5 """select /*+ leading(t1 {alias2 t2}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_6 """select /*+ leading(alias2 t1 t3) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_7 """select /*+ leading(alias2 {t1 t3}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_8 """select /*+ leading(alias2 t3 t1) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_9 """select /*+ leading(alias2 {t3 t1}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_12 """select /*+ leading(t3 alias2 t1) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select86_13 """select /*+ leading(t3 {alias2 t1}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left semi join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// right join + anti join
|
||||
qt_select87_1 """select count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_2 """select /*+ leading(t1 alias2 t3) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_3 """select /*+ leading(t1 {alias2 t3}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_5 """select /*+ leading(t1 {alias2 t2}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_6 """select /*+ leading(alias2 t1 t3) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_7 """select /*+ leading(alias2 {t1 t3}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_8 """select /*+ leading(alias2 t3 t1) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_9 """select /*+ leading(alias2 {t3 t1}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_12 """select /*+ leading(t3 alias2 t1) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select87_13 """select /*+ leading(t3 {alias2 t1}) */ count(*) from t1 right join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c2 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
// semi join + anti join
|
||||
qt_select88_1 """select count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_2 """select /*+ leading(t1 alias2 t3) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_3 """select /*+ leading(t1 {alias2 t3}) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_4 """select /*+ leading(t1 t3 t2) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_5 """select /*+ leading(t1 {alias2 t2}) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_6 """select /*+ leading(alias2 t1 t3) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_7 """select /*+ leading(alias2 {t1 t3}) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_8 """select /*+ leading(alias2 t3 t1) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_9 """select /*+ leading(alias2 {t3 t1}) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_10 """select /*+ leading(t3 t1 t2) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_11 """select /*+ leading(t3 {t1 t2}) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_12 """select /*+ leading(t3 alias2 t1) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
qt_select88_13 """select /*+ leading(t3 {alias2 t1}) */ count(*) from t1 left semi join (select c2 from t2) as alias2 on c1 = c2 left anti join t3 on c1 = c3 where exists (select 1 from t3 join t4 on c3 = c4);"""
|
||||
|
||||
sql """drop table if exists t1;"""
|
||||
sql """drop table if exists t2;"""
|
||||
|
||||
Reference in New Issue
Block a user