diff database/postgresql/src/driver.cpp @ 29:99792c6c8b06

Server: add initial postgresql account management, #475
author David Demelier <markand@malikania.fr>
date Thu, 26 May 2016 07:32:05 +0200
parents
children a1e80d991968
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/database/postgresql/src/driver.cpp	Thu May 26 07:32:05 2016 +0200
@@ -0,0 +1,113 @@
+/*
+ * 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.h>
+
+#include "driver.h"
+
+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