8
8
*
9
9
*
10
10
* 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 $
12
12
*
13
13
* NOTES
14
14
* This cruft is the server side of PQfn.
@@ -271,9 +271,14 @@ update_fp_info(Oid func_id, struct fp_info * fip)
271
271
* Note: All ordinary errors result in elog(ERROR,...). However,
272
272
* if we lose the frontend connection there is no one to elog to,
273
273
* 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.
274
279
*/
275
280
int
276
- HandleFunctionRequest ()
281
+ HandleFunctionRequest (void )
277
282
{
278
283
Oid fid ;
279
284
int argsize ;
@@ -285,6 +290,32 @@ HandleFunctionRequest()
285
290
char * p ;
286
291
struct fp_info * fip ;
287
292
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
+
288
319
if (pq_getint (& tmp , 4 )) /* function oid */
289
320
return EOF ;
290
321
fid = (Oid ) tmp ;
@@ -293,23 +324,13 @@ HandleFunctionRequest()
293
324
294
325
/*
295
326
* 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.
297
329
*/
298
330
fip = & last_fp ;
299
331
if (!valid_fp_info (fid , fip ))
300
332
update_fp_info (fid , fip );
301
333
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
-
313
334
if (fip -> flinfo .fn_nargs != nargs || nargs > FUNC_MAX_ARGS )
314
335
{
315
336
elog (ERROR , "HandleFunctionRequest: actual arguments (%d) != registered arguments (%d)" ,
@@ -366,6 +387,17 @@ HandleFunctionRequest()
366
387
}
367
388
}
368
389
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
+
369
401
#ifdef NO_FASTPATH
370
402
/* force a NULL return */
371
403
retval = (Datum ) 0 ;
0 commit comments