pg: Rework txn implementation + statement config API

I liked the Perl implementation of transactions, but managing state
between Perl and C is a bit cumbersome, so I've moved the whole thing
into C.

Also added a few statement configuration methods that currently don't do
anything yet.
This commit is contained in:
Yorhel 2025-02-07 18:30:33 +01:00
parent 8f94dd0921
commit 166744dd51
7 changed files with 335 additions and 186 deletions

112
FU.xs
View file

@ -16,13 +16,21 @@
#define FUPG_CONN_COOKIE \
if (c->cookie) fu_confess("Invalid attempt to run a query on the top-level connection while a transaction object exists")
if (c->cookie) fu_confess("Invalid operation on the top-level connection while a transaction object exists")
#define FUPG_TXN_COOKIE \
if (!t->cookie) fu_confess("Invalid operation on a transaction that has already been marked as done"); \
if (t->cookie != t->conn->cookie) fu_confess("Invalid operation on transaction while a subtransaction object exists")
#define FUPG_ST_COOKIE \
if (st->cookie != st->conn->cookie) fu_confess("Invalid cross-transaction operation on statement object")
typedef fupg_conn *fupg_txn;
#define FUPG_STFLAGS do {\
if (!ix) ix = FUPG_CACHE;\
if (items == 1 || SvTRUE(ST(1))) x->stflags |= ix; \
else x->stflags &= ~ix; \
XSRETURN(1); \
} while(0)
MODULE = FU
@ -32,7 +40,7 @@ PROTOTYPES: DISABLE
TYPEMAP: <<EOT
TYPEMAP
fupg_conn * FUPG_CONN
fupg_txn FUPG_TXN
fupg_txn * FUPG_TXN
fupg_st * FUPG_ST
INPUT
@ -41,7 +49,8 @@ FUPG_CONN
else fu_confess(\"invalid connection object\");
FUPG_TXN
$var = fupg_get_transaction(aTHX_ $arg);
if (sv_derived_from($arg, \"FU::PG::txn\")) $var = (fupg_txn *)SvIVX(SvRV($arg));
else fu_confess(\"invalid transaction object\");
FUPG_ST
if (sv_derived_from($arg, \"FU::PG::st\")) $var = (fupg_st *)SvIVX(SvRV($arg));
@ -94,19 +103,30 @@ void _debug_trace(fupg_conn *c, bool on)
else PQuntrace(c->conn);
ST(0) = c->self;
void _set_cookie(fupg_conn *c, UV cookie)
CODE:
c->cookie = cookie;
UV _get_cookie(fupg_conn *c)
CODE:
RETVAL = c->cookie;
OUTPUT:
RETVAL
void status(fupg_conn *c)
CODE:
ST(0) = sv_2mortal(newSVpv(fupg_status(c), 0));
ST(0) = sv_2mortal(newSVpv(fupg_conn_status(c), 0));
void cache(fupg_conn *x, ...)
ALIAS:
FU::PG::conn::text_params = FUPG_TEXT_PARAMS
FU::PG::conn::text_results = FUPG_TEXT_RESULTS
FU::PG::conn::text = FUPG_TEXT
CODE:
FUPG_STFLAGS;
void disconnect(fupg_conn *c)
CODE:
fupg_conn_disconnect(c);
void DESTROY(fupg_conn *c)
CODE:
fupg_conn_destroy(c);
void txn(fupg_conn *c)
CODE:
FUPG_CONN_COOKIE;
ST(0) = fupg_conn_txn(c);
void exec(fupg_conn *c, SV *sv)
CODE:
@ -116,34 +136,62 @@ void exec(fupg_conn *c, SV *sv)
void q(fupg_conn *c, SV *sv, ...)
CODE:
FUPG_CONN_COOKIE;
ST(0) = fupg_q(aTHX_ c, SvPVutf8_nolen(sv), ax, items);
void disconnect(fupg_conn *c)
CODE:
fupg_disconnect(c);
void DESTROY(fupg_conn *c)
CODE:
fupg_destroy(c);
ST(0) = fupg_q(aTHX_ c, c->stflags, SvPVutf8_nolen(sv), ax, items);
MODULE = FU PACKAGE = FU::PG::txn
void exec(fupg_txn c, SV *sv)
void DESTROY(fupg_txn *t)
CODE:
ST(0) = fupg_exec(aTHX_ c, SvPVutf8_nolen(sv));
fupg_txn_destroy(t);
void q(fupg_txn c, SV *sv, ...)
void cache(fupg_txn *x, ...)
ALIAS:
FU::PG::txn::text_params = FUPG_TEXT_PARAMS
FU::PG::txn::text_results = FUPG_TEXT_RESULTS
FU::PG::txn::text = FUPG_TEXT
CODE:
ST(0) = fupg_q(aTHX_ c, SvPVutf8_nolen(sv), ax, items);
FUPG_STFLAGS;
void status(fupg_txn *t)
CODE:
ST(0) = sv_2mortal(newSVpv(fupg_txn_status(t), 0));
void txn(fupg_txn *t)
CODE:
FUPG_TXN_COOKIE;
ST(0) = fupg_txn_txn(t);
void commit(fupg_txn *t)
CODE:
FUPG_TXN_COOKIE;
fupg_txn_commit(t);
void rollback(fupg_txn *t)
CODE:
FUPG_TXN_COOKIE;
fupg_txn_rollback(t);
void exec(fupg_txn *t, SV *sv)
CODE:
FUPG_TXN_COOKIE;
ST(0) = fupg_exec(aTHX_ t->conn, SvPVutf8_nolen(sv));
void q(fupg_txn *t, SV *sv, ...)
CODE:
FUPG_TXN_COOKIE;
ST(0) = fupg_q(aTHX_ t->conn, t->stflags, SvPVutf8_nolen(sv), ax, items);
MODULE = FU PACKAGE = FU::PG::st
void text_results(fupg_st *st, ...)
void cache(fupg_st *x, ...)
ALIAS:
FU::PG::st::text_params = FUPG_TEXT_PARAMS
FU::PG::st::text_results = FUPG_TEXT_RESULTS
FU::PG::st::text = FUPG_TEXT
CODE:
st->text_results = items == 1 || SvTRUE(ST(1));
XSRETURN(1);
FUPG_STFLAGS;
void params(fupg_st *st)
CODE: