view database/postgresql/src/driver.cpp @ 94:e354bca9bef9

Server: remove useless using namespace std::placeholders
author David Demelier <markand@malikania.fr>
date Thu, 08 Jun 2017 08:46:07 +0200
parents d4f5f7231b84
children
line wrap: on
line source

/*
 * driver.cpp -- PostgreSQL database driver
 *
 * Copyright (c) 2013-2016 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 <string>
#include <unordered_map>

#include <malikania/dynlib.hpp>

#include "driver.hpp"

namespace pgsql {

PGconn *connection{nullptr};

std::shared_ptr<PGresult> exec(const std::string &sql)
{
    std::shared_ptr<PGresult> ptr(PQexec(connection, sql.c_str()), PQclear);

    if (PQresultStatus(ptr.get()) != PGRES_TUPLES_OK && PQresultStatus(ptr.get()) != PGRES_COMMAND_OK)
        throw std::runtime_error(PQresultErrorMessage(ptr.get()));

    return ptr;
}

std::string escape(const std::string &input)
{
    auto text = PQescapeLiteral(connection, input.c_str(), input.length());

    if (!text)
        throw std::runtime_error(PQerrorMessage(connection));

    std::string result(text);

    PQfreemem(text);

    return result;
}

} // !pgsql

namespace {

std::string parameters(const std::unordered_map<std::string, std::string> &params)
{
    std::ostringstream oss;
    std::unordered_map<std::string, std::string>::const_iterator it;

    // Host.
    if ((it = params.find("host")) == params.end())
        throw std::runtime_error("missing 'host' parameter");

    oss << "host = " << it->second << " ";

    // Database.
    if ((it = params.find("database")) == params.end())
        throw std::runtime_error("missing 'database' parameter");

    oss << "dbname = " << it->second << " ";

    // User.
    if ((it = params.find("user")) == params.end())
        throw std::runtime_error("missing 'user' parameter");

    oss << "user = " << it->second << " ";

    // Port (optional).
    if ((it = params.find("port")) != params.end())
        oss << "port = " << it->second << " ";

    // Password (optional).
    if ((it = params.find("password")) != params.end())
        oss << "password = " << it->second << " ";

    return oss.str();
}

} // !namespace

extern "C" {

DYNLIB_EXPORT void malikania_driver_load(const std::unordered_map<std::string, std::string> &params)
{
    pgsql::connection = PQconnectdb(parameters(params).c_str());

    if (!pgsql::connection)
        throw std::runtime_error(PQerrorMessage(pgsql::connection));
}

DYNLIB_EXPORT void malikania_driver_unload()
{
    if (pgsql::connection) {
        PQfinish(pgsql::connection);
        pgsql::connection = nullptr;
    }
}

} // !C