const failable patch()

in components/sqldb/pgsql.hpp [271:317]


const failable<bool> patch(const value& key, const value& val, const PGSql& pgsql) {
    debug(key, "pgsql::patch::key");
    debug(val, "pgsql::patch::value");
    debug(pgsql.conninfo, "pgsql::patch::conninfo");
    debug(pgsql.table, "pgsql::patch::table");
    setup(pgsql);

    const string ks(write(content(scheme::writeValue(key))));
    const string vs(write(content(scheme::writeValue(val))));
    const char* const params[2] = { c_str(ks), c_str(vs) };
    PGresult* const r = PQexecParams(pgsql.conn, c_str(string("update ") + pgsql.table + string(" set ") + pgsql.vname + string(" = $2 where ") + pgsql.kname + string(" = $1;")), 2, NULL, params, NULL, NULL, 0);
    if (PQresultStatus(r) != PGRES_COMMAND_OK) {
        const string rs = string("Couldn't execute update postgresql SQL statement: ") + pgfailure(r, pgsql.conn);
        const char* const st = PQresultErrorField(r, PG_DIAG_SQLSTATE);
        if (st != NULL && !strncmp(st, "40", 2)) {

            // Report a transaction serialization conflict
            PQclear(r);
            return mkfailure<bool>(rs, 409);
        }
        PQclear(r);
        return mkfailure<bool>(rs);
    }
    const char* const t = PQcmdTuples(r);
    if (t != NULL && strcmp(t, "0")) {
        PQclear(r);
        debug(true, "pgsql::patch::result");
        return true;
    }
    PQclear(r);

    PGresult* const pr = PQexecParams(pgsql.conn, c_str(string("insert into ") + pgsql.table + string(" values($1, $2);")), 2, NULL, params, NULL, NULL, 0);
    if (PQresultStatus(pr) != PGRES_COMMAND_OK) {
        const string rs = string("Couldn't execute insert postgresql SQL statement: ") + pgfailure(pr, pgsql.conn);
        const char* const st = PQresultErrorField(pr, PG_DIAG_SQLSTATE);
        if (st != NULL && !strncmp(st, "40", 2)) {
            PQclear(pr);
            return mkfailure<bool>(rs, 40);
        }
        PQclear(pr);
        return mkfailure<bool>(rs);
    }
    PQclear(pr);

    debug(true, "pgsql::patch::result");
    return true;
}