1load 'plpgsql';
2create extension if not exists plpgsql_check;
3set client_min_messages to notice;
4set plpgsql_check.regress_test_mode = true;
5--
6-- check function statement tests
7--
8--should fail - is not plpgsql
9select * from plpgsql_check_function_tb('session_user()');
10ERROR:  "session_user"() is not a plpgsql function
11create table t1(a int, b int);
12create table pa (id int, pa_id character varying(32), status character varying(60));
13create table  ml(ml_id character varying(32), status_from character varying(60), pa_id character varying(32), xyz int);
14create function f1()
15returns void as $$
16begin
17  if false then
18    update t1 set c = 30;
19  end if;
20  if false then
21     raise notice '%', r.c;
22  end if;
23end;
24$$ language plpgsql;
25select f1();
26 f1
27----
28
29(1 row)
30
31select * from plpgsql_check_function_tb('f1()', fatal_errors := true);
32 functionid | lineno |   statement   | sqlstate |                  message                   | detail | hint | level | position |        query         | context
33------------+--------+---------------+----------+--------------------------------------------+--------+------+-------+----------+----------------------+---------
34 f1         |      4 | SQL statement | 42703    | column "c" of relation "t1" does not exist |        |      | error |       15 | update t1 set c = 30 |
35(1 row)
36
37select * from plpgsql_check_function_tb('f1()', fatal_errors := false);
38 functionid | lineno |   statement   | sqlstate |                  message                   | detail | hint | level | position |        query         | context
39------------+--------+---------------+----------+--------------------------------------------+--------+------+-------+----------+----------------------+---------
40 f1         |      4 | SQL statement | 42703    | column "c" of relation "t1" does not exist |        |      | error |       15 | update t1 set c = 30 |
41 f1         |      7 | RAISE         | 42P01    | missing FROM-clause entry for table "r"    |        |      | error |        8 | SELECT r.c           |
42(2 rows)
43
44select * from plpgsql_check_function_tb('f1()');
45 functionid | lineno |   statement   | sqlstate |                  message                   | detail | hint | level | position |        query         | context
46------------+--------+---------------+----------+--------------------------------------------+--------+------+-------+----------+----------------------+---------
47 f1         |      4 | SQL statement | 42703    | column "c" of relation "t1" does not exist |        |      | error |       15 | update t1 set c = 30 |
48(1 row)
49
50drop function f1();
51create function f1()
52returns void as $$
53begin
54  if false then
55    insert into t1 values(10,20);
56    update t1 set a = 10;
57    delete from t1;
58  end if;
59end;
60$$ language plpgsql stable;
61select f1();
62 f1
63----
64
65(1 row)
66
67select * from plpgsql_check_function_tb('f1()', fatal_errors := false);
68 functionid | lineno |   statement   | sqlstate |                     message                      | detail | hint | level | position |            query             | context
69------------+--------+---------------+----------+--------------------------------------------------+--------+------+-------+----------+------------------------------+---------
70 f1         |      4 | SQL statement | 0A000    | INSERT is not allowed in a non volatile function |        |      | error |        1 | insert into t1 values(10,20) |
71 f1         |      5 | SQL statement | 0A000    | UPDATE is not allowed in a non volatile function |        |      | error |        1 | update t1 set a = 10         |
72 f1         |      6 | SQL statement | 0A000    | DELETE is not allowed in a non volatile function |        |      | error |        1 | delete from t1               |
73(3 rows)
74
75drop function f1();
76-- profiler check
77set plpgsql_check.profiler to on;
78create function f1()
79returns void as $$
80begin
81  if false then
82    insert into t1 values(10,20);
83    update t1 set a = 10;
84    delete from t1;
85  end if;
86end;
87$$ language plpgsql;
88select lineno, stmt_lineno, exec_stmts, source from plpgsql_profiler_function_tb('f1()');
89 lineno | stmt_lineno | exec_stmts |              source
90--------+-------------+------------+-----------------------------------
91      1 |             |            |
92      2 |             |            | begin
93      3 |             |            |   if false then
94      4 |             |            |     insert into t1 values(10,20);
95      5 |             |            |     update t1 set a = 10;
96      6 |             |            |     delete from t1;
97      7 |             |            |   end if;
98      8 |             |            | end;
99(8 rows)
100
101select f1();
102 f1
103----
104
105(1 row)
106
107select lineno, stmt_lineno, exec_stmts, source from plpgsql_profiler_function_tb('f1()');
108 lineno | stmt_lineno | exec_stmts |              source
109--------+-------------+------------+-----------------------------------
110      1 |             |            |
111      2 |           2 |          1 | begin
112      3 |           3 |          1 |   if false then
113      4 |           4 |          0 |     insert into t1 values(10,20);
114      5 |           5 |          0 |     update t1 set a = 10;
115      6 |           6 |          0 |     delete from t1;
116      7 |             |            |   end if;
117      8 |             |            | end;
118(8 rows)
119
120select plpgsql_profiler_reset('f1()');
121 plpgsql_profiler_reset
122------------------------
123
124(1 row)
125
126select lineno, stmt_lineno, exec_stmts, source from plpgsql_profiler_function_tb('f1()');
127 lineno | stmt_lineno | exec_stmts |              source
128--------+-------------+------------+-----------------------------------
129      1 |             |            |
130      2 |             |            | begin
131      3 |             |            |   if false then
132      4 |             |            |     insert into t1 values(10,20);
133      5 |             |            |     update t1 set a = 10;
134      6 |             |            |     delete from t1;
135      7 |             |            |   end if;
136      8 |             |            | end;
137(8 rows)
138
139select f1();
140 f1
141----
142
143(1 row)
144
145select lineno, stmt_lineno, exec_stmts, source from plpgsql_profiler_function_tb('f1()');
146 lineno | stmt_lineno | exec_stmts |              source
147--------+-------------+------------+-----------------------------------
148      1 |             |            |
149      2 |           2 |          1 | begin
150      3 |           3 |          1 |   if false then
151      4 |           4 |          0 |     insert into t1 values(10,20);
152      5 |           5 |          0 |     update t1 set a = 10;
153      6 |           6 |          0 |     delete from t1;
154      7 |             |            |   end if;
155      8 |             |            | end;
156(8 rows)
157
158select plpgsql_profiler_reset_all();
159 plpgsql_profiler_reset_all
160----------------------------
161
162(1 row)
163
164select lineno, stmt_lineno, exec_stmts, source from plpgsql_profiler_function_tb('f1()');
165 lineno | stmt_lineno | exec_stmts |              source
166--------+-------------+------------+-----------------------------------
167      1 |             |            |
168      2 |             |            | begin
169      3 |             |            |   if false then
170      4 |             |            |     insert into t1 values(10,20);
171      5 |             |            |     update t1 set a = 10;
172      6 |             |            |     delete from t1;
173      7 |             |            |   end if;
174      8 |             |            | end;
175(8 rows)
176
177drop function f1();
178-- test queryid retrieval
179create function f1()
180returns void as $$
181declare
182  t1 text = 't1';
183begin
184  insert into t1 values(10,20);
185  EXECUTE 'update ' ||  't1' || ' set a = 10';
186  EXECUTE 'delete from ' || t1;
187end;
188$$ language plpgsql;
189select plpgsql_profiler_reset_all();
190 plpgsql_profiler_reset_all
191----------------------------
192
193(1 row)
194
195select plpgsql_profiler_install_fake_queryid_hook();
196 plpgsql_profiler_install_fake_queryid_hook
197--------------------------------------------
198
199(1 row)
200
201select f1();
202 f1
203----
204
205(1 row)
206
207select queryids, lineno, stmt_lineno, exec_stmts, source from plpgsql_profiler_function_tb('f1()');
208 queryids | lineno | stmt_lineno | exec_stmts |                     source
209----------+--------+-------------+------------+------------------------------------------------
210          |      1 |             |            |
211          |      2 |             |            | declare
212          |      3 |             |            |   t1 text = 't1';
213          |      4 |           4 |          1 | begin
214 {3}      |      5 |           5 |          1 |   insert into t1 values(10,20);
215 {2}      |      6 |           6 |          1 |   EXECUTE 'update ' ||  't1' || ' set a = 10';
216 {4}      |      7 |           7 |          1 |   EXECUTE 'delete from ' || t1;
217          |      8 |             |            | end;
218(8 rows)
219
220select plpgsql_profiler_remove_fake_queryid_hook();
221 plpgsql_profiler_remove_fake_queryid_hook
222-------------------------------------------
223
224(1 row)
225
226drop function f1();
227set plpgsql_check.profiler to off;
228create function f1()
229returns void as $$
230declare r record;
231begin
232  if false then
233    for r in update t1 set a = a + 1 returning *
234    loop
235      raise notice '%', r.a;
236    end loop;
237  end if;
238end;
239$$ language plpgsql;
240select f1();
241 f1
242----
243
244(1 row)
245
246select * from plpgsql_check_function_tb('f1()', fatal_errors := false);
247 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
248------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
249(0 rows)
250
251drop function f1();
252create function f1()
253returns void as $$
254declare r record;
255begin
256  if false then
257    for r in update t1 set a = a + 1 returning *
258    loop
259      raise notice '%', r.a;
260    end loop;
261  end if;
262end;
263$$ language plpgsql stable;
264select f1();
265 f1
266----
267
268(1 row)
269
270select * from plpgsql_check_function_tb('f1()', fatal_errors := false);
271 functionid | lineno |      statement       | sqlstate |                     message                      | detail | hint | level | position |                query                | context
272------------+--------+----------------------+----------+--------------------------------------------------+--------+------+-------+----------+-------------------------------------+---------
273 f1         |      5 | FOR over SELECT rows | 0A000    | UPDATE is not allowed in a non volatile function |        |      | error |        1 | update t1 set a = a + 1 returning * |
274(1 row)
275
276drop function f1();
277create function g1(out a int, out b int)
278as $$
279  select 10,20;
280$$ language sql;
281create function f1()
282returns void as $$
283declare r record;
284begin
285  r := g1();
286  if false then
287    raise notice '%', r.c;
288  end if;
289end;
290$$ language plpgsql;
291select f1();
292 f1
293----
294
295(1 row)
296
297select * from plpgsql_check_function_tb('f1()');
298 functionid | lineno | statement | sqlstate |           message           | detail | hint | level | position | query |          context
299------------+--------+-----------+----------+-----------------------------+--------+------+-------+----------+-------+----------------------------
300 f1         |      6 | RAISE     | 42703    | record "r" has no field "c" |        |      | error |          |       | SQL statement "SELECT r.c"
301(1 row)
302
303select f1();
304 f1
305----
306
307(1 row)
308
309drop function f1();
310drop function g1();
311create function g1(out a int, out b int)
312returns setof record as $$
313select * from t1;
314$$ language sql;
315create function f1()
316returns void as $$
317declare r record;
318begin
319  for r in select * from g1()
320  loop
321    raise notice '%', r.c;
322  end loop;
323end;
324$$ language plpgsql;
325select f1();
326 f1
327----
328
329(1 row)
330
331select * from plpgsql_check_function_tb('f1()');
332 functionid | lineno | statement | sqlstate |           message           | detail | hint | level | position | query |          context
333------------+--------+-----------+----------+-----------------------------+--------+------+-------+----------+-------+----------------------------
334 f1         |      6 | RAISE     | 42703    | record "r" has no field "c" |        |      | error |          |       | SQL statement "SELECT r.c"
335(1 row)
336
337select f1();
338 f1
339----
340
341(1 row)
342
343create or replace function f1()
344returns void as $$
345declare r record;
346begin
347  for r in select * from g1()
348  loop
349    r.c := 20;
350  end loop;
351end;
352$$ language plpgsql;
353select f1();
354 f1
355----
356
357(1 row)
358
359select * from plpgsql_check_function_tb('f1()');
360 functionid | lineno | statement  | sqlstate |           message           | detail | hint | level | position | query |                            context
361------------+--------+------------+----------+-----------------------------+--------+------+-------+----------+-------+---------------------------------------------------------------
362 f1         |      6 | assignment | 42703    | record "r" has no field "c" |        |      | error |          |       | at assignment to field "c" of variable "r" declared on line 2
363(1 row)
364
365select f1();
366 f1
367----
368
369(1 row)
370
371drop function f1();
372drop function g1();
373create function f1()
374returns int as $$
375declare r int;
376begin
377  if false then
378    r := a + b;
379  end if;
380  return r;
381end;
382$$ language plpgsql;
383select f1();
384 f1
385----
386
387(1 row)
388
389select * from plpgsql_check_function_tb('f1()');
390 functionid | lineno | statement  | sqlstate |          message          | detail | hint | level | position |    query     |                     context
391------------+--------+------------+----------+---------------------------+--------+------+-------+----------+--------------+--------------------------------------------------
392 f1         |      5 | assignment | 42703    | column "a" does not exist |        |      | error |        8 | SELECT a + b | at assignment to variable "r" declared on line 2
393(1 row)
394
395select f1();
396 f1
397----
398
399(1 row)
400
401drop function f1();
402create or replace function f1()
403returns void as $$
404declare r int[];
405begin
406  if false then
407    r[c+10] := 20;
408  end if;
409end;
410$$ language plpgsql;
411select f1();
412 f1
413----
414
415(1 row)
416
417select * from plpgsql_check_function_tb('f1()');
418 functionid | lineno | statement  | sqlstate |          message          | detail | hint | level | position |    query    |                           context
419------------+--------+------------+----------+---------------------------+--------+------+-------+----------+-------------+-------------------------------------------------------------
420 f1         |      5 | assignment | 42703    | column "c" does not exist |        |      | error |        8 | SELECT c+10 | at assignment to element of variable "r" declared on line 2
421(1 row)
422
423select f1();
424 f1
425----
426
427(1 row)
428
429drop function f1();
430create or replace function f1()
431returns void as $$
432declare r int;
433begin
434  if false then
435    r[10] := 20;
436  end if;
437end;
438$$ language plpgsql set search_path = public;
439select f1();
440 f1
441----
442
443(1 row)
444
445select * from plpgsql_check_function_tb('f1()');
446 functionid | lineno | statement  | sqlstate |              message               | detail | hint | level | position | query |                           context
447------------+--------+------------+----------+------------------------------------+--------+------+-------+----------+-------+-------------------------------------------------------------
448 f1         |      5 | assignment | 42804    | subscripted object is not an array |        |      | error |          |       | at assignment to element of variable "r" declared on line 2
449(1 row)
450
451select f1();
452 f1
453----
454
455(1 row)
456
457drop function f1();
458create or replace function f1_trg()
459returns trigger as $$
460begin
461  if new.a > 10 then
462    raise notice '%', new.b;
463    raise notice '%', new.c;
464  end if;
465  return new;
466end;
467$$ language plpgsql;
468create trigger t1_f1 before insert on t1
469  for each row
470  execute procedure f1_trg();
471insert into t1 values(6,30);
472select * from plpgsql_check_function_tb('f1_trg()','t1');
473 functionid | lineno | statement | sqlstate |            message            | detail | hint | level | position | query |           context
474------------+--------+-----------+----------+-------------------------------+--------+------+-------+----------+-------+------------------------------
475 f1_trg     |      5 | RAISE     | 42703    | record "new" has no field "c" |        |      | error |          |       | SQL statement "SELECT new.c"
476(1 row)
477
478insert into t1 values(6,30);
479create or replace function f1_trg()
480returns trigger as $$
481begin
482  new.a := new.a + 10;
483  new.b := new.b + 10;
484  new.c := 30;
485  return new;
486end;
487$$ language plpgsql;
488-- should to fail
489select * from plpgsql_check_function_tb('f1_trg()','t1');
490 functionid | lineno | statement  | sqlstate |            message            | detail | hint | level | position | query |                             context
491------------+--------+------------+----------+-------------------------------+--------+------+-------+----------+-------+-----------------------------------------------------------------
492 f1_trg     |      5 | assignment | 42703    | record "new" has no field "c" |        |      | error |          |       | at assignment to field "c" of variable "new" declared on line 0
493(1 row)
494
495-- should to fail but not crash
496insert into t1 values(6,30);
497ERROR:  record "new" has no field "c"
498CONTEXT:  PL/pgSQL function f1_trg() line 5 at assignment
499create or replace function f1_trg()
500returns trigger as $$
501begin
502  new.a := new.a + 10;
503  new.b := new.b + 10;
504  return new;
505end;
506$$ language plpgsql;
507-- ok
508select * from plpgsql_check_function_tb('f1_trg()', 't1');
509 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
510------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
511(0 rows)
512
513-- ok
514insert into t1 values(6,30);
515create or replace function f1_trg()
516returns trigger as $$
517begin
518  new.a := new.a + 10;
519  new.b := new.b + 10;
520  return null;
521end;
522$$ language plpgsql;
523-- ok
524select * from plpgsql_check_function_tb('f1_trg()', 't1');
525 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
526------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
527(0 rows)
528
529insert into t1 values(60,300);
530select * from t1;
531 a  | b
532----+----
533  6 | 30
534  6 | 30
535 16 | 40
536(3 rows)
537
538insert into t1 values(600,30);
539select * from t1;
540 a  | b
541----+----
542  6 | 30
543  6 | 30
544 16 | 40
545(3 rows)
546
547drop trigger t1_f1 on t1;
548drop function f1_trg();
549-- test of showing caret on correct place for multiline queries
550create or replace function f1()
551returns void as $$
552begin
553  select
554  var
555  from
556  foo;
557end;
558$$ language plpgsql;
559select * from plpgsql_check_function_tb('f1()');
560 functionid | lineno |   statement   | sqlstate |            message            | detail | hint | level | position | query  | context
561------------+--------+---------------+----------+-------------------------------+--------+------+-------+----------+--------+---------
562 f1         |      3 | SQL statement | 42P01    | relation "foo" does not exist |        |      | error |       23 | select+|
563            |        |               |          |                               |        |      |       |          |   var +|
564            |        |               |          |                               |        |      |       |          |   from+|
565            |        |               |          |                               |        |      |       |          |   foo  |
566(1 row)
567
568drop function f1();
569create or replace function f1()
570returns int as $$
571begin
572  return (select a
573             from t1
574            where hh = 20);
575end;
576$$ language plpgsql;
577select * from plpgsql_check_function_tb('f1()');
578 functionid | lineno | statement | sqlstate |          message           | detail | hint | level | position |           query            | context
579------------+--------+-----------+----------+----------------------------+--------+------+-------+----------+----------------------------+---------
580 f1         |      3 | RETURN    | 42703    | column "hh" does not exist |        |      | error |       57 | SELECT (select a          +|
581            |        |           |          |                            |        |      |       |          |              from t1      +|
582            |        |           |          |                            |        |      |       |          |             where hh = 20) |
583(1 row)
584
585create or replace function f1()
586returns int as $$
587begin
588  return (select a
589             from txxxxxxx
590            where hh = 20);
591end;
592$$ language plpgsql;
593select * from plpgsql_check_function_tb('f1()');
594 functionid | lineno | statement | sqlstate |              message               | detail | hint | level | position |           query            | context
595------------+--------+-----------+----------+------------------------------------+--------+------+-------+----------+----------------------------+---------
596 f1         |      3 | RETURN    | 42P01    | relation "txxxxxxx" does not exist |        |      | error |       36 | SELECT (select a          +|
597            |        |           |          |                                    |        |      |       |          |              from txxxxxxx+|
598            |        |           |          |                                    |        |      |       |          |             where hh = 20) |
599(1 row)
600
601drop function f1();
602drop table t1;
603-- raise warnings when target row has different number of attributies in
604-- SELECT INTO statement
605create or replace function f1()
606returns void as $$
607declare a1 int; a2 int;
608begin
609  select 10,20 into a1,a2;
610end;
611$$ language plpgsql;
612-- should be ok
613select * from plpgsql_check_function_tb('f1()');
614 functionid | lineno | statement | sqlstate |         message          | detail | hint |     level     | position | query | context
615------------+--------+-----------+----------+--------------------------+--------+------+---------------+----------+-------+---------
616 f1         |      2 | DECLARE   | 00000    | never read variable "a1" |        |      | warning extra |          |       |
617 f1         |      2 | DECLARE   | 00000    | never read variable "a2" |        |      | warning extra |          |       |
618(2 rows)
619
620create or replace function f1()
621returns void as $$
622declare a1 int;
623begin
624  select 10,20 into a1;
625end;
626$$ language plpgsql;
627-- raise warning
628select * from plpgsql_check_function_tb('f1()');
629 functionid | lineno |   statement   | sqlstate |                 message                  |                            detail                             |                      hint                       |     level     | position | query | context
630------------+--------+---------------+----------+------------------------------------------+---------------------------------------------------------------+-------------------------------------------------+---------------+----------+-------+---------
631 f1         |      4 | SQL statement | 00000    | too many attributes for target variables | There are less target variables than output columns in query. | Check target variables in SELECT INTO statement | warning       |          |       |
632 f1         |      2 | DECLARE       | 00000    | never read variable "a1"                 |                                                               |                                                 | warning extra |          |       |
633(2 rows)
634
635create or replace function f1()
636returns void as $$
637declare a1 int; a2 int;
638begin
639  select 10 into a1,a2;
640end;
641$$ language plpgsql;
642-- raise warning
643select * from plpgsql_check_function_tb('f1()');
644 functionid | lineno |   statement   | sqlstate |                 message                 |                            detail                             |                       hint                       |     level     | position | query | context
645------------+--------+---------------+----------+-----------------------------------------+---------------------------------------------------------------+--------------------------------------------------+---------------+----------+-------+---------
646 f1         |      4 | SQL statement | 00000    | too few attributes for target variables | There are more target variables than output columns in query. | Check target variables in SELECT INTO statement. | warning       |          |       |
647 f1         |      2 | DECLARE       | 00000    | never read variable "a1"                |                                                               |                                                  | warning extra |          |       |
648 f1         |      2 | DECLARE       | 00000    | never read variable "a2"                |                                                               |                                                  | warning extra |          |       |
649(3 rows)
650
651-- bogus code
652set check_function_bodies to off;
653create or replace function f1()
654returns void as $$
655adasdfsadf
656$$ language plpgsql;
657select * from plpgsql_check_function_tb('f1()');
658 functionid | lineno | statement | sqlstate |               message                | detail | hint | level | position |   query    |                      context
659------------+--------+-----------+----------+--------------------------------------+--------+------+-------+----------+------------+---------------------------------------------------
660 f1         |        |           | 42601    | syntax error at or near "adasdfsadf" |        |      | error |        2 |           +| compilation of PL/pgSQL function "f1" near line 1
661            |        |           |          |                                      |        |      |       |          | adasdfsadf+|
662            |        |           |          |                                      |        |      |       |          |            |
663(1 row)
664
665drop function f1();
666create table t1(a int, b int);
667create function g1(out a int, out b int)
668as $$
669  select 10,20;
670$$ language sql;
671create function f1()
672returns void as $$
673declare r record;
674begin
675  r := g1();
676  if false then
677    raise notice '%', r.c;
678  end if;
679end;
680$$ language plpgsql;
681select f1();
682 f1
683----
684
685(1 row)
686
687select * from plpgsql_check_function('f1()');
688             plpgsql_check_function
689-------------------------------------------------
690 error:42703:6:RAISE:record "r" has no field "c"
691 Context: SQL statement "SELECT r.c"
692(2 rows)
693
694select f1();
695 f1
696----
697
698(1 row)
699
700drop function f1();
701drop function g1();
702create function g1(out a int, out b int)
703returns setof record as $$
704select * from t1;
705$$ language sql;
706create function f1()
707returns void as $$
708declare r record;
709begin
710  for r in select * from g1()
711  loop
712    raise notice '%', r.c;
713  end loop;
714end;
715$$ language plpgsql;
716select f1();
717 f1
718----
719
720(1 row)
721
722select * from plpgsql_check_function('f1()');
723             plpgsql_check_function
724-------------------------------------------------
725 error:42703:6:RAISE:record "r" has no field "c"
726 Context: SQL statement "SELECT r.c"
727(2 rows)
728
729select f1();
730 f1
731----
732
733(1 row)
734
735create or replace function f1()
736returns void as $$
737declare r record;
738begin
739  for r in select * from g1()
740  loop
741    r.c := 20;
742  end loop;
743end;
744$$ language plpgsql;
745select f1();
746 f1
747----
748
749(1 row)
750
751select * from plpgsql_check_function('f1()');
752                         plpgsql_check_function
753------------------------------------------------------------------------
754 error:42703:6:assignment:record "r" has no field "c"
755 Context: at assignment to field "c" of variable "r" declared on line 2
756(2 rows)
757
758select f1();
759 f1
760----
761
762(1 row)
763
764drop function f1();
765drop function g1();
766create function f1()
767returns int as $$
768declare r int;
769begin
770  if false then
771    r := a + b;
772  end if;
773  return r;
774end;
775$$ language plpgsql;
776select f1();
777 f1
778----
779
780(1 row)
781
782select * from plpgsql_check_function('f1()');
783                  plpgsql_check_function
784-----------------------------------------------------------
785 error:42703:5:assignment:column "a" does not exist
786 Query: SELECT a + b
787 --            ^
788 Context: at assignment to variable "r" declared on line 2
789(4 rows)
790
791select f1();
792 f1
793----
794
795(1 row)
796
797drop function f1();
798create or replace function f1()
799returns void as $$
800declare r int[];
801begin
802  if false then
803    r[c+10] := 20;
804  end if;
805end;
806$$ language plpgsql;
807select f1();
808 f1
809----
810
811(1 row)
812
813select * from plpgsql_check_function('f1()');
814                        plpgsql_check_function
815----------------------------------------------------------------------
816 error:42703:5:assignment:column "c" does not exist
817 Query: SELECT c+10
818 --            ^
819 Context: at assignment to element of variable "r" declared on line 2
820(4 rows)
821
822select f1();
823 f1
824----
825
826(1 row)
827
828drop function f1();
829create or replace function f1()
830returns void as $$
831declare r int;
832begin
833  if false then
834    r[10] := 20;
835  end if;
836end;
837$$ language plpgsql set search_path = public;
838select f1();
839 f1
840----
841
842(1 row)
843
844select * from plpgsql_check_function('f1()');
845                        plpgsql_check_function
846----------------------------------------------------------------------
847 error:42804:5:assignment:subscripted object is not an array
848 Context: at assignment to element of variable "r" declared on line 2
849(2 rows)
850
851select f1();
852 f1
853----
854
855(1 row)
856
857drop function f1();
858create or replace function f1_trg()
859returns trigger as $$
860begin
861  if new.a > 10 then
862    raise notice '%', new.b;
863    raise notice '%', new.c;
864  end if;
865  return new;
866end;
867$$ language plpgsql;
868create trigger t1_f1 before insert on t1
869  for each row
870  execute procedure f1_trg();
871insert into t1 values(6,30);
872select * from plpgsql_check_function('f1_trg()','t1');
873              plpgsql_check_function
874---------------------------------------------------
875 error:42703:5:RAISE:record "new" has no field "c"
876 Context: SQL statement "SELECT new.c"
877(2 rows)
878
879insert into t1 values(6,30);
880create or replace function f1_trg()
881returns trigger as $$
882begin
883  new.a := new.a + 10;
884  new.b := new.b + 10;
885  new.c := 30;
886  return new;
887end;
888$$ language plpgsql;
889-- should to fail
890select * from plpgsql_check_function('f1_trg()','t1');
891                          plpgsql_check_function
892--------------------------------------------------------------------------
893 error:42703:5:assignment:record "new" has no field "c"
894 Context: at assignment to field "c" of variable "new" declared on line 0
895(2 rows)
896
897-- should to fail but not crash
898insert into t1 values(6,30);
899ERROR:  record "new" has no field "c"
900CONTEXT:  PL/pgSQL function f1_trg() line 5 at assignment
901create or replace function f1_trg()
902returns trigger as $$
903begin
904  new.a := new.a + 10;
905  new.b := new.b + 10;
906  return new;
907end;
908$$ language plpgsql;
909-- ok
910select * from plpgsql_check_function('f1_trg()', 't1');
911 plpgsql_check_function
912------------------------
913(0 rows)
914
915-- ok
916insert into t1 values(6,30);
917select * from t1;
918 a  | b
919----+----
920  6 | 30
921  6 | 30
922 16 | 40
923(3 rows)
924
925drop trigger t1_f1 on t1;
926drop function f1_trg();
927-- test of showing caret on correct place for multiline queries
928create or replace function f1()
929returns void as $$
930begin
931  select
932  var
933  from
934  foo;
935end;
936$$ language plpgsql;
937select * from plpgsql_check_function('f1()');
938                  plpgsql_check_function
939-----------------------------------------------------------
940 error:42P01:3:SQL statement:relation "foo" does not exist
941 Query: select
942          var
943          from
944          foo
945 --       ^
946(6 rows)
947
948drop function f1();
949create or replace function f1()
950returns int as $$
951begin
952  return (select a
953             from t1
954            where hh = 20);
955end;
956$$ language plpgsql;
957select * from plpgsql_check_function('f1()');
958             plpgsql_check_function
959-------------------------------------------------
960 error:42703:3:RETURN:column "hh" does not exist
961 Query: SELECT (select a
962                     from t1
963                    where hh = 20)
964 --                       ^
965(5 rows)
966
967create or replace function f1()
968returns int as $$
969begin
970  return (select a
971             from txxxxxxx
972            where hh = 20);
973end;
974$$ language plpgsql;
975select * from plpgsql_check_function('f1()');
976                 plpgsql_check_function
977---------------------------------------------------------
978 error:42P01:3:RETURN:relation "txxxxxxx" does not exist
979 Query: SELECT (select a
980                     from txxxxxxx
981 --                       ^
982                    where hh = 20)
983(5 rows)
984
985drop function f1();
986drop table t1;
987-- raise warnings when target row has different number of attributies in
988-- SELECT INTO statement
989create or replace function f1()
990returns void as $$
991declare a1 int; a2 int;
992begin
993  select 10,20 into a1,a2;
994end;
995$$ language plpgsql;
996-- should be ok
997select * from plpgsql_check_function('f1()');
998                 plpgsql_check_function
999--------------------------------------------------------
1000 warning extra:00000:2:DECLARE:never read variable "a1"
1001 warning extra:00000:2:DECLARE:never read variable "a2"
1002(2 rows)
1003
1004create or replace function f1()
1005returns void as $$
1006declare a1 int;
1007begin
1008  select 10,20 into a1;
1009end;
1010$$ language plpgsql;
1011-- raise warning
1012select * from plpgsql_check_function('f1()');
1013                         plpgsql_check_function
1014------------------------------------------------------------------------
1015 warning:00000:4:SQL statement:too many attributes for target variables
1016 Detail: There are less target variables than output columns in query.
1017 Hint: Check target variables in SELECT INTO statement
1018 warning extra:00000:2:DECLARE:never read variable "a1"
1019(4 rows)
1020
1021create or replace function f1()
1022returns void as $$
1023declare a1 int; a2 int;
1024begin
1025  select 10 into a1,a2;
1026end;
1027$$ language plpgsql;
1028-- raise warning
1029select * from plpgsql_check_function('f1()');
1030                        plpgsql_check_function
1031-----------------------------------------------------------------------
1032 warning:00000:4:SQL statement:too few attributes for target variables
1033 Detail: There are more target variables than output columns in query.
1034 Hint: Check target variables in SELECT INTO statement.
1035 warning extra:00000:2:DECLARE:never read variable "a1"
1036 warning extra:00000:2:DECLARE:never read variable "a2"
1037(5 rows)
1038
1039-- bogus code
1040set check_function_bodies to off;
1041create or replace function f1()
1042returns void as $$
1043adasdfsadf
1044$$ language plpgsql;
1045select * from plpgsql_check_function('f1()');
1046                   plpgsql_check_function
1047------------------------------------------------------------
1048 error:42601:syntax error at or near "adasdfsadf"
1049 Query:
1050        adasdfsadf
1051 --     ^
1052
1053 Context: compilation of PL/pgSQL function "f1" near line 1
1054(6 rows)
1055
1056drop function f1();
1057create table f1tbl(a int, b int);
1058-- unused variables
1059create or replace function f1(_input1 int)
1060returns table(_output1 int, _output2 int)
1061as $$
1062declare
1063_f1 int;
1064_f2 int;
1065_f3 int;
1066_f4 int;
1067_f5 int;
1068_r record;
1069_tbl f1tbl;
1070begin
1071if true then
1072	_f1 := 1;
1073end if;
1074select 1, 2 into _f3, _f4;
1075perform 1 where _f5 is null;
1076select 1 into _r;
1077select 1, 2 into _tbl;
1078
1079-- check that SQLSTATE and SQLERRM don't raise false positives
1080begin
1081exception when raise_exception then
1082end;
1083
1084end
1085$$ language plpgsql;
1086select * from plpgsql_check_function('f1(int)');
1087                  plpgsql_check_function
1088----------------------------------------------------------
1089 warning:00000:4:DECLARE:unused variable "_f2"
1090 warning extra:00000:3:DECLARE:never read variable "_f1"
1091 warning extra:00000:5:DECLARE:never read variable "_f3"
1092 warning extra:00000:6:DECLARE:never read variable "_f4"
1093 warning extra:00000:8:DECLARE:never read variable "_r"
1094 warning extra:00000:9:DECLARE:never read variable "_tbl"
1095 warning extra:00000:unused parameter "_input1"
1096 warning extra:00000:unmodified OUT variable "_output1"
1097 warning extra:00000:unmodified OUT variable "_output2"
1098(9 rows)
1099
1100drop function f1(int);
1101drop table f1tbl;
1102-- check that NEW and OLD are not reported unused
1103create table f1tbl();
1104create or replace function f1()
1105returns trigger
1106as $$
1107begin
1108return null;
1109end
1110$$ language plpgsql;
1111select * from plpgsql_check_function('f1()', 'f1tbl');
1112 plpgsql_check_function
1113------------------------
1114(0 rows)
1115
1116drop function f1();
1117drop table f1tbl;
1118create table tabret(a int, b int);
1119insert into tabret values(10,10);
1120create or replace function f1()
1121returns int as $$
1122begin
1123  return (select a from tabret);
1124end;
1125$$ language plpgsql;
1126select * from plpgsql_check_function('f1()', performance_warnings := true);
1127                                 plpgsql_check_function
1128-----------------------------------------------------------------------------------------
1129 performance:00000:routine is marked as VOLATILE, should be STABLE
1130 Hint: When you fix this issue, please, recheck other functions that uses this function.
1131(2 rows)
1132
1133create or replace function f1()
1134returns int as $$
1135begin
1136  return (select a::numeric from tabret);
1137end;
1138$$ language plpgsql;
1139select * from plpgsql_check_function('f1()', performance_warnings := true);
1140                                 plpgsql_check_function
1141-----------------------------------------------------------------------------------------
1142 performance:42804:3:RETURN:target type is different type than source type
1143 Detail: cast "numeric" value to "integer" type
1144 Hint: Hidden casting can be a performance issue.
1145 performance:00000:routine is marked as VOLATILE, should be STABLE
1146 Hint: When you fix this issue, please, recheck other functions that uses this function.
1147(5 rows)
1148
1149create or replace function f1()
1150returns int as $$
1151begin
1152  return (select a, b from tabret);
1153end;
1154$$ language plpgsql;
1155select * from plpgsql_check_function('f1()', performance_warnings := true);
1156                  plpgsql_check_function
1157-----------------------------------------------------------
1158 error:42601:3:RETURN:subquery must return only one column
1159 Query: SELECT (select a, b from tabret)
1160 --            ^
1161(3 rows)
1162
1163drop function f1();
1164create or replace function f1()
1165returns table(ax int, bx int) as $$
1166begin
1167  return query select * from tabret;
1168  return;
1169end;
1170$$ language plpgsql;
1171select * from plpgsql_check_function('f1()', performance_warnings := true);
1172                                 plpgsql_check_function
1173-----------------------------------------------------------------------------------------
1174 performance:00000:routine is marked as VOLATILE, should be STABLE
1175 Hint: When you fix this issue, please, recheck other functions that uses this function.
1176(2 rows)
1177
1178drop function f1();
1179create or replace function f1()
1180returns table(ax numeric, bx numeric) as $$
1181begin
1182  return query select * from tabret;
1183  return;
1184end;
1185$$ language plpgsql;
1186select * from plpgsql_check_function('f1()', performance_warnings := true);
1187                              plpgsql_check_function
1188-----------------------------------------------------------------------------------
1189 error:42804:3:RETURN QUERY:structure of query does not match function result type
1190 Detail: Returned type integer does not match expected type numeric in column 1.
1191(2 rows)
1192
1193drop function f1();
1194create or replace function f1()
1195returns setof tabret as $$
1196begin
1197  return query select * from tabret;
1198  return;
1199end;
1200$$ language plpgsql;
1201select * from plpgsql_check_function('f1()', performance_warnings := true);
1202                                 plpgsql_check_function
1203-----------------------------------------------------------------------------------------
1204 performance:00000:routine is marked as VOLATILE, should be STABLE
1205 Hint: When you fix this issue, please, recheck other functions that uses this function.
1206(2 rows)
1207
1208create or replace function f1()
1209returns setof tabret as $$
1210begin
1211  return query select a from tabret;
1212  return;
1213end;
1214$$ language plpgsql;
1215select * from plpgsql_check_function('f1()', performance_warnings := true);
1216                              plpgsql_check_function
1217-----------------------------------------------------------------------------------
1218 error:42804:3:RETURN QUERY:structure of query does not match function result type
1219 Detail: Number of returned columns (1) does not match expected column count (2).
1220(2 rows)
1221
1222create or replace function f1()
1223returns setof tabret as $$
1224begin
1225  return query select a::numeric,b::numeric from tabret;
1226  return;
1227end;
1228$$ language plpgsql;
1229select * from plpgsql_check_function('f1()', performance_warnings := true);
1230                              plpgsql_check_function
1231-----------------------------------------------------------------------------------
1232 error:42804:3:RETURN QUERY:structure of query does not match function result type
1233 Detail: Returned type numeric does not match expected type integer in column 1.
1234(2 rows)
1235
1236drop function f1();
1237create or replace function f1(a int)
1238returns setof numeric as $$
1239begin return query select a;
1240end $$ language plpgsql;
1241select * from plpgsql_check_function('f1(int)', performance_warnings := true);
1242                              plpgsql_check_function
1243-----------------------------------------------------------------------------------
1244 error:42804:2:RETURN QUERY:structure of query does not match function result type
1245 Detail: Returned type integer does not match expected type numeric in column 1.
1246(2 rows)
1247
1248drop function f1(int);
1249drop table tabret;
1250create or replace function f1() returns void as $$
1251declare
1252intval integer;
1253begin
1254  intval := null; -- ok
1255  intval := 1; -- OK
1256  intval := '1'; -- OK
1257  intval := text '1'; -- not OK
1258  intval := current_date; -- not OK
1259
1260  select 1 into intval; -- OK
1261  select '1' into intval; -- OK
1262  select text '1' into intval; -- not OK
1263end
1264$$ language plpgsql;
1265select * from plpgsql_check_function('f1()', performance_warnings := true);
1266                                plpgsql_check_function
1267--------------------------------------------------------------------------------------
1268 warning:42804:7:assignment:target type is different type than source type
1269 Detail: cast "text" value to "integer" type
1270 Hint: The input expression type does not have an assignment cast to the target type.
1271 Context: at assignment to variable "intval" declared on line 3
1272 warning:42804:8:assignment:target type is different type than source type
1273 Detail: cast "text" value to "integer" type
1274 Hint: The input expression type does not have an assignment cast to the target type.
1275 Context: at assignment to variable "intval" declared on line 3
1276 warning:42804:9:assignment:target type is different type than source type
1277 Detail: cast "date" value to "integer" type
1278 Hint: There are no possible explicit coercion between those types, possibly bug!
1279 Context: at assignment to variable "intval" declared on line 3
1280 warning:42804:12:SQL statement:target type is different type than source type
1281 Detail: cast "text" value to "integer" type
1282 Hint: The input expression type does not have an assignment cast to the target type.
1283 warning:42804:13:SQL statement:target type is different type than source type
1284 Detail: cast "text" value to "integer" type
1285 Hint: The input expression type does not have an assignment cast to the target type.
1286 warning extra:00000:3:DECLARE:never read variable "intval"
1287(19 rows)
1288
1289drop function f1();
1290create or replace function f1()
1291returns int as $$
1292begin
1293  return 1;
1294end;
1295$$ language plpgsql;
1296select * from plpgsql_check_function('f1()', performance_warnings := true);
1297                                 plpgsql_check_function
1298-----------------------------------------------------------------------------------------
1299 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1300 Hint: When you fix this issue, please, recheck other functions that uses this function.
1301(2 rows)
1302
1303create or replace function f1()
1304returns int as $$
1305begin
1306  return 1::numeric;
1307end;
1308$$ language plpgsql;
1309select * from plpgsql_check_function('f1()', performance_warnings := true);
1310                                 plpgsql_check_function
1311-----------------------------------------------------------------------------------------
1312 performance:42804:3:RETURN:target type is different type than source type
1313 Detail: cast "numeric" value to "integer" type
1314 Hint: Hidden casting can be a performance issue.
1315 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1316 Hint: When you fix this issue, please, recheck other functions that uses this function.
1317(5 rows)
1318
1319create or replace function f1()
1320returns int as $$
1321begin
1322  return null;
1323end;
1324$$ language plpgsql;
1325select * from plpgsql_check_function('f1()', performance_warnings := true);
1326                                 plpgsql_check_function
1327-----------------------------------------------------------------------------------------
1328 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1329 Hint: When you fix this issue, please, recheck other functions that uses this function.
1330(2 rows)
1331
1332create or replace function f1()
1333returns int as $$
1334begin
1335  return current_date;
1336end;
1337$$ language plpgsql;
1338select * from plpgsql_check_function('f1()', performance_warnings := true);
1339                                 plpgsql_check_function
1340-----------------------------------------------------------------------------------------
1341 warning:42804:3:RETURN:target type is different type than source type
1342 Detail: cast "date" value to "integer" type
1343 Hint: There are no possible explicit coercion between those types, possibly bug!
1344 performance:00000:routine is marked as VOLATILE, should be STABLE
1345 Hint: When you fix this issue, please, recheck other functions that uses this function.
1346(5 rows)
1347
1348create or replace function f1()
1349returns int as $$
1350declare a int;
1351begin
1352  return a;
1353end;
1354$$ language plpgsql;
1355select * from plpgsql_check_function('f1()', performance_warnings := true);
1356                                 plpgsql_check_function
1357-----------------------------------------------------------------------------------------
1358 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1359 Hint: When you fix this issue, please, recheck other functions that uses this function.
1360(2 rows)
1361
1362create or replace function f1()
1363returns int as $$
1364declare a numeric;
1365begin
1366  return a;
1367end;
1368$$ language plpgsql;
1369select * from plpgsql_check_function('f1()', performance_warnings := true);
1370                                 plpgsql_check_function
1371-----------------------------------------------------------------------------------------
1372 performance:42804:4:RETURN:target type is different type than source type
1373 Detail: cast "numeric" value to "integer" type
1374 Hint: Hidden casting can be a performance issue.
1375 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1376 Hint: When you fix this issue, please, recheck other functions that uses this function.
1377(5 rows)
1378
1379drop function f1();
1380create or replace function f1()
1381returns setof int as $$
1382begin
1383  return next 1;
1384end;
1385$$ language plpgsql;
1386select * from plpgsql_check_function('f1()', performance_warnings := true);
1387                                 plpgsql_check_function
1388-----------------------------------------------------------------------------------------
1389 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1390 Hint: When you fix this issue, please, recheck other functions that uses this function.
1391(2 rows)
1392
1393create or replace function f1()
1394returns setof int as $$
1395begin
1396  return next 1::numeric; -- tolerant, doesn't use tupmap
1397end;
1398$$ language plpgsql;
1399select * from plpgsql_check_function('f1()', performance_warnings := true);
1400                                 plpgsql_check_function
1401-----------------------------------------------------------------------------------------
1402 performance:42804:3:RETURN NEXT:target type is different type than source type
1403 Detail: cast "numeric" value to "integer" type
1404 Hint: Hidden casting can be a performance issue.
1405 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1406 Hint: When you fix this issue, please, recheck other functions that uses this function.
1407(5 rows)
1408
1409drop function f1();
1410create type t1 as (a int, b int, c int);
1411create type t2 as (a int, b numeric);
1412create or replace function fx()
1413returns t2 as $$
1414declare x t1;
1415begin
1416  return x;
1417end;
1418$$ language plpgsql;
1419select * from plpgsql_check_function('fx()', performance_warnings := true);
1420                             plpgsql_check_function
1421---------------------------------------------------------------------------------
1422 error:42804:4:RETURN:returned record type does not match expected record type
1423 Detail: Returned type integer does not match expected type numeric in column 2.
1424(2 rows)
1425
1426create or replace function fx()
1427returns t2 as $$
1428declare x t2;
1429begin
1430  return x;
1431end;
1432$$ language plpgsql;
1433select * from plpgsql_check_function('fx()', performance_warnings := true);
1434                                 plpgsql_check_function
1435-----------------------------------------------------------------------------------------
1436 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1437 Hint: When you fix this issue, please, recheck other functions that uses this function.
1438(2 rows)
1439
1440drop function fx();
1441create or replace function fx()
1442returns setof t2 as $$
1443declare x t1;
1444begin
1445  return next x;
1446  return;
1447end;
1448$$ language plpgsql;
1449select * from plpgsql_check_function('fx()', performance_warnings := true);
1450                             plpgsql_check_function
1451---------------------------------------------------------------------------------
1452 error:42804:4:RETURN NEXT:wrong record type supplied in RETURN NEXT
1453 Detail: Returned type integer does not match expected type numeric in column 2.
1454(2 rows)
1455
1456create or replace function fx()
1457returns setof t2 as $$
1458declare x t2;
1459begin
1460  return next x;
1461  return;
1462end;
1463$$ language plpgsql;
1464select * from plpgsql_check_function('fx()', performance_warnings := true);
1465                                 plpgsql_check_function
1466-----------------------------------------------------------------------------------------
1467 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
1468 Hint: When you fix this issue, please, recheck other functions that uses this function.
1469(2 rows)
1470
1471drop function fx();
1472create or replace function fx2(_id int, _pa_id varchar(32), _status varchar(60))
1473returns void as $$
1474declare
1475begin
1476  insert into pa values(_id, _pa_id, _status);
1477exception
1478  when OTHERS then
1479    raise notice '%', 'some message';
1480    raise exception '%', sqlerrm;
1481end
1482$$ language plpgsql;
1483select * from plpgsql_check_function('fx2(int, varchar, varchar)', performance_warnings := true);
1484 plpgsql_check_function
1485------------------------
1486(0 rows)
1487
1488create or replace function fx2(_id int, _pa_id varchar(32), _status varchar(60))
1489returns void as $$
1490declare
1491begin
1492  insert into pa values(_id, _pa_id, _status) returning *;
1493exception
1494  when OTHERS then
1495    raise notice '%', 'some message';
1496    raise exception '%', sqlerrm;
1497end
1498$$ language plpgsql;
1499select * from plpgsql_check_function('fx2(int, varchar, varchar)', performance_warnings := true);
1500                        plpgsql_check_function
1501----------------------------------------------------------------------
1502 error:42601:4:SQL statement:query has no destination for result data
1503(1 row)
1504
1505create or replace function fx2(_id int, _pa_id varchar(32), _status varchar(60))
1506returns void as $$
1507declare
1508begin
1509  SELECT * FROM pa LIMIT 1;
1510exception
1511  when OTHERS then
1512    raise notice '%', 'some message';
1513    raise exception '%', sqlerrm;
1514end
1515$$ language plpgsql;
1516select * from plpgsql_check_function('fx2(int, varchar, varchar)', performance_warnings := true);
1517                        plpgsql_check_function
1518----------------------------------------------------------------------
1519 error:42601:4:SQL statement:query has no destination for result data
1520(1 row)
1521
1522drop function fx2(int, varchar, varchar);
1523create or replace function foreach_array_loop()
1524returns void as
1525$body$
1526declare
1527  arr text[];
1528  el text;
1529begin
1530  arr := array['1111','2222','3333'];
1531  foreach el in array arr loop
1532    raise notice '%', el;
1533  end loop;
1534end;
1535$body$
1536language 'plpgsql' stable;
1537select * from plpgsql_check_function_tb('foreach_array_loop()', performance_warnings := true);
1538     functionid     | lineno | statement | sqlstate |                     message                      | detail |                                       hint                                        |    level    | position | query | context
1539--------------------+--------+-----------+----------+--------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1540 foreach_array_loop |        |           | 00000    | routine is marked as STABLE, should be IMMUTABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1541(1 row)
1542
1543create or replace function foreach_array_loop()
1544returns void as
1545$body$
1546declare
1547  arr text[];
1548  el int;
1549begin
1550  arr := array['1111','2222','3333'];
1551  foreach el in array arr loop
1552    raise notice '%', el;
1553  end loop;
1554end;
1555$body$
1556language 'plpgsql' stable;
1557select * from plpgsql_check_function_tb('foreach_array_loop()', performance_warnings := true);
1558     functionid     | lineno |     statement      | sqlstate |                     message                      |               detail                |                                       hint                                        |    level    | position | query | context
1559--------------------+--------+--------------------+----------+--------------------------------------------------+-------------------------------------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1560 foreach_array_loop |      7 | FOREACH over array | 42804    | target type is different type than source type   | cast "text" value to "integer" type | The input expression type does not have an assignment cast to the target type.    | warning     |          |       |
1561 foreach_array_loop |        |                    | 00000    | routine is marked as STABLE, should be IMMUTABLE |                                     | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1562(2 rows)
1563
1564create or replace function foreach_array_loop()
1565returns void as
1566$body$
1567declare
1568  arr date[];
1569  el int;
1570begin
1571  arr := array['2014-01-01','2015-01-01','2016-01-01']::date[];
1572  foreach el in array arr loop
1573    raise notice '%', el;
1574  end loop;
1575end;
1576$body$
1577language 'plpgsql' stable;
1578select * from plpgsql_check_function_tb('foreach_array_loop()', performance_warnings := true);
1579     functionid     | lineno |     statement      | sqlstate |                     message                      |               detail                |                                       hint                                        |    level    | position | query | context
1580--------------------+--------+--------------------+----------+--------------------------------------------------+-------------------------------------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1581 foreach_array_loop |      7 | FOREACH over array | 42804    | target type is different type than source type   | cast "date" value to "integer" type | There are no possible explicit coercion between those types, possibly bug!        | warning     |          |       |
1582 foreach_array_loop |        |                    | 00000    | routine is marked as STABLE, should be IMMUTABLE |                                     | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1583(2 rows)
1584
1585create or replace function foreach_array_loop()
1586returns void as
1587$body$
1588declare
1589  el text;
1590begin
1591  foreach el in array array['1111','2222','3333'] loop
1592    raise notice '%', el;
1593  end loop;
1594end;
1595$body$
1596language 'plpgsql' stable;
1597select * from plpgsql_check_function_tb('foreach_array_loop()', performance_warnings := true);
1598     functionid     | lineno | statement | sqlstate |                     message                      | detail |                                       hint                                        |    level    | position | query | context
1599--------------------+--------+-----------+----------+--------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1600 foreach_array_loop |        |           | 00000    | routine is marked as STABLE, should be IMMUTABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1601(1 row)
1602
1603create or replace function foreach_array_loop()
1604returns void as
1605$body$
1606declare
1607  el int;
1608begin
1609  foreach el in array array['1111','2222','3333'] loop
1610    raise notice '%', el;
1611  end loop;
1612end;
1613$body$
1614language 'plpgsql' stable;
1615select * from plpgsql_check_function_tb('foreach_array_loop()', performance_warnings := true);
1616     functionid     | lineno |     statement      | sqlstate |                     message                      |               detail                |                                       hint                                        |    level    | position | query | context
1617--------------------+--------+--------------------+----------+--------------------------------------------------+-------------------------------------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1618 foreach_array_loop |      5 | FOREACH over array | 42804    | target type is different type than source type   | cast "text" value to "integer" type | The input expression type does not have an assignment cast to the target type.    | warning     |          |       |
1619 foreach_array_loop |        |                    | 00000    | routine is marked as STABLE, should be IMMUTABLE |                                     | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1620(2 rows)
1621
1622create or replace function foreach_array_loop()
1623returns void as
1624$body$
1625declare
1626  el int;
1627begin
1628  foreach el in array array['2014-01-01','2015-01-01','2016-01-01']::date[] loop
1629    raise notice '%', el;
1630  end loop;
1631end;
1632$body$
1633language 'plpgsql' stable;
1634select * from plpgsql_check_function_tb('foreach_array_loop()', performance_warnings := true);
1635     functionid     | lineno |     statement      | sqlstate |                     message                      |               detail                |                                       hint                                        |    level    | position | query | context
1636--------------------+--------+--------------------+----------+--------------------------------------------------+-------------------------------------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1637 foreach_array_loop |      5 | FOREACH over array | 42804    | target type is different type than source type   | cast "date" value to "integer" type | There are no possible explicit coercion between those types, possibly bug!        | warning     |          |       |
1638 foreach_array_loop |        |                    | 00000    | routine is marked as STABLE, should be IMMUTABLE |                                     | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1639(2 rows)
1640
1641drop function foreach_array_loop();
1642create or replace function scan_rows(int[]) returns void AS $$
1643declare
1644  x int[];
1645begin
1646  foreach x slice 1 in array $1
1647  loop
1648    raise notice 'row = %', x;
1649  end loop;
1650end;
1651$$ language plpgsql;
1652select * from plpgsql_check_function_tb('scan_rows(int[])', performance_warnings := true);
1653 functionid | lineno | statement | sqlstate |                      message                       | detail |                                       hint                                        |    level    | position | query | context
1654------------+--------+-----------+----------+----------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1655 scan_rows  |        |           | 00000    | routine is marked as VOLATILE, should be IMMUTABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1656(1 row)
1657
1658create or replace function scan_rows(int[]) returns void AS $$
1659declare
1660  x int[];
1661begin
1662  foreach x in array $1
1663  loop
1664    raise notice 'row = %', x;
1665  end loop;
1666end;
1667$$ language plpgsql;
1668select * from plpgsql_check_function_tb('scan_rows(int[])', performance_warnings := true);
1669 functionid | lineno |     statement      | sqlstate |                      message                       |                  detail                  |                                       hint                                        |    level    | position | query | context
1670------------+--------+--------------------+----------+----------------------------------------------------+------------------------------------------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1671 scan_rows  |      5 | FOREACH over array | 42804    | target type is different type than source type     | cast "integer" value to "integer[]" type | There are no possible explicit coercion between those types, possibly bug!        | warning     |          |       |
1672 scan_rows  |        |                    | 00000    | routine is marked as VOLATILE, should be IMMUTABLE |                                          | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1673(2 rows)
1674
1675drop function scan_rows(int[]);
1676drop function fx();
1677ERROR:  function fx() does not exist
1678drop type t1;
1679drop type t2;
1680create table t1(a int, b int);
1681create table t2(a int, b int, c int);
1682create table t3(a numeric, b int);
1683insert into t1 values(10,20),(30,40);
1684create or replace function fx()
1685returns int as $$
1686declare
1687  s int default 0;
1688  r t1;
1689begin
1690  foreach r in array (select array_agg(t1) from t1)
1691  loop
1692    s := r.a + r.b;
1693  end loop;
1694  return s;
1695end;
1696$$ language plpgsql;
1697select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1698 functionid | lineno | statement | sqlstate |                     message                     | detail |                                       hint                                        |    level    | position | query | context
1699------------+--------+-----------+----------+-------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1700 fx         |        |           | 00000    | routine is marked as VOLATILE, should be STABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1701(1 row)
1702
1703create or replace function fx()
1704returns int as $$
1705declare
1706  s int default 0;
1707  r t1;
1708  c t1[];
1709begin
1710  c := (select array_agg(t1) from t1);
1711  foreach r in array c
1712  loop
1713    s := r.a + r.b;
1714  end loop;
1715  return s;
1716end;
1717$$ language plpgsql;
1718select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1719 functionid | lineno | statement | sqlstate |                     message                     | detail |                                       hint                                        |    level    | position | query | context
1720------------+--------+-----------+----------+-------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1721 fx         |        |           | 00000    | routine is marked as VOLATILE, should be STABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1722(1 row)
1723
1724create or replace function fx()
1725returns int as $$
1726declare
1727  s int default 0;
1728  r t1;
1729  c t1[];
1730begin
1731  select array_agg(t1) into c from t1;
1732  foreach r in array c
1733  loop
1734    s := r.a + r.b;
1735  end loop;
1736  return s;
1737end;
1738$$ language plpgsql;
1739select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1740 functionid | lineno | statement | sqlstate |                     message                     | detail |                                       hint                                        |    level    | position | query | context
1741------------+--------+-----------+----------+-------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1742 fx         |        |           | 00000    | routine is marked as VOLATILE, should be STABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1743(1 row)
1744
1745create or replace function fx()
1746returns int as $$
1747declare
1748  s int default 0;
1749  r t1;
1750  c t1[];
1751begin
1752  select array_agg(t1) into c from t1;
1753  for i in array_lower(c, 1) .. array_upper(c, 1)
1754  loop
1755    r := c[i];
1756    s := r.a + r.b;
1757  end loop;
1758  return s;
1759end;
1760$$ language plpgsql;
1761select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1762 functionid | lineno | statement | sqlstate |                     message                     | detail |                                       hint                                        |    level    | position | query | context
1763------------+--------+-----------+----------+-------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1764 fx         |        |           | 00000    | routine is marked as VOLATILE, should be STABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1765(1 row)
1766
1767create or replace function fx()
1768returns int as $$
1769declare
1770  s int default 0;
1771  c t1[];
1772begin
1773  select array_agg(t1) into c from t1;
1774  for i in array_lower(c, 1) .. array_upper(c, 1)
1775  loop
1776    s := (c[i]).a + (c[i]).b;
1777  end loop;
1778  return s;
1779end;
1780$$ language plpgsql;
1781select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1782 functionid | lineno | statement | sqlstate |                     message                     | detail |                                       hint                                        |    level    | position | query | context
1783------------+--------+-----------+----------+-------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1784 fx         |        |           | 00000    | routine is marked as VOLATILE, should be STABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1785(1 row)
1786
1787create or replace function fx()
1788returns int as $$
1789declare
1790  s int default 0;
1791  r record;
1792  c t1[];
1793begin
1794  select array_agg(t1) into c from t1;
1795  for i in array_lower(c, 1) .. array_upper(c, 1)
1796  loop
1797    r := c[i];
1798    s := r.a + r.b;
1799  end loop;
1800  return s;
1801end;
1802$$ language plpgsql;
1803select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1804 functionid | lineno | statement | sqlstate |                     message                     | detail |                                       hint                                        |    level    | position | query | context
1805------------+--------+-----------+----------+-------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1806 fx         |        |           | 00000    | routine is marked as VOLATILE, should be STABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1807(1 row)
1808
1809create or replace function fx()
1810returns int as $$
1811declare
1812  s int default 0;
1813  r record;
1814  c t1[];
1815begin
1816  select array_agg(t1) into c from t1;
1817  for i in array_lower(c, 1) .. array_upper(c, 1)
1818  loop
1819    r := c[i];
1820    s := r.a + r.b + r.c;
1821  end loop;
1822  return s;
1823end;
1824$$ language plpgsql;
1825select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1826 functionid | lineno | statement  | sqlstate |           message           | detail | hint | level | position | query |                context
1827------------+--------+------------+----------+-----------------------------+--------+------+-------+----------+-------+----------------------------------------
1828 fx         |     11 | assignment | 42703    | record "r" has no field "c" |        |      | error |          |       | SQL statement "SELECT r.a + r.b + r.c"
1829(1 row)
1830
1831create or replace function fx()
1832returns int as $$
1833declare
1834  s int default 0;
1835  r t2;
1836begin
1837  foreach r in array (select array_agg(t1) from t1)
1838  loop
1839    s := r.a + r.b;
1840  end loop;
1841  return s;
1842end;
1843$$ language plpgsql;
1844select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1845 functionid | lineno |     statement      | sqlstate |                     message                     | detail |                                       hint                                        |    level    | position | query | context
1846------------+--------+--------------------+----------+-------------------------------------------------+--------+-----------------------------------------------------------------------------------+-------------+----------+-------+---------
1847 fx         |      6 | FOREACH over array | 00000    | too few attributes for composite variable       |        |                                                                                   | warning     |          |       |
1848 fx         |        |                    | 00000    | routine is marked as VOLATILE, should be STABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1849(2 rows)
1850
1851create or replace function fx()
1852returns int as $$
1853declare
1854  s int default 0;
1855  r t3;
1856begin
1857  foreach r in array (select array_agg(t1) from t1)
1858  loop
1859    s := r.a + r.b;
1860  end loop;
1861  return s;
1862end;
1863$$ language plpgsql;
1864select * from plpgsql_check_function_tb('fx()', performance_warnings := true);
1865 functionid | lineno |     statement      | sqlstate |                     message                     |                 detail                 |                                       hint                                        |    level    | position | query |                     context
1866------------+--------+--------------------+----------+-------------------------------------------------+----------------------------------------+-----------------------------------------------------------------------------------+-------------+----------+-------+--------------------------------------------------
1867 fx         |      6 | FOREACH over array | 42804    | target type is different type than source type  | cast "integer" value to "numeric" type | Hidden casting can be a performance issue.                                        | performance |          |       |
1868 fx         |      8 | assignment         | 42804    | target type is different type than source type  | cast "numeric" value to "integer" type | Hidden casting can be a performance issue.                                        | performance |          |       | at assignment to variable "s" declared on line 3
1869 fx         |        |                    | 00000    | routine is marked as VOLATILE, should be STABLE |                                        | When you fix this issue, please, recheck other functions that uses this function. | performance |          |       |
1870(3 rows)
1871
1872drop function fx();
1873drop table t1;
1874-- mscottie issue #13
1875create table test (
1876  a text,
1877  b integer,
1878  c uuid
1879);
1880create function before_insert_test()
1881returns trigger language plpgsql as $$
1882begin
1883  select a into NEW.a from test where b = 1;
1884  select b into NEW.b from test where b = 1;
1885  select null::uuid into NEW.c from test where b = 1;
1886  return new;
1887end;
1888$$;
1889select * from plpgsql_check_function_tb('before_insert_test()','test');
1890 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
1891------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
1892(0 rows)
1893
1894create or replace function before_insert_test()
1895returns trigger language plpgsql as $$
1896begin
1897  NEW.a := (select a from test where b = 1);
1898  NEW.b := (select b from test where b = 1);
1899  NEW.c := (select c from test where b = 1);
1900  return new;
1901end;
1902$$;
1903select * from plpgsql_check_function_tb('before_insert_test()','test', fatal_errors := false);
1904 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
1905------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
1906(0 rows)
1907
1908create or replace function before_insert_test()
1909returns trigger language plpgsql as $$
1910begin
1911  NEW.a := 'Hello'::text;
1912  NEW.b := 10;
1913  NEW.c := null::uuid;
1914  return new;
1915end;
1916$$;
1917select * from plpgsql_check_function_tb('before_insert_test()','test', fatal_errors := false);
1918 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
1919------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
1920(0 rows)
1921
1922drop function before_insert_test();
1923create or replace function fx()
1924returns void as $$
1925declare NEW test; OLD test;
1926begin
1927  select null::uuid into NEW.c from test where b = 1;
1928end;
1929$$ language plpgsql;
1930select * from plpgsql_check_function_tb('fx()', performance_warnings := true, fatal_errors := false);
1931 functionid | lineno | statement | sqlstate |          message          | detail | hint |     level     | position | query | context
1932------------+--------+-----------+----------+---------------------------+--------+------+---------------+----------+-------+---------
1933 fx         |      2 | DECLARE   | 00000    | unused variable "old"     |        |      | warning       |          |       |
1934 fx         |      2 | DECLARE   | 00000    | never read variable "new" |        |      | warning extra |          |       |
1935(2 rows)
1936
1937drop function fx();
1938create or replace function fx()
1939returns void as $$
1940declare NEW test;
1941begin
1942  NEW.a := 'Hello'::text;
1943  NEW.b := 10;
1944  NEW.c := null::uuid;
1945end;
1946$$ language plpgsql;
1947select * from plpgsql_check_function_tb('fx()', performance_warnings := true, fatal_errors := false);
1948 functionid | lineno | statement | sqlstate |                      message                       | detail |                                       hint                                        |     level     | position | query | context
1949------------+--------+-----------+----------+----------------------------------------------------+--------+-----------------------------------------------------------------------------------+---------------+----------+-------+---------
1950 fx         |      2 | DECLARE   | 00000    | never read variable "new"                          |        |                                                                                   | warning extra |          |       |
1951 fx         |        |           | 00000    | routine is marked as VOLATILE, should be IMMUTABLE |        | When you fix this issue, please, recheck other functions that uses this function. | performance   |          |       |
1952(2 rows)
1953
1954drop function fx();
1955drop table test;
1956create or replace function fx()
1957returns void as $$
1958declare
1959  s int;
1960  sa int[];
1961  sd date;
1962  bs int[];
1963begin
1964  sa[10] := s;
1965  sa[10] := sd;
1966  s := bs[10];
1967end;
1968$$ language plpgsql;
1969select * from plpgsql_check_function_tb('fx()', performance_warnings := true, fatal_errors := false);
1970 functionid | lineno | statement  | sqlstate |                      message                       |               detail                |                                       hint                                        |     level     | position | query |                           context
1971------------+--------+------------+----------+----------------------------------------------------+-------------------------------------+-----------------------------------------------------------------------------------+---------------+----------+-------+--------------------------------------------------------------
1972 fx         |      9 | assignment | 42804    | target type is different type than source type     | cast "date" value to "integer" type | There are no possible explicit coercion between those types, possibly bug!        | warning       |          |       | at assignment to element of variable "sa" declared on line 4
1973 fx         |      4 | DECLARE    | 00000    | never read variable "sa"                           |                                     |                                                                                   | warning extra |          |       |
1974 fx         |        |            | 00000    | routine is marked as VOLATILE, should be IMMUTABLE |                                     | When you fix this issue, please, recheck other functions that uses this function. | performance   |          |       |
1975(3 rows)
1976
1977drop function fx();
1978create type t as (t text);
1979create or replace function fx()
1980returns void as $$
1981declare _t t; _tt t[];
1982  _txt text;
1983begin
1984  _t.t := 'ABC'; -- correct warning "unknown"
1985  _tt[1] := _t;
1986  _txt := _t;
1987end;
1988$$ language plpgsql;
1989select * from plpgsql_check_function('fx()', performance_warnings := true);
1990                                      plpgsql_check_function
1991---------------------------------------------------------------------------------------------------
1992 error:42804:7:assignment:cannot cast composite value of "t" type to a scalar value of "text" type
1993 Context: at assignment to variable "_txt" declared on line 3
1994(2 rows)
1995
1996drop function fx();
1997create or replace function fx()
1998returns void as $$
1999declare _t1 t; _t2 t;
2000begin
2001  _t1.t := 'ABC'::text;
2002  _t2 := _t1;
2003  raise notice '% %', _t2, _t2.t;
2004end;
2005$$ language plpgsql;
2006select * from plpgsql_check_function('fx()', performance_warnings := true);
2007                                 plpgsql_check_function
2008-----------------------------------------------------------------------------------------
2009 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
2010 Hint: When you fix this issue, please, recheck other functions that uses this function.
2011(2 rows)
2012
2013drop function fx();
2014create or replace function fx(out _tt t[]) as $$
2015declare _t t;
2016begin
2017  _t.t := 'ABC'::text;
2018  _tt[1] := _t;
2019end;
2020$$ language plpgsql;
2021select * from plpgsql_check_function('fx()', performance_warnings := true);
2022                                 plpgsql_check_function
2023-----------------------------------------------------------------------------------------
2024 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
2025 Hint: When you fix this issue, please, recheck other functions that uses this function.
2026(2 rows)
2027
2028drop function fx();
2029drop type t;
2030create or replace function fx()
2031returns int as $$
2032declare x int;
2033begin
2034  perform 1;
2035  return 10;
2036end;
2037$$ language plpgsql;
2038select * from plpgsql_check_function('fx()', performance_warnings := true);
2039                                 plpgsql_check_function
2040-----------------------------------------------------------------------------------------
2041 warning:00000:2:DECLARE:unused variable "x"
2042 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
2043 Hint: When you fix this issue, please, recheck other functions that uses this function.
2044(3 rows)
2045
2046drop function fx();
2047create table t(i int);
2048create function test_t(OUT t) returns t AS $$
2049begin
2050    $1 := null;
2051end;
2052$$ language plpgsql;
2053select test_t();
2054 test_t
2055--------
2056
2057(1 row)
2058
2059select * from test_t();
2060 i
2061---
2062
2063(1 row)
2064
2065select * from plpgsql_check_function('test_t()', performance_warnings := true);
2066                                 plpgsql_check_function
2067-----------------------------------------------------------------------------------------
2068 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
2069 Hint: When you fix this issue, please, recheck other functions that uses this function.
2070(2 rows)
2071
2072create or replace function fx()
2073returns void as $$
2074declare
2075  c cursor for select * from t;
2076  x varchar;
2077begin
2078  open c;
2079  fetch c into x;
2080  close c;
2081end;
2082$$ language plpgsql;
2083select test_t();
2084 test_t
2085--------
2086
2087(1 row)
2088
2089select * from test_t();
2090 i
2091---
2092
2093(1 row)
2094
2095select * from plpgsql_check_function('fx()', performance_warnings := true, fatal_errors := false);
2096                          plpgsql_check_function
2097--------------------------------------------------------------------------
2098 performance:42804:7:FETCH:target type is different type than source type
2099 Detail: cast "integer" value to "character varying" type
2100 Hint: Hidden casting can be a performance issue.
2101 warning extra:00000:4:DECLARE:never read variable "x"
2102(4 rows)
2103
2104drop function fx();
2105create or replace function fx()
2106returns void as $$
2107declare
2108  c cursor for select * from t;
2109  x int;
2110begin
2111  open c;
2112  fetch c into x;
2113  close c;
2114end;
2115$$ language plpgsql;
2116select test_t();
2117 test_t
2118--------
2119
2120(1 row)
2121
2122select * from test_t();
2123 i
2124---
2125
2126(1 row)
2127
2128select * from plpgsql_check_function('fx()', performance_warnings := true, fatal_errors := false);
2129                plpgsql_check_function
2130-------------------------------------------------------
2131 warning extra:00000:4:DECLARE:never read variable "x"
2132(1 row)
2133
2134drop function fx();
2135create or replace function fx()
2136returns void as $$
2137declare
2138  c cursor for select * from t;
2139begin
2140  for r in c loop
2141    raise notice '%', r.a;
2142  end loop;
2143end;
2144$$ language plpgsql;
2145select test_t();
2146 test_t
2147--------
2148
2149(1 row)
2150
2151select * from test_t();
2152 i
2153---
2154
2155(1 row)
2156
2157select * from plpgsql_check_function('fx()', performance_warnings := true, fatal_errors := false);
2158                plpgsql_check_function
2159-------------------------------------------------------
2160 error:42703:6:RAISE:record "r" has no field "a"
2161 Context: SQL statement "SELECT r.a"
2162 warning extra:00000:5:DECLARE:never read variable "r"
2163(3 rows)
2164
2165drop function fx();
2166create or replace function fx()
2167returns void as $$
2168declare
2169  c cursor for select * from t;
2170begin
2171  for r in c loop
2172    raise notice '%', r.i;
2173  end loop;
2174end;
2175$$ language plpgsql;
2176select test_t();
2177 test_t
2178--------
2179
2180(1 row)
2181
2182select * from test_t();
2183 i
2184---
2185
2186(1 row)
2187
2188select * from plpgsql_check_function('fx()', performance_warnings := true, fatal_errors := false);
2189 plpgsql_check_function
2190------------------------
2191(0 rows)
2192
2193drop function fx();
2194create table foo(a int, b int);
2195create or replace function fx()
2196returns void as $$
2197declare f1 int; f2 int;
2198begin
2199  select 1, 2 into f1;
2200  select 1 into f1, f2;
2201  select a b into f1, f2 from foo;
2202end;
2203$$ language plpgsql;
2204select fx();
2205 fx
2206----
2207
2208(1 row)
2209
2210select * from plpgsql_check_function('fx()', performance_warnings := true, fatal_errors := false);
2211                         plpgsql_check_function
2212------------------------------------------------------------------------
2213 warning:00000:4:SQL statement:too many attributes for target variables
2214 Detail: There are less target variables than output columns in query.
2215 Hint: Check target variables in SELECT INTO statement
2216 warning:00000:5:SQL statement:too few attributes for target variables
2217 Detail: There are more target variables than output columns in query.
2218 Hint: Check target variables in SELECT INTO statement.
2219 warning:00000:6:SQL statement:too few attributes for target variables
2220 Detail: There are more target variables than output columns in query.
2221 Hint: Check target variables in SELECT INTO statement.
2222 warning extra:00000:2:DECLARE:never read variable "f1"
2223 warning extra:00000:2:DECLARE:never read variable "f2"
2224(11 rows)
2225
2226drop function fx();
2227drop table foo;
2228create or replace function fx()
2229returns void as $$
2230declare d date;
2231begin
2232  d := (select 1 from pg_class limit 1);
2233  raise notice '%', d;
2234end;
2235$$ language plpgsql;
2236select fx();
2237ERROR:  invalid input syntax for type date: "1"
2238CONTEXT:  PL/pgSQL function fx() line 4 at assignment
2239select * from plpgsql_check_function('fx()', performance_warnings := true, fatal_errors := false);
2240                              plpgsql_check_function
2241----------------------------------------------------------------------------------
2242 warning:42804:4:assignment:target type is different type than source type
2243 Detail: cast "integer" value to "date" type
2244 Hint: There are no possible explicit coercion between those types, possibly bug!
2245 Context: at assignment to variable "d" declared on line 2
2246(4 rows)
2247
2248drop function fx();
2249create table tab_1(i int);
2250create or replace function fx(a int)
2251returns setof int as $$
2252declare
2253  c refcursor;
2254  r record;
2255begin
2256  open c for select i from tab_1 where i = a;
2257  loop
2258    fetch c into r;
2259    if not found then
2260      exit;
2261    end if;
2262    return next r.i;
2263  end loop;
2264end;
2265$$ language plpgsql;
2266select * from plpgsql_check_function('fx(int)', performance_warnings := true, fatal_errors := false);
2267                                 plpgsql_check_function
2268-----------------------------------------------------------------------------------------
2269 performance:00000:routine is marked as VOLATILE, should be STABLE
2270 Hint: When you fix this issue, please, recheck other functions that uses this function.
2271(2 rows)
2272
2273create or replace function fx(a int)
2274returns setof int as $$
2275declare
2276  c refcursor;
2277  r record;
2278begin
2279  open c for select i from tab_1 where i = a;
2280  loop
2281    fetch c into r;
2282    if not found then
2283      exit;
2284    end if;
2285    return next r.x;
2286  end loop;
2287end;
2288$$ language plpgsql;
2289select * from plpgsql_check_function('fx(int)', performance_warnings := true, fatal_errors := false);
2290                                 plpgsql_check_function
2291-----------------------------------------------------------------------------------------
2292 error:42703:12:RETURN NEXT:record "r" has no field "x"
2293 Context: SQL statement "SELECT r.x"
2294 warning extra:00000:4:DECLARE:never read variable "r"
2295 performance:00000:routine is marked as VOLATILE, should be STABLE
2296 Hint: When you fix this issue, please, recheck other functions that uses this function.
2297(5 rows)
2298
2299drop function fx(int);
2300drop table tab_1;
2301create or replace function fxx()
2302returns void as $$
2303begin
2304  rollback;
2305end;
2306$$ language plpgsql;
2307select fxx();
2308ERROR:  invalid transaction termination
2309CONTEXT:  PL/pgSQL function fxx() line 3 at ROLLBACK
2310select * from plpgsql_check_function('fxx()');
2311                 plpgsql_check_function
2312--------------------------------------------------------
2313 error:2D000:3:ROLLBACK:invalid transaction termination
2314(1 row)
2315
2316drop function fxx();
2317create or replace function fxx()
2318returns void as $$
2319declare x int;
2320begin
2321  declare x int;
2322  begin
2323  end;
2324end;
2325$$ language plpgsql;
2326select * from plpgsql_check_function('fxx()');
2327                                  plpgsql_check_function
2328------------------------------------------------------------------------------------------
2329 warning extra:00000:5:statement block:variable "x" shadows a previously defined variable
2330 Hint: SET plpgsql.extra_warnings TO 'shadowed_variables'
2331 warning:00000:2:DECLARE:unused variable "x"
2332 warning:00000:4:DECLARE:unused variable "x"
2333(4 rows)
2334
2335select * from plpgsql_check_function('fxx()', extra_warnings := false);
2336           plpgsql_check_function
2337---------------------------------------------
2338 warning:00000:2:DECLARE:unused variable "x"
2339 warning:00000:4:DECLARE:unused variable "x"
2340(2 rows)
2341
2342drop function fxx();
2343create or replace function fxx(in a int, in b int, out c int, out d int)
2344as $$
2345begin
2346  c := a;
2347end;
2348$$ language plpgsql;
2349select * from plpgsql_check_function('fxx(int, int)');
2350             plpgsql_check_function
2351-------------------------------------------------
2352 warning extra:00000:unused parameter "b"
2353 warning extra:00000:unmodified OUT variable "d"
2354(2 rows)
2355
2356create or replace function fxx(in a int, in b int, out c int, out d int)
2357as $$
2358begin
2359  c := d;
2360end;
2361$$ language plpgsql;
2362select * from plpgsql_check_function('fxx(int, int)');
2363             plpgsql_check_function
2364-------------------------------------------------
2365 warning extra:00000:unused parameter "a"
2366 warning extra:00000:unused parameter "b"
2367 warning extra:00000:unmodified OUT variable "d"
2368(3 rows)
2369
2370create type ct as (a int, b int);
2371create or replace function fxx(a ct, b ct, OUT c ct, OUT d ct)
2372as $$
2373begin
2374  c.a := a.a;
2375end;
2376$$ language plpgsql;
2377select * from plpgsql_check_function('fxx(ct, ct)');
2378                        plpgsql_check_function
2379-----------------------------------------------------------------------
2380 warning extra:00000:unused parameter "b"
2381 warning extra:00000:composite OUT variable "c" is not single argument
2382 warning extra:00000:composite OUT variable "d" is not single argument
2383 warning extra:00000:unmodified OUT variable "d"
2384(4 rows)
2385
2386create or replace function fxx(a ct, b ct, OUT c ct, OUT d ct)
2387as $$
2388begin
2389  c.a := d.a;
2390end;
2391$$ language plpgsql;
2392select * from plpgsql_check_function('fxx(ct, ct)');
2393                        plpgsql_check_function
2394-----------------------------------------------------------------------
2395 warning extra:00000:unused parameter "a"
2396 warning extra:00000:unused parameter "b"
2397 warning extra:00000:composite OUT variable "c" is not single argument
2398 warning extra:00000:composite OUT variable "d" is not single argument
2399 warning extra:00000:unmodified OUT variable "d"
2400(5 rows)
2401
2402create or replace function tx(a int)
2403returns int as $$
2404declare a int; ax int;
2405begin
2406  declare ax int;
2407  begin
2408    ax := 10;
2409  end;
2410  a := 10;
2411  return 20;
2412end;
2413$$ language plpgsql;
2414select * from plpgsql_check_function('tx(int)');
2415                                  plpgsql_check_function
2416-------------------------------------------------------------------------------------------
2417 warning:00000:3:statement block:parameter "a" is overlapped
2418 Detail: Local variable overlap function parameter.
2419 warning extra:00000:5:statement block:variable "ax" shadows a previously defined variable
2420 Hint: SET plpgsql.extra_warnings TO 'shadowed_variables'
2421 warning:00000:2:DECLARE:unused variable "ax"
2422 warning extra:00000:2:DECLARE:never read variable "a"
2423 warning extra:00000:4:DECLARE:never read variable "ax"
2424 warning extra:00000:unused parameter "a"
2425(8 rows)
2426
2427create type xt as (a int, b int, c int);
2428create or replace function fx_xt(out x xt)
2429as $$
2430declare l xt;
2431a int;
2432begin
2433  return;
2434end;
2435$$ language plpgsql;
2436select * from plpgsql_check_function('fx_xt()');
2437             plpgsql_check_function
2438-------------------------------------------------
2439 warning:00000:2:DECLARE:unused variable "l"
2440 warning:00000:3:DECLARE:unused variable "a"
2441 warning extra:00000:unmodified OUT variable "x"
2442(3 rows)
2443
2444drop function fx_xt();
2445create or replace function fx_xt(out x xt)
2446as $$
2447declare l xt;
2448a int;
2449begin
2450  x.c := 1000;
2451  return;
2452end;
2453$$ language plpgsql;
2454select * from plpgsql_check_function('fx_xt()');
2455           plpgsql_check_function
2456---------------------------------------------
2457 warning:00000:2:DECLARE:unused variable "l"
2458 warning:00000:3:DECLARE:unused variable "a"
2459(2 rows)
2460
2461drop function fx_xt();
2462create or replace function fx_xt(out x xt, out y xt)
2463as $$
2464declare c1 xt; c2 xt;
2465begin
2466  return;
2467end;
2468$$ language plpgsql;
2469select * from plpgsql_check_function('fx_xt()');
2470                        plpgsql_check_function
2471-----------------------------------------------------------------------
2472 warning:00000:2:DECLARE:unused variable "c1"
2473 warning:00000:2:DECLARE:unused variable "c2"
2474 warning extra:00000:composite OUT variable "x" is not single argument
2475 warning extra:00000:unmodified OUT variable "x"
2476 warning extra:00000:composite OUT variable "y" is not single argument
2477 warning extra:00000:unmodified OUT variable "y"
2478(6 rows)
2479
2480drop function fx_xt();
2481create or replace function fx_xt(out x xt, out y xt)
2482as $$
2483declare c1 xt; c2 xt;
2484begin
2485  x.a := 100;
2486  y := row(10,20,30);
2487  return;
2488end;
2489$$ language plpgsql;
2490select * from plpgsql_check_function('fx_xt()');
2491                        plpgsql_check_function
2492-----------------------------------------------------------------------
2493 warning:00000:2:DECLARE:unused variable "c1"
2494 warning:00000:2:DECLARE:unused variable "c2"
2495 warning extra:00000:composite OUT variable "x" is not single argument
2496 warning extra:00000:composite OUT variable "y" is not single argument
2497(4 rows)
2498
2499drop function fx_xt();
2500create or replace function fx_xt(out x xt, out z int)
2501as $$
2502begin
2503  return;
2504end;
2505$$ language plpgsql;
2506select * from plpgsql_check_function('fx_xt()');
2507                        plpgsql_check_function
2508-----------------------------------------------------------------------
2509 warning extra:00000:composite OUT variable "x" is not single argument
2510 warning extra:00000:unmodified OUT variable "x"
2511 warning extra:00000:unmodified OUT variable "z"
2512(3 rows)
2513
2514drop function fx_xt();
2515drop type xt;
2516-- missing RETURN
2517create or replace function fx_flow()
2518returns int as $$
2519begin
2520  raise notice 'kuku';
2521end;
2522$$ language plpgsql;
2523select fx_flow();
2524NOTICE:  kuku
2525ERROR:  control reached end of function without RETURN
2526CONTEXT:  PL/pgSQL function fx_flow()
2527select * from plpgsql_check_function('fx_flow()');
2528                   plpgsql_check_function
2529------------------------------------------------------------
2530 error:2F005:control reached end of function without RETURN
2531(1 row)
2532
2533-- ok
2534create or replace function fx_flow()
2535returns int as $$
2536declare a int;
2537begin
2538  if a > 10 then
2539    return a;
2540  end if;
2541  return 10;
2542end;
2543$$ language plpgsql;
2544select * from plpgsql_check_function('fx_flow()');
2545 plpgsql_check_function
2546------------------------
2547(0 rows)
2548
2549-- dead code
2550create or replace function fx_flow()
2551returns int as $$
2552declare a int;
2553begin
2554  if a > 10 then
2555    return a;
2556  else
2557    return a + 1;
2558  end if;
2559  return 10;
2560end;
2561$$ language plpgsql;
2562select * from plpgsql_check_function('fx_flow()');
2563            plpgsql_check_function
2564-----------------------------------------------
2565 warning extra:00000:9:RETURN:unreachable code
2566(1 row)
2567
2568-- missing return
2569create or replace function fx_flow()
2570returns int as $$
2571declare a int;
2572begin
2573  if a > 10 then
2574    return a;
2575  end if;
2576end;
2577$$ language plpgsql;
2578select * from plpgsql_check_function('fx_flow()');
2579                       plpgsql_check_function
2580--------------------------------------------------------------------
2581 warning extra:2F005:control reached end of function without RETURN
2582(1 row)
2583
2584drop function fx_flow();
2585create or replace function fx_flow(in p_param1 integer)
2586returns text as
2587$$
2588declare
2589  z1 text;
2590begin
2591  if p_param1 is not null then
2592    z1 := '1111';
2593    return z1;
2594  else
2595    z1 := '222222';
2596  end if;
2597  return z1;
2598end;
2599$$
2600language plpgsql stable;
2601select * from plpgsql_check_function_tb('fx_flow(integer)');
2602 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
2603------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
2604(0 rows)
2605
2606create or replace function fx_flow(in p_param1 integer)
2607returns text as
2608$$
2609declare
2610  z1 text;
2611begin
2612  if p_param1 is not null then
2613    z1 := '1111';
2614    return z1;
2615  else
2616    z1 := '222222';
2617    raise exception 'stop';
2618  end if;
2619  return z1;
2620end;
2621$$
2622language plpgsql stable;
2623select * from plpgsql_check_function_tb('fx_flow(integer)');
2624 functionid | lineno | statement | sqlstate |     message      | detail | hint |     level     | position | query | context
2625------------+--------+-----------+----------+------------------+--------+------+---------------+----------+-------+---------
2626 fx_flow    |     12 | RETURN    | 00000    | unreachable code |        |      | warning extra |          |       |
2627(1 row)
2628
2629drop function fx_flow();
2630ERROR:  function fx_flow() does not exist
2631drop function fx(int);
2632ERROR:  function fx(integer) does not exist
2633create or replace function fx(x int)
2634returns table(y int)
2635as $$
2636begin
2637  return query select x union select x;
2638end
2639$$ language plpgsql;
2640select * from fx(10);
2641 y
2642----
2643 10
2644(1 row)
2645
2646select * from plpgsql_check_function_tb('fx(int)');
2647 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
2648------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
2649(0 rows)
2650
2651drop function fx(int);
2652create or replace function fx(x int)
2653returns table(y int, z int)
2654as $$
2655begin
2656  return query select x,x+1 union select x, x+1;
2657end
2658$$ language plpgsql;
2659select * from fx(10);
2660 y  | z
2661----+----
2662 10 | 11
2663(1 row)
2664
2665select * from plpgsql_check_function_tb('fx(int)');
2666 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
2667------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
2668(0 rows)
2669
2670drop function fx(int);
2671create table xx(a int);
2672create or replace function fx(x int)
2673returns int as $$
2674declare _a int;
2675begin
2676  begin
2677    select a from xx into strict _a where a = x;
2678    return _a;
2679  exception when others then
2680    null;
2681  end;
2682  return -1;
2683end;
2684$$ language plpgsql;
2685select * from plpgsql_check_function_tb('fx(int)');
2686 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
2687------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
2688(0 rows)
2689
2690drop table xx;
2691create or replace function fx(x int)
2692returns int as $$
2693begin
2694  begin
2695    if (x > 0) then
2696      raise exception 'xxx' using errcode = 'XX888';
2697    else
2698      raise exception 'yyy' using errcode = 'YY888';
2699    end if;
2700    return -1; -- dead code;
2701  end;
2702  return -1;
2703end;
2704$$ language plpgsql;
2705select * from plpgsql_check_function_tb('fx(int)');
2706 functionid | lineno | statement | sqlstate |     message      | detail | hint |     level     | position | query | context
2707------------+--------+-----------+----------+------------------+--------+------+---------------+----------+-------+---------
2708 fx         |      9 | RETURN    | 00000    | unreachable code |        |      | warning extra |          |       |
2709 fx         |     11 | RETURN    | 00000    | unreachable code |        |      | warning extra |          |       |
2710(2 rows)
2711
2712create or replace function fx(x int)
2713returns int as $$
2714begin
2715  begin
2716    if (x > 0) then
2717      raise exception 'xxx' using errcode = 'XX888';
2718    else
2719      raise exception 'yyy' using errcode = 'YY888';
2720    end if;
2721  exception
2722    when sqlstate 'XX888' then
2723      null;
2724    when sqlstate 'YY888' then
2725      null;
2726  end;
2727end; -- missing return;
2728$$ language plpgsql;
2729select * from plpgsql_check_function_tb('fx(int)');
2730 functionid | lineno | statement | sqlstate |                    message                     | detail | hint | level | position | query | context
2731------------+--------+-----------+----------+------------------------------------------------+--------+------+-------+----------+-------+---------
2732 fx         |        |           | 2F005    | control reached end of function without RETURN |        |      | error |          |       |
2733(1 row)
2734
2735create or replace function fx(x int)
2736returns int as $$
2737begin
2738  begin
2739    if (x > 0) then
2740      raise exception 'xxx' using errcode = 'XX888';
2741    else
2742      raise exception 'yyy' using errcode = 'YY888';
2743    end if;
2744  exception
2745    when others then
2746      return 10;
2747  end;
2748end; -- ok now
2749$$ language plpgsql;
2750select * from plpgsql_check_function_tb('fx(int)');
2751 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
2752------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
2753(0 rows)
2754
2755--false alarm reported by Filip Zach
2756create type testtype as (id integer);
2757create or replace function fx()
2758returns testtype as $$
2759begin
2760  return row(1);
2761end;
2762$$ language plpgsql;
2763select * from fx();
2764 id
2765----
2766  1
2767(1 row)
2768
2769select fx();
2770 fx
2771-----
2772 (1)
2773(1 row)
2774
2775select * from plpgsql_check_function('fx()');
2776 plpgsql_check_function
2777------------------------
2778(0 rows)
2779
2780drop function fx();
2781create function out1(OUT f1 int, OUT f2 int)
2782returns setof record as
2783$$
2784begin
2785  for f1, f2 in
2786     execute $q$ select 1, 2 $q$
2787  loop
2788    return next;
2789  end loop;
2790end $$ language plpgsql;
2791select * from plpgsql_check_function('out1()');
2792 plpgsql_check_function
2793------------------------
2794(0 rows)
2795
2796drop function out1();
2797create function out1(OUT f1 int, OUT f2 int)
2798returns setof record as
2799$$
2800begin
2801  for f1, f2 in
2802     select 1, 2
2803  loop
2804    return next;
2805  end loop;
2806end $$ language plpgsql;
2807select * from plpgsql_check_function('out1()');
2808 plpgsql_check_function
2809------------------------
2810(0 rows)
2811
2812drop function out1();
2813-- never read variable detection
2814create function a()
2815returns int as $$
2816declare foo int;
2817begin
2818  foo := 2;
2819  return 1;
2820end;
2821$$ language plpgsql;
2822select * from plpgsql_check_function('a()');
2823                 plpgsql_check_function
2824---------------------------------------------------------
2825 warning extra:00000:2:DECLARE:never read variable "foo"
2826(1 row)
2827
2828drop function a();
2829-- issue #29 false unused variable
2830create or replace function f1(in p_cursor refcursor) returns void as
2831$body$
2832declare
2833  z_offset integer;
2834begin
2835  z_offset := 10;
2836  move absolute z_offset from p_cursor;
2837end;
2838$body$ language 'plpgsql' stable;
2839select * from plpgsql_check_function_tb('f1(refcursor)');
2840 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
2841------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
2842(0 rows)
2843
2844drop function f1(refcursor);
2845-- issue #30 segfault due NULL refname
2846create or replace function test(a varchar)
2847returns void as $$
2848  declare x cursor (_a varchar) for select _a;
2849begin
2850  open x(a);
2851end;
2852$$ language plpgsql;
2853select * from plpgsql_check_function_tb('test(varchar)');
2854 functionid | lineno | statement | sqlstate |         message         | detail | hint |     level     | position | query | context
2855------------+--------+-----------+----------+-------------------------+--------+------+---------------+----------+-------+---------
2856 test       |      2 | DECLARE   | 00000    | never read variable "x" |        |      | warning extra |          |       |
2857(1 row)
2858
2859drop function test(varchar);
2860create or replace function test()
2861returns void as $$
2862declare x numeric;
2863begin
2864  x := NULL;
2865end;
2866$$ language plpgsql;
2867select * from plpgsql_check_function('test()');
2868                plpgsql_check_function
2869-------------------------------------------------------
2870 warning extra:00000:2:DECLARE:never read variable "x"
2871(1 row)
2872
2873drop function test();
2874create table testtable(a int);
2875create or replace function test()
2876returns int as $$
2877declare r testtable;
2878begin
2879  select * into r from testtable;
2880  return r.a;
2881end;
2882$$ language plpgsql;
2883select * from plpgsql_check_function('test()');
2884 plpgsql_check_function
2885------------------------
2886(0 rows)
2887
2888set check_function_bodies to on;
2889drop table testtable;
2890create table testtable(a int, b int);
2891create or replace function test()
2892returns int as $$
2893declare r testtable;
2894begin
2895  select * into r from testtable;
2896  return r.a;
2897end;
2898$$ language plpgsql;
2899alter table testtable drop column b;
2900-- expected false alarm on PostgreSQL 10 and older
2901-- there is not possibility to enforce recompilation
2902-- before checking.
2903select * from plpgsql_check_function('test()');
2904 plpgsql_check_function
2905------------------------
2906(0 rows)
2907
2908drop function test();
2909-- issue #32
2910create table bigtable(id bigint, v varchar);
2911create or replace function test()
2912returns void as $$
2913declare
2914  r record;
2915  _id numeric;
2916begin
2917  select * into r from bigtable where id = _id;
2918  for r in select * from bigtable where _id = id
2919  loop
2920  end loop;
2921  if (exists(select * from bigtable where id = _id)) then
2922  end if;
2923end;
2924$$ language plpgsql;
2925select test();
2926 test
2927------
2928
2929(1 row)
2930
2931-- should to show performance warnings
2932select * from plpgsql_check_function('test()', performance_warnings := true);
2933                                                    plpgsql_check_function
2934-------------------------------------------------------------------------------------------------------------------------------
2935 performance:42804:6:SQL statement:implicit cast of attribute caused by different PLpgSQL variable type in WHERE clause
2936 Query: select *        from bigtable where id = _id
2937 --                                              ^
2938 Detail: An index of some attribute cannot be used, when variable, used in predicate, has not right type like a attribute
2939 Hint: Check a variable type - int versus numeric
2940 performance:42804:7:FOR over SELECT rows:implicit cast of attribute caused by different PLpgSQL variable type in WHERE clause
2941 Query: select * from bigtable where _id = id
2942 --                                  ^
2943 Detail: An index of some attribute cannot be used, when variable, used in predicate, has not right type like a attribute
2944 Hint: Check a variable type - int versus numeric
2945 performance:42804:10:IF:implicit cast of attribute caused by different PLpgSQL variable type in WHERE clause
2946 Query: SELECT (exists(select * from bigtable where id = _id))
2947 --                                                      ^
2948 Detail: An index of some attribute cannot be used, when variable, used in predicate, has not right type like a attribute
2949 Hint: Check a variable type - int versus numeric
2950 warning extra:00000:3:DECLARE:never read variable "r"
2951(16 rows)
2952
2953create or replace function test()
2954returns void as $$
2955declare
2956  r record;
2957  _id bigint;
2958begin
2959  select * into r from bigtable where id = _id;
2960  for r in select * from bigtable where _id = id
2961  loop
2962  end loop;
2963  if (exists(select * from bigtable where id = _id)) then
2964  end if;
2965end;
2966$$ language plpgsql;
2967-- there are not any performance issue now
2968select * from plpgsql_check_function('test()', performance_warnings := true);
2969                plpgsql_check_function
2970-------------------------------------------------------
2971 warning extra:00000:3:DECLARE:never read variable "r"
2972(1 row)
2973
2974-- nextval, currval and setval test
2975create table test_table();
2976create or replace function testseq()
2977returns void as $$
2978begin
2979  perform nextval('test_table');
2980  perform currval('test_table');
2981  perform setval('test_table', 10);
2982  perform setval('test_table', 10, true);
2983end;
2984$$ language plpgsql;
2985-- should to fail
2986select testseq();
2987ERROR:  "test_table" is not a sequence
2988CONTEXT:  SQL statement "SELECT nextval('test_table')"
2989PL/pgSQL function testseq() line 3 at PERFORM
2990select * from plpgsql_check_function('testseq()', fatal_errors := false);
2991                plpgsql_check_function
2992------------------------------------------------------
2993 error:42809:3:PERFORM:"test_table" is not a sequence
2994 Query: SELECT nextval('test_table')
2995 --                    ^
2996 error:42809:4:PERFORM:"test_table" is not a sequence
2997 Query: SELECT currval('test_table')
2998 --                    ^
2999 error:42809:5:PERFORM:"test_table" is not a sequence
3000 Query: SELECT setval('test_table', 10)
3001 --                   ^
3002 error:42809:6:PERFORM:"test_table" is not a sequence
3003 Query: SELECT setval('test_table', 10, true)
3004 --                   ^
3005(12 rows)
3006
3007drop function testseq();
3008drop table test_table;
3009-- tests designed for PostgreSQL 9.2
3010set check_function_bodies to off;
3011create table t1(a int, b int);
3012create function f1()
3013returns void as $$
3014begin
3015  if false then
3016    update t1 set c = 30;
3017  end if;
3018  if false then
3019    raise notice '%', r.c;
3020  end if;
3021end;
3022$$ language plpgsql;
3023select f1();
3024 f1
3025----
3026
3027(1 row)
3028
3029select * from plpgsql_check_function_tb('f1()', fatal_errors := true);
3030 functionid | lineno |   statement   | sqlstate |                  message                   | detail | hint | level | position |        query         | context
3031------------+--------+---------------+----------+--------------------------------------------+--------+------+-------+----------+----------------------+---------
3032 f1         |      4 | SQL statement | 42703    | column "c" of relation "t1" does not exist |        |      | error |       15 | update t1 set c = 30 |
3033(1 row)
3034
3035select * from plpgsql_check_function_tb('f1()', fatal_errors := false);
3036 functionid | lineno |   statement   | sqlstate |                  message                   | detail | hint | level | position |        query         | context
3037------------+--------+---------------+----------+--------------------------------------------+--------+------+-------+----------+----------------------+---------
3038 f1         |      4 | SQL statement | 42703    | column "c" of relation "t1" does not exist |        |      | error |       15 | update t1 set c = 30 |
3039 f1         |      7 | RAISE         | 42P01    | missing FROM-clause entry for table "r"    |        |      | error |        8 | SELECT r.c           |
3040(2 rows)
3041
3042select * from plpgsql_check_function_tb('f1()');
3043 functionid | lineno |   statement   | sqlstate |                  message                   | detail | hint | level | position |        query         | context
3044------------+--------+---------------+----------+--------------------------------------------+--------+------+-------+----------+----------------------+---------
3045 f1         |      4 | SQL statement | 42703    | column "c" of relation "t1" does not exist |        |      | error |       15 | update t1 set c = 30 |
3046(1 row)
3047
3048select f1();
3049 f1
3050----
3051
3052(1 row)
3053
3054drop function f1();
3055create or replace function f1()
3056returns void as $$
3057begin
3058  if false then
3059    raise notice '%', 1, 2;
3060  end if;
3061end;
3062$$ language plpgsql;
3063select f1();
3064ERROR:  too many parameters specified for RAISE
3065CONTEXT:  compilation of PL/pgSQL function "f1" near line 4
3066select * from plpgsql_check_function_tb('f1()');
3067 functionid | lineno | statement | sqlstate |                 message                 | detail | hint | level | position | query |                      context
3068------------+--------+-----------+----------+-----------------------------------------+--------+------+-------+----------+-------+---------------------------------------------------
3069 f1         |        |           | 42601    | too many parameters specified for RAISE |        |      | error |          |       | compilation of PL/pgSQL function "f1" near line 4
3070(1 row)
3071
3072select f1();
3073ERROR:  too many parameters specified for RAISE
3074CONTEXT:  compilation of PL/pgSQL function "f1" near line 4
3075drop function f1();
3076create or replace function f1()
3077returns void as $$
3078begin
3079  if false then
3080    raise notice '% %';
3081  end if;
3082end;
3083$$ language plpgsql;
3084select f1();
3085ERROR:  too few parameters specified for RAISE
3086CONTEXT:  compilation of PL/pgSQL function "f1" near line 4
3087select * from plpgsql_check_function_tb('f1()');
3088 functionid | lineno | statement | sqlstate |                message                 | detail | hint | level | position | query |                      context
3089------------+--------+-----------+----------+----------------------------------------+--------+------+-------+----------+-------+---------------------------------------------------
3090 f1         |        |           | 42601    | too few parameters specified for RAISE |        |      | error |          |       | compilation of PL/pgSQL function "f1" near line 4
3091(1 row)
3092
3093select f1();
3094ERROR:  too few parameters specified for RAISE
3095CONTEXT:  compilation of PL/pgSQL function "f1" near line 4
3096drop function f1();
3097create or replace function ml_trg()
3098returns trigger as $$
3099#option dump
3100declare
3101begin
3102  if TG_OP = 'INSERT' then
3103    if NEW.status_from IS NULL then
3104      begin
3105        -- performance issue only
3106        select status into NEW.status_from
3107           from pa
3108          where pa_id = NEW.pa_id;
3109        -- nonexist target value
3110        select status into NEW.status_from_xxx
3111           from pa
3112          where pa_id = NEW.pa_id;
3113      exception
3114        when DATA_EXCEPTION then
3115          new.status_from := 'DE';
3116      end;
3117    end if;
3118  end if;
3119  if TG_OP = 'DELETE' then return OLD; else return NEW; end if;
3120exception
3121  when OTHERS then
3122    NULL;
3123    if TG_OP = 'DELETE' then return OLD; else return NEW; end if;
3124end;
3125$$ language plpgsql;
3126select * from plpgsql_check_function('ml_trg()', 'ml', performance_warnings := true);
3127                          plpgsql_check_function
3128--------------------------------------------------------------------------
3129 error:42703:13:SQL statement:record "new" has no field "status_from_xxx"
3130(1 row)
3131
3132create or replace function fx2()
3133returns void as $$
3134declare _pa pa;
3135begin
3136  select pa.id into _pa.id from pa limit 1;
3137  select pa.pa_id into _pa.pa_id from pa limit 1;
3138end;
3139$$ language plpgsql;
3140select * from plpgsql_check_function('fx2()', performance_warnings := true);
3141                 plpgsql_check_function
3142---------------------------------------------------------
3143 warning extra:00000:2:DECLARE:never read variable "_pa"
3144(1 row)
3145
3146drop function fx2();
3147create or replace function fx2()
3148returns void as $$
3149declare _pa pa;
3150begin
3151  _pa.id := (select pa.id from pa limit 1);
3152  _pa.pa_id := (select pa.pa_id from pa limit 1);
3153end;
3154$$ language plpgsql;
3155select * from plpgsql_check_function('fx2()', performance_warnings := true);
3156                 plpgsql_check_function
3157---------------------------------------------------------
3158 warning extra:00000:2:DECLARE:never read variable "_pa"
3159(1 row)
3160
3161drop function fx2();
3162create or replace function test_lab()
3163returns void as $$
3164begin
3165    <<outer>>
3166    for a in 1..3 loop
3167    <<sub>>
3168    BEGIN
3169        <<inner>>
3170        for b in 8..9 loop
3171            if a=2 then
3172                continue sub;
3173            end if;
3174            raise notice '% %', a, b;
3175        end loop inner;
3176    END sub;
3177    end loop outer;
3178end;
3179$$ language plpgsql;
3180select test_lab();
3181ERROR:  block label "sub" cannot be used in CONTINUE
3182LINE 10:                 continue sub;
3183                                  ^
3184QUERY:
3185begin
3186    <<outer>>
3187    for a in 1..3 loop
3188    <<sub>>
3189    BEGIN
3190        <<inner>>
3191        for b in 8..9 loop
3192            if a=2 then
3193                continue sub;
3194            end if;
3195            raise notice '% %', a, b;
3196        end loop inner;
3197    END sub;
3198    end loop outer;
3199end;
3200
3201CONTEXT:  compilation of PL/pgSQL function "test_lab" near line 10
3202select * from plpgsql_check_function('test_lab()', performance_warnings := true);
3203                      plpgsql_check_function
3204-------------------------------------------------------------------
3205 error:42601:block label "sub" cannot be used in CONTINUE
3206 Query:
3207        begin
3208            <<outer>>
3209            for a in 1..3 loop
3210            <<sub>>
3211            BEGIN
3212                <<inner>>
3213                for b in 8..9 loop
3214                    if a=2 then
3215                        continue sub;
3216 --                              ^
3217                    end if;
3218                    raise notice '% %', a, b;
3219                end loop inner;
3220            END sub;
3221            end loop outer;
3222        end;
3223
3224 Context: compilation of PL/pgSQL function "test_lab" near line 10
3225(20 rows)
3226
3227create or replace function test_lab()
3228returns void as $$
3229begin
3230  continue;
3231end;
3232$$ language plpgsql;
3233select test_lab();
3234ERROR:  CONTINUE cannot be used outside a loop
3235LINE 3:   continue;
3236          ^
3237QUERY:
3238begin
3239  continue;
3240end;
3241
3242CONTEXT:  compilation of PL/pgSQL function "test_lab" near line 3
3243select * from plpgsql_check_function('test_lab()', performance_warnings := true);
3244                      plpgsql_check_function
3245------------------------------------------------------------------
3246 error:42601:CONTINUE cannot be used outside a loop
3247 Query:
3248        begin
3249          continue;
3250 --       ^
3251        end;
3252
3253 Context: compilation of PL/pgSQL function "test_lab" near line 3
3254(8 rows)
3255
3256create type _exception_type as (
3257  state text,
3258  message text,
3259  detail text);
3260create or replace function f1()
3261returns void as $$
3262declare
3263  _exception record;
3264begin
3265  _exception := NULL::_exception_type;
3266exception when others then
3267  get stacked diagnostics
3268        _exception.state = RETURNED_SQLSTATE,
3269        _exception.message = MESSAGE_TEXT,
3270        _exception.detail = PG_EXCEPTION_DETAIL,
3271        _exception.hint = PG_EXCEPTION_HINT;
3272end;
3273$$ language plpgsql;
3274select f1();
3275 f1
3276----
3277
3278(1 row)
3279
3280select * from plpgsql_check_function('f1()');
3281                            plpgsql_check_function
3282-------------------------------------------------------------------------------
3283 error:42703:7:GET STACKED DIAGNOSTICS:record "_exception" has no field "hint"
3284(1 row)
3285
3286drop function f1();
3287drop type _exception_type;
3288drop table t1;
3289create function myfunc1(a int, b float) returns integer as $$ begin end $$ language plpgsql;
3290create function myfunc2(a int, b float) returns integer as $$ begin end $$ language plpgsql;
3291create function myfunc3(a int, b float) returns integer as $$ begin end $$ language plpgsql;
3292create function myfunc4(a int, b float) returns integer as $$ begin end $$ language plpgsql;
3293create table mytable(a int);
3294create table myview as select * from mytable;
3295create function testfunc(a int, b float)
3296returns void as $$
3297declare x integer;
3298begin
3299  raise notice '%', myfunc1(a, b);
3300  x := myfunc2(a, b);
3301  perform myfunc3(m.a, b) from myview m;
3302  insert into mytable select myfunc4(a, b);
3303end;
3304$$ language plpgsql;
3305select * from plpgsql_check_function('testfunc(int,float)');
3306                plpgsql_check_function
3307-------------------------------------------------------
3308 warning extra:00000:2:DECLARE:never read variable "x"
3309(1 row)
3310
3311select type, schema, name, params from plpgsql_show_dependency_tb('testfunc(int,float)');
3312   type   | schema |  name   |           params
3313----------+--------+---------+----------------------------
3314 FUNCTION | public | myfunc1 | (integer,double precision)
3315 FUNCTION | public | myfunc2 | (integer,double precision)
3316 FUNCTION | public | myfunc3 | (integer,double precision)
3317 FUNCTION | public | myfunc4 | (integer,double precision)
3318 RELATION | public | mytable |
3319 RELATION | public | myview  |
3320(6 rows)
3321
3322drop function testfunc(int, float);
3323drop function myfunc1(int, float);
3324drop function myfunc2(int, float);
3325drop function myfunc3(int, float);
3326drop function myfunc4(int, float);
3327drop table mytable;
3328drop view myview;
3329ERROR:  "myview" is not a view
3330HINT:  Use DROP TABLE to remove a table.
3331-- issue #34
3332create or replace function testcase()
3333returns bool as $$
3334declare x int;
3335begin
3336  set local search_path to public, test;
3337  case x when 1 then return true; else return false; end case;
3338end;
3339$$ language plpgsql;
3340-- should not to raise warning
3341select * from plpgsql_check_function('testcase()');
3342 plpgsql_check_function
3343------------------------
3344(0 rows)
3345
3346drop function testcase();
3347-- Adam's Bartoszewicz example
3348create or replace function public.test12()
3349returns refcursor
3350language plpgsql
3351as $body$
3352declare
3353  rc refcursor;
3354begin
3355  open rc scroll for select pc.* from pg_cast pc;
3356  return rc;
3357end;
3358$body$;
3359-- should not returns false alarm
3360select * from plpgsql_check_function('test12()');
3361 plpgsql_check_function
3362------------------------
3363(0 rows)
3364
3365drop function public.test12();
3366-- should to show performance warning on bad flag
3367create or replace function flag_test1(int)
3368returns int as $$
3369begin
3370  return $1 + 10;
3371end;
3372$$ language plpgsql stable;
3373create table fufu(a int);
3374create or replace function flag_test2(int)
3375returns int as $$
3376begin
3377  return (select * from fufu limit 1);
3378end;
3379$$ language plpgsql volatile;
3380select * from plpgsql_check_function('flag_test1(int)', performance_warnings := true);
3381                                 plpgsql_check_function
3382-----------------------------------------------------------------------------------------
3383 performance:00000:routine is marked as STABLE, should be IMMUTABLE
3384 Hint: When you fix this issue, please, recheck other functions that uses this function.
3385(2 rows)
3386
3387select * from plpgsql_check_function('flag_test2(int)', performance_warnings := true);
3388                                 plpgsql_check_function
3389-----------------------------------------------------------------------------------------
3390 warning extra:00000:unused parameter "$1"
3391 performance:00000:routine is marked as VOLATILE, should be STABLE
3392 Hint: When you fix this issue, please, recheck other functions that uses this function.
3393(3 rows)
3394
3395drop table fufu;
3396drop function flag_test1(int);
3397drop function flag_test2(int);
3398create or replace function rrecord01()
3399returns setof record as $$
3400begin
3401  return query select 1,2;
3402end;
3403$$ language plpgsql;
3404create or replace function rrecord02()
3405returns record as $$
3406begin
3407  return row(10,20,30);
3408end;
3409$$ language plpgsql;
3410-- should not to raise false alarms
3411select * from plpgsql_check_function('rrecord01');
3412 plpgsql_check_function
3413------------------------
3414(0 rows)
3415
3416select * from plpgsql_check_function('rrecord02');
3417 plpgsql_check_function
3418------------------------
3419(0 rows)
3420
3421drop function rrecord01();
3422drop function rrecord02();
3423create or replace function bugfunc01()
3424returns void as $$
3425declare
3426  cvar cursor(a int, b int) for select a + b from generate_series(1,b);
3427begin
3428  for t in cvar(1,3)
3429  loop
3430    raise notice '%', t;
3431  end loop;
3432end;
3433$$ language plpgsql;
3434select bugfunc01();
3435NOTICE:  (4)
3436NOTICE:  (4)
3437NOTICE:  (4)
3438 bugfunc01
3439-----------
3440
3441(1 row)
3442
3443select * from plpgsql_check_function('bugfunc01');
3444 plpgsql_check_function
3445------------------------
3446(0 rows)
3447
3448create or replace function bugfunc02()
3449returns void as $$
3450declare
3451  cvar cursor(a int, b int) for select a + b from generate_series(1,b);
3452begin
3453  open cvar(10,20);
3454  close cvar;
3455end;
3456$$ language plpgsql;
3457select bugfunc02();
3458 bugfunc02
3459-----------
3460
3461(1 row)
3462
3463select * from plpgsql_check_function('bugfunc02');
3464 plpgsql_check_function
3465------------------------
3466(0 rows)
3467
3468create or replace function bugfunc03()
3469returns void as $$
3470declare
3471  cvar cursor(a int, b int) for select a + b from not_exists_table;
3472begin
3473  open cvar(10,20);
3474  close cvar;
3475end;
3476$$ language plpgsql;
3477select bugfunc03();
3478ERROR:  relation "not_exists_table" does not exist
3479LINE 1: select a + b from not_exists_table
3480                          ^
3481QUERY:  select a + b from not_exists_table
3482CONTEXT:  PL/pgSQL function bugfunc03() line 5 at OPEN
3483select * from plpgsql_check_function('bugfunc03');
3484                    plpgsql_check_function
3485---------------------------------------------------------------
3486 error:42P01:5:OPEN:relation "not_exists_table" does not exist
3487 Query: select a + b from not_exists_table
3488 --                       ^
3489(3 rows)
3490
3491create or replace function f1(out cr refcursor)
3492as $$
3493begin
3494end;
3495$$ language plpgsql;
3496-- should to raise warning
3497select * from plpgsql_check_function('f1()');
3498              plpgsql_check_function
3499--------------------------------------------------
3500 warning extra:00000:unmodified OUT variable "cr"
3501(1 row)
3502
3503create or replace function f1(out cr refcursor)
3504as $$
3505begin
3506  open cr for select 1;
3507end;
3508$$ language plpgsql;
3509-- should not to raise warning, see issue #43
3510select * from plpgsql_check_function('f1()');
3511 plpgsql_check_function
3512------------------------
3513(0 rows)
3514
3515drop function f1();
3516create table testt(a int);
3517create or replace function testt_trg_func()
3518returns trigger as $$
3519begin
3520  return new;
3521end;
3522$$ language plpgsql;
3523create trigger testt_trg
3524  before insert or update
3525  on testt
3526  for each row execute procedure testt_trg_func();
3527create or replace function maintaince_function()
3528returns void as $$
3529begin
3530
3531  alter table testt disable trigger testt_trg;
3532  alter table testt enable trigger testt_trg;
3533
3534end;
3535$$ language plpgsql;
3536-- should not to crash
3537select * from plpgsql_check_function_tb('maintaince_function()', 0, true, true, true);
3538 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
3539------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
3540(0 rows)
3541
3542drop function maintaince_function();
3543drop trigger testt_trg on testt;
3544drop function testt_trg_func();
3545drop table testt;
3546create or replace function test_crash()
3547returns void as $$
3548declare
3549  ec int default buggyfunc(10);
3550begin
3551  select * into ec from buggytab;
3552end;
3553$$ language plpgsql;
3554-- should not to crash
3555select * from plpgsql_check_function('test_crash', fatal_errors := false);
3556                                         plpgsql_check_function
3557---------------------------------------------------------------------------------------------------------
3558 error:42883:4:statement block:function buggyfunc(integer) does not exist
3559 Query: SELECT buggyfunc(10)
3560 --            ^
3561 Hint: No function matches the given name and argument types. You might need to add explicit type casts.
3562 Context: during statement block local variable "ec" initialization on line 3
3563 error:42P01:5:SQL statement:relation "buggytab" does not exist
3564 Query: select *         from buggytab
3565 --                           ^
3566 warning extra:00000:3:DECLARE:never read variable "ec"
3567(9 rows)
3568
3569select * from plpgsql_check_function('test_crash', fatal_errors := true);
3570                                         plpgsql_check_function
3571---------------------------------------------------------------------------------------------------------
3572 error:42883:4:statement block:function buggyfunc(integer) does not exist
3573 Query: SELECT buggyfunc(10)
3574 --            ^
3575 Hint: No function matches the given name and argument types. You might need to add explicit type casts.
3576 Context: during statement block local variable "ec" initialization on line 3
3577(5 rows)
3578
3579drop function test_crash();
3580-- fix false alarm reported by Piotr Stepniewski
3581create or replace function public.fx()
3582returns void
3583language plpgsql
3584as $function$
3585begin
3586  raise exception 'xxx';
3587end;
3588$function$;
3589-- show raise nothing
3590select * from plpgsql_check_function('fx()');
3591 plpgsql_check_function
3592------------------------
3593(0 rows)
3594
3595create table errtab(
3596  message text,
3597  code character(5)
3598);
3599create or replace function public.fx()
3600returns void
3601language plpgsql
3602as $function$
3603declare
3604  var errtab%rowtype;
3605begin
3606  raise exception using message = var.message, errcode = var.code;
3607end;
3608$function$;
3609-- should not to crash
3610select * from plpgsql_check_function('fx()');
3611 plpgsql_check_function
3612------------------------
3613(0 rows)
3614
3615create or replace function public.fx()
3616returns void
3617language plpgsql
3618as $function$
3619declare
3620  var errtab%rowtype;
3621begin
3622  raise exception using message = var.message, errcode = var.code, hint = var.hint;
3623end;
3624$function$;
3625-- should not to crash
3626select * from plpgsql_check_function('fx()');
3627                plpgsql_check_function
3628------------------------------------------------------
3629 error:42703:5:RAISE:record "var" has no field "hint"
3630 Context: SQL statement "SELECT var.hint"
3631(2 rows)
3632
3633drop function fx();
3634create or replace function foo_format(a text, b text)
3635returns void as $$
3636declare s text;
3637begin
3638  s := format('%s'); -- should to raise error
3639  s := format('%s %10s', a, b); -- should be ok
3640  s := format('%s %s', a, b, a); -- should to raise warning
3641  s := format('%s %d', a, b); -- should to raise error
3642  raise notice '%', s;
3643end;
3644$$ language plpgsql;
3645select * from plpgsql_check_function('foo_format', fatal_errors := false);
3646                      plpgsql_check_function
3647-------------------------------------------------------------------
3648 error:22023:4:assignment:too few arguments for format()
3649 Query: SELECT format('%s')
3650 --                   ^
3651 Context: at assignment to variable "s" declared on line 2
3652 warning:00000:6:assignment:unused parameters of function "format"
3653 Query: SELECT format('%s %s', a, b, a)
3654 --                   ^
3655 Context: at assignment to variable "s" declared on line 2
3656 error:22023:7:assignment:unrecognized format() type specifier "d"
3657 Query: SELECT format('%s %d', a, b)
3658 --                   ^
3659 Context: at assignment to variable "s" declared on line 2
3660(12 rows)
3661
3662drop function foo_format(text, text);
3663create or replace function dyn_sql_1()
3664returns void as $$
3665declare
3666  v varchar;
3667  n int;
3668begin
3669  execute 'select ' || n; -- ok
3670  execute 'select ' || quote_literal(v); -- ok
3671  execute 'select ' || v; -- vulnerable
3672  execute format('select * from %I', v); -- ok
3673  execute format('select * from %s', v); -- vulnerable
3674  execute 'select $1' using v; -- ok
3675  execute 'select 1'; -- ok
3676  execute 'select 1' using v; -- warning
3677  execute 'select $1'; -- error
3678end;
3679$$ language plpgsql;
3680select * from plpgsql_check_function('dyn_sql_1', security_warnings := true, fatal_errors := false);
3681                                  plpgsql_check_function
3682------------------------------------------------------------------------------------------
3683 security:00000:8:EXECUTE:text type variable is not sanitized
3684 Query: SELECT 'select ' || v
3685 --                         ^
3686 Detail: The EXECUTE expression is SQL injection vulnerable.
3687 Hint: Use quote_ident, quote_literal or format function to secure variable.
3688 security:00000:10:EXECUTE:text type variable is not sanitized
3689 Query: SELECT format('select * from %s', v)
3690 --                                       ^
3691 Detail: The EXECUTE expression is SQL injection vulnerable.
3692 Hint: Use quote_ident, quote_literal or format function to secure variable.
3693 warning:00000:13:EXECUTE:values passed to EXECUTE statement by USING clause was not used
3694 error:42P02:14:EXECUTE:there is no parameter $1
3695 Query: select $1
3696 --            ^
3697(14 rows)
3698
3699drop function dyn_sql_1();
3700create type tp as (a int, b int);
3701create or replace function dyn_sql_2()
3702returns void as $$
3703declare
3704  r tp;
3705  result int;
3706begin
3707  select 10 a, 20 b into r;
3708  raise notice '%', r.a;
3709  execute 'select $1.a + $1.b' into result using r;
3710  execute 'select $1.c' into result using r; -- error
3711  raise notice '%', result;
3712end;
3713$$ language plpgsql;
3714select * from plpgsql_check_function('dyn_sql_2', security_warnings := true);
3715                   plpgsql_check_function
3716------------------------------------------------------------
3717 error:42703:9:EXECUTE:column "c" not found in data type tp
3718 Query: select $1.c
3719 --            ^
3720(3 rows)
3721
3722drop function dyn_sql_2();
3723drop type tp;
3724/*
3725 * Should not to work
3726 *
3727 * note: plpgsql doesn't support passing some necessary details for record
3728 * type. The parser setup for dynamic SQL column doesn't use ref hooks, and
3729 * then it cannot to pass TupleDesc info to query anyway.
3730 */
3731create or replace function dyn_sql_2()
3732returns void as $$
3733declare
3734  r record;
3735  result int;
3736begin
3737  select 10 a, 20 b into r;
3738  raise notice '%', r.a;
3739  execute 'select $1.a + $1.b' into result using r;
3740  raise notice '%', result;
3741end;
3742$$ language plpgsql;
3743select dyn_sql_2(); --should to fail
3744NOTICE:  10
3745ERROR:  could not identify column "a" in record data type
3746LINE 1: select $1.a + $1.b
3747               ^
3748QUERY:  select $1.a + $1.b
3749CONTEXT:  PL/pgSQL function dyn_sql_2() line 8 at EXECUTE
3750select * from plpgsql_check_function('dyn_sql_2', security_warnings := true);
3751                         plpgsql_check_function
3752-------------------------------------------------------------------------
3753 error:42703:8:EXECUTE:could not identify column "a" in record data type
3754 Query: select $1.a + $1.b
3755 --            ^
3756(3 rows)
3757
3758drop function dyn_sql_2();
3759create or replace function dyn_sql_3()
3760returns void as $$
3761declare r int;
3762begin
3763  execute 'select $1' into r using 1;
3764  raise notice '%', r;
3765end
3766$$ language plpgsql;
3767select dyn_sql_3();
3768NOTICE:  1
3769 dyn_sql_3
3770-----------
3771
3772(1 row)
3773
3774-- should be ok
3775select * from plpgsql_check_function('dyn_sql_3');
3776 plpgsql_check_function
3777------------------------
3778(0 rows)
3779
3780create or replace function dyn_sql_3()
3781returns void as $$
3782declare r record;
3783begin
3784  execute 'select $1 as a, $2 as b' into r using 1, 2;
3785  raise notice '% %', r.a, r.b;
3786end
3787$$ language plpgsql;
3788select dyn_sql_3();
3789NOTICE:  1 2
3790 dyn_sql_3
3791-----------
3792
3793(1 row)
3794
3795-- should be ok
3796select * from plpgsql_check_function('dyn_sql_3');
3797 plpgsql_check_function
3798------------------------
3799(0 rows)
3800
3801create or replace function dyn_sql_3()
3802returns void as $$
3803declare r record;
3804begin
3805  execute 'create table foo(a int)' into r using 1, 2;
3806  raise notice '% %', r.a, r.b;
3807end
3808$$ language plpgsql;
3809-- raise a error
3810select * from plpgsql_check_function('dyn_sql_3');
3811                                 plpgsql_check_function
3812-----------------------------------------------------------------------------------------
3813 warning:00000:4:EXECUTE:values passed to EXECUTE statement by USING clause was not used
3814 error:XX000:4:EXECUTE:expression does not return data
3815(2 rows)
3816
3817create or replace function dyn_sql_3()
3818returns void as $$
3819declare r1 int; r2 int;
3820begin
3821  execute 'select 1' into r1, r2 using 1, 2;
3822  raise notice '% %', r1, r2;
3823end
3824$$ language plpgsql;
3825-- raise a error
3826select * from plpgsql_check_function('dyn_sql_3');
3827                                 plpgsql_check_function
3828-----------------------------------------------------------------------------------------
3829 warning:00000:4:EXECUTE:values passed to EXECUTE statement by USING clause was not used
3830 warning:00000:4:EXECUTE:too few attributes for target variables
3831 Detail: There are more target variables than output columns in query.
3832 Hint: Check target variables in SELECT INTO statement.
3833(4 rows)
3834
3835drop function dyn_sql_3();
3836create or replace function dyn_sql_3()
3837returns void as $$
3838declare r record;
3839begin
3840  for r in execute 'select 1 as a, 2 as b'
3841  loop
3842    raise notice '%', r.a;
3843  end loop;
3844end
3845$$ language plpgsql;
3846-- should be ok
3847select * from plpgsql_check_function('dyn_sql_3');
3848 plpgsql_check_function
3849------------------------
3850(0 rows)
3851
3852drop function dyn_sql_3();
3853create or replace function dyn_sql_3()
3854returns void as $$
3855declare r record;
3856begin
3857  for r in execute 'select 1 as a, 2 as b'
3858  loop
3859    raise notice '%', r.c;
3860  end loop;
3861end
3862$$ language plpgsql;
3863-- should be error
3864select * from plpgsql_check_function('dyn_sql_3');
3865             plpgsql_check_function
3866-------------------------------------------------
3867 error:42703:6:RAISE:record "r" has no field "c"
3868 Context: SQL statement "SELECT r.c"
3869(2 rows)
3870
3871drop function dyn_sql_3();
3872create or replace function dyn_sql_3()
3873returns void as $$
3874declare
3875  r record;
3876  v text = 'select 10 a, 20 b't;
3877begin
3878  select 10 a, 20 b into r;
3879  for r in execute v
3880  loop
3881    raise notice '%', r.a;
3882  end loop;
3883end
3884$$ language plpgsql;
3885-- should be warning
3886select * from plpgsql_check_function('dyn_sql_3');
3887                                plpgsql_check_function
3888---------------------------------------------------------------------------------------
3889 warning:00000:7:FOR over EXECUTE statement:cannot determinate a result of dynamic SQL
3890 Detail: There is a risk of related false alarms.
3891 Hint: Don't use dynamic SQL and record type together, when you would check function.
3892(3 rows)
3893
3894drop function dyn_sql_3();
3895create or replace function dyn_sql_4()
3896returns table(ax int, bx int) as $$
3897begin
3898  return query execute 'select 10, 20';
3899  return;
3900end;
3901$$ language plpgsql;
3902-- should be ok
3903select * from plpgsql_check_function('dyn_sql_4()');
3904 plpgsql_check_function
3905------------------------
3906(0 rows)
3907
3908create or replace function dyn_sql_4()
3909returns table(ax int, bx int) as $$
3910begin
3911  return query execute 'select 10, 20, 30';
3912  return;
3913end;
3914$$ language plpgsql;
3915select * from dyn_sql_4();
3916ERROR:  structure of query does not match function result type
3917DETAIL:  Number of returned columns (3) does not match expected column count (2).
3918CONTEXT:  PL/pgSQL function dyn_sql_4() line 3 at RETURN QUERY
3919-- should be error
3920select * from plpgsql_check_function('dyn_sql_4()');
3921                              plpgsql_check_function
3922-----------------------------------------------------------------------------------
3923 error:42804:3:RETURN QUERY:structure of query does not match function result type
3924 Detail: Number of returned columns (3) does not match expected column count (2).
3925(2 rows)
3926
3927drop function dyn_sql_4();
3928create or replace function test_bug(text)
3929returns regproc as $$
3930begin
3931  return $1::regproc;
3932  exception when undefined_function or invalid_name then
3933    raise;
3934end;
3935$$ language plpgsql;
3936-- should not raise a exception
3937select * from plpgsql_check_function('test_bug');
3938 plpgsql_check_function
3939------------------------
3940(0 rows)
3941
3942create or replace function test_bug(text)
3943returns regproc as $$
3944begin
3945  return $1::regproc;
3946  exception when undefined_function or invalid_name then
3947    raise notice '%', $1; -- bug
3948end;
3949$$ language plpgsql;
3950select test_bug('kuku'); -- should to fail
3951NOTICE:  kuku
3952ERROR:  control reached end of function without RETURN
3953CONTEXT:  PL/pgSQL function test_bug(text)
3954select * from plpgsql_check_function('test_bug');
3955                       plpgsql_check_function
3956--------------------------------------------------------------------
3957 warning extra:2F005:control reached end of function without RETURN
3958(1 row)
3959
3960drop function test_bug(text);
3961create or replace function test_bug(text)
3962returns regproc as $$
3963begin
3964  return $1::regproc;
3965  exception when undefined_function or invalid_name then
3966    raise notice '%', $1;
3967    return NULL;
3968end;
3969$$ language plpgsql;
3970select test_bug('kuku'); -- should be ok
3971NOTICE:  kuku
3972 test_bug
3973----------
3974
3975(1 row)
3976
3977select * from plpgsql_check_function('test_bug');
3978 plpgsql_check_function
3979------------------------
3980(0 rows)
3981
3982drop function test_bug(text);
3983create or replace function foo(a text, b text)
3984returns void as $$
3985begin
3986  -- unsecure
3987  execute 'select ' || a;
3988  a := quote_literal(a); -- is safe now
3989  execute 'select ' || a;
3990  a := a || b; -- it is unsecure again
3991  execute 'select ' || a;
3992end;
3993$$ language plpgsql;
3994\sf+ foo(text, text)
3995        CREATE OR REPLACE FUNCTION public.foo(a text, b text)
3996         RETURNS void
3997         LANGUAGE plpgsql
39981       AS $function$
39992       begin
40003         -- unsecure
40014         execute 'select ' || a;
40025         a := quote_literal(a); -- is safe now
40036         execute 'select ' || a;
40047         a := a || b; -- it is unsecure again
40058         execute 'select ' || a;
40069       end;
400710      $function$
4008-- should to raise two warnings
4009select * from plpgsql_check_function('foo', security_warnings := true);
4010                           plpgsql_check_function
4011-----------------------------------------------------------------------------
4012 security:00000:4:EXECUTE:text type variable is not sanitized
4013 Query: SELECT 'select ' || a
4014 --                         ^
4015 Detail: The EXECUTE expression is SQL injection vulnerable.
4016 Hint: Use quote_ident, quote_literal or format function to secure variable.
4017 security:00000:8:EXECUTE:text type variable is not sanitized
4018 Query: SELECT 'select ' || a
4019 --                         ^
4020 Detail: The EXECUTE expression is SQL injection vulnerable.
4021 Hint: Use quote_ident, quote_literal or format function to secure variable.
4022(10 rows)
4023
4024drop function foo(text, text);
4025-- test of very long function inside profiler
4026create or replace function longfx(int)
4027returns int as $$
4028declare
4029  s int default 0;
4030  j int default 0;
4031  r record;
4032begin
4033  begin
4034    while j < 10
4035    loop
4036      for i in 1..1
4037      loop
4038        for r in select * from generate_series(1,1)
4039        loop
4040          s := s + 1;
4041          s := s + 1;
4042          s := s + 1;
4043          s := s + 1;
4044          s := s + 1;
4045          s := s + 1;
4046          s := s + 1;
4047          s := s + 1;
4048          s := s + 1;
4049          s := s + 1;
4050          s := s + 1;
4051          s := s + 1;
4052          s := s + 1;
4053          s := s + 1;
4054          s := s + 1;
4055          s := s + 1;
4056          s := s + 1;
4057          s := s + 1;
4058          s := s + 1;
4059          s := s + 1;
4060          s := s + 1;
4061          s := s + 1;
4062          s := s + 1;
4063          s := s + 1;
4064          s := s + 1;
4065          s := s + 1;
4066          s := s + 1;
4067          s := s + 1;
4068          s := s + 1;
4069          s := s + 1;
4070          s := s + 1;
4071          s := s + 1;
4072          s := s + 1;
4073          s := s + 1;
4074          s := s + 1;
4075          s := s + 1;
4076          s := s + 1;
4077          s := s + 1;
4078          s := s + 1;
4079          s := s + 1;
4080          s := s + 1;
4081          s := s + 1;
4082          s := s + 1;
4083          s := s + 1;
4084          s := s + 1;
4085          s := s + 1;
4086          s := s + 1;
4087          s := s + 1;
4088          s := s + 1;
4089          s := s + 1;
4090          s := s + 1;
4091          s := s + 1;
4092          s := s + 1;
4093          s := s + 1;
4094          s := s + 1;
4095          s := s + 1;
4096          s := s + 1;
4097          s := s + 1;
4098          s := s + 1;
4099          s := s + 1;
4100          s := s + 1;
4101          s := s + 1;
4102          s := s + 1;
4103          s := s + 1;
4104          s := s + 1;
4105          s := s + 1;
4106          s := s + 1;
4107          s := s + 1;
4108          s := s + 1;
4109          s := s + 1;
4110          s := s + 1;
4111          s := s + 1;
4112          s := s + 1;
4113          s := s + 1;
4114          s := s + 1;
4115          s := s + 1;
4116          s := s + 1;
4117          s := s + 1;
4118          s := s + 1;
4119          s := s + 1;
4120          s := s + 1;
4121          s := s + 1;
4122          s := s + 1;
4123          s := s + 1;
4124          s := s + 1;
4125          s := s + 1;
4126          s := s + 1;
4127          s := s + 1;
4128          s := s + 1;
4129          s := s + 1;
4130          s := s + 1;
4131          s := s + 1;
4132          s := s + 1;
4133          s := s + 1;
4134          s := s + 1;
4135          s := s + 1;
4136          s := s + 1;
4137          s := s + 1;
4138          s := s + 1;
4139          s := s + 1;
4140          s := s + 1;
4141          s := s + 1;
4142          s := s + 1;
4143          s := s + 1;
4144          s := s + 1;
4145          s := s + 1;
4146          s := s + 1;
4147          s := s + 1;
4148          s := s + 1;
4149          s := s + 1;
4150          s := s + 1;
4151          s := s + 1;
4152          s := s + 1;
4153          s := s + 1;
4154          s := s + 1;
4155          s := s + 1;
4156          s := s + 1;
4157          s := s + 1;
4158          s := s + 1;
4159          s := s + 1;
4160          s := s + 1;
4161          s := s + 1;
4162          s := s + 1;
4163          s := s + 1;
4164          s := s + 1;
4165          s := s + 1;
4166          s := s + 1;
4167          s := s + 1;
4168          s := s + 1;
4169          s := s + 1;
4170          s := s + 1;
4171          s := s + 1;
4172          s := s + 1;
4173          s := s + 1;
4174          s := s + 1;
4175          s := s + 1;
4176          s := s + 1;
4177          s := s + 1;
4178          s := s + 1;
4179          s := s + 1;
4180          s := s + 1;
4181          s := s + 1;
4182          s := s + 1;
4183          s := s + 1;
4184          s := s + 1;
4185          s := s + 1;
4186          s := s + 1;
4187          s := s + 1;
4188          s := s + 1;
4189          s := s + 1;
4190          s := s + 1;
4191          s := s + 1;
4192          s := s + 1;
4193          s := s + 1;
4194          s := s + 1;
4195          s := s + 1;
4196          s := s + 1;
4197          s := s + 1;
4198          s := s + 1;
4199          s := s + 1;
4200          s := s + 1;
4201          s := s + 1;
4202          s := s + 1;
4203          s := s + 1;
4204          s := s + 1;
4205          s := s + 1;
4206          s := s + 1;
4207          s := s + 1;
4208          s := s + 1;
4209          s := s + 1;
4210          s := s + 1;
4211          s := s + 1;
4212          s := s + 1;
4213          s := s + 1;
4214          s := s + 1;
4215          s := s + 1;
4216          s := s + 1;
4217          s := s + 1;
4218          s := s + 1;
4219          s := s + 1;
4220          s := s + 1;
4221          s := s + 1;
4222          s := s + 1;
4223          s := s + 1;
4224          s := s + 1;
4225          s := s + 1;
4226          s := s + 1;
4227          s := s + 1;
4228          s := s + 1;
4229          s := s + 1;
4230          s := s + 1;
4231          s := s + 1;
4232          s := s + 1;
4233          s := s + 1;
4234          s := s + 1;
4235          s := s + 1;
4236          s := s + 1;
4237          s := s + 1;
4238          s := s + 1;
4239          s := s + 1;
4240          s := s + 1;
4241          s := s + 1;
4242          s := s + 1;
4243          s := s + 1;
4244          s := s + 1;
4245          s := s + 1;
4246          s := s + 1;
4247          s := s + 1;
4248          s := s + 1;
4249          s := s + 1;
4250          s := s + 1;
4251          s := s + 1;
4252          s := s + 1;
4253          s := s + 1;
4254          s := s + 1;
4255          s := s + 1;
4256          s := s + 1;
4257          s := s + 1;
4258          s := s + 1;
4259          s := s + 1;
4260          s := s + 1;
4261          s := s + 1;
4262          s := s + 1;
4263          s := s + 1;
4264          s := s + 1;
4265          s := s + 1;
4266          s := s + 1;
4267          s := s + 1;
4268          s := s + 1;
4269          s := s + 1;
4270          s := s + 1;
4271          s := s + 1;
4272          s := s + 1;
4273          s := s + 1;
4274          s := s + 1;
4275          s := s + 1;
4276          s := s + 1;
4277          s := s + 1;
4278          s := s + 1;
4279          s := s + 1;
4280          s := s + 1;
4281          s := s + 1;
4282          s := s + 1;
4283          s := s + 1;
4284          s := s + 1;
4285          s := s + 1;
4286          s := s + 1;
4287          s := s + 1;
4288          s := s + 1;
4289          s := s + 1;
4290          s := s + 1;
4291          s := s + 1;
4292          s := s + 1;
4293          s := s + 1;
4294          s := s + 1;
4295          s := s + 1;
4296          s := s + 1;
4297          s := s + 1;
4298          s := s + 1;
4299          s := s + 1;
4300          s := s + 1;
4301          s := s + 1;
4302          s := s + 1;
4303          s := s + 1;
4304          s := s + 1;
4305          s := s + 1;
4306          s := s + 1;
4307          s := s + 1;
4308          s := s + 1;
4309          s := s + 1;
4310          s := s + 1;
4311          s := s + 1;
4312          s := s + 1;
4313          s := s + 1;
4314          s := s + 1;
4315          s := s + 1;
4316          s := s + 1;
4317          s := s + 1;
4318          s := s + 1;
4319          s := s + 1;
4320          s := s + 1;
4321          s := s + 1;
4322          s := s + 1;
4323          s := s + 1;
4324          s := s + 1;
4325          s := s + 1;
4326          s := s + 1;
4327          s := s + 1;
4328          s := s + 1;
4329          s := s + 1;
4330          s := s + 1;
4331          s := s + 1;
4332          s := s + 1;
4333          s := s + 1;
4334          s := s + 1;
4335          s := s + 1;
4336          s := s + 1;
4337          s := s + 1;
4338          s := s + 1;
4339          s := s + 1;
4340          s := s + 1;
4341          s := s + 1;
4342          s := s + 1;
4343          s := s + 1;
4344          s := s + 1;
4345          s := s + 1;
4346          s := s + 1;
4347          s := s + 1;
4348          s := s + 1;
4349          s := s + 1;
4350          s := s + 1;
4351          s := s + 1;
4352          s := s + 1;
4353          s := s + 1;
4354          s := s + 1;
4355          s := s + 1;
4356          s := s + 1;
4357          s := s + 1;
4358          s := s + 1;
4359          s := s + 1;
4360          s := s + 1;
4361          s := s + 1;
4362          s := s + 1;
4363          s := s + 1;
4364          s := s + 1;
4365          s := s + 1;
4366          s := s + 1;
4367          s := s + 1;
4368          s := s + 1;
4369          s := s + 1;
4370          s := s + 1;
4371          s := s + 1;
4372          s := s + 1;
4373          s := s + 1;
4374          s := s + 1;
4375          s := s + 1;
4376          s := s + 1;
4377          s := s + 1;
4378          s := s + 1;
4379          s := s + 1;
4380          s := s + 1;
4381          s := s + 1;
4382          s := s + 1;
4383          s := s + 1;
4384          s := s + 1;
4385          s := s + 1;
4386          s := s + 1;
4387          s := s + 1;
4388          s := s + 1;
4389          s := s + 1;
4390          s := s + 1;
4391          s := s + 1;
4392          s := s + 1;
4393          s := s + 1;
4394          s := s + 1;
4395          s := s + 1;
4396          s := s + 1;
4397          s := s + 1;
4398          s := s + 1;
4399          s := s + 1;
4400          s := s + 1;
4401          s := s + 1;
4402          s := s + 1;
4403          s := s + 1;
4404          s := s + 1;
4405          s := s + 1;
4406          s := s + 1;
4407          s := s + 1;
4408          s := s + 1;
4409          s := s + 1;
4410          s := s + 1;
4411          s := s + 1;
4412          s := s + 1;
4413          s := s + 1;
4414          s := s + 1;
4415          s := s + 1;
4416          s := s + 1;
4417          s := s + 1;
4418          s := s + 1;
4419          s := s + 1;
4420          s := s + 1;
4421          s := s + 1;
4422          s := s + 1;
4423          s := s + 1;
4424          s := s + 1;
4425          s := s + 1;
4426          s := s + 1;
4427          s := s + 1;
4428          s := s + 1;
4429          s := s + 1;
4430          s := s + 1;
4431          s := s + 1;
4432          s := s + 1;
4433          s := s + 1;
4434          s := s + 1;
4435          s := s + 1;
4436          s := s + 1;
4437          s := s + 1;
4438          s := s + 1;
4439          s := s + 1;
4440          s := s + 1;
4441          s := s + 1;
4442          s := s + 1;
4443          s := s + 1;
4444          s := s + 1;
4445          s := s + 1;
4446          s := s + 1;
4447          s := s + 1;
4448          s := s + 1;
4449          s := s + 1;
4450          s := s + 1;
4451          s := s + 1;
4452          s := s + 1;
4453          s := s + 1;
4454          s := s + 1;
4455          s := s + 1;
4456          s := s + 1;
4457          s := s + 1;
4458          s := s + 1;
4459          s := s + 1;
4460          s := s + 1;
4461          s := s + 1;
4462          s := s + 1;
4463          s := s + 1;
4464          s := s + 1;
4465          s := s + 1;
4466          s := s + 1;
4467          s := s + 1;
4468          s := s + 1;
4469          s := s + 1;
4470          s := s + 1;
4471          s := s + 1;
4472          s := s + 1;
4473          s := s + 1;
4474          s := s + 1;
4475          s := s + 1;
4476          s := s + 1;
4477          s := s + 1;
4478          s := s + 1;
4479          s := s + 1;
4480          s := s + 1;
4481          s := s + 1;
4482          s := s + 1;
4483          s := s + 1;
4484          s := s + 1;
4485          s := s + 1;
4486          s := s + 1;
4487          s := s + 1;
4488          s := s + 1;
4489          s := s + 1;
4490          s := s + 1;
4491          s := s + 1;
4492          s := s + 1;
4493          s := s + 1;
4494          s := s + 1;
4495          s := s + 1;
4496          s := s + 1;
4497          s := s + 1;
4498          s := s + 1;
4499          s := s + 1;
4500          s := s + 1;
4501          s := s + 1;
4502          s := s + 1;
4503          s := s + 1;
4504          s := s + 1;
4505          s := s + 1;
4506          s := s + 1;
4507          s := s + 1;
4508          s := s + 1;
4509          s := s + 1;
4510          s := s + 1;
4511          s := s + 1;
4512          s := s + 1;
4513          s := s + 1;
4514          s := s + 1;
4515          s := s + 1;
4516          s := s + 1;
4517          s := s + 1;
4518          s := s + 1;
4519          s := s + 1;
4520          s := s + 1;
4521          s := s + 1;
4522          s := s + 1;
4523          s := s + 1;
4524          s := s + 1;
4525          s := s + 1;
4526          s := s + 1;
4527          s := s + 1;
4528          s := s + 1;
4529          s := s + 1;
4530          s := s + 1;
4531          s := s + 1;
4532          s := s + 1;
4533          s := s + 1;
4534          s := s + 1;
4535          s := s + 1;
4536          s := s + 1;
4537          s := s + 1;
4538          s := s + 1;
4539          s := s + 1;
4540          s := s + 1;
4541          s := s + 1;
4542          s := s + 1;
4543          s := s + 1;
4544          s := s + 1;
4545          s := s + 1;
4546          s := s + 1;
4547          s := s + 1;
4548          s := s + 1;
4549          s := s + 1;
4550          s := s + 1;
4551          s := s + 1;
4552          s := s + 1;
4553          s := s + 1;
4554          s := s + 1;
4555          s := s + 1;
4556          s := s + 1;
4557          s := s + 1;
4558          s := s + 1;
4559          s := s + 1;
4560          s := s + 1;
4561          s := s + 1;
4562          s := s + 1;
4563          s := s + 1;
4564          s := s + 1;
4565          s := s + 1;
4566          s := s + 1;
4567          s := s + 1;
4568          s := s + 1;
4569          s := s + 1;
4570          s := s + 1;
4571          s := s + 1;
4572          s := s + 1;
4573          s := s + 1;
4574          s := s + 1;
4575          s := s + 1;
4576          s := s + 1;
4577          s := s + 1;
4578          s := s + 1;
4579          s := s + 1;
4580          s := s + 1;
4581          s := s + 1;
4582          s := s + 1;
4583          s := s + 1;
4584          s := s + 1;
4585          s := s + 1;
4586          s := s + 1;
4587          s := s + 1;
4588          s := s + 1;
4589          s := s + 1;
4590          s := s + 1;
4591          s := s + 1;
4592          s := s + 1;
4593          s := s + 1;
4594          s := s + 1;
4595          s := s + 1;
4596          s := s + 1;
4597          s := s + 1;
4598          s := s + 1;
4599          s := s + 1;
4600          s := s + 1;
4601          s := s + 1;
4602          s := s + 1;
4603          s := s + 1;
4604          s := s + 1;
4605          s := s + 1;
4606          s := s + 1;
4607          s := s + 1;
4608          s := s + 1;
4609          s := s + 1;
4610          s := s + 1;
4611          s := s + 1;
4612          s := s + 1;
4613          s := s + 1;
4614          s := s + 1;
4615          s := s + 1;
4616          s := s + 1;
4617          s := s + 1;
4618          s := s + 1;
4619          s := s + 1;
4620          s := s + 1;
4621          s := s + 1;
4622          s := s + 1;
4623          s := s + 1;
4624          s := s + 1;
4625          s := s + 1;
4626          s := s + 1;
4627          s := s + 1;
4628          s := s + 1;
4629          s := s + 1;
4630          s := s + 1;
4631          s := s + 1;
4632          s := s + 1;
4633          s := s + 1;
4634          s := s + 1;
4635          s := s + 1;
4636          s := s + 1;
4637          s := s + 1;
4638          s := s + 1;
4639          s := s + 1;
4640          s := s + 1;
4641          s := s + 1;
4642          s := s + 1;
4643          s := s + 1;
4644          s := s + 1;
4645          s := s + 1;
4646          s := s + 1;
4647          s := s + 1;
4648          s := s + 1;
4649          s := s + 1;
4650          s := s + 1;
4651          s := s + 1;
4652          s := s + 1;
4653          s := s + 1;
4654          s := s + 1;
4655          s := s + 1;
4656          s := s + 1;
4657          s := s + 1;
4658          s := s + 1;
4659          s := s + 1;
4660          s := s + 1;
4661          s := s + 1;
4662          s := s + 1;
4663          s := s + 1;
4664          s := s + 1;
4665          s := s + 1;
4666          s := s + 1;
4667          s := s + 1;
4668          s := s + 1;
4669          s := s + 1;
4670          s := s + 1;
4671          s := s + 1;
4672          s := s + 1;
4673          s := s + 1;
4674          s := s + 1;
4675          s := s + 1;
4676          s := s + 1;
4677          s := s + 1;
4678          s := s + 1;
4679          s := s + 1;
4680          s := s + 1;
4681          s := s + 1;
4682          s := s + 1;
4683          s := s + 1;
4684          s := s + 1;
4685          s := s + 1;
4686          s := s + 1;
4687          s := s + 1;
4688          s := s + 1;
4689          s := s + 1;
4690          s := s + 1;
4691          s := s + 1;
4692          s := s + 1;
4693          s := s + 1;
4694          s := s + 1;
4695          s := s + 1;
4696          s := s + 1;
4697          s := s + 1;
4698          s := s + 1;
4699          s := s + 1;
4700          s := s + 1;
4701          s := s + 1;
4702          s := s + 1;
4703          s := s + 1;
4704          s := s + 1;
4705          s := s + 1;
4706          s := s + 1;
4707          s := s + 1;
4708          s := s + 1;
4709          s := s + 1;
4710          s := s + 1;
4711          s := s + 1;
4712          s := s + 1;
4713          s := s + 1;
4714          s := s + 1;
4715          s := s + 1;
4716          s := s + 1;
4717          s := s + 1;
4718          s := s + 1;
4719          s := s + 1;
4720          s := s + 1;
4721          s := s + 1;
4722          s := s + 1;
4723          s := s + 1;
4724          s := s + 1;
4725          s := s + 1;
4726          s := s + 1;
4727          s := s + 1;
4728          s := s + 1;
4729          s := s + 1;
4730          s := s + 1;
4731          s := s + 1;
4732          s := s + 1;
4733          s := s + 1;
4734          s := s + 1;
4735          s := s + 1;
4736          s := s + 1;
4737          s := s + 1;
4738          s := s + 1;
4739          s := s + 1;
4740          s := s + 1;
4741          s := s + 1;
4742          s := s + 1;
4743          s := s + 1;
4744          s := s + 1;
4745          s := s + 1;
4746          s := s + 1;
4747          s := s + 1;
4748          s := s + 1;
4749          s := s + 1;
4750          s := s + 1;
4751          s := s + 1;
4752          s := s + 1;
4753          s := s + 1;
4754          s := s + 1;
4755          s := s + 1;
4756          s := s + 1;
4757          s := s + 1;
4758          s := s + 1;
4759          s := s + 1;
4760          s := s + 1;
4761          s := s + 1;
4762          s := s + 1;
4763          s := s + 1;
4764          s := s + 1;
4765          s := s + 1;
4766          s := s + 1;
4767          s := s + 1;
4768          s := s + 1;
4769          s := s + 1;
4770          s := s + 1;
4771          s := s + 1;
4772          s := s + 1;
4773          s := s + 1;
4774          s := s + 1;
4775          s := s + 1;
4776          s := s + 1;
4777          s := s + 1;
4778          s := s + 1;
4779          s := s + 1;
4780          s := s + 1;
4781          s := s + 1;
4782          s := s + 1;
4783          s := s + 1;
4784          s := s + 1;
4785          s := s + 1;
4786          s := s + 1;
4787          s := s + 1;
4788          s := s + 1;
4789          s := s + 1;
4790          s := s + 1;
4791          s := s + 1;
4792          s := s + 1;
4793          s := s + 1;
4794          s := s + 1;
4795          s := s + 1;
4796          s := s + 1;
4797          s := s + 1;
4798          s := s + 1;
4799          s := s + 1;
4800          s := s + 1;
4801          s := s + 1;
4802          s := s + 1;
4803          s := s + 1;
4804          s := s + 1;
4805          s := s + 1;
4806          s := s + 1;
4807          s := s + 1;
4808          s := s + 1;
4809          s := s + 1;
4810          s := s + 1;
4811          s := s + 1;
4812          s := s + 1;
4813          s := s + 1;
4814          s := s + 1;
4815          s := s + 1;
4816          s := s + 1;
4817          s := s + 1;
4818          s := s + 1;
4819          s := s + 1;
4820          s := s + 1;
4821          s := s + 1;
4822          s := s + 1;
4823          s := s + 1;
4824          s := s + 1;
4825          s := s + 1;
4826          s := s + 1;
4827          s := s + 1;
4828          s := s + 1;
4829          s := s + 1;
4830          s := s + 1;
4831          s := s + 1;
4832          s := s + 1;
4833          s := s + 1;
4834          s := s + 1;
4835          s := s + 1;
4836          s := s + 1;
4837          s := s + 1;
4838          s := s + 1;
4839          s := s + 1;
4840          s := s + 1;
4841          s := s + 1;
4842          s := s + 1;
4843          s := s + 1;
4844          s := s + 1;
4845          s := s + 1;
4846          s := s + 1;
4847          s := s + 1;
4848          s := s + 1;
4849          s := s + 1;
4850          s := s + 1;
4851          s := s + 1;
4852          s := s + 1;
4853          s := s + 1;
4854          s := s + 1;
4855          s := s + 1;
4856          s := s + 1;
4857          s := s + 1;
4858          s := s + 1;
4859          s := s + 1;
4860          s := s + 1;
4861          s := s + 1;
4862          s := s + 1;
4863          s := s + 1;
4864          s := s + 1;
4865          s := s + 1;
4866          s := s + 1;
4867          s := s + 1;
4868          s := s + 1;
4869          s := s + 1;
4870          s := s + 1;
4871          s := s + 1;
4872          s := s + 1;
4873          s := s + 1;
4874          s := s + 1;
4875          s := s + 1;
4876          s := s + 1;
4877          s := s + 1;
4878          s := s + 1;
4879          s := s + 1;
4880          s := s + 1;
4881          s := s + 1;
4882          s := s + 1;
4883          s := s + 1;
4884          s := s + 1;
4885          s := s + 1;
4886          s := s + 1;
4887          s := s + 1;
4888          s := s + 1;
4889          s := s + 1;
4890          s := s + 1;
4891          s := s + 1;
4892          s := s + 1;
4893          s := s + 1;
4894          s := s + 1;
4895          s := s + 1;
4896          s := s + 1;
4897          s := s + 1;
4898          s := s + 1;
4899          s := s + 1;
4900          s := s + 1;
4901          s := s + 1;
4902          s := s + 1;
4903          s := s + 1;
4904          s := s + 1;
4905          s := s + 1;
4906          s := s + 1;
4907          s := s + 1;
4908          s := s + 1;
4909          s := s + 1;
4910          s := s + 1;
4911          s := s + 1;
4912          s := s + 1;
4913          s := s + 1;
4914          s := s + 1;
4915          s := s + 1;
4916          s := s + 1;
4917          s := s + 1;
4918          s := s + 1;
4919          s := s + 1;
4920          s := s + 1;
4921          s := s + 1;
4922          s := s + 1;
4923          s := s + 1;
4924          s := s + 1;
4925          s := s + 1;
4926          s := s + 1;
4927          s := s + 1;
4928          s := s + 1;
4929          s := s + 1;
4930          s := s + 1;
4931          s := s + 1;
4932          s := s + 1;
4933          s := s + 1;
4934          s := s + 1;
4935          s := s + 1;
4936          s := s + 1;
4937          s := s + 1;
4938          s := s + 1;
4939          s := s + 1;
4940          s := s + 1;
4941          s := s + 1;
4942          s := s + 1;
4943          s := s + 1;
4944          s := s + 1;
4945          s := s + 1;
4946          s := s + 1;
4947          s := s + 1;
4948          s := s + 1;
4949          s := s + 1;
4950          s := s + 1;
4951          s := s + 1;
4952          s := s + 1;
4953          s := s + 1;
4954          s := s + 1;
4955          s := s + 1;
4956          s := s + 1;
4957          s := s + 1;
4958          s := s + 1;
4959          s := s + 1;
4960          s := s + 1;
4961          s := s + 1;
4962          s := s + 1;
4963          s := s + 1;
4964          s := s + 1;
4965          s := s + 1;
4966          s := s + 1;
4967          s := s + 1;
4968          s := s + 1;
4969          s := s + 1;
4970          s := s + 1;
4971          s := s + 1;
4972          s := s + 1;
4973          s := s + 1;
4974          s := s + 1;
4975          s := s + 1;
4976          s := s + 1;
4977          s := s + 1;
4978          s := s + 1;
4979          s := s + 1;
4980          s := s + 1;
4981          s := s + 1;
4982          s := s + 1;
4983          s := s + 1;
4984          s := s + 1;
4985          s := s + 1;
4986          s := s + 1;
4987          s := s + 1;
4988          s := s + 1;
4989          s := s + 1;
4990          s := s + 1;
4991          s := s + 1;
4992          s := s + 1;
4993          s := s + 1;
4994          s := s + 1;
4995          s := s + 1;
4996          s := s + 1;
4997          s := s + 1;
4998          s := s + 1;
4999          s := s + 1;
5000          s := s + 1;
5001          s := s + 1;
5002          s := s + 1;
5003          s := s + 1;
5004          s := s + 1;
5005          s := s + 1;
5006          s := s + 1;
5007          s := s + 1;
5008          s := s + 1;
5009          s := s + 1;
5010          s := s + 1;
5011          s := s + 1;
5012          s := s + 1;
5013          s := s + 1;
5014          s := s + 1;
5015          s := s + 1;
5016          s := s + 1;
5017          s := s + 1;
5018          s := s + 1;
5019          s := s + 1;
5020          s := s + 1;
5021          s := s + 1;
5022          s := s + 1;
5023          s := s + 1;
5024          s := s + 1;
5025          s := s + 1;
5026          s := s + 1;
5027          s := s + 1;
5028          s := s + 1;
5029          s := s + 1;
5030          s := s + 1;
5031          s := s + 1;
5032          s := s + 1;
5033          s := s + 1;
5034          s := s + 1;
5035          s := s + 1;
5036          s := s + 1;
5037          s := s + 1;
5038          s := s + 1;
5039          s := s + 1;
5040          s := s + 1;
5041          s := s + 1;
5042          s := s + 1;
5043          s := s + 1;
5044          s := s + 1;
5045          s := s + 1;
5046          s := s + 1;
5047          s := s + 1;
5048          s := s + 1;
5049          s := s + 1;
5050          s := s + 1;
5051          s := s + 1;
5052          s := s + 1;
5053          s := s + 1;
5054          s := s + 1;
5055          s := s + 1;
5056          s := s + 1;
5057          s := s + 1;
5058          s := s + 1;
5059          s := s + 1;
5060          s := s + 1;
5061          s := s + 1;
5062          s := s + 1;
5063          s := s + 1;
5064        end loop;
5065      end loop;
5066      j := j + 1;
5067    end loop;
5068  exception when others then
5069    raise 'reraised exception %', sqlerrm;
5070  end;
5071  return $1;
5072end;
5073$$ language plpgsql;
5074select lineno, stmt_lineno, exec_stmts, source from plpgsql_profiler_function_tb('longfx');
5075 lineno | stmt_lineno | exec_stmts |                       source
5076--------+-------------+------------+-----------------------------------------------------
5077      1 |             |            |
5078      2 |             |            | declare
5079      3 |             |            |   s int default 0;
5080      4 |             |            |   j int default 0;
5081      5 |             |            |   r record;
5082      6 |             |            | begin
5083      7 |             |            |   begin
5084      8 |             |            |     while j < 10
5085      9 |             |            |     loop
5086     10 |             |            |       for i in 1..1
5087     11 |             |            |       loop
5088     12 |             |            |         for r in select * from generate_series(1,1)
5089     13 |             |            |         loop
5090     14 |             |            |           s := s + 1;
5091     15 |             |            |           s := s + 1;
5092     16 |             |            |           s := s + 1;
5093     17 |             |            |           s := s + 1;
5094     18 |             |            |           s := s + 1;
5095     19 |             |            |           s := s + 1;
5096     20 |             |            |           s := s + 1;
5097     21 |             |            |           s := s + 1;
5098     22 |             |            |           s := s + 1;
5099     23 |             |            |           s := s + 1;
5100     24 |             |            |           s := s + 1;
5101     25 |             |            |           s := s + 1;
5102     26 |             |            |           s := s + 1;
5103     27 |             |            |           s := s + 1;
5104     28 |             |            |           s := s + 1;
5105     29 |             |            |           s := s + 1;
5106     30 |             |            |           s := s + 1;
5107     31 |             |            |           s := s + 1;
5108     32 |             |            |           s := s + 1;
5109     33 |             |            |           s := s + 1;
5110     34 |             |            |           s := s + 1;
5111     35 |             |            |           s := s + 1;
5112     36 |             |            |           s := s + 1;
5113     37 |             |            |           s := s + 1;
5114     38 |             |            |           s := s + 1;
5115     39 |             |            |           s := s + 1;
5116     40 |             |            |           s := s + 1;
5117     41 |             |            |           s := s + 1;
5118     42 |             |            |           s := s + 1;
5119     43 |             |            |           s := s + 1;
5120     44 |             |            |           s := s + 1;
5121     45 |             |            |           s := s + 1;
5122     46 |             |            |           s := s + 1;
5123     47 |             |            |           s := s + 1;
5124     48 |             |            |           s := s + 1;
5125     49 |             |            |           s := s + 1;
5126     50 |             |            |           s := s + 1;
5127     51 |             |            |           s := s + 1;
5128     52 |             |            |           s := s + 1;
5129     53 |             |            |           s := s + 1;
5130     54 |             |            |           s := s + 1;
5131     55 |             |            |           s := s + 1;
5132     56 |             |            |           s := s + 1;
5133     57 |             |            |           s := s + 1;
5134     58 |             |            |           s := s + 1;
5135     59 |             |            |           s := s + 1;
5136     60 |             |            |           s := s + 1;
5137     61 |             |            |           s := s + 1;
5138     62 |             |            |           s := s + 1;
5139     63 |             |            |           s := s + 1;
5140     64 |             |            |           s := s + 1;
5141     65 |             |            |           s := s + 1;
5142     66 |             |            |           s := s + 1;
5143     67 |             |            |           s := s + 1;
5144     68 |             |            |           s := s + 1;
5145     69 |             |            |           s := s + 1;
5146     70 |             |            |           s := s + 1;
5147     71 |             |            |           s := s + 1;
5148     72 |             |            |           s := s + 1;
5149     73 |             |            |           s := s + 1;
5150     74 |             |            |           s := s + 1;
5151     75 |             |            |           s := s + 1;
5152     76 |             |            |           s := s + 1;
5153     77 |             |            |           s := s + 1;
5154     78 |             |            |           s := s + 1;
5155     79 |             |            |           s := s + 1;
5156     80 |             |            |           s := s + 1;
5157     81 |             |            |           s := s + 1;
5158     82 |             |            |           s := s + 1;
5159     83 |             |            |           s := s + 1;
5160     84 |             |            |           s := s + 1;
5161     85 |             |            |           s := s + 1;
5162     86 |             |            |           s := s + 1;
5163     87 |             |            |           s := s + 1;
5164     88 |             |            |           s := s + 1;
5165     89 |             |            |           s := s + 1;
5166     90 |             |            |           s := s + 1;
5167     91 |             |            |           s := s + 1;
5168     92 |             |            |           s := s + 1;
5169     93 |             |            |           s := s + 1;
5170     94 |             |            |           s := s + 1;
5171     95 |             |            |           s := s + 1;
5172     96 |             |            |           s := s + 1;
5173     97 |             |            |           s := s + 1;
5174     98 |             |            |           s := s + 1;
5175     99 |             |            |           s := s + 1;
5176    100 |             |            |           s := s + 1;
5177    101 |             |            |           s := s + 1;
5178    102 |             |            |           s := s + 1;
5179    103 |             |            |           s := s + 1;
5180    104 |             |            |           s := s + 1;
5181    105 |             |            |           s := s + 1;
5182    106 |             |            |           s := s + 1;
5183    107 |             |            |           s := s + 1;
5184    108 |             |            |           s := s + 1;
5185    109 |             |            |           s := s + 1;
5186    110 |             |            |           s := s + 1;
5187    111 |             |            |           s := s + 1;
5188    112 |             |            |           s := s + 1;
5189    113 |             |            |           s := s + 1;
5190    114 |             |            |           s := s + 1;
5191    115 |             |            |           s := s + 1;
5192    116 |             |            |           s := s + 1;
5193    117 |             |            |           s := s + 1;
5194    118 |             |            |           s := s + 1;
5195    119 |             |            |           s := s + 1;
5196    120 |             |            |           s := s + 1;
5197    121 |             |            |           s := s + 1;
5198    122 |             |            |           s := s + 1;
5199    123 |             |            |           s := s + 1;
5200    124 |             |            |           s := s + 1;
5201    125 |             |            |           s := s + 1;
5202    126 |             |            |           s := s + 1;
5203    127 |             |            |           s := s + 1;
5204    128 |             |            |           s := s + 1;
5205    129 |             |            |           s := s + 1;
5206    130 |             |            |           s := s + 1;
5207    131 |             |            |           s := s + 1;
5208    132 |             |            |           s := s + 1;
5209    133 |             |            |           s := s + 1;
5210    134 |             |            |           s := s + 1;
5211    135 |             |            |           s := s + 1;
5212    136 |             |            |           s := s + 1;
5213    137 |             |            |           s := s + 1;
5214    138 |             |            |           s := s + 1;
5215    139 |             |            |           s := s + 1;
5216    140 |             |            |           s := s + 1;
5217    141 |             |            |           s := s + 1;
5218    142 |             |            |           s := s + 1;
5219    143 |             |            |           s := s + 1;
5220    144 |             |            |           s := s + 1;
5221    145 |             |            |           s := s + 1;
5222    146 |             |            |           s := s + 1;
5223    147 |             |            |           s := s + 1;
5224    148 |             |            |           s := s + 1;
5225    149 |             |            |           s := s + 1;
5226    150 |             |            |           s := s + 1;
5227    151 |             |            |           s := s + 1;
5228    152 |             |            |           s := s + 1;
5229    153 |             |            |           s := s + 1;
5230    154 |             |            |           s := s + 1;
5231    155 |             |            |           s := s + 1;
5232    156 |             |            |           s := s + 1;
5233    157 |             |            |           s := s + 1;
5234    158 |             |            |           s := s + 1;
5235    159 |             |            |           s := s + 1;
5236    160 |             |            |           s := s + 1;
5237    161 |             |            |           s := s + 1;
5238    162 |             |            |           s := s + 1;
5239    163 |             |            |           s := s + 1;
5240    164 |             |            |           s := s + 1;
5241    165 |             |            |           s := s + 1;
5242    166 |             |            |           s := s + 1;
5243    167 |             |            |           s := s + 1;
5244    168 |             |            |           s := s + 1;
5245    169 |             |            |           s := s + 1;
5246    170 |             |            |           s := s + 1;
5247    171 |             |            |           s := s + 1;
5248    172 |             |            |           s := s + 1;
5249    173 |             |            |           s := s + 1;
5250    174 |             |            |           s := s + 1;
5251    175 |             |            |           s := s + 1;
5252    176 |             |            |           s := s + 1;
5253    177 |             |            |           s := s + 1;
5254    178 |             |            |           s := s + 1;
5255    179 |             |            |           s := s + 1;
5256    180 |             |            |           s := s + 1;
5257    181 |             |            |           s := s + 1;
5258    182 |             |            |           s := s + 1;
5259    183 |             |            |           s := s + 1;
5260    184 |             |            |           s := s + 1;
5261    185 |             |            |           s := s + 1;
5262    186 |             |            |           s := s + 1;
5263    187 |             |            |           s := s + 1;
5264    188 |             |            |           s := s + 1;
5265    189 |             |            |           s := s + 1;
5266    190 |             |            |           s := s + 1;
5267    191 |             |            |           s := s + 1;
5268    192 |             |            |           s := s + 1;
5269    193 |             |            |           s := s + 1;
5270    194 |             |            |           s := s + 1;
5271    195 |             |            |           s := s + 1;
5272    196 |             |            |           s := s + 1;
5273    197 |             |            |           s := s + 1;
5274    198 |             |            |           s := s + 1;
5275    199 |             |            |           s := s + 1;
5276    200 |             |            |           s := s + 1;
5277    201 |             |            |           s := s + 1;
5278    202 |             |            |           s := s + 1;
5279    203 |             |            |           s := s + 1;
5280    204 |             |            |           s := s + 1;
5281    205 |             |            |           s := s + 1;
5282    206 |             |            |           s := s + 1;
5283    207 |             |            |           s := s + 1;
5284    208 |             |            |           s := s + 1;
5285    209 |             |            |           s := s + 1;
5286    210 |             |            |           s := s + 1;
5287    211 |             |            |           s := s + 1;
5288    212 |             |            |           s := s + 1;
5289    213 |             |            |           s := s + 1;
5290    214 |             |            |           s := s + 1;
5291    215 |             |            |           s := s + 1;
5292    216 |             |            |           s := s + 1;
5293    217 |             |            |           s := s + 1;
5294    218 |             |            |           s := s + 1;
5295    219 |             |            |           s := s + 1;
5296    220 |             |            |           s := s + 1;
5297    221 |             |            |           s := s + 1;
5298    222 |             |            |           s := s + 1;
5299    223 |             |            |           s := s + 1;
5300    224 |             |            |           s := s + 1;
5301    225 |             |            |           s := s + 1;
5302    226 |             |            |           s := s + 1;
5303    227 |             |            |           s := s + 1;
5304    228 |             |            |           s := s + 1;
5305    229 |             |            |           s := s + 1;
5306    230 |             |            |           s := s + 1;
5307    231 |             |            |           s := s + 1;
5308    232 |             |            |           s := s + 1;
5309    233 |             |            |           s := s + 1;
5310    234 |             |            |           s := s + 1;
5311    235 |             |            |           s := s + 1;
5312    236 |             |            |           s := s + 1;
5313    237 |             |            |           s := s + 1;
5314    238 |             |            |           s := s + 1;
5315    239 |             |            |           s := s + 1;
5316    240 |             |            |           s := s + 1;
5317    241 |             |            |           s := s + 1;
5318    242 |             |            |           s := s + 1;
5319    243 |             |            |           s := s + 1;
5320    244 |             |            |           s := s + 1;
5321    245 |             |            |           s := s + 1;
5322    246 |             |            |           s := s + 1;
5323    247 |             |            |           s := s + 1;
5324    248 |             |            |           s := s + 1;
5325    249 |             |            |           s := s + 1;
5326    250 |             |            |           s := s + 1;
5327    251 |             |            |           s := s + 1;
5328    252 |             |            |           s := s + 1;
5329    253 |             |            |           s := s + 1;
5330    254 |             |            |           s := s + 1;
5331    255 |             |            |           s := s + 1;
5332    256 |             |            |           s := s + 1;
5333    257 |             |            |           s := s + 1;
5334    258 |             |            |           s := s + 1;
5335    259 |             |            |           s := s + 1;
5336    260 |             |            |           s := s + 1;
5337    261 |             |            |           s := s + 1;
5338    262 |             |            |           s := s + 1;
5339    263 |             |            |           s := s + 1;
5340    264 |             |            |           s := s + 1;
5341    265 |             |            |           s := s + 1;
5342    266 |             |            |           s := s + 1;
5343    267 |             |            |           s := s + 1;
5344    268 |             |            |           s := s + 1;
5345    269 |             |            |           s := s + 1;
5346    270 |             |            |           s := s + 1;
5347    271 |             |            |           s := s + 1;
5348    272 |             |            |           s := s + 1;
5349    273 |             |            |           s := s + 1;
5350    274 |             |            |           s := s + 1;
5351    275 |             |            |           s := s + 1;
5352    276 |             |            |           s := s + 1;
5353    277 |             |            |           s := s + 1;
5354    278 |             |            |           s := s + 1;
5355    279 |             |            |           s := s + 1;
5356    280 |             |            |           s := s + 1;
5357    281 |             |            |           s := s + 1;
5358    282 |             |            |           s := s + 1;
5359    283 |             |            |           s := s + 1;
5360    284 |             |            |           s := s + 1;
5361    285 |             |            |           s := s + 1;
5362    286 |             |            |           s := s + 1;
5363    287 |             |            |           s := s + 1;
5364    288 |             |            |           s := s + 1;
5365    289 |             |            |           s := s + 1;
5366    290 |             |            |           s := s + 1;
5367    291 |             |            |           s := s + 1;
5368    292 |             |            |           s := s + 1;
5369    293 |             |            |           s := s + 1;
5370    294 |             |            |           s := s + 1;
5371    295 |             |            |           s := s + 1;
5372    296 |             |            |           s := s + 1;
5373    297 |             |            |           s := s + 1;
5374    298 |             |            |           s := s + 1;
5375    299 |             |            |           s := s + 1;
5376    300 |             |            |           s := s + 1;
5377    301 |             |            |           s := s + 1;
5378    302 |             |            |           s := s + 1;
5379    303 |             |            |           s := s + 1;
5380    304 |             |            |           s := s + 1;
5381    305 |             |            |           s := s + 1;
5382    306 |             |            |           s := s + 1;
5383    307 |             |            |           s := s + 1;
5384    308 |             |            |           s := s + 1;
5385    309 |             |            |           s := s + 1;
5386    310 |             |            |           s := s + 1;
5387    311 |             |            |           s := s + 1;
5388    312 |             |            |           s := s + 1;
5389    313 |             |            |           s := s + 1;
5390    314 |             |            |           s := s + 1;
5391    315 |             |            |           s := s + 1;
5392    316 |             |            |           s := s + 1;
5393    317 |             |            |           s := s + 1;
5394    318 |             |            |           s := s + 1;
5395    319 |             |            |           s := s + 1;
5396    320 |             |            |           s := s + 1;
5397    321 |             |            |           s := s + 1;
5398    322 |             |            |           s := s + 1;
5399    323 |             |            |           s := s + 1;
5400    324 |             |            |           s := s + 1;
5401    325 |             |            |           s := s + 1;
5402    326 |             |            |           s := s + 1;
5403    327 |             |            |           s := s + 1;
5404    328 |             |            |           s := s + 1;
5405    329 |             |            |           s := s + 1;
5406    330 |             |            |           s := s + 1;
5407    331 |             |            |           s := s + 1;
5408    332 |             |            |           s := s + 1;
5409    333 |             |            |           s := s + 1;
5410    334 |             |            |           s := s + 1;
5411    335 |             |            |           s := s + 1;
5412    336 |             |            |           s := s + 1;
5413    337 |             |            |           s := s + 1;
5414    338 |             |            |           s := s + 1;
5415    339 |             |            |           s := s + 1;
5416    340 |             |            |           s := s + 1;
5417    341 |             |            |           s := s + 1;
5418    342 |             |            |           s := s + 1;
5419    343 |             |            |           s := s + 1;
5420    344 |             |            |           s := s + 1;
5421    345 |             |            |           s := s + 1;
5422    346 |             |            |           s := s + 1;
5423    347 |             |            |           s := s + 1;
5424    348 |             |            |           s := s + 1;
5425    349 |             |            |           s := s + 1;
5426    350 |             |            |           s := s + 1;
5427    351 |             |            |           s := s + 1;
5428    352 |             |            |           s := s + 1;
5429    353 |             |            |           s := s + 1;
5430    354 |             |            |           s := s + 1;
5431    355 |             |            |           s := s + 1;
5432    356 |             |            |           s := s + 1;
5433    357 |             |            |           s := s + 1;
5434    358 |             |            |           s := s + 1;
5435    359 |             |            |           s := s + 1;
5436    360 |             |            |           s := s + 1;
5437    361 |             |            |           s := s + 1;
5438    362 |             |            |           s := s + 1;
5439    363 |             |            |           s := s + 1;
5440    364 |             |            |           s := s + 1;
5441    365 |             |            |           s := s + 1;
5442    366 |             |            |           s := s + 1;
5443    367 |             |            |           s := s + 1;
5444    368 |             |            |           s := s + 1;
5445    369 |             |            |           s := s + 1;
5446    370 |             |            |           s := s + 1;
5447    371 |             |            |           s := s + 1;
5448    372 |             |            |           s := s + 1;
5449    373 |             |            |           s := s + 1;
5450    374 |             |            |           s := s + 1;
5451    375 |             |            |           s := s + 1;
5452    376 |             |            |           s := s + 1;
5453    377 |             |            |           s := s + 1;
5454    378 |             |            |           s := s + 1;
5455    379 |             |            |           s := s + 1;
5456    380 |             |            |           s := s + 1;
5457    381 |             |            |           s := s + 1;
5458    382 |             |            |           s := s + 1;
5459    383 |             |            |           s := s + 1;
5460    384 |             |            |           s := s + 1;
5461    385 |             |            |           s := s + 1;
5462    386 |             |            |           s := s + 1;
5463    387 |             |            |           s := s + 1;
5464    388 |             |            |           s := s + 1;
5465    389 |             |            |           s := s + 1;
5466    390 |             |            |           s := s + 1;
5467    391 |             |            |           s := s + 1;
5468    392 |             |            |           s := s + 1;
5469    393 |             |            |           s := s + 1;
5470    394 |             |            |           s := s + 1;
5471    395 |             |            |           s := s + 1;
5472    396 |             |            |           s := s + 1;
5473    397 |             |            |           s := s + 1;
5474    398 |             |            |           s := s + 1;
5475    399 |             |            |           s := s + 1;
5476    400 |             |            |           s := s + 1;
5477    401 |             |            |           s := s + 1;
5478    402 |             |            |           s := s + 1;
5479    403 |             |            |           s := s + 1;
5480    404 |             |            |           s := s + 1;
5481    405 |             |            |           s := s + 1;
5482    406 |             |            |           s := s + 1;
5483    407 |             |            |           s := s + 1;
5484    408 |             |            |           s := s + 1;
5485    409 |             |            |           s := s + 1;
5486    410 |             |            |           s := s + 1;
5487    411 |             |            |           s := s + 1;
5488    412 |             |            |           s := s + 1;
5489    413 |             |            |           s := s + 1;
5490    414 |             |            |           s := s + 1;
5491    415 |             |            |           s := s + 1;
5492    416 |             |            |           s := s + 1;
5493    417 |             |            |           s := s + 1;
5494    418 |             |            |           s := s + 1;
5495    419 |             |            |           s := s + 1;
5496    420 |             |            |           s := s + 1;
5497    421 |             |            |           s := s + 1;
5498    422 |             |            |           s := s + 1;
5499    423 |             |            |           s := s + 1;
5500    424 |             |            |           s := s + 1;
5501    425 |             |            |           s := s + 1;
5502    426 |             |            |           s := s + 1;
5503    427 |             |            |           s := s + 1;
5504    428 |             |            |           s := s + 1;
5505    429 |             |            |           s := s + 1;
5506    430 |             |            |           s := s + 1;
5507    431 |             |            |           s := s + 1;
5508    432 |             |            |           s := s + 1;
5509    433 |             |            |           s := s + 1;
5510    434 |             |            |           s := s + 1;
5511    435 |             |            |           s := s + 1;
5512    436 |             |            |           s := s + 1;
5513    437 |             |            |           s := s + 1;
5514    438 |             |            |           s := s + 1;
5515    439 |             |            |           s := s + 1;
5516    440 |             |            |           s := s + 1;
5517    441 |             |            |           s := s + 1;
5518    442 |             |            |           s := s + 1;
5519    443 |             |            |           s := s + 1;
5520    444 |             |            |           s := s + 1;
5521    445 |             |            |           s := s + 1;
5522    446 |             |            |           s := s + 1;
5523    447 |             |            |           s := s + 1;
5524    448 |             |            |           s := s + 1;
5525    449 |             |            |           s := s + 1;
5526    450 |             |            |           s := s + 1;
5527    451 |             |            |           s := s + 1;
5528    452 |             |            |           s := s + 1;
5529    453 |             |            |           s := s + 1;
5530    454 |             |            |           s := s + 1;
5531    455 |             |            |           s := s + 1;
5532    456 |             |            |           s := s + 1;
5533    457 |             |            |           s := s + 1;
5534    458 |             |            |           s := s + 1;
5535    459 |             |            |           s := s + 1;
5536    460 |             |            |           s := s + 1;
5537    461 |             |            |           s := s + 1;
5538    462 |             |            |           s := s + 1;
5539    463 |             |            |           s := s + 1;
5540    464 |             |            |           s := s + 1;
5541    465 |             |            |           s := s + 1;
5542    466 |             |            |           s := s + 1;
5543    467 |             |            |           s := s + 1;
5544    468 |             |            |           s := s + 1;
5545    469 |             |            |           s := s + 1;
5546    470 |             |            |           s := s + 1;
5547    471 |             |            |           s := s + 1;
5548    472 |             |            |           s := s + 1;
5549    473 |             |            |           s := s + 1;
5550    474 |             |            |           s := s + 1;
5551    475 |             |            |           s := s + 1;
5552    476 |             |            |           s := s + 1;
5553    477 |             |            |           s := s + 1;
5554    478 |             |            |           s := s + 1;
5555    479 |             |            |           s := s + 1;
5556    480 |             |            |           s := s + 1;
5557    481 |             |            |           s := s + 1;
5558    482 |             |            |           s := s + 1;
5559    483 |             |            |           s := s + 1;
5560    484 |             |            |           s := s + 1;
5561    485 |             |            |           s := s + 1;
5562    486 |             |            |           s := s + 1;
5563    487 |             |            |           s := s + 1;
5564    488 |             |            |           s := s + 1;
5565    489 |             |            |           s := s + 1;
5566    490 |             |            |           s := s + 1;
5567    491 |             |            |           s := s + 1;
5568    492 |             |            |           s := s + 1;
5569    493 |             |            |           s := s + 1;
5570    494 |             |            |           s := s + 1;
5571    495 |             |            |           s := s + 1;
5572    496 |             |            |           s := s + 1;
5573    497 |             |            |           s := s + 1;
5574    498 |             |            |           s := s + 1;
5575    499 |             |            |           s := s + 1;
5576    500 |             |            |           s := s + 1;
5577    501 |             |            |           s := s + 1;
5578    502 |             |            |           s := s + 1;
5579    503 |             |            |           s := s + 1;
5580    504 |             |            |           s := s + 1;
5581    505 |             |            |           s := s + 1;
5582    506 |             |            |           s := s + 1;
5583    507 |             |            |           s := s + 1;
5584    508 |             |            |           s := s + 1;
5585    509 |             |            |           s := s + 1;
5586    510 |             |            |           s := s + 1;
5587    511 |             |            |           s := s + 1;
5588    512 |             |            |           s := s + 1;
5589    513 |             |            |           s := s + 1;
5590    514 |             |            |           s := s + 1;
5591    515 |             |            |           s := s + 1;
5592    516 |             |            |           s := s + 1;
5593    517 |             |            |           s := s + 1;
5594    518 |             |            |           s := s + 1;
5595    519 |             |            |           s := s + 1;
5596    520 |             |            |           s := s + 1;
5597    521 |             |            |           s := s + 1;
5598    522 |             |            |           s := s + 1;
5599    523 |             |            |           s := s + 1;
5600    524 |             |            |           s := s + 1;
5601    525 |             |            |           s := s + 1;
5602    526 |             |            |           s := s + 1;
5603    527 |             |            |           s := s + 1;
5604    528 |             |            |           s := s + 1;
5605    529 |             |            |           s := s + 1;
5606    530 |             |            |           s := s + 1;
5607    531 |             |            |           s := s + 1;
5608    532 |             |            |           s := s + 1;
5609    533 |             |            |           s := s + 1;
5610    534 |             |            |           s := s + 1;
5611    535 |             |            |           s := s + 1;
5612    536 |             |            |           s := s + 1;
5613    537 |             |            |           s := s + 1;
5614    538 |             |            |           s := s + 1;
5615    539 |             |            |           s := s + 1;
5616    540 |             |            |           s := s + 1;
5617    541 |             |            |           s := s + 1;
5618    542 |             |            |           s := s + 1;
5619    543 |             |            |           s := s + 1;
5620    544 |             |            |           s := s + 1;
5621    545 |             |            |           s := s + 1;
5622    546 |             |            |           s := s + 1;
5623    547 |             |            |           s := s + 1;
5624    548 |             |            |           s := s + 1;
5625    549 |             |            |           s := s + 1;
5626    550 |             |            |           s := s + 1;
5627    551 |             |            |           s := s + 1;
5628    552 |             |            |           s := s + 1;
5629    553 |             |            |           s := s + 1;
5630    554 |             |            |           s := s + 1;
5631    555 |             |            |           s := s + 1;
5632    556 |             |            |           s := s + 1;
5633    557 |             |            |           s := s + 1;
5634    558 |             |            |           s := s + 1;
5635    559 |             |            |           s := s + 1;
5636    560 |             |            |           s := s + 1;
5637    561 |             |            |           s := s + 1;
5638    562 |             |            |           s := s + 1;
5639    563 |             |            |           s := s + 1;
5640    564 |             |            |           s := s + 1;
5641    565 |             |            |           s := s + 1;
5642    566 |             |            |           s := s + 1;
5643    567 |             |            |           s := s + 1;
5644    568 |             |            |           s := s + 1;
5645    569 |             |            |           s := s + 1;
5646    570 |             |            |           s := s + 1;
5647    571 |             |            |           s := s + 1;
5648    572 |             |            |           s := s + 1;
5649    573 |             |            |           s := s + 1;
5650    574 |             |            |           s := s + 1;
5651    575 |             |            |           s := s + 1;
5652    576 |             |            |           s := s + 1;
5653    577 |             |            |           s := s + 1;
5654    578 |             |            |           s := s + 1;
5655    579 |             |            |           s := s + 1;
5656    580 |             |            |           s := s + 1;
5657    581 |             |            |           s := s + 1;
5658    582 |             |            |           s := s + 1;
5659    583 |             |            |           s := s + 1;
5660    584 |             |            |           s := s + 1;
5661    585 |             |            |           s := s + 1;
5662    586 |             |            |           s := s + 1;
5663    587 |             |            |           s := s + 1;
5664    588 |             |            |           s := s + 1;
5665    589 |             |            |           s := s + 1;
5666    590 |             |            |           s := s + 1;
5667    591 |             |            |           s := s + 1;
5668    592 |             |            |           s := s + 1;
5669    593 |             |            |           s := s + 1;
5670    594 |             |            |           s := s + 1;
5671    595 |             |            |           s := s + 1;
5672    596 |             |            |           s := s + 1;
5673    597 |             |            |           s := s + 1;
5674    598 |             |            |           s := s + 1;
5675    599 |             |            |           s := s + 1;
5676    600 |             |            |           s := s + 1;
5677    601 |             |            |           s := s + 1;
5678    602 |             |            |           s := s + 1;
5679    603 |             |            |           s := s + 1;
5680    604 |             |            |           s := s + 1;
5681    605 |             |            |           s := s + 1;
5682    606 |             |            |           s := s + 1;
5683    607 |             |            |           s := s + 1;
5684    608 |             |            |           s := s + 1;
5685    609 |             |            |           s := s + 1;
5686    610 |             |            |           s := s + 1;
5687    611 |             |            |           s := s + 1;
5688    612 |             |            |           s := s + 1;
5689    613 |             |            |           s := s + 1;
5690    614 |             |            |           s := s + 1;
5691    615 |             |            |           s := s + 1;
5692    616 |             |            |           s := s + 1;
5693    617 |             |            |           s := s + 1;
5694    618 |             |            |           s := s + 1;
5695    619 |             |            |           s := s + 1;
5696    620 |             |            |           s := s + 1;
5697    621 |             |            |           s := s + 1;
5698    622 |             |            |           s := s + 1;
5699    623 |             |            |           s := s + 1;
5700    624 |             |            |           s := s + 1;
5701    625 |             |            |           s := s + 1;
5702    626 |             |            |           s := s + 1;
5703    627 |             |            |           s := s + 1;
5704    628 |             |            |           s := s + 1;
5705    629 |             |            |           s := s + 1;
5706    630 |             |            |           s := s + 1;
5707    631 |             |            |           s := s + 1;
5708    632 |             |            |           s := s + 1;
5709    633 |             |            |           s := s + 1;
5710    634 |             |            |           s := s + 1;
5711    635 |             |            |           s := s + 1;
5712    636 |             |            |           s := s + 1;
5713    637 |             |            |           s := s + 1;
5714    638 |             |            |           s := s + 1;
5715    639 |             |            |           s := s + 1;
5716    640 |             |            |           s := s + 1;
5717    641 |             |            |           s := s + 1;
5718    642 |             |            |           s := s + 1;
5719    643 |             |            |           s := s + 1;
5720    644 |             |            |           s := s + 1;
5721    645 |             |            |           s := s + 1;
5722    646 |             |            |           s := s + 1;
5723    647 |             |            |           s := s + 1;
5724    648 |             |            |           s := s + 1;
5725    649 |             |            |           s := s + 1;
5726    650 |             |            |           s := s + 1;
5727    651 |             |            |           s := s + 1;
5728    652 |             |            |           s := s + 1;
5729    653 |             |            |           s := s + 1;
5730    654 |             |            |           s := s + 1;
5731    655 |             |            |           s := s + 1;
5732    656 |             |            |           s := s + 1;
5733    657 |             |            |           s := s + 1;
5734    658 |             |            |           s := s + 1;
5735    659 |             |            |           s := s + 1;
5736    660 |             |            |           s := s + 1;
5737    661 |             |            |           s := s + 1;
5738    662 |             |            |           s := s + 1;
5739    663 |             |            |           s := s + 1;
5740    664 |             |            |           s := s + 1;
5741    665 |             |            |           s := s + 1;
5742    666 |             |            |           s := s + 1;
5743    667 |             |            |           s := s + 1;
5744    668 |             |            |           s := s + 1;
5745    669 |             |            |           s := s + 1;
5746    670 |             |            |           s := s + 1;
5747    671 |             |            |           s := s + 1;
5748    672 |             |            |           s := s + 1;
5749    673 |             |            |           s := s + 1;
5750    674 |             |            |           s := s + 1;
5751    675 |             |            |           s := s + 1;
5752    676 |             |            |           s := s + 1;
5753    677 |             |            |           s := s + 1;
5754    678 |             |            |           s := s + 1;
5755    679 |             |            |           s := s + 1;
5756    680 |             |            |           s := s + 1;
5757    681 |             |            |           s := s + 1;
5758    682 |             |            |           s := s + 1;
5759    683 |             |            |           s := s + 1;
5760    684 |             |            |           s := s + 1;
5761    685 |             |            |           s := s + 1;
5762    686 |             |            |           s := s + 1;
5763    687 |             |            |           s := s + 1;
5764    688 |             |            |           s := s + 1;
5765    689 |             |            |           s := s + 1;
5766    690 |             |            |           s := s + 1;
5767    691 |             |            |           s := s + 1;
5768    692 |             |            |           s := s + 1;
5769    693 |             |            |           s := s + 1;
5770    694 |             |            |           s := s + 1;
5771    695 |             |            |           s := s + 1;
5772    696 |             |            |           s := s + 1;
5773    697 |             |            |           s := s + 1;
5774    698 |             |            |           s := s + 1;
5775    699 |             |            |           s := s + 1;
5776    700 |             |            |           s := s + 1;
5777    701 |             |            |           s := s + 1;
5778    702 |             |            |           s := s + 1;
5779    703 |             |            |           s := s + 1;
5780    704 |             |            |           s := s + 1;
5781    705 |             |            |           s := s + 1;
5782    706 |             |            |           s := s + 1;
5783    707 |             |            |           s := s + 1;
5784    708 |             |            |           s := s + 1;
5785    709 |             |            |           s := s + 1;
5786    710 |             |            |           s := s + 1;
5787    711 |             |            |           s := s + 1;
5788    712 |             |            |           s := s + 1;
5789    713 |             |            |           s := s + 1;
5790    714 |             |            |           s := s + 1;
5791    715 |             |            |           s := s + 1;
5792    716 |             |            |           s := s + 1;
5793    717 |             |            |           s := s + 1;
5794    718 |             |            |           s := s + 1;
5795    719 |             |            |           s := s + 1;
5796    720 |             |            |           s := s + 1;
5797    721 |             |            |           s := s + 1;
5798    722 |             |            |           s := s + 1;
5799    723 |             |            |           s := s + 1;
5800    724 |             |            |           s := s + 1;
5801    725 |             |            |           s := s + 1;
5802    726 |             |            |           s := s + 1;
5803    727 |             |            |           s := s + 1;
5804    728 |             |            |           s := s + 1;
5805    729 |             |            |           s := s + 1;
5806    730 |             |            |           s := s + 1;
5807    731 |             |            |           s := s + 1;
5808    732 |             |            |           s := s + 1;
5809    733 |             |            |           s := s + 1;
5810    734 |             |            |           s := s + 1;
5811    735 |             |            |           s := s + 1;
5812    736 |             |            |           s := s + 1;
5813    737 |             |            |           s := s + 1;
5814    738 |             |            |           s := s + 1;
5815    739 |             |            |           s := s + 1;
5816    740 |             |            |           s := s + 1;
5817    741 |             |            |           s := s + 1;
5818    742 |             |            |           s := s + 1;
5819    743 |             |            |           s := s + 1;
5820    744 |             |            |           s := s + 1;
5821    745 |             |            |           s := s + 1;
5822    746 |             |            |           s := s + 1;
5823    747 |             |            |           s := s + 1;
5824    748 |             |            |           s := s + 1;
5825    749 |             |            |           s := s + 1;
5826    750 |             |            |           s := s + 1;
5827    751 |             |            |           s := s + 1;
5828    752 |             |            |           s := s + 1;
5829    753 |             |            |           s := s + 1;
5830    754 |             |            |           s := s + 1;
5831    755 |             |            |           s := s + 1;
5832    756 |             |            |           s := s + 1;
5833    757 |             |            |           s := s + 1;
5834    758 |             |            |           s := s + 1;
5835    759 |             |            |           s := s + 1;
5836    760 |             |            |           s := s + 1;
5837    761 |             |            |           s := s + 1;
5838    762 |             |            |           s := s + 1;
5839    763 |             |            |           s := s + 1;
5840    764 |             |            |           s := s + 1;
5841    765 |             |            |           s := s + 1;
5842    766 |             |            |           s := s + 1;
5843    767 |             |            |           s := s + 1;
5844    768 |             |            |           s := s + 1;
5845    769 |             |            |           s := s + 1;
5846    770 |             |            |           s := s + 1;
5847    771 |             |            |           s := s + 1;
5848    772 |             |            |           s := s + 1;
5849    773 |             |            |           s := s + 1;
5850    774 |             |            |           s := s + 1;
5851    775 |             |            |           s := s + 1;
5852    776 |             |            |           s := s + 1;
5853    777 |             |            |           s := s + 1;
5854    778 |             |            |           s := s + 1;
5855    779 |             |            |           s := s + 1;
5856    780 |             |            |           s := s + 1;
5857    781 |             |            |           s := s + 1;
5858    782 |             |            |           s := s + 1;
5859    783 |             |            |           s := s + 1;
5860    784 |             |            |           s := s + 1;
5861    785 |             |            |           s := s + 1;
5862    786 |             |            |           s := s + 1;
5863    787 |             |            |           s := s + 1;
5864    788 |             |            |           s := s + 1;
5865    789 |             |            |           s := s + 1;
5866    790 |             |            |           s := s + 1;
5867    791 |             |            |           s := s + 1;
5868    792 |             |            |           s := s + 1;
5869    793 |             |            |           s := s + 1;
5870    794 |             |            |           s := s + 1;
5871    795 |             |            |           s := s + 1;
5872    796 |             |            |           s := s + 1;
5873    797 |             |            |           s := s + 1;
5874    798 |             |            |           s := s + 1;
5875    799 |             |            |           s := s + 1;
5876    800 |             |            |           s := s + 1;
5877    801 |             |            |           s := s + 1;
5878    802 |             |            |           s := s + 1;
5879    803 |             |            |           s := s + 1;
5880    804 |             |            |           s := s + 1;
5881    805 |             |            |           s := s + 1;
5882    806 |             |            |           s := s + 1;
5883    807 |             |            |           s := s + 1;
5884    808 |             |            |           s := s + 1;
5885    809 |             |            |           s := s + 1;
5886    810 |             |            |           s := s + 1;
5887    811 |             |            |           s := s + 1;
5888    812 |             |            |           s := s + 1;
5889    813 |             |            |           s := s + 1;
5890    814 |             |            |           s := s + 1;
5891    815 |             |            |           s := s + 1;
5892    816 |             |            |           s := s + 1;
5893    817 |             |            |           s := s + 1;
5894    818 |             |            |           s := s + 1;
5895    819 |             |            |           s := s + 1;
5896    820 |             |            |           s := s + 1;
5897    821 |             |            |           s := s + 1;
5898    822 |             |            |           s := s + 1;
5899    823 |             |            |           s := s + 1;
5900    824 |             |            |           s := s + 1;
5901    825 |             |            |           s := s + 1;
5902    826 |             |            |           s := s + 1;
5903    827 |             |            |           s := s + 1;
5904    828 |             |            |           s := s + 1;
5905    829 |             |            |           s := s + 1;
5906    830 |             |            |           s := s + 1;
5907    831 |             |            |           s := s + 1;
5908    832 |             |            |           s := s + 1;
5909    833 |             |            |           s := s + 1;
5910    834 |             |            |           s := s + 1;
5911    835 |             |            |           s := s + 1;
5912    836 |             |            |           s := s + 1;
5913    837 |             |            |           s := s + 1;
5914    838 |             |            |           s := s + 1;
5915    839 |             |            |           s := s + 1;
5916    840 |             |            |           s := s + 1;
5917    841 |             |            |           s := s + 1;
5918    842 |             |            |           s := s + 1;
5919    843 |             |            |           s := s + 1;
5920    844 |             |            |           s := s + 1;
5921    845 |             |            |           s := s + 1;
5922    846 |             |            |           s := s + 1;
5923    847 |             |            |           s := s + 1;
5924    848 |             |            |           s := s + 1;
5925    849 |             |            |           s := s + 1;
5926    850 |             |            |           s := s + 1;
5927    851 |             |            |           s := s + 1;
5928    852 |             |            |           s := s + 1;
5929    853 |             |            |           s := s + 1;
5930    854 |             |            |           s := s + 1;
5931    855 |             |            |           s := s + 1;
5932    856 |             |            |           s := s + 1;
5933    857 |             |            |           s := s + 1;
5934    858 |             |            |           s := s + 1;
5935    859 |             |            |           s := s + 1;
5936    860 |             |            |           s := s + 1;
5937    861 |             |            |           s := s + 1;
5938    862 |             |            |           s := s + 1;
5939    863 |             |            |           s := s + 1;
5940    864 |             |            |           s := s + 1;
5941    865 |             |            |           s := s + 1;
5942    866 |             |            |           s := s + 1;
5943    867 |             |            |           s := s + 1;
5944    868 |             |            |           s := s + 1;
5945    869 |             |            |           s := s + 1;
5946    870 |             |            |           s := s + 1;
5947    871 |             |            |           s := s + 1;
5948    872 |             |            |           s := s + 1;
5949    873 |             |            |           s := s + 1;
5950    874 |             |            |           s := s + 1;
5951    875 |             |            |           s := s + 1;
5952    876 |             |            |           s := s + 1;
5953    877 |             |            |           s := s + 1;
5954    878 |             |            |           s := s + 1;
5955    879 |             |            |           s := s + 1;
5956    880 |             |            |           s := s + 1;
5957    881 |             |            |           s := s + 1;
5958    882 |             |            |           s := s + 1;
5959    883 |             |            |           s := s + 1;
5960    884 |             |            |           s := s + 1;
5961    885 |             |            |           s := s + 1;
5962    886 |             |            |           s := s + 1;
5963    887 |             |            |           s := s + 1;
5964    888 |             |            |           s := s + 1;
5965    889 |             |            |           s := s + 1;
5966    890 |             |            |           s := s + 1;
5967    891 |             |            |           s := s + 1;
5968    892 |             |            |           s := s + 1;
5969    893 |             |            |           s := s + 1;
5970    894 |             |            |           s := s + 1;
5971    895 |             |            |           s := s + 1;
5972    896 |             |            |           s := s + 1;
5973    897 |             |            |           s := s + 1;
5974    898 |             |            |           s := s + 1;
5975    899 |             |            |           s := s + 1;
5976    900 |             |            |           s := s + 1;
5977    901 |             |            |           s := s + 1;
5978    902 |             |            |           s := s + 1;
5979    903 |             |            |           s := s + 1;
5980    904 |             |            |           s := s + 1;
5981    905 |             |            |           s := s + 1;
5982    906 |             |            |           s := s + 1;
5983    907 |             |            |           s := s + 1;
5984    908 |             |            |           s := s + 1;
5985    909 |             |            |           s := s + 1;
5986    910 |             |            |           s := s + 1;
5987    911 |             |            |           s := s + 1;
5988    912 |             |            |           s := s + 1;
5989    913 |             |            |           s := s + 1;
5990    914 |             |            |           s := s + 1;
5991    915 |             |            |           s := s + 1;
5992    916 |             |            |           s := s + 1;
5993    917 |             |            |           s := s + 1;
5994    918 |             |            |           s := s + 1;
5995    919 |             |            |           s := s + 1;
5996    920 |             |            |           s := s + 1;
5997    921 |             |            |           s := s + 1;
5998    922 |             |            |           s := s + 1;
5999    923 |             |            |           s := s + 1;
6000    924 |             |            |           s := s + 1;
6001    925 |             |            |           s := s + 1;
6002    926 |             |            |           s := s + 1;
6003    927 |             |            |           s := s + 1;
6004    928 |             |            |           s := s + 1;
6005    929 |             |            |           s := s + 1;
6006    930 |             |            |           s := s + 1;
6007    931 |             |            |           s := s + 1;
6008    932 |             |            |           s := s + 1;
6009    933 |             |            |           s := s + 1;
6010    934 |             |            |           s := s + 1;
6011    935 |             |            |           s := s + 1;
6012    936 |             |            |           s := s + 1;
6013    937 |             |            |           s := s + 1;
6014    938 |             |            |           s := s + 1;
6015    939 |             |            |           s := s + 1;
6016    940 |             |            |           s := s + 1;
6017    941 |             |            |           s := s + 1;
6018    942 |             |            |           s := s + 1;
6019    943 |             |            |           s := s + 1;
6020    944 |             |            |           s := s + 1;
6021    945 |             |            |           s := s + 1;
6022    946 |             |            |           s := s + 1;
6023    947 |             |            |           s := s + 1;
6024    948 |             |            |           s := s + 1;
6025    949 |             |            |           s := s + 1;
6026    950 |             |            |           s := s + 1;
6027    951 |             |            |           s := s + 1;
6028    952 |             |            |           s := s + 1;
6029    953 |             |            |           s := s + 1;
6030    954 |             |            |           s := s + 1;
6031    955 |             |            |           s := s + 1;
6032    956 |             |            |           s := s + 1;
6033    957 |             |            |           s := s + 1;
6034    958 |             |            |           s := s + 1;
6035    959 |             |            |           s := s + 1;
6036    960 |             |            |           s := s + 1;
6037    961 |             |            |           s := s + 1;
6038    962 |             |            |           s := s + 1;
6039    963 |             |            |           s := s + 1;
6040    964 |             |            |           s := s + 1;
6041    965 |             |            |           s := s + 1;
6042    966 |             |            |           s := s + 1;
6043    967 |             |            |           s := s + 1;
6044    968 |             |            |           s := s + 1;
6045    969 |             |            |           s := s + 1;
6046    970 |             |            |           s := s + 1;
6047    971 |             |            |           s := s + 1;
6048    972 |             |            |           s := s + 1;
6049    973 |             |            |           s := s + 1;
6050    974 |             |            |           s := s + 1;
6051    975 |             |            |           s := s + 1;
6052    976 |             |            |           s := s + 1;
6053    977 |             |            |           s := s + 1;
6054    978 |             |            |           s := s + 1;
6055    979 |             |            |           s := s + 1;
6056    980 |             |            |           s := s + 1;
6057    981 |             |            |           s := s + 1;
6058    982 |             |            |           s := s + 1;
6059    983 |             |            |           s := s + 1;
6060    984 |             |            |           s := s + 1;
6061    985 |             |            |           s := s + 1;
6062    986 |             |            |           s := s + 1;
6063    987 |             |            |           s := s + 1;
6064    988 |             |            |           s := s + 1;
6065    989 |             |            |           s := s + 1;
6066    990 |             |            |           s := s + 1;
6067    991 |             |            |           s := s + 1;
6068    992 |             |            |           s := s + 1;
6069    993 |             |            |           s := s + 1;
6070    994 |             |            |           s := s + 1;
6071    995 |             |            |           s := s + 1;
6072    996 |             |            |           s := s + 1;
6073    997 |             |            |           s := s + 1;
6074    998 |             |            |           s := s + 1;
6075    999 |             |            |           s := s + 1;
6076   1000 |             |            |           s := s + 1;
6077   1001 |             |            |           s := s + 1;
6078   1002 |             |            |           s := s + 1;
6079   1003 |             |            |           s := s + 1;
6080   1004 |             |            |           s := s + 1;
6081   1005 |             |            |           s := s + 1;
6082   1006 |             |            |           s := s + 1;
6083   1007 |             |            |           s := s + 1;
6084   1008 |             |            |           s := s + 1;
6085   1009 |             |            |           s := s + 1;
6086   1010 |             |            |           s := s + 1;
6087   1011 |             |            |           s := s + 1;
6088   1012 |             |            |           s := s + 1;
6089   1013 |             |            |           s := s + 1;
6090   1014 |             |            |           s := s + 1;
6091   1015 |             |            |           s := s + 1;
6092   1016 |             |            |           s := s + 1;
6093   1017 |             |            |           s := s + 1;
6094   1018 |             |            |           s := s + 1;
6095   1019 |             |            |           s := s + 1;
6096   1020 |             |            |           s := s + 1;
6097   1021 |             |            |           s := s + 1;
6098   1022 |             |            |           s := s + 1;
6099   1023 |             |            |           s := s + 1;
6100   1024 |             |            |           s := s + 1;
6101   1025 |             |            |           s := s + 1;
6102   1026 |             |            |           s := s + 1;
6103   1027 |             |            |           s := s + 1;
6104   1028 |             |            |           s := s + 1;
6105   1029 |             |            |           s := s + 1;
6106   1030 |             |            |           s := s + 1;
6107   1031 |             |            |           s := s + 1;
6108   1032 |             |            |           s := s + 1;
6109   1033 |             |            |           s := s + 1;
6110   1034 |             |            |           s := s + 1;
6111   1035 |             |            |           s := s + 1;
6112   1036 |             |            |           s := s + 1;
6113   1037 |             |            |           s := s + 1;
6114   1038 |             |            |         end loop;
6115   1039 |             |            |       end loop;
6116   1040 |             |            |       j := j + 1;
6117   1041 |             |            |     end loop;
6118   1042 |             |            |   exception when others then
6119   1043 |             |            |     raise 'reraised exception %', sqlerrm;
6120   1044 |             |            |   end;
6121   1045 |             |            |   return $1;
6122   1046 |             |            | end;
6123(1046 rows)
6124
6125set plpgsql_check.profiler = on;
6126select longfx(10);
6127 longfx
6128--------
6129     10
6130(1 row)
6131
6132select longfx(10);
6133 longfx
6134--------
6135     10
6136(1 row)
6137
6138set plpgsql_check.profiler = off;
6139select longfx(10);
6140 longfx
6141--------
6142     10
6143(1 row)
6144
6145select lineno, stmt_lineno, exec_stmts, source from plpgsql_profiler_function_tb('longfx');
6146 lineno | stmt_lineno | exec_stmts |                       source
6147--------+-------------+------------+-----------------------------------------------------
6148      1 |             |            |
6149      2 |             |            | declare
6150      3 |             |            |   s int default 0;
6151      4 |             |            |   j int default 0;
6152      5 |             |            |   r record;
6153      6 |           6 |          2 | begin
6154      7 |           7 |          2 |   begin
6155      8 |           8 |          2 |     while j < 10
6156      9 |             |            |     loop
6157     10 |          10 |         20 |       for i in 1..1
6158     11 |             |            |       loop
6159     12 |          12 |         20 |         for r in select * from generate_series(1,1)
6160     13 |             |            |         loop
6161     14 |          14 |         20 |           s := s + 1;
6162     15 |          15 |         20 |           s := s + 1;
6163     16 |          16 |         20 |           s := s + 1;
6164     17 |          17 |         20 |           s := s + 1;
6165     18 |          18 |         20 |           s := s + 1;
6166     19 |          19 |         20 |           s := s + 1;
6167     20 |          20 |         20 |           s := s + 1;
6168     21 |          21 |         20 |           s := s + 1;
6169     22 |          22 |         20 |           s := s + 1;
6170     23 |          23 |         20 |           s := s + 1;
6171     24 |          24 |         20 |           s := s + 1;
6172     25 |          25 |         20 |           s := s + 1;
6173     26 |          26 |         20 |           s := s + 1;
6174     27 |          27 |         20 |           s := s + 1;
6175     28 |          28 |         20 |           s := s + 1;
6176     29 |          29 |         20 |           s := s + 1;
6177     30 |          30 |         20 |           s := s + 1;
6178     31 |          31 |         20 |           s := s + 1;
6179     32 |          32 |         20 |           s := s + 1;
6180     33 |          33 |         20 |           s := s + 1;
6181     34 |          34 |         20 |           s := s + 1;
6182     35 |          35 |         20 |           s := s + 1;
6183     36 |          36 |         20 |           s := s + 1;
6184     37 |          37 |         20 |           s := s + 1;
6185     38 |          38 |         20 |           s := s + 1;
6186     39 |          39 |         20 |           s := s + 1;
6187     40 |          40 |         20 |           s := s + 1;
6188     41 |          41 |         20 |           s := s + 1;
6189     42 |          42 |         20 |           s := s + 1;
6190     43 |          43 |         20 |           s := s + 1;
6191     44 |          44 |         20 |           s := s + 1;
6192     45 |          45 |         20 |           s := s + 1;
6193     46 |          46 |         20 |           s := s + 1;
6194     47 |          47 |         20 |           s := s + 1;
6195     48 |          48 |         20 |           s := s + 1;
6196     49 |          49 |         20 |           s := s + 1;
6197     50 |          50 |         20 |           s := s + 1;
6198     51 |          51 |         20 |           s := s + 1;
6199     52 |          52 |         20 |           s := s + 1;
6200     53 |          53 |         20 |           s := s + 1;
6201     54 |          54 |         20 |           s := s + 1;
6202     55 |          55 |         20 |           s := s + 1;
6203     56 |          56 |         20 |           s := s + 1;
6204     57 |          57 |         20 |           s := s + 1;
6205     58 |          58 |         20 |           s := s + 1;
6206     59 |          59 |         20 |           s := s + 1;
6207     60 |          60 |         20 |           s := s + 1;
6208     61 |          61 |         20 |           s := s + 1;
6209     62 |          62 |         20 |           s := s + 1;
6210     63 |          63 |         20 |           s := s + 1;
6211     64 |          64 |         20 |           s := s + 1;
6212     65 |          65 |         20 |           s := s + 1;
6213     66 |          66 |         20 |           s := s + 1;
6214     67 |          67 |         20 |           s := s + 1;
6215     68 |          68 |         20 |           s := s + 1;
6216     69 |          69 |         20 |           s := s + 1;
6217     70 |          70 |         20 |           s := s + 1;
6218     71 |          71 |         20 |           s := s + 1;
6219     72 |          72 |         20 |           s := s + 1;
6220     73 |          73 |         20 |           s := s + 1;
6221     74 |          74 |         20 |           s := s + 1;
6222     75 |          75 |         20 |           s := s + 1;
6223     76 |          76 |         20 |           s := s + 1;
6224     77 |          77 |         20 |           s := s + 1;
6225     78 |          78 |         20 |           s := s + 1;
6226     79 |          79 |         20 |           s := s + 1;
6227     80 |          80 |         20 |           s := s + 1;
6228     81 |          81 |         20 |           s := s + 1;
6229     82 |          82 |         20 |           s := s + 1;
6230     83 |          83 |         20 |           s := s + 1;
6231     84 |          84 |         20 |           s := s + 1;
6232     85 |          85 |         20 |           s := s + 1;
6233     86 |          86 |         20 |           s := s + 1;
6234     87 |          87 |         20 |           s := s + 1;
6235     88 |          88 |         20 |           s := s + 1;
6236     89 |          89 |         20 |           s := s + 1;
6237     90 |          90 |         20 |           s := s + 1;
6238     91 |          91 |         20 |           s := s + 1;
6239     92 |          92 |         20 |           s := s + 1;
6240     93 |          93 |         20 |           s := s + 1;
6241     94 |          94 |         20 |           s := s + 1;
6242     95 |          95 |         20 |           s := s + 1;
6243     96 |          96 |         20 |           s := s + 1;
6244     97 |          97 |         20 |           s := s + 1;
6245     98 |          98 |         20 |           s := s + 1;
6246     99 |          99 |         20 |           s := s + 1;
6247    100 |         100 |         20 |           s := s + 1;
6248    101 |         101 |         20 |           s := s + 1;
6249    102 |         102 |         20 |           s := s + 1;
6250    103 |         103 |         20 |           s := s + 1;
6251    104 |         104 |         20 |           s := s + 1;
6252    105 |         105 |         20 |           s := s + 1;
6253    106 |         106 |         20 |           s := s + 1;
6254    107 |         107 |         20 |           s := s + 1;
6255    108 |         108 |         20 |           s := s + 1;
6256    109 |         109 |         20 |           s := s + 1;
6257    110 |         110 |         20 |           s := s + 1;
6258    111 |         111 |         20 |           s := s + 1;
6259    112 |         112 |         20 |           s := s + 1;
6260    113 |         113 |         20 |           s := s + 1;
6261    114 |         114 |         20 |           s := s + 1;
6262    115 |         115 |         20 |           s := s + 1;
6263    116 |         116 |         20 |           s := s + 1;
6264    117 |         117 |         20 |           s := s + 1;
6265    118 |         118 |         20 |           s := s + 1;
6266    119 |         119 |         20 |           s := s + 1;
6267    120 |         120 |         20 |           s := s + 1;
6268    121 |         121 |         20 |           s := s + 1;
6269    122 |         122 |         20 |           s := s + 1;
6270    123 |         123 |         20 |           s := s + 1;
6271    124 |         124 |         20 |           s := s + 1;
6272    125 |         125 |         20 |           s := s + 1;
6273    126 |         126 |         20 |           s := s + 1;
6274    127 |         127 |         20 |           s := s + 1;
6275    128 |         128 |         20 |           s := s + 1;
6276    129 |         129 |         20 |           s := s + 1;
6277    130 |         130 |         20 |           s := s + 1;
6278    131 |         131 |         20 |           s := s + 1;
6279    132 |         132 |         20 |           s := s + 1;
6280    133 |         133 |         20 |           s := s + 1;
6281    134 |         134 |         20 |           s := s + 1;
6282    135 |         135 |         20 |           s := s + 1;
6283    136 |         136 |         20 |           s := s + 1;
6284    137 |         137 |         20 |           s := s + 1;
6285    138 |         138 |         20 |           s := s + 1;
6286    139 |         139 |         20 |           s := s + 1;
6287    140 |         140 |         20 |           s := s + 1;
6288    141 |         141 |         20 |           s := s + 1;
6289    142 |         142 |         20 |           s := s + 1;
6290    143 |         143 |         20 |           s := s + 1;
6291    144 |         144 |         20 |           s := s + 1;
6292    145 |         145 |         20 |           s := s + 1;
6293    146 |         146 |         20 |           s := s + 1;
6294    147 |         147 |         20 |           s := s + 1;
6295    148 |         148 |         20 |           s := s + 1;
6296    149 |         149 |         20 |           s := s + 1;
6297    150 |         150 |         20 |           s := s + 1;
6298    151 |         151 |         20 |           s := s + 1;
6299    152 |         152 |         20 |           s := s + 1;
6300    153 |         153 |         20 |           s := s + 1;
6301    154 |         154 |         20 |           s := s + 1;
6302    155 |         155 |         20 |           s := s + 1;
6303    156 |         156 |         20 |           s := s + 1;
6304    157 |         157 |         20 |           s := s + 1;
6305    158 |         158 |         20 |           s := s + 1;
6306    159 |         159 |         20 |           s := s + 1;
6307    160 |         160 |         20 |           s := s + 1;
6308    161 |         161 |         20 |           s := s + 1;
6309    162 |         162 |         20 |           s := s + 1;
6310    163 |         163 |         20 |           s := s + 1;
6311    164 |         164 |         20 |           s := s + 1;
6312    165 |         165 |         20 |           s := s + 1;
6313    166 |         166 |         20 |           s := s + 1;
6314    167 |         167 |         20 |           s := s + 1;
6315    168 |         168 |         20 |           s := s + 1;
6316    169 |         169 |         20 |           s := s + 1;
6317    170 |         170 |         20 |           s := s + 1;
6318    171 |         171 |         20 |           s := s + 1;
6319    172 |         172 |         20 |           s := s + 1;
6320    173 |         173 |         20 |           s := s + 1;
6321    174 |         174 |         20 |           s := s + 1;
6322    175 |         175 |         20 |           s := s + 1;
6323    176 |         176 |         20 |           s := s + 1;
6324    177 |         177 |         20 |           s := s + 1;
6325    178 |         178 |         20 |           s := s + 1;
6326    179 |         179 |         20 |           s := s + 1;
6327    180 |         180 |         20 |           s := s + 1;
6328    181 |         181 |         20 |           s := s + 1;
6329    182 |         182 |         20 |           s := s + 1;
6330    183 |         183 |         20 |           s := s + 1;
6331    184 |         184 |         20 |           s := s + 1;
6332    185 |         185 |         20 |           s := s + 1;
6333    186 |         186 |         20 |           s := s + 1;
6334    187 |         187 |         20 |           s := s + 1;
6335    188 |         188 |         20 |           s := s + 1;
6336    189 |         189 |         20 |           s := s + 1;
6337    190 |         190 |         20 |           s := s + 1;
6338    191 |         191 |         20 |           s := s + 1;
6339    192 |         192 |         20 |           s := s + 1;
6340    193 |         193 |         20 |           s := s + 1;
6341    194 |         194 |         20 |           s := s + 1;
6342    195 |         195 |         20 |           s := s + 1;
6343    196 |         196 |         20 |           s := s + 1;
6344    197 |         197 |         20 |           s := s + 1;
6345    198 |         198 |         20 |           s := s + 1;
6346    199 |         199 |         20 |           s := s + 1;
6347    200 |         200 |         20 |           s := s + 1;
6348    201 |         201 |         20 |           s := s + 1;
6349    202 |         202 |         20 |           s := s + 1;
6350    203 |         203 |         20 |           s := s + 1;
6351    204 |         204 |         20 |           s := s + 1;
6352    205 |         205 |         20 |           s := s + 1;
6353    206 |         206 |         20 |           s := s + 1;
6354    207 |         207 |         20 |           s := s + 1;
6355    208 |         208 |         20 |           s := s + 1;
6356    209 |         209 |         20 |           s := s + 1;
6357    210 |         210 |         20 |           s := s + 1;
6358    211 |         211 |         20 |           s := s + 1;
6359    212 |         212 |         20 |           s := s + 1;
6360    213 |         213 |         20 |           s := s + 1;
6361    214 |         214 |         20 |           s := s + 1;
6362    215 |         215 |         20 |           s := s + 1;
6363    216 |         216 |         20 |           s := s + 1;
6364    217 |         217 |         20 |           s := s + 1;
6365    218 |         218 |         20 |           s := s + 1;
6366    219 |         219 |         20 |           s := s + 1;
6367    220 |         220 |         20 |           s := s + 1;
6368    221 |         221 |         20 |           s := s + 1;
6369    222 |         222 |         20 |           s := s + 1;
6370    223 |         223 |         20 |           s := s + 1;
6371    224 |         224 |         20 |           s := s + 1;
6372    225 |         225 |         20 |           s := s + 1;
6373    226 |         226 |         20 |           s := s + 1;
6374    227 |         227 |         20 |           s := s + 1;
6375    228 |         228 |         20 |           s := s + 1;
6376    229 |         229 |         20 |           s := s + 1;
6377    230 |         230 |         20 |           s := s + 1;
6378    231 |         231 |         20 |           s := s + 1;
6379    232 |         232 |         20 |           s := s + 1;
6380    233 |         233 |         20 |           s := s + 1;
6381    234 |         234 |         20 |           s := s + 1;
6382    235 |         235 |         20 |           s := s + 1;
6383    236 |         236 |         20 |           s := s + 1;
6384    237 |         237 |         20 |           s := s + 1;
6385    238 |         238 |         20 |           s := s + 1;
6386    239 |         239 |         20 |           s := s + 1;
6387    240 |         240 |         20 |           s := s + 1;
6388    241 |         241 |         20 |           s := s + 1;
6389    242 |         242 |         20 |           s := s + 1;
6390    243 |         243 |         20 |           s := s + 1;
6391    244 |         244 |         20 |           s := s + 1;
6392    245 |         245 |         20 |           s := s + 1;
6393    246 |         246 |         20 |           s := s + 1;
6394    247 |         247 |         20 |           s := s + 1;
6395    248 |         248 |         20 |           s := s + 1;
6396    249 |         249 |         20 |           s := s + 1;
6397    250 |         250 |         20 |           s := s + 1;
6398    251 |         251 |         20 |           s := s + 1;
6399    252 |         252 |         20 |           s := s + 1;
6400    253 |         253 |         20 |           s := s + 1;
6401    254 |         254 |         20 |           s := s + 1;
6402    255 |         255 |         20 |           s := s + 1;
6403    256 |         256 |         20 |           s := s + 1;
6404    257 |         257 |         20 |           s := s + 1;
6405    258 |         258 |         20 |           s := s + 1;
6406    259 |         259 |         20 |           s := s + 1;
6407    260 |         260 |         20 |           s := s + 1;
6408    261 |         261 |         20 |           s := s + 1;
6409    262 |         262 |         20 |           s := s + 1;
6410    263 |         263 |         20 |           s := s + 1;
6411    264 |         264 |         20 |           s := s + 1;
6412    265 |         265 |         20 |           s := s + 1;
6413    266 |         266 |         20 |           s := s + 1;
6414    267 |         267 |         20 |           s := s + 1;
6415    268 |         268 |         20 |           s := s + 1;
6416    269 |         269 |         20 |           s := s + 1;
6417    270 |         270 |         20 |           s := s + 1;
6418    271 |         271 |         20 |           s := s + 1;
6419    272 |         272 |         20 |           s := s + 1;
6420    273 |         273 |         20 |           s := s + 1;
6421    274 |         274 |         20 |           s := s + 1;
6422    275 |         275 |         20 |           s := s + 1;
6423    276 |         276 |         20 |           s := s + 1;
6424    277 |         277 |         20 |           s := s + 1;
6425    278 |         278 |         20 |           s := s + 1;
6426    279 |         279 |         20 |           s := s + 1;
6427    280 |         280 |         20 |           s := s + 1;
6428    281 |         281 |         20 |           s := s + 1;
6429    282 |         282 |         20 |           s := s + 1;
6430    283 |         283 |         20 |           s := s + 1;
6431    284 |         284 |         20 |           s := s + 1;
6432    285 |         285 |         20 |           s := s + 1;
6433    286 |         286 |         20 |           s := s + 1;
6434    287 |         287 |         20 |           s := s + 1;
6435    288 |         288 |         20 |           s := s + 1;
6436    289 |         289 |         20 |           s := s + 1;
6437    290 |         290 |         20 |           s := s + 1;
6438    291 |         291 |         20 |           s := s + 1;
6439    292 |         292 |         20 |           s := s + 1;
6440    293 |         293 |         20 |           s := s + 1;
6441    294 |         294 |         20 |           s := s + 1;
6442    295 |         295 |         20 |           s := s + 1;
6443    296 |         296 |         20 |           s := s + 1;
6444    297 |         297 |         20 |           s := s + 1;
6445    298 |         298 |         20 |           s := s + 1;
6446    299 |         299 |         20 |           s := s + 1;
6447    300 |         300 |         20 |           s := s + 1;
6448    301 |         301 |         20 |           s := s + 1;
6449    302 |         302 |         20 |           s := s + 1;
6450    303 |         303 |         20 |           s := s + 1;
6451    304 |         304 |         20 |           s := s + 1;
6452    305 |         305 |         20 |           s := s + 1;
6453    306 |         306 |         20 |           s := s + 1;
6454    307 |         307 |         20 |           s := s + 1;
6455    308 |         308 |         20 |           s := s + 1;
6456    309 |         309 |         20 |           s := s + 1;
6457    310 |         310 |         20 |           s := s + 1;
6458    311 |         311 |         20 |           s := s + 1;
6459    312 |         312 |         20 |           s := s + 1;
6460    313 |         313 |         20 |           s := s + 1;
6461    314 |         314 |         20 |           s := s + 1;
6462    315 |         315 |         20 |           s := s + 1;
6463    316 |         316 |         20 |           s := s + 1;
6464    317 |         317 |         20 |           s := s + 1;
6465    318 |         318 |         20 |           s := s + 1;
6466    319 |         319 |         20 |           s := s + 1;
6467    320 |         320 |         20 |           s := s + 1;
6468    321 |         321 |         20 |           s := s + 1;
6469    322 |         322 |         20 |           s := s + 1;
6470    323 |         323 |         20 |           s := s + 1;
6471    324 |         324 |         20 |           s := s + 1;
6472    325 |         325 |         20 |           s := s + 1;
6473    326 |         326 |         20 |           s := s + 1;
6474    327 |         327 |         20 |           s := s + 1;
6475    328 |         328 |         20 |           s := s + 1;
6476    329 |         329 |         20 |           s := s + 1;
6477    330 |         330 |         20 |           s := s + 1;
6478    331 |         331 |         20 |           s := s + 1;
6479    332 |         332 |         20 |           s := s + 1;
6480    333 |         333 |         20 |           s := s + 1;
6481    334 |         334 |         20 |           s := s + 1;
6482    335 |         335 |         20 |           s := s + 1;
6483    336 |         336 |         20 |           s := s + 1;
6484    337 |         337 |         20 |           s := s + 1;
6485    338 |         338 |         20 |           s := s + 1;
6486    339 |         339 |         20 |           s := s + 1;
6487    340 |         340 |         20 |           s := s + 1;
6488    341 |         341 |         20 |           s := s + 1;
6489    342 |         342 |         20 |           s := s + 1;
6490    343 |         343 |         20 |           s := s + 1;
6491    344 |         344 |         20 |           s := s + 1;
6492    345 |         345 |         20 |           s := s + 1;
6493    346 |         346 |         20 |           s := s + 1;
6494    347 |         347 |         20 |           s := s + 1;
6495    348 |         348 |         20 |           s := s + 1;
6496    349 |         349 |         20 |           s := s + 1;
6497    350 |         350 |         20 |           s := s + 1;
6498    351 |         351 |         20 |           s := s + 1;
6499    352 |         352 |         20 |           s := s + 1;
6500    353 |         353 |         20 |           s := s + 1;
6501    354 |         354 |         20 |           s := s + 1;
6502    355 |         355 |         20 |           s := s + 1;
6503    356 |         356 |         20 |           s := s + 1;
6504    357 |         357 |         20 |           s := s + 1;
6505    358 |         358 |         20 |           s := s + 1;
6506    359 |         359 |         20 |           s := s + 1;
6507    360 |         360 |         20 |           s := s + 1;
6508    361 |         361 |         20 |           s := s + 1;
6509    362 |         362 |         20 |           s := s + 1;
6510    363 |         363 |         20 |           s := s + 1;
6511    364 |         364 |         20 |           s := s + 1;
6512    365 |         365 |         20 |           s := s + 1;
6513    366 |         366 |         20 |           s := s + 1;
6514    367 |         367 |         20 |           s := s + 1;
6515    368 |         368 |         20 |           s := s + 1;
6516    369 |         369 |         20 |           s := s + 1;
6517    370 |         370 |         20 |           s := s + 1;
6518    371 |         371 |         20 |           s := s + 1;
6519    372 |         372 |         20 |           s := s + 1;
6520    373 |         373 |         20 |           s := s + 1;
6521    374 |         374 |         20 |           s := s + 1;
6522    375 |         375 |         20 |           s := s + 1;
6523    376 |         376 |         20 |           s := s + 1;
6524    377 |         377 |         20 |           s := s + 1;
6525    378 |         378 |         20 |           s := s + 1;
6526    379 |         379 |         20 |           s := s + 1;
6527    380 |         380 |         20 |           s := s + 1;
6528    381 |         381 |         20 |           s := s + 1;
6529    382 |         382 |         20 |           s := s + 1;
6530    383 |         383 |         20 |           s := s + 1;
6531    384 |         384 |         20 |           s := s + 1;
6532    385 |         385 |         20 |           s := s + 1;
6533    386 |         386 |         20 |           s := s + 1;
6534    387 |         387 |         20 |           s := s + 1;
6535    388 |         388 |         20 |           s := s + 1;
6536    389 |         389 |         20 |           s := s + 1;
6537    390 |         390 |         20 |           s := s + 1;
6538    391 |         391 |         20 |           s := s + 1;
6539    392 |         392 |         20 |           s := s + 1;
6540    393 |         393 |         20 |           s := s + 1;
6541    394 |         394 |         20 |           s := s + 1;
6542    395 |         395 |         20 |           s := s + 1;
6543    396 |         396 |         20 |           s := s + 1;
6544    397 |         397 |         20 |           s := s + 1;
6545    398 |         398 |         20 |           s := s + 1;
6546    399 |         399 |         20 |           s := s + 1;
6547    400 |         400 |         20 |           s := s + 1;
6548    401 |         401 |         20 |           s := s + 1;
6549    402 |         402 |         20 |           s := s + 1;
6550    403 |         403 |         20 |           s := s + 1;
6551    404 |         404 |         20 |           s := s + 1;
6552    405 |         405 |         20 |           s := s + 1;
6553    406 |         406 |         20 |           s := s + 1;
6554    407 |         407 |         20 |           s := s + 1;
6555    408 |         408 |         20 |           s := s + 1;
6556    409 |         409 |         20 |           s := s + 1;
6557    410 |         410 |         20 |           s := s + 1;
6558    411 |         411 |         20 |           s := s + 1;
6559    412 |         412 |         20 |           s := s + 1;
6560    413 |         413 |         20 |           s := s + 1;
6561    414 |         414 |         20 |           s := s + 1;
6562    415 |         415 |         20 |           s := s + 1;
6563    416 |         416 |         20 |           s := s + 1;
6564    417 |         417 |         20 |           s := s + 1;
6565    418 |         418 |         20 |           s := s + 1;
6566    419 |         419 |         20 |           s := s + 1;
6567    420 |         420 |         20 |           s := s + 1;
6568    421 |         421 |         20 |           s := s + 1;
6569    422 |         422 |         20 |           s := s + 1;
6570    423 |         423 |         20 |           s := s + 1;
6571    424 |         424 |         20 |           s := s + 1;
6572    425 |         425 |         20 |           s := s + 1;
6573    426 |         426 |         20 |           s := s + 1;
6574    427 |         427 |         20 |           s := s + 1;
6575    428 |         428 |         20 |           s := s + 1;
6576    429 |         429 |         20 |           s := s + 1;
6577    430 |         430 |         20 |           s := s + 1;
6578    431 |         431 |         20 |           s := s + 1;
6579    432 |         432 |         20 |           s := s + 1;
6580    433 |         433 |         20 |           s := s + 1;
6581    434 |         434 |         20 |           s := s + 1;
6582    435 |         435 |         20 |           s := s + 1;
6583    436 |         436 |         20 |           s := s + 1;
6584    437 |         437 |         20 |           s := s + 1;
6585    438 |         438 |         20 |           s := s + 1;
6586    439 |         439 |         20 |           s := s + 1;
6587    440 |         440 |         20 |           s := s + 1;
6588    441 |         441 |         20 |           s := s + 1;
6589    442 |         442 |         20 |           s := s + 1;
6590    443 |         443 |         20 |           s := s + 1;
6591    444 |         444 |         20 |           s := s + 1;
6592    445 |         445 |         20 |           s := s + 1;
6593    446 |         446 |         20 |           s := s + 1;
6594    447 |         447 |         20 |           s := s + 1;
6595    448 |         448 |         20 |           s := s + 1;
6596    449 |         449 |         20 |           s := s + 1;
6597    450 |         450 |         20 |           s := s + 1;
6598    451 |         451 |         20 |           s := s + 1;
6599    452 |         452 |         20 |           s := s + 1;
6600    453 |         453 |         20 |           s := s + 1;
6601    454 |         454 |         20 |           s := s + 1;
6602    455 |         455 |         20 |           s := s + 1;
6603    456 |         456 |         20 |           s := s + 1;
6604    457 |         457 |         20 |           s := s + 1;
6605    458 |         458 |         20 |           s := s + 1;
6606    459 |         459 |         20 |           s := s + 1;
6607    460 |         460 |         20 |           s := s + 1;
6608    461 |         461 |         20 |           s := s + 1;
6609    462 |         462 |         20 |           s := s + 1;
6610    463 |         463 |         20 |           s := s + 1;
6611    464 |         464 |         20 |           s := s + 1;
6612    465 |         465 |         20 |           s := s + 1;
6613    466 |         466 |         20 |           s := s + 1;
6614    467 |         467 |         20 |           s := s + 1;
6615    468 |         468 |         20 |           s := s + 1;
6616    469 |         469 |         20 |           s := s + 1;
6617    470 |         470 |         20 |           s := s + 1;
6618    471 |         471 |         20 |           s := s + 1;
6619    472 |         472 |         20 |           s := s + 1;
6620    473 |         473 |         20 |           s := s + 1;
6621    474 |         474 |         20 |           s := s + 1;
6622    475 |         475 |         20 |           s := s + 1;
6623    476 |         476 |         20 |           s := s + 1;
6624    477 |         477 |         20 |           s := s + 1;
6625    478 |         478 |         20 |           s := s + 1;
6626    479 |         479 |         20 |           s := s + 1;
6627    480 |         480 |         20 |           s := s + 1;
6628    481 |         481 |         20 |           s := s + 1;
6629    482 |         482 |         20 |           s := s + 1;
6630    483 |         483 |         20 |           s := s + 1;
6631    484 |         484 |         20 |           s := s + 1;
6632    485 |         485 |         20 |           s := s + 1;
6633    486 |         486 |         20 |           s := s + 1;
6634    487 |         487 |         20 |           s := s + 1;
6635    488 |         488 |         20 |           s := s + 1;
6636    489 |         489 |         20 |           s := s + 1;
6637    490 |         490 |         20 |           s := s + 1;
6638    491 |         491 |         20 |           s := s + 1;
6639    492 |         492 |         20 |           s := s + 1;
6640    493 |         493 |         20 |           s := s + 1;
6641    494 |         494 |         20 |           s := s + 1;
6642    495 |         495 |         20 |           s := s + 1;
6643    496 |         496 |         20 |           s := s + 1;
6644    497 |         497 |         20 |           s := s + 1;
6645    498 |         498 |         20 |           s := s + 1;
6646    499 |         499 |         20 |           s := s + 1;
6647    500 |         500 |         20 |           s := s + 1;
6648    501 |         501 |         20 |           s := s + 1;
6649    502 |         502 |         20 |           s := s + 1;
6650    503 |         503 |         20 |           s := s + 1;
6651    504 |         504 |         20 |           s := s + 1;
6652    505 |         505 |         20 |           s := s + 1;
6653    506 |         506 |         20 |           s := s + 1;
6654    507 |         507 |         20 |           s := s + 1;
6655    508 |         508 |         20 |           s := s + 1;
6656    509 |         509 |         20 |           s := s + 1;
6657    510 |         510 |         20 |           s := s + 1;
6658    511 |         511 |         20 |           s := s + 1;
6659    512 |         512 |         20 |           s := s + 1;
6660    513 |         513 |         20 |           s := s + 1;
6661    514 |         514 |         20 |           s := s + 1;
6662    515 |         515 |         20 |           s := s + 1;
6663    516 |         516 |         20 |           s := s + 1;
6664    517 |         517 |         20 |           s := s + 1;
6665    518 |         518 |         20 |           s := s + 1;
6666    519 |         519 |         20 |           s := s + 1;
6667    520 |         520 |         20 |           s := s + 1;
6668    521 |         521 |         20 |           s := s + 1;
6669    522 |         522 |         20 |           s := s + 1;
6670    523 |         523 |         20 |           s := s + 1;
6671    524 |         524 |         20 |           s := s + 1;
6672    525 |         525 |         20 |           s := s + 1;
6673    526 |         526 |         20 |           s := s + 1;
6674    527 |         527 |         20 |           s := s + 1;
6675    528 |         528 |         20 |           s := s + 1;
6676    529 |         529 |         20 |           s := s + 1;
6677    530 |         530 |         20 |           s := s + 1;
6678    531 |         531 |         20 |           s := s + 1;
6679    532 |         532 |         20 |           s := s + 1;
6680    533 |         533 |         20 |           s := s + 1;
6681    534 |         534 |         20 |           s := s + 1;
6682    535 |         535 |         20 |           s := s + 1;
6683    536 |         536 |         20 |           s := s + 1;
6684    537 |         537 |         20 |           s := s + 1;
6685    538 |         538 |         20 |           s := s + 1;
6686    539 |         539 |         20 |           s := s + 1;
6687    540 |         540 |         20 |           s := s + 1;
6688    541 |         541 |         20 |           s := s + 1;
6689    542 |         542 |         20 |           s := s + 1;
6690    543 |         543 |         20 |           s := s + 1;
6691    544 |         544 |         20 |           s := s + 1;
6692    545 |         545 |         20 |           s := s + 1;
6693    546 |         546 |         20 |           s := s + 1;
6694    547 |         547 |         20 |           s := s + 1;
6695    548 |         548 |         20 |           s := s + 1;
6696    549 |         549 |         20 |           s := s + 1;
6697    550 |         550 |         20 |           s := s + 1;
6698    551 |         551 |         20 |           s := s + 1;
6699    552 |         552 |         20 |           s := s + 1;
6700    553 |         553 |         20 |           s := s + 1;
6701    554 |         554 |         20 |           s := s + 1;
6702    555 |         555 |         20 |           s := s + 1;
6703    556 |         556 |         20 |           s := s + 1;
6704    557 |         557 |         20 |           s := s + 1;
6705    558 |         558 |         20 |           s := s + 1;
6706    559 |         559 |         20 |           s := s + 1;
6707    560 |         560 |         20 |           s := s + 1;
6708    561 |         561 |         20 |           s := s + 1;
6709    562 |         562 |         20 |           s := s + 1;
6710    563 |         563 |         20 |           s := s + 1;
6711    564 |         564 |         20 |           s := s + 1;
6712    565 |         565 |         20 |           s := s + 1;
6713    566 |         566 |         20 |           s := s + 1;
6714    567 |         567 |         20 |           s := s + 1;
6715    568 |         568 |         20 |           s := s + 1;
6716    569 |         569 |         20 |           s := s + 1;
6717    570 |         570 |         20 |           s := s + 1;
6718    571 |         571 |         20 |           s := s + 1;
6719    572 |         572 |         20 |           s := s + 1;
6720    573 |         573 |         20 |           s := s + 1;
6721    574 |         574 |         20 |           s := s + 1;
6722    575 |         575 |         20 |           s := s + 1;
6723    576 |         576 |         20 |           s := s + 1;
6724    577 |         577 |         20 |           s := s + 1;
6725    578 |         578 |         20 |           s := s + 1;
6726    579 |         579 |         20 |           s := s + 1;
6727    580 |         580 |         20 |           s := s + 1;
6728    581 |         581 |         20 |           s := s + 1;
6729    582 |         582 |         20 |           s := s + 1;
6730    583 |         583 |         20 |           s := s + 1;
6731    584 |         584 |         20 |           s := s + 1;
6732    585 |         585 |         20 |           s := s + 1;
6733    586 |         586 |         20 |           s := s + 1;
6734    587 |         587 |         20 |           s := s + 1;
6735    588 |         588 |         20 |           s := s + 1;
6736    589 |         589 |         20 |           s := s + 1;
6737    590 |         590 |         20 |           s := s + 1;
6738    591 |         591 |         20 |           s := s + 1;
6739    592 |         592 |         20 |           s := s + 1;
6740    593 |         593 |         20 |           s := s + 1;
6741    594 |         594 |         20 |           s := s + 1;
6742    595 |         595 |         20 |           s := s + 1;
6743    596 |         596 |         20 |           s := s + 1;
6744    597 |         597 |         20 |           s := s + 1;
6745    598 |         598 |         20 |           s := s + 1;
6746    599 |         599 |         20 |           s := s + 1;
6747    600 |         600 |         20 |           s := s + 1;
6748    601 |         601 |         20 |           s := s + 1;
6749    602 |         602 |         20 |           s := s + 1;
6750    603 |         603 |         20 |           s := s + 1;
6751    604 |         604 |         20 |           s := s + 1;
6752    605 |         605 |         20 |           s := s + 1;
6753    606 |         606 |         20 |           s := s + 1;
6754    607 |         607 |         20 |           s := s + 1;
6755    608 |         608 |         20 |           s := s + 1;
6756    609 |         609 |         20 |           s := s + 1;
6757    610 |         610 |         20 |           s := s + 1;
6758    611 |         611 |         20 |           s := s + 1;
6759    612 |         612 |         20 |           s := s + 1;
6760    613 |         613 |         20 |           s := s + 1;
6761    614 |         614 |         20 |           s := s + 1;
6762    615 |         615 |         20 |           s := s + 1;
6763    616 |         616 |         20 |           s := s + 1;
6764    617 |         617 |         20 |           s := s + 1;
6765    618 |         618 |         20 |           s := s + 1;
6766    619 |         619 |         20 |           s := s + 1;
6767    620 |         620 |         20 |           s := s + 1;
6768    621 |         621 |         20 |           s := s + 1;
6769    622 |         622 |         20 |           s := s + 1;
6770    623 |         623 |         20 |           s := s + 1;
6771    624 |         624 |         20 |           s := s + 1;
6772    625 |         625 |         20 |           s := s + 1;
6773    626 |         626 |         20 |           s := s + 1;
6774    627 |         627 |         20 |           s := s + 1;
6775    628 |         628 |         20 |           s := s + 1;
6776    629 |         629 |         20 |           s := s + 1;
6777    630 |         630 |         20 |           s := s + 1;
6778    631 |         631 |         20 |           s := s + 1;
6779    632 |         632 |         20 |           s := s + 1;
6780    633 |         633 |         20 |           s := s + 1;
6781    634 |         634 |         20 |           s := s + 1;
6782    635 |         635 |         20 |           s := s + 1;
6783    636 |         636 |         20 |           s := s + 1;
6784    637 |         637 |         20 |           s := s + 1;
6785    638 |         638 |         20 |           s := s + 1;
6786    639 |         639 |         20 |           s := s + 1;
6787    640 |         640 |         20 |           s := s + 1;
6788    641 |         641 |         20 |           s := s + 1;
6789    642 |         642 |         20 |           s := s + 1;
6790    643 |         643 |         20 |           s := s + 1;
6791    644 |         644 |         20 |           s := s + 1;
6792    645 |         645 |         20 |           s := s + 1;
6793    646 |         646 |         20 |           s := s + 1;
6794    647 |         647 |         20 |           s := s + 1;
6795    648 |         648 |         20 |           s := s + 1;
6796    649 |         649 |         20 |           s := s + 1;
6797    650 |         650 |         20 |           s := s + 1;
6798    651 |         651 |         20 |           s := s + 1;
6799    652 |         652 |         20 |           s := s + 1;
6800    653 |         653 |         20 |           s := s + 1;
6801    654 |         654 |         20 |           s := s + 1;
6802    655 |         655 |         20 |           s := s + 1;
6803    656 |         656 |         20 |           s := s + 1;
6804    657 |         657 |         20 |           s := s + 1;
6805    658 |         658 |         20 |           s := s + 1;
6806    659 |         659 |         20 |           s := s + 1;
6807    660 |         660 |         20 |           s := s + 1;
6808    661 |         661 |         20 |           s := s + 1;
6809    662 |         662 |         20 |           s := s + 1;
6810    663 |         663 |         20 |           s := s + 1;
6811    664 |         664 |         20 |           s := s + 1;
6812    665 |         665 |         20 |           s := s + 1;
6813    666 |         666 |         20 |           s := s + 1;
6814    667 |         667 |         20 |           s := s + 1;
6815    668 |         668 |         20 |           s := s + 1;
6816    669 |         669 |         20 |           s := s + 1;
6817    670 |         670 |         20 |           s := s + 1;
6818    671 |         671 |         20 |           s := s + 1;
6819    672 |         672 |         20 |           s := s + 1;
6820    673 |         673 |         20 |           s := s + 1;
6821    674 |         674 |         20 |           s := s + 1;
6822    675 |         675 |         20 |           s := s + 1;
6823    676 |         676 |         20 |           s := s + 1;
6824    677 |         677 |         20 |           s := s + 1;
6825    678 |         678 |         20 |           s := s + 1;
6826    679 |         679 |         20 |           s := s + 1;
6827    680 |         680 |         20 |           s := s + 1;
6828    681 |         681 |         20 |           s := s + 1;
6829    682 |         682 |         20 |           s := s + 1;
6830    683 |         683 |         20 |           s := s + 1;
6831    684 |         684 |         20 |           s := s + 1;
6832    685 |         685 |         20 |           s := s + 1;
6833    686 |         686 |         20 |           s := s + 1;
6834    687 |         687 |         20 |           s := s + 1;
6835    688 |         688 |         20 |           s := s + 1;
6836    689 |         689 |         20 |           s := s + 1;
6837    690 |         690 |         20 |           s := s + 1;
6838    691 |         691 |         20 |           s := s + 1;
6839    692 |         692 |         20 |           s := s + 1;
6840    693 |         693 |         20 |           s := s + 1;
6841    694 |         694 |         20 |           s := s + 1;
6842    695 |         695 |         20 |           s := s + 1;
6843    696 |         696 |         20 |           s := s + 1;
6844    697 |         697 |         20 |           s := s + 1;
6845    698 |         698 |         20 |           s := s + 1;
6846    699 |         699 |         20 |           s := s + 1;
6847    700 |         700 |         20 |           s := s + 1;
6848    701 |         701 |         20 |           s := s + 1;
6849    702 |         702 |         20 |           s := s + 1;
6850    703 |         703 |         20 |           s := s + 1;
6851    704 |         704 |         20 |           s := s + 1;
6852    705 |         705 |         20 |           s := s + 1;
6853    706 |         706 |         20 |           s := s + 1;
6854    707 |         707 |         20 |           s := s + 1;
6855    708 |         708 |         20 |           s := s + 1;
6856    709 |         709 |         20 |           s := s + 1;
6857    710 |         710 |         20 |           s := s + 1;
6858    711 |         711 |         20 |           s := s + 1;
6859    712 |         712 |         20 |           s := s + 1;
6860    713 |         713 |         20 |           s := s + 1;
6861    714 |         714 |         20 |           s := s + 1;
6862    715 |         715 |         20 |           s := s + 1;
6863    716 |         716 |         20 |           s := s + 1;
6864    717 |         717 |         20 |           s := s + 1;
6865    718 |         718 |         20 |           s := s + 1;
6866    719 |         719 |         20 |           s := s + 1;
6867    720 |         720 |         20 |           s := s + 1;
6868    721 |         721 |         20 |           s := s + 1;
6869    722 |         722 |         20 |           s := s + 1;
6870    723 |         723 |         20 |           s := s + 1;
6871    724 |         724 |         20 |           s := s + 1;
6872    725 |         725 |         20 |           s := s + 1;
6873    726 |         726 |         20 |           s := s + 1;
6874    727 |         727 |         20 |           s := s + 1;
6875    728 |         728 |         20 |           s := s + 1;
6876    729 |         729 |         20 |           s := s + 1;
6877    730 |         730 |         20 |           s := s + 1;
6878    731 |         731 |         20 |           s := s + 1;
6879    732 |         732 |         20 |           s := s + 1;
6880    733 |         733 |         20 |           s := s + 1;
6881    734 |         734 |         20 |           s := s + 1;
6882    735 |         735 |         20 |           s := s + 1;
6883    736 |         736 |         20 |           s := s + 1;
6884    737 |         737 |         20 |           s := s + 1;
6885    738 |         738 |         20 |           s := s + 1;
6886    739 |         739 |         20 |           s := s + 1;
6887    740 |         740 |         20 |           s := s + 1;
6888    741 |         741 |         20 |           s := s + 1;
6889    742 |         742 |         20 |           s := s + 1;
6890    743 |         743 |         20 |           s := s + 1;
6891    744 |         744 |         20 |           s := s + 1;
6892    745 |         745 |         20 |           s := s + 1;
6893    746 |         746 |         20 |           s := s + 1;
6894    747 |         747 |         20 |           s := s + 1;
6895    748 |         748 |         20 |           s := s + 1;
6896    749 |         749 |         20 |           s := s + 1;
6897    750 |         750 |         20 |           s := s + 1;
6898    751 |         751 |         20 |           s := s + 1;
6899    752 |         752 |         20 |           s := s + 1;
6900    753 |         753 |         20 |           s := s + 1;
6901    754 |         754 |         20 |           s := s + 1;
6902    755 |         755 |         20 |           s := s + 1;
6903    756 |         756 |         20 |           s := s + 1;
6904    757 |         757 |         20 |           s := s + 1;
6905    758 |         758 |         20 |           s := s + 1;
6906    759 |         759 |         20 |           s := s + 1;
6907    760 |         760 |         20 |           s := s + 1;
6908    761 |         761 |         20 |           s := s + 1;
6909    762 |         762 |         20 |           s := s + 1;
6910    763 |         763 |         20 |           s := s + 1;
6911    764 |         764 |         20 |           s := s + 1;
6912    765 |         765 |         20 |           s := s + 1;
6913    766 |         766 |         20 |           s := s + 1;
6914    767 |         767 |         20 |           s := s + 1;
6915    768 |         768 |         20 |           s := s + 1;
6916    769 |         769 |         20 |           s := s + 1;
6917    770 |         770 |         20 |           s := s + 1;
6918    771 |         771 |         20 |           s := s + 1;
6919    772 |         772 |         20 |           s := s + 1;
6920    773 |         773 |         20 |           s := s + 1;
6921    774 |         774 |         20 |           s := s + 1;
6922    775 |         775 |         20 |           s := s + 1;
6923    776 |         776 |         20 |           s := s + 1;
6924    777 |         777 |         20 |           s := s + 1;
6925    778 |         778 |         20 |           s := s + 1;
6926    779 |         779 |         20 |           s := s + 1;
6927    780 |         780 |         20 |           s := s + 1;
6928    781 |         781 |         20 |           s := s + 1;
6929    782 |         782 |         20 |           s := s + 1;
6930    783 |         783 |         20 |           s := s + 1;
6931    784 |         784 |         20 |           s := s + 1;
6932    785 |         785 |         20 |           s := s + 1;
6933    786 |         786 |         20 |           s := s + 1;
6934    787 |         787 |         20 |           s := s + 1;
6935    788 |         788 |         20 |           s := s + 1;
6936    789 |         789 |         20 |           s := s + 1;
6937    790 |         790 |         20 |           s := s + 1;
6938    791 |         791 |         20 |           s := s + 1;
6939    792 |         792 |         20 |           s := s + 1;
6940    793 |         793 |         20 |           s := s + 1;
6941    794 |         794 |         20 |           s := s + 1;
6942    795 |         795 |         20 |           s := s + 1;
6943    796 |         796 |         20 |           s := s + 1;
6944    797 |         797 |         20 |           s := s + 1;
6945    798 |         798 |         20 |           s := s + 1;
6946    799 |         799 |         20 |           s := s + 1;
6947    800 |         800 |         20 |           s := s + 1;
6948    801 |         801 |         20 |           s := s + 1;
6949    802 |         802 |         20 |           s := s + 1;
6950    803 |         803 |         20 |           s := s + 1;
6951    804 |         804 |         20 |           s := s + 1;
6952    805 |         805 |         20 |           s := s + 1;
6953    806 |         806 |         20 |           s := s + 1;
6954    807 |         807 |         20 |           s := s + 1;
6955    808 |         808 |         20 |           s := s + 1;
6956    809 |         809 |         20 |           s := s + 1;
6957    810 |         810 |         20 |           s := s + 1;
6958    811 |         811 |         20 |           s := s + 1;
6959    812 |         812 |         20 |           s := s + 1;
6960    813 |         813 |         20 |           s := s + 1;
6961    814 |         814 |         20 |           s := s + 1;
6962    815 |         815 |         20 |           s := s + 1;
6963    816 |         816 |         20 |           s := s + 1;
6964    817 |         817 |         20 |           s := s + 1;
6965    818 |         818 |         20 |           s := s + 1;
6966    819 |         819 |         20 |           s := s + 1;
6967    820 |         820 |         20 |           s := s + 1;
6968    821 |         821 |         20 |           s := s + 1;
6969    822 |         822 |         20 |           s := s + 1;
6970    823 |         823 |         20 |           s := s + 1;
6971    824 |         824 |         20 |           s := s + 1;
6972    825 |         825 |         20 |           s := s + 1;
6973    826 |         826 |         20 |           s := s + 1;
6974    827 |         827 |         20 |           s := s + 1;
6975    828 |         828 |         20 |           s := s + 1;
6976    829 |         829 |         20 |           s := s + 1;
6977    830 |         830 |         20 |           s := s + 1;
6978    831 |         831 |         20 |           s := s + 1;
6979    832 |         832 |         20 |           s := s + 1;
6980    833 |         833 |         20 |           s := s + 1;
6981    834 |         834 |         20 |           s := s + 1;
6982    835 |         835 |         20 |           s := s + 1;
6983    836 |         836 |         20 |           s := s + 1;
6984    837 |         837 |         20 |           s := s + 1;
6985    838 |         838 |         20 |           s := s + 1;
6986    839 |         839 |         20 |           s := s + 1;
6987    840 |         840 |         20 |           s := s + 1;
6988    841 |         841 |         20 |           s := s + 1;
6989    842 |         842 |         20 |           s := s + 1;
6990    843 |         843 |         20 |           s := s + 1;
6991    844 |         844 |         20 |           s := s + 1;
6992    845 |         845 |         20 |           s := s + 1;
6993    846 |         846 |         20 |           s := s + 1;
6994    847 |         847 |         20 |           s := s + 1;
6995    848 |         848 |         20 |           s := s + 1;
6996    849 |         849 |         20 |           s := s + 1;
6997    850 |         850 |         20 |           s := s + 1;
6998    851 |         851 |         20 |           s := s + 1;
6999    852 |         852 |         20 |           s := s + 1;
7000    853 |         853 |         20 |           s := s + 1;
7001    854 |         854 |         20 |           s := s + 1;
7002    855 |         855 |         20 |           s := s + 1;
7003    856 |         856 |         20 |           s := s + 1;
7004    857 |         857 |         20 |           s := s + 1;
7005    858 |         858 |         20 |           s := s + 1;
7006    859 |         859 |         20 |           s := s + 1;
7007    860 |         860 |         20 |           s := s + 1;
7008    861 |         861 |         20 |           s := s + 1;
7009    862 |         862 |         20 |           s := s + 1;
7010    863 |         863 |         20 |           s := s + 1;
7011    864 |         864 |         20 |           s := s + 1;
7012    865 |         865 |         20 |           s := s + 1;
7013    866 |         866 |         20 |           s := s + 1;
7014    867 |         867 |         20 |           s := s + 1;
7015    868 |         868 |         20 |           s := s + 1;
7016    869 |         869 |         20 |           s := s + 1;
7017    870 |         870 |         20 |           s := s + 1;
7018    871 |         871 |         20 |           s := s + 1;
7019    872 |         872 |         20 |           s := s + 1;
7020    873 |         873 |         20 |           s := s + 1;
7021    874 |         874 |         20 |           s := s + 1;
7022    875 |         875 |         20 |           s := s + 1;
7023    876 |         876 |         20 |           s := s + 1;
7024    877 |         877 |         20 |           s := s + 1;
7025    878 |         878 |         20 |           s := s + 1;
7026    879 |         879 |         20 |           s := s + 1;
7027    880 |         880 |         20 |           s := s + 1;
7028    881 |         881 |         20 |           s := s + 1;
7029    882 |         882 |         20 |           s := s + 1;
7030    883 |         883 |         20 |           s := s + 1;
7031    884 |         884 |         20 |           s := s + 1;
7032    885 |         885 |         20 |           s := s + 1;
7033    886 |         886 |         20 |           s := s + 1;
7034    887 |         887 |         20 |           s := s + 1;
7035    888 |         888 |         20 |           s := s + 1;
7036    889 |         889 |         20 |           s := s + 1;
7037    890 |         890 |         20 |           s := s + 1;
7038    891 |         891 |         20 |           s := s + 1;
7039    892 |         892 |         20 |           s := s + 1;
7040    893 |         893 |         20 |           s := s + 1;
7041    894 |         894 |         20 |           s := s + 1;
7042    895 |         895 |         20 |           s := s + 1;
7043    896 |         896 |         20 |           s := s + 1;
7044    897 |         897 |         20 |           s := s + 1;
7045    898 |         898 |         20 |           s := s + 1;
7046    899 |         899 |         20 |           s := s + 1;
7047    900 |         900 |         20 |           s := s + 1;
7048    901 |         901 |         20 |           s := s + 1;
7049    902 |         902 |         20 |           s := s + 1;
7050    903 |         903 |         20 |           s := s + 1;
7051    904 |         904 |         20 |           s := s + 1;
7052    905 |         905 |         20 |           s := s + 1;
7053    906 |         906 |         20 |           s := s + 1;
7054    907 |         907 |         20 |           s := s + 1;
7055    908 |         908 |         20 |           s := s + 1;
7056    909 |         909 |         20 |           s := s + 1;
7057    910 |         910 |         20 |           s := s + 1;
7058    911 |         911 |         20 |           s := s + 1;
7059    912 |         912 |         20 |           s := s + 1;
7060    913 |         913 |         20 |           s := s + 1;
7061    914 |         914 |         20 |           s := s + 1;
7062    915 |         915 |         20 |           s := s + 1;
7063    916 |         916 |         20 |           s := s + 1;
7064    917 |         917 |         20 |           s := s + 1;
7065    918 |         918 |         20 |           s := s + 1;
7066    919 |         919 |         20 |           s := s + 1;
7067    920 |         920 |         20 |           s := s + 1;
7068    921 |         921 |         20 |           s := s + 1;
7069    922 |         922 |         20 |           s := s + 1;
7070    923 |         923 |         20 |           s := s + 1;
7071    924 |         924 |         20 |           s := s + 1;
7072    925 |         925 |         20 |           s := s + 1;
7073    926 |         926 |         20 |           s := s + 1;
7074    927 |         927 |         20 |           s := s + 1;
7075    928 |         928 |         20 |           s := s + 1;
7076    929 |         929 |         20 |           s := s + 1;
7077    930 |         930 |         20 |           s := s + 1;
7078    931 |         931 |         20 |           s := s + 1;
7079    932 |         932 |         20 |           s := s + 1;
7080    933 |         933 |         20 |           s := s + 1;
7081    934 |         934 |         20 |           s := s + 1;
7082    935 |         935 |         20 |           s := s + 1;
7083    936 |         936 |         20 |           s := s + 1;
7084    937 |         937 |         20 |           s := s + 1;
7085    938 |         938 |         20 |           s := s + 1;
7086    939 |         939 |         20 |           s := s + 1;
7087    940 |         940 |         20 |           s := s + 1;
7088    941 |         941 |         20 |           s := s + 1;
7089    942 |         942 |         20 |           s := s + 1;
7090    943 |         943 |         20 |           s := s + 1;
7091    944 |         944 |         20 |           s := s + 1;
7092    945 |         945 |         20 |           s := s + 1;
7093    946 |         946 |         20 |           s := s + 1;
7094    947 |         947 |         20 |           s := s + 1;
7095    948 |         948 |         20 |           s := s + 1;
7096    949 |         949 |         20 |           s := s + 1;
7097    950 |         950 |         20 |           s := s + 1;
7098    951 |         951 |         20 |           s := s + 1;
7099    952 |         952 |         20 |           s := s + 1;
7100    953 |         953 |         20 |           s := s + 1;
7101    954 |         954 |         20 |           s := s + 1;
7102    955 |         955 |         20 |           s := s + 1;
7103    956 |         956 |         20 |           s := s + 1;
7104    957 |         957 |         20 |           s := s + 1;
7105    958 |         958 |         20 |           s := s + 1;
7106    959 |         959 |         20 |           s := s + 1;
7107    960 |         960 |         20 |           s := s + 1;
7108    961 |         961 |         20 |           s := s + 1;
7109    962 |         962 |         20 |           s := s + 1;
7110    963 |         963 |         20 |           s := s + 1;
7111    964 |         964 |         20 |           s := s + 1;
7112    965 |         965 |         20 |           s := s + 1;
7113    966 |         966 |         20 |           s := s + 1;
7114    967 |         967 |         20 |           s := s + 1;
7115    968 |         968 |         20 |           s := s + 1;
7116    969 |         969 |         20 |           s := s + 1;
7117    970 |         970 |         20 |           s := s + 1;
7118    971 |         971 |         20 |           s := s + 1;
7119    972 |         972 |         20 |           s := s + 1;
7120    973 |         973 |         20 |           s := s + 1;
7121    974 |         974 |         20 |           s := s + 1;
7122    975 |         975 |         20 |           s := s + 1;
7123    976 |         976 |         20 |           s := s + 1;
7124    977 |         977 |         20 |           s := s + 1;
7125    978 |         978 |         20 |           s := s + 1;
7126    979 |         979 |         20 |           s := s + 1;
7127    980 |         980 |         20 |           s := s + 1;
7128    981 |         981 |         20 |           s := s + 1;
7129    982 |         982 |         20 |           s := s + 1;
7130    983 |         983 |         20 |           s := s + 1;
7131    984 |         984 |         20 |           s := s + 1;
7132    985 |         985 |         20 |           s := s + 1;
7133    986 |         986 |         20 |           s := s + 1;
7134    987 |         987 |         20 |           s := s + 1;
7135    988 |         988 |         20 |           s := s + 1;
7136    989 |         989 |         20 |           s := s + 1;
7137    990 |         990 |         20 |           s := s + 1;
7138    991 |         991 |         20 |           s := s + 1;
7139    992 |         992 |         20 |           s := s + 1;
7140    993 |         993 |         20 |           s := s + 1;
7141    994 |         994 |         20 |           s := s + 1;
7142    995 |         995 |         20 |           s := s + 1;
7143    996 |         996 |         20 |           s := s + 1;
7144    997 |         997 |         20 |           s := s + 1;
7145    998 |         998 |         20 |           s := s + 1;
7146    999 |         999 |         20 |           s := s + 1;
7147   1000 |        1000 |         20 |           s := s + 1;
7148   1001 |        1001 |         20 |           s := s + 1;
7149   1002 |        1002 |         20 |           s := s + 1;
7150   1003 |        1003 |         20 |           s := s + 1;
7151   1004 |        1004 |         20 |           s := s + 1;
7152   1005 |        1005 |         20 |           s := s + 1;
7153   1006 |        1006 |         20 |           s := s + 1;
7154   1007 |        1007 |         20 |           s := s + 1;
7155   1008 |        1008 |         20 |           s := s + 1;
7156   1009 |        1009 |         20 |           s := s + 1;
7157   1010 |        1010 |         20 |           s := s + 1;
7158   1011 |        1011 |         20 |           s := s + 1;
7159   1012 |        1012 |         20 |           s := s + 1;
7160   1013 |        1013 |         20 |           s := s + 1;
7161   1014 |        1014 |         20 |           s := s + 1;
7162   1015 |        1015 |         20 |           s := s + 1;
7163   1016 |        1016 |         20 |           s := s + 1;
7164   1017 |        1017 |         20 |           s := s + 1;
7165   1018 |        1018 |         20 |           s := s + 1;
7166   1019 |        1019 |         20 |           s := s + 1;
7167   1020 |        1020 |         20 |           s := s + 1;
7168   1021 |        1021 |         20 |           s := s + 1;
7169   1022 |        1022 |         20 |           s := s + 1;
7170   1023 |        1023 |         20 |           s := s + 1;
7171   1024 |        1024 |         20 |           s := s + 1;
7172   1025 |        1025 |         20 |           s := s + 1;
7173   1026 |        1026 |         20 |           s := s + 1;
7174   1027 |        1027 |         20 |           s := s + 1;
7175   1028 |        1028 |         20 |           s := s + 1;
7176   1029 |        1029 |         20 |           s := s + 1;
7177   1030 |        1030 |         20 |           s := s + 1;
7178   1031 |        1031 |         20 |           s := s + 1;
7179   1032 |        1032 |         20 |           s := s + 1;
7180   1033 |        1033 |         20 |           s := s + 1;
7181   1034 |        1034 |         20 |           s := s + 1;
7182   1035 |        1035 |         20 |           s := s + 1;
7183   1036 |        1036 |         20 |           s := s + 1;
7184   1037 |        1037 |         20 |           s := s + 1;
7185   1038 |             |            |         end loop;
7186   1039 |             |            |       end loop;
7187   1040 |        1040 |         20 |       j := j + 1;
7188   1041 |             |            |     end loop;
7189   1042 |             |            |   exception when others then
7190   1043 |        1043 |          0 |     raise 'reraised exception %', sqlerrm;
7191   1044 |             |            |   end;
7192   1045 |        1045 |          2 |   return $1;
7193   1046 |             |            | end;
7194(1046 rows)
7195
7196select funcoid, exec_count from plpgsql_profiler_functions_all();
7197     funcoid     | exec_count
7198-----------------+------------
7199 longfx(integer) |          2
7200(1 row)
7201
7202create table testr(a int);
7203create rule testr_rule as on insert to testr do nothing;
7204create or replace function fx_testr()
7205returns void as $$
7206begin
7207  insert into testr values(20);
7208end;
7209$$ language plpgsql;
7210-- allow some rules on tables
7211select fx_testr();
7212 fx_testr
7213----------
7214
7215(1 row)
7216
7217select * from plpgsql_check_function_tb('fx_testr');
7218 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
7219------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
7220(0 rows)
7221
7222drop function fx_testr();
7223drop table testr;
7224-- coverage tests
7225set plpgsql_check.profiler to on;
7226create or replace function covtest(int)
7227returns int as $$
7228declare a int = $1;
7229begin
7230  a := a + 1;
7231  if a < 10 then
7232    a := a + 1;
7233  end if;
7234  a := a + 1;
7235  return a;
7236end;
7237$$ language plpgsql;
7238set plpgsql_check.profiler to on;
7239select covtest(10);
7240 covtest
7241---------
7242      12
7243(1 row)
7244
7245select stmtid, exec_stmts, stmtname from plpgsql_profiler_function_statements_tb('covtest');
7246 stmtid | exec_stmts |    stmtname
7247--------+------------+-----------------
7248      0 |          1 | statement block
7249      1 |          1 | assignment
7250      2 |          1 | IF
7251      3 |          0 | assignment
7252      4 |          1 | assignment
7253      5 |          1 | RETURN
7254(6 rows)
7255
7256select plpgsql_coverage_statements('covtest');
7257 plpgsql_coverage_statements
7258-----------------------------
7259          0.8333333333333334
7260(1 row)
7261
7262select plpgsql_coverage_branches('covtest');
7263 plpgsql_coverage_branches
7264---------------------------
7265                       0.5
7266(1 row)
7267
7268select covtest(1);
7269 covtest
7270---------
7271       4
7272(1 row)
7273
7274select stmtid, exec_stmts, stmtname from plpgsql_profiler_function_statements_tb('covtest');
7275 stmtid | exec_stmts |    stmtname
7276--------+------------+-----------------
7277      0 |          2 | statement block
7278      1 |          2 | assignment
7279      2 |          2 | IF
7280      3 |          1 | assignment
7281      4 |          2 | assignment
7282      5 |          2 | RETURN
7283(6 rows)
7284
7285select plpgsql_coverage_statements('covtest');
7286 plpgsql_coverage_statements
7287-----------------------------
7288                           1
7289(1 row)
7290
7291select plpgsql_coverage_branches('covtest');
7292 plpgsql_coverage_branches
7293---------------------------
7294                         1
7295(1 row)
7296
7297set plpgsql_check.profiler to off;
7298create or replace function f() returns void as $$
7299declare
7300  r1 record;
7301  r2 record;
7302begin
7303  select 10 as a, 20 as b into r1;
7304  r2 := json_populate_record(r1, '{}');
7305  raise notice '%', r2.a;
7306end;
7307$$ language plpgsql;
7308select * from plpgsql_check_function('f');
7309 plpgsql_check_function
7310------------------------
7311(0 rows)
7312
7313-- fix issue #63
7314create or replace function distinct_array(arr anyarray) returns anyarray as $$
7315begin
7316  return array(select distinct e from unnest(arr) as e);
7317end;
7318$$ language plpgsql immutable;
7319select plpgsql_check_function('distinct_array(anyarray)');
7320 plpgsql_check_function
7321------------------------
7322(0 rows)
7323
7324drop function distinct_array(anyarray);
7325-- tracer test
7326set plpgsql_check.enable_tracer to on;
7327set plpgsql_check.tracer to on;
7328set plpgsql_check.tracer_test_mode = true;
7329\set VERBOSITY terse
7330create or replace function fxo(a int, b int, c date, d numeric)
7331returns void as $$
7332begin
7333  insert into tracer_tab values(a,b,c,d);
7334end;
7335$$ language plpgsql;
7336create table tracer_tab(a int, b int, c date, d numeric);
7337create or replace function tracer_tab_trg_fx()
7338returns trigger as $$
7339begin
7340  return new;
7341end;
7342$$ language plpgsql;
7343create trigger tracer_tab_trg before insert on tracer_tab for each row execute procedure tracer_tab_trg_fx();
7344select fxo(10,20,'20200815', 3.14);
7345NOTICE:  #0   ->> start of function fxo(integer,integer,date,numeric) (oid=0)
7346NOTICE:  #0       "a" => '10', "b" => '20', "c" => '08-15-2020', "d" => '3.14'
7347NOTICE:  #2     ->> start of function tracer_tab_trg_fx() (oid=0)
7348NOTICE:  #2          call by fxo(integer,integer,date,numeric) line 3 at SQL statement
7349NOTICE:  #2         triggered by before row insert trigger
7350NOTICE:  #2         "new" => '(10,20,08-15-2020,3.14)'
7351NOTICE:  #2     <<- end of function tracer_tab_trg_fx (elapsed time=0.010 ms)
7352NOTICE:  #0   <<- end of function fxo (elapsed time=0.010 ms)
7353 fxo
7354-----
7355
7356(1 row)
7357
7358select fxo(11,21,'20200816', 6.28);
7359NOTICE:  #0   ->> start of function fxo(integer,integer,date,numeric) (oid=0)
7360NOTICE:  #0       "a" => '11', "b" => '21', "c" => '08-16-2020', "d" => '6.28'
7361NOTICE:  #2     ->> start of function tracer_tab_trg_fx() (oid=0)
7362NOTICE:  #2          call by fxo(integer,integer,date,numeric) line 3 at SQL statement
7363NOTICE:  #2         triggered by before row insert trigger
7364NOTICE:  #2         "new" => '(11,21,08-16-2020,6.28)'
7365NOTICE:  #2     <<- end of function tracer_tab_trg_fx (elapsed time=0.010 ms)
7366NOTICE:  #0   <<- end of function fxo (elapsed time=0.010 ms)
7367 fxo
7368-----
7369
7370(1 row)
7371
7372set plpgsql_check.enable_tracer to off;
7373set plpgsql_check.tracer to off;
7374drop table tracer_tab cascade;
7375drop function tracer_tab_trg_fx();
7376drop function fxo(int, int, date, numeric);
7377create or replace function foo_trg_func()
7378returns trigger as $$
7379begin
7380  -- bad function, RETURN is missing
7381end;
7382$$ language plpgsql;
7383create table foo(a int);
7384create trigger foo_trg before insert for each row execute procedure foo_trg_func();
7385ERROR:  syntax error at or near "for" at character 38
7386-- should to print error
7387select * from plpgsql_check_function('foo_trg_func', 'foo');
7388                   plpgsql_check_function
7389------------------------------------------------------------
7390 error:2F005:control reached end of function without RETURN
7391(1 row)
7392
7393drop table foo;
7394drop function foo_trg_func();
7395-- check event trigger function
7396create or replace function f1() returns event_trigger as $$
7397BEGIN
7398    RAISE NOTICE 'test_event_trigger: % %', tg_event, tg_tag;
7399END
7400$$ language plpgsql;
7401select * from plpgsql_check_function_tb('f1()');
7402 functionid | lineno | statement | sqlstate | message | detail | hint | level | position | query | context
7403------------+--------+-----------+----------+---------+--------+------+-------+----------+-------+---------
7404(0 rows)
7405
7406-- should fail
7407create or replace function f1() returns event_trigger as $$
7408BEGIN
7409    RAISE NOTICE 'test_event_trigger: % %', tg_event, tg_tagX;
7410END
7411$$ language plpgsql;
7412select * from plpgsql_check_function_tb('f1()');
7413 functionid | lineno | statement | sqlstate |             message             | detail | hint | level | position |     query      | context
7414------------+--------+-----------+----------+---------------------------------+--------+------+-------+----------+----------------+---------
7415 f1         |      3 | RAISE     | 42703    | column "tg_tagx" does not exist |        |      | error |        8 | SELECT tg_tagX |
7416(1 row)
7417
7418drop function f1();
7419-- check event trigger function
7420create or replace function f1() returns event_trigger as $$
7421BEGIN
7422    RAISE NOTICE 'test_event_trigger: % %', tg_event, tg_tag;
7423END
7424$$ language plpgsql;
7425select * from plpgsql_check_function('f1()');
7426 plpgsql_check_function
7427------------------------
7428(0 rows)
7429
7430-- should fail
7431create or replace function f1() returns event_trigger as $$
7432BEGIN
7433    RAISE NOTICE 'test_event_trigger: % %', tg_event, tg_tagX;
7434END
7435$$ language plpgsql;
7436select * from plpgsql_check_function('f1()');
7437               plpgsql_check_function
7438-----------------------------------------------------
7439 error:42703:3:RAISE:column "tg_tagx" does not exist
7440 Query: SELECT tg_tagX
7441 --            ^
7442(3 rows)
7443
7444drop function f1();
7445create table t1tab(a int, b int);
7446create or replace function f1()
7447returns setof t1tab as $$
7448begin
7449  return next (10,20);
7450  return;
7451end;
7452$$ language plpgsql;
7453select * from plpgsql_check_function('f1()', performance_warnings => true);
7454                                 plpgsql_check_function
7455-----------------------------------------------------------------------------------------
7456 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
7457 Hint: When you fix this issue, please, recheck other functions that uses this function.
7458(2 rows)
7459
7460create or replace function f1()
7461returns setof t1tab as $$
7462begin
7463  return next (10::numeric,20);
7464  return;
7465end;
7466$$ language plpgsql;
7467select * from plpgsql_check_function('f1()', performance_warnings => true);
7468                               plpgsql_check_function
7469------------------------------------------------------------------------------------
7470 error:42804:3:RETURN NEXT:returned record type does not match expected record type
7471 Detail: Returned type numeric does not match expected type integer in column 1.
7472(2 rows)
7473
7474create or replace function f1()
7475returns setof t1tab as $$
7476declare a int; b int;
7477begin
7478  return next (a,b);
7479  return;
7480end;
7481$$ language plpgsql;
7482select * from plpgsql_check_function('f1()', performance_warnings => true);
7483                                 plpgsql_check_function
7484-----------------------------------------------------------------------------------------
7485 performance:00000:routine is marked as VOLATILE, should be IMMUTABLE
7486 Hint: When you fix this issue, please, recheck other functions that uses this function.
7487(2 rows)
7488
7489create or replace function f1()
7490returns setof t1tab as $$
7491declare a numeric; b int;
7492begin
7493  return next (a,b::numeric);
7494  return;
7495end;
7496$$ language plpgsql;
7497select * from plpgsql_check_function('f1()', performance_warnings => true);
7498                               plpgsql_check_function
7499------------------------------------------------------------------------------------
7500 error:42804:4:RETURN NEXT:returned record type does not match expected record type
7501 Detail: Returned type numeric does not match expected type integer in column 1.
7502(2 rows)
7503
7504drop function f1();
7505create table t1(a int, b int);
7506create or replace function fx()
7507returns t2 as $$
7508begin
7509  return (10,20,30)::t1;
7510end;
7511$$ language plpgsql;
7512select * from plpgsql_check_function('fx()', performance_warnings => true);
7513               plpgsql_check_function
7514----------------------------------------------------
7515 error:42846:3:RETURN:cannot cast type record to t1
7516 Query: SELECT (10,20,30)::t1
7517 --                      ^
7518 Detail: Input has too many columns.
7519(4 rows)
7520
7521drop function fx();
7522drop table t1tab;
7523drop table t1;
7524create or replace function fx()
7525returns void as $$
7526begin
7527  assert exists(select * from foo);
7528  assert false, (select boo from boo limit 1);
7529end;
7530$$ language plpgsql;
7531select * from plpgsql_check_function('fx()', fatal_errors => false);
7532               plpgsql_check_function
7533----------------------------------------------------
7534 error:42P01:3:ASSERT:relation "foo" does not exist
7535 Query: SELECT exists(select * from foo)
7536 --                                 ^
7537 error:42P01:4:ASSERT:relation "boo" does not exist
7538 Query: SELECT (select boo from boo limit 1)
7539 --                             ^
7540(6 rows)
7541
7542create or replace function ml_trg()
7543returns trigger as $$
7544#option dump
7545declare
7546begin
7547  if TG_OP = 'INSERT' then
7548    if NEW.status_from IS NULL then
7549      begin
7550        -- performance issue only
7551        select status into NEW.status_from
7552           from pa
7553          where pa_id = NEW.pa_id;
7554        -- nonexist target value
7555        select status into NEW.status_from_xxx
7556           from pa
7557          where pa_id = NEW.pa_id;
7558      exception
7559        when DATA_EXCEPTION then
7560          new.status_from := 'DE';
7561      end;
7562    end if;
7563  end if;
7564  if TG_OP = 'DELETE' then return OLD; else return NEW; end if;
7565exception
7566  when OTHERS then
7567    NULL;
7568    if TG_OP = 'DELETE' then return OLD; else return NEW; end if;
7569end;
7570$$ language plpgsql;
7571select * from plpgsql_check_function('ml_trg()', 'ml', performance_warnings := true);
7572                          plpgsql_check_function
7573--------------------------------------------------------------------------
7574 error:42703:13:SQL statement:record "new" has no field "status_from_xxx"
7575(1 row)
7576
7577create or replace function fx2()
7578returns void as $$
7579declare _pa pa;
7580begin
7581  select pa.id into _pa.id from pa limit 1;
7582  select pa.pa_id into _pa.pa_id from pa limit 1;
7583end;
7584$$ language plpgsql;
7585select * from plpgsql_check_function('fx2()', performance_warnings := true);
7586                 plpgsql_check_function
7587---------------------------------------------------------
7588 warning extra:00000:2:DECLARE:never read variable "_pa"
7589(1 row)
7590
7591drop function fx2();
7592create or replace function fx2()
7593returns void as $$
7594declare _pa pa;
7595begin
7596  _pa.id := (select pa.id from pa limit 1);
7597  _pa.pa_id := (select pa.pa_id from pa limit 1);
7598end;
7599$$ language plpgsql;
7600select * from plpgsql_check_function('fx2()', performance_warnings := true);
7601                 plpgsql_check_function
7602---------------------------------------------------------
7603 warning extra:00000:2:DECLARE:never read variable "_pa"
7604(1 row)
7605
7606drop function fx2();
7607create type _exception_type as (
7608  state text,
7609  message text,
7610  detail text);
7611create or replace function f1()
7612returns void as $$
7613declare
7614  _exception record;
7615begin
7616  _exception := NULL::_exception_type;
7617exception when others then
7618  get stacked diagnostics
7619        _exception.state = RETURNED_SQLSTATE,
7620        _exception.message = MESSAGE_TEXT,
7621        _exception.detail = PG_EXCEPTION_DETAIL,
7622        _exception.hint = PG_EXCEPTION_HINT;
7623end;
7624$$ language plpgsql;
7625select f1();
7626 f1
7627----
7628
7629(1 row)
7630
7631select * from plpgsql_check_function_tb('f1()');
7632 functionid | lineno |        statement        | sqlstate |                 message                 | detail | hint | level | position | query | context
7633------------+--------+-------------------------+----------+-----------------------------------------+--------+------+-------+----------+-------+---------
7634 f1         |      7 | GET STACKED DIAGNOSTICS | 42703    | record "_exception" has no field "hint" |        |      | error |          |       |
7635(1 row)
7636
7637create or replace function f1()
7638returns void as $$
7639declare
7640  _exception _exception_type;
7641begin
7642  _exception := NULL::_exception_type;
7643exception when others then
7644  get stacked diagnostics
7645        _exception.state = RETURNED_SQLSTATE,
7646        _exception.message = MESSAGE_TEXT,
7647        _exception.detail = PG_EXCEPTION_DETAIL;
7648end;
7649$$ language plpgsql;
7650select f1();
7651 f1
7652----
7653
7654(1 row)
7655
7656select * from plpgsql_check_function_tb('f1()');
7657 functionid | lineno | statement | sqlstate |             message              | detail | hint |     level     | position | query | context
7658------------+--------+-----------+----------+----------------------------------+--------+------+---------------+----------+-------+---------
7659 f1         |      3 | DECLARE   | 00000    | never read variable "_exception" |        |      | warning extra |          |       |
7660(1 row)
7661
7662drop function f1();
7663drop type _exception_type;
7664create type _exception_type as (
7665  state text,
7666  message text,
7667  detail text);
7668create or replace function f1()
7669returns void as $$
7670declare
7671  _exception record;
7672begin
7673  _exception := NULL::_exception_type;
7674exception when others then
7675  get stacked diagnostics
7676        _exception.state = RETURNED_SQLSTATE,
7677        _exception.message = MESSAGE_TEXT,
7678        _exception.detail = PG_EXCEPTION_DETAIL,
7679        _exception.hint = PG_EXCEPTION_HINT;
7680end;
7681$$ language plpgsql;
7682select f1();
7683 f1
7684----
7685
7686(1 row)
7687
7688select * from plpgsql_check_function('f1()');
7689                            plpgsql_check_function
7690-------------------------------------------------------------------------------
7691 error:42703:7:GET STACKED DIAGNOSTICS:record "_exception" has no field "hint"
7692(1 row)
7693
7694drop function f1();
7695drop type _exception_type;
7696create table footab(a int, b int, c int);
7697create or replace function footab_trig_func()
7698returns trigger as $$
7699declare x int;
7700begin
7701  if false then
7702    -- should be ok;
7703    select count(*) from newtab into x;
7704
7705    -- should fail;
7706    select count(*) from newtab where d = 10 into x;
7707  end if;
7708  return null;
7709end;
7710$$ language plpgsql;
7711select * from plpgsql_check_function('footab_trig_func','footab', newtable := 'newtab');
7712                plpgsql_check_function
7713-------------------------------------------------------
7714 error:42703:9:SQL statement:column "d" does not exist
7715 Query: select count(*) from newtab where d = 10
7716 --                                       ^
7717(3 rows)
7718
7719drop table footab;
7720drop function footab_trig_func();
7721create or replace function df1(anyelement)
7722returns anyelement as $$
7723begin
7724  return $1;
7725end;
7726$$ language plpgsql;
7727create or replace function df2(anyelement, jsonb)
7728returns anyelement as $$
7729begin
7730  return $1;
7731end;
7732$$ language plpgsql;
7733create or replace function t1()
7734returns void as $$
7735declare
7736  r record;
7737begin
7738  r := df1(r);
7739end;
7740$$ language plpgsql;
7741select * from plpgsql_check_function('t1()');
7742 plpgsql_check_function
7743------------------------
7744(0 rows)
7745
7746create or replace function t1()
7747returns void as $$
7748declare
7749  r record;
7750begin
7751  r := df2(r, '{}');
7752end;
7753$$ language plpgsql;
7754select * from plpgsql_check_function('t1()');
7755 plpgsql_check_function
7756------------------------
7757(0 rows)
7758
7759create or replace function t1()
7760returns void as $$
7761declare
7762  r1 record;
7763  r2 record;
7764begin
7765  select 10 as a, 20 as b into r1;
7766  r2 := df1(r1);
7767  raise notice '%', r2.a;
7768end;
7769$$ language plpgsql;
7770select * from plpgsql_check_function('t1()');
7771 plpgsql_check_function
7772------------------------
7773(0 rows)
7774
7775create or replace function t1()
7776returns void as $$
7777declare
7778  r1 record;
7779  r2 record;
7780begin
7781  select 10 as a, 20 as b into r1;
7782  r2 := df2(r1, '{}');
7783  raise notice '%', r2.a;
7784end;
7785$$ language plpgsql;
7786select * from plpgsql_check_function('t1()');
7787 plpgsql_check_function
7788------------------------
7789(0 rows)
7790
7791create or replace function df1(anyelement)
7792returns anyelement as $$ select $1 $$ language sql;
7793create or replace function df22(jsonb, anyelement)
7794returns anyelement as $$ select $2; $$ language sql;
7795create or replace function t1()
7796returns void as $$
7797declare
7798  r1 record;
7799  r2 record;
7800begin
7801  select 10 as a, 20 as b into r1;
7802  r2 := df1(r1);
7803  raise notice '%', r2.a;
7804end;
7805$$ language plpgsql;
7806select * from plpgsql_check_function('t1()');
7807 plpgsql_check_function
7808------------------------
7809(0 rows)
7810
7811create or replace function t1()
7812returns void as $$
7813declare
7814  r1 record;
7815  r2 record;
7816begin
7817  select 10 as a, 20 as b into r1;
7818  r2 := df22('{}', r1);
7819  raise notice '%', r2.a;
7820end;
7821$$ language plpgsql;
7822select * from plpgsql_check_function('t1()');
7823 plpgsql_check_function
7824------------------------
7825(0 rows)
7826
7827drop function df1(anyelement);
7828drop function df2(anyelement, jsonb);
7829drop function df22(jsonb, anyelement);
7830drop function t1();
7831create or replace function dyntest()
7832returns void as $$
7833begin
7834  execute 'drop table if exists xxx; create table xxx(a int)';
7835end;
7836$$ language plpgsql;
7837-- should be ok
7838select * from plpgsql_check_function('dyntest');
7839 plpgsql_check_function
7840------------------------
7841(0 rows)
7842
7843create or replace function dyntest()
7844returns void as $$
7845declare x int;
7846begin
7847  execute 'drop table if exists xxx; create table xxx(a int)' into x;
7848end;
7849$$ language plpgsql;
7850-- should to report error
7851select * from plpgsql_check_function('dyntest');
7852                plpgsql_check_function
7853-------------------------------------------------------
7854 error:XX000:4:EXECUTE:expression does not return data
7855(1 row)
7856
7857drop function dyntest();
7858-- should to report error
7859create type typ2 as (a int, b int);
7860create or replace function broken_into()
7861returns void as $$
7862declare v typ2;
7863begin
7864  -- should to fail
7865  select (10,20)::typ2 into v;
7866  -- should be ok
7867  select ((10,20)::typ2).* into v;
7868  -- should to fail
7869  execute 'select (10,20)::typ2' into v;
7870  -- should be ok
7871  execute 'select ((10,20)::typ2).*' into v;
7872end;
7873$$ language plpgsql;
7874select * from plpgsql_check_function('broken_into', fatal_errors => false);
7875                                           plpgsql_check_function
7876------------------------------------------------------------------------------------------------------------
7877 error:42804:5:SQL statement:cannot cast composite value of "typ2" type to a scalar value of "integer" type
7878 warning:00000:5:SQL statement:too few attributes for composite variable
7879 error:42804:9:EXECUTE:cannot cast composite value of "typ2" type to a scalar value of "integer" type
7880 warning:00000:9:EXECUTE:too few attributes for composite variable
7881 warning extra:00000:2:DECLARE:never read variable "v"
7882(5 rows)
7883
7884drop function broken_into();
7885drop type typ2;
7886-- check output in xml or json formats
7887CREATE OR REPLACE FUNCTION test_function()
7888 RETURNS void
7889 LANGUAGE plpgsql
7890AS $function$
7891begin
7892    insert into non_existing_table values (1);
7893end
7894$function$;
7895select * from plpgsql_check_function('test_function', format => 'xml');
7896                           plpgsql_check_function
7897----------------------------------------------------------------------------
7898 <Function>                                                                +
7899   <Issue>                                                                 +
7900     <Level>error</Level>                                                  +
7901     <Sqlstate>42P01</Sqlstate>                                            +
7902     <Message>relation "non_existing_table" does not exist</Message>       +
7903     <Stmt lineno="3">SQL statement</Stmt>                                 +
7904     <Query position="13">insert into non_existing_table values (1)</Query>+
7905   </Issue>                                                                +
7906 </Function>
7907(1 row)
7908
7909select * from plpgsql_check_function('test_function', format => 'json');
7910                     plpgsql_check_function
7911-----------------------------------------------------------------
7912 { "issues":[                                                   +
7913   {                                                            +
7914     "level":"error",                                           +
7915     "message":"relation \"non_existing_table\" does not exist",+
7916     "statement":{                                              +
7917 "lineNumber":"3",                                              +
7918 "text":"SQL statement"                                         +
7919 },                                                             +
7920     "query":{                                                  +
7921 "position":"13",                                               +
7922 "text":"insert into non_existing_table values (1)"             +
7923 },                                                             +
7924     "sqlState":"42P01"                                         +
7925   }                                                            +
7926                                                                +
7927 ]                                                              +
7928 }
7929(1 row)
7930
7931drop function test_function();
7932-- test settype pragma
7933create or replace function test_function()
7934returns void as $$
7935declare r record;
7936begin
7937  raise notice '%', r.a;
7938end;
7939$$ language plpgsql;
7940-- should to detect error
7941select * from plpgsql_check_function('test_function');
7942                           plpgsql_check_function
7943----------------------------------------------------------------------------
7944 error:55000:4:RAISE:record "r" is not assigned yet
7945 Detail: The tuple structure of a not-yet-assigned record is indeterminate.
7946 Context: SQL statement "SELECT r.a"
7947(3 rows)
7948
7949create type ctype as (a int, b int);
7950create or replace function test_function()
7951returns void as $$
7952declare r record;
7953begin
7954  perform plpgsql_check_pragma('type: r ctype');
7955  raise notice '%', r.a;
7956end;
7957$$ language plpgsql;
7958-- should to be ok
7959select * from plpgsql_check_function('test_function');
7960 plpgsql_check_function
7961------------------------
7962(0 rows)
7963
7964create or replace function test_function()
7965returns void as $$
7966<<x>>declare r record;
7967begin
7968  perform plpgsql_check_pragma('type: x.r public."ctype"');
7969  raise notice '%', r.a;
7970end;
7971$$ language plpgsql;
7972-- should to be ok
7973select * from plpgsql_check_function('test_function');
7974 plpgsql_check_function
7975------------------------
7976(0 rows)
7977
7978create or replace function test_function()
7979returns void as $$
7980<<x>>declare r record;
7981begin
7982  perform plpgsql_check_pragma('type: "x".r (a int, b int)');
7983  raise notice '%', r.a;
7984end;
7985$$ language plpgsql;
7986-- should to be ok
7987select * from plpgsql_check_function('test_function');
7988 plpgsql_check_function
7989------------------------
7990(0 rows)
7991
7992create or replace function test_function()
7993returns void as $$
7994<<x>>declare r record;
7995begin
7996  perform plpgsql_check_pragma('type: "x".r (a int, b int');
7997  raise notice '%', r.a;
7998end;
7999$$ language plpgsql;
8000-- should to be ok
8001select * from plpgsql_check_function('test_function');
8002WARNING:  Pragma "type" on line 4 is not processed.
8003                           plpgsql_check_function
8004----------------------------------------------------------------------------
8005 error:55000:5:RAISE:record "r" is not assigned yet
8006 Detail: The tuple structure of a not-yet-assigned record is indeterminate.
8007 Context: SQL statement "SELECT r.a"
8008(3 rows)
8009
8010create or replace function test_function()
8011returns void as $$
8012<<x>>declare r record;
8013begin
8014  perform plpgsql_check_pragma('type: "x".r (a int, b int)x');
8015  raise notice '%', r.a;
8016end;
8017$$ language plpgsql;
8018-- should to be ok
8019select * from plpgsql_check_function('test_function');
8020WARNING:  Pragma "type" on line 4 is not processed.
8021                           plpgsql_check_function
8022----------------------------------------------------------------------------
8023 error:55000:5:RAISE:record "r" is not assigned yet
8024 Detail: The tuple structure of a not-yet-assigned record is indeterminate.
8025 Context: SQL statement "SELECT r.a"
8026(3 rows)
8027
8028drop function test_function();
8029drop type ctype;
8030create or replace function test_function()
8031returns void as $$
8032declare r pg_class;
8033begin
8034  create temp table foo(like pg_class);
8035  select * from foo into r;
8036end;
8037$$ language plpgsql;
8038-- should to raise an error
8039select * from plpgsql_check_function('test_function');
8040                  plpgsql_check_function
8041-----------------------------------------------------------
8042 error:42P01:5:SQL statement:relation "foo" does not exist
8043 Query: select * from foo
8044 --                   ^
8045(3 rows)
8046
8047create or replace function test_function()
8048returns void as $$
8049declare r record;
8050begin
8051  create temp table foo(like pg_class);
8052  perform plpgsql_check_pragma('table: foo(like pg_class)');
8053  select * from foo into r;
8054  raise notice '%', r.relname;
8055end;
8056$$ language plpgsql;
8057-- should be ok
8058select * from plpgsql_check_function('test_function');
8059 plpgsql_check_function
8060------------------------
8061(0 rows)
8062
8063drop function test_function();
8064-- now plpgsql_check can do some other checks when statement EXECUTE
8065-- contains only format function with constant fmt.
8066create or replace function test_function()
8067returns void as $$
8068begin
8069  execute format('create table zzz %I(a int, b int)', 'zzz');
8070end;
8071$$ language plpgsql;
8072-- should to detect bad expression
8073select * from plpgsql_check_function('test_function');
8074                plpgsql_check_function
8075------------------------------------------------------
8076 error:42601:3:EXECUTE:syntax error at or near ""%I""
8077(1 row)
8078
8079-- should to correctly detect type
8080create or replace function test_function()
8081returns void as $$
8082declare r record;
8083begin
8084  execute format('select %L::date + 1 as x', current_date) into r;
8085  raise notice '%',  extract(dow from r.x);
8086end;
8087$$ language plpgsql;
8088-- should be ok
8089select * from plpgsql_check_function('test_function');
8090 plpgsql_check_function
8091------------------------
8092(0 rows)
8093
8094-- should not to crash
8095create or replace function test_function()
8096returns void as $$
8097declare r record;
8098begin
8099  r := null;
8100end;
8101$$ language plpgsql;
8102select * from plpgsql_check_function('test_function');
8103                plpgsql_check_function
8104-------------------------------------------------------
8105 warning extra:00000:2:DECLARE:never read variable "r"
8106(1 row)
8107
8108