Skip to content

Commit 86084cb

Browse files
aleks-ffrwilckens
andauthored
feat(Data::AbstractSessionImpl): add autoCommit property and tests #4261 (#4262)
* fix(Data::AbstracSessionImpl): protect autocommit feature handlers #4261 * chore(CI): re-enable mysql * MySQL SessionImpl: make sure autocommit mode is on when session is openend or reset. * PostgreSQL SessionImpl: reuse autocommit flag of AbstractSessionImpl. * Github workflow: re-activated linux-gcc-make-postgres * Fixed indentation in ci.yml * Fix for DataTest SQLExecutor: use connector * Data::Session: when parser is not used and autocommit mode is off, assume any SQL statement begins a transaction. * PostgreSQL: don't use SQL parser (it currently cannot handle placeholders). * PostgreSQL: added test sessionTransactionNoAutoCommit * PostgreSQL test suite: removed reference to generic SQLExecutor * PostgreSQL: fixes for sessionTransactionNoAutoCommit. * MySQL: added test sessionPoolAndUnicode (from #2801) * Fixed #define in sql-parser * Data generic testsuite: support numbered placeholders * PostgreSQL test suite: added missing include directory to Makefile. * Attempt to fix PostgreSQL Makefiles * PostgreSQL testsuite: added include path to Makefile * PostgreSQL testsuite: added PocoDataTest library to Makefile * DataTest SQLExecutor::formatSQL: don't use string_view * PostgreSQL test suite: delegated most tests to Poco::Data::Test * Makefile: added dependencies on Data-Tests * Weaken assumptions about async in generic transaction tests * Makefile: added dependency for Prometheus samples * Fix deadlock in DataTest SQLExecutor * PostgreSQL tests SQLExecutor: cleanup * feat(Data::AbstractSessionImpl): add autoCommit property and tests #4261 * Brought MySQL backend in line with _autoCommit flag of AbstractSessionImpl. --------- Co-authored-by: Friedrich Wilckens <[email protected]> Co-authored-by: Friedrich Wilckens <[email protected]>
1 parent 80cde9e commit 86084cb

File tree

27 files changed

+441
-1340
lines changed

27 files changed

+441
-1340
lines changed

.github/workflows/ci.yml

Lines changed: 48 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -420,55 +420,55 @@ jobs:
420420
# cd cmake-build;
421421
# ctest --output-on-failure -E "(DataMySQL)|(DataODBC)|(Redis)|(MongoDB)" -C Debug
422422

