Skip to content

Commit

Permalink
Hide libpq from API (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
bgs99 authored May 11, 2024
1 parent 0e7542a commit c5bd06c
Show file tree
Hide file tree
Showing 10 changed files with 220 additions and 138 deletions.
5 changes: 4 additions & 1 deletion .clang-format
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,15 @@ BasedOnStyle: LLVM

IncludeBlocks: Regroup
IncludeCategories:
- Regex: "^\""
Priority: 0
- Regex: "^<pfr-orm/"
CaseSensitive: true
Priority: 1
- Regex: "^<(fmt/|boost/|libpq-fe\\.h>)"
CaseSensitive: true
Priority: 3
- Priority: 2
- Regex: "^<"
Priority: 2

ForEachMacros: []
7 changes: 4 additions & 3 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,13 @@ find_package(PostgreSQL REQUIRED)

add_library(pfr-orm STATIC)
target_compile_features(pfr-orm PUBLIC cxx_std_20)
target_sources(pfr-orm PRIVATE lib/detail/operations.cpp)
target_sources(pfr-orm PRIVATE lib/postgres/utils.cpp
lib/postgres/operations.cpp)
target_include_directories(pfr-orm PUBLIC include)
target_link_libraries(
pfr-orm
PUBLIC Boost::pfr PostgreSQL::PostgreSQL
PRIVATE fmt::fmt)
PUBLIC Boost::pfr
PRIVATE PostgreSQL::PostgreSQL fmt::fmt)

option(PFR_ORM_USE_GSL_SPAN
"Use Microsoft.GSL for span implementation instead of std::span" OFF)
Expand Down
7 changes: 3 additions & 4 deletions include/pfr-orm/detail/operations.hpp
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
#pragma once

#include <pfr-orm/definitions.hpp>

#include <libpq-fe.h>
#include <pfr-orm/postgres/utils.hpp>

namespace pfrorm::postgres::detail {

void createTable(PGconn &connection, const EntityDescription &entity);
void createTable(Connection &connection, const EntityDescription &entity);

bool exists(PGconn &connection, const EntityDescription &entity);
bool exists(Connection &connection, const EntityDescription &entity);

} // namespace pfrorm::postgres::detail
104 changes: 0 additions & 104 deletions include/pfr-orm/postges-helpers.hpp

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,15 @@

#include <pfr-orm/definitions.hpp>
#include <pfr-orm/detail/operations.hpp>

#include <libpq-fe.h>
#include <pfr-orm/postgres/utils.hpp>

namespace pfrorm::postgres {

template <DatabaseEntity T> void createTable(PGconn &connection) {
template <DatabaseEntity T> void createTable(Connection &connection) {
return detail::createTable(connection, DatabaseEntityDescription<T>);
}

template <typename T> bool exists(PGconn &connection) {
template <typename T> bool exists(Connection &connection) {
return detail::exists(connection, DatabaseEntityDescription<T>);
}

Expand Down
96 changes: 96 additions & 0 deletions include/pfr-orm/postgres/utils.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
#pragma once

#include <cstdint>
#include <string>
#include <string_view>

struct pg_conn;
struct pg_result;

namespace pfrorm::postgres {

class Str {
public:
Str(char *str) : str(str) {}
~Str();

[[nodiscard]] std::string_view view() const { return str; }
operator std::string_view() const { return str; }

Str(const Str &) = delete;
Str(Str &&) = delete;
Str &operator=(const Str &) = delete;
Str &operator=(Str &&) = delete;

private:
char *str;
};

class Result {
public:
Result(pg_result *result) : result(result) {}
~Result();

[[nodiscard]] int status() const;
[[nodiscard]] std::string_view value(int row, int column) const;

Result(const Result &) = delete;
Result(Result &&) noexcept;
Result &operator=(const Result &) = delete;
Result &operator=(Result &&) = delete;

private:
pg_result *result;
};

class Connection {
public:
Connection(const std::string &connectionStr);
~Connection();

Connection(const Connection &) = delete;
Connection(Connection &&) noexcept;
Connection &operator=(const Connection &) = delete;
Connection &operator=(Connection &&) = delete;

[[nodiscard]] Str escapeIdentifier(std::string_view identifier) const;

Result execute(const std::string &statement);

Result query(const std::string &statement);

private:
pg_conn *connection;
};

struct ParameterTraits {
struct Parameter {
std::string data;
bool isBinary; // TODO: pass everything as binary
};

template <typename T> static Parameter toParam(const T &value) = delete;
};

template <>
inline ParameterTraits::Parameter
ParameterTraits::toParam(const uint64_t &value) {
return {
.data = std::to_string(value),
.isBinary = false,
};
}

template <>
inline ParameterTraits::Parameter
ParameterTraits::toParam(const std::string &value) {
return {
.data = value,
.isBinary = true,
};
}

template <typename T>
concept AsParameter = requires { ParameterTraits::toParam<T>; };

} // namespace pfrorm::postgres
18 changes: 18 additions & 0 deletions lib/postgres/formatters.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#pragma once

#include <pfr-orm/postgres/utils.hpp>

#include <string_view>

#include <fmt/core.h>
#include <fmt/format.h>

template <>
struct fmt::formatter<pfrorm::postgres::Str> : formatter<std::string_view> {
public:
template <typename FormatContext>
constexpr auto format(const pfrorm::postgres::Str &str,
FormatContext &ctx) const -> decltype(ctx.out()) {
return formatter<std::string_view>::format(str.view(), ctx);
}
};
35 changes: 18 additions & 17 deletions lib/detail/operations.cpp → lib/postgres/operations.cpp
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#include "../detail/multilambda.hpp"
#include "formatters.hpp" // IWYU pragma: keep

#include <pfr-orm/api.hpp>
#include <pfr-orm/definitions.hpp>
#include <pfr-orm/postges-helpers.hpp>
#include <pfr-orm/postgres/utils.hpp>

#include "multilambda.hpp"
#include <cstddef>
#include <string_view>
#include <type_traits>
Expand All @@ -11,7 +13,6 @@

#include <fmt/core.h>
#include <fmt/format.h>
#include <libpq-fe.h>

namespace pfrorm::postgres::detail {

Expand All @@ -27,19 +28,19 @@ std::string_view toString(const NativeType type) {
}

void createTableFields(const FieldDescription &description,
const bool isPrimaryKey, PGconn &connection,
const bool isPrimaryKey, Connection &connection,
fmt::appender &appender,
std::vector<std::string_view> prefixes, bool &first) {
prefixes.push_back(description.name);

const auto createPrimitiveField =
[isPrimaryKey, &prefixes, &connection, &appender,
&first](const PrimitiveFieldDescription &descr) {
fmt::format_to(
appender, "{}{} {}{}", first ? "" : ",",
escapeIdentifier(connection,
fmt::to_string(fmt::join(prefixes, "_"))),
toString(descr.nativeType), isPrimaryKey ? " PRIMARY KEY" : "");
fmt::format_to(appender, "{}{} {}{}", first ? "" : ",",
connection.escapeIdentifier(
fmt::to_string(fmt::join(prefixes, "_"))),
toString(descr.nativeType),
isPrimaryKey ? " PRIMARY KEY" : "");
first = false;
};

Expand Down Expand Up @@ -67,9 +68,9 @@ void createTableFields(const FieldDescription &description,

} // namespace

void createTable(PGconn &connection, const EntityDescription &entity) {
const Str escapedTableName = escapeIdentifier(connection, entity.name);
execute(connection, fmt::format("DROP TABLE IF EXISTS {}", escapedTableName));
void createTable(Connection &connection, const EntityDescription &entity) {
const Str escapedTableName = connection.escapeIdentifier(entity.name);
connection.execute(fmt::format("DROP TABLE IF EXISTS {}", escapedTableName));

fmt::memory_buffer buf;
fmt::appender appender{buf};
Expand All @@ -80,14 +81,14 @@ void createTable(PGconn &connection, const EntityDescription &entity) {
appender, {}, first);
}
fmt::format_to(appender, ")");
execute(connection, fmt::to_string(buf));
connection.execute(fmt::to_string(buf));
}

bool exists(PGconn &connection, const EntityDescription &entity) {
bool exists(Connection &connection, const EntityDescription &entity) {
const Result result =
query(connection, fmt::format("SELECT EXISTS(SELECT 1 FROM {})",
escapeIdentifier(connection, entity.name)));
return *PQgetvalue(result.get(), 0, 0) == 't';
connection.query(fmt::format("SELECT EXISTS(SELECT 1 FROM {})",
connection.escapeIdentifier(entity.name)));
return result.value(0, 0)[0] == 't';
}

} // namespace pfrorm::postgres::detail
Loading

0 comments on commit c5bd06c

Please sign in to comment.