]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Do not execute fastpath function calls if in transaction ABORT state.
authorTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Oct 2000 20:59:35 +0000 (20:59 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Tue, 24 Oct 2000 20:59:35 +0000 (20:59 +0000)
Just like queries, doing nothing is better than possibly getting weird
error messages.  Also, improve comments.

src/backend/tcop/fastpath.c

index fd30bd58ac555ce04a75719a9be659041b1df76a..05640b5be8f003793c8b554add064f7d348934d9 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.43 2000/07/03 23:09:46 wieck Exp $
+ *       $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.44 2000/10/24 20:59:35 tgl Exp $
  *
  * NOTES
  *       This cruft is the server side of PQfn.
@@ -271,9 +271,14 @@ update_fp_info(Oid func_id, struct fp_info * fip)
  * Note: All ordinary errors result in elog(ERROR,...).  However,
  * if we lose the frontend connection there is no one to elog to,
  * and no use in proceeding...
+ *
+ * Note: palloc()s done here and in the called function do not need to be
+ * cleaned up explicitly.  We are called from PostgresMain() in the
+ * QueryContext memory context, which will be automatically reset when
+ * control returns to PostgresMain.
  */
 int
-HandleFunctionRequest()
+HandleFunctionRequest(void)
 {
        Oid                     fid;
        int                     argsize;
@@ -285,6 +290,32 @@ HandleFunctionRequest()
        char       *p;
        struct fp_info *fip;
 
+       /*
+        * XXX FIXME: This protocol is misdesigned.
+        *
+        * We really do not want to elog() before having swallowed all of the
+        * frontend's fastpath message; otherwise we will lose sync with the input
+        * datastream.  What should happen is we absorb all of the input message
+        * per protocol syntax, and *then* do error checking (including lookup of
+        * the given function ID) and elog if appropriate.  Unfortunately, because
+        * we cannot even read the message properly without knowing whether the
+        * data types are pass-by-ref or pass-by-value, it's not all that easy to
+        * do :-(.  The protocol should require the client to supply what it
+        * thinks is the typbyval and typlen value for each arg, so that we can
+        * read the data without having to do any lookups.  Then after we've read
+        * the message, we should do the lookups, verify agreement of the actual
+        * function arg types with what we received, and finally call the function.
+        *
+        * As things stand, not only will we lose sync for an invalid message
+        * (such as requested function OID doesn't exist), but we may lose sync
+        * for a perfectly valid message if we are in transaction-aborted state!
+        * This can happen because our database lookup attempts may fail entirely
+        * in abort state.
+        *
+        * Unfortunately I see no way to fix this without breaking a lot of
+        * existing clients.  Maybe do it as part of next protocol version change.
+        */
+
        if (pq_getint(&tmp, 4))         /* function oid */
                return EOF;
        fid = (Oid) tmp;
@@ -293,23 +324,13 @@ HandleFunctionRequest()
 
        /*
         * This is where the one-back caching is done. If you want to save
-        * more state, make this a loop around an array.
+        * more state, make this a loop around an array.  Given the relatively
+        * short lifespan of the cache, not clear that there's any win possible.
         */
        fip = &last_fp;
        if (!valid_fp_info(fid, fip))
                update_fp_info(fid, fip);
 
-       /*
-        * XXX FIXME: elog() here means we lose sync with the frontend, since
-        * we have not swallowed all of its input message.      What should happen
-        * is we absorb all of the input message per protocol syntax, and
-        * *then* do error checking (including lookup of the given function ID)
-        * and elog if appropriate.  Unfortunately, because we cannot even read
-        * the message properly without knowing whether the data types are
-        * pass-by-ref or pass-by-value, it's not all that easy to fix :-(.
-        * This protocol is misdesigned.
-        */
-
        if (fip->flinfo.fn_nargs != nargs || nargs > FUNC_MAX_ARGS)
        {
                elog(ERROR, "HandleFunctionRequest: actual arguments (%d) != registered arguments (%d)",
@@ -366,6 +387,17 @@ HandleFunctionRequest()
                }
        }
 
+       /*
+        * Now that we've eaten the input message, check to see if we actually
+        * want to do the function call or not.
+        *
+        * Currently, we report an error if in ABORT state, or return a dummy
+        * NULL response if fastpath support has been compiled out.
+        */
+       if (IsAbortedTransactionBlockState())
+               elog(ERROR, "current transaction is aborted, "
+                        "queries ignored until end of transaction block");
+
 #ifdef NO_FASTPATH
        /* force a NULL return */
        retval = (Datum) 0;