Skip to content

Commit d69d01b

Browse files
committed
Fix Memoize to work with partitionwise joining.
A couple of places weren't up to speed for this. By sheer good luck, we didn't fail but just selected a non-memoized join plan, at least in the test case we have. Nonetheless, it's a bug, and I'm not quite sure that it couldn't have worse consequences in other examples. So back-patch to v14 where Memoize came in. Richard Guo Discussion: https://postgr.es/m/CAMbWs48GkNom272sfp0-WeD6_0HSR19BJ4H1c9ZKSfbVnJsvRg@mail.gmail.com
1 parent 35ce24c commit d69d01b

File tree

5 files changed

+63
-3
lines changed

5 files changed

+63
-3
lines changed

src/backend/optimizer/path/joinpath.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -597,7 +597,8 @@ get_memoize_path(PlannerInfo *root, RelOptInfo *innerrel,
597597
/* Check if we have hash ops for each parameter to the path */
598598
if (paraminfo_get_equal_hashops(root,
599599
inner_path->param_info,
600-
outerrel,
600+
outerrel->top_parent ?
601+
outerrel->top_parent : outerrel,
601602
innerrel,
602603
&param_exprs,
603604
&hash_operators,

src/backend/optimizer/util/pathnode.c

+1
Original file line numberDiff line numberDiff line change
@@ -4246,6 +4246,7 @@ do { \
42464246

42474247
FLAT_COPY_PATH(mpath, path, MemoizePath);
42484248
REPARAMETERIZE_CHILD_PATH(mpath->subpath);
4249+
ADJUST_CHILD_ATTRS(mpath->param_exprs);
42494250
new_path = (Path *) mpath;
42504251
}
42514252
break;

src/include/nodes/pathnodes.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -1865,8 +1865,8 @@ typedef struct MemoizePath
18651865
{
18661866
Path path;
18671867
Path *subpath; /* outerpath to cache tuples from */
1868-
List *hash_operators; /* hash operators for each key */
1869-
List *param_exprs; /* cache keys */
1868+
List *hash_operators; /* OIDs of hash equality ops for cache keys */
1869+
List *param_exprs; /* expressions that are cache keys */
18701870
bool singlerow; /* true if the cache entry is to be marked as
18711871
* complete after caching the first record. */
18721872
bool binary_mode; /* true when cache key should be compared bit

src/test/regress/expected/memoize.out

+39
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,45 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false);
197197
(8 rows)
198198

199199
DROP TABLE strtest;
200+
-- Ensure memoize works with partitionwise join
201+
SET enable_partitionwise_join TO on;
202+
CREATE TABLE prt (a int) PARTITION BY RANGE(a);
203+
CREATE TABLE prt_p1 PARTITION OF prt FOR VALUES FROM (0) TO (10);
204+
CREATE TABLE prt_p2 PARTITION OF prt FOR VALUES FROM (10) TO (20);
205+
INSERT INTO prt VALUES (0), (0), (0), (0);
206+
INSERT INTO prt VALUES (10), (10), (10), (10);
207+
CREATE INDEX iprt_p1_a ON prt_p1 (a);
208+
CREATE INDEX iprt_p2_a ON prt_p2 (a);
209+
ANALYZE prt;
210+
SELECT explain_memoize('
211+
SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false);
212+
explain_memoize
213+
------------------------------------------------------------------------------------------
214+
Append (actual rows=32 loops=N)
215+
-> Nested Loop (actual rows=16 loops=N)
216+
-> Index Only Scan using iprt_p1_a on prt_p1 t1_1 (actual rows=4 loops=N)
217+
Heap Fetches: N
218+
-> Memoize (actual rows=4 loops=N)
219+
Cache Key: t1_1.a
220+
Cache Mode: logical
221+
Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB
222+
-> Index Only Scan using iprt_p1_a on prt_p1 t2_1 (actual rows=4 loops=N)
223+
Index Cond: (a = t1_1.a)
224+
Heap Fetches: N
225+
-> Nested Loop (actual rows=16 loops=N)
226+
-> Index Only Scan using iprt_p2_a on prt_p2 t1_2 (actual rows=4 loops=N)
227+
Heap Fetches: N
228+
-> Memoize (actual rows=4 loops=N)
229+
Cache Key: t1_2.a
230+
Cache Mode: logical
231+
Hits: 3 Misses: 1 Evictions: Zero Overflows: 0 Memory Usage: NkB
232+
-> Index Only Scan using iprt_p2_a on prt_p2 t2_2 (actual rows=4 loops=N)
233+
Index Cond: (a = t1_2.a)
234+
Heap Fetches: N
235+
(21 rows)
236+
237+
DROP TABLE prt;
238+
RESET enable_partitionwise_join;
200239
-- Exercise Memoize code that flushes the cache when a parameter changes which
201240
-- is not part of the cache key.
202241
-- Ensure we get a Memoize plan

src/test/regress/sql/memoize.sql

+19
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,25 @@ SELECT * FROM strtest s1 INNER JOIN strtest s2 ON s1.t >= s2.t;', false);
104104

105105
DROP TABLE strtest;
106106

107+
-- Ensure memoize works with partitionwise join
108+
SET enable_partitionwise_join TO on;
109+
110+
CREATE TABLE prt (a int) PARTITION BY RANGE(a);
111+
CREATE TABLE prt_p1 PARTITION OF prt FOR VALUES FROM (0) TO (10);
112+
CREATE TABLE prt_p2 PARTITION OF prt FOR VALUES FROM (10) TO (20);
113+
INSERT INTO prt VALUES (0), (0), (0), (0);
114+
INSERT INTO prt VALUES (10), (10), (10), (10);
115+
CREATE INDEX iprt_p1_a ON prt_p1 (a);
116+
CREATE INDEX iprt_p2_a ON prt_p2 (a);
117+
ANALYZE prt;
118+
119+
SELECT explain_memoize('
120+
SELECT * FROM prt t1 INNER JOIN prt t2 ON t1.a = t2.a;', false);
121+
122+
DROP TABLE prt;
123+
124+
RESET enable_partitionwise_join;
125+
107126
-- Exercise Memoize code that flushes the cache when a parameter changes which
108127
-- is not part of the cache key.
109128

0 commit comments

Comments
 (0)