Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitacb2d7d

Browse files
committed
plpgsql: report proper line number for errors in variable initialization.
Previously, we pointed at the surrounding block's BEGIN keyword.If there are multiple variables being initialized in a DECLARE section,this isn't good enough: it can be quite confusing and unhelpful.We do know where the variable's declaration started, so it just takesa tiny bit more error-reporting infrastructure to use that.Discussion:https://postgr.es/m/713975.1635530414@sss.pgh.pa.us
1 parentfd27065 commitacb2d7d

File tree

6 files changed

+49
-31
lines changed

6 files changed

+49
-31
lines changed

‎src/pl/plpgsql/src/expected/plpgsql_domain.out

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ SELECT * FROM test_assign_booltrue(true, true);
3333

3434
SELECT * FROM test_assign_booltrue(false, true);
3535
ERROR: value for domain booltrue violates check constraint "booltrue_check"
36-
CONTEXT: PL/pgSQL function test_assign_booltrue(boolean,boolean) line3 during statement block local variable initialization
36+
CONTEXT: PL/pgSQL function test_assign_booltrue(boolean,boolean) line2 during statement block local variable initialization
3737
SELECT * FROM test_assign_booltrue(true, false);
3838
ERROR: value for domain booltrue violates check constraint "booltrue_check"
3939
CONTEXT: PL/pgSQL function test_assign_booltrue(boolean,boolean) line 4 at assignment
@@ -76,7 +76,7 @@ ERROR: value for domain uint2 violates check constraint "uint2_check"
7676
CONTEXT: PL/pgSQL function test_assign_uint2(integer,integer) line 4 at assignment
7777
SELECT * FROM test_assign_uint2(-100, 50);
7878
ERROR: value for domain uint2 violates check constraint "uint2_check"
79-
CONTEXT: PL/pgSQL function test_assign_uint2(integer,integer) line3 during statement block local variable initialization
79+
CONTEXT: PL/pgSQL function test_assign_uint2(integer,integer) line2 during statement block local variable initialization
8080
SELECT * FROM test_assign_uint2(null, 1);
8181
test_assign_uint2
8282
-------------------
@@ -115,7 +115,7 @@ SELECT * FROM test_assign_nnint(10, 20);
115115

116116
SELECT * FROM test_assign_nnint(null, 20);
117117
ERROR: domain nnint does not allow null values
118-
CONTEXT: PL/pgSQL function test_assign_nnint(integer,integer) line3 during statement block local variable initialization
118+
CONTEXT: PL/pgSQL function test_assign_nnint(integer,integer) line2 during statement block local variable initialization
119119
SELECT * FROM test_assign_nnint(10, null);
120120
ERROR: domain nnint does not allow null values
121121
CONTEXT: PL/pgSQL function test_assign_nnint(integer,integer) line 4 at assignment
@@ -168,7 +168,7 @@ ERROR: value for domain ordered_pair_domain violates check constraint "ordered_
168168
CONTEXT: PL/pgSQL function test_assign_ordered_pair_domain(integer,integer,integer) line 4 at assignment
169169
SELECT * FROM test_assign_ordered_pair_domain(2,1,3);
170170
ERROR: value for domain ordered_pair_domain violates check constraint "ordered_pair_domain_check"
171-
CONTEXT: PL/pgSQL function test_assign_ordered_pair_domain(integer,integer,integer) line3 during statement block local variable initialization
171+
CONTEXT: PL/pgSQL function test_assign_ordered_pair_domain(integer,integer,integer) line2 during statement block local variable initialization
172172
--
173173
-- Arrays of domains
174174
--
@@ -276,7 +276,7 @@ ERROR: domain nnint does not allow null values
276276
CONTEXT: PL/pgSQL function test_assign_nnint_container(integer,integer,integer) line 4 at assignment
277277
SELECT * FROM test_assign_nnint_container(1,null,3);
278278
ERROR: domain nnint does not allow null values
279-
CONTEXT: PL/pgSQL function test_assign_nnint_container(integer,integer,integer) line3 during statement block local variable initialization
279+
CONTEXT: PL/pgSQL function test_assign_nnint_container(integer,integer,integer) line2 during statement block local variable initialization
280280
-- Since core system allows this:
281281
SELECT null::nnint_container;
282282
nnint_container
@@ -356,7 +356,7 @@ ERROR: value for domain ordered_named_pair violates check constraint "ordered_n
356356
CONTEXT: PL/pgSQL function test_assign_ordered_named_pair(integer,integer,integer) line 4 at assignment
357357
SELECT * FROM test_assign_ordered_named_pair(2,1,3);
358358
ERROR: value for domain ordered_named_pair violates check constraint "ordered_named_pair_check"
359-
CONTEXT: PL/pgSQL function test_assign_ordered_named_pair(integer,integer,integer) line3 during statement block local variable initialization
359+
CONTEXT: PL/pgSQL function test_assign_ordered_named_pair(integer,integer,integer) line2 during statement block local variable initialization
360360
CREATE FUNCTION build_ordered_named_pairs(i int, j int) RETURNS ordered_named_pair[] AS $$
361361
begin
362362
return array[row(i, j), row(i, j+1)];
@@ -388,7 +388,7 @@ SELECT * FROM test_assign_ordered_named_pairs(1,2,3);
388388

