From 65add865fddffe7eb01d4eca2d3d6d99daca64a8 Mon Sep 17 00:00:00 2001 From: Rafi Shamim Date: Mon, 17 Aug 2020 16:49:55 -0400 Subject: [PATCH] sql: allow DEALLOCATE ALL with a prepared statement PR #48842 added logic to exhaust portals after executing them. This had issues when the portal being executed closes itself, which happens when using DEALLOCATE in a prepared statement. Now we check if the portal still exists before exhausting it. There is no release note as this fixes a bug that only exists in unreleased versions. Release note: None --- pkg/sql/conn_executor_exec.go | 6 +++- pkg/sql/pgwire/testdata/pgtest/pgjdbc | 52 +++++++++++++++++++++++++++ 2 files changed, 57 insertions(+), 1 deletion(-) diff --git a/pkg/sql/conn_executor_exec.go b/pkg/sql/conn_executor_exec.go index d85dbd3394b9..6311879a4fc3 100644 --- a/pkg/sql/conn_executor_exec.go +++ b/pkg/sql/conn_executor_exec.go @@ -157,7 +157,11 @@ func (ex *connExecutor) execPortal( // Note that the portal is considered exhausted regardless of // the fact whether an error occurred or not - if it did, we // still don't want to re-execute the portal from scratch. - ex.exhaustPortal(portalName) + // The current statement may have just closed and deleted the portal, + // so only exhaust it if it still exists. + if _, ok := ex.extraTxnState.prepStmtsNamespace.portals[portalName]; ok { + ex.exhaustPortal(portalName) + } } default: ev, payload, err = ex.execStmt(stmtCtx, curStmt, stmtRes, pinfo) diff --git a/pkg/sql/pgwire/testdata/pgtest/pgjdbc b/pkg/sql/pgwire/testdata/pgtest/pgjdbc index 864572d153e6..64d0579a7887 100644 --- a/pkg/sql/pgwire/testdata/pgtest/pgjdbc +++ b/pkg/sql/pgwire/testdata/pgtest/pgjdbc @@ -1,3 +1,55 @@ +# deallocate_test checks that we can run DEALLOCATE ALL using a prepared +# statement. See #52915. +send +Query {"String": "DROP TABLE IF EXISTS deallocate_test"} +---- + +until ignore=NoticeResponse +ReadyForQuery +---- +{"Type":"CommandComplete","CommandTag":"DROP TABLE"} +{"Type":"ReadyForQuery","TxStatus":"I"} + +send +Query {"String": "CREATE TABLE deallocate_test (a INT)"} +---- + +until +ReadyForQuery +---- +{"Type":"CommandComplete","CommandTag":"CREATE TABLE"} +{"Type":"ReadyForQuery","TxStatus":"I"} + +# 80 = ASCII 'P' for Portal +send +Parse {"Name": "s1", "Query": "DEALLOCATE ALL"} +Bind {"DestinationPortal": "p1", "PreparedStatement": "s1"} +Describe {"ObjectType": 80, "Name": "p1"} +Execute {"Portal": "p1"} +Sync +---- + +until +ReadyForQuery +---- +{"Type":"ParseComplete"} +{"Type":"BindComplete"} +{"Type":"NoData"} +{"Type":"CommandComplete","CommandTag":"DEALLOCATE ALL"} +{"Type":"ReadyForQuery","TxStatus":"I"} + +send +Query {"String": "DISCARD ALL"} +---- + +until +ReadyForQuery +---- +{"Type":"ParameterStatus","Name":"application_name","Value":""} +{"Type":"ParameterStatus","Name":"TimeZone","Value":"UTC"} +{"Type":"CommandComplete","CommandTag":"DISCARD"} +{"Type":"ReadyForQuery","TxStatus":"I"} + # Send a simple query in the middle of extended protocol, which is apparently # allowed. (See #41511, #33693) send