memgraph/tests/macro_benchmark/clients/postgres_client.hpp
Mislav Bradac 7e5dddecae Move harness stuff to parent directory
Reviewers: buda

Reviewed By: buda

Subscribers: pullbot

Differential Revision: https://phabricator.memgraph.io/D799
2017-09-15 14:05:26 +02:00

109 lines
2.9 KiB
C++

#pragma once
#include <map>
#include <string>
#include <vector>
#include <fmt/format.h>
#include <glog/logging.h>
#include <libpq-fe.h>
#include "communication/bolt/client.hpp"
#include "communication/bolt/v1/decoder/decoded_value.hpp"
#include "utils/exceptions.hpp"
using communication::bolt::QueryData;
namespace postgres {
class ClientException : public utils::BasicException {
using utils::BasicException::BasicException;
};
class ClientQueryException : public ClientException {
public:
using ClientException::ClientException;
ClientQueryException() : ClientException("Couldn't execute query!") {}
};
class Client {
public:
Client(const std::string &host, const std::string &port,
const std::string &username, const std::string &password,
const std::string &database = "") {
// https://www.postgresql.org/docs/9.4/static/libpq-connect.html#LIBPQ-PARAMKEYWORDS
std::string pass = "";
if (password != "") {
pass = "password=" + password;
}
std::string conninfo =
fmt::format("host={} port={} user={} {} dbname={} sslmode=disable",
host, port, username, pass, database);
// Make a connection to the database.
connection_ = PQconnectdb(conninfo.c_str());
// Check to see that the backend connection was successfully made
if (PQstatus(connection_) != CONNECTION_OK) {
throw ClientException(PQerrorMessage(connection_));
}
}
QueryData Execute(
const std::string &query,
const std::map<std::string, communication::bolt::DecodedValue>
&parameters) {
QueryData ret;
CHECK(parameters.size() == 0U) << "Parameters not yet supported";
DLOG(INFO) << "Sending run message with statement: '" << query << "'";
result_ = PQexec(connection_, query.c_str());
if (PQresultStatus(result_) == PGRES_TUPLES_OK) {
// get fields
int num_fields = PQnfields(result_);
for (int i = 0; i < num_fields; ++i) {
ret.fields.push_back(PQfname(result_, i));
}
// get records
int num_records = PQntuples(result_);
ret.records.resize(num_records);
for (int i = 0; i < num_records; ++i) {
for (int j = 0; j < num_fields; ++j) {
ret.records[i].push_back(std::string(PQgetvalue(result_, i, j)));
}
}
// get metadata
ret.metadata.insert({"status", std::string(PQcmdStatus(result_))});
ret.metadata.insert({"rows_affected", std::string(PQcmdTuples(result_))});
} else if (PQresultStatus(result_) != PGRES_COMMAND_OK) {
throw ClientQueryException(PQerrorMessage(connection_));
}
PQclear(result_);
result_ = nullptr;
return ret;
}
void Close() {
if (result_ != nullptr) {
PQclear(result_);
result_ = nullptr;
}
if (connection_ != nullptr) {
PQfinish(connection_);
connection_ = nullptr;
}
}
~Client() { Close(); }
private:
PGconn *connection_{nullptr};
PGresult *result_{nullptr};
};
}