389389
SELECT * FROM test_assign_ordered_named_pairs(2,1,3);
390390
ERROR: value for domain ordered_named_pair violates check constraint "ordered_named_pair_check"
391-
CONTEXT: PL/pgSQL function test_assign_ordered_named_pairs(integer,integer,integer) line3 during statement block local variable initialization
391+
CONTEXT: PL/pgSQL function test_assign_ordered_named_pairs(integer,integer,integer) line2 during statement block local variable initialization
392392
SELECT * FROM test_assign_ordered_named_pairs(1,2,0); -- should fail someday
393393
test_assign_ordered_named_pairs
394394
---------------------------------

‎src/pl/plpgsql/src/expected/plpgsql_varprops.out

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ begin
7777
end$$;
7878
ERROR: division by zero
7979
CONTEXT: SQL expression "1/0"
80-
PL/pgSQL function inline_code_block line3 during statement block local variable initialization
80+
PL/pgSQL function inline_code_block line2 during statement block local variable initialization
8181
do $$
8282
declare x bigint[] := array[1,3,5];
8383
begin
@@ -120,7 +120,7 @@ begin
120120
raise notice 'x = %', x;
121121
end$$;
122122
ERROR: null value cannot be assigned to variable "x" declared NOT NULL
123-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
123+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
124124
do $$
125125
declare x record not null; -- fail
126126
begin
@@ -147,7 +147,7 @@ begin
147147
raise notice 'x = %', x;
148148
end$$;
149149
ERROR: null value cannot be assigned to variable "x" declared NOT NULL
150-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
150+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
151151
do $$
152152
declare x var_record not null; -- fail
153153
begin
@@ -174,7 +174,7 @@ begin
174174
raise notice 'x = %', x;
175175
end$$;
176176
ERROR: null value cannot be assigned to variable "x" declared NOT NULL
177-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
177+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
178178
-- Check that variables are reinitialized on block re-entry.
179179
do $$
180180
begin
@@ -216,14 +216,14 @@ begin
216216
raise notice 'x = %', x;
217217
end$$;
218218
ERROR: domain int_nn does not allow null values
219-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
219+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
220220
do $$
221221
declare x int_nn := null; -- fail
222222
begin
223223
raise notice 'x = %', x;
224224
end$$;
225225
ERROR: domain int_nn does not allow null values
226-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
226+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
227227
do $$
228228
declare x int_nn := 42;
229229
begin
@@ -239,14 +239,14 @@ begin
239239
raise notice 'x = %', x;
240240
end$$;
241241
ERROR: domain var_record_nn does not allow null values
242-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
242+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
243243
do $$
244244
declare x var_record_nn := null; -- fail
245245
begin
246246
raise notice 'x = %', x;
247247
end$$;
248248
ERROR: domain var_record_nn does not allow null values
249-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
249+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
250250
do $$
251251
declare x var_record_nn := row(1,2);
252252
begin
@@ -263,21 +263,21 @@ begin
263263
raise notice 'x = %', x;
264264
end$$;
265265
ERROR: value for domain var_record_colnn violates check constraint "var_record_colnn_check"
266-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
266+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
267267
do $$
268268
declare x var_record_colnn := null; -- fail
269269
begin
270270
raise notice 'x = %', x;
271271
end$$;
272272
ERROR: value for domain var_record_colnn violates check constraint "var_record_colnn_check"
273-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
273+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
274274
do $$
275275
declare x var_record_colnn := row(1,null); -- fail
276276
begin
277277
raise notice 'x = %', x;
278278
end$$;
279279
ERROR: value for domain var_record_colnn violates check constraint "var_record_colnn_check"
280-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
280+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
281281
do $$
282282
declare x var_record_colnn := row(1,2);
283283
begin

‎src/pl/plpgsql/src/pl_exec.c

