diff --git a/dbcon/joblist/jlf_tuplejoblist.cpp b/dbcon/joblist/jlf_tuplejoblist.cpp index 8a176c4ab..19cc2774a 100644 --- a/dbcon/joblist/jlf_tuplejoblist.cpp +++ b/dbcon/joblist/jlf_tuplejoblist.cpp @@ -3632,6 +3632,22 @@ inline void updateJoinSides(uint32_t small, uint32_t large, map& joins, + const std::set& smallSideTid, uint32_t tableId) +{ + const auto it = jobInfo.joinFeTableMap.find(joins[tableId].fJoinId); + if (it != jobInfo.joinFeTableMap.end()) + { + const set& tids = it->second; + for (const auto si : smallSideTid) + { + if (tids.count(si)) + return true; + } + } + return false; +} + // For OUTER JOIN bug @2422/2633/3437/3759, join table based on join order. // The largest table will be always the streaming table, other tables are always on small side. void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap& tableInfoMap, @@ -3734,12 +3750,12 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap& for (uint64_t js = 0; js < joins.size(); js++) { - set smallSideTid; + std::set smallSideTid; if (joins[js].fJoinId != 0) isSemijoin = false; - vector smallSides; + std::vector smallSides; uint32_t tid1 = joins[js].fTid1; uint32_t tid2 = joins[js].fTid2; lastJoinId = joins[js].fJoinId; @@ -3780,6 +3796,14 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap& for (uint64_t ns = js + 1; ns < joins.size(); js++, ns++) { // Check if FE needs table in previous smallsides. + if (needsFeForSmallSides(jobInfo, joins, smallSideTid, ns)) + { + // Mark as `umstream` to prevent an second type of merge optimization, when CS merges smallside into + // current `TupleHashJoinStep`. + umstream = true; + break; + } + uint32_t tid1 = joins[ns].fTid1; uint32_t tid2 = joins[ns].fTid2; uint32_t small = (uint32_t)-1; @@ -3801,20 +3825,6 @@ void joinTablesInOrder(uint32_t largest, JobStepVector& joinSteps, TableInfoMap& break; } - // check if FE needs table in previous smallsides - if (jobInfo.joinFeTableMap[joins[ns].fJoinId].size() > 0) - { - set& tids = jobInfo.joinFeTableMap[joins[ns].fJoinId]; - - for (set::iterator si = smallSideTid.begin(); si != smallSideTid.end(); si++) - { - if (tids.find(*si) != tids.end()) - throw runtime_error( - "On clause filter involving a table not directly involved in the outer join is currently not " - "supported."); - } - } - updateJoinSides(small, large, joinInfoMap, smallSides, tableInfoMap, jobInfo); lastJoinId = joins[ns].fJoinId; diff --git a/mysql-test/columnstore/basic/r/mcol-5167.result b/mysql-test/columnstore/basic/r/mcol-5167.result new file mode 100644 index 000000000..3d7ca7682 --- /dev/null +++ b/mysql-test/columnstore/basic/r/mcol-5167.result @@ -0,0 +1,61 @@ +DROP DATABASE IF EXISTS mcol5167; +CREATE DATABASE mcol5167; +USE mcol5167; +create table t1 (a int, b int) engine=columnstore; +create table t2 (a int, b int) engine=columnstore; +create table t3 (a int, b int) engine=columnstore; +create table t4 (a int, b int) engine=columnstore; +insert into t1 values (1, 3), (2, 3), (3, 4); +insert into t2 values (1, 2), (2, 4), (4, 5); +insert into t3 values (1, 2), (2, 3), (3, 4), (4, 5); +insert into t4 values (1, 2), (2, 3), (3, 4); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b and t2.a > 1); +a b a b a b +1 3 1 2 NULL NULL +2 3 2 4 2 3 +3 4 NULL NULL NULL NULL +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t2.b = t3.b and t1.a > 1); +a b a b a b +1 3 1 2 NULL NULL +2 3 2 4 3 4 +3 4 NULL NULL NULL NULL +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t2.b = t3.b and t1.a > 1 and t2.a > 1); +a b a b a b +1 3 1 2 NULL NULL +2 3 2 4 3 4 +3 4 NULL NULL NULL NULL +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t2.b = t3.b and t2.a > 1 and t1.a > 1); +a b a b a b +1 3 1 2 NULL NULL +2 3 2 4 3 4 +3 4 NULL NULL NULL NULL +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b and t2.a > 3); +a b a b a b +1 3 1 2 NULL NULL +2 3 2 4 NULL NULL +3 4 NULL NULL NULL NULL +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t2.b = t3.b and t1.a > 3); +a b a b a b +1 3 1 2 NULL NULL +2 3 2 4 NULL NULL +3 4 NULL NULL NULL NULL +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b) left join t4 on (t3.a = t4.a and t1.a > 1 and t2.a > 1); +a b a b a b a b +1 3 1 2 2 3 NULL NULL +2 3 2 4 2 3 2 3 +3 4 NULL NULL 3 4 NULL NULL +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b) left join t4 on (t3.a = t4.a and t1.a > 1 and t2.a > 2); +a b a b a b a b +1 3 1 2 2 3 NULL NULL +2 3 2 4 2 3 NULL NULL +3 4 NULL NULL 3 4 NULL NULL +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b and t1.a > 1) left join t4 on (t3.a = t4.a and t1.a > 1 and t2.a > 1); +a b a b a b a b +1 3 1 2 NULL NULL NULL NULL +2 3 2 4 2 3 2 3 +3 4 NULL NULL 3 4 NULL NULL +drop table t1; +drop table t2; +drop table t3; +drop table t4; +DROP DATABASE mcol5167; diff --git a/mysql-test/columnstore/basic/t/mcol-5167.test b/mysql-test/columnstore/basic/t/mcol-5167.test new file mode 100644 index 000000000..318854256 --- /dev/null +++ b/mysql-test/columnstore/basic/t/mcol-5167.test @@ -0,0 +1,37 @@ + +#-- source ../include/have_columnstore.inc + +--disable_warnings +DROP DATABASE IF EXISTS mcol5167; +--enable_warnings + +CREATE DATABASE mcol5167; + +USE mcol5167; + +create table t1 (a int, b int) engine=columnstore; +create table t2 (a int, b int) engine=columnstore; +create table t3 (a int, b int) engine=columnstore; +create table t4 (a int, b int) engine=columnstore; + +insert into t1 values (1, 3), (2, 3), (3, 4); +insert into t2 values (1, 2), (2, 4), (4, 5); +insert into t3 values (1, 2), (2, 3), (3, 4), (4, 5); +insert into t4 values (1, 2), (2, 3), (3, 4); + +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b and t2.a > 1); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t2.b = t3.b and t1.a > 1); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t2.b = t3.b and t1.a > 1 and t2.a > 1); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t2.b = t3.b and t2.a > 1 and t1.a > 1); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b and t2.a > 3); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t2.b = t3.b and t1.a > 3); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b) left join t4 on (t3.a = t4.a and t1.a > 1 and t2.a > 1); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b) left join t4 on (t3.a = t4.a and t1.a > 1 and t2.a > 2); +select * from t1 left join t2 on (t1.a = t2.a) left join t3 on (t1.b = t3.b and t1.a > 1) left join t4 on (t3.a = t4.a and t1.a > 1 and t2.a > 1); + +drop table t1; +drop table t2; +drop table t3; +drop table t4; + +DROP DATABASE mcol5167;