PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

pqxx réutiliser / réactiver une transaction de travail

pqxx::work est juste un pqxx::transaction<> qui obtient finalement la majeure partie de sa logique de pqxx::transaction_base .

Cette classe n'est pas destinée à servir pour plusieurs transactions. Au lieu de cela, il est destiné à une seule transaction dans un bloc try/catch. Il a une variable de membre d'état (m_Status ) qui n'est jamais réinitialisé, même après un commit.

Le modèle normal est :

{
    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;
    }
}

On peut dire que libpqxx pourrait annuler la transaction lors de la suppression (pour éviter complètement le try/catch), mais ce n'est pas le cas.

Il semble que cela ne corresponde pas à votre modèle d'utilisation comme vous le souhaitez G_work être une variable globale accessible depuis plusieurs endroits de votre programme. Veuillez noter que pqxx::work n'est pas la classe des objets de connexion, mais juste un moyen d'encapsuler begin/commit/rollback avec la gestion des exceptions C++.

Néanmoins, libpqxx vous permet également d'exécuter des instructions en dehors des transactions (ou du moins en dehors des transactions gérées par libpqxx). Vous devez utiliser des instances de 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');");
}

Veuillez noter que cela équivaut à :

#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');");
}

Finalement, rien ne vous empêche de gérer les transactions avec pqxx::nontransaction . Cela est particulièrement vrai si vous voulez des des points de sauvegarde . Je conseillerais également d'utiliser pqxx::nontransaction si votre transaction est censée durer au-delà d'une portée de fonction (par exemple, à portée 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;");
}