Lines changed: 26 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1214,6 +1214,20 @@ static void
12141214
plpgsql_exec_error_callback(void*arg)
12151215
{
12161216
PLpgSQL_execstate*estate= (PLpgSQL_execstate*)arg;
1217+
interr_lineno;
1218+
1219+
/*
1220+
* If err_var is set, report the variable's declaration line number.
1221+
* Otherwise, if err_stmt is set, report the err_stmt's line number. When
1222+
* err_stmt is not set, we're in function entry/exit, or some such place
1223+
* not attached to a specific line number.
1224+
*/
1225+
if (estate->err_var!=NULL)
1226+
err_lineno=estate->err_var->lineno;
1227+
elseif (estate->err_stmt!=NULL)
1228+
err_lineno=estate->err_stmt->lineno;
1229+
else
1230+
err_lineno=0;
12171231

12181232
if (estate->err_text!=NULL)
12191233
{
@@ -1222,21 +1236,16 @@ plpgsql_exec_error_callback(void *arg)
12221236
* actually need it. Therefore, places that set up err_text should
12231237
* use gettext_noop() to ensure the strings get recorded in the
12241238
* message dictionary.
1225-
*
1226-
* If both err_text and err_stmt are set, use the err_text as
1227-
* description, but report the err_stmt's line number. When err_stmt
1228-
* is not set, we're in function entry/exit, or some such place not
1229-
* attached to a specific line number.
12301239
*/
1231-
if (estate->err_stmt!=NULL)
1240+
if (err_lineno>0)
12321241
{
12331242
/*
12341243
* translator: last %s is a phrase such as "during statement block
12351244
* local variable initialization"
12361245
*/
12371246
errcontext("PL/pgSQL function %s line %d %s",
12381247
estate->func->fn_signature,
1239-
estate->err_stmt->lineno,
1248+
err_lineno,
12401249
_(estate->err_text));
12411250
}
12421251
else
@@ -1250,12 +1259,12 @@ plpgsql_exec_error_callback(void *arg)
12501259
_(estate->err_text));
12511260
}
12521261
}
1253-
elseif (estate->err_stmt!=NULL)
1262+
elseif (estate->err_stmt!=NULL&&err_lineno>0)
12541263
{
12551264
/* translator: last %s is a plpgsql statement type name */
12561265
errcontext("PL/pgSQL function %s line %d at %s",
12571266
estate->func->fn_signature,
1258-
estate->err_stmt->lineno,
1267+
err_lineno,
12591268
plpgsql_stmt_typename(estate->err_stmt));
12601269
}
12611270
else
@@ -1643,7 +1652,12 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
16431652
* Note that we currently don't support promise datums within blocks,
16441653
* only at a function's outermost scope, so we needn't handle those
16451654
* here.
1655+
*
1656+
* Since RECFIELD isn't a supported case either, it's okay to cast the
1657+
* PLpgSQL_datum to PLpgSQL_variable.
16461658
*/
1659+
estate->err_var= (PLpgSQL_variable*)datum;
1660+
16471661
switch (datum->dtype)
16481662
{
16491663
casePLPGSQL_DTYPE_VAR:
@@ -1717,6 +1731,8 @@ exec_stmt_block(PLpgSQL_execstate *estate, PLpgSQL_stmt_block *block)
17171731
}
17181732
}
17191733

1734+
estate->err_var=NULL;
1735+
17201736
if (block->exceptions)
17211737
{
17221738
/*
@@ -4041,6 +4057,7 @@ plpgsql_estate_setup(PLpgSQL_execstate *estate,
40414057
estate->eval_econtext=NULL;
40424058

40434059
estate->err_stmt=NULL;
4060+
estate->err_var=NULL;
40444061
estate->err_text=NULL;
40454062

40464063
estate->plugin_info=NULL;

‎src/pl/plpgsql/src/plpgsql.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1088,6 +1088,7 @@ typedef struct PLpgSQL_execstate
10881088

10891089
/* status information for error context reporting */
10901090
PLpgSQL_stmt*err_stmt;/* current stmt */
1091+
PLpgSQL_variable*err_var;/* current variable, if in a DECLARE section */
10911092
constchar*err_text;/* additional state info */
10921093

10931094
void*plugin_info;/* reserved for use by optional plugin */

‎src/test/regress/expected/domain.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -847,15 +847,15 @@ begin
847847
end$$ language plpgsql;
848848
select doubledecrement(3); -- fail because of implicit null assignment
849849
ERROR: domain pos_int does not allow null values
850-
CONTEXT: PL/pgSQL function doubledecrement(pos_int) line3 during statement block local variable initialization
850+
CONTEXT: PL/pgSQL function doubledecrement(pos_int) line2 during statement block local variable initialization
851851
create or replace function doubledecrement(p1 pos_int) returns pos_int as $$
852852
declare v pos_int := 0;
853853
begin
854854
return p1;
855855
end$$ language plpgsql;
856856
select doubledecrement(3); -- fail at initialization assignment
857857
ERROR: value for domain pos_int violates check constraint "pos_int_check"
858-
CONTEXT: PL/pgSQL function doubledecrement(pos_int) line3 during statement block local variable initialization
858+
CONTEXT: PL/pgSQL function doubledecrement(pos_int) line2 during statement block local variable initialization
859859
create or replace function doubledecrement(p1 pos_int) returns pos_int as $$
860860
declare v pos_int := 1;
861861
begin

‎src/test/regress/expected/plpgsql.out

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4648,7 +4648,7 @@ ERROR: column "x" does not exist
46484648
LINE 1: x + 1
46494649
^
46504650
QUERY: x + 1
4651-
CONTEXT: PL/pgSQL function inline_code_block line3 during statement block local variable initialization
4651+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
46524652
do $$
46534653
declare y int := x + 1; -- error
46544654
x int := 42;
@@ -4660,7 +4660,7 @@ ERROR: column "x" does not exist
46604660
LINE 1: x + 1
46614661
^
46624662
QUERY: x + 1
4663-
CONTEXT: PL/pgSQL function inline_code_block line4 during statement block local variable initialization
4663+
CONTEXT: PL/pgSQL function inline_code_block line2 during statement block local variable initialization
46644664
do $$
46654665
declare x int := 42;
46664666
y int := x + 1;

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp