Commit 70d6226e authored by Peter Eisentraut's avatar Peter Eisentraut

Use portal pinning in PL/Perl and PL/Python

PL/pgSQL "pins" internally generated portals so that user code cannot
close them by guessing their names.  Add this functionality to PL/Perl
and PL/Python as well, preventing users from manually closing cursors
created by spi_query and plpy.cursor, respectively.  (PL/Tcl does not
currently offer any cursor functionality.)
parent 51158541
...@@ -3406,6 +3406,8 @@ plperl_spi_query(char *query) ...@@ -3406,6 +3406,8 @@ plperl_spi_query(char *query)
SPI_result_code_string(SPI_result)); SPI_result_code_string(SPI_result));
cursor = cstr2sv(portal->name); cursor = cstr2sv(portal->name);
PinPortal(portal);
/* Commit the inner transaction, return to outer xact context */ /* Commit the inner transaction, return to outer xact context */
ReleaseCurrentSubTransaction(); ReleaseCurrentSubTransaction();
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
...@@ -3469,6 +3471,7 @@ plperl_spi_fetchrow(char *cursor) ...@@ -3469,6 +3471,7 @@ plperl_spi_fetchrow(char *cursor)
SPI_cursor_fetch(p, true, 1); SPI_cursor_fetch(p, true, 1);
if (SPI_processed == 0) if (SPI_processed == 0)
{ {
UnpinPortal(p);
SPI_cursor_close(p); SPI_cursor_close(p);
row = &PL_sv_undef; row = &PL_sv_undef;
} }
...@@ -3520,7 +3523,10 @@ plperl_spi_cursor_close(char *cursor) ...@@ -3520,7 +3523,10 @@ plperl_spi_cursor_close(char *cursor)
p = SPI_cursor_find(cursor); p = SPI_cursor_find(cursor);
if (p) if (p)
{
UnpinPortal(p);
SPI_cursor_close(p); SPI_cursor_close(p);
}
} }
SV * SV *
...@@ -3884,6 +3890,8 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv) ...@@ -3884,6 +3890,8 @@ plperl_spi_query_prepared(char *query, int argc, SV **argv)
cursor = cstr2sv(portal->name); cursor = cstr2sv(portal->name);
PinPortal(portal);
/* Commit the inner transaction, return to outer xact context */ /* Commit the inner transaction, return to outer xact context */
ReleaseCurrentSubTransaction(); ReleaseCurrentSubTransaction();
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
......
...@@ -151,6 +151,8 @@ PLy_cursor_query(const char *query) ...@@ -151,6 +151,8 @@ PLy_cursor_query(const char *query)
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name); cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
PinPortal(portal);
PLy_spi_subtransaction_commit(oldcontext, oldowner); PLy_spi_subtransaction_commit(oldcontext, oldowner);
} }
PG_CATCH(); PG_CATCH();
...@@ -266,6 +268,8 @@ PLy_cursor_plan(PyObject *ob, PyObject *args) ...@@ -266,6 +268,8 @@ PLy_cursor_plan(PyObject *ob, PyObject *args)
cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name); cursor->portalname = MemoryContextStrdup(cursor->mcxt, portal->name);
PinPortal(portal);
PLy_spi_subtransaction_commit(oldcontext, oldowner); PLy_spi_subtransaction_commit(oldcontext, oldowner);
} }
PG_CATCH(); PG_CATCH();
...@@ -317,7 +321,10 @@ PLy_cursor_dealloc(PyObject *arg) ...@@ -317,7 +321,10 @@ PLy_cursor_dealloc(PyObject *arg)
portal = GetPortalByName(cursor->portalname); portal = GetPortalByName(cursor->portalname);
if (PortalIsValid(portal)) if (PortalIsValid(portal))
{
UnpinPortal(portal);
SPI_cursor_close(portal); SPI_cursor_close(portal);
}
cursor->closed = true; cursor->closed = true;
} }
if (cursor->mcxt) if (cursor->mcxt)
...@@ -508,6 +515,7 @@ PLy_cursor_close(PyObject *self, PyObject *unused) ...@@ -508,6 +515,7 @@ PLy_cursor_close(PyObject *self, PyObject *unused)
return NULL; return NULL;
} }
UnpinPortal(portal);
SPI_cursor_close(portal); SPI_cursor_close(portal);
cursor->closed = true; cursor->closed = true;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment