summaryrefslogtreecommitdiff
path: root/src/pl/plperl/plperl.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/pl/plperl/plperl.c')
-rw-r--r--src/pl/plperl/plperl.c69
1 files changed, 67 insertions, 2 deletions
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 10feef11cf3..77c41b28215 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1929,7 +1929,7 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
current_call_data = &this_call_data;
- if (SPI_connect() != SPI_OK_CONNECT)
+ if (SPI_connect_ext(codeblock->atomic ? 0 : SPI_OPT_NONATOMIC) != SPI_OK_CONNECT)
elog(ERROR, "could not connect to SPI manager");
select_perl_context(desc.lanpltrusted);
@@ -2396,13 +2396,18 @@ plperl_call_perl_event_trigger_func(plperl_proc_desc *desc,
static Datum
plperl_func_handler(PG_FUNCTION_ARGS)
{
+ bool nonatomic;
plperl_proc_desc *prodesc;
SV *perlret;
Datum retval = 0;
ReturnSetInfo *rsi;
ErrorContextCallback pl_error_context;
- if (SPI_connect() != SPI_OK_CONNECT)
+ nonatomic = fcinfo->context &&
+ IsA(fcinfo->context, CallContext) &&
+ !castNode(CallContext, fcinfo->context)->atomic;
+
+ if (SPI_connect_ext(nonatomic ? SPI_OPT_NONATOMIC : 0) != SPI_OK_CONNECT)
elog(ERROR, "could not connect to SPI manager");
prodesc = compile_plperl_function(fcinfo->flinfo->fn_oid, false, false);
@@ -3953,6 +3958,66 @@ plperl_spi_freeplan(char *query)
SPI_freeplan(plan);
}
+void
+plperl_spi_commit(void)
+{
+ MemoryContext oldcontext = CurrentMemoryContext;
+
+ PG_TRY();
+ {
+ if (ThereArePinnedPortals())
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot commit transaction while a cursor is open")));
+
+ SPI_commit();
+ SPI_start_transaction();
+ }
+ PG_CATCH();
+ {
+ ErrorData *edata;
+
+ /* Save error info */
+ MemoryContextSwitchTo(oldcontext);
+ edata = CopyErrorData();
+ FlushErrorState();
+
+ /* Punt the error to Perl */
+ croak_cstr(edata->message);
+ }
+ PG_END_TRY();
+}
+
+void
+plperl_spi_rollback(void)
+{
+ MemoryContext oldcontext = CurrentMemoryContext;
+
+ PG_TRY();
+ {
+ if (ThereArePinnedPortals())
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_TRANSACTION_TERMINATION),
+ errmsg("cannot abort transaction while a cursor is open")));
+
+ SPI_rollback();
+ SPI_start_transaction();
+ }
+ PG_CATCH();
+ {
+ ErrorData *edata;
+
+ /* Save error info */
+ MemoryContextSwitchTo(oldcontext);
+ edata = CopyErrorData();
+ FlushErrorState();
+
+ /* Punt the error to Perl */
+ croak_cstr(edata->message);
+ }
+ PG_END_TRY();
+}
+
/*
* Implementation of plperl's elog() function
*