Skip to content

Commit 98c1e14

Browse files
committed
set correctly context of hiddent cast for all cases (not just for assignment), and for this warning set the query field when the statement is EXECSQL
1 parent 3c6fb7d commit 98c1e14

File tree

8 files changed

+374
-109
lines changed

8 files changed

+374
-109
lines changed

expected/plpgsql_check_active_3.out

Lines changed: 96 additions & 51 deletions
Large diffs are not rendered by default.

src/assign.c

Lines changed: 71 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,20 @@ plpgsql_check_assign_to_target_type(PLpgSQL_checkstate *cstate,
242242
Oid target_typoid,
243243
int32 target_typmod,
244244
Oid value_typoid,
245-
bool isnull)
245+
bool isnull,
246+
int target_dno)
246247
{
248+
char *local_err_text = NULL;
249+
char *local_query = NULL;
250+
251+
if (!cstate->estate->err_text && cstate->estate->err_stmt)
252+
local_err_text = plpgsql_check_prepare_err_text_with_target_vardecl(cstate,
253+
cstate->estate->err_stmt,
254+
target_dno);
255+
256+
if (cstate->estate->err_stmt && cstate->estate->err_stmt->cmd_type == PLPGSQL_STMT_EXECSQL)
257+
local_query = ((PLpgSQL_stmt_execsql *) cstate->estate->err_stmt)->sqlstmt->query;
258+
247259
/* not used yet */
248260
(void) target_typmod;
249261

@@ -267,7 +279,7 @@ plpgsql_check_assign_to_target_type(PLpgSQL_checkstate *cstate,
267279
NULL,
268280
NULL,
269281
PLPGSQL_CHECK_ERROR,
270-
0, NULL, NULL);
282+
0, local_query, local_err_text);
271283
}
272284
else if (!isnull)
273285
{
@@ -286,15 +298,15 @@ plpgsql_check_assign_to_target_type(PLpgSQL_checkstate *cstate,
286298
str.data,
287299
"There are no possible explicit coercion between those types, possibly bug!",
288300
PLPGSQL_CHECK_WARNING_OTHERS,
289-
0, NULL, NULL);
301+
0, local_query, local_err_text);
290302
else if (!can_coerce_type(1, &value_typoid, &target_typoid, COERCION_ASSIGNMENT))
291303
plpgsql_check_put_error(cstate,
292304
ERRCODE_DATATYPE_MISMATCH, 0,
293305
"target type is different type than source type",
294306
str.data,
295307
"The input expression type does not have an assignment cast to the target type.",
296308
PLPGSQL_CHECK_WARNING_OTHERS,
297-
0, NULL, NULL);
309+
0, local_query, local_err_text);
298310
else
299311
{
300312
/* highly probably only performance issue */
@@ -304,11 +316,15 @@ plpgsql_check_assign_to_target_type(PLpgSQL_checkstate *cstate,
304316
str.data,
305317
"Hidden casting can be a performance issue.",
306318
PLPGSQL_CHECK_WARNING_PERFORMANCE,
307-
0, NULL, NULL);
319+
0, local_query, local_err_text);
308320
}
309321

310322
pfree(str.data);
311323
}
324+
325+
/* release local err_text */
326+
if (local_err_text)
327+
pfree(local_err_text);
312328
}
313329

314330
/*
@@ -328,7 +344,8 @@ plpgsql_check_assign_tupdesc_dno(PLpgSQL_checkstate *cstate, int varno, TupleDes
328344
plpgsql_check_assign_to_target_type(cstate,
329345
var->datatype->typoid, var->datatype->atttypmod,
330346
TupleDescAttr(tupdesc, 0)->atttypid,
331-
isnull);
347+
isnull,
348+
target->dno);
332349
}
333350
break;
334351

@@ -350,7 +367,8 @@ plpgsql_check_assign_tupdesc_dno(PLpgSQL_checkstate *cstate, int varno, TupleDes
350367
plpgsql_check_assign_to_target_type(cstate,
351368
typoid, typmod,
352369
TupleDescAttr(tupdesc, 0)->atttypid,
353-
isnull);
370+
isnull,
371+
target->dno);
354372
}
355373
break;
356374

@@ -373,11 +391,34 @@ plpgsql_check_assign_tupdesc_row_or_rec(PLpgSQL_checkstate *cstate,
373391
{
374392
if (tupdesc == NULL)
375393
{
394+
char *local_err_text = NULL;
395+
396+
if (!cstate->estate->err_text && cstate->estate->err_stmt)
397+
{
398+
int target_dno;
399+
400+
if (rec)
401+
target_dno = rec->dno;
402+
else if (row)
403+
target_dno = row->dno;
404+
else
405+
target_dno = -1;
406+
407+
local_err_text = plpgsql_check_prepare_err_text_with_target_vardecl(cstate,
408+
cstate->estate->err_stmt,
409+
target_dno);
410+
}
411+
376412
plpgsql_check_put_error(cstate,
377413
0, 0,
378414
"tuple descriptor is empty", NULL, NULL,
379415
PLPGSQL_CHECK_WARNING_OTHERS,
380-
0, NULL, NULL);
416+
0, NULL, local_err_text);
417+
418+
/* release local err_text */
419+
if (local_err_text)
420+
pfree(local_err_text);
421+
381422
return;
382423
}
383424

