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