aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2016-11-06 14:43:13 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2016-11-06 14:43:13 -0500
commitabdc839985a396cb8516a9131e75f602ae277d27 (patch)
treec62fe69b4e05c06dc03d2a23e319b270b59ed9ed /src
parent674877e93a1b9217c692a5671e1118136959ee74 (diff)
downloadpostgresql-abdc839985a396cb8516a9131e75f602ae277d27.tar.gz
postgresql-abdc839985a396cb8516a9131e75f602ae277d27.zip
Rationalize and document pltcl's handling of magic ".tupno" array element.
For a very long time, pltcl's spi_exec and spi_execp commands have had a behavior of storing the current row number as an element of output arrays, but this was never documented. Fix that. For an equally long time, pltcl_trigger_handler had a behavior of silently ignoring ".tupno" as an output column name, evidently so that the result of spi_exec could be used directly as a trigger result tuple. Not sure how useful that really is, but in any case it's bad that it would break attempts to use ".tupno" as an actual column name. We can fix it by not checking for ".tupno" until after we check for a column name match. This comports with the effective behavior of spi_exec[p] that ".tupno" is only magic when you don't have an actual column named that. In passing, wordsmith the description of returning modified tuples from a pltcl trigger. Noted while working on Jim Nasby's patch to support composite results from pltcl. The inability to return trigger tuples using ".tupno" as a column name is a bug, so back-patch to all supported branches.
Diffstat (limited to 'src')
-rw-r--r--src/pl/tcl/pltcl.c23
1 files changed, 15 insertions, 8 deletions
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index dce5d04adf8..92098570a66 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -1079,20 +1079,22 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS, bool pltrusted)
FmgrInfo finfo;
/************************************************************
- * Ignore ".tupno" pseudo elements (see pltcl_set_tuple_values)
- ************************************************************/
- if (strcmp(ret_name, ".tupno") == 0)
- continue;
-
- /************************************************************
* Get the attribute number
+ *
+ * We silently ignore ".tupno", if it's present but doesn't match
+ * any actual output column. This allows direct use of a row
+ * returned by pltcl_set_tuple_values().
************************************************************/
attnum = SPI_fnumber(tupdesc, ret_name);
if (attnum == SPI_ERROR_NOATTRIBUTE)
+ {
+ if (strcmp(ret_name, ".tupno") == 0)
+ continue;
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_COLUMN),
errmsg("unrecognized attribute \"%s\"",
ret_name)));
+ }
if (attnum <= 0)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
@@ -2505,8 +2507,7 @@ pltcl_set_tuple_values(Tcl_Interp *interp, CONST84 char *arrayname,
CONST84 char *nullname = NULL;
/************************************************************
- * Prepare pointers for Tcl_SetVar2() below and in array
- * mode set the .tupno element
+ * Prepare pointers for Tcl_SetVar2() below
************************************************************/
if (arrayname == NULL)
{
@@ -2517,6 +2518,12 @@ pltcl_set_tuple_values(Tcl_Interp *interp, CONST84 char *arrayname,
{
arrptr = &arrayname;
nameptr = &attname;
+
+ /*
+ * When outputting to an array, fill the ".tupno" element with the
+ * current tuple number. This will be overridden below if ".tupno" is
+ * in use as an actual field name in the rowtype.
+ */
snprintf(buf, sizeof(buf), "%d", tupno);
Tcl_SetVar2(interp, arrayname, ".tupno", buf, 0);
}