Skip to content

Commit a9c2bc9

Browse files
committed
Fix hint matching for outer joins
1 parent 8d28590 commit a9c2bc9

File tree

7 files changed

+504
-6
lines changed

7 files changed

+504
-6
lines changed

expected/ut-J.out

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4775,3 +4775,103 @@ error hint:
47754775
-> Seq Scan on t3
47764776
(11 rows)
47774777

4778+
----
4779+
---- No. J-4-1 outer join support
4780+
----
4781+
-- No. J-4-1-1 nested outer join as inner side of join
4782+
EXPLAIN (COSTS false) SELECT * FROM s1.t1 JOIN (s1.t2 LEFT JOIN s1.t3 ON t2.c1 = t3.c1) ON t1.c1 = t2.c1;
4783+
QUERY PLAN
4784+
------------------------------------------
4785+
Merge Join
4786+
Merge Cond: (t1.c1 = t2.c1)
4787+
-> Index Scan using t1_i1 on t1
4788+
-> Sort
4789+
Sort Key: t2.c1
4790+
-> Hash Right Join
4791+
Hash Cond: (t3.c1 = t2.c1)
4792+
-> Seq Scan on t3
4793+
-> Hash
4794+
-> Seq Scan on t2
4795+
(10 rows)
4796+
4797+
/*+Leading((t1 (t2 t3))) NestLoop(t1 t2 t3)*/
4798+
EXPLAIN (COSTS false) SELECT * FROM s1.t1 JOIN (s1.t2 LEFT JOIN s1.t3 ON t2.c1 = t3.c1) ON t1.c1 = t2.c1;
4799+
LOG: pg_hint_plan:
4800+
used hint:
4801+
NestLoop(t1 t2 t3)
4802+
Leading((t1 (t2 t3)))
4803+
not used hint:
4804+
duplication hint:
4805+
error hint:
4806+
4807+
QUERY PLAN
4808+
------------------------------------------
4809+
Nested Loop
4810+
Join Filter: (t1.c1 = t2.c1)
4811+
-> Seq Scan on t1
4812+
-> Materialize
4813+
-> Hash Left Join
4814+
Hash Cond: (t2.c1 = t3.c1)
4815+
-> Seq Scan on t2
4816+
-> Hash
4817+
-> Seq Scan on t3
4818+
(9 rows)
4819+
4820+
-- No. J-4-1-2 SEMI join
4821+
EXPLAIN (COSTS false) SELECT * FROM s1.t1 WHERE EXISTS (SELECT 1 FROM s1.t2 WHERE t1.c1 = t2.c1);
4822+
QUERY PLAN
4823+
------------------------------------
4824+
Merge Join
4825+
Merge Cond: (t1.c1 = t2.c1)
4826+
-> Index Scan using t1_i1 on t1
4827+
-> Sort
4828+
Sort Key: t2.c1
4829+
-> Seq Scan on t2
4830+
(6 rows)
4831+
4832+
/*+HashJoin(t1 t2)*/
4833+
EXPLAIN (COSTS false) SELECT * FROM s1.t1 WHERE EXISTS (SELECT 1 FROM s1.t2 WHERE t1.c1 = t2.c1);
4834+
LOG: pg_hint_plan:
4835+
used hint:
4836+
HashJoin(t1 t2)
4837+
not used hint:
4838+
duplication hint:
4839+
error hint:
4840+
4841+
QUERY PLAN
4842+
------------------------------
4843+
Hash Join
4844+
Hash Cond: (t1.c1 = t2.c1)
4845+
-> Seq Scan on t1
4846+
-> Hash
4847+
-> Seq Scan on t2
4848+
(5 rows)
4849+
4850+
-- No. J-4-1-3 ANTI join
4851+
EXPLAIN (COSTS false) SELECT * FROM s1.t1 WHERE NOT EXISTS (SELECT 1 FROM s1.t2 WHERE t1.c1 = t2.c1);
4852+
QUERY PLAN
4853+
------------------------------
4854+
Hash Anti Join
4855+
Hash Cond: (t1.c1 = t2.c1)
4856+
-> Seq Scan on t1
4857+
-> Hash
4858+
-> Seq Scan on t2
4859+
(5 rows)
4860+
4861+
/*+NestLoop(t1 t2)*/
4862+
EXPLAIN (COSTS false) SELECT * FROM s1.t1 WHERE NOT EXISTS (SELECT 1 FROM s1.t2 WHERE t1.c1 = t2.c1);
4863+
LOG: pg_hint_plan:
4864+
used hint:
4865+
NestLoop(t1 t2)
4866+
not used hint:
4867+
duplication hint:
4868+
error hint:
4869+
4870+
QUERY PLAN
4871+
-----------------------------------------
4872+
Nested Loop Anti Join
4873+
-> Seq Scan on t1
4874+
-> Index Only Scan using t2_i1 on t2
4875+
Index Cond: (c1 = t1.c1)
4876+
(4 rows)
4877+

