Mercurial > code
view C++/DriverPG.cpp @ 171:e47c4e9e3f9d
Add SQL drivers
author | David Demelier <markand@malikania.fr> |
---|---|
date | Tue, 10 Sep 2013 17:28:32 +0200 |
parents | |
children |
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 "DriverPG.h" /* -------------------------------------------------------- * Query PostgreSQL (protected methods) * -------------------------------------------------------- */ QueryCheck QueryPG::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) * -------------------------------------------------------- */ QueryPG::QueryPG(PostgresResult result) { m_result = std::move(result); } QueryPG::~QueryPG() { } int QueryPG::countRows() { return PQntuples(m_result.get()); } int QueryPG::countColumns() { return PQnfields(m_result.get()); } bool QueryPG::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 QueryPG::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 QueryPG::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 QueryPG::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 QueryPG::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 QueryPG::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 QueryPG::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 * -------------------------------------------------------- */ DriverPG::DriverPG() { } DriverPG::~DriverPG() { } std::string DriverPG::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 DriverPG::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> DriverPG::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 QueryPG(QueryPG::PostgresResult(info))); } std::string DriverPG::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(); }