Skip to content

support simple/cross lateral joins #16015

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 11 commits into from
May 16, 2025
Merged

Conversation

jayzhan211
Copy link
Contributor

@jayzhan211 jayzhan211 commented May 10, 2025

Which issue does this PR close?

address comment from #14595 to get this in.

Rationale for this change

What changes are included in this PR?

Are these changes tested?

Are there any user-facing changes?

skyzh and others added 9 commits February 16, 2025 18:01
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
@github-actions github-actions bot added optimizer Optimizer rules sqllogictest SQL Logic Tests (.slt) labels May 10, 2025
Copy link
Contributor

@comphead comphead left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @jayzhan211 imho it is lgtm, please check some nits though

4 4 1

query IIII
SELECT * FROM t0, LATERAL (SELECT * FROM t1 WHERE t1.v0 = 1);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we also check the join syntax?

SELECT * FROM t0 JOIN LATERAL (SELECT * FROM t1 WHERE t1.v0 = 1) on true;

?

@@ -313,6 +317,11 @@ impl TreeNodeRewriter for PullUpCorrelatedExpr {
missing_exprs.push(un_matched_row);
}
}
if aggregate.group_expr.is_empty() {
// TODO: how do we handle the case where we have pulled multiple aggregations? For example,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prob we can create a ticket for that?

}