expected/ut-R.out

Lines changed: 262 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4941,3 +4941,265 @@ error hint:
49414941
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
49424942
(6 rows)
49434943

4944+
SET client_min_messages TO LOG;
4945+
----
4946+
---- No. R-4-1 outer join support
4947+
----
4948+
-- No. R-4-1-1 LEFT JOIN
4949+
SELECT explain_filter('
4950+
EXPLAIN SELECT * FROM s1.t1 LEFT JOIN s1.t2 ON t1.c1 = t2.c1;
4951+
');
4952+
explain_filter
4953+
----------------------------------------------------------------
4954+
Hash Left Join (cost=xxx..xxx rows=1000 width=xxx)
4955+
Hash Cond: (t1.c1 = t2.c1)
4956+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
4957+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
4958+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
4959+
(5 rows)
4960+
4961+
SELECT explain_filter('
4962+
/*+Rows(t1 t2 #1)*/
4963+
EXPLAIN SELECT * FROM s1.t1 LEFT JOIN s1.t2 ON t1.c1 = t2.c1;
4964+
');
4965+
LOG: pg_hint_plan:
4966+
used hint:
4967+
Rows(t1 t2 #1)
4968+
not used hint:
4969+
duplication hint:
4970+
error hint:
4971+
4972+
explain_filter
4973+
----------------------------------------------------------------
4974+
Hash Left Join (cost=xxx..xxx rows=1 width=xxx)
4975+
Hash Cond: (t1.c1 = t2.c1)
4976+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
4977+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
4978+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
4979+
(5 rows)
4980+
4981+
-- No. R-4-1-2 RIGHT JOIN
4982+
SELECT explain_filter('
4983+
EXPLAIN SELECT * FROM s1.t1 RIGHT JOIN s1.t2 ON t1.c1 = t2.c1;
4984+
');
4985+
explain_filter
4986+
-------------------------------------------------------------------------
4987+
Merge Right Join (cost=xxx..xxx rows=100 width=xxx)
4988+
Merge Cond: (t1.c1 = t2.c1)
4989+
-> Index Scan using t1_i1 on t1 (cost=xxx..xxx rows=1000 width=xxx)
4990+
-> Sort (cost=xxx..xxx rows=100 width=xxx)
4991+
Sort Key: t2.c1
4992+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
4993+
(6 rows)
4994+
4995+
SELECT explain_filter('
4996+
/*+Rows(t1 t2 #1)*/
4997+
EXPLAIN SELECT * FROM s1.t1 RIGHT JOIN s1.t2 ON t1.c1 = t2.c1;
4998+
');
4999+
LOG: pg_hint_plan:
5000+
used hint:
5001+
Rows(t1 t2 #1)
5002+
not used hint:
5003+
duplication hint:
5004+
error hint:
5005+
5006+
explain_filter
5007+
-------------------------------------------------------------------------
5008+
Merge Right Join (cost=xxx..xxx rows=1 width=xxx)
5009+
Merge Cond: (t1.c1 = t2.c1)
5010+
-> Index Scan using t1_i1 on t1 (cost=xxx..xxx rows=1000 width=xxx)
5011+
-> Sort (cost=xxx..xxx rows=100 width=xxx)
5012+
Sort Key: t2.c1
5013+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5014+
(6 rows)
5015+
5016+
-- No. R-4-1-3 FULL JOIN
5017+
SELECT explain_filter('
5018+
EXPLAIN SELECT * FROM s1.t1 FULL JOIN s1.t2 ON t1.c1 = t2.c1;
5019+
');
5020+
explain_filter
5021+
----------------------------------------------------------------
5022+
Hash Full Join (cost=xxx..xxx rows=1000 width=xxx)
5023+
Hash Cond: (t1.c1 = t2.c1)
5024+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
5025+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5026+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5027+
(5 rows)
5028+
5029+
SELECT explain_filter('
5030+
/*+Rows(t1 t2 #1)*/
5031+
EXPLAIN SELECT * FROM s1.t1 FULL JOIN s1.t2 ON t1.c1 = t2.c1;
5032+
');
5033+
LOG: pg_hint_plan:
5034+
used hint:
5035+
Rows(t1 t2 #1)
5036+
not used hint:
5037+
duplication hint:
5038+
error hint:
5039+
5040+
explain_filter
5041+
----------------------------------------------------------------
5042+
Hash Full Join (cost=xxx..xxx rows=1 width=xxx)
5043+
Hash Cond: (t1.c1 = t2.c1)
5044+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
5045+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5046+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5047+
(5 rows)
5048+
5049+
-- No. R-4-1-4 nested outer joins
5050+
SELECT explain_filter('
5051+
EXPLAIN SELECT * FROM s1.t1 LEFT JOIN s1.t2 ON t1.c1 = t2.c1 LEFT JOIN s1.t3 ON t2.c1 = t3.c1;
5052+
');
5053+
explain_filter
5054+
----------------------------------------------------------------------------
5055+
Hash Left Join (cost=xxx..xxx rows=1000 width=xxx)
5056+
Hash Cond: (t1.c1 = t2.c1)
5057+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
5058+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5059+
-> Hash Right Join (cost=xxx..xxx rows=100 width=xxx)
5060+
Hash Cond: (t3.c1 = t2.c1)
5061+
-> Seq Scan on t3 (cost=xxx..xxx rows=1130 width=xxx)
5062+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5063+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5064+
(9 rows)
5065+
5066+
SELECT explain_filter('
5067+
/*+Rows(t2 t3 #1)*/
5068+
EXPLAIN SELECT * FROM s1.t1 LEFT JOIN s1.t2 ON t1.c1 = t2.c1 LEFT JOIN s1.t3 ON t2.c1 = t3.c1;
5069+
');
5070+
LOG: pg_hint_plan:
5071+
used hint:
5072+
Rows(t2 t3 #1)
5073+
not used hint:
5074+
duplication hint:
5075+
error hint:
5076+
5077+
explain_filter
5078+
----------------------------------------------------------------------------
5079+
Hash Left Join (cost=xxx..xxx rows=1000 width=xxx)
5080+
Hash Cond: (t1.c1 = t2.c1)
5081+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
5082+
-> Hash (cost=xxx..xxx rows=1 width=xxx)
5083+
-> Hash Right Join (cost=xxx..xxx rows=1 width=xxx)
5084+
Hash Cond: (t3.c1 = t2.c1)
5085+
-> Seq Scan on t3 (cost=xxx..xxx rows=1130 width=xxx)
5086+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5087+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5088+
(9 rows)
5089+
5090+
----
5091+
---- No. R-4-2 SEMI/ANTI join support
5092+
----
5093+
-- No. R-4-2-1 SEMI join
5094+
SELECT explain_filter('
5095+
EXPLAIN SELECT * FROM s1.t1 WHERE EXISTS (SELECT 1 FROM s1.t2 WHERE t1.c1 = t2.c1);
5096+
');
5097+
explain_filter
5098+
-------------------------------------------------------------------------
5099+
Merge Join (cost=xxx..xxx rows=100 width=xxx)
5100+
Merge Cond: (t1.c1 = t2.c1)
5101+
-> Index Scan using t1_i1 on t1 (cost=xxx..xxx rows=1000 width=xxx)
5102+
-> Sort (cost=xxx..xxx rows=100 width=xxx)
5103+
Sort Key: t2.c1
5104+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5105+
(6 rows)
5106+
5107+
SELECT explain_filter('
5108+
/*+Rows(t1 t2 #1)*/
5109+
EXPLAIN SELECT * FROM s1.t1 WHERE EXISTS (SELECT 1 FROM s1.t2 WHERE t1.c1 = t2.c1);
5110+
');
5111+
LOG: pg_hint_plan:
5112+
used hint:
5113+
Rows(t1 t2 #1)
5114+
not used hint:
5115+
duplication hint:
5116+
error hint:
5117+
5118+
explain_filter
5119+
-------------------------------------------------------------------------
5120+
Merge Join (cost=xxx..xxx rows=1 width=xxx)
5121+
Merge Cond: (t1.c1 = t2.c1)
5122+
-> Index Scan using t1_i1 on t1 (cost=xxx..xxx rows=1000 width=xxx)
5123+
-> Sort (cost=xxx..xxx rows=100 width=xxx)
5124+
Sort Key: t2.c1
5125+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5126+
(6 rows)
5127+
5128+
-- No. R-4-2-2 ANTI join
5129+
SELECT explain_filter('
5130+
EXPLAIN SELECT * FROM s1.t1 WHERE NOT EXISTS (SELECT 1 FROM s1.t2 WHERE t1.c1 = t2.c1);
5131+
');
5132+
explain_filter
5133+
----------------------------------------------------------------
5134+
Hash Anti Join (cost=xxx..xxx rows=900 width=xxx)
5135+
Hash Cond: (t1.c1 = t2.c1)
5136+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
5137+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5138+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5139+
(5 rows)
5140+
5141+
SELECT explain_filter('
5142+
/*+Rows(t1 t2 #1)*/
5143+
EXPLAIN SELECT * FROM s1.t1 WHERE NOT EXISTS (SELECT 1 FROM s1.t2 WHERE t1.c1 = t2.c1);
5144+
');
5145+
LOG: pg_hint_plan:
5146+
used hint:
5147+
Rows(t1 t2 #1)
5148+
not used hint:
5149+
duplication hint:
5150+
error hint:
5151+
5152+
explain_filter
5153+
----------------------------------------------------------------
5154+
Hash Anti Join (cost=xxx..xxx rows=1 width=xxx)
5155+
Hash Cond: (t1.c1 = t2.c1)
5156+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
5157+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5158+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5159+
(5 rows)
5160+
5161+
----
5162+
---- No. R-4-3 negative tests
5163+
----
5164+
-- No. R-4-3-1 hint references non-existent table
5165+
SELECT explain_filter('
5166+
/*+Rows(t1 t99 #1)*/
5167+
EXPLAIN SELECT * FROM s1.t1 LEFT JOIN s1.t2 ON t1.c1 = t2.c1;
5168+
');
5169+
LOG: pg_hint_plan:
5170+
used hint:
5171+
not used hint:
5172+
Rows(t1 t99 #1)
5173+
duplication hint:
5174+
error hint:
5175+
5176+
explain_filter
5177+
----------------------------------------------------------------
5178+
Hash Left Join (cost=xxx..xxx rows=1000 width=xxx)
5179+
Hash Cond: (t1.c1 = t2.c1)
5180+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
5181+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5182+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5183+
(5 rows)
5184+
5185+
-- No. R-4-3-2 hint references tables not in join
5186+
SELECT explain_filter('
5187+
/*+Rows(t1 t3 #1)*/
5188+
EXPLAIN SELECT * FROM s1.t1 LEFT JOIN s1.t2 ON t1.c1 = t2.c1;
5189+
');
5190+
LOG: pg_hint_plan:
5191+
used hint:
5192+
not used hint:
5193+
Rows(t1 t3 #1)
5194+
duplication hint:
5195+
error hint:
5196+
5197+
explain_filter
5198+
----------------------------------------------------------------
5199+
Hash Left Join (cost=xxx..xxx rows=1000 width=xxx)
5200+
Hash Cond: (t1.c1 = t2.c1)
5201+
-> Seq Scan on t1 (cost=xxx..xxx rows=1000 width=xxx)
5202+
-> Hash (cost=xxx..xxx rows=100 width=xxx)
5203+
-> Seq Scan on t2 (cost=xxx..xxx rows=100 width=xxx)
5204+
(5 rows)
5205+

0 commit comments

Comments
 (0)