@@ -112,7 +112,10 @@ EXPLAIN (COSTS OFF) SELECT * FROM test.range_rel_1 UNION ALL SELECT * FROM test.
112
112
* Join
113
113
*/
114
114
SET enable_hashjoin= OFF;
115
+ set enable_nestloop= OFF;
115
116
SET enable_mergejoin= ON ;
117
+ SET pg_pathman .enable_runtimeappend = OFF;
118
+ SET pg_pathman .enable_runtimemergeappend = OFF;
116
119
EXPLAIN (COSTS OFF)
117
120
SELECT * FROM test .range_rel j1
118
121
JOIN test .range_rel j2on j2 .id = j1 .id
@@ -137,6 +140,149 @@ EXPLAIN (COSTS OFF)
137
140
WITH tttAS (SELECT * FROM test .hash_rel WHERE value= 2 )
138
141
SELECT * FROM ttt;
139
142
143
+
144
+ /*
145
+ * Test RuntimeAppend
146
+ */
147
+
148
+ create or replace function test .pathman_assert(smt bool, error_msgtext ) returnstext as $$
149
+ begin
150
+ if not smt then
151
+ raise exception' %' , error_msg;
152
+ end if;
153
+
154
+ return' ok' ;
155
+ end;
156
+ $$ language plpgsql;
157
+
158
+ create or replace function test .pathman_equal(atext , btext , error_msgtext ) returnstext as $$
159
+ begin
160
+ if a!= b then
161
+ raise exception' ' ' %' ' is not equal to' ' %' ' , %' , a, b, error_msg;
162
+ end if;
163
+
164
+ return' equal' ;
165
+ end;
166
+ $$ language plpgsql;
167
+
168
+ create or replace function test .pathman_test(querytext ) returns jsonbas $$
169
+ declare
170
+ plan jsonb;
171
+ begin
172
+ execute' explain (analyze, format json)' || query into plan;
173
+
174
+ return plan;
175
+ end;
176
+ $$ language plpgsql;
177
+
178
+ create or replace function test .pathman_test_1() returnstext as $$
179
+ declare
180
+ plan jsonb;
181
+ numint ;
182
+ begin
183
+ plan= test .pathman_test (' select * from test.runtime_test_1 where id = (select * from test.run_values limit 1)' );
184
+
185
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Node Type' )::text ,
186
+ ' "Custom Scan"' ,
187
+ ' wrong plan type' );
188
+
189
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Custom Plan Provider' )::text ,
190
+ ' "RuntimeAppend"' ,
191
+ ' wrong plan provider' );
192
+
193
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Relation Name' )::text ,
194
+ ' "runtime_test_1_1"' ,
195
+ ' wrong partition' );
196
+ return' ok' ;
197
+ end;
198
+ $$ language plpgsql;
199
+
200
+ create or replace function test .pathman_test_2() returnstext as $$
201
+ declare
202
+ plan jsonb;
203
+ numint ;
204
+ begin
205
+ plan= test .pathman_test (' select * from test.runtime_test_1 where id = any (select * from test.run_values limit 6)' );
206
+
207
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Node Type' )::text ,
208
+ ' "Nested Loop"' ,
209
+ ' wrong plan type' );
210
+
211
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Node Type' )::text ,
212
+ ' "Custom Scan"' ,
213
+ ' wrong plan type' );
214
+
215
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Custom Plan Provider' )::text ,
216
+ ' "RuntimeAppend"' ,
217
+ ' wrong plan provider' );
218
+
219
+ select count (* )from jsonb_array_elements_text(plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Plans' ) into num;
220
+ performtest .pathman_equal (num::text ,' 6' ,' expected 6 child plans for custom scan' );
221
+
222
+ for iin 0 ..5 loop
223
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Plans' - > i- > ' Relation Name' )::text ,
224
+ format(' "runtime_test_1_%s"' , i+ 1 ),
225
+ ' wrong partition' );
226
+
227
+ num= plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Plans' - > i- > ' Actual Loops' ;
228
+ performtest .pathman_equal (num::text ,' 1' ,' expected 1 loop' );
229
+ end loop;
230
+
231
+ return' ok' ;
232
+ end;
233
+ $$ language plpgsql;
234
+
235
+ create or replace function test .pathman_test_3() returnstext as $$
236
+ declare
237
+ plan jsonb;
238
+ numint ;
239
+ begin
240
+ plan= test .pathman_test (' select * from test.runtime_test_1 a join test.run_values b on a.id = b.val' );
241
+
242
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Node Type' )::text ,
243
+ ' "Nested Loop"' ,
244
+ ' wrong plan type' );
245
+
246
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Node Type' )::text ,
247
+ ' "Custom Scan"' ,
248
+ ' wrong plan type' );
249
+
250
+ performtest .pathman_equal ((plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Custom Plan Provider' )::text ,
251
+ ' "RuntimeAppend"' ,
252
+ ' wrong plan provider' );
253
+
254
+ select count (* )from jsonb_array_elements_text(plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Plans' ) into num;
255
+ performtest .pathman_equal (num::text ,' 128' ,' expected 128 child plans for custom scan' );
256
+
257
+ for iin 0 ..127 loop
258
+ num= plan- > 0 - > ' Plan' - > ' Plans' - > 1 - > ' Plans' - > i- > ' Actual Loops' ;
259
+ performtest .pathman_assert (num<= 79 ,' expected no more than 79 loops' );
260
+ end loop;
261
+
262
+ return' ok' ;
263
+ end;
264
+ $$ language plpgsql;
265
+
266
+
267
+ create table test .run_valuesas select generate_series(1 ,10000 ) val;
268
+ create table test .runtime_test_1(idserial primary key , valreal );
269
+ insert into test .runtime_test_1 select generate_series(1 ,10000 ), random();
270
+ select pathman .create_hash_partitions (' test.runtime_test_1' ,' id' ,128 );
271
+
272
+ analyzetest .run_values ;
273
+ analyzetest .runtime_test_1 ;
274
+
275
+ set enable_mergejoin= off;
276
+ set enable_hashjoin= off;
277
+ set pg_pathman .enable_runtimeappend = on ;
278
+ select test .pathman_test_1 ();/* RuntimeAppend (select ... where id = (subquery))*/
279
+ select test .pathman_test_2 ();/* RuntimeAppend (select ... where id = any(subquery))*/
280
+ select test .pathman_test_3 ();/* RuntimeAppend (a join b on a.id = b.val)*/
281
+ set enable_mergejoin= on ;
282
+ set enable_hashjoin= on ;
283
+
284
+ drop table test .run_values ,test .runtime_test_1 cascade;
285
+
140
286
/*
141
287
* Test split and merge
142
288
*/