summaryrefslogtreecommitdiff
path: root/src/test
diff options
context:
space:
mode:
Diffstat (limited to 'src/test')
-rw-r--r--src/test/regress/expected/aggregates.out2
-rw-r--r--src/test/regress/expected/join.out131
-rw-r--r--src/test/regress/expected/partition_prune.out5
-rw-r--r--src/test/regress/expected/resultcache.out158
-rw-r--r--src/test/regress/expected/subselect.out20
-rw-r--r--src/test/regress/expected/sysviews.out3
-rw-r--r--src/test/regress/parallel_schedule2
-rw-r--r--src/test/regress/serial_schedule1
-rw-r--r--src/test/regress/sql/aggregates.sql2
-rw-r--r--src/test/regress/sql/join.sql2
-rw-r--r--src/test/regress/sql/partition_prune.sql5
-rw-r--r--src/test/regress/sql/resultcache.sql91
12 files changed, 358 insertions, 64 deletions
diff --git a/src/test/regress/expected/aggregates.out b/src/test/regress/expected/aggregates.out
index 1ae0e5d9398..ca06d41dd04 100644
--- a/src/test/regress/expected/aggregates.out
+++ b/src/test/regress/expected/aggregates.out
@@ -2584,6 +2584,7 @@ select v||'a', case when v||'a' = 'aa' then 1 else 0 end, count(*)
-- Make sure that generation of HashAggregate for uniqification purposes
-- does not lead to array overflow due to unexpected duplicate hash keys
-- see CAFeeJoKKu0u+A_A9R9316djW-YW3-+Gtgvy3ju655qRHR3jtdA@mail.gmail.com
+set enable_resultcache to off;
explain (costs off)
select 1 from tenk1
where (hundred, thousand) in (select twothousand, twothousand from onek);
@@ -2599,6 +2600,7 @@ explain (costs off)
-> Seq Scan on onek
(8 rows)
+reset enable_resultcache;
--
-- Hash Aggregation Spill tests
--
diff --git a/src/test/regress/expected/join.out b/src/test/regress/expected/join.out
index 04e802d4213..86fd3907c53 100644
--- a/src/test/regress/expected/join.out
+++ b/src/test/regress/expected/join.out
@@ -2536,6 +2536,7 @@ reset enable_nestloop;
--
set work_mem to '64kB';
set enable_mergejoin to off;
+set enable_resultcache to off;
explain (costs off)
select count(*) from tenk1 a, tenk1 b
where a.hundred = b.thousand and (b.fivethous % 10) < 10;
@@ -2559,6 +2560,7 @@ select count(*) from tenk1 a, tenk1 b
reset work_mem;
reset enable_mergejoin;
+reset enable_resultcache;
--
-- regression test for 8.2 bug with improper re-ordering of left joins
--
@@ -3663,8 +3665,8 @@ select * from tenk1 t1 left join
(tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2)
on t1.hundred = t2.hundred and t1.ten = t3.ten
where t1.unique1 = 1;
- QUERY PLAN
---------------------------------------------------------
+ QUERY PLAN
+--------------------------------------------------------------
Nested Loop Left Join
-> Index Scan using tenk1_unique1 on tenk1 t1
Index Cond: (unique1 = 1)
@@ -3674,17 +3676,19 @@ where t1.unique1 = 1;
Recheck Cond: (t1.hundred = hundred)
-> Bitmap Index Scan on tenk1_hundred
Index Cond: (hundred = t1.hundred)
- -> Index Scan using tenk1_unique2 on tenk1 t3
- Index Cond: (unique2 = t2.thousand)
-(11 rows)
+ -> Result Cache
+ Cache Key: t2.thousand
+ -> Index Scan using tenk1_unique2 on tenk1 t3
+ Index Cond: (unique2 = t2.thousand)
+(13 rows)
explain (costs off)
select * from tenk1 t1 left join
(tenk1 t2 join tenk1 t3 on t2.thousand = t3.unique2)
on t1.hundred = t2.hundred and t1.ten + t2.ten = t3.ten
where t1.unique1 = 1;
- QUERY PLAN
---------------------------------------------------------
+ QUERY PLAN
+--------------------------------------------------------------
Nested Loop Left Join
-> Index Scan using tenk1_unique1 on tenk1 t1
Index Cond: (unique1 = 1)
@@ -3694,9 +3698,11 @@ where t1.unique1 = 1;
Recheck Cond: (t1.hundred = hundred)
-> Bitmap Index Scan on tenk1_hundred
Index Cond: (hundred = t1.hundred)
- -> Index Scan using tenk1_unique2 on tenk1 t3
- Index Cond: (unique2 = t2.thousand)
-(11 rows)
+ -> Result Cache
+ Cache Key: t2.thousand
+ -> Index Scan using tenk1_unique2 on tenk1 t3
+ Index Cond: (unique2 = t2.thousand)
+(13 rows)
explain (costs off)
select count(*) from
@@ -4210,8 +4216,8 @@ where t1.f1 = ss.f1;
QUERY PLAN
--------------------------------------------------
Nested Loop
- Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1
- Join Filter: (t1.f1 = t2.f1)
+ Output: t1.f1, i8.q1, i8.q2, q1, f1
+ Join Filter: (t1.f1 = f1)
-> Nested Loop Left Join
Output: t1.f1, i8.q1, i8.q2
-> Seq Scan on public.text_tbl t1
@@ -4221,11 +4227,14 @@ where t1.f1 = ss.f1;
-> Seq Scan on public.int8_tbl i8
Output: i8.q1, i8.q2
Filter: (i8.q2 = 123)
- -> Limit
- Output: (i8.q1), t2.f1
- -> Seq Scan on public.text_tbl t2
- Output: i8.q1, t2.f1
-(16 rows)
+ -> Result Cache
+ Output: q1, f1
+ Cache Key: i8.q1
+ -> Limit
+ Output: (i8.q1), t2.f1
+ -> Seq Scan on public.text_tbl t2
+ Output: i8.q1, t2.f1
+(19 rows)
select * from
text_tbl t1
@@ -4246,13 +4255,13 @@ select * from
lateral (select i8.q1, t2.f1 from text_tbl t2 limit 1) as ss1,
lateral (select ss1.* from text_tbl t3 limit 1) as ss2
where t1.f1 = ss2.f1;
- QUERY PLAN
--------------------------------------------------------------------
+ QUERY PLAN
+--------------------------------------------------------
Nested Loop
- Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1, ((i8.q1)), (t2.f1)
- Join Filter: (t1.f1 = (t2.f1))
+ Output: t1.f1, i8.q1, i8.q2, q1, f1, q1, f1
+ Join Filter: (t1.f1 = f1)
-> Nested Loop
- Output: t1.f1, i8.q1, i8.q2, (i8.q1), t2.f1
+ Output: t1.f1, i8.q1, i8.q2, q1, f1
-> Nested Loop Left Join
Output: t1.f1, i8.q1, i8.q2
-> Seq Scan on public.text_tbl t1
@@ -4262,15 +4271,21 @@ where t1.f1 = ss2.f1;
-> Seq Scan on public.int8_tbl i8
Output: i8.q1, i8.q2
Filter: (i8.q2 = 123)
+ -> Result Cache
+ Output: q1, f1
+ Cache Key: i8.q1
+ -> Limit
+ Output: (i8.q1), t2.f1
+ -> Seq Scan on public.text_tbl t2
+ Output: i8.q1, t2.f1
+ -> Result Cache
+ Output: q1, f1
+ Cache Key: q1, f1
-> Limit
- Output: (i8.q1), t2.f1
- -> Seq Scan on public.text_tbl t2
- Output: i8.q1, t2.f1
- -> Limit
- Output: ((i8.q1)), (t2.f1)
- -> Seq Scan on public.text_tbl t3
- Output: (i8.q1), t2.f1
-(22 rows)
+ Output: (q1), (f1)
+ -> Seq Scan on public.text_tbl t3
+ Output: q1, f1
+(28 rows)
select * from
text_tbl t1
@@ -4316,14 +4331,17 @@ where tt1.f1 = ss1.c0;
-> Seq Scan on public.text_tbl tt4
Output: tt4.f1
Filter: (tt4.f1 = 'foo'::text)
- -> Subquery Scan on ss1
+ -> Result Cache
Output: ss1.c0
- Filter: (ss1.c0 = 'foo'::text)
- -> Limit
- Output: (tt4.f1)
- -> Seq Scan on public.text_tbl tt5
- Output: tt4.f1
-(29 rows)
+ Cache Key: tt4.f1
+ -> Subquery Scan on ss1
+ Output: ss1.c0
+ Filter: (ss1.c0 = 'foo'::text)
+ -> Limit
+ Output: (tt4.f1)
+ -> Seq Scan on public.text_tbl tt5
+ Output: tt4.f1
+(32 rows)
select 1 from
text_tbl as tt1
@@ -4997,34 +5015,40 @@ select count(*) from tenk1 a, lateral generate_series(1,two) g;
explain (costs off)
select count(*) from tenk1 a, lateral generate_series(1,two) g;
- QUERY PLAN
-------------------------------------------------
+ QUERY PLAN
+------------------------------------------------------
Aggregate
-> Nested Loop
-> Seq Scan on tenk1 a
- -> Function Scan on generate_series g
-(4 rows)
+ -> Result Cache
+ Cache Key: a.two
+ -> Function Scan on generate_series g
+(6 rows)
explain (costs off)
select count(*) from tenk1 a cross join lateral generate_series(1,two) g;
- QUERY PLAN
-------------------------------------------------
+ QUERY PLAN
+------------------------------------------------------
Aggregate
-> Nested Loop
-> Seq Scan on tenk1 a
- -> Function Scan on generate_series g
-(4 rows)
+ -> Result Cache
+ Cache Key: a.two
+ -> Function Scan on generate_series g
+(6 rows)
-- don't need the explicit LATERAL keyword for functions
explain (costs off)
select count(*) from tenk1 a, generate_series(1,two) g;
- QUERY PLAN
-------------------------------------------------
+ QUERY PLAN
+------------------------------------------------------
Aggregate
-> Nested Loop
-> Seq Scan on tenk1 a
- -> Function Scan on generate_series g
-(4 rows)
+ -> Result Cache
+ Cache Key: a.two
+ -> Function Scan on generate_series g
+(6 rows)
-- lateral with UNION ALL subselect
explain (costs off)
@@ -5079,14 +5103,15 @@ explain (costs off)
QUERY PLAN
------------------------------------------------------------------
Aggregate
- -> Hash Join
- Hash Cond: ("*VALUES*".column1 = b.unique2)
+ -> Nested Loop
-> Nested Loop
-> Index Only Scan using tenk1_unique1 on tenk1 a
-> Values Scan on "*VALUES*"
- -> Hash
+ -> Result Cache
+ Cache Key: "*VALUES*".column1
-> Index Only Scan using tenk1_unique2 on tenk1 b
-(8 rows)
+ Index Cond: (unique2 = "*VALUES*".column1)
+(9 rows)
select count(*) from tenk1 a,
tenk1 b join lateral (values(a.unique1),(-1)) ss(x) on b.unique2 = ss.x;
diff --git a/src/test/regress/expected/partition_prune.out b/src/test/regress/expected/partition_prune.out
index c4e827caec3..1a7149bfd57 100644
--- a/src/test/regress/expected/partition_prune.out
+++ b/src/test/regress/expected/partition_prune.out
@@ -1958,6 +1958,9 @@ begin
ln := regexp_replace(ln, 'Workers Launched: \d+', 'Workers Launched: N');
ln := regexp_replace(ln, 'actual rows=\d+ loops=\d+', 'actual rows=N loops=N');
ln := regexp_replace(ln, 'Rows Removed by Filter: \d+', 'Rows Removed by Filter: N');
+ ln := regexp_replace(ln, 'Hits: \d+', 'Hits: N');
+ ln := regexp_replace(ln, 'Misses: \d+', 'Misses: N');
+ ln := regexp_replace(ln, 'Memory Usage: \d+', 'Memory Usage: N');
return next ln;
end loop;
end;
@@ -2085,6 +2088,7 @@ create index ab_a3_b2_a_idx on ab_a3_b2 (a);
create index ab_a3_b3_a_idx on ab_a3_b3 (a);
set enable_hashjoin = 0;
set enable_mergejoin = 0;
+set enable_resultcache = 0;
select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(0, 0, 1)');
explain_parallel_append
--------------------------------------------------------------------------------------------------------
@@ -2253,6 +2257,7 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
reset enable_hashjoin;
reset enable_mergejoin;
+reset enable_resultcache;
reset parallel_setup_cost;
reset parallel_tuple_cost;
reset min_parallel_table_scan_size;
diff --git a/src/test/regress/expected/resultcache.out b/src/test/regress/expected/resultcache.out
new file mode 100644
index 00000000000..65d9e251692
--- /dev/null
+++ b/src/test/regress/expected/resultcache.out
@@ -0,0 +1,158 @@
+-- Perform tests on the Result Cache node.
+-- The cache hits/misses/evictions from the Result Cache node can vary between
+-- machines. Let's just replace the number with an 'N'. In order to allow us
+-- to perform validation when the measure was zero, we replace a zero value
+-- with "Zero". All other numbers are replaced with 'N'.
+create function explain_resultcache(query text, hide_hitmiss bool) returns setof text
+language plpgsql as
+$$
+declare
+ ln text;
+begin
+ for ln in
+ execute format('explain (analyze, costs off, summary off, timing off) %s',
+ query)
+ loop
+ if hide_hitmiss = true then
+ ln := regexp_replace(ln, 'Hits: 0', 'Hits: Zero');
+ ln := regexp_replace(ln, 'Hits: \d+', 'Hits: N');
+ ln := regexp_replace(ln, 'Misses: 0', 'Misses: Zero');
+ ln := regexp_replace(ln, 'Misses: \d+', 'Misses: N');
+ end if;
+ ln := regexp_replace(ln, 'Evictions: 0', 'Evictions: Zero');
+ ln := regexp_replace(ln, 'Evictions: \d+', 'Evictions: N');
+ ln := regexp_replace(ln, 'Memory Usage: \d+', 'Memory Usage: N');
+ ln := regexp_replace(ln, 'Heap Fetches: \d+', 'Heap Fetches: N');
+ return next ln;
+ end loop;
+end;
+$$;
+-- Ensure we get a result cache on the inner side of the nested loop
+SET enable_hashjoin TO off;
+SET enable_bitmapscan TO off;
+SELECT explain_resultcache('
+SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
+INNER JOIN tenk1 t2 ON t1.unique1 = t2.twenty
+WHERE t2.unique1 < 1000;', false);
+ explain_resultcache
+--------------------------------------------------------------------------------------------
+ Aggregate (actual rows=1 loops=1)
+ -> Nested Loop (actual rows=1000 loops=1)
+ -> Seq Scan on tenk1 t2 (actual rows=1000 loops=1)
+ Filter: (unique1 < 1000)
+ Rows Removed by Filter: 9000
+ -> Result Cache (actual rows=1 loops=1000)
+ Cache Key: t2.twenty
+ Hits: 980 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB
+ -> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1 loops=20)
+ Index Cond: (unique1 = t2.twenty)
+ Heap Fetches: N
+(11 rows)
+
+-- And check we get the expected results.
+SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
+INNER JOIN tenk1 t2 ON t1.unique1 = t2.twenty
+WHERE t2.unique1 < 1000;
+ count | avg
+-------+--------------------
+ 1000 | 9.5000000000000000
+(1 row)
+
+-- Try with LATERAL joins
+SELECT explain_resultcache('
+SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
+LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2
+WHERE t1.unique1 < 1000;', false);
+ explain_resultcache
+--------------------------------------------------------------------------------------------
+ Aggregate (actual rows=1 loops=1)
+ -> Nested Loop (actual rows=1000 loops=1)
+ -> Seq Scan on tenk1 t1 (actual rows=1000 loops=1)
+ Filter: (unique1 < 1000)
+ Rows Removed by Filter: 9000
+ -> Result Cache (actual rows=1 loops=1000)
+ Cache Key: t1.twenty
+ Hits: 980 Misses: 20 Evictions: Zero Overflows: 0 Memory Usage: NkB
+ -> Index Only Scan using tenk1_unique1 on tenk1 t2 (actual rows=1 loops=20)
+ Index Cond: (unique1 = t1.twenty)
+ Heap Fetches: N
+(11 rows)
+
+-- And check we get the expected results.
+SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
+LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2
+WHERE t1.unique1 < 1000;
+ count | avg
+-------+--------------------
+ 1000 | 9.5000000000000000
+(1 row)
+
+-- Reduce work_mem so that we see some cache evictions
+SET work_mem TO '64kB';
+SET enable_mergejoin TO off;
+-- Ensure we get some evictions. We're unable to validate the hits and misses
+-- here as the number of entries that fit in the cache at once will vary
+-- between different machines.
+SELECT explain_resultcache('
+SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
+INNER JOIN tenk1 t2 ON t1.unique1 = t2.thousand
+WHERE t2.unique1 < 1200;', true);
+ explain_resultcache
+----------------------------------------------------------------------------------------------
+ Aggregate (actual rows=1 loops=1)
+ -> Nested Loop (actual rows=1200 loops=1)
+ -> Seq Scan on tenk1 t2 (actual rows=1200 loops=1)
+ Filter: (unique1 < 1200)
+ Rows Removed by Filter: 8800
+ -> Result Cache (actual rows=1 loops=1200)
+ Cache Key: t2.thousand
+ Hits: N Misses: N Evictions: N Overflows: 0 Memory Usage: NkB
+ -> Index Only Scan using tenk1_unique1 on tenk1 t1 (actual rows=1 loops=1028)
+ Index Cond: (unique1 = t2.thousand)
+ Heap Fetches: N
+(11 rows)
+
+RESET enable_mergejoin;
+RESET work_mem;
+RESET enable_bitmapscan;
+RESET enable_hashjoin;
+-- Test parallel plans with Result Cache.
+SET min_parallel_table_scan_size TO 0;
+SET parallel_setup_cost TO 0;
+SET parallel_tuple_cost TO 0;
+SET max_parallel_workers_per_gather TO 2;
+-- Ensure we get a parallel plan.
+EXPLAIN (COSTS OFF)
+SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
+LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2
+WHERE t1.unique1 < 1000;
+ QUERY PLAN
+-------------------------------------------------------------------------------
+ Finalize Aggregate
+ -> Gather
+ Workers Planned: 2
+ -> Partial Aggregate
+ -> Nested Loop
+ -> Parallel Bitmap Heap Scan on tenk1 t1
+ Recheck Cond: (unique1 < 1000)
+ -> Bitmap Index Scan on tenk1_unique1
+ Index Cond: (unique1 < 1000)
+ -> Result Cache
+ Cache Key: t1.twenty
+ -> Index Only Scan using tenk1_unique1 on tenk1 t2
+ Index Cond: (unique1 = t1.twenty)
+(13 rows)
+
+-- And ensure the parallel plan gives us the correct results.
+SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
+LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2
+WHERE t1.unique1 < 1000;
+ count | avg
+-------+--------------------
+ 1000 | 9.5000000000000000
+(1 row)
+
+RESET max_parallel_workers_per_gather;
+RESET parallel_tuple_cost;
+RESET parallel_setup_cost;
+RESET min_parallel_table_scan_size;
diff --git a/src/test/regress/expected/subselect.out b/src/test/regress/expected/subselect.out
index d5532d0ccc0..c7986fb7fcc 100644
--- a/src/test/regress/expected/subselect.out
+++ b/src/test/regress/expected/subselect.out
@@ -1091,19 +1091,21 @@ select sum(o.four), sum(ss.a) from
select * from x
) ss
where o.ten = 1;
- QUERY PLAN
----------------------------------------------------
+ QUERY PLAN
+---------------------------------------------------------
Aggregate
-> Nested Loop
-> Seq Scan on onek o
Filter: (ten = 1)
- -> CTE Scan on x
- CTE x
- -> Recursive Union
- -> Result
- -> WorkTable Scan on x x_1
- Filter: (a < 10)
-(10 rows)
+ -> Result Cache
+ Cache Key: o.four
+ -> CTE Scan on x
+ CTE x
+ -> Recursive Union
+ -> Result
+ -> WorkTable Scan on x x_1
+ Filter: (a < 10)
+(12 rows)
select sum(o.four), sum(ss.a) from
onek o cross join lateral (
diff --git a/src/test/regress/expected/sysviews.out b/src/test/regress/expected/sysviews.out
index 98dde452e62..0bb558d93c9 100644
--- a/src/test/regress/expected/sysviews.out
+++ b/src/test/regress/expected/sysviews.out
@@ -111,10 +111,11 @@ select name, setting from pg_settings where name like 'enable%';
enable_partition_pruning | on
enable_partitionwise_aggregate | off
enable_partitionwise_join | off
+ enable_resultcache | on
enable_seqscan | on
enable_sort | on
enable_tidscan | on
-(19 rows)
+(20 rows)
-- Test that the pg_timezone_names and pg_timezone_abbrevs views are
-- more-or-less working. We can't test their contents in any great detail
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index 312c11a4bd9..2e898390892 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -119,7 +119,7 @@ test: plancache limit plpgsql copy2 temp domain rangefuncs prepare conversion tr
# ----------
# Another group of parallel tests
# ----------
-test: partition_join partition_prune reloptions hash_part indexing partition_aggregate partition_info tuplesort explain compression
+test: partition_join partition_prune reloptions hash_part indexing partition_aggregate partition_info tuplesort explain compression resultcache
# event triggers cannot run concurrently with any test that runs DDL
# oidjoins is read-only, though, and should run late for best coverage
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 5a80bfacd88..a46f3d01789 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -203,6 +203,7 @@ test: partition_info
test: tuplesort
test: explain
test: compression
+test: resultcache
test: event_trigger
test: oidjoins
test: fast_default
diff --git a/src/test/regress/sql/aggregates.sql b/src/test/regress/sql/aggregates.sql
index eb53668299c..eb80a2fe063 100644
--- a/src/test/regress/sql/aggregates.sql
+++ b/src/test/regress/sql/aggregates.sql
@@ -1098,9 +1098,11 @@ select v||'a', case when v||'a' = 'aa' then 1 else 0 end, count(*)
-- Make sure that generation of HashAggregate for uniqification purposes
-- does not lead to array overflow due to unexpected duplicate hash keys
-- see CAFeeJoKKu0u+A_A9R9316djW-YW3-+Gtgvy3ju655qRHR3jtdA@mail.gmail.com
+set enable_resultcache to off;
explain (costs off)
select 1 from tenk1
where (hundred, thousand) in (select twothousand, twothousand from onek);
+reset enable_resultcache;
--
-- Hash Aggregation Spill tests
diff --git a/src/test/regress/sql/join.sql b/src/test/regress/sql/join.sql
index 8164383fb53..7f866c603b8 100644
--- a/src/test/regress/sql/join.sql
+++ b/src/test/regress/sql/join.sql
@@ -550,6 +550,7 @@ reset enable_nestloop;
set work_mem to '64kB';
set enable_mergejoin to off;
+set enable_resultcache to off;
explain (costs off)
select count(*) from tenk1 a, tenk1 b
@@ -559,6 +560,7 @@ select count(*) from tenk1 a, tenk1 b
reset work_mem;
reset enable_mergejoin;
+reset enable_resultcache;
--
-- regression test for 8.2 bug with improper re-ordering of left joins
diff --git a/src/test/regress/sql/partition_prune.sql b/src/test/regress/sql/partition_prune.sql
index 6ccb52ad1d6..247264f93b7 100644
--- a/src/test/regress/sql/partition_prune.sql
+++ b/src/test/regress/sql/partition_prune.sql
@@ -464,6 +464,9 @@ begin
ln := regexp_replace(ln, 'Workers Launched: \d+', 'Workers Launched: N');
ln := regexp_replace(ln, 'actual rows=\d+ loops=\d+', 'actual rows=N loops=N');
ln := regexp_replace(ln, 'Rows Removed by Filter: \d+', 'Rows Removed by Filter: N');
+ ln := regexp_replace(ln, 'Hits: \d+', 'Hits: N');
+ ln := regexp_replace(ln, 'Misses: \d+', 'Misses: N');
+ ln := regexp_replace(ln, 'Memory Usage: \d+', 'Memory Usage: N');
return next ln;
end loop;
end;
@@ -515,6 +518,7 @@ create index ab_a3_b3_a_idx on ab_a3_b3 (a);
set enable_hashjoin = 0;
set enable_mergejoin = 0;
+set enable_resultcache = 0;
select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on ab.a = a.a where a.a in(0, 0, 1)');
@@ -533,6 +537,7 @@ select explain_parallel_append('select avg(ab.a) from ab inner join lprt_a a on
reset enable_hashjoin;
reset enable_mergejoin;
+reset enable_resultcache;
reset parallel_setup_cost;
reset parallel_tuple_cost;
reset min_parallel_table_scan_size;
diff --git a/src/test/regress/sql/resultcache.sql b/src/test/regress/sql/resultcache.sql
new file mode 100644
index 00000000000..2be5b8f2d88
--- /dev/null
+++ b/src/test/regress/sql/resultcache.sql
@@ -0,0 +1,91 @@
+-- Perform tests on the Result Cache node.
+
+-- The cache hits/misses/evictions from the Result Cache node can vary between
+-- machines. Let's just replace the number with an 'N'. In order to allow us
+-- to perform validation when the measure was zero, we replace a zero value
+-- with "Zero". All other numbers are replaced with 'N'.
+create function explain_resultcache(query text, hide_hitmiss bool) returns setof text
+language plpgsql as
+$$
+declare
+ ln text;
+begin
+ for ln in
+ execute format('explain (analyze, costs off, summary off, timing off) %s',
+ query)
+ loop
+ if hide_hitmiss = true then
+ ln := regexp_replace(ln, 'Hits: 0', 'Hits: Zero');
+ ln := regexp_replace(ln, 'Hits: \d+', 'Hits: N');
+ ln := regexp_replace(ln, 'Misses: 0', 'Misses: Zero');
+ ln := regexp_replace(ln, 'Misses: \d+', 'Misses: N');
+ end if;
+ ln := regexp_replace(ln, 'Evictions: 0', 'Evictions: Zero');
+ ln := regexp_replace(ln, 'Evictions: \d+', 'Evictions: N');
+ ln := regexp_replace(ln, 'Memory Usage: \d+', 'Memory Usage: N');
+ ln := regexp_replace(ln, 'Heap Fetches: \d+', 'Heap Fetches: N');
+ return next ln;
+ end loop;
+end;
+$$;
+
+-- Ensure we get a result cache on the inner side of the nested loop
+SET enable_hashjoin TO off;
+SET enable_bitmapscan TO off;
+SELECT explain_resultcache('
+SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
+INNER JOIN tenk1 t2 ON t1.unique1 = t2.twenty
+WHERE t2.unique1 < 1000;', false);
+
+-- And check we get the expected results.
+SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
+INNER JOIN tenk1 t2 ON t1.unique1 = t2.twenty
+WHERE t2.unique1 < 1000;
+
+-- Try with LATERAL joins
+SELECT explain_resultcache('
+SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
+LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2
+WHERE t1.unique1 < 1000;', false);
+
+-- And check we get the expected results.
+SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
+LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2
+WHERE t1.unique1 < 1000;
+
+-- Reduce work_mem so that we see some cache evictions
+SET work_mem TO '64kB';
+SET enable_mergejoin TO off;
+-- Ensure we get some evictions. We're unable to validate the hits and misses
+-- here as the number of entries that fit in the cache at once will vary
+-- between different machines.
+SELECT explain_resultcache('
+SELECT COUNT(*),AVG(t1.unique1) FROM tenk1 t1
+INNER JOIN tenk1 t2 ON t1.unique1 = t2.thousand
+WHERE t2.unique1 < 1200;', true);
+RESET enable_mergejoin;
+RESET work_mem;
+RESET enable_bitmapscan;
+RESET enable_hashjoin;
+
+-- Test parallel plans with Result Cache.
+SET min_parallel_table_scan_size TO 0;
+SET parallel_setup_cost TO 0;
+SET parallel_tuple_cost TO 0;
+SET max_parallel_workers_per_gather TO 2;
+
+-- Ensure we get a parallel plan.
+EXPLAIN (COSTS OFF)
+SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
+LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2
+WHERE t1.unique1 < 1000;
+
+-- And ensure the parallel plan gives us the correct results.
+SELECT COUNT(*),AVG(t2.unique1) FROM tenk1 t1,
+LATERAL (SELECT t2.unique1 FROM tenk1 t2 WHERE t1.twenty = t2.unique1) t2
+WHERE t1.unique1 < 1000;
+
+RESET max_parallel_workers_per_gather;
+RESET parallel_tuple_cost;
+RESET parallel_setup_cost;
+RESET min_parallel_table_scan_size;