Fix problems with dropped columns in pltcl triggers, per report from Patrick Samson.

This commit is contained in:
Tom Lane 2004-01-24 23:06:29 +00:00
parent 0152f14812
commit c8bcd5ca92
2 changed files with 28 additions and 19 deletions

View File

@ -1,5 +1,5 @@
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.28 2003/11/29 19:51:37 pgsql Exp $ $PostgreSQL: pgsql/doc/src/sgml/pltcl.sgml,v 2.29 2004/01/24 23:06:29 tgl Exp $
--> -->
<chapter id="pltcl"> <chapter id="pltcl">
@ -516,7 +516,10 @@ SELECT 'doesn''t' AS ret
element. So looking up a column name in the list with <application>Tcl</>'s element. So looking up a column name in the list with <application>Tcl</>'s
<function>lsearch</> command returns the element's number starting <function>lsearch</> command returns the element's number starting
with 1 for the first column, the same way the columns are customarily with 1 for the first column, the same way the columns are customarily
numbered in <productname>PostgreSQL</productname>. numbered in <productname>PostgreSQL</productname>. (Empty list
elements also appear in the positions of columns that have been
dropped, so that the attribute numbering is correct for columns
to their right.)
</para> </para>
</listitem> </listitem>
</varlistentry> </varlistentry>

View File

@ -31,7 +31,7 @@
* ENHANCEMENTS, OR MODIFICATIONS. * ENHANCEMENTS, OR MODIFICATIONS.
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.81 2004/01/06 23:55:19 tgl Exp $ * $PostgreSQL: pgsql/src/pl/tcl/pltcl.c,v 1.82 2004/01/24 23:06:29 tgl Exp $
* *
**********************************************************************/ **********************************************************************/
@ -695,11 +695,15 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
pfree(stroid); pfree(stroid);
/* A list of attribute names for argument TG_relatts */ /* A list of attribute names for argument TG_relatts */
/* note: we deliberately include dropped atts here */
Tcl_DStringAppendElement(&tcl_trigtup, ""); Tcl_DStringAppendElement(&tcl_trigtup, "");
for (i = 0; i < tupdesc->natts; i++) for (i = 0; i < tupdesc->natts; i++)
Tcl_DStringAppendElement(&tcl_trigtup, {
NameStr(tupdesc->attrs[i]->attname)); if (tupdesc->attrs[i]->attisdropped)
Tcl_DStringAppendElement(&tcl_trigtup, "");
else
Tcl_DStringAppendElement(&tcl_trigtup,
NameStr(tupdesc->attrs[i]->attname));
}
Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup)); Tcl_DStringAppendElement(&tcl_cmd, Tcl_DStringValue(&tcl_trigtup));
Tcl_DStringFree(&tcl_trigtup); Tcl_DStringFree(&tcl_trigtup);
Tcl_DStringInit(&tcl_trigtup); Tcl_DStringInit(&tcl_trigtup);
@ -881,9 +885,10 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
siglongjmp(Warn_restart, 1); siglongjmp(Warn_restart, 1);
} }
i = 0; for (i = 0; i < ret_numvals; i += 2)
while (i < ret_numvals)
{ {
CONST84 char *ret_name = ret_values[i];
CONST84 char *ret_value = ret_values[i + 1];
int attnum; int attnum;
HeapTuple typeTup; HeapTuple typeTup;
Oid typinput; Oid typinput;
@ -891,24 +896,25 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
FmgrInfo finfo; FmgrInfo finfo;
/************************************************************ /************************************************************
* Ignore pseudo elements with a dot name * Ignore ".tupno" pseudo elements (see pltcl_set_tuple_values)
************************************************************/ ************************************************************/
if (*(ret_values[i]) == '.') if (strcmp(ret_name, ".tupno") == 0)
{
i += 2;
continue; continue;
}
/************************************************************ /************************************************************
* Get the attribute number * Get the attribute number
************************************************************/ ************************************************************/
attnum = SPI_fnumber(tupdesc, ret_values[i++]); attnum = SPI_fnumber(tupdesc, ret_name);
if (attnum == SPI_ERROR_NOATTRIBUTE) if (attnum == SPI_ERROR_NOATTRIBUTE)
elog(ERROR, "invalid attribute \"%s\"", elog(ERROR, "invalid attribute \"%s\"", ret_name);
ret_values[--i]);
if (attnum <= 0) if (attnum <= 0)
elog(ERROR, "cannot set system attribute \"%s\"", elog(ERROR, "cannot set system attribute \"%s\"", ret_name);
ret_values[--i]);
/************************************************************
* Ignore dropped columns
************************************************************/
if (tupdesc->attrs[attnum - 1]->attisdropped)
continue;
/************************************************************ /************************************************************
* Lookup the attribute type in the syscache * Lookup the attribute type in the syscache
@ -932,7 +938,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
UTF_BEGIN; UTF_BEGIN;
modvalues[attnum - 1] = modvalues[attnum - 1] =
FunctionCall3(&finfo, FunctionCall3(&finfo,
CStringGetDatum(UTF_U2E(ret_values[i++])), CStringGetDatum(UTF_U2E(ret_value)),
ObjectIdGetDatum(typelem), ObjectIdGetDatum(typelem),
Int32GetDatum(tupdesc->attrs[attnum - 1]->atttypmod)); Int32GetDatum(tupdesc->attrs[attnum - 1]->atttypmod));
UTF_END; UTF_END;