Fix problems with dropped columns in pltcl triggers, per report from Patrick Samson.
authorTom Lane
Sat, 24 Jan 2004 23:06:29 +0000 (23:06 +0000)
committerTom Lane
Sat, 24 Jan 2004 23:06:29 +0000 (23:06 +0000)
doc/src/sgml/pltcl.sgml
src/pl/tcl/pltcl.c

index 22121c2b2979ac1ff61a6c370f8ea62d047b17dd..2e7b9f88e188f0f39e102defbb2f86ddb7897154 100644 (file)
@@ -1,5 +1,5 @@
 
 
  
@@ -516,7 +516,10 @@ SELECT 'doesn''t' AS ret
          element. So looking up a column name in the list with Tcl's
          lsearch command returns the element's number starting
     with 1 for the first column, the same way the columns are customarily
-    numbered in PostgreSQL.
+    numbered in PostgreSQL.  (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.)
    
        
       
index f813841f2d86a6a9c66d23e1eb5f3dba71a0c35a..37e515ff66b590e42891d19a7689a354302c9058 100644 (file)
@@ -31,7 +31,7 @@
  *   ENHANCEMENTS, OR MODIFICATIONS.
  *
  * 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);
 
    /* A list of attribute names for argument TG_relatts */
-   /* note: we deliberately include dropped atts here */
    Tcl_DStringAppendElement(&tcl_trigtup, "");
    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_DStringFree(&tcl_trigtup);
    Tcl_DStringInit(&tcl_trigtup);
@@ -881,9 +885,10 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
        siglongjmp(Warn_restart, 1);
    }
 
-   i = 0;
-   while (i < ret_numvals)
+   for (i = 0; i < ret_numvals; i += 2)
    {
+       CONST84 char *ret_name = ret_values[i];
+       CONST84 char *ret_value = ret_values[i + 1];
        int         attnum;
        HeapTuple   typeTup;
        Oid         typinput;
@@ -891,24 +896,25 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
        FmgrInfo    finfo;
 
        /************************************************************
-        * Ignore pseudo elements with a dot name
+        * Ignore ".tupno" pseudo elements (see pltcl_set_tuple_values)
         ************************************************************/
-       if (*(ret_values[i]) == '.')
-       {
-           i += 2;
+       if (strcmp(ret_name, ".tupno") == 0)
            continue;
-       }
 
        /************************************************************
         * Get the attribute number
         ************************************************************/
-       attnum = SPI_fnumber(tupdesc, ret_values[i++]);
+       attnum = SPI_fnumber(tupdesc, ret_name);
        if (attnum == SPI_ERROR_NOATTRIBUTE)
-           elog(ERROR, "invalid attribute \"%s\"",
-                ret_values[--i]);
+           elog(ERROR, "invalid attribute \"%s\"", ret_name);
        if (attnum <= 0)
-           elog(ERROR, "cannot set system attribute \"%s\"",
-                ret_values[--i]);
+           elog(ERROR, "cannot set system attribute \"%s\"", ret_name);
+
+       /************************************************************
+        * Ignore dropped columns
+        ************************************************************/
+       if (tupdesc->attrs[attnum - 1]->attisdropped)
+           continue;
 
        /************************************************************
         * Lookup the attribute type in the syscache
@@ -932,7 +938,7 @@ pltcl_trigger_handler(PG_FUNCTION_ARGS)
        UTF_BEGIN;
        modvalues[attnum - 1] =
            FunctionCall3(&finfo,
-                         CStringGetDatum(UTF_U2E(ret_values[i++])),
+                         CStringGetDatum(UTF_U2E(ret_value)),
                          ObjectIdGetDatum(typelem),
                   Int32GetDatum(tupdesc->attrs[attnum - 1]->atttypmod));
        UTF_END;