From 070d2c7d55af1cac5f1c7b55186cb7cb3f69dab1 Mon Sep 17 00:00:00 2001 From: Bent Bisballe Nyeng Date: Wed, 26 Feb 2014 14:57:37 +0100 Subject: Port from libpqxx to libpq. --- server/src/pgwork.cc | 146 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 146 insertions(+) create mode 100644 server/src/pgwork.cc (limited to 'server/src/pgwork.cc') diff --git a/server/src/pgwork.cc b/server/src/pgwork.cc new file mode 100644 index 0000000..948bb5f --- /dev/null +++ b/server/src/pgwork.cc @@ -0,0 +1,146 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set et sw=2 ts=2: */ +/*************************************************************************** + * pgwork.cc + * + * Wed Feb 26 14:49:37 CET 2014 + * Copyright 2014 Bent Bisballe Nyeng + * deva@aasimon.org + ****************************************************************************/ + +/* + * This file is part of Pracro. + * + * Pracro is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * Pracro is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Pracro; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + */ +#include "pgwork.h" + +#include + +#include "debug.h" + +/** + * Convert list of tuples to list of string arrays. + */ +static result_t toArray(PGresult *pg) +{ + std::list > res; + for(int j = 0; j < PQntuples(pg); j++) { + std::vector v; + for(int i = 0; i < PQnfields(pg); i++) { + v.push_back(std::string(PQgetvalue(pg, j, i))); + } + res.push_back(v); + } + return res; +} + +class pq_exc : public std::exception { +public: + pq_exc(std::string _what) : w(_what) {} + ~pq_exc() throw() {} + const char *what() { return w.c_str(); } +private: + std::string w; +}; + +Work::Work(PGconn *_c) throw(std::exception) + : c(_c) +{ + state = WORK_OPEN; + try { + exec("BEGIN"); + } catch(std::exception &e) { + ERR(db, "Error beginning transaction: %s\n", e.what()); + state = WORK_INVALID; + throw e; + } +} + +Work::~Work() +{ + if(state == WORK_OPEN) abort(); +} + +/** + * Execute query and return result as list of string arrays. + */ +result_t Work::exec(const std::string &query) + throw(std::exception) +{ + if(state != WORK_OPEN) { + ERR(db, "Transaction is not is not valid. Cannot execute query!\n"); + return result_t(); + } + + PGresult *pg = PQexec(c, query.c_str()); + if(PQresultStatus(pg) != PGRES_TUPLES_OK && + PQresultStatus(pg) != PGRES_COMMAND_OK) { + throw pq_exc(PQerrorMessage(c)); + } + + result_t R = toArray(pg); + + PQclear(pg); + return R; +} + +void Work::commit() + throw(std::exception) +{ + try { + exec("COMMIT"); + } catch(std::exception &e) { + ERR(db, "Error committing transaction: %s\n", e.what()); + throw e; + } + state = WORK_COMMITTED; +} + +void Work::abort() + throw(std::exception) +{ + try { + exec("ROLLBACK"); + } catch(std::exception &e) { + ERR(db, "Error aborting transaction: %s\n", e.what()); + throw e; + } + state = WORK_ABORTED; +} + +std::string Work::esc(const std::string &from) +{ + if(from == "") return ""; + + size_t buf_size = from.length() * 2 + 1; + char *buf = (char *)malloc(buf_size); + int error = 0; + + size_t size = PQescapeStringConn(c, buf, from.data(), + from.length(), &error); + + if(error) { + ERR(db, "SQL escaping failed due to invalid multibyte character" + " in '%s'\n", from.c_str()); + return ""; + } + + std::string to; + if(size > 0 && error == 0) to.append(buf, size); + + free(buf); + return to; +} -- cgit v1.2.3