1--
2-- PARALLEL
3--
4
5create or replace function parallel_restricted(int) returns int as
6  $$begin return $1; end$$ language plpgsql parallel restricted;
7
8-- Serializable isolation would disable parallel query, so explicitly use an
9-- arbitrary other level.
10begin isolation level repeatable read;
11
12-- encourage use of parallel plans
13set parallel_setup_cost=0;
14set parallel_tuple_cost=0;
15set min_parallel_relation_size=0;
16set max_parallel_workers_per_gather=4;
17
18explain (costs off)
19  select count(*) from a_star;
20select count(*) from a_star;
21
22-- test that parallel_restricted function doesn't run in worker
23alter table tenk1 set (parallel_workers = 4);
24explain (verbose, costs off)
25select parallel_restricted(unique1) from tenk1
26  where stringu1 = 'GRAAAA' order by 1;
27
28-- test parallel plan when group by expression is in target list.
29explain (costs off)
30	select length(stringu1) from tenk1 group by length(stringu1);
31select length(stringu1) from tenk1 group by length(stringu1);
32
33explain (costs off)
34	select stringu1, count(*) from tenk1 group by stringu1 order by stringu1;
35
36-- test that parallel plan for aggregates is not selected when
37-- target list contains parallel restricted clause.
38explain (costs off)
39	select  sum(parallel_restricted(unique1)) from tenk1
40	group by(parallel_restricted(unique1));
41
42-- check parallelized int8 aggregate (bug #14897)
43explain (costs off)
44select avg(aa::int8) from a_star;
45
46select avg(aa::int8) from a_star;
47
48-- test accumulation of stats for parallel nodes
49set enable_indexscan to off;
50set enable_bitmapscan to off;
51set enable_material to off;
52alter table tenk2 set (parallel_workers = 0);
53create function explain_parallel_stats() returns setof text
54language plpgsql as
55$$
56declare ln text;
57begin
58    for ln in
59        explain (analyze, timing off, costs off)
60          select count(*) from tenk1, tenk2 where
61            tenk1.hundred > 1 and tenk2.thousand=0
62    loop
63        ln := regexp_replace(ln, 'Planning time: \S*',  'Planning time: xxx');
64        ln := regexp_replace(ln, 'Execution time: \S*', 'Execution time: xxx');
65        return next ln;
66    end loop;
67end;
68$$;
69select * from explain_parallel_stats();
70reset enable_indexscan;
71reset enable_bitmapscan;
72reset enable_material;
73alter table tenk2 reset (parallel_workers);
74drop function explain_parallel_stats();
75
76-- test the sanity of parallel query after the active role is dropped.
77set force_parallel_mode=1;
78drop role if exists regress_parallel_worker;
79create role regress_parallel_worker;
80set role regress_parallel_worker;
81reset session authorization;
82drop role regress_parallel_worker;
83select count(*) from tenk1;
84reset role;
85
86-- Window function calculation can't be pushed to workers.
87explain (costs off, verbose)
88  select count(*) from tenk1 a where (unique1, two) in
89    (select unique1, row_number() over() from tenk1 b);
90
91-- LIMIT/OFFSET within sub-selects can't be pushed to workers.
92explain (costs off)
93  select * from tenk1 a where two in
94    (select two from tenk1 b where stringu1 like '%AAAA' limit 3);
95
96explain (costs off)
97  select stringu1::int2 from tenk1 where unique1 = 1;
98
99-- test passing expanded-value representations to workers
100CREATE FUNCTION make_some_array(int,int) returns int[] as
101$$declare x int[];
102  begin
103    x[1] := $1;
104    x[2] := $2;
105    return x;
106  end$$ language plpgsql parallel safe;
107CREATE TABLE fooarr(f1 text, f2 int[], f3 text);
108INSERT INTO fooarr VALUES('1', ARRAY[1,2], 'one');
109
110PREPARE pstmt(text, int[]) AS SELECT * FROM fooarr WHERE f1 = $1 AND f2 = $2;
111EXPLAIN (COSTS OFF) EXECUTE pstmt('1', make_some_array(1,2));
112EXECUTE pstmt('1', make_some_array(1,2));
113DEALLOCATE pstmt;
114
115do $$begin
116  -- Provoke error, possibly in worker.  If this error happens to occur in
117  -- the worker, there will be a CONTEXT line which must be hidden.
118  -- (make the error message long enough to require multiple bufferloads)
119  perform (stringu1 || repeat('abcd', 5000))::int2 from tenk1 where unique1 = 1;
120  exception
121	when others then
122		raise 'SQLERRM: %', sqlerrm;
123end$$;
124
125rollback;
126