1
0
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:
Denis Khalikov
2022-08-16 00:12:15 +03:00
parent a7a9ccf889
commit 59166608b1
4 changed files with 86 additions and 5 deletions

View File

@ -286,6 +286,8 @@ struct JobInfo
// bug 2634, 5311 and 5374, outjoin and predicates
std::set<uint32_t> outerOnTable;
// MCOL-4715.
std::set<uint32_t> innerOnTable;
std::set<uint32_t> tableHasIsNull;
JobStepVector outerJoinExpressions;

View File

@ -1576,6 +1576,12 @@ bool addFunctionJoin(vector<uint32_t>& joinedTables, JobStepVector& joinSteps, s
{
m1->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
@ -2513,12 +2519,21 @@ void spanningTreeCheck(TableInfoMap& tableInfoMap, JobStepVector& joinSteps, Job
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)
TableInfo& tblInfo = tableInfoMap[*i];
if (jobInfo.tableHasIsNull.find(tableId) != jobInfo.tableHasIsNull.end())
tables.insert(tableId);
}
for (const auto tableId : tables)
{
// resetTableFilters(tableInfoMap[tableId], jobInfo)
TableInfo& tblInfo = tableInfoMap[tableId];
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.
if (jobInfo.tableHasIsNull.find(*i) != jobInfo.tableHasIsNull.end())
if (jobInfo.tableHasIsNull.find(tableId) != jobInfo.tableHasIsNull.end())
tblInfo.fQuerySteps = onClauseFilterSteps;
}
@ -4740,6 +4755,12 @@ void associateTupleJobSteps(JobStepVector& querySteps, JobStepVector& projectSte
{
m1->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

View 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;

View 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;