zhouqingqing / qpmodel

A Relational Optimizer and Executor
MIT License
64 stars 18 forks source link

[BUG] Incorrect handling of BETWEEN predicate, EXISTS, NOT EXISTS, IN, NOT IN subqueries #224

Open pkommoju opened 3 years ago

pkommoju commented 3 years ago

This test is from NIST test suite. RunNistTests needs to be run but asserts are suppressed. NIST Test dml014. SELECT PNUM FROM PROJ WHERE BUDGET >= 40000 AND BUDGET <= 60000; Should return only one row, with 'Vienna' but returns four: Deale, Vienna, Deale, Akorn

SELECT CITY FROM STAFF WHERE NOT(GRADE BETWEEN 12 AND 13); Also should return one row but returns many.

Similar problem. SELECT WORKS.HOURS FROM WORKS WHERE WORKS.PNUM NOT IN (SELECT PROJ.PNUM FROM PROJ WHERE PROJ.BUDGET BETWEEN 5000 AND 40000); Returns more than one row.

SELECT HOURS FROM WORKS WHERE PNUM NOT IN (SELECT PNUM FROM WORKS WHERE PNUM IN ('P1','P2','P4','P5','P6')); Returns more than one row.

SELECT STAFF.EMPNAME FROM STAFF WHERE NOT EXISTS (SELECT FROM PROJ WHERE NOT EXISTS (SELECT FROM WORKS WHERE STAFF.EMPNUM = WORKS.EMPNUM AND WORKS.PNUM=PROJ.PNUM)); Returns more than one row.

SUM() in WHERE is not supported but this is valid SQL. SELECT PNUM, SUM(HOURS) FROM WORKS GROUP BY PNUM HAVING EXISTS (SELECT PNAME FROM PROJ WHERE PROJ.PNUM = WORKS.PNUM AND SUM(WORKS.HOURS) > PROJ.BUDGET / 200); Returns error: WHERE condition must be a boolean expression and no aggregation is allowed.

-- BUG: Assertion goes off. Problem with BUDGET - GRADE HOURS 100 IN (-4400, -1000, 4000) not being a BinExpr. It should have been one but it is InListExpr.

SELECT MIN(PNAME) FROM PROJ, WORKS, STAFF WHERE PROJ.PNUM = WORKS.PNUM AND WORKS.EMPNUM = STAFF.EMPNUM AND BUDGET - GRADE HOURS 100 IN (-4400, -1000, 4000); LogicJoin.CreateKeyList() line 620 LogicJoin.AddFilter(Expr filter) line 571 <>cDisplayClass8_0.b0(LogicNode n) line 400 TreeNode1.VisitEachExists(Func2 callback, List1 excluding) line 115 TreeNode1.VisitEachExists(Func2 callback, List1 excluding) line 119 TreeNode1.VisitEachExists(Func2 callback, List`1 excluding) line 119 FilterHelper.PushJoinFilter(LogicNode plan, Expr filter) line 384 SelectStmt.pushdownFilter(LogicNode plan, Expr filter, Boolean pushJoinFilter) line 598 <>cDisplayClass43_0.b0(Expr e) line 654 List1.RemoveAll(Predicate1 match) SelectStmt.FilterPushDown(LogicNode plan, Boolean pushJoinFilter) line 647 SelectStmt.SubstitutionOptimize() line 777

BUG: SELECT EMPNUM, SUM (HOURS) FROM WORKS OWORKS GROUP BY EMPNUM HAVING EMPNUM IN ( SELECT WORKS.EMPNUM FROM WORKS JOIN STAFF ON WORKS.EMPNUM = STAFF.EMPNUM AND HOURS < SUM (OWORKS.HOURS) / 3 AND GRADE > 10) ORDER BY EMPNUM;

qpmodel.dll!qpmodel.utils.TreeNode.VisitEachT(System.Action callback) Line 77 C# qpmodel.dll!qpmodel.utils.TreeNode.VisitEach(System.Action callback) Line 80 C# qpmodel.dll!qpmodel.logic.SelectStmt.CreateSinglePlan() Line 577 C# qpmodel.dll!qpmodel.logic.SelectStmt.CreatePlan() Line 485 C# qpmodel.dll!qpmodel.logic.SQLStatement.Exec() Line 96 C# qpmodel.dll!qpmodel.logic.SQLStatement.ExecSQL(qpmodel.logic.SQLStatement stmt, out string physicplan, qpmodel.logic.QueryOption option) Line 145 C# qpmodel.dll!qpmodel.logic.SQLStatement.ExecSQL(string sql, out qpmodel.logic.SQLStatement stmt, out string physicplan, out string error, qpmodel.logic.QueryOption option) Line 157 C# qpmodel.dll!qpmodel.logic.SQLStatement.ExecSQL(string sql, out string physicplan, out string error, qpmodel.logic.QueryOption option) Line 185 C# test.dll!qpmodel.unittest.TU.ExecuteSQL(string sql, out string physicplan, qpmodel.logic.QueryOption option) Line 57 C# test.dll!qpmodel.unittest.TU.ExecuteSQL(string sql) Line 53 C# test.dll!qpmodel.unittest.NistTests.dml073() Line 3881 C# test.dll!qpmodel.unittest.NistTests.RunNistTests() Line 3299 C# [External Code] And this one too SELECT EMPNUM, SUM (HOURS) FROM WORKS OWORKS GROUP BY EMPNUM HAVING EMPNUM IN ( SELECT WORKS.EMPNUM FROM WORKS JOIN STAFF ON WORKS.EMPNUM = STAFF.EMPNUM AND HOURS >= 10 + AVG (OWORKS.HOURS) AND CITY = 'Deale') ORDER BY EMPNUM;

zhouqingqing commented 3 years ago

how to repro the tests? can you add the NIST as part of the unittest?

pkommoju commented 3 years ago

My branch has it but I think I will separate the Tests into a separate branch and push it so that you can merge into master.

pkommoju commented 3 years ago

branch nist_tests has these tests.

9DemonFox commented 3 years ago

@zhouruiapple ,the NOT IN subqueres is handling in #220