@@ -24,6 +24,11 @@ constexpr pg::CommandControl kTransactionPoolerDefaultCmdCtl{
2424 std::chrono::seconds{10 },
2525 std::chrono::seconds{10 },
2626};
27+ constexpr pg::CommandControl kTransactionPoolerNoPrepareCmdCtl {
28+ kTransactionPoolerNetworkTimeout ,
29+ kTransactionPoolerStatementTimeout ,
30+ pg::CommandControl::PreparedStatementsOptionOverride::kDisabled ,
31+ };
2732
2833pg::ConnectionSettings MakeTransactionPoolerSettings (const pg::ConnectionSettings& base = kCachePreparedStatements ) {
2934 auto settings = base;
@@ -214,6 +219,39 @@ UTEST_F(PostgreTransactionModeConnection, TransactionPoolerResendsSetConfigWhenC
214219 EXPECT_TRUE (conn->IsIdle ());
215220}
216221
222+ UTEST_F (PostgreTransactionModeConnection, DuplicatePreparedStatementDirtyConnectionIsCleanedUp) {
223+ const pg::Query query{" SELECT 42" };
224+
225+ std::string statement_name;
226+ {
227+ const auto conn = MakeConn ();
228+ UEXPECT_NO_THROW (
229+ statement_name = conn->PrepareStatement (query, {}, utest::kMaxTestWaitTime ).meta_statement_name
230+ );
231+ }
232+ ASSERT_FALSE (statement_name.empty ());
233+
234+ const DefaultCommandControlScope begin_scope{kTransactionPoolerCmdCtl };
235+
236+ const auto conn = MakeConn ();
237+
238+ UEXPECT_NO_THROW (conn->Execute (" PREPARE " + statement_name + " AS SELECT 42" , {}, kTransactionPoolerNoPrepareCmdCtl )
239+ );
240+
241+ UEXPECT_NO_THROW (conn->Begin ({}, {}));
242+ UEXPECT_THROW (conn->Execute (query), pg::DuplicatePreparedStatement);
243+ ASSERT_EQ (pg::ConnectionState::kTranError , conn->GetState ());
244+
245+ const DefaultCommandControlScope cleanup_scope{kTransactionPoolerDefaultCmdCtl };
246+
247+ UEXPECT_NO_THROW (conn->Cleanup (utest::kMaxTestWaitTime ));
248+ EXPECT_EQ (pg::ConnectionState::kIdle , conn->GetState ());
249+ EXPECT_FALSE (conn->IsBroken ());
250+
251+ UEXPECT_NO_THROW (conn->Execute (" SELECT 1" ));
252+ EXPECT_FALSE (conn->IsBroken ());
253+ }
254+
217255} // namespace
218256
219257USERVER_NAMESPACE_END
0 commit comments