Fix Assert failure when a fastpath function call is attempted inside an
authorTom Lane <[email protected]>
Sun, 11 Jun 2006 15:49:36 +0000 (15:49 +0000)
committerTom Lane <[email protected]>
Sun, 11 Jun 2006 15:49:36 +0000 (15:49 +0000)
already-aborted transaction block.  GetSnapshotData throws an Assert if
not in a valid transaction; hence we mustn't attempt to set a snapshot
for the function until after checking for aborted transaction.  This is
harmless AFAICT if Asserts aren't enabled (GetSnapshotData will compute
a bogus snapshot, but it doesn't matter since HandleFunctionRequest will
throw an error shortly anywy).  Hence, not a major bug.

Along the way, add some ability to log fastpath calls when statement
logging is turned on.  This could probably stand to be improved further,
but not logging anything is clearly undesirable.

Backpatched as far as 8.0; bug doesn't exist before that.

src/backend/tcop/fastpath.c
src/backend/tcop/postgres.c

index c410061f274cb89801d395da6b1ba7013396a192..db0d9e050082191eba236c231bc67320d6b73fdd 100644 (file)
@@ -26,6 +26,7 @@
 #include "miscadmin.h"
 #include "mb/pg_wchar.h"
 #include "tcop/fastpath.h"
+#include "tcop/tcopprot.h"
 #include "utils/acl.h"
 #include "utils/lsyscache.h"
 #include "utils/syscache.h"
@@ -302,14 +303,25 @@ HandleFunctionRequest(StringInfo msgBuf)
                                 errmsg("current transaction is aborted, "
                                                "commands ignored until end of transaction block")));
 
+       /*
+        * Now that we know we are in a valid transaction, set snapshot in
+        * case needed by function itself or one of the datatype I/O routines.
+        */
+       ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
+
        /*
         * Begin parsing the buffer contents.
         */
        if (PG_PROTOCOL_MAJOR(FrontendProtocol) < 3)
-               (void) pq_getmsgstring(msgBuf); /* dummy string */
+               (void) pq_getmsgstring(msgBuf);                 /* dummy string */
 
        fid = (Oid) pq_getmsgint(msgBuf, 4);            /* function oid */
 
+       if (log_statement == LOGSTMT_ALL)
+               ereport(LOG,
+                               (errmsg("fastpath function call: function OID %u",
+                                               fid)));
+
        /*
         * There used to be a lame attempt at caching lookup info here. Now we
         * just do the lookups on every call.
index 6248a8651ce2bbb792e0d20ca16059272fa9e021..48bb04ae3aa33f437b5639f8534d0dc7de86c4bd 100644 (file)
@@ -3276,12 +3276,18 @@ PostgresMain(int argc, char *argv[], const char *username)
                                /* start an xact for this function invocation */
                                start_xact_command();
 
+                               /*
+                                * Note: we may at this point be inside an aborted
+                                * transaction.  We can't throw error for that until
+                                * we've finished reading the function-call message, so
+                                * HandleFunctionRequest() must check for it after doing so.
+                                * Be careful not to do anything that assumes we're inside a
+                                * valid transaction here.
+                                */
+
                                /* switch back to message context */
                                MemoryContextSwitchTo(MessageContext);
 
-                               /* set snapshot in case function needs one */
-                               ActiveSnapshot = CopySnapshot(GetTransactionSnapshot());
-
                                if (HandleFunctionRequest(&input_message) == EOF)
                                {
                                        /* lost frontend connection during F message input */