You've already forked mariadb-columnstore-engine
mirror of
https://github.com/mariadb-corporation/mariadb-columnstore-engine.git
synced 2025-07-30 19:23:07 +03:00
MCOL-4715 Mixed inner and outer joins with "null" filter for the table which is not involved into the outer join produces wrong results.
This commit is contained in:
@ -286,6 +286,8 @@ struct JobInfo
|
|||||||
|
|
||||||
// bug 2634, 5311 and 5374, outjoin and predicates
|
// bug 2634, 5311 and 5374, outjoin and predicates
|
||||||
std::set<uint32_t> outerOnTable;
|
std::set<uint32_t> outerOnTable;
|
||||||
|
// MCOL-4715.
|
||||||
|
std::set<uint32_t> innerOnTable;
|
||||||
std::set<uint32_t> tableHasIsNull;
|
std::set<uint32_t> tableHasIsNull;
|
||||||
JobStepVector outerJoinExpressions;
|
JobStepVector outerJoinExpressions;
|
||||||
|
|
||||||
|
@ -1576,6 +1576,12 @@ bool addFunctionJoin(vector<uint32_t>& joinedTables, JobStepVector& joinSteps, s
|
|||||||
{
|
{
|
||||||
m1->second.fTypes.push_back(joinType);
|
m1->second.fTypes.push_back(joinType);
|
||||||
m2->second.fTypes.push_back(joinType);
|
m2->second.fTypes.push_back(joinType);
|
||||||
|
|
||||||
|
if (joinType == INNER)
|
||||||
|
{
|
||||||
|
jobInfo.innerOnTable.insert(tid1);
|
||||||
|
jobInfo.innerOnTable.insert(tid2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// need id to keep the join order
|
// need id to keep the join order
|
||||||
@ -2513,12 +2519,21 @@ void spanningTreeCheck(TableInfoMap& tableInfoMap, JobStepVector& joinSteps, Job
|
|||||||
|
|
||||||
void outjoinPredicateAdjust(TableInfoMap& tableInfoMap, JobInfo& jobInfo)
|
void outjoinPredicateAdjust(TableInfoMap& tableInfoMap, JobInfo& jobInfo)
|
||||||
{
|
{
|
||||||
set<uint32_t>::iterator i = jobInfo.outerOnTable.begin();
|
std::set<uint32_t> tables = jobInfo.outerOnTable;
|
||||||
|
if (!tables.size())
|
||||||
|
return;
|
||||||
|
|
||||||
for (; i != jobInfo.outerOnTable.end(); i++)
|
// Mixed outer/inner joins and a table with a `null filter`.
|
||||||
|
for (const auto tableId : jobInfo.innerOnTable)
|
||||||
{
|
{
|
||||||
// resetTableFilters(tableInfoMap[*i], jobInfo)
|
if (jobInfo.tableHasIsNull.find(tableId) != jobInfo.tableHasIsNull.end())
|
||||||
TableInfo& tblInfo = tableInfoMap[*i];
|
tables.insert(tableId);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto tableId : tables)
|
||||||
|
{
|
||||||
|
// resetTableFilters(tableInfoMap[tableId], jobInfo)
|
||||||
|
TableInfo& tblInfo = tableInfoMap[tableId];
|
||||||
|
|
||||||
if (tblInfo.fTableOid != CNX_VTABLE_ID)
|
if (tblInfo.fTableOid != CNX_VTABLE_ID)
|
||||||
{
|
{
|
||||||
@ -2597,7 +2612,7 @@ void outjoinPredicateAdjust(TableInfoMap& tableInfoMap, JobInfo& jobInfo)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Do not apply the primitive filters if there is an "IS NULL" in where clause.
|
// Do not apply the primitive filters if there is an "IS NULL" in where clause.
|
||||||
if (jobInfo.tableHasIsNull.find(*i) != jobInfo.tableHasIsNull.end())
|
if (jobInfo.tableHasIsNull.find(tableId) != jobInfo.tableHasIsNull.end())
|
||||||
tblInfo.fQuerySteps = onClauseFilterSteps;
|
tblInfo.fQuerySteps = onClauseFilterSteps;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4740,6 +4755,12 @@ void associateTupleJobSteps(JobStepVector& querySteps, JobStepVector& projectSte
|
|||||||
{
|
{
|
||||||
m1->second.fTypes.push_back(joinType);
|
m1->second.fTypes.push_back(joinType);
|
||||||
m2->second.fTypes.push_back(joinType);
|
m2->second.fTypes.push_back(joinType);
|
||||||
|
|
||||||
|
if (joinType == INNER)
|
||||||
|
{
|
||||||
|
jobInfo.innerOnTable.insert(tid1);
|
||||||
|
jobInfo.innerOnTable.insert(tid2);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// need id to keep the join order
|
// need id to keep the join order
|
||||||
|
30
mysql-test/columnstore/bugfixes/mcol-4715.result
Normal file
30
mysql-test/columnstore/bugfixes/mcol-4715.result
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
DROP DATABASE IF EXISTS mcol_4715;
|
||||||
|
CREATE DATABASE mcol_4715;
|
||||||
|
USE mcol_4715;
|
||||||
|
create table t1 (a int) engine=columnstore;
|
||||||
|
create table t2 (a int) engine=columnstore;
|
||||||
|
create table t3 (a int) engine=columnstore;
|
||||||
|
create table t4 (a int) engine=columnstore;
|
||||||
|
insert into t1 values (1), (2), (3), (4);
|
||||||
|
insert into t2 values (2), (3), (4);
|
||||||
|
insert into t3 values (3), (4);
|
||||||
|
insert into t4 values (4);
|
||||||
|
select * from t1 left join t2 left join t3 on t2.a=t3.a on t1.a=t3.a where t2.a is null order by t1.a;
|
||||||
|
a a a
|
||||||
|
1 NULL NULL
|
||||||
|
2 NULL NULL
|
||||||
|
select * from t2 inner join t3 on t2.a = t3.a right join t1 on t1.a = t3.a where t2.a is null order by t1.a;
|
||||||
|
a a a
|
||||||
|
NULL NULL 1
|
||||||
|
NULL NULL 2
|
||||||
|
select * from t1 left join t2 on t1.a=t2.a left join t3 left join t4 on t3.a=t4.a on t1.a=t4.a where t3.a is null order by t1.a;
|
||||||
|
a a a a
|
||||||
|
1 NULL NULL NULL
|
||||||
|
2 2 NULL NULL
|
||||||
|
3 3 NULL NULL
|
||||||
|
select * from t1 left join t2 on t1.a=t2.a left join t3 left join t4 on t3.a=t4.a on t2.a=t4.a where t3.a is null order by t1.a;
|
||||||
|
a a a a
|
||||||
|
1 NULL NULL NULL
|
||||||
|
2 2 NULL NULL
|
||||||
|
3 3 NULL NULL
|
||||||
|
DROP DATABASE mcol_4715;
|
28
mysql-test/columnstore/bugfixes/mcol-4715.test
Normal file
28
mysql-test/columnstore/bugfixes/mcol-4715.test
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
#
|
||||||
|
# Mixed inner and outer joins with "null filter" for the table which is not involved into the outer join produces wrong results.
|
||||||
|
#
|
||||||
|
|
||||||
|
-- source ../include/have_columnstore.inc
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
DROP DATABASE IF EXISTS mcol_4715;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
CREATE DATABASE mcol_4715;
|
||||||
|
USE mcol_4715;
|
||||||
|
|
||||||
|
create table t1 (a int) engine=columnstore;
|
||||||
|
create table t2 (a int) engine=columnstore;
|
||||||
|
create table t3 (a int) engine=columnstore;
|
||||||
|
create table t4 (a int) engine=columnstore;
|
||||||
|
insert into t1 values (1), (2), (3), (4);
|
||||||
|
insert into t2 values (2), (3), (4);
|
||||||
|
insert into t3 values (3), (4);
|
||||||
|
insert into t4 values (4);
|
||||||
|
|
||||||
|
select * from t1 left join t2 left join t3 on t2.a=t3.a on t1.a=t3.a where t2.a is null order by t1.a;
|
||||||
|
select * from t2 inner join t3 on t2.a = t3.a right join t1 on t1.a = t3.a where t2.a is null order by t1.a;
|
||||||
|
select * from t1 left join t2 on t1.a=t2.a left join t3 left join t4 on t3.a=t4.a on t1.a=t4.a where t3.a is null order by t1.a;
|
||||||
|
select * from t1 left join t2 on t1.a=t2.a left join t3 left join t4 on t3.a=t4.a on t2.a=t4.a where t3.a is null order by t1.a;
|
||||||
|
|
||||||
|
DROP DATABASE mcol_4715;
|
Reference in New Issue
Block a user