PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

pqxx riutilizza/riattiva una transazione di lavoro

pqxx::work è solo un pqxx::transaction<> che alla fine ottiene la maggior parte della sua logica da pqxx::transaction_base .

Questa classe non è destinata a servire per più transazioni. Invece, è inteso per una singola transazione all'interno di un blocco try/catch. Ha una variabile membro di stato (m_Status ) che non viene mai reinizializzato, nemmeno dopo un commit.

Lo schema normale è:

{
    pqxx::work l_work(G_connexion);
    try {
        l_work.exec("insert into test.table1(nom) VALUES('foo');");
        l_work.commit();
    } catch (const exception& e) {
        l_work.abort();
        throw;
    }
}

Probabilmente, libpqxx potrebbe eseguire il rollback della transazione in caso di eliminazione (per evitare completamente il try/catch), ma non è così.

Sembra che questo non si adatti al tuo modello di utilizzo poiché desideri G_work essere una variabile globale accessibile da più punti del programma. Tieni presente che pqxx::work non è la classe per gli oggetti di connessione, ma solo un modo per incapsulare begin/commit/rollback con la gestione delle eccezioni C++.

Tuttavia, libpqxx consente anche di eseguire istruzioni al di fuori delle transazioni (o almeno al di fuori delle transazioni gestite da libpqxx). Dovresti usare istanze di pqxx::nontransaction classe.

#include "pqxx/nontransaction"

pqxx::connection G_connexion("dbname=basetest user=usertest password=1234");
pqxx::nontransaction G_work(G_connexion);

int f() {
    G_work.exec("insert into test.table1(nom) VALUES('foo');");
    G_work.exec("insert into test.table1(nom) VALUES('bar');");
}

Tieni presente che questo equivale a:

#include "pqxx/nontransaction"

pqxx::connection G_connexion("dbname=basetest user=usertest password=1234");

int f() {
    pqxx::nontransaction l_work(G_connexion);
    l_work.exec("insert into test.table1(nom) VALUES('foo');");
    l_work.exec("insert into test.table1(nom) VALUES('bar');");
}

Alla fine, niente ti impedisce di gestire le transazioni con pqxx::nontransaction . Ciò è particolarmente vero se desideri punti di salvataggio . Consiglierei anche di usare pqxx::nontransaction se la tua transazione è destinata a durare oltre l'ambito di una funzione (ad es. a livello globale).

#include "pqxx/nontransaction"

pqxx::connection G_connexion("dbname=basetest user=usertest password=1234");
pqxx::nontransaction G_work(G_connexion);

int f() {
    G_work.exec("begin;");
    G_work.exec("insert into test.table1(nom) VALUES('foo');");
    G_work.exec("savepoint f_savepoint;");
    // If the statement fails, rollback to checkpoint.
    try {
        G_work.exec("insert into test.table1(nom) VALUES('bar');");
    } catch (const pqxx::sql_error& e) {
        G_work.exec("rollback to savepoint f_savepoint;");
    }
    G_work.exec("commit;");
}