@@ -421,7 +462,8 @@ plpgsql_check_assign_tupdesc_row_or_rec(PLpgSQL_checkstate *cstate,
421462
var->datatype->typoid,
422463
var->datatype->atttypmod,
423464
valtype,
424-
isnull);
465+
isnull,
466+
target->dno);
425467
}
426468
break;
427469

@@ -435,7 +477,8 @@ plpgsql_check_assign_tupdesc_row_or_rec(PLpgSQL_checkstate *cstate,
435477
expected_typoid,
436478
expected_typmod,
437479
valtype,
438-
isnull);
480+
isnull,
481+
target->dno);
439482
}
440483
break;
441484
default:
@@ -487,6 +530,16 @@ plpgsql_check_recval_assign_tupdesc(PLpgSQL_checkstate *cstate, PLpgSQL_rec *rec
487530
char *chunk;
488531
int vtd_natts;
489532
int i;
533+
char *local_err_text = NULL;
534+
char *local_query = NULL;
535+
536+
if (!cstate->estate->err_text && cstate->estate->err_stmt)
537+
local_err_text = plpgsql_check_prepare_err_text_with_target_vardecl(cstate,
538+
cstate->estate->err_stmt,
539+
rec->dno);
540+
541+
if (cstate->estate->err_stmt && cstate->estate->err_stmt->cmd_type == PLPGSQL_STMT_EXECSQL)
542+
local_query = ((PLpgSQL_stmt_execsql *) cstate->estate->err_stmt)->sqlstmt->query;
490543

491544
mcontext = get_eval_mcontext(estate);
492545
plpgsql_check_recval_release(rec);
@@ -556,7 +609,8 @@ plpgsql_check_recval_assign_tupdesc(PLpgSQL_checkstate *cstate, PLpgSQL_rec *rec
556609
plpgsql_check_assign_to_target_type(cstate,
557610
tattr->atttypid, tattr->atttypmod,
558611
sattr->atttypid,
559-
false);
612+
false,
613+
rec->dno);
560614

561615
/* try to search next tuple of fields */
562616
src_field_is_valid = false;
@@ -575,15 +629,15 @@ plpgsql_check_recval_assign_tupdesc(PLpgSQL_checkstate *cstate, PLpgSQL_rec *rec
575629
NULL,
576630
NULL,
577631
PLPGSQL_CHECK_WARNING_OTHERS,
578-
0, NULL, NULL);
632+
0, local_query, local_err_text);
579633
else if (src_nfields > target_nfields)
580634
plpgsql_check_put_error(cstate,
581635
0, 0,
582636
"too many attributes for composite variable",
583637
NULL,
584638
NULL,
585639
PLPGSQL_CHECK_WARNING_OTHERS,
586-
0, NULL, NULL);
640+
0, local_query, local_err_text);
587641
}
588642