match join.right.apply_with_subqueries(|p| {
if p.contains_outer_reference() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

perhaps we can add a comment why queries with outer reference won't be optimized? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not yet supported feature

return Ok(Transformed::no(LogicalPlan::Join(join)));
}
let subquery_plan = subquery.subquery.as_ref();
let mut pull_up = PullUpCorrelatedExpr::new().with_need_handle_count_bug(true);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

now I'm thinking of having this .with_need_handle_count_bug to move it to unsafe or something to let users know immediately the risks?

@alamb
Copy link
Contributor

alamb commented May 12, 2025

FYI @Lordworms I am not sure if this is related to some of your other work

@Lordworms
Copy link
Contributor

FYI @Lordworms I am not sure if this is related to some of your other work

I am doing a DelimJoin way (duckdb style) to support non-euqual lateral join like

SELECT *
FROM t0,
LATERAL (
  SELECT *
  FROM t1
  WHERE t1.v0 < t0.v0
);

and
table function like

SELECT *
FROM t0,
LATERAL range(1, t0.v1 + 3);

which may got some overlap with this pr since I have to identify the join condition as well

@alamb
Copy link
Contributor

alamb commented May 15, 2025

@irenjj perhaps you can review this PR as well as i cross / lateral joins are related to subqueries I think

Copy link
Contributor

@alamb alamb left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe eventually it would be nice to add / adapt the tests from duckdb and make sure we get the same answers: https://github.com/duckdb/duckdb/tree/main/test/sql/subquery/lateral

@alamb
Copy link
Contributor

alamb commented May 15, 2025

🤖 ./gh_compare_branch_bench.sh Benchmark Script Running
Linux aal-dev 6.11.0-1013-gcp #13~24.04.1-Ubuntu SMP Wed Apr 2 16:34:16 UTC 2025 x86_64 x86_64 x86_64 GNU/Linux
Comparing lateral-planning-v3 (1c21573) to e917167 diff
BENCH_NAME=sql_planner
BENCH_COMMAND=cargo bench --bench sql_planner
BENCH_FILTER=
BENCH_BRANCH_NAME=lateral-planning-v3
Results will be posted here when complete

Comment on lines 42 to 44
pub mod decorrelate;
pub mod decorrelate_lateral_join;
pub mod decorrelate_predicate_subquery;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would be really nice to figure out how to combine these passes into one unified set of decorrelation code -- now we have three passes

FYI @irenjj

@alamb
Copy link
Contributor

alamb commented May 15, 2025

I am sorry I don't have the capacity to study LATERAL joins in detail to really review the code carefully.

If you are happy with I think we should merge it.

I suspect we'll have to add more general code eventually but augmenting our test cases / features along the way seems good to me

@alamb
Copy link
Contributor

alamb commented May 15, 2025

🤖: Benchmark completed

Details

group                                         lateral-planning-v3                    main
-----                                         -------------------                    ----
logical_aggregate_with_join                   1.01    744.3±4.43µs        ? ?/sec    1.00    738.4±3.20µs        ? ?/sec
logical_select_all_from_1000                  1.10    143.8±2.86ms        ? ?/sec    1.00    131.0±0.23ms        ? ?/sec
logical_select_one_from_700                   1.02    424.0±2.15µs        ? ?/sec    1.00    415.5±1.90µs        ? ?/sec
logical_trivial_join_high_numbered_columns    1.01    386.0±2.71µs        ? ?/sec    1.00    381.4±8.43µs        ? ?/sec
logical_trivial_join_low_numbered_columns     1.03    372.7±6.31µs        ? ?/sec    1.00    362.5±1.13µs        ? ?/sec
physical_intersection                         1.02    866.8±5.59µs        ? ?/sec    1.00    853.0±4.63µs        ? ?/sec
physical_join_consider_sort                   1.01   1400.1±7.99µs        ? ?/sec    1.00   1379.6±7.45µs        ? ?/sec
physical_join_distinct                        1.02    362.5±1.48µs        ? ?/sec    1.00    355.9±1.77µs        ? ?/sec
physical_many_self_joins                      1.02     10.5±0.04ms        ? ?/sec    1.00     10.2±0.06ms        ? ?/sec
physical_plan_clickbench_all                  1.01    144.7±1.63ms        ? ?/sec    1.00    142.6±1.40ms        ? ?/sec
physical_plan_clickbench_q1                   1.02  1719.0±16.25µs        ? ?/sec    1.00  1686.2±17.31µs        ? ?/sec
physical_plan_clickbench_q10                  1.02      2.5±0.02ms        ? ?/sec    1.00      2.4±0.03ms        ? ?/sec
physical_plan_clickbench_q11                  1.03      2.6±0.04ms        ? ?/sec    1.00      2.5±0.03ms        ? ?/sec
physical_plan_clickbench_q12                  1.03      2.8±0.04ms        ? ?/sec    1.00      2.7±0.03ms        ? ?/sec
physical_plan_clickbench_q13                  1.03      2.4±0.03ms        ? ?/sec    1.00      2.4±0.02ms        ? ?/sec
physical_plan_clickbench_q14                  1.03      2.6±0.02ms        ? ?/sec    1.00      2.5±0.02ms        ? ?/sec
physical_plan_clickbench_q15                  1.02      2.5±0.02ms        ? ?/sec    1.00      2.4±0.02ms        ? ?/sec
physical_plan_clickbench_q16                  1.01      2.3±0.02ms        ? ?/sec    1.00      2.3±0.03ms        ? ?/sec
physical_plan_clickbench_q17                  1.04      2.5±0.03ms        ? ?/sec    1.00      2.4±0.02ms        ? ?/sec
physical_plan_clickbench_q18                  1.01      2.0±0.03ms        ? ?/sec    1.00  1981.1±23.20µs        ? ?/sec
physical_plan_clickbench_q19                  1.04      3.0±0.03ms        ? ?/sec    1.00      2.9±0.03ms        ? ?/sec
physical_plan_clickbench_q2                   1.01  1941.2±32.40µs        ? ?/sec    1.00  1916.7±18.69µs        ? ?/sec
physical_plan_clickbench_q20                  1.03  1710.9±23.79µs        ? ?/sec    1.00  1655.7±16.63µs        ? ?/sec
physical_plan_clickbench_q21                  1.02      2.0±0.01ms        ? ?/sec    1.00  1972.6±27.52µs        ? ?/sec
physical_plan_clickbench_q22                  1.01      2.6±0.03ms        ? ?/sec    1.00      2.6±0.03ms        ? ?/sec
physical_plan_clickbench_q23                  1.02      3.0±0.03ms        ? ?/sec    1.00      2.9±0.05ms        ? ?/sec
physical_plan_clickbench_q24                  1.01      4.8±0.04ms        ? ?/sec    1.00      4.7±0.04ms        ? ?/sec
physical_plan_clickbench_q25                  1.03      2.1±0.02ms        ? ?/sec    1.00  1996.0±16.78µs        ? ?/sec
physical_plan_clickbench_q26                  1.02  1864.1±27.91µs        ? ?/sec    1.00  1833.6±28.03µs        ? ?/sec
physical_plan_clickbench_q27                  1.02      2.1±0.02ms        ? ?/sec    1.00      2.0±0.03ms        ? ?/sec
physical_plan_clickbench_q28                  1.03      2.9±0.04ms        ? ?/sec    1.00      2.8±0.03ms        ? ?/sec
physical_plan_clickbench_q29                  1.02      3.6±0.03ms        ? ?/sec    1.00      3.5±0.03ms        ? ?/sec
physical_plan_clickbench_q3                   1.02  1938.8±28.33µs        ? ?/sec    1.00  1903.0±23.14µs        ? ?/sec
physical_plan_clickbench_q30                  1.01     14.5±0.13ms        ? ?/sec    1.00     14.4±0.13ms        ? ?/sec
physical_plan_clickbench_q31                  1.02      2.9±0.03ms        ? ?/sec    1.00      2.8±0.02ms        ? ?/sec
physical_plan_clickbench_q32                  1.01      2.9±0.03ms        ? ?/sec    1.00      2.9±0.02ms        ? ?/sec
physical_plan_clickbench_q33                  1.01      2.5±0.02ms        ? ?/sec    1.00      2.4±0.03ms        ? ?/sec
physical_plan_clickbench_q34                  1.02      2.2±0.02ms        ? ?/sec    1.00      2.1±0.03ms        ? ?/sec
physical_plan_clickbench_q35                  1.02      2.2±0.03ms        ? ?/sec    1.00      2.2±0.03ms        ? ?/sec
physical_plan_clickbench_q36                  1.01      3.0±0.03ms        ? ?/sec    1.00      3.0±0.04ms        ? ?/sec
physical_plan_clickbench_q37                  1.02      3.1±0.03ms        ? ?/sec    1.00      3.0±0.03ms        ? ?/sec
physical_plan_clickbench_q38                  1.03      3.1±0.03ms        ? ?/sec    1.00      3.0±0.02ms        ? ?/sec
physical_plan_clickbench_q39                  1.01      2.8±0.01ms        ? ?/sec    1.00      2.8±0.04ms        ? ?/sec
physical_plan_clickbench_q4                   1.01  1673.1±21.80µs        ? ?/sec    1.00  1654.0±24.97µs        ? ?/sec
physical_plan_clickbench_q40                  1.02      3.5±0.03ms        ? ?/sec    1.00      3.4±0.04ms        ? ?/sec
physical_plan_clickbench_q41                  1.01      3.0±0.02ms        ? ?/sec    1.00      3.0±0.03ms        ? ?/sec
physical_plan_clickbench_q42                  1.01      3.0±0.02ms        ? ?/sec    1.00      2.9±0.04ms        ? ?/sec
physical_plan_clickbench_q43                  1.01      3.2±0.04ms        ? ?/sec    1.00      3.1±0.05ms        ? ?/sec
physical_plan_clickbench_q44                  1.00  1813.0±15.74µs        ? ?/sec    1.00  1805.4±21.01µs        ? ?/sec
physical_plan_clickbench_q45                  1.01  1837.5±25.72µs        ? ?/sec    1.00  1823.6±34.53µs        ? ?/sec
physical_plan_clickbench_q46                  1.01      2.3±0.02ms        ? ?/sec    1.00      2.2±0.02ms        ? ?/sec
physical_plan_clickbench_q47                  1.01      2.9±0.03ms        ? ?/sec    1.00      2.8±0.03ms        ? ?/sec
physical_plan_clickbench_q48                  1.01      3.5±0.03ms        ? ?/sec    1.00      3.4±0.04ms        ? ?/sec
physical_plan_clickbench_q49                  1.00      3.9±0.04ms        ? ?/sec    1.00      3.9±0.04ms        ? ?/sec
physical_plan_clickbench_q5                   1.00  1851.1±13.42µs        ? ?/sec    1.00  1843.6±24.52µs        ? ?/sec
physical_plan_clickbench_q50                  1.02      3.6±0.03ms        ? ?/sec    1.00      3.5±0.04ms        ? ?/sec
physical_plan_clickbench_q51                  1.00      2.3±0.02ms        ? ?/sec    1.00      2.3±0.02ms        ? ?/sec
physical_plan_clickbench_q6                   1.03  1893.4±28.59µs        ? ?/sec    1.00  1845.6±28.33µs        ? ?/sec
physical_plan_clickbench_q7                   1.01  1720.8±19.20µs        ? ?/sec    1.00  1698.6±18.04µs        ? ?/sec
physical_plan_clickbench_q8                   1.02      2.4±0.03ms        ? ?/sec    1.00      2.3±0.03ms        ? ?/sec
physical_plan_clickbench_q9                   1.02      2.3±0.02ms        ? ?/sec    1.00      2.3±0.03ms        ? ?/sec
physical_plan_tpcds_all                       1.01   1097.5±5.44ms        ? ?/sec    1.00   1086.7±4.41ms        ? ?/sec
physical_plan_tpch_all                        1.01     65.3±0.31ms        ? ?/sec    1.00     64.5±0.35ms        ? ?/sec
physical_plan_tpch_q1                         1.01      2.2±0.02ms        ? ?/sec    1.00      2.2±0.02ms        ? ?/sec
physical_plan_tpch_q10                        1.00      3.3±0.01ms        ? ?/sec    1.00      3.3±0.01ms        ? ?/sec
physical_plan_tpch_q11                        1.01      3.4±0.01ms        ? ?/sec    1.00      3.4±0.01ms        ? ?/sec
physical_plan_tpch_q12                        1.01  1942.6±14.48µs        ? ?/sec    1.00   1929.4±8.37µs        ? ?/sec
physical_plan_tpch_q13                        1.01  1505.4±23.46µs        ? ?/sec    1.00  1493.7±26.10µs        ? ?/sec
physical_plan_tpch_q14                        1.01   1953.1±9.81µs        ? ?/sec    1.00   1933.2±9.36µs        ? ?/sec
physical_plan_tpch_q16                        1.01      2.6±0.02ms        ? ?/sec    1.00      2.6±0.01ms        ? ?/sec
physical_plan_tpch_q17                        1.01      2.6±0.01ms        ? ?/sec    1.00      2.6±0.03ms        ? ?/sec
physical_plan_tpch_q18                        1.01      2.8±0.03ms        ? ?/sec    1.00      2.7±0.01ms        ? ?/sec
physical_plan_tpch_q19                        1.02      4.0±0.02ms        ? ?/sec    1.00      3.9±0.02ms        ? ?/sec
physical_plan_tpch_q2                         1.01      5.7±0.02ms        ? ?/sec    1.00      5.7±0.04ms        ? ?/sec
physical_plan_tpch_q20                        1.01      3.5±0.02ms        ? ?/sec    1.00      3.4±0.05ms        ? ?/sec
physical_plan_tpch_q21                        1.01      4.5±0.06ms        ? ?/sec    1.00      4.4±0.03ms        ? ?/sec
physical_plan_tpch_q22                        1.01      3.0±0.01ms        ? ?/sec    1.00      3.0±0.03ms        ? ?/sec
physical_plan_tpch_q3                         1.01      2.2±0.01ms        ? ?/sec    1.00      2.2±0.02ms        ? ?/sec
physical_plan_tpch_q4                         1.01  1689.1±18.84µs        ? ?/sec    1.00  1674.3±13.55µs        ? ?/sec
physical_plan_tpch_q5                         1.01      3.2±0.01ms        ? ?/sec    1.00      3.2±0.03ms        ? ?/sec
physical_plan_tpch_q6                         1.01   939.3±11.24µs        ? ?/sec    1.00   929.5±12.45µs        ? ?/sec
physical_plan_tpch_q7                         1.01      4.4±0.02ms        ? ?/sec    1.00      4.4±0.04ms        ? ?/sec
physical_plan_tpch_q8                         1.01      5.3±0.02ms        ? ?/sec    1.00      5.3±0.04ms        ? ?/sec
physical_plan_tpch_q9                         1.01      4.2±0.02ms        ? ?/sec    1.00      4.2±0.03ms        ? ?/sec
physical_select_aggregates_from_200           1.00     26.6±0.10ms        ? ?/sec    1.00     26.5±0.12ms        ? ?/sec
physical_select_all_from_1000                 1.10    160.6±1.45ms        ? ?/sec    1.00    145.8±0.33ms        ? ?/sec
physical_select_one_from_700                  1.02  1083.3±12.60µs        ? ?/sec    1.00   1061.5±5.18µs        ? ?/sec
physical_sorted_union_orderby                 1.01     64.3±0.36ms        ? ?/sec    1.00     63.4±0.38ms        ? ?/sec
physical_theta_join_consider_sort             1.01   1771.2±7.71µs        ? ?/sec    1.00   1754.1±5.87µs        ? ?/sec
physical_unnest_to_join                       1.02  1365.7±14.05µs        ? ?/sec    1.00   1343.2±7.82µs        ? ?/sec
with_param_values_many_columns                1.00    169.0±0.89µs        ? ?/sec    1.00    168.2±0.82µs        ? ?/sec

@jayzhan211
Copy link
Contributor Author

TODOs:

  1. Add tests from https://github.com/duckdb/duckdb/tree/main/test/sql/subquery/lateral or others
  2. Unify decorrelate passes

@jayzhan211 jayzhan211 merged commit 07fe23f into apache:main May 16, 2025
27 checks passed
@jayzhan211 jayzhan211 deleted the lateral-planning-v3 branch May 16, 2025 01:14
@jayzhan211
Copy link
Contributor Author

Thanks @alamb @comphead and @skyzh

jfahne pushed a commit to jfahne/datafusion that referenced this pull request May 18, 2025
* support simple lateral joins

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>

* fix explain test

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>

* plan scalar agg correctly

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>

* add uncorrelated query tests

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>

* fix clippy + fmt

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>

* make rule matching faster

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>

* revert build_join visibility

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>

* revert find plan outer column changes

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>

* remove clone

* address comment

---------

Signed-off-by: Alex Chi Z <iskyzh@gmail.com>
Co-authored-by: Alex Chi Z <iskyzh@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
optimizer Optimizer rules sqllogictest SQL Logic Tests (.slt)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants