This is an answer rather than a question which I need to state in SO anyway. I was struggle with this question ("how to turn off autocommit when using soci library with PostgreSQL databases") for a long time and came up with several solutions.
In Oracle, by default the auto commit option is turned off and we have to call soci::session::commit
explicitly to commit the transactions we have made but in PostgreSQL this is other way around and it will commit as soon as we execute a sql statement (correct me, if I'm wrong). This will introduce problems when we write applications database independently. The soci library provide soci::transaction
in order to address this.
So, when we initialize a soci::transaction
by providing the soci::session
to that, it will hold the transaction we have made without commiting to the database. At the end when we call soci::transaction::commit
it will commit the changes to the database.
soci::session sql(CONNECTION_STRING);
soci::transaction tr(sql);
try {
sql << "insert into soci_test(id, name) values(7, \'John\')";
tr.commit();
}
catch (std::exception& e) {
tr.rollback();
}
But, performing commit
or rollback
will end the transaction tr
and we need to initialize another soci::transaction
in order to hold future transactions (to create an active in progress transaction) we are about to make. Here are more fun facts about soci::transaction
.
- You can have only one
soci::transaction
instance persoci::session
. The second one will replace the first one, if you initialize another. - You can not perform more than a single
commit
orrollback
using asoci::transaction
. You will receive an exception, at the second time you do commit or rollback. - You can initialize a
transaction
, then usesession::commit
orsession::rollback
. It will give the same result astransaction::commit
ortransaction::rollback
. But the transaction will end as soon as you perform single commit or rollback as usual. - It doesn't matter the visibility of the
soci::transaction
object to your scope (where you execute the sql and call commit or rollback) in order to hold the db transactions you made until explicitly commit or rollback. In other words, if there is an activetransaction
in progress for asession
, db transactions will hold until we explicitly commit or rollback. - But, if the lifetime of the
transaction
instance which created for thesession
was end, we cannot expect the db transactions will be halt. - If you every suffer with "WARNING: there is no transaction in progress", you have to perform commit or rollback only using
soci::transaction::commit
orsoci::transaction::rollback
.
Now I will post the solution which I came up with, in order to enable the explicit commit or rollback with any database backend.