589643
chunk = eval_mcontext_alloc(estate,
@@ -601,6 +655,10 @@ plpgsql_check_recval_assign_tupdesc(PLpgSQL_checkstate *cstate, PLpgSQL_rec *rec
601655

602656
TransferExpandedRecord(newerh, estate->datum_context);
603657
rec->erh = newerh;
658+
659+
/* release local err_text */
660+
if (local_err_text)
661+
pfree(local_err_text);
604662
}
605663

606664
/*

src/check_expr.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -980,7 +980,8 @@ plpgsql_check_expr_with_scalar_type(PLpgSQL_checkstate *cstate,
980980
plpgsql_check_assign_to_target_type(cstate,
981981
expected_typoid, -1,
982982
TupleDescAttr(tupdesc, 0)->atttypid,
983-
is_immutable_null);
983+
is_immutable_null,
984+
-1);
984985

985986
ReleaseTupleDesc(tupdesc);
986987
}
@@ -1128,7 +1129,8 @@ plpgsql_check_returned_expr(PLpgSQL_checkstate *cstate, PLpgSQL_expr *expr, bool
11281129
plpgsql_check_assign_to_target_type(cstate,
11291130
func->fn_rettype, -1,
11301131
TupleDescAttr(tupdesc, 0)->atttypid,
1131-
is_immutable_null);
1132+
is_immutable_null,
1133+
-1);
11321134
}
11331135
}
11341136

@@ -1256,6 +1258,25 @@ plpgsql_check_expr_as_rvalue(PLpgSQL_checkstate *cstate, PLpgSQL_expr *expr,
12561258

12571259
PG_TRY();
12581260
{
1261+
char *local_err_text;
1262+
bool free_local_err_text;
1263+
1264+
if (cstate->estate->err_text)
1265+
{
1266+
local_err_text = (char *) cstate->estate->err_text;
1267+
free_local_err_text = false;
1268+
}
1269+
else if (cstate->estate->err_stmt)
1270+
{
1271+
local_err_text = plpgsql_check_prepare_err_text_with_target_vardecl(cstate, cstate->estate->err_stmt, -1);
1272+
free_local_err_text = local_err_text != NULL;
1273+
}
1274+
else
1275+
{
1276+
local_err_text = NULL;
1277+
free_local_err_text = false;
1278+
}
1279+
12591280
prepare_plan(cstate, expr, 0, NULL, NULL, is_expression);
12601281
/* record all variables used by the query */
12611282

@@ -1338,23 +1359,23 @@ plpgsql_check_expr_as_rvalue(PLpgSQL_checkstate *cstate, PLpgSQL_expr *expr,
13381359
str.data,
13391360
"There are no possible explicit coercion between those types, possibly bug!",
13401361
PLPGSQL_CHECK_WARNING_OTHERS,
1341-
0, NULL, NULL);
1362+
0, expr->query, local_err_text);
13421363
else if (!can_coerce_type(1, &value_typoid, &target_typoid, COERCION_ASSIGNMENT))
13431364
plpgsql_check_put_error(cstate,
13441365
ERRCODE_DATATYPE_MISMATCH, 0,
13451366
"target type is different type than source type",
13461367
str.data,
13471368
"The input expression type does not have an assignment cast to the target type.",
13481369
PLPGSQL_CHECK_WARNING_OTHERS,
1349-
0, NULL, NULL);
1370+
0, expr->query, local_err_text);
13501371
else
13511372
plpgsql_check_put_error(cstate,
13521373
ERRCODE_DATATYPE_MISMATCH, 0,
13531374
"target type is different type than source type",
13541375
str.data,
13551376
"Hidden casting can be a performance issue.",
13561377
PLPGSQL_CHECK_WARNING_PERFORMANCE,
1357-
0, NULL, NULL);
1378+
0, expr->query, local_err_text);
13581379

13591380
pfree(str.data);
13601381
}
@@ -1512,7 +1533,7 @@ plpgsql_check_expr_as_rvalue(PLpgSQL_checkstate *cstate, PLpgSQL_expr *expr,
15121533
NULL,
15131534
NULL,
15141535
PLPGSQL_CHECK_ERROR,
1515-
0, NULL, NULL);
1536+
0, NULL, local_err_text);
15161537

15171538
goto no_other_check;
15181539
}
@@ -1540,22 +1561,25 @@ plpgsql_check_expr_as_rvalue(PLpgSQL_checkstate *cstate, PLpgSQL_expr *expr,
15401561
"There are more target variables than output columns in query.",
15411562
"Check target variables in SELECT INTO statement.",
15421563
PLPGSQL_CHECK_WARNING_OTHERS,
1543-
0, NULL, NULL);
1564+
0, expr->query, local_err_text);
15441565
else if (RowGetValidFields(targetrow) < TupleDescNVatts(tupdesc))
15451566
plpgsql_check_put_error(cstate,
15461567
0, 0,
15471568
"too many attributes for target variables",
15481569
"There are less target variables than output columns in query.",
15491570
"Check target variables in SELECT INTO statement",
15501571
PLPGSQL_CHECK_WARNING_OTHERS,
1551-
0, NULL, NULL);
1572+
0, expr->query, local_err_text);
15521573
}
15531574
}
15541575

15551576
no_other_check:
15561577
if (tupdesc)
15571578
ReleaseTupleDesc(tupdesc);
15581579

1580+
if (free_local_err_text)
1581+
pfree(local_err_text);
1582+
15591583
ReleaseCurrentSubTransaction();
15601584
MemoryContextSwitchTo(oldCxt);
15611585
CurrentResourceOwner = oldowner;

src/check_function.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ collect_out_variables(PLpgSQL_function *func, PLpgSQL_checkstate *cstate)
8989
int varno = func->out_param_varno;
9090
PLpgSQL_variable *var = (PLpgSQL_variable *) func->datums[varno];
9191

92-
if (var->dtype == PLPGSQL_DTYPE_ROW && is_internal_variable(cstate, var))
92+
if (var->dtype == PLPGSQL_DTYPE_ROW && plpgsql_check_is_internal_variable(cstate, var))
9393
{
9494
/* this function has more OUT parameters */
9595
PLpgSQL_row *row = (PLpgSQL_row *) var;

0 commit comments

Comments
 (0)