diff --git a/src/common/symbols.cpp b/src/common/symbols.cpp index 24996ba65cca..bfec975b9c00 100644 --- a/src/common/symbols.cpp +++ b/src/common/symbols.cpp @@ -15,7 +15,7 @@ #include "duckdb/main/query_result.hpp" #include "duckdb/main/relation.hpp" #include "duckdb/main/stream_query_result.hpp" -#include "duckdb/optimizer/join_order_optimizer.hpp" +#include "duckdb/optimizer/join_order/join_order_optimizer.hpp" #include "duckdb/optimizer/rule.hpp" #include "duckdb/parallel/pipeline.hpp" #include "duckdb/parallel/meta_pipeline.hpp" diff --git a/src/include/duckdb/execution/physical_operator.hpp b/src/include/duckdb/execution/physical_operator.hpp index fdaad81e07dd..51871c4b079f 100644 --- a/src/include/duckdb/execution/physical_operator.hpp +++ b/src/include/duckdb/execution/physical_operator.hpp @@ -14,7 +14,7 @@ #include "duckdb/common/enums/physical_operator_type.hpp" #include "duckdb/common/types/data_chunk.hpp" #include "duckdb/execution/execution_context.hpp" -#include "duckdb/optimizer/join_node.hpp" +#include "duckdb/optimizer/join_order/join_node.hpp" namespace duckdb { class Event; diff --git a/src/include/duckdb/optimizer/filter_pushdown.hpp b/src/include/duckdb/optimizer/filter_pushdown.hpp index ee4d40e7d365..b79737aaff0f 100644 --- a/src/include/duckdb/optimizer/filter_pushdown.hpp +++ b/src/include/duckdb/optimizer/filter_pushdown.hpp @@ -11,6 +11,7 @@ #include "duckdb/common/unordered_set.hpp" #include "duckdb/optimizer/filter_combiner.hpp" #include "duckdb/optimizer/rule.hpp" +#include "duckdb/optimizer/operator_pool.hpp" namespace duckdb { diff --git a/src/include/duckdb/optimizer/cardinality_estimator.hpp b/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp similarity index 97% rename from src/include/duckdb/optimizer/cardinality_estimator.hpp rename to src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp index cb823ca55cca..f9a718d6dc15 100644 --- a/src/include/duckdb/optimizer/cardinality_estimator.hpp +++ b/src/include/duckdb/optimizer/join_order/cardinality_estimator.hpp @@ -1,14 +1,14 @@ //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/optimizer/cardinality_estimator.hpp +// duckdb/optimizer/join_order/cardinality_estimator.hpp // // //===----------------------------------------------------------------------===// #pragma once #include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" -#include "duckdb/optimizer/join_node.hpp" +#include "duckdb/optimizer/join_order/join_node.hpp" #include "duckdb/planner/column_binding.hpp" #include "duckdb/planner/column_binding_map.hpp" #include "duckdb/planner/filter/conjunction_filter.hpp" diff --git a/src/include/duckdb/optimizer/estimated_properties.hpp b/src/include/duckdb/optimizer/join_order/estimated_properties.hpp similarity index 95% rename from src/include/duckdb/optimizer/estimated_properties.hpp rename to src/include/duckdb/optimizer/join_order/estimated_properties.hpp index 4a43d0f38ce1..31c4b60fb8bb 100644 --- a/src/include/duckdb/optimizer/estimated_properties.hpp +++ b/src/include/duckdb/optimizer/join_order/estimated_properties.hpp @@ -1,7 +1,7 @@ //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/optimizer/estimated_properties.hpp +// duckdb/optimizer/join_order/estimated_properties.hpp // // //===----------------------------------------------------------------------===// diff --git a/src/include/duckdb/optimizer/join_node.hpp b/src/include/duckdb/optimizer/join_order/join_node.hpp similarity index 95% rename from src/include/duckdb/optimizer/join_node.hpp rename to src/include/duckdb/optimizer/join_order/join_node.hpp index c6bec09ea50d..7e8c545bbfa3 100644 --- a/src/include/duckdb/optimizer/join_node.hpp +++ b/src/include/duckdb/optimizer/join_order/join_node.hpp @@ -1,23 +1,23 @@ //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/optimizer/join_node.hpp +// duckdb/optimizer/join_order/join_node.hpp // // //===----------------------------------------------------------------------===// #pragma once +#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" #include "duckdb/common/unordered_map.hpp" #include "duckdb/common/unordered_set.hpp" -#include "duckdb/optimizer/join_order/query_graph.hpp" +#include "duckdb/optimizer/join_order/estimated_properties.hpp" #include "duckdb/optimizer/join_order/join_relation.hpp" +#include "duckdb/optimizer/join_order/query_graph.hpp" #include "duckdb/parser/expression_map.hpp" #include "duckdb/planner/logical_operator_visitor.hpp" -#include "duckdb/storage/statistics/distinct_statistics.hpp" #include "duckdb/planner/table_filter.hpp" -#include "duckdb/catalog/catalog_entry/table_catalog_entry.hpp" -#include "duckdb/optimizer/estimated_properties.hpp" +#include "duckdb/storage/statistics/distinct_statistics.hpp" namespace duckdb { diff --git a/src/include/duckdb/optimizer/join_order_optimizer.hpp b/src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp similarity index 96% rename from src/include/duckdb/optimizer/join_order_optimizer.hpp rename to src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp index 9d89758ea276..2c0f44c5c0e3 100644 --- a/src/include/duckdb/optimizer/join_order_optimizer.hpp +++ b/src/include/duckdb/optimizer/join_order/join_order_optimizer.hpp @@ -1,7 +1,7 @@ //===----------------------------------------------------------------------===// // DuckDB // -// duckdb/optimizer/join_order_optimizer.hpp +// duckdb/optimizer/join_order/join_order_optimizer.hpp // // //===----------------------------------------------------------------------===// @@ -10,13 +10,13 @@ #include "duckdb/common/unordered_map.hpp" #include "duckdb/common/unordered_set.hpp" -#include "duckdb/optimizer/join_order/query_graph.hpp" #include "duckdb/optimizer/join_order/join_relation.hpp" -#include "duckdb/optimizer/join_node.hpp" +#include "duckdb/optimizer/join_order/cardinality_estimator.hpp" +#include "duckdb/optimizer/join_order/query_graph.hpp" +#include "duckdb/optimizer/join_order/join_node.hpp" #include "duckdb/parser/expression_map.hpp" #include "duckdb/planner/logical_operator.hpp" #include "duckdb/planner/logical_operator_visitor.hpp" -#include "duckdb/optimizer/cardinality_estimator.hpp" #include diff --git a/src/include/duckdb/optimizer/operator_pool.hpp b/src/include/duckdb/optimizer/operator_pool.hpp new file mode 100644 index 000000000000..b98b29bf0b62 --- /dev/null +++ b/src/include/duckdb/optimizer/operator_pool.hpp @@ -0,0 +1,29 @@ +//===----------------------------------------------------------------------===// +// DuckDB +// +// duckdb/optimizer/operator_pool.hpp +// +// +//===----------------------------------------------------------------------===// + +#pragma once + +#include "duckdb/planner/logical_operator.hpp" +#include "duckdb/common/unordered_set.hpp" + +namespace duckdb { + +class OperatorPool { +public: + OperatorPool() { + seen_operators = unordered_set(); + } + + void AddOperator(LogicalOperator *op); + bool InPool(LogicalOperator *op); + void EmptyOperatorPool(); + +private: + unordered_set seen_operators; +}; +} // namespace duckdb diff --git a/src/include/duckdb/optimizer/optimizer.hpp b/src/include/duckdb/optimizer/optimizer.hpp index 96bde0ad7012..f7fdff949d2a 100644 --- a/src/include/duckdb/optimizer/optimizer.hpp +++ b/src/include/duckdb/optimizer/optimizer.hpp @@ -12,6 +12,7 @@ #include "duckdb/planner/logical_operator.hpp" #include "duckdb/planner/logical_operator_visitor.hpp" #include "duckdb/common/enums/optimizer_type.hpp" +#include "duckdb/optimizer/operator_pool.hpp" #include @@ -27,6 +28,7 @@ class Optimizer { ClientContext &context; Binder &binder; ExpressionRewriter rewriter; + OperatorPool seen_operators; private: void RunOptimizer(OptimizerType type, const std::function &callback); diff --git a/src/include/duckdb/planner/logical_operator.hpp b/src/include/duckdb/planner/logical_operator.hpp index a02f232eacd7..ab7947374ecb 100644 --- a/src/include/duckdb/planner/logical_operator.hpp +++ b/src/include/duckdb/planner/logical_operator.hpp @@ -9,16 +9,16 @@ #pragma once #include "duckdb/catalog/catalog.hpp" -#include "duckdb/optimizer/estimated_properties.hpp" #include "duckdb/common/common.hpp" #include "duckdb/common/enums/logical_operator_type.hpp" +#include "duckdb/optimizer/join_order/estimated_properties.hpp" +#include "duckdb/planner/column_binding.hpp" #include "duckdb/planner/expression.hpp" #include "duckdb/planner/logical_operator_visitor.hpp" -#include "duckdb/planner/column_binding.hpp" #include "duckdb/planner/plan_serialization.hpp" -#include #include +#include namespace duckdb { diff --git a/src/optimizer/CMakeLists.txt b/src/optimizer/CMakeLists.txt index fb9a485b49d1..7f7ce3f68dd1 100644 --- a/src/optimizer/CMakeLists.txt +++ b/src/optimizer/CMakeLists.txt @@ -17,11 +17,8 @@ add_library_unity( filter_pushdown.cpp filter_pullup.cpp in_clause_rewriter.cpp - join_node.cpp - join_order_optimizer.cpp - cardinality_estimator.cpp - estimated_properties.cpp optimizer.cpp + operator_pool.cpp expression_rewriter.cpp regex_range_filter.cpp remove_unused_columns.cpp diff --git a/src/optimizer/filter_pushdown.cpp b/src/optimizer/filter_pushdown.cpp index b8b51830ab79..e29f4277d625 100644 --- a/src/optimizer/filter_pushdown.cpp +++ b/src/optimizer/filter_pushdown.cpp @@ -5,6 +5,8 @@ #include "duckdb/planner/operator/logical_join.hpp" #include "duckdb/optimizer/optimizer.hpp" +#include "iostream" + namespace duckdb { using Filter = FilterPushdown::Filter; @@ -13,6 +15,11 @@ FilterPushdown::FilterPushdown(Optimizer &optimizer) : optimizer(optimizer), com } unique_ptr FilterPushdown::Rewrite(unique_ptr op) { + if (optimizer.seen_operators.InPool(op.get())) { + // We've already optimized this operator, so just return. + return move(op); + } + optimizer.seen_operators.AddOperator(op.get()); D_ASSERT(!combiner.HasFilters()); switch (op->type) { case LogicalOperatorType::LOGICAL_AGGREGATE_AND_GROUP_BY: diff --git a/src/optimizer/join_order/CMakeLists.txt b/src/optimizer/join_order/CMakeLists.txt index c3dd8bb1d2fe..57dc2f29a14c 100644 --- a/src/optimizer/join_order/CMakeLists.txt +++ b/src/optimizer/join_order/CMakeLists.txt @@ -1,5 +1,12 @@ -add_library_unity(duckdb_optimizer_join_order OBJECT query_graph.cpp - join_relation_set.cpp) +add_library_unity( + duckdb_optimizer_join_order + OBJECT + query_graph.cpp + cardinality_estimator.cpp + join_relation_set.cpp + join_node.cpp + estimated_properties.cpp + join_order_optimizer.cpp) set(ALL_OBJECT_FILES ${ALL_OBJECT_FILES} $ PARENT_SCOPE) diff --git a/src/optimizer/cardinality_estimator.cpp b/src/optimizer/join_order/cardinality_estimator.cpp similarity index 99% rename from src/optimizer/cardinality_estimator.cpp rename to src/optimizer/join_order/cardinality_estimator.cpp index 9fda8a66d1f1..c30c84017553 100644 --- a/src/optimizer/cardinality_estimator.cpp +++ b/src/optimizer/join_order/cardinality_estimator.cpp @@ -1,12 +1,12 @@ +#include "duckdb/function/table/table_scan.hpp" +#include "duckdb/optimizer/join_order/join_node.hpp" +#include "duckdb/optimizer/join_order/join_order_optimizer.hpp" #include "duckdb/planner/filter/conjunction_filter.hpp" #include "duckdb/planner/filter/constant_filter.hpp" -#include "duckdb/optimizer/join_order_optimizer.hpp" -#include "duckdb/optimizer/join_node.hpp" -#include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/planner/operator/logical_comparison_join.hpp" +#include "duckdb/planner/operator/logical_get.hpp" #include "duckdb/storage/data_table.hpp" #include "duckdb/storage/statistics/numeric_statistics.hpp" -#include "duckdb/function/table/table_scan.hpp" namespace duckdb { diff --git a/src/optimizer/estimated_properties.cpp b/src/optimizer/join_order/estimated_properties.cpp similarity index 89% rename from src/optimizer/estimated_properties.cpp rename to src/optimizer/join_order/estimated_properties.cpp index e966039adca4..3fb1ba65783f 100644 --- a/src/optimizer/estimated_properties.cpp +++ b/src/optimizer/join_order/estimated_properties.cpp @@ -1,5 +1,5 @@ -#include "duckdb/optimizer/estimated_properties.hpp" +#include "duckdb/optimizer/join_order/estimated_properties.hpp" namespace duckdb { diff --git a/src/optimizer/join_node.cpp b/src/optimizer/join_order/join_node.cpp similarity index 97% rename from src/optimizer/join_node.cpp rename to src/optimizer/join_order/join_node.cpp index 08d5beb4e5e7..182e5d0ee5f5 100644 --- a/src/optimizer/join_node.cpp +++ b/src/optimizer/join_order/join_node.cpp @@ -1,7 +1,8 @@ +#include "duckdb/optimizer/join_order/join_node.hpp" + #include "duckdb/common/limits.hpp" #include "duckdb/planner/expression/list.hpp" #include "duckdb/planner/operator/list.hpp" -#include "duckdb/optimizer/join_node.hpp" namespace duckdb { diff --git a/src/optimizer/join_order_optimizer.cpp b/src/optimizer/join_order/join_order_optimizer.cpp similarity index 99% rename from src/optimizer/join_order_optimizer.cpp rename to src/optimizer/join_order/join_order_optimizer.cpp index 15e422faf9e8..cc5141910576 100644 --- a/src/optimizer/join_order_optimizer.cpp +++ b/src/optimizer/join_order/join_order_optimizer.cpp @@ -1,7 +1,8 @@ -#include "duckdb/optimizer/join_order_optimizer.hpp" +#include "duckdb/optimizer/join_order/join_order_optimizer.hpp" + +#include "duckdb/common/limits.hpp" #include "duckdb/common/pair.hpp" #include "duckdb/main/client_context.hpp" -#include "duckdb/common/limits.hpp" #include "duckdb/planner/expression/list.hpp" #include "duckdb/planner/expression_iterator.hpp" #include "duckdb/planner/operator/list.hpp" diff --git a/src/optimizer/operator_pool.cpp b/src/optimizer/operator_pool.cpp new file mode 100644 index 000000000000..7088cf3343db --- /dev/null +++ b/src/optimizer/operator_pool.cpp @@ -0,0 +1,23 @@ +// +// Created by Tom Ebergen on 06/12/2022. +// + +#include "duckdb/optimizer/operator_pool.hpp" + +namespace duckdb { + +void OperatorPool::AddOperator(LogicalOperator *op) { + D_ASSERT(!InPool(op)); + seen_operators.insert((idx_t)op); +} + +bool OperatorPool::InPool(LogicalOperator *op) { + auto it = seen_operators.find((idx_t)op); + return it != seen_operators.end(); +} + +void OperatorPool::EmptyOperatorPool() { + seen_operators.clear(); +} + +} // namespace duckdb diff --git a/src/optimizer/optimizer.cpp b/src/optimizer/optimizer.cpp index bd676fd8a09b..3dda7b3e4c6a 100644 --- a/src/optimizer/optimizer.cpp +++ b/src/optimizer/optimizer.cpp @@ -1,5 +1,6 @@ #include "duckdb/optimizer/optimizer.hpp" +#include "duckdb/execution/column_binding_resolver.hpp" #include "duckdb/execution/expression_executor.hpp" #include "duckdb/main/client_context.hpp" #include "duckdb/main/config.hpp" @@ -12,7 +13,7 @@ #include "duckdb/optimizer/filter_pullup.hpp" #include "duckdb/optimizer/filter_pushdown.hpp" #include "duckdb/optimizer/in_clause_rewriter.hpp" -#include "duckdb/optimizer/join_order_optimizer.hpp" +#include "duckdb/optimizer/join_order/join_order_optimizer.hpp" #include "duckdb/optimizer/regex_range_filter.hpp" #include "duckdb/optimizer/remove_unused_columns.hpp" #include "duckdb/optimizer/rule/equal_or_null_simplification.hpp" @@ -22,11 +23,11 @@ #include "duckdb/optimizer/topn_optimizer.hpp" #include "duckdb/planner/binder.hpp" #include "duckdb/planner/planner.hpp" -#include "duckdb/execution/column_binding_resolver.hpp" namespace duckdb { -Optimizer::Optimizer(Binder &binder, ClientContext &context) : context(context), binder(binder), rewriter(context) { +Optimizer::Optimizer(Binder &binder, ClientContext &context) + : context(context), binder(binder), rewriter(context), seen_operators() { rewriter.rules.push_back(make_unique(rewriter)); rewriter.rules.push_back(make_unique(rewriter)); rewriter.rules.push_back(make_unique(rewriter)); @@ -60,6 +61,7 @@ void Optimizer::RunOptimizer(OptimizerType type, const std::function &ca profiler.StartPhase(OptimizerTypeToString(type)); callback(); profiler.EndPhase(); + seen_operators.EmptyOperatorPool(); if (plan) { Verify(*plan); } diff --git a/src/optimizer/pushdown/pushdown_left_join.cpp b/src/optimizer/pushdown/pushdown_left_join.cpp index 6e5d143d1375..c33081c0cef4 100644 --- a/src/optimizer/pushdown/pushdown_left_join.cpp +++ b/src/optimizer/pushdown/pushdown_left_join.cpp @@ -8,6 +8,8 @@ #include "duckdb/planner/operator/logical_comparison_join.hpp" #include "duckdb/planner/operator/logical_filter.hpp" +#include "iostream" + namespace duckdb { using Filter = FilterPushdown::Filter; @@ -120,8 +122,11 @@ unique_ptr FilterPushdown::PushdownLeftJoin(unique_ptrchildren[0] = left_pushdown.Rewrite(move(op->children[0])); op->children[1] = right_pushdown.Rewrite(move(op->children[1])); + // Need to add the operators here because they are optimized with different + // filter_pushdown objects (i.e. left_pushdown and right_pushdown) return FinishPushdown(move(op)); } diff --git a/test/optimizer/pushdown/issue_5097.test b/test/optimizer/pushdown/issue_5097.test new file mode 100644 index 000000000000..cbbeccd6c286 --- /dev/null +++ b/test/optimizer/pushdown/issue_5097.test @@ -0,0 +1,204 @@ +# name: test/optimizer/pushdown/issue_5097.test +# description: Test Pushdown with many Left Joins +# group: [pushdown] + +statement ok +CREATE TABLE t1(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t10(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t11(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t12(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t13(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t14(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t15(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t16(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t17(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t18(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t19(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t2(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t20(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t21(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t22(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t23(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t24(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t25(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t26(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t27(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t28(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t29(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t3(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t30(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t31(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t32(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t33(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t34(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t35(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t36(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t37(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t38(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t39(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t4(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t40(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t41(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t42(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t43(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t44(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t45(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t46(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t47(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t48(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t5(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t6(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t7(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t8(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +statement ok +CREATE TABLE t9(c1 INTEGER NOT NULL, c2 INTEGER, c3 INTEGER, c4 INTEGER, c5 INTEGER, c6 INTEGER, c7 INTEGER, c8 INTEGER, c9 INTEGER, info VARCHAR); + +# Multiple column in the root OR node, don't push down +statement ok +select t1.c2 from t1 +inner join t2 on (t1.c2=t2.c1) +left join t4 on (t1.c3=t4.c1) +left join t5 on (t4.c2=t5.c1) +left join t6 on (t5.c2=t6.c1) +left join t7 on (t6.c2=t7.c1) +left join t8 on (t7.c2=t8.c1) +left join t9 on (t8.c2=t9.c1) +left join t10 on (t9.c2=t10.c1) +left join t11 on (t10.c2=t11.c1) +left join t12 on (t11.c2=t12.c1) +left join t13 on (t12.c2=t13.c1) +left join t14 on (t13.c2=t14.c1) +left join t15 on (t14.c2=t15.c1) +left join t16 on (t15.c2=t16.c1) +left join t17 on (t16.c2=t17.c1) +left join t18 on (t17.c2=t18.c1) +left join t19 on (t18.c2=t19.c1) +left join t20 on (t19.c2=t20.c1) +left join t21 on (t20.c2=t21.c1) +left join t22 on (t21.c2=t22.c1) +left join t23 on (t22.c2=t23.c1) +left join t24 on (t23.c2=t24.c1) +left join t25 on (t24.c2=t25.c1) +left join t26 on (t25.c2=t26.c1) +left join t27 on (t26.c2=t27.c1) +left join t28 on (t27.c2=t28.c1) +left join t29 on (t28.c2=t29.c1) +left join t30 on (t29.c2=t30.c1) +left join t31 on (t30.c2=t31.c1) +left join t32 on (t31.c2=t32.c1) +left join t33 on (t32.c2=t33.c1) +left join t34 on (t33.c2=t34.c1) +left join t35 on (t34.c2=t35.c1) +left join t36 on (t35.c2=t36.c1) +left join t37 on (t36.c2=t37.c1) +left join t38 on (t37.c2=t38.c1) +left join t39 on (t38.c2=t39.c1) +left join t3 ttttt3 on (ttttt3.c6=t33.c5) +left join t40 on (t39.c2=t40.c1) +left join t41 on (t40.c2=t41.c1) +left join t42 on (t41.c2=t42.c1) +left join t43 on (t42.c2=t43.c1) +left join t44 on (t43.c2=t44.c1) +left join t45 on (t44.c2=t45.c1) +left join t46 on (t45.c2=t46.c1) +left join t47 on (t46.c2=t47.c1) +left join t48 on (t47.c2=t48.c1) +left join t5 ttt5 on (t42.c1=ttt5.c3) +left join t5 ttt6 on (ttt5.c4=ttt6.c5) +left join t5 ttt7 on (ttt6.c6=ttt7.c7) +inner join t3 on (t2.c2=t3.c1) +left join t4 tt4 on (t47.c1=tt4.c3) +left join t4 tt5 on (tt4.c4=tt5.c5); \ No newline at end of file