From ed6366fef652557e0e5afeb9e2a9167f5dc39797 Mon Sep 17 00:00:00 2001 From: Sascha Kuehl Date: Thu, 18 Jan 2024 07:21:40 +0100 Subject: [PATCH] determine NOT NULL constraint from std::optional --- include/matador/sql/column_generator.hpp | 19 ++++++++-- include/matador/utils/access.hpp | 6 ++++ src/sql/column_generator.cpp | 2 +- test/ColumnGeneratorTest.cpp | 46 ++++++++++++++++++------ 4 files changed, 58 insertions(+), 15 deletions(-) diff --git a/include/matador/sql/column_generator.hpp b/include/matador/sql/column_generator.hpp index 0a071c8..eff5566 100644 --- a/include/matador/sql/column_generator.hpp +++ b/include/matador/sql/column_generator.hpp @@ -73,7 +73,10 @@ public: void on_revision(const char *id, unsigned long long &rev); template - void on_attribute(const char *id, Type &x, const utils::field_attributes &attr = utils::null_attributes); + void on_attribute(const char *id, Type &x, const utils::field_attributes &attr = utils::not_null_attributes); + + template + void on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr = utils::null_attributes); template void on_belongs_to(const char *id, Pointer &x, utils::cascade_type) @@ -106,13 +109,23 @@ private: template void column_generator::on_primary_key(const char *id, V &x, typename std::enable_if::value && !std::is_same::value>::type*) { - on_attribute(id, x, { utils::constraints::PRIMARY_KEY }); + on_attribute(id, x, { utils::constraints::PRIMARY_KEY | utils::constraints::NOT_NULL }); } template void column_generator::on_attribute(const char *id, Type &x, const utils::field_attributes &attr) { - columns_.emplace_back(id, x, attr); + if (attr.options() == utils::constraints::NONE) { + columns_.push_back(column{id, x, { attr.size(), utils::constraints::NOT_NULL}}); + } else { + columns_.emplace_back(id, x, attr); + } +} + +template +void column_generator::on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr) +{ + columns_.emplace_back(id, data_type_traits::builtin_type(attr.size()), attr); } } diff --git a/include/matador/utils/access.hpp b/include/matador/utils/access.hpp index e77a901..796b72b 100644 --- a/include/matador/utils/access.hpp +++ b/include/matador/utils/access.hpp @@ -4,6 +4,7 @@ #include "matador/utils/cascade_type.hpp" #include +#include namespace matador::utils { @@ -44,6 +45,11 @@ void attribute(Operator &op, const char *id, Type &value, const field_attributes op.on_attribute(id, value, attr); } +template +void attribute(Operator &op, const char *id, std::optional &value, const field_attributes &attr) { + op.on_attribute(id, value, attr); +} + template void attribute(Operator &op, const char *id, Type &value) { op.on_attribute(id, value); diff --git a/src/sql/column_generator.cpp b/src/sql/column_generator.cpp index 56afb2d..0cefa5d 100644 --- a/src/sql/column_generator.cpp +++ b/src/sql/column_generator.cpp @@ -10,7 +10,7 @@ column_generator::column_generator(std::vector &columns, const table_rep void column_generator::on_primary_key(const char *id, std::string &pk, size_t size) { - on_attribute(id, pk, { size, utils::constraints::PRIMARY_KEY }); + on_attribute(id, pk, { size, utils::constraints::PRIMARY_KEY | utils::constraints::NOT_NULL }); } void column_generator::on_revision(const char *id, unsigned long long int &x) diff --git a/test/ColumnGeneratorTest.cpp b/test/ColumnGeneratorTest.cpp index f8ec55b..e488697 100644 --- a/test/ColumnGeneratorTest.cpp +++ b/test/ColumnGeneratorTest.cpp @@ -4,29 +4,53 @@ #include "matador/sql/table_repository.hpp" #include "models/product.hpp" +#include "models/optional.hpp" using namespace matador::sql; +using namespace matador::utils; TEST_CASE("Generate columns from object", "[column generator]") { table_repository repo; auto columns = column_generator::generate(repo); - const std::vector expected_columns = { - "product_name", - "supplier_id", - "category_id", - "quantity_per_unit", - "unit_price", - "units_in_stock", - "units_in_order", - "reorder_level", - "discontinued" + const std::vector expected_columns = { + column{ "product_name", data_type_t::type_varchar, { constraints::PRIMARY_KEY | constraints::NOT_NULL } }, + column{ "supplier_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY }, + column{ "category_id", data_type_t::type_unsigned_long, constraints::FOREIGN_KEY }, + column{ "quantity_per_unit", data_type_t::type_varchar, constraints::NOT_NULL }, + column{ "unit_price", data_type_t::type_unsigned_int, constraints::NOT_NULL }, + column{ "units_in_stock", data_type_t::type_unsigned_int, constraints::NOT_NULL }, + column{ "units_in_order", data_type_t::type_unsigned_int, constraints::NOT_NULL }, + column{ "reorder_level", data_type_t::type_unsigned_int, constraints::NOT_NULL }, + column{ "discontinued", data_type_t::type_bool, constraints::NOT_NULL } }; REQUIRE(!columns.empty()); REQUIRE(columns.size() == expected_columns.size()); for (size_t i = 0; i != expected_columns.size(); ++i) { - REQUIRE(expected_columns[i] == columns[i].name()); + REQUIRE(expected_columns[i].name() == columns[i].name()); + REQUIRE(expected_columns[i].attributes().options() == columns[i].attributes().options() ); + REQUIRE(expected_columns[i].type() == columns[i].type() ); } } + +TEST_CASE("Generate columns from object with nullable columns", "[column generator]") { + table_repository repo; + + auto columns = column_generator::generate(repo); + + const std::vector expected_columns = { + column{ "id", data_type_t::type_unsigned_long, { constraints::PRIMARY_KEY | constraints::NOT_NULL } }, + column{ "name", data_type_t::type_varchar, null_attributes }, + column{ "age", data_type_t::type_unsigned_int, null_attributes } + }; + REQUIRE(!columns.empty()); + REQUIRE(columns.size() == expected_columns.size()); + + for (size_t i = 0; i != expected_columns.size(); ++i) { + REQUIRE(expected_columns[i].name() == columns[i].name()); + REQUIRE(expected_columns[i].attributes().options() == columns[i].attributes().options() ); + REQUIRE(expected_columns[i].type() == columns[i].type() ); + } +} \ No newline at end of file