Re: assert in nested SQL procedure call in current HEAD

2018-07-14 Thread Peter Eisentraut
On 12.07.18 18:43, Andres Freund wrote:
> On 2018-06-29 13:52:23 +0200, Peter Eisentraut wrote:
>> From 95fc7156afe521b715fab08d44606774df875e92 Mon Sep 17 00:00:00 2001
>> From: Peter Eisentraut 
>> Date: Fri, 29 Jun 2018 13:28:39 +0200
>> Subject: [PATCH] Fix assert in nested SQL procedure call
> 
> Andrew, Peter, are you happy with this? It'd be good to close this open
> item.

Yes, it's done.  I'm going to update the wiki.

-- 
Peter Eisentraut  http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: assert in nested SQL procedure call in current HEAD

2018-07-12 Thread Peter Eisentraut
On 12.06.18 18:47, Andrew Gierth wrote:
> While testing this, I ran into another semi-related issue:
> shmem_exit_inprogress isn't ever being cleared in the postmaster, which
> means that if you ever have a crash-restart, any attempt to do a
> rollback in a procedure will then crash or get some other form of
> corruption again every time until you manually restart the cluster.

I have committed a fix for this.

-- 
Peter Eisentraut  http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: assert in nested SQL procedure call in current HEAD

2018-07-12 Thread Andres Freund
Hi,

On 2018-06-29 13:52:23 +0200, Peter Eisentraut wrote:
> From 95fc7156afe521b715fab08d44606774df875e92 Mon Sep 17 00:00:00 2001
> From: Peter Eisentraut 
> Date: Fri, 29 Jun 2018 13:28:39 +0200
> Subject: [PATCH] Fix assert in nested SQL procedure call

Andrew, Peter, are you happy with this? It'd be good to close this open
item.

- Andres



Re: assert in nested SQL procedure call in current HEAD

2018-06-29 Thread Peter Eisentraut
On 12.06.18 18:47, Andrew Gierth wrote:
> While testing this, I ran into another semi-related issue:
> shmem_exit_inprogress isn't ever being cleared in the postmaster, which
> means that if you ever have a crash-restart, any attempt to do a
> rollback in a procedure will then crash or get some other form of
> corruption again every time until you manually restart the cluster.

I think we could unset shmem_exit_inprogress at the end of shmem_exit().
 I'm trying to remember why we didn't just use proc_exit_inprogress for
this.  I'll need to test this more.

-- 
Peter Eisentraut  http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: assert in nested SQL procedure call in current HEAD

2018-06-29 Thread Peter Eisentraut
On 6/27/18 18:51, Peter Eisentraut wrote:
> On 6/27/18 17:44, Andres Freund wrote:
>> This hasn't progressed in a while. Peter, since you committed the
>> relevant change, could you update us please?
> 
> I've been on vacation for a bit.  I will work on this next.  I hope to
> have a solution in a few days.

Proposed patch attached.

-- 
Peter Eisentraut  http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services
From 95fc7156afe521b715fab08d44606774df875e92 Mon Sep 17 00:00:00 2001
From: Peter Eisentraut 
Date: Fri, 29 Jun 2018 13:28:39 +0200
Subject: [PATCH] Fix assert in nested SQL procedure call

When executing CALL in PL/pgSQL, we need to set a snapshot before
invoking the to-be-called procedure.  Otherwise, the to-be-called
procedure might end up running without a snapshot.  For LANGUAGE SQL
procedures, this would result in an assertion failure.  (For most other
languages, this is usually not a problem, because those use SPI and SPI
sets snapshots in most cases.)  Setting the snapshot restores the
behavior of how CALL worked when it was handled as a generic SQL
statement in PL/pgSQL (exec_stmt_execsql()).

This change revealed another problem:  In SPI_commit(), we popped the
active snapshot before committing the transaction, to avoid "snapshot %p
still active" errors.  However, there is no particular reason why only
at most one snapshot should be on the stack.  So change this to pop all
active snapshots instead of only one.
---
 src/backend/executor/spi.c|  7 +++-
 .../src/expected/plpgsql_transaction.out  | 19 +++
 src/pl/plpgsql/src/pl_exec.c  | 32 ---
 .../plpgsql/src/sql/plpgsql_transaction.sql   | 20 
 4 files changed, 72 insertions(+), 6 deletions(-)

diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c
index 22dd55c378..5756365c8f 100644
--- a/src/backend/executor/spi.c
+++ b/src/backend/executor/spi.c
@@ -228,8 +228,13 @@ SPI_commit(void)
 
_SPI_current->internal_xact = true;
 
-   if (ActiveSnapshotSet())
+   /*
+* Before committing, pop all active snapshots to avoid error about
+* "snapshot %p still active".
+*/
+   while (ActiveSnapshotSet())
PopActiveSnapshot();
+
CommitTransactionCommand();
MemoryContextSwitchTo(oldcontext);
 
diff --git a/src/pl/plpgsql/src/expected/plpgsql_transaction.out 
b/src/pl/plpgsql/src/expected/plpgsql_transaction.out
index 7f008ac57e..274b2c6f17 100644
--- a/src/pl/plpgsql/src/expected/plpgsql_transaction.out
+++ b/src/pl/plpgsql/src/expected/plpgsql_transaction.out
@@ -432,6 +432,25 @@ END;
 $$;
 ERROR:  EXECUTE of transaction commands is not implemented
 CONTEXT:  PL/pgSQL function inline_code_block line 3 at EXECUTE
+-- snapshot handling test
+TRUNCATE test2;
+CREATE PROCEDURE transaction_test9()
+LANGUAGE SQL
+AS $$
+INSERT INTO test2 VALUES (42);
+$$;
+DO LANGUAGE plpgsql $$
+BEGIN
+  ROLLBACK;
+  CALL transaction_test9();
+END
+$$;
+SELECT * FROM test2;
+ x  
+
+ 42
+(1 row)
+
 DROP TABLE test1;
 DROP TABLE test2;
 DROP TABLE test3;
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 66ecf5eb55..e39f7357bd 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -2075,6 +2075,7 @@ exec_stmt_call(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_call *stmt)
ParamListInfo paramLI;
LocalTransactionId before_lxid;
LocalTransactionId after_lxid;
+   boolpushed_active_snap = false;
int rc;
 
if (expr->plan == NULL)
@@ -2090,6 +2091,7 @@ exec_stmt_call(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_call *stmt)
/*
 * The procedure call could end transactions, which would upset 
the
 * snapshot management in SPI_execute*, so don't let it do it.
+* Instead, we set the snapshots ourselves below.
 */
expr->plan->no_snapshots = true;
}
@@ -2098,6 +2100,16 @@ exec_stmt_call(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_call *stmt)
 
before_lxid = MyProc->lxid;
 
