Skip to content

Commit c06629c

Browse files
committed
Improve plpgsql's ability to report tuple incompatibility problems.
Volkan YAZICI
1 parent ead2163 commit c06629c

File tree

1 file changed

+49
-33
lines changed

1 file changed

+49
-33
lines changed

src/pl/plpgsql/src/pl_exec.c

Lines changed: 49 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.219 2008/09/01 22:30:33 tgl Exp $
11+
* $PostgreSQL: pgsql/src/pl/plpgsql/src/pl_exec.c,v 1.220 2008/09/09 15:14:08 alvherre Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -188,7 +188,8 @@ static Datum exec_simple_cast_value(Datum value, Oid valtype,
188188
Oid reqtype, int32 reqtypmod,
189189
bool isnull);
190190
static void exec_init_tuple_store(PLpgSQL_execstate *estate);
191-
static bool compatible_tupdesc(TupleDesc td1, TupleDesc td2);
191+
static void validate_tupdesc_compat(TupleDesc expected, TupleDesc returned,
192+
const char *msg);
192193
static void exec_set_found(PLpgSQL_execstate *estate, bool state);
193194
static void plpgsql_create_econtext(PLpgSQL_execstate *estate);
194195
static void free_var(PLpgSQL_var *var);
@@ -384,11 +385,9 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo)
384385
{
385386
case TYPEFUNC_COMPOSITE:
386387
/* got the expected result rowtype, now check it */
387-
if (estate.rettupdesc == NULL ||
388-
!compatible_tupdesc(estate.rettupdesc, tupdesc))
389-
ereport(ERROR,
390-
(errcode(ERRCODE_DATATYPE_MISMATCH),
391-
errmsg("returned record type does not match expected record type")));
388+
validate_tupdesc_compat(tupdesc, estate.rettupdesc,
389+
gettext_noop("returned record type does "
390+
"not match expected record type"));
392391
break;
393392
case TYPEFUNC_RECORD:
394393

@@ -705,11 +704,10 @@ plpgsql_exec_trigger(PLpgSQL_function *func,
705704
rettup = NULL;
706705
else
707706
{
708-
if (!compatible_tupdesc(estate.rettupdesc,
709-
trigdata->tg_relation->rd_att))
710-
ereport(ERROR,
711-
(errcode(ERRCODE_DATATYPE_MISMATCH),
712-
errmsg("returned tuple structure does not match table of trigger event")));
707+
validate_tupdesc_compat(trigdata->tg_relation->rd_att,
708+
estate.rettupdesc,
709+
gettext_noop("returned tuple structure does "
710+
"not match table of trigger event"));
713711
/* Copy tuple to upper executor memory */
714712
rettup = SPI_copytuple((HeapTuple) DatumGetPointer(estate.retval));
715713
}
@@ -2199,11 +2197,11 @@ exec_stmt_return_next(PLpgSQL_execstate *estate,
21992197
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
22002198
errmsg("record \"%s\" is not assigned yet",
22012199
rec->refname),
2202-
errdetail("The tuple structure of a not-yet-assigned record is indeterminate.")));
2203-
if (!compatible_tupdesc(tupdesc, rec->tupdesc))
2204-
ereport(ERROR,
2205-
(errcode(ERRCODE_DATATYPE_MISMATCH),
2206-
errmsg("wrong record type supplied in RETURN NEXT")));
2200+
errdetail("The tuple structure of a not-yet-assigned"
2201+
" record is indeterminate.")));
2202+
validate_tupdesc_compat(tupdesc, rec->tupdesc,
2203+
gettext_noop("wrong record type supplied "
2204+
"in RETURN NEXT"));
22072205
tuple = rec->tup;
22082206
}
22092207
break;
@@ -2309,10 +2307,9 @@ exec_stmt_return_query(PLpgSQL_execstate *estate,
23092307
stmt->params);
23102308
}
23112309

2312-
if (!compatible_tupdesc(estate->rettupdesc, portal->tupDesc))
2313-
ereport(ERROR,
2314-
(errcode(ERRCODE_DATATYPE_MISMATCH),
2315-
errmsg("structure of query does not match function result type")));
2310+
validate_tupdesc_compat(estate->rettupdesc, portal->tupDesc,
2311+
gettext_noop("structure of query does not match "
2312+
"function result type"));
23162313

23172314
while (true)
23182315
{
@@ -5145,23 +5142,42 @@ exec_simple_check_plan(PLpgSQL_expr *expr)
51455142
}
51465143

51475144
/*
5148-
* Check two tupledescs have matching number and types of attributes
5145+
* Validates compatibility of supplied TupleDesc pair by checking number and type
5146+
* of attributes.
51495147
*/
5150-
static bool
5151-
compatible_tupdesc(TupleDesc td1, TupleDesc td2)
5148+
static void
5149+
validate_tupdesc_compat(TupleDesc expected, TupleDesc returned, const char *msg)
51525150
{
5153-
int i;
5151+
int i;
5152+
const char dropped_column_type[] = gettext_noop("n/a (dropped column)");
51545153

5155-
if (td1->natts != td2->natts)
5156-
return false;
5154+
if (!expected || !returned)
5155+
ereport(ERROR,
5156+
(errcode(ERRCODE_DATATYPE_MISMATCH),
5157+
errmsg("%s", _(msg))));
51575158

5158-
for (i = 0; i < td1->natts; i++)
5159-
{
5160-
if (td1->attrs[i]->atttypid != td2->attrs[i]->atttypid)
5161-
return false;
5162-
}
5159+
if (expected->natts != returned->natts)
5160+
ereport(ERROR,
5161+
(errcode(ERRCODE_DATATYPE_MISMATCH),
5162+
errmsg("%s", _(msg)),
5163+
errdetail("Number of returned columns (%d) does not match "
5164+
"expected column count (%d).",
5165+
returned->natts, expected->natts)));
51635166

5164-
return true;
5167+
for (i = 0; i < expected->natts; i++)
5168+
if (expected->attrs[i]->atttypid != returned->attrs[i]->atttypid)
5169+
ereport(ERROR,
5170+
(errcode(ERRCODE_DATATYPE_MISMATCH),
5171+
errmsg("%s", _(msg)),
5172+
errdetail("Returned type %s does not match expected type "
5173+
"%s in column %s.",
5174+
OidIsValid(returned->attrs[i]->atttypid) ?
5175+
format_type_be(returned->attrs[i]->atttypid) :
5176+
_(dropped_column_type),
5177+
OidIsValid(expected->attrs[i]->atttypid) ?
5178+
format_type_be(expected->attrs[i]->atttypid) :
5179+
_(dropped_column_type),
5180+
NameStr(expected->attrs[i]->attname))));
51655181
}
51665182

51675183
/* ----------

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy