diff --git a/include/sqlgen/postgres/Connection.hpp b/include/sqlgen/postgres/Connection.hpp index 89e919b..b0e5b51 100644 --- a/include/sqlgen/postgres/Connection.hpp +++ b/include/sqlgen/postgres/Connection.hpp @@ -54,9 +54,21 @@ class Connection : public sqlgen::Connection { } private: + std::string add_not_null_if_necessary( + const dynamic::types::Properties& _p) const noexcept; + + std::string column_to_sql_definition( + const dynamic::Column& _col) const noexcept; + + std::string create_table_to_sql( + const dynamic::CreateTable& _stmt) const noexcept; + static ConnPtr make_conn(const std::string& _conn_str); - std::string select_from_to_sql(const dynamic::SelectFrom& _stmt) noexcept; + std::string select_from_to_sql( + const dynamic::SelectFrom& _stmt) const noexcept; + + std::string type_to_sql(const dynamic::Type& _type) const noexcept; private: ConnPtr conn_; diff --git a/src/sqlgen/postgres/Connection.cpp b/src/sqlgen/postgres/Connection.cpp index 700cae9..45a9212 100644 --- a/src/sqlgen/postgres/Connection.cpp +++ b/src/sqlgen/postgres/Connection.cpp @@ -10,6 +10,46 @@ namespace sqlgen::postgres { +std::string Connection::add_not_null_if_necessary( + const dynamic::types::Properties& _p) const noexcept { + return std::string(_p.nullable ? "" : " NOT NULL"); +} + +std::string Connection::column_to_sql_definition( + const dynamic::Column& _col) const noexcept { + return "\"" + _col.name + "\"" + " " + type_to_sql(_col.type) + + add_not_null_if_necessary( + _col.type.visit([](const auto& _t) { return _t.properties; })); +} + +std::string Connection::create_table_to_sql( + const dynamic::CreateTable& _stmt) const noexcept { + using namespace std::ranges::views; + + const auto col_to_sql = [&](const auto& _col) { + return column_to_sql_definition(_col); + }; + + std::stringstream stream; + stream << "CREATE TABLE "; + + if (_stmt.if_not_exists) { + stream << "IF NOT EXISTS "; + } + + if (_stmt.table.schema) { + stream << "\"" << *_stmt.table.schema << "\"."; + } + stream << "\"" << _stmt.table.name << "\" "; + + stream << "("; + stream << internal::strings::join( + ", ", internal::collect::vector(_stmt.columns | transform(col_to_sql))); + stream << ");"; + + return stream.str(); +} + rfl::Result> Connection::make( const Credentials& _credentials) noexcept { try { @@ -34,7 +74,7 @@ typename Connection::ConnPtr Connection::make_conn( } std::string Connection::select_from_to_sql( - const dynamic::SelectFrom& _stmt) noexcept { + const dynamic::SelectFrom& _stmt) const noexcept { using namespace std::ranges::views; const auto to_str = [](const auto& _col) -> std::string { @@ -58,12 +98,12 @@ std::string Connection::select_from_to_sql( std::string Connection::to_sql(const dynamic::Statement& _stmt) noexcept { return _stmt.visit([&](const auto& _s) -> std::string { using S = std::remove_cvref_t; - /*if constexpr (std::is_same_v) { + if constexpr (std::is_same_v) { return create_table_to_sql(_s); - } else if constexpr (std::is_same_v) { - return insert_to_sql(_s); - } else*/ - if constexpr (std::is_same_v) { + /*} else if constexpr (std::is_same_v) { + return insert_to_sql(_s); + } else*/ + } else if constexpr (std::is_same_v) { return select_from_to_sql(_s); } else { return "TODO"; @@ -72,4 +112,40 @@ std::string Connection::to_sql(const dynamic::Statement& _stmt) noexcept { }); } +std::string Connection::type_to_sql(const dynamic::Type& _type) const noexcept { + return _type.visit([](const auto _t) -> std::string { + using T = std::remove_cvref_t; + if constexpr (std::is_same_v) { + return "BOOLEAN"; + } else if constexpr (std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v) { + return "SMALLINT"; + } else if constexpr (std::is_same_v || + std::is_same_v) { + return "INTEGER"; + } else if constexpr (std::is_same_v || + std::is_same_v) { + return "BIGINT"; + } else if constexpr (std::is_same_v) { + return "REAL"; + } else if constexpr (std::is_same_v) { + return "DOUBLE PRECISION"; + } else if constexpr (std::is_same_v) { + return "TEXT"; + } else if constexpr (std::is_same_v) { + return "VARCHAR(" + std::to_string(_t.length) + ")"; + } else if constexpr (std::is_same_v) { + return "TIMESTAMP"; + } else if constexpr (std::is_same_v) { + return "TIMESTAMP WITH TIME ZONE"; + } else if constexpr (std::is_same_v) { + return "TEXT"; + } else { + static_assert(rfl::always_false_v, "Not all cases were covered."); + } + }); +} + } // namespace sqlgen::postgres