88 *
99 *
1010 * IDENTIFICATION
11- * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.43 2000/07/03 23:09:46 wieck Exp $
11+ * $Header: /cvsroot/pgsql/src/backend/tcop/fastpath.c,v 1.44 2000/10/24 20:59:35 tgl Exp $
1212 *
1313 * NOTES
1414 * This cruft is the server side of PQfn.
@@ -271,9 +271,14 @@ update_fp_info(Oid func_id, struct fp_info * fip)
271271 * Note: All ordinary errors result in elog(ERROR,...). However,
272272 * if we lose the frontend connection there is no one to elog to,
273273 * and no use in proceeding...
274+ *
275+ * Note: palloc()s done here and in the called function do not need to be
276+ * cleaned up explicitly. We are called from PostgresMain() in the
277+ * QueryContext memory context, which will be automatically reset when
278+ * control returns to PostgresMain.
274279 */
275280int
276- HandleFunctionRequest ()
281+ HandleFunctionRequest (void )
277282{
278283 Oid fid ;
279284 int argsize ;
@@ -285,6 +290,32 @@ HandleFunctionRequest()
285290 char * p ;
286291 struct fp_info * fip ;
287292
293+ /*
294+ * XXX FIXME: This protocol is misdesigned.
295+ *
296+ * We really do not want to elog() before having swallowed all of the
297+ * frontend's fastpath message; otherwise we will lose sync with the input
298+ * datastream. What should happen is we absorb all of the input message
299+ * per protocol syntax, and *then* do error checking (including lookup of
300+ * the given function ID) and elog if appropriate. Unfortunately, because
301+ * we cannot even read the message properly without knowing whether the
302+ * data types are pass-by-ref or pass-by-value, it's not all that easy to
303+ * do :-(. The protocol should require the client to supply what it
304+ * thinks is the typbyval and typlen value for each arg, so that we can
305+ * read the data without having to do any lookups. Then after we've read
306+ * the message, we should do the lookups, verify agreement of the actual
307+ * function arg types with what we received, and finally call the function.
308+ *
309+ * As things stand, not only will we lose sync for an invalid message
310+ * (such as requested function OID doesn't exist), but we may lose sync
311+ * for a perfectly valid message if we are in transaction-aborted state!
312+ * This can happen because our database lookup attempts may fail entirely
313+ * in abort state.
314+ *
315+ * Unfortunately I see no way to fix this without breaking a lot of
316+ * existing clients. Maybe do it as part of next protocol version change.
317+ */
318+
288319 if (pq_getint (& tmp , 4 )) /* function oid */
289320 return EOF ;
290321 fid = (Oid ) tmp ;
@@ -293,23 +324,13 @@ HandleFunctionRequest()
293324
294325 /*
295326 * This is where the one-back caching is done. If you want to save
296- * more state, make this a loop around an array.
327+ * more state, make this a loop around an array. Given the relatively
328+ * short lifespan of the cache, not clear that there's any win possible.
297329 */
298330 fip = & last_fp ;
299331 if (!valid_fp_info (fid , fip ))
300332 update_fp_info (fid , fip );
301333
302- /*
303- * XXX FIXME: elog() here means we lose sync with the frontend, since
304- * we have not swallowed all of its input message. What should happen
305- * is we absorb all of the input message per protocol syntax, and
306- * *then* do error checking (including lookup of the given function ID)
307- * and elog if appropriate. Unfortunately, because we cannot even read
308- * the message properly without knowing whether the data types are
309- * pass-by-ref or pass-by-value, it's not all that easy to fix :-(.
310- * This protocol is misdesigned.
311- */
312-
313334 if (fip -> flinfo .fn_nargs != nargs || nargs > FUNC_MAX_ARGS )
314335 {
315336 elog (ERROR , "HandleFunctionRequest: actual arguments (%d) != registered arguments (%d)" ,
@@ -366,6 +387,17 @@ HandleFunctionRequest()
366387 }
367388 }
368389
390+ /*
391+ * Now that we've eaten the input message, check to see if we actually
392+ * want to do the function call or not.
393+ *
394+ * Currently, we report an error if in ABORT state, or return a dummy
395+ * NULL response if fastpath support has been compiled out.
396+ */
397+ if (IsAbortedTransactionBlockState ())
398+ elog (ERROR , "current transaction is aborted, "
399+ "queries ignored until end of transaction block" );
400+
369401#ifdef NO_FASTPATH
370402 /* force a NULL return */
371403 retval = (Datum ) 0 ;
0 commit comments