423-
# linux-gcc-make-mysql:
424-
# runs-on: ubuntu-22.04
425-
# services:
426-
# mysql:
427-
# image: mysql:8.1.0
428-
# env:
429-
# MYSQL_ALLOW_EMPTY_PASSWORD: yes
430-
# MYSQL_USER: pocotest
431-
# MYSQL_PASSWORD: pocotest
432-
# MYSQL_DATABASE: pocotest
433-
# ports:
434-
# - 3306:3306
435-
# steps:
436-
# - uses: actions/checkout@v3
437-
# - run: sudo apt -y update && sudo apt -y install libssl-dev unixodbc-dev libmysqlclient-dev mysql-client
438-
# - run: ./configure --everything --no-samples --omit=ActiveRecord,ApacheConnector,CppParser,Crypto,Data/PostgreSQL,Data/SQLite,Data/ODBC,Encodings,JSON,JWT,MongoDB,Net,NetSSL_OpenSSL,NetSSL_Win,PDF,PageCompiler,PocoDoc,ProGen,Prometheus,Redis,SevenZip,Util,XML,Zip && make all -s -j4 && sudo make install
439-
# - uses: ./.github/actions/retry-action
440-
# with:
441-
# timeout_minutes: 90
442-
# max_attempts: 3
443-
# retry_on: any
444-
# command: >-
445-
# sudo -s
446-
# EXCLUDE_TESTS="ActiveRecord ApacheConnector CppParser CppUnit Crypto Data Data/PostgreSQL Data/ODBC Data/SQLite Encodings Foundation JSON JWT MongoDB Net NetSSL_OpenSSL NetSSL_Win PDF PageCompiler PocoDoc ProGen Prometheus Redis SevenZip Util XML Zip"
447-
# ./ci/runtests.sh
423+
linux-gcc-make-mysql:
424+
runs-on: ubuntu-22.04
425+
services:
426+
mysql:
427+
image: mysql:8.1.0
428+
env:
429+
MYSQL_ALLOW_EMPTY_PASSWORD: yes
430+
MYSQL_USER: pocotest
431+
MYSQL_PASSWORD: pocotest
432+
MYSQL_DATABASE: pocotest
433+
ports:
434+
- 3306:3306
435+
steps:
436+
- uses: actions/checkout@v3
437+
- run: sudo apt -y update && sudo apt -y install libssl-dev unixodbc-dev libmysqlclient-dev mysql-client
438+
- run: ./configure --everything --no-samples --omit=ActiveRecord,ApacheConnector,CppParser,Crypto,Data/PostgreSQL,Data/SQLite,Data/ODBC,Encodings,JSON,JWT,MongoDB,Net,NetSSL_OpenSSL,NetSSL_Win,PDF,PageCompiler,PocoDoc,ProGen,Prometheus,Redis,SevenZip,Util,XML,Zip && make all -s -j4 && sudo make install
439+
- uses: ./.github/actions/retry-action
440+
with:
441+
timeout_minutes: 90
442+
max_attempts: 3
443+
retry_on: any
444+
command: >-
445+
sudo -s
446+
EXCLUDE_TESTS="ActiveRecord ApacheConnector CppParser CppUnit Crypto Data Data/PostgreSQL Data/ODBC Data/SQLite Encodings Foundation JSON JWT MongoDB Net NetSSL_OpenSSL NetSSL_Win PDF PageCompiler PocoDoc ProGen Prometheus Redis SevenZip Util XML Zip"
447+
./ci/runtests.sh
448448
449-
# TODO tests sometimes failling on testTransaction and testReconnect
450-
# linux-gcc-make-postgres:
451-
# runs-on: ubuntu-22.04
452-
# services:
453-
# postgres:
454-
# image: postgres:16.0
455-
# env:
456-
# POSTGRES_PASSWORD: postgres
457-
# ports:
458-
# - 5432:5432
459-
# steps:
460-
# - uses: actions/checkout@v3
461-
# - run: sudo apt -y update && sudo apt -y install libssl-dev unixodbc-dev libmysqlclient-dev odbc-postgresql
462-
# - run: ./configure --everything --no-samples --omit=ActiveRecord,ApacheConnector,CppParser,Crypto,Data/MySQL,Data/ODBC,Data/SQLite,Encodings,JSON,JWT,MongoDB,Net,NetSSL_OpenSSL,NetSSL_Win,PDF,PageCompiler,PocoDoc,ProGen,Prometheus,Redis,SevenZip,Util,XML,Zip && make all -s -j4 && sudo make install
463-
# - uses: ./.github/actions/retry-action
464-
# with:
465-
# timeout_minutes: 90
466-
# max_attempts: 3
467-
# retry_on: any
468-
# command: >-
469-
# sudo -s
470-
# EXCLUDE_TESTS="ActiveRecord ApacheConnector CppParser CppUnit Crypto Data Data/ODBC Data/MySQL Data/SQLite Encodings Foundation JSON JWT MongoDB Net NetSSL_OpenSSL NetSSL_Win PDF PageCompiler PocoDoc ProGen Prometheus Redis SevenZip Util XML Zip"
471-
# ./ci/runtests.sh
449+
# TODO tests sometimes failing on testTransaction and testReconnect
450+
linux-gcc-make-postgres:
451+
runs-on: ubuntu-22.04
452+
services:
453+
postgres:
454+
image: postgres:16.0
455+
env:
456+
POSTGRES_PASSWORD: postgres
457+
ports:
458+
- 5432:5432
459+
steps:
460+
- uses: actions/checkout@v3
461+
- run: sudo apt -y update && sudo apt -y install libssl-dev unixodbc-dev libmysqlclient-dev odbc-postgresql
462+
- run: ./configure --everything --no-samples --omit=ActiveRecord,ApacheConnector,CppParser,Crypto,Data/MySQL,Data/ODBC,Data/SQLite,Encodings,JSON,JWT,MongoDB,Net,NetSSL_OpenSSL,NetSSL_Win,PDF,PageCompiler,PocoDoc,ProGen,Prometheus,Redis,SevenZip,Util,XML,Zip && make all -s -j4 && sudo make install
463+
- uses: ./.github/actions/retry-action
464+
with:
465+
timeout_minutes: 90
466+
max_attempts: 3
467+
retry_on: any
468+
command: >-
469+
sudo -s
470+
EXCLUDE_TESTS="ActiveRecord ApacheConnector CppParser CppUnit Crypto Data Data/ODBC Data/MySQL Data/SQLite Encodings Foundation JSON JWT MongoDB Net NetSSL_OpenSSL NetSSL_Win PDF PageCompiler PocoDoc ProGen Prometheus Redis SevenZip Util XML Zip"
471+
./ci/runtests.sh
472472
473473
linux-gcc-make-redis:
474474
runs-on: ubuntu-22.04

Data/MySQL/include/Poco/Data/MySQL/SessionHandle.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ class SessionHandle
6767
void rollback();
6868
/// Rollback transaction
6969

70+
void autoCommit(bool val);
71+
/// Set autocommit mode
72+
7073
void reset();
7174
/// Reset connection with dababase and clears session state, but without disconnecting
7275

Data/MySQL/src/SessionHandle.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,13 @@ void SessionHandle::rollback()
181181
}
182182

183183

184+
void SessionHandle::autoCommit(bool val)
185+
{
186+
if (mysql_autocommit(_pHandle, val) != 0)
187+
throw TransactionException("Setting autocommit mode failed.", _pHandle);
188+
}
189+
190+
184191
void SessionHandle::reset()
185192
{
186193
#if ((defined (MYSQL_VERSION_ID)) && (MYSQL_VERSION_ID >= 50700)) || ((defined (MARIADB_PACKAGE_VERSION_ID)) && (MARIADB_PACKAGE_VERSION_ID >= 30000))

Data/MySQL/src/SessionImpl.cpp

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,9 @@ void SessionImpl::open(const std::string& connect)
173173
&SessionImpl::autoCommit,
174174
&SessionImpl::isAutoCommit);
175175

176+
// autocommit is initially on when a session is opened
177+
AbstractSessionImpl::setAutoCommit("", true);
178+
176179
_connected = true;
177180
}
178181

@@ -215,18 +218,18 @@ void SessionImpl::rollback()
215218
}
216219

217220

218-
void SessionImpl::autoCommit(const std::string&, bool val)
221+
void SessionImpl::autoCommit(const std::string& s, bool val)
219222
{
220-
StatementExecutor ex(_handle);
221-
ex.prepare(Poco::format("SET autocommit=%d", val ? 1 : 0));
222-
ex.execute();
223+
if (val != getAutoCommit(s)) {
224+
_handle.autoCommit(val);
225+
AbstractSessionImpl::setAutoCommit(s, val);
226+
}
223227
}
224228

225229

226-
bool SessionImpl::isAutoCommit(const std::string&) const
230+
bool SessionImpl::isAutoCommit(const std::string& s) const
227231
{
228-
int ac = 0;
229-
return 1 == getSetting("autocommit", ac);
232+
return AbstractSessionImpl::getAutoCommit(s);
230233
}
231234

232235

@@ -306,6 +309,7 @@ void SessionImpl::reset()
306309
if (_connected && _reset)
307310
{
308311
_handle.reset();
312+
AbstractSessionImpl::setAutoCommit("", true);
309313
}
310314
}
311315

Data/MySQL/testsuite/src/MySQLTest.cpp

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -727,6 +727,15 @@ void MySQLTest::testTupleWithNullable()
727727
}
728728

729729

730+
void MySQLTest::testSessionPoolAndUnicode()
731+
{
732+
if (!_pSession) fail ("Test not available.");
733+
734+
recreateStringsTable();
735+
_pExecutor->sessionPoolAndUnicode(_dbConnString);
736+
}
737+
738+
730739
void MySQLTest::dropTable(const std::string& tableName)
731740
{
732741
try { *_pSession << format("DROP TABLE IF EXISTS %s", tableName), now; }
@@ -993,6 +1002,6 @@ CppUnit::Test* MySQLTest::suite()
9931002
CppUnit_addTest(pSuite, MySQLTest, testSessionTransaction);
9941003
CppUnit_addTest(pSuite, MySQLTest, testTransaction);
9951004
CppUnit_addTest(pSuite, MySQLTest, testReconnect);
996-
1005+
CppUnit_addTest(pSuite, MySQLTest, testSessionPoolAndUnicode);
9971006
return pSuite;
9981007
}

Data/MySQL/testsuite/src/MySQLTest.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ class MySQLTest: public CppUnit::TestCase
107107
void testTransaction();
108108

109109
void testReconnect();
110+
void testSessionPoolAndUnicode();
110111

111112
void setUp();
112113
void tearDown();

Data/MySQL/testsuite/src/SQLExecutor.cpp

Lines changed: 32 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
#include "Poco/Data/Time.h"
2222
#include "Poco/Data/StatementImpl.h"
2323
#include "Poco/Data/RecordSet.h"
24+
#include "Poco/Data/SessionPool.h"
2425
#include "Poco/Data/Transaction.h"
2526
#include "Poco/Data/MySQL/Connector.h"
2627
#include "Poco/Data/MySQL/MySQLException.h"
@@ -1372,7 +1373,7 @@ void SQLExecutor::timestamp()
13721373
std::string firstName("Simpson");
13731374
std::string address("Springfield");
13741375
DateTime birthday(1980, 4, 1, 5, 45, 12, 354, 879);
1375-
1376+
13761377
int count = 0;
13771378
try { *_pSession << "INSERT INTO Person VALUES (?,?,?,?)", use(lastName), use(firstName), use(address), use(birthday), now; }
13781379
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
@@ -1381,14 +1382,14 @@ void SQLExecutor::timestamp()
13811382
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
13821383
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
13831384
assertTrue (count == 1);
1384-
1385+
13851386
DateTime bd;
13861387
assertTrue (bd != birthday);
13871388
try { *_pSession << "SELECT Birthday FROM Person", into(bd), now; }
13881389
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
13891390
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
13901391
assertTrue (bd == birthday);
1391-
1392+
13921393
std::cout << std::endl << RecordSet(*_pSession, "SELECT * FROM Person");
13931394
}
13941395