+   /*
+* Set snapshot only for non-read-only procedures, similar to SPI
+* behavior.
+*/
+   if (!estate->readonly_func)
+   {
+   PushActiveSnapshot(GetTransactionSnapshot());
+   pushed_active_snap = true;
+   }
+
PG_TRY();
{
rc = SPI_execute_plan_with_paramlist(expr->plan, paramLI,
@@ -2126,12 +2138,22 @@ exec_stmt_call(PLpgSQL_execstate *estate, 
PLpgSQL_stmt_call *stmt)
elog(ERROR, "SPI_execute_plan_with_paramlist failed executing 
query \"%s\": %s",
 expr->query, SPI_result_code_string(rc));
 
-   /*
-* If we are in a new transaction after the call, we need to reset some
-* internal state.
-*/
-   if (befo

Re: assert in nested SQL procedure call in current HEAD

2018-06-27 Thread Peter Eisentraut
On 6/27/18 17:44, Andres Freund wrote:
> This hasn't progressed in a while. Peter, since you committed the
> relevant change, could you update us please?

I've been on vacation for a bit.  I will work on this next.  I hope to
have a solution in a few days.

-- 
Peter Eisentraut  http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: assert in nested SQL procedure call in current HEAD

2018-06-27 Thread Andres Freund
Hi Peter,

On 2018-06-10 21:06:59 +0200, Dmitry Dolgov wrote:
> > On 8 June 2018 at 06:20, Andrew Gierth  wrote:
> 
> >  Joe> My colleague Yogesh Sharma discovered an assert in nested SQL
> >  Joe> procedure calls after ROLLBACK is used. Minimal test case and
> >  Joe> backtrace below. I have not yet tried to figure out exactly what
> >  Joe> is going on beyond seeing that it occurs in pg_plan_query() where
> >  Joe> the comment says "Planner must have a snapshot in case it calls
> >  Joe> user-defined functions"...
> >
> >  Andrew> 
> > https://www.postgresql.org/message-id/29608.1518533...@sss.pgh.pa.us
> >
> > I added it to the open items list since nobody else seems to have taken
> > notice; from Tom's linked message it seems this should be Peter E's bag?
> 
> I've taken a look at this - indeed, the situation looks similar to what
> described in the linked message, namely after a transaction rollback and
> creation of a new one no active snapshot was pushed. But in this particular
> case the timeframe without an active snapshot is actually limited and includes
> only some initialization and planning activity (after that a new one is
> pushed). The commentary says that "Planner must have a snapshot in case it
> calls user-defined functions." -  I tried to simulate this in order to see 
> what
> would happen, but got no errors. Is there a chance that it's an outdated
> Assert?

This hasn't progressed in a while. Peter, since you committed the
relevant change, could you update us please?

Greetings,

Andres Freund



Re: assert in nested SQL procedure call in current HEAD

2018-06-12 Thread Andrew Gierth
> "Peter" == Peter Eisentraut  writes:

 >> Did you miss the fact that the issue only occurs when the top-level
 >> procedure does a rollback? The problem is not with nested calls, but
 >> rather with the fact that commit or rollback is leaving
 >> ActiveSnapshot unset, which is (as Tom pointed out at the linked
 >> post) not the expected condition inside PL code.

 Peter> We need that so that we can run things like SET TRANSACTION
 Peter> ISOLATION.

While testing this, I ran into another semi-related issue:
shmem_exit_inprogress isn't ever being cleared in the postmaster, which
means that if you ever have a crash-restart, any attempt to do a
rollback in a procedure will then crash or get some other form of
corruption again every time until you manually restart the cluster.

-- 
Andrew (irc:RhodiumToad)



Re: assert in nested SQL procedure call in current HEAD

2018-06-12 Thread Peter Eisentraut
On 6/12/18 10:03, Andrew Gierth wrote:
>> "Peter" == Peter Eisentraut  writes:
> 
>  Peter> The problem with these nested procedure calls is that if the
>  Peter> nested call
> 
> Did you miss the fact that the issue only occurs when the top-level
> procedure does a rollback? The problem is not with nested calls, but
> rather with the fact that commit or rollback is leaving ActiveSnapshot
> unset, which is (as Tom pointed out at the linked post) not the expected
> condition inside PL code.

We need that so that we can run things like SET TRANSACTION ISOLATION.

-- 
Peter Eisentraut  http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: assert in nested SQL procedure call in current HEAD

2018-06-12 Thread Andrew Gierth
> "Peter" == Peter Eisentraut  writes:

 Peter> The problem with these nested procedure calls is that if the
 Peter> nested call

Did you miss the fact that the issue only occurs when the top-level
procedure does a rollback? The problem is not with nested calls, but
rather with the fact that commit or rollback is leaving ActiveSnapshot
unset, which is (as Tom pointed out at the linked post) not the expected
condition inside PL code.

-- 
Andrew (irc:RhodiumToad)



Re: assert in nested SQL procedure call in current HEAD

2018-06-12 Thread Peter Eisentraut
On 6/10/18 15:06, Dmitry Dolgov wrote:
>> I added it to the open items list since nobody else seems to have taken
>> notice; from Tom's linked message it seems this should be Peter E's bag?
> I've taken a look at this - indeed, the situation looks similar to what
> described in the linked message, namely after a transaction rollback and
> creation of a new one no active snapshot was pushed. But in this particular
> case the timeframe without an active snapshot is actually limited and includes
> only some initialization and planning activity (after that a new one is
> pushed). The commentary says that "Planner must have a snapshot in case it
> calls user-defined functions." -  I tried to simulate this in order to see 
> what
> would happen, but got no errors. Is there a chance that it's an outdated
> Assert?

The problem with these nested procedure calls is that if the nested call
does a commit, you would get the dreaded "snapshot %p still active"
warning.  So PL/pgSQL in combination with SPI is going out of its way to
make sure that there is no active snapshot when we call out to
ProcessUtility() for the nested CALL.  However, if whatever the nested
CALL executes requires an active snapshot to be set, then there is this
problem.  Apparently, the LANGUAGE SQL procedure requires a snapshot to
be set previously.  This is not a problem, for example, if you replace
the example procedure with LANGUAGE plpgsql, which does its own snapshot
management.  So perhaps a fix here is to teach the LANGUAGE SQL handler
to set a snapshot if there isn't one already.  That would make the
different language handlers behave consistently.  (The alternative is to
get rid of the warning in snapmgr.c.)

-- 
Peter Eisentraut  http://www.2ndQuadrant.com/
PostgreSQL Development, 24x7 Support, Remote DBA, Training & Services



Re: assert in nested SQL procedure call in current HEAD

2018-06-10 Thread Dmitry Dolgov
> On 8 June 2018 at 06:20, Andrew Gierth  wrote:

>  Joe> My colleague Yogesh Sharma discovered an assert in nested SQL
>  Joe> procedure calls after ROLLBACK is used. Minimal test case and
>  Joe> backtrace below. I have not yet tried to figure out exactly what
>  Joe> is going on beyond seeing that it occurs in pg_plan_query() where
>  Joe> the comment says "Planner must have a snapshot in case it calls
>  Joe> user-defined functions"...
>
>  Andrew> https://www.postgresql.org/message-id/29608.1518533...@sss.pgh.pa.us
>
> I added it to the open items list since nobody else seems to have taken
> notice; from Tom's linked message it seems this should be Peter E's bag?

I've taken a look at this - indeed, the situation looks similar to what
described in the linked message, namely after a transaction rollback and
creation of a new one no active snapshot was pushed. But in this particular
case the timeframe without an active snapshot is actually limited and includes
only some initialization and planning activity (after that a new one is
pushed). The commentary says that "Planner must have a snapshot in case it
calls user-defined functions." -  I tried to simulate this in order to see what
would happen, but got no errors. Is there a chance that it's an outdated
Assert?



Re: assert in nested SQL procedure call in current HEAD

2018-06-07 Thread Andrew Gierth
> "Andrew" == Andrew Gierth  writes:

> "Joe" == Joe Conway  writes:

 Joe> My colleague Yogesh Sharma discovered an assert in nested SQL
 Joe> procedure calls after ROLLBACK is used. Minimal test case and
 Joe> backtrace below. I have not yet tried to figure out exactly what
 Joe> is going on beyond seeing that it occurs in pg_plan_query() where
 Joe> the comment says "Planner must have a snapshot in case it calls
 Joe> user-defined functions"...

 Andrew> https://www.postgresql.org/message-id/29608.1518533...@sss.pgh.pa.us

I added it to the open items list since nobody else seems to have taken
notice; from Tom's linked message it seems this should be Peter E's bag?

-- 
Andrew (irc:RhodiumToad)



Re: assert in nested SQL procedure call in current HEAD

2018-05-25 Thread Andrew Gierth
> "Joe" == Joe Conway  writes:

 Joe> My colleague Yogesh Sharma discovered an assert in nested SQL
 Joe> procedure calls after ROLLBACK is used. Minimal test case and
 Joe> backtrace below. I have not yet tried to figure out exactly what
 Joe> is going on beyond seeing that it occurs in pg_plan_query() where
 Joe> the comment says "Planner must have a snapshot in case it calls
 Joe> user-defined functions"...

https://www.postgresql.org/message-id/29608.1518533...@sss.pgh.pa.us

-- 
Andrew (irc:RhodiumToad)