Skip to content

Commit a591a48

Browse files
committed
fix: add error handling for SPI calls in autonomous functions
- Check SPI_connect() return value before proceeding - Wrap SPI operations in PG_TRY/PG_CATCH to prevent memory leaks - Add utils/datum.h include for datumCopy() function - Ensure pfree(query) and SPI_finish() always execute on error paths
1 parent 3ebc4e8 commit a591a48

1 file changed

Lines changed: 44 additions & 24 deletions

File tree

src/pl/plisql/src/pl_autonomous.c

Lines changed: 44 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "parser/parse_func.h"
2323
#include "parser/parse_type.h"
2424
#include "utils/builtins.h"
25+
#include "utils/datum.h"
2526
#include "utils/guc.h"
2627
#include "utils/inval.h"
2728
#include "utils/lsyscache.h"
@@ -342,36 +343,55 @@ execute_autonomous_function(char *connstr, char *sql, Oid rettype, FunctionCallI
342343
quote_literal_cstr(sql),
343344
format_type_be(rettype));
344345

345-
/* Execute via SPI */
346-
SPI_connect();
346+
/* Execute via SPI with proper error handling */
347+
PG_TRY();
348+
{
349+
/* Connect to SPI */
350+
ret = SPI_connect();
351+
if (ret < 0)
352+
ereport(ERROR,
353+
(errcode(ERRCODE_INTERNAL_ERROR),
354+
errmsg("could not connect to SPI for autonomous function execution"),
355+
errdetail("SPI_connect returned %d", ret)));
347356

348-
ret = SPI_execute(query, true, 1);
349-
if (ret != SPI_OK_SELECT)
350-
ereport(ERROR,
351-
(errcode(ERRCODE_INTERNAL_ERROR),
352-
errmsg("autonomous function execution failed"),
353-
errdetail("SPI_execute returned %d", ret)));
357+
/* Execute the query */
358+
ret = SPI_execute(query, true, 1);
359+
if (ret != SPI_OK_SELECT)
360+
ereport(ERROR,
361+
(errcode(ERRCODE_INTERNAL_ERROR),
362+
errmsg("autonomous function execution failed"),
363+
errdetail("SPI_execute returned %d", ret)));
354364

355-
if (SPI_processed != 1)
356-
ereport(ERROR,
357-
(errcode(ERRCODE_INTERNAL_ERROR),
358-
errmsg("autonomous function returned unexpected number of rows: %lu",
359-
(unsigned long) SPI_processed)));
365+
if (SPI_processed != 1)
366+
ereport(ERROR,
367+
(errcode(ERRCODE_INTERNAL_ERROR),
368+
errmsg("autonomous function returned unexpected number of rows: %lu",
369+
(unsigned long) SPI_processed)));
370+
371+
/* Extract return value from result */
372+
result = SPI_getbinval(SPI_tuptable->vals[0],
373+
SPI_tuptable->tupdesc,
374+
1,
375+
&isnull);
360376

361-
/* Extract return value from result */
362-
result = SPI_getbinval(SPI_tuptable->vals[0],
363-
SPI_tuptable->tupdesc,
364-
1,
365-
&isnull);
377+
/* Get type information for datumCopy */
378+
get_typlenbyval(rettype, &typlen, &typbyval);
366379

367-
/* Get type information for datumCopy */
368-
get_typlenbyval(rettype, &typlen, &typbyval);
380+
/* Copy result to upper context before SPI_finish frees SPI memory */
381+
if (!isnull && !typbyval)
382+
result = datumCopy(result, typbyval, typlen);
369383

370-
/* Copy result to upper context before SPI_finish frees SPI memory */
371-
if (!isnull && !typbyval)
372-
result = datumCopy(result, typbyval, typlen);
384+
SPI_finish();
385+
}
386+
PG_CATCH();
387+
{
388+
/* Clean up on error */
389+
SPI_finish();
390+
pfree(query);
391+
PG_RE_THROW();
392+
}
393+
PG_END_TRY();
373394

374-
SPI_finish();
375395
pfree(query);
376396

377397
fcinfo->isnull = isnull;

0 commit comments

Comments
 (0)