pg: Pipeline prepare + describeprepared

This commit is contained in:
Yorhel 2025-02-09 09:26:01 +01:00
parent 7b76d94719
commit b6517cf05a
2 changed files with 43 additions and 14 deletions

View file

@ -261,6 +261,9 @@ static void fupg_txn_destroy(pTHX_ fupg_txn *t) {
/* XXX: It feels a bit wasteful to load *all* types; even on an empty database
* that's ~55k of data, but it's easier and (potentially) faster than fetching
* each type seperately as we encounter them.
* Perhaps an easier optimization is to filter out all table-based composites
* and their array types by default, I've never seen anyone use those types for
* I/O and that would shrink the data by nearly a factor 5.
*/
static void fupg_refresh_types(pTHX_ fupg_conn *c) {
safefree(c->types);
@ -354,19 +357,41 @@ static void fupg_st_prepare(pTHX_ fupg_st *st) {
snprintf(st->name, sizeof(st->name), "fupg%"UVuf, ++st->conn->prep_counter);
/* TODO: Pipeline these two commands, no need for two round-trips with the server */
PGresult *r = PQprepare(st->conn->conn, st->name, st->query, 0, NULL);
if (!r) fupg_conn_croak(st->conn , "prepare");
if (PQresultStatus(r) != PGRES_COMMAND_OK)
fupg_result_croak(r, "prepare", st->query);
PQclear(r);
/* Send prepare + describe in a pipeline to avoid a double round-trip with the server */
PQenterPipelineMode(st->conn->conn);
PQsendPrepare(st->conn->conn, st->name, st->query, 0, NULL);
PQsendDescribePrepared(st->conn->conn, st->name);
PQpipelineSync(st->conn->conn);
PGresult *prep = PQgetResult(st->conn->conn); PQgetResult(st->conn->conn); /* NULL */
PGresult *desc = PQgetResult(st->conn->conn); PQgetResult(st->conn->conn); /* NULL */
PGresult *sync = PQgetResult(st->conn->conn);
PQexitPipelineMode(st->conn->conn);
if (!prep) {
PQclear(desc); PQclear(sync);
fupg_conn_croak(st->conn , "prepare");
}
if (PQresultStatus(prep) != PGRES_COMMAND_OK) {
PQclear(desc); PQclear(sync);
fupg_result_croak(prep, "prepare", st->query);
}
PQclear(prep);
st->prepared = 1;
r = PQdescribePrepared(st->conn->conn, st->name);
if (!r) fupg_conn_croak(st->conn , "prepare");
if (PQresultStatus(r) != PGRES_COMMAND_OK)
fupg_result_croak(r, "prepare", st->query);
st->describe = r;
if (!desc) {
PQclear(sync);
fupg_conn_croak(st->conn , "prepare");
}
if (PQresultStatus(desc) != PGRES_COMMAND_OK) {
PQclear(sync);
fupg_result_croak(desc, "prepare", st->query);
}
st->describe = desc;
if (!sync) fupg_conn_croak(st->conn , "prepare");
if (PQresultStatus(sync) != PGRES_PIPELINE_SYNC)
fupg_result_croak(sync, "prepare", st->query);
PQclear(sync);
}
static SV *fupg_st_params(pTHX_ fupg_st *st) {