mirror of
https://github.com/getml/sqlgen.git
synced 2026-01-08 02:19:32 -06:00
Added the support for insert
This commit is contained in:
@@ -1,6 +0,0 @@
|
||||
#ifndef SQLGEN_INTERNAL_COLLECT_HPP_
|
||||
#define SQLGEN_INTERNAL_COLLECT_HPP_
|
||||
|
||||
namespace sqlgen::internal::collect {}
|
||||
|
||||
#endif
|
||||
111
include/sqlgen/parsing/make_columns.hpp
Normal file
111
include/sqlgen/parsing/make_columns.hpp
Normal file
@@ -0,0 +1,111 @@
|
||||
#ifndef SQLGEN_PARSING_MAKE_COLUMNS_HPP_
|
||||
#define SQLGEN_PARSING_MAKE_COLUMNS_HPP_
|
||||
|
||||
#include <rfl.hpp>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
|
||||
#include "../dynamic/Column.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "../dynamic/types.hpp"
|
||||
#include "has_reflection_method.hpp"
|
||||
#include "is_nullable.hpp"
|
||||
#include "is_primary_key.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <class Name>
|
||||
std::string to_colname() {
|
||||
return Name().str();
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
dynamic::Type to_type() {
|
||||
using T = std::remove_cvref_t<Type>;
|
||||
if constexpr (is_primary_key_v<T>) {
|
||||
return to_type<typename T::ReflectionType>().visit(
|
||||
[](auto _t) -> dynamic::Type {
|
||||
_t.properties.primary = true;
|
||||
return _t;
|
||||
});
|
||||
|
||||
} else if constexpr (is_nullable_v<T>) {
|
||||
const auto set_nullable = [](auto _t) -> dynamic::Type {
|
||||
_t.properties.nullable = true;
|
||||
return _t;
|
||||
};
|
||||
if constexpr (is_ptr<T>::value) {
|
||||
return to_type<typename T::element_type>().visit(set_nullable);
|
||||
} else {
|
||||
return to_type<typename T::value_type>().visit(set_nullable);
|
||||
}
|
||||
|
||||
} else if constexpr (has_reflection_method<T>) {
|
||||
return to_type<typename Type::ReflectionType>();
|
||||
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
return dynamic::types::Boolean{};
|
||||
|
||||
} else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>) {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return dynamic::types::Int8{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return dynamic::types::Int16{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::Int32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::Int64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported signed integer.");
|
||||
}
|
||||
} else if constexpr (std::is_integral_v<T> && !std::is_signed_v<T>) {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return dynamic::types::UInt8{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return dynamic::types::UInt16{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::UInt32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::UInt64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported unsigned integer.");
|
||||
}
|
||||
} else if constexpr (std::is_floating_point_v<T>) {
|
||||
if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::Float32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::Float64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>,
|
||||
"Unsupported floating point value.");
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
return dynamic::types::Text{};
|
||||
}
|
||||
}
|
||||
|
||||
template <class FieldType>
|
||||
dynamic::Column to_column() {
|
||||
return dynamic::Column{.name = to_colname<typename FieldType::Name>(),
|
||||
.type = to_type<typename FieldType::Type>()};
|
||||
}
|
||||
|
||||
template <class Fields, int... _is>
|
||||
std::vector<dynamic::Column> make_columns(std::integer_sequence<int, _is...>) {
|
||||
return std::vector<dynamic::Column>(
|
||||
{to_column<rfl::tuple_element_t<_is, Fields>>()...});
|
||||
}
|
||||
|
||||
} // namespace sqlgen::parsing
|
||||
|
||||
#endif
|
||||
@@ -7,115 +7,14 @@
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../dynamic/Column.hpp"
|
||||
#include "../dynamic/CreateTable.hpp"
|
||||
#include "../dynamic/Table.hpp"
|
||||
#include "../dynamic/Type.hpp"
|
||||
#include "../dynamic/types.hpp"
|
||||
#include "get_schema.hpp"
|
||||
#include "get_tablename.hpp"
|
||||
#include "has_reflection_method.hpp"
|
||||
#include "is_nullable.hpp"
|
||||
#include "is_primary_key.hpp"
|
||||
#include "make_columns.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
namespace internal {
|
||||
|
||||
template <class Name>
|
||||
std::string to_colname() {
|
||||
return Name().str();
|
||||
}
|
||||
|
||||
template <class Type>
|
||||
dynamic::Type to_type() {
|
||||
using T = std::remove_cvref_t<Type>;
|
||||
if constexpr (is_primary_key_v<T>) {
|
||||
return to_type<typename T::ReflectionType>().visit(
|
||||
[](auto _t) -> dynamic::Type {
|
||||
_t.properties.primary = true;
|
||||
return _t;
|
||||
});
|
||||
|
||||
} else if constexpr (is_nullable_v<T>) {
|
||||
const auto set_nullable = [](auto _t) -> dynamic::Type {
|
||||
_t.properties.nullable = true;
|
||||
return _t;
|
||||
};
|
||||
if constexpr (is_ptr<T>::value) {
|
||||
return to_type<typename T::element_type>().visit(set_nullable);
|
||||
} else {
|
||||
return to_type<typename T::value_type>().visit(set_nullable);
|
||||
}
|
||||
|
||||
} else if constexpr (has_reflection_method<T>) {
|
||||
return to_type<typename Type::ReflectionType>();
|
||||
|
||||
} else if constexpr (std::is_same_v<T, bool>) {
|
||||
return dynamic::types::Boolean{};
|
||||
|
||||
} else if constexpr (std::is_integral_v<T> && std::is_signed_v<T>) {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return dynamic::types::Int8{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return dynamic::types::Int16{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::Int32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::Int64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported signed integer.");
|
||||
}
|
||||
} else if constexpr (std::is_integral_v<T> && !std::is_signed_v<T>) {
|
||||
if constexpr (sizeof(T) == 1) {
|
||||
return dynamic::types::UInt8{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 2) {
|
||||
return dynamic::types::UInt16{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::UInt32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::UInt64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>, "Unsupported unsigned integer.");
|
||||
}
|
||||
} else if constexpr (std::is_floating_point_v<T>) {
|
||||
if constexpr (sizeof(T) == 4) {
|
||||
return dynamic::types::Float32{};
|
||||
|
||||
} else if constexpr (sizeof(T) == 8) {
|
||||
return dynamic::types::Float64{};
|
||||
|
||||
} else {
|
||||
static_assert(rfl::always_false_v<T>,
|
||||
"Unsupported floating point value.");
|
||||
}
|
||||
} else if constexpr (std::is_same_v<T, std::string>) {
|
||||
return dynamic::types::Text{};
|
||||
}
|
||||
}
|
||||
|
||||
template <class FieldType>
|
||||
dynamic::Column to_column() {
|
||||
return dynamic::Column{.name = to_colname<typename FieldType::Name>(),
|
||||
.type = to_type<typename FieldType::Type>()};
|
||||
}
|
||||
|
||||
template <class Fields, int... _is>
|
||||
std::vector<dynamic::Column> make_columns(std::integer_sequence<int, _is...>) {
|
||||
return std::vector<dynamic::Column>(
|
||||
{to_column<rfl::tuple_element_t<_is, Fields>>()...});
|
||||
}
|
||||
|
||||
} // namespace internal
|
||||
|
||||
template <class T>
|
||||
requires std::is_class_v<std::remove_cvref_t<T>> &&
|
||||
std::is_aggregate_v<std::remove_cvref_t<T>>
|
||||
@@ -125,7 +24,7 @@ dynamic::CreateTable to_create_table() {
|
||||
return dynamic::CreateTable{
|
||||
.table =
|
||||
dynamic::Table{.name = get_tablename<T>(), .schema = get_schema<T>()},
|
||||
.columns = internal::make_columns<Fields>(
|
||||
.columns = make_columns<Fields>(
|
||||
std::make_integer_sequence<int, rfl::tuple_size_v<Fields>>()),
|
||||
.if_not_exists = true};
|
||||
}
|
||||
|
||||
42
include/sqlgen/parsing/to_insert.hpp
Normal file
42
include/sqlgen/parsing/to_insert.hpp
Normal file
@@ -0,0 +1,42 @@
|
||||
#ifndef SQLGEN_PARSING_TO_INSERT_HPP_
|
||||
#define SQLGEN_PARSING_TO_INSERT_HPP_
|
||||
|
||||
#include <ranges>
|
||||
#include <rfl.hpp>
|
||||
#include <string>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "../dynamic/Insert.hpp"
|
||||
#include "../dynamic/Table.hpp"
|
||||
#include "../internal/collect/vector.hpp"
|
||||
#include "get_schema.hpp"
|
||||
#include "get_tablename.hpp"
|
||||
#include "make_columns.hpp"
|
||||
|
||||
namespace sqlgen::parsing {
|
||||
|
||||
template <class T>
|
||||
requires std::is_class_v<std::remove_cvref_t<T>> &&
|
||||
std::is_aggregate_v<std::remove_cvref_t<T>>
|
||||
dynamic::Insert to_insert() {
|
||||
using namespace std::ranges::views;
|
||||
|
||||
using NamedTupleType = rfl::named_tuple_t<std::remove_cvref_t<T>>;
|
||||
using Fields = typename NamedTupleType::Fields;
|
||||
|
||||
const auto columns = make_columns<Fields>(
|
||||
std::make_integer_sequence<int, rfl::tuple_size_v<Fields>>());
|
||||
|
||||
const auto get_name = [](const auto& _col) { return _col.name; };
|
||||
|
||||
return dynamic::Insert{.table = dynamic::Table{.name = get_tablename<T>(),
|
||||
.schema = get_schema<T>()},
|
||||
.columns = sqlgen::internal::collect::vector(
|
||||
columns | transform(get_name))};
|
||||
}
|
||||
|
||||
} // namespace sqlgen::parsing
|
||||
|
||||
#endif
|
||||
26
tests/test_to_insert.cpp
Normal file
26
tests/test_to_insert.cpp
Normal file
@@ -0,0 +1,26 @@
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
#include <rfl/json.hpp>
|
||||
#include <sqlgen.hpp>
|
||||
#include <sqlgen/parsing/to_insert.hpp>
|
||||
|
||||
namespace test_to_insert {
|
||||
|
||||
struct TestTable {
|
||||
std::string field1;
|
||||
int32_t field2;
|
||||
sqlgen::PrimaryKey<uint32_t> id;
|
||||
std::optional<std::string> nullable;
|
||||
};
|
||||
|
||||
TEST(general, test_to_insert) {
|
||||
const auto insert_stmt = sqlgen::parsing::to_insert<TestTable>();
|
||||
|
||||
const std::string expected =
|
||||
R"({"table":{"name":"TestTable"},"columns":["field1","field2","id","nullable"]})";
|
||||
|
||||
const auto json_str = rfl::json::write(insert_stmt);
|
||||
|
||||
EXPECT_EQ(json_str, expected);
|
||||
}
|
||||
} // namespace test_to_insert
|
||||
Reference in New Issue
Block a user