@@ -2066,3 +2067,31 @@ void SQLExecutor::reconnect()
20662067
assertTrue (count == age);
20672068
assertTrue (_pSession->isConnected());
20682069
}
2070+
2071+
2072+
void SQLExecutor::sessionPoolAndUnicode(const std::string& connString)
2073+
{
2074+
std::string funct = "unicode()";
2075+
std::string text = "ěščřžťďůň";
2076+
std::string text2;
2077+
2078+
// Test uses session from SessionPool instead of _pSession to prove session
2079+
// obtained and returned into pool is valid.
2080+
2081+
// Min/Max 1 session - ensures that when get() is called, same session should be returned
2082+
Poco::SharedPtr<Poco::Data::SessionPool> sp = new Poco::Data::SessionPool(MySQL::Connector::KEY, connString, 1, 1);
2083+
2084+
{
2085+
Poco::Data::Session session = sp->get();
2086+
try { session << "INSERT INTO Strings VALUES (?)", use(text), now; }
2087+
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
2088+
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
2089+
} // parentheses to ensure session is returned into pool
2090+
2091+
Poco::Data::Session session2 = sp->get();
2092+
try { session2 << "SELECT str FROM Strings", into(text2), now; }
2093+
catch(ConnectionException& ce){ std::cout << ce.displayText() << std::endl; fail (funct); }
2094+
catch(StatementException& se){ std::cout << se.displayText() << std::endl; fail (funct); }
2095+
2096+
assertTrue (text == text2);
2097+
}

Data/MySQL/testsuite/src/SQLExecutor.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class SQLExecutor: public CppUnit::TestCase
8888
void longText();
8989
#ifdef POCO_MYSQL_JSON
9090
void json();
91-
#endif
91+
#endif
9292
void unsignedInts();
9393
void floats();
9494
void doubles();
@@ -103,6 +103,7 @@ class SQLExecutor: public CppUnit::TestCase
103103
void transaction(const std::string& connect);
104104

105105
void reconnect();
106+
void sessionPoolAndUnicode(const std::string& connString);
106107

107108
private:
108109
void setTransactionIsolation(Poco::Data::Session& session, Poco::UInt32 ti);

Data/PostgreSQL/Makefile

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,13 @@ objects = Extractor BinaryExtractor Binder SessionImpl Connector \
1212
PostgreSQLStatementImpl PostgreSQLException \
1313
SessionHandle StatementExecutor PostgreSQLTypes Utility
1414

15+
16+
target_includes = $(POCO_BASE)/Data/testsuite/include
1517
ifndef POCO_DATA_NO_SQL_PARSER
16-
target_includes = $(POCO_BASE)/Data/src
18+
target_includes += $(POCO_BASE)/Data/src
1719
endif
1820

21+
1922
target = PocoDataPostgreSQL
2023
target_version = $(LIBVERSION)
2124
target_libs = PocoData PocoFoundation

Data/PostgreSQL/include/Poco/Data/PostgreSQL/SessionHandle.h

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -118,7 +118,7 @@ class SessionHandle
118118
bool isAutoCommit() const;
119119
/// is the connection in auto commit mode?
120120

121-
void setAutoCommit(bool aShouldAutoCommit = true);
121+
void autoCommit(bool val);
122122
/// is the connection in auto commit mode?
123123

124124
bool isAsynchronousCommit() const;
@@ -193,7 +193,6 @@ class SessionHandle
193193
PGconn* _pConnection;
194194
std::string _connectionString;
195195
bool _inTransaction;
196-
bool _isAutoCommit;
197196
bool _isAsynchronousCommit;
198197
Poco::UInt32 _tranactionIsolationLevel;
199198
std::vector <std::string> _preparedStatementsToBeDeallocated;
@@ -306,12 +305,6 @@ inline bool SessionHandle::isTransaction() const
306305
}
307306

308307

309-
inline bool SessionHandle::isAutoCommit() const
310-
{
311-
return _isAutoCommit;
312-
}
313-
314-
315308
inline bool SessionHandle::isAsynchronousCommit() const
316309
{
317310
return _isAsynchronousCommit;

0 commit comments

Comments
 (0)