Mercurial > code
view C++/DriverPostgres.cpp @ 172:a61cddaf7547
Rename Driver postgres
author | David Demelier <markand@malikania.fr> |
---|---|
date | Wed, 11 Sep 2013 15:27:00 +0200 |
parents | C++/DriverPG.cpp@e47c4e9e3f9d |
children | f0cca031bcce |
line wrap: on
line source
/* * DriverPostgres.cpp -- PostgreSQL driver * * Copyright (c) 2013, David Demelier <markand@malikania.fr> * * Permission to use, copy, modify, and/or distribute this software for any * purpose with or without fee is hereby granted, provided that the above * copyright notice and this permission notice appear in all copies. * * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ #include <sstream> #include "DriverPostgres.h" /* -------------------------------------------------------- * Query PostgreSQL (protected methods) * -------------------------------------------------------- */ QueryCheck QueryPostgres::checkRequest(int row, const std::string &column, ColumnType type) { QueryCheck ret = QueryCheck::InvalidType; Oid pqType; int colIndex; bool success = false; // Invalid row if (row >= PQntuples(m_result.get())) return QueryCheck::InvalidRow; if ((colIndex = PQfnumber(m_result.get(), column.c_str())) == -1) return QueryCheck::InvalidColumn; pqType = PQftype(m_result.get(), colIndex); switch (type) { case ColumnType::Boolean: success = (pqType == 16); break; case ColumnType::Date: success = (pqType == 1082) || (pqType == 1083) || (pqType == 1114); break; case ColumnType::Double: success = (pqType = 1700) || (pqType == 700) || (pqType == 701); break; case ColumnType::Integer: success = (pqType == 20) || (pqType == 21) || (pqType == 23) || (pqType == 1700); break; case ColumnType::String: success = (pqType == 25) || (pqType == 1042) || (pqType == 1043); break; default: ret = QueryCheck::InvalidType; } // valid type requested? if (success) ret = QueryCheck::NoError; return ret; } /* -------------------------------------------------------- * Query PostgreSQL (public methods) * -------------------------------------------------------- */ QueryPostgres::QueryPostgres(PostgresResult result) { m_result = std::move(result); } QueryPostgres::~QueryPostgres() { } int QueryPostgres::countRows() { return PQntuples(m_result.get()); } int QueryPostgres::countColumns() { return PQnfields(m_result.get()); } bool QueryPostgres::checkBool(int row, const std::string &column) { int idx = PQfnumber(m_result.get(), column.c_str()); std::string code = PQgetvalue(m_result.get(), row, idx); return code[0] == 't'; } Date QueryPostgres::checkDate(int row, const std::string &column) { int idx = PQfnumber(m_result.get(), column.c_str()); long timestamp = static_cast<long>(time(0)); try { timestamp = std::stol(PQgetvalue(m_result.get(), row, idx)); } catch (std::invalid_argument) { } return Date(static_cast<time_t>(timestamp)); } double QueryPostgres::checkDouble(int row, const std::string &column) { int idx = PQfnumber(m_result.get(), column.c_str()); double d = 0; try { d = std::stod(PQgetvalue(m_result.get(), row, idx)); } catch (std::invalid_argument) { } return d; } int QueryPostgres::checkInt(int row, const std::string &column) { int idx = PQfnumber(m_result.get(), column.c_str()); int i = 0; try { i = std::stoi(PQgetvalue(m_result.get(), row, idx)); } catch (std::invalid_argument) { } return i; } std::string QueryPostgres::checkString(int row, const std::string &column) { int idx = PQfnumber(m_result.get(), column.c_str()); return std::string(PQgetvalue(m_result.get(), row, idx)); } bool QueryPostgres::isNull(int row, const std::string &column) { int idx = PQfnumber(m_result.get(), column.c_str()); return PQgetisnull(m_result.get(), row, idx) == 1; } void QueryPostgres::dump(void) { std::cout << "Dumping PostgreSQL result, "; std::cout << countRows() << " rows, "; std::cout << countColumns() << " columns" << std::endl; for (int r = 0; r < countRows(); ++r) { std::cout << "Dumping row " << r << std::endl; std::cout << "==============================" << std::endl; for (int c = 0; c < countColumns(); ++c) { std::cout << "\t" << PQfname(m_result.get(), c); std::cout << " = " << PQgetvalue(m_result.get(), r, c) << std::endl; } } } /* -------------------------------------------------------- * Driver PostgreSQL * -------------------------------------------------------- */ DriverPostgres::DriverPostgres() { } DriverPostgres::~DriverPostgres() { } std::string DriverPostgres::convert(Params ¶ms) { std::ostringstream oss; oss << "host = " << params["host"] << " "; oss << "port = " << params["port"] << " "; oss << "user = " << params["user"] << " "; oss << "dbname = " << params["database"] << " "; oss << "password = " << params["password"]; return oss.str(); } bool DriverPostgres::connect(const Params ¶ms) { Params copy = params; PGconn *conn = PQconnectdb(convert(copy).c_str()); if (conn == nullptr) { m_error = strerror(ENOMEM); return false; } if (PQstatus(conn) == CONNECTION_BAD) { m_error = PQerrorMessage(conn); PQfinish(conn); return false; } m_connection = PostgresConn(conn); return true; } std::unique_ptr<Query> DriverPostgres::query(const std::string &cmd) { PGresult *info; // If NULL, the libpq said no memory info = PQexec(m_connection.get(), cmd.c_str()); if (info == nullptr) throw QueryError(strerror(ENOMEM)); // If an error occured int errorCode = PQresultStatus(info); if (errorCode != PGRES_COMMAND_OK && errorCode != PGRES_TUPLES_OK) { std::string error = PQresultErrorMessage(info); PQclear(info); throw QueryError(error); } return std::unique_ptr<Query>(new QueryPostgres(QueryPostgres::PostgresResult(info))); } std::string DriverPostgres::description() const { std::ostringstream oss; oss << "Connected on PostgreSQL database: " << std::endl; oss << " host: " << PQhost(m_connection.get()) << std::endl; oss << " port: " << PQport(m_connection.get()) << std::endl; oss << " user: " << PQuser(m_connection.get()) << std::endl; oss << " database: " << PQdb(m_connection.get()) << std::endl; return oss.str(); }