diff --git a/backends/postgres/src/postgres_connection.cpp b/backends/postgres/src/postgres_connection.cpp index da57ab2..ec5cf0c 100644 --- a/backends/postgres/src/postgres_connection.cpp +++ b/backends/postgres/src/postgres_connection.cpp @@ -96,8 +96,8 @@ utils::result, utils::error> postgres_co std::vector prototype = context.prototype; - const auto num_col = PQnfields(res); - if (prototype.size() != num_col) { + const int num_col = PQnfields(res); + if (prototype.size() != static_cast(num_col)) { return utils::failure(make_error(sql::error_code::FETCH_FAILED, res, conn_, "Number of received columns doesn't match expected columns.", context.sql)); } for (int i = 0; i < num_col; ++i) { @@ -170,7 +170,7 @@ utils::basic_type oid2type(const Oid oid) { return utils::basic_type::type_int32; case 20: return utils::basic_type::type_int64; - case 24: + case 25: return utils::basic_type::type_text; case 1043: return utils::basic_type::type_varchar; diff --git a/backends/postgres/test/CMakeLists.txt b/backends/postgres/test/CMakeLists.txt index 2edc12c..e45efed 100644 --- a/backends/postgres/test/CMakeLists.txt +++ b/backends/postgres/test/CMakeLists.txt @@ -2,7 +2,7 @@ CPMAddPackage("gh:catchorg/Catch2@3.7.1") list(APPEND CMAKE_MODULE_PATH ${catch2_SOURCE_DIR}/extras) -set(POSTGRES_CONNECTION_STRING "postgres://news:news@localhost:15432/matador") +set(POSTGRES_CONNECTION_STRING "postgres://test:test123!@127.0.0.1:5432/matador") configure_file(Connection.hpp.in ${PROJECT_BINARY_DIR}/backends/postgres/test/connection.hpp @ONLY IMMEDIATE) diff --git a/include/matador/object/attribute_definition_generator.hpp b/include/matador/object/attribute_definition_generator.hpp index a8bd051..db19b29 100644 --- a/include/matador/object/attribute_definition_generator.hpp +++ b/include/matador/object/attribute_definition_generator.hpp @@ -32,20 +32,20 @@ public: type_ = utils::data_type_traits::type(0); } void on_primary_key(const char * /*id*/, std::string &/*pk*/, size_t size); - void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {} + static void on_revision(const char * /*id*/, unsigned long long &/*rev*/) {} template < class Type > - void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} - void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} + static void on_attribute(const char * /*id*/, Type &/*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} + static void on_attribute(const char * /*id*/, char * /*x*/, const utils::field_attributes &/*attr*/ = utils::null_attributes) {} template - void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} + static void on_belongs_to(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} template - void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} + static void on_has_one(const char * /*id*/, Pointer &/*x*/, const utils::foreign_attributes &/*attr*/) {} template - void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} + static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} template - void on_has_many_to_many(const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &/*attr*/) {} + static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {} template - void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {} + static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {} private: utils::basic_type type_{}; @@ -65,7 +65,7 @@ public: attribute_definition_generator gen(columns, repo); Type obj; access::process(gen, obj); - return std::move(columns); + return columns; } template < class V > @@ -92,11 +92,11 @@ public: } } template - void on_has_many(const char *id, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} + static void on_has_many(const char * /*id*/, ContainerType &, const char *, const utils::foreign_attributes &/*attr*/) {} template - void on_has_many_to_many(const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &/*attr*/) {} + static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes &/*attr*/) {} template - void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &/*attr*/) {} + static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {} private: [[nodiscard]] utils::result, utils::error> determine_foreign_ref(const std::type_index &ti) const; @@ -122,7 +122,7 @@ void attribute_definition_generator::on_attribute(const char *id, Type &x, const } template -void attribute_definition_generator::on_attribute(const char *id, std::optional &x, const utils::field_attributes &attr) +void attribute_definition_generator::on_attribute(const char *id, std::optional & /*x*/, const utils::field_attributes &attr) { columns_.emplace_back(id, utils::data_type_traits::type(attr.size()), attr, null_option::NULLABLE); } diff --git a/include/matador/object/schema_node.hpp b/include/matador/object/schema_node.hpp index 5c0bad6..d22a4d3 100644 --- a/include/matador/object/schema_node.hpp +++ b/include/matador/object/schema_node.hpp @@ -53,7 +53,6 @@ public: template object_info_ref info() const { - auto ref = std::ref(static_cast&>(*info_)); return std::ref(static_cast&>(*info_)); } diff --git a/include/matador/orm/session.hpp b/include/matador/orm/session.hpp index 4a31448..5cbe78e 100644 --- a/include/matador/orm/session.hpp +++ b/include/matador/orm/session.hpp @@ -26,7 +26,7 @@ public: explicit session(sql::connection_pool &pool); template - [[nodiscard]] utils::result attach(const std::string &table_name); + [[nodiscard]] utils::result attach(const std::string &table_name) const; utils::result create_schema() const; @@ -58,6 +58,9 @@ public: auto obj = build_select_query(data.release()).template fetch_one(*c); if (!obj) { + return utils::failure(obj.err()); + } + if (!obj->get()) { return utils::failure(make_error(error_code::FailedToFindObject, "Failed to find object of type " + info->get().name() + " with primary key " + std::to_string(pk) + ".")); } return utils::ok(object::object_ptr{ obj.release() }); @@ -104,8 +107,8 @@ public: } template - void drop_table(); - void drop_table(const std::string &table_name) const; + utils::result drop_table(); + utils::result drop_table(const std::string &table_name) const; [[nodiscard]] utils::result, utils::error> fetch(const sql::query_context &q) const; // [[nodiscard]] query_result fetch(const std::string &sql) const; @@ -133,8 +136,7 @@ private: }; template -[[nodiscard]] utils::result session::attach(const std::string &table_name) -{ +[[nodiscard]] utils::result session::attach(const std::string &table_name) const { return schema_->attach(table_name); } @@ -159,13 +161,14 @@ utils::result, utils::error> session::insert(Type *obj) } template -void session::drop_table() -{ +utils::result session::drop_table() { auto info = schema_->info(); if (info) { - return drop_table(info.name); + return drop_table(info->get().name()); } + return utils::failure(info.err()); } + } #endif //QUERY_SESSION_HPP diff --git a/include/matador/orm/session_query_builder.hpp b/include/matador/orm/session_query_builder.hpp index e7cd14b..cd6038b 100644 --- a/include/matador/orm/session_query_builder.hpp +++ b/include/matador/orm/session_query_builder.hpp @@ -62,10 +62,10 @@ private: struct entity_query_data { std::string root_table_name; - std::string pk_column_; - std::vector columns; - std::vector joins; - std::unique_ptr where_clause; + std::string pk_column_{}; + std::vector columns{}; + std::vector joins{}; + std::unique_ptr where_clause{}; }; enum class query_build_error : std::uint8_t { @@ -175,7 +175,7 @@ public: } template - void on_has_many(const char * id, ContainerType &, const char *join_column, const utils::foreign_attributes &attr) { + void on_has_many(const char * /*id*/, ContainerType &, const char *join_column, const utils::foreign_attributes &attr) { if (attr.fetch() == utils::fetch_type::EAGER) { const auto info = schema_.info(); if (!info) { diff --git a/include/matador/query/query_compiler.hpp b/include/matador/query/query_compiler.hpp index 5ee62d0..b336c2e 100644 --- a/include/matador/query/query_compiler.hpp +++ b/include/matador/query/query_compiler.hpp @@ -15,6 +15,10 @@ class dialect; namespace matador::query { +namespace internal { +struct basic_type_to_string_visitor; +} + struct query_data; struct value_visitor; @@ -56,6 +60,7 @@ protected: static std::string build_table_name(sql::dialect_token token, const sql::dialect &d, const sql::table& t); std::string determine_value(value_visitor &visitor, const std::variant &val); + std::string determine_set_value(internal::basic_type_to_string_visitor &visitor, const utils::database_type &val); protected: const query_data *data_{}; diff --git a/include/matador/sql/column_generator.hpp b/include/matador/sql/column_generator.hpp index f844660..3c4de2d 100644 --- a/include/matador/sql/column_generator.hpp +++ b/include/matador/sql/column_generator.hpp @@ -37,7 +37,7 @@ public: column_generator gen(columns, scm, info.value().get().name(), force_lazy); Type obj; access::process(gen, obj); - return std::move(columns); + return columns; } template < class V > @@ -113,10 +113,10 @@ public: } template - static void on_has_many_to_many(const char *id, ContainerType &c, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes &attr) {} + static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const char * /*join_column*/, const char * /*inverse_join_column*/, const utils::foreign_attributes & /*attr*/) {} template - static void on_has_many_to_many(const char *id, ContainerType &c, const utils::foreign_attributes &attr) {} + static void on_has_many_to_many(const char * /*id*/, ContainerType & /*cont*/, const utils::foreign_attributes &/*attr*/) {} private: void push(const std::string &column_name); diff --git a/include/matador/utils/convert.hpp b/include/matador/utils/convert.hpp index a5d5187..3d4c002 100644 --- a/include/matador/utils/convert.hpp +++ b/include/matador/utils/convert.hpp @@ -222,6 +222,9 @@ result to(const SourceType &/*source*/, std::enable_ template < typename DestType, typename SourceType > result to(const SourceType &source, std::enable_if_t &&std::is_same_v>* = nullptr) { + if (source == nullptr) { + return ok(std::string{}); + } return ok(std::string(source)); } diff --git a/source/orm/orm/session.cpp b/source/orm/orm/session.cpp index 597aff2..be39c86 100644 --- a/source/orm/orm/session.cpp +++ b/source/orm/orm/session.cpp @@ -30,13 +30,20 @@ utils::result session::create_schema() const { return utils::ok(); } -void session::drop_table(const std::string &table_name) const { +utils::result session::drop_table(const std::string &table_name) const { auto c = pool_.acquire(); if (!c.valid()) { throw std::logic_error("no database connection available"); } - // c->query(*schema_).drop().table(table_name).execute(); + auto result = query::query::drop() + .table(table_name) + .execute(*c); + if (result.is_error()) { + return utils::failure(result.err()); + } + + return utils::ok(); } utils::result, utils::error> session::fetch(const sql::query_context &q) const diff --git a/source/orm/query/query_compiler.cpp b/source/orm/query/query_compiler.cpp index ba357d7..c4d08eb 100644 --- a/source/orm/query/query_compiler.cpp +++ b/source/orm/query/query_compiler.cpp @@ -183,6 +183,7 @@ std::string query_compiler::determine_value(value_visitor &visitor, const std::v query_.bind_vars.emplace_back(std::string("value_") + std::to_string(query_.bind_vars.size() + 1)); return dialect_->next_placeholder(query_.bind_vars); } + void query_compiler::visit(internal::query_values_part &values_part) { query_.sql += " " + dialect_->token_at(sql::dialect_token::VALUES); @@ -289,32 +290,45 @@ void query_compiler::visit(internal::query_drop_part &/*drop_part*/) query_.sql = dialect_->token_at(sql::dialect_token::DROP); } +std::string query_compiler::determine_set_value(internal::basic_type_to_string_visitor &visitor, const utils::database_type &val) { + if (data_->mode == query_mode::Direct) { + std::visit(visitor, val); + return visitor.result; + } + + query_.bind_vars.emplace_back(std::string("value_") + std::to_string(query_.bind_vars.size() + 1)); + return dialect_->next_placeholder(query_.bind_vars); +} + void query_compiler::visit(internal::query_set_part &set_part) { query_.sql += " " + dialect_->token_at(sql::dialect_token::SET) + " "; attribute_string_writer writer(*dialect_, connection_); - internal::basic_type_to_string_visitor value_to_string(writer, query_); + internal::basic_type_to_string_visitor visitor(writer, query_); std::string result; if (set_part.key_values().size() < 2) { for (const auto &col: set_part.key_values()) { result.append(dialect_->prepare_identifier_string(col.name()) + "="); - auto var = col.value(); - std::visit(value_to_string, var); - result.append(value_to_string.result); + result.append(determine_set_value(visitor, col.value())); + // auto var = col.value(); + // std::visit(visitor, var); + // result.append(visitor.result); } } else { auto it = set_part.key_values().begin(); result.append(dialect_->prepare_identifier_string(it->name()) + "="); - auto var = (it++)->value(); - std::visit(value_to_string, var); - result.append(value_to_string.result); + result.append(determine_set_value(visitor, (it++)->value())); + // auto var = (it++)->value(); + // std::visit(visitor, var); + // result.append(visitor.result); for (; it != set_part.key_values().end(); ++it) { result.append(", "); result.append(dialect_->prepare_identifier_string(it->name()) + "="); - var = it->value(); - std::visit(value_to_string, var); - result.append(value_to_string.result); + result.append(determine_set_value(visitor, it->value())); + // var = it->value(); + // std::visit(visitor, var); + // result.append(visitor.result); } } diff --git a/test/backends/QueryBasicTest.cpp b/test/backends/QueryBasicTest.cpp index 42f5929..564b5a2 100644 --- a/test/backends/QueryBasicTest.cpp +++ b/test/backends/QueryBasicTest.cpp @@ -291,8 +291,8 @@ TEST_CASE_METHOD(QueryFixture, "Test describe table", "[query][describe][table]" std::vector column_names = { "id", "val_char", "val_float", "val_double", "val_short", - "val_int", "val_long", "val_long_long", "val_unsigned_char", - "val_unsigned_short", "val_unsigned_int", "val_unsigned_long", "val_unsigned_long_long", + "val_int", "val_long_long", "val_unsigned_char", + "val_unsigned_short", "val_unsigned_int", "val_unsigned_long_long", "val_bool", "val_cstr", "val_string", "val_varchar", // "val_date", "val_time", "val_binary"}; @@ -307,8 +307,8 @@ TEST_CASE_METHOD(QueryFixture, "Test describe table", "[query][describe][table]" [](const attribute_definition &cf) { return cf.is_integer(); }, [](const attribute_definition &cf) { return cf.is_integer(); }, [](const attribute_definition &cf) { return cf.is_integer(); }, - [](const attribute_definition &cf) { return cf.is_integer(); }, - [](const attribute_definition &cf) { return cf.is_integer(); }, + // [](const attribute_definition &cf) { return cf.is_integer(); }, + // [](const attribute_definition &cf) { return cf.is_integer(); }, [](const attribute_definition &cf) { return cf.is_integer(); }, [](const attribute_definition &cf) { return cf.is_bool(); }, [](const attribute_definition &cf) { return cf.is_varchar(); }, diff --git a/test/backends/SessionTest.cpp b/test/backends/SessionTest.cpp index 373af8e..4c759ac 100644 --- a/test/backends/SessionTest.cpp +++ b/test/backends/SessionTest.cpp @@ -48,11 +48,11 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session auto a380 = ses.insert(1, "Boeing", "A380"); REQUIRE(a380.is_ok()); - auto res = ses.find(2); - REQUIRE(!result.is_ok()); - REQUIRE((result.err().ec() == orm::error_code::FailedToFindObject)); + auto find_result = ses.find(2); + REQUIRE(!find_result.is_ok()); + REQUIRE((find_result.err().ec() == orm::error_code::FailedToFindObject)); - auto find_result = ses.find(1); + find_result = ses.find(1); REQUIRE(find_result); auto read_a380 = find_result.value(); diff --git a/test/models/author.hpp b/test/models/author.hpp index e947d54..a309ec2 100644 --- a/test/models/author.hpp +++ b/test/models/author.hpp @@ -30,7 +30,7 @@ struct author { field::attribute(op, "date_of_birth", date_of_birth, 31); field::attribute(op, "year_of_birth", year_of_birth); field::attribute(op, "distinguished", distinguished); - field::has_many(op, "books", books, "author_id", utils::fetch_type::EAGER); + field::has_many(op, "books", books, "author_id", utils::fetch_type::LAZY); } }; diff --git a/test/models/person.hpp b/test/models/person.hpp index be894bd..1342686 100644 --- a/test/models/person.hpp +++ b/test/models/person.hpp @@ -13,7 +13,7 @@ struct person { unsigned int id{}; std::string name; unsigned int age{}; - utils::blob image; + utils::blob image{}; template void process(Operator &op) { diff --git a/test/models/recipe.hpp b/test/models/recipe.hpp index a832a4d..eb39c15 100644 --- a/test/models/recipe.hpp +++ b/test/models/recipe.hpp @@ -16,7 +16,7 @@ struct ingredient { unsigned int id{}; std::string name; - std::vector> recipes; + std::vector> recipes{}; template void process(Operator &op) { @@ -31,7 +31,7 @@ struct recipe { unsigned int id{}; std::string name; - std::vector> ingredients; + std::vector> ingredients{}; template void process(Operator &op) {