This is simply magical. \o/ Vendored in khashl.h. I wouldn't have used it if this were the only place where I'd need a custom hash table, but it should come in handy for other tasks as well, especially when I get to implementing an LRU for prepared statement caching. (Can all be done with Perl HV's, but they're less efficient and more cumbersome for these tasks)
264 lines
5.5 KiB
Text
264 lines
5.5 KiB
Text
#include <stdio.h>
|
|
#include <errno.h>
|
|
#include <string.h>
|
|
#include <arpa/inet.h>
|
|
#include <dlfcn.h>
|
|
|
|
#undef PERL_IMPLICIT_SYS
|
|
#define PERL_NO_GET_CONTEXT
|
|
#include "EXTERN.h"
|
|
#include "perl.h"
|
|
#include "XSUB.h"
|
|
|
|
#include "c/khashl.h"
|
|
#include "c/common.c"
|
|
#include "c/jsonfmt.c"
|
|
#include "c/jsonparse.c"
|
|
#include "c/libpq.h"
|
|
#include "c/pgtypes.c"
|
|
#include "c/pgconn.c"
|
|
#include "c/pgst.c"
|
|
|
|
|
|
#define FUPG_CONN_COOKIE \
|
|
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")
|
|
|
|
#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
|
|
|
|
PROTOTYPES: DISABLE
|
|
|
|
|
|
TYPEMAP: <<EOT
|
|
TYPEMAP
|
|
fupg_conn * FUPG_CONN
|
|
fupg_txn * FUPG_TXN
|
|
fupg_st * FUPG_ST
|
|
|
|
INPUT
|
|
FUPG_CONN
|
|
if (sv_derived_from($arg, \"FU::Pg::conn\")) $var = (fupg_conn *)SvIVX(SvRV($arg));
|
|
else fu_confess(\"invalid connection object\");
|
|
|
|
FUPG_TXN
|
|
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));
|
|
else fu_confess(\"invalid statement object\");
|
|
#"
|
|
EOT
|
|
|
|
|
|
MODULE = FU PACKAGE = FU::Util
|
|
|
|
void json_format(SV *val, ...)
|
|
CODE:
|
|
ST(0) = fujson_fmt_xs(aTHX_ ax, items, val);
|
|
|
|
void json_parse(SV *val, ...)
|
|
CODE:
|
|
ST(0) = fujson_parse_xs(aTHX_ ax, items, val);
|
|
|
|
|
|
|
|
MODULE = FU PACKAGE = FU::Pg
|
|
|
|
void _load_libpq()
|
|
CODE:
|
|
if (!PQconnectdb) fupg_load();
|
|
|
|
void lib_version()
|
|
CODE:
|
|
XSRETURN_IV(PQlibVersion());
|
|
|
|
void connect(const char *pkg, const char *conninfo)
|
|
CODE:
|
|
(void)pkg;
|
|
ST(0) = fupg_connect(aTHX_ conninfo);
|
|
|
|
|
|
MODULE = FU PACKAGE = FU::Pg::conn
|
|
|
|
void server_version(fupg_conn *c)
|
|
CODE:
|
|
XSRETURN_IV(PQserverVersion(c->conn));
|
|
|
|
void _debug_trace(fupg_conn *c, bool on)
|
|
CODE:
|
|
if (on) PQtrace(c->conn, stderr);
|
|
else PQuntrace(c->conn);
|
|
ST(0) = c->self;
|
|
|
|
void status(fupg_conn *c)
|
|
CODE:
|
|
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:
|
|
FUPG_CONN_COOKIE;
|
|
ST(0) = fupg_exec(aTHX_ c, SvPVutf8_nolen(sv));
|
|
|
|
void q(fupg_conn *c, SV *sv, ...)
|
|
CODE:
|
|
FUPG_CONN_COOKIE;
|
|
ST(0) = fupg_q(aTHX_ c, c->stflags, SvPVutf8_nolen(sv), ax, items);
|
|
|
|
|
|
MODULE = FU PACKAGE = FU::Pg::txn
|
|
|
|
void DESTROY(fupg_txn *t)
|
|
CODE:
|
|
fupg_txn_destroy(t);
|
|
|
|
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:
|
|
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 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:
|
|
FUPG_STFLAGS;
|
|
|
|
void param_types(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_param_types(aTHX_ st);
|
|
|
|
void columns(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_columns(aTHX_ st);
|
|
|
|
void exec(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_exec(aTHX_ st);
|
|
|
|
void val(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_val(aTHX_ st);
|
|
|
|
void rowl(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
XSRETURN(fupg_st_rowl(aTHX_ st, ax));
|
|
|
|
void rowa(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_rowa(aTHX_ st);
|
|
|
|
void rowh(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_rowh(aTHX_ st);
|
|
|
|
void alla(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_alla(aTHX_ st);
|
|
|
|
void allh(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_allh(aTHX_ st);
|
|
|
|
void flat(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_flat(aTHX_ st);
|
|
|
|
void kvv(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_kvv(aTHX_ st);
|
|
|
|
void kva(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_kva(aTHX_ st);
|
|
|
|
void kvh(fupg_st *st)
|
|
CODE:
|
|
FUPG_ST_COOKIE;
|
|
ST(0) = fupg_st_kvh(aTHX_ st);
|
|
|
|
void DESTROY(fupg_st *st)
|
|
CODE:
|
|
fupg_st_destroy(st);
|