PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

pqxx reutilizar/reativar uma transação de trabalho


pqxx::work é apenas um pqxx::transaction<> que eventualmente obtém a maior parte de sua lógica de pqxx::transaction_base .

Esta classe não se destina a servir para várias transações. Em vez disso, destina-se a uma única transação dentro de um bloco try/catch. Tem uma variável de membro de estado (m_Status ) que nunca é reinicializado, mesmo após um commit.

O padrão normal é:
{
    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;
    }
}

Indiscutivelmente, libpqxx poderia reverter a transação na exclusão (para evitar totalmente o try/catch), mas isso não acontece.

Parece que isso não se encaixa no seu padrão de uso como você deseja G_work para ser uma variável global acessível de vários lugares em seu programa. Observe que pqxx::work não é a classe para objetos de conexão, mas apenas uma maneira de encapsular begin/commit/rollback com tratamento de exceções C++.

No entanto, libpqxx também permite que você execute comandos fora de transações (ou pelo menos fora de transações gerenciadas por libpqxx). Você deve usar instâncias 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');");
}

Observe que isso é equivalente 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');");
}

Eventualmente, nada impede que você gerencie transações com pqxx::nontransaction . Isso é especialmente verdadeiro se você deseja savepoints . Eu também aconselharia usar pqxx::nontransaction se sua transação deve durar além de um escopo de função (por exemplo, no escopo global).
#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;");
}