|
8 | 8 | * |
9 | 9 | * |
10 | 10 | * 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 $ |
12 | 12 | * |
13 | 13 | *------------------------------------------------------------------------- |
14 | 14 | */ |
@@ -188,7 +188,8 @@ static Datum exec_simple_cast_value(Datum value, Oid valtype, |
188 | 188 | Oid reqtype, int32 reqtypmod, |
189 | 189 | bool isnull); |
190 | 190 | 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); |
192 | 193 | static void exec_set_found(PLpgSQL_execstate *estate, bool state); |
193 | 194 | static void plpgsql_create_econtext(PLpgSQL_execstate *estate); |
194 | 195 | static void free_var(PLpgSQL_var *var); |
@@ -384,11 +385,9 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo) |
384 | 385 | { |
385 | 386 | case TYPEFUNC_COMPOSITE: |
386 | 387 | /* 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")); |
392 | 391 | break; |
393 | 392 | case TYPEFUNC_RECORD: |
394 | 393 |
|
@@ -705,11 +704,10 @@ plpgsql_exec_trigger(PLpgSQL_function *func, |
705 | 704 | rettup = NULL; |
706 | 705 | else |
707 | 706 | { |
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")); |
713 | 711 | /* Copy tuple to upper executor memory */ |
714 | 712 | rettup = SPI_copytuple((HeapTuple) DatumGetPointer(estate.retval)); |
715 | 713 | } |
@@ -2199,11 +2197,11 @@ exec_stmt_return_next(PLpgSQL_execstate *estate, |
2199 | 2197 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE), |
2200 | 2198 | errmsg("record \"%s\" is not assigned yet", |
2201 | 2199 | 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")); |
2207 | 2205 | tuple = rec->tup; |
2208 | 2206 | } |
2209 | 2207 | break; |
@@ -2309,10 +2307,9 @@ exec_stmt_return_query(PLpgSQL_execstate *estate, |
2309 | 2307 | stmt->params); |
2310 | 2308 | } |
2311 | 2309 |
|
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")); |
2316 | 2313 |
|
2317 | 2314 | while (true) |
2318 | 2315 | { |
@@ -5145,23 +5142,42 @@ exec_simple_check_plan(PLpgSQL_expr *expr) |
5145 | 5142 | } |
5146 | 5143 |
|
5147 | 5144 | /* |
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. |
5149 | 5147 | */ |
5150 | | -static bool |
5151 | | -compatible_tupdesc(TupleDesc td1, TupleDesc td2) |
| 5148 | +static void |
| 5149 | +validate_tupdesc_compat(TupleDesc expected, TupleDesc returned, const char *msg) |
5152 | 5150 | { |
5153 | | - int i; |
| 5151 | + int i; |
| 5152 | + const char dropped_column_type[] = gettext_noop("n/a (dropped column)"); |
5154 | 5153 |
|
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)))); |
5157 | 5158 |
|
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))); |
5163 | 5166 |
|
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)))); |
5165 | 5181 | } |
5166 | 5182 |
|
5167 | 5183 | /* ---------- |
|
0 commit comments