Skip to content

Commit 4a97725

Browse files
committed
raise warning when record type cannot be detected
1 parent b186630 commit 4a97725

File tree

3 files changed

+69
-4
lines changed

3 files changed

+69
-4
lines changed

expected/plpgsql_check_active.out

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3841,6 +3841,29 @@ select * from plpgsql_check_function('dyn_sql_3');
38413841
Context: SQL statement "SELECT r.c"
38423842
(2 rows)
38433843

3844+
drop function dyn_sql_3();
3845+
create or replace function dyn_sql_3()
3846+
returns void as $$
3847+
declare
3848+
r record;
3849+
v text = 'select 10 a, 20 b't;
3850+
begin
3851+
select 10 a, 20 b into r;
3852+
for r in execute v
3853+
loop
3854+
raise notice '%', r.a;
3855+
end loop;
3856+
end
3857+
$$ language plpgsql;
3858+
-- should be warning
3859+
select * from plpgsql_check_function('dyn_sql_3');
3860+
plpgsql_check_function
3861+
---------------------------------------------------------------------------------------
3862+
warning:00000:7:FOR over EXECUTE statement:cannot determinate a result of dynamic SQL
3863+
Detail: There is a risk of related false alarms.
3864+
Hint: Don't use dynamic SQL and record type together, when you would check function.
3865+
(3 rows)
3866+
38443867
drop function dyn_sql_3();
38453868
create or replace function dyn_sql_4()
38463869
returns table(ax int, bx int) as $$

sql/plpgsql_check_active.sql

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2800,6 +2800,25 @@ select * from plpgsql_check_function('dyn_sql_3');
28002800

28012801
drop function dyn_sql_3();
28022802

2803+
create or replace function dyn_sql_3()
2804+
returns void as $$
2805+
declare
2806+
r record;
2807+
v text = 'select 10 a, 20 b't;
2808+
begin
2809+
select 10 a, 20 b into r;
2810+
for r in execute v
2811+
loop
2812+
raise notice '%', r.a;
2813+
end loop;
2814+
end
2815+
$$ language plpgsql;
2816+
2817+
-- should be warning
2818+
select * from plpgsql_check_function('dyn_sql_3');
2819+
2820+
drop function dyn_sql_3();
2821+
28032822
create or replace function dyn_sql_4()
28042823
returns table(ax int, bx int) as $$
28052824
begin

src/stmtwalk.c

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1774,6 +1774,7 @@ check_dynamic_sql(PLpgSQL_checkstate *cstate,
17741774
Node *expr_node;
17751775
ListCell *l;
17761776
int loc = -1;
1777+
bool raise_unknown_rec_warning = false;
17771778

17781779
/*
17791780
* possible checks:
@@ -1903,6 +1904,27 @@ check_dynamic_sql(PLpgSQL_checkstate *cstate,
19031904
query->query,
19041905
NULL);
19051906
}
1907+
1908+
/*
1909+
* In this case, we don't know a result type, and we should
1910+
* to raise warning about this situation.
1911+
*/
1912+
if (into)
1913+
{
1914+
1915+
#if PG_VERSION_NUM >= 110000
1916+
1917+
if (target->dtype == PLPGSQL_DTYPE_REC)
1918+
raise_unknown_rec_warning = true;
1919+
1920+
#else
1921+
1922+
if (rec)
1923+
raise_unknown_rec_warning = true;
1924+
1925+
#endif
1926+
1927+
}
19061928
}
19071929

19081930
/* recheck if target rec var has assigned tupdesc */
@@ -1913,22 +1935,23 @@ check_dynamic_sql(PLpgSQL_checkstate *cstate,
19131935

19141936
check_variable(cstate, target);
19151937

1916-
if (target->dtype == PLPGSQL_DTYPE_REC &&
1917-
!has_assigned_tupdesc(cstate, (PLpgSQL_rec *) target))
1938+
if (raise_unknown_rec_warning ||
1939+
(target->dtype == PLPGSQL_DTYPE_REC &&
1940+
!has_assigned_tupdesc(cstate, (PLpgSQL_rec *) target)))
19181941

19191942
#else
19201943

19211944
plpgsql_check_row_or_rec(cstate, row, rec);
19221945

1923-
if (rec != NULL && !has_assigned_tupdesc(cstate, rec))
1946+
if (raise_unknown_rec_warning || (rec != NULL && !has_assigned_tupdesc(cstate, rec)))
19241947

19251948
#endif
19261949

19271950
{
19281951
plpgsql_check_put_error(cstate,
19291952
0, 0,
19301953
"cannot determinate a result of dynamic SQL",
1931-
"Cannot to contine in check.",
1954+
"There is a risk of related false alarms.",
19321955
"Don't use dynamic SQL and record type together, when you would check function.",
19331956
PLPGSQL_CHECK_WARNING_OTHERS,
19341957
0, NULL, NULL);

0 commit comments

Comments
 (0)