fixed postgres tests
This commit is contained in:
parent
6e64ba99de
commit
ec96c15905
|
|
@ -96,8 +96,8 @@ utils::result<std::unique_ptr<sql::query_result_impl>, utils::error> postgres_co
|
|||
|
||||
std::vector<object::attribute_definition> 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<size_t>(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;
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -32,20 +32,20 @@ public:
|
|||
type_ = utils::data_type_traits<ValueType>::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<class Pointer>
|
||||
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<class Pointer>
|
||||
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<class ContainerType>
|
||||
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<class ContainerType>
|
||||
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<class ContainerType>
|
||||
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<class ContainerType>
|
||||
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<class ContainerType>
|
||||
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<class ContainerType>
|
||||
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<std::shared_ptr<attribute_definition>, 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<typename Type>
|
||||
void attribute_definition_generator::on_attribute(const char *id, std::optional<Type> &x, const utils::field_attributes &attr)
|
||||
void attribute_definition_generator::on_attribute(const char *id, std::optional<Type> & /*x*/, const utils::field_attributes &attr)
|
||||
{
|
||||
columns_.emplace_back(id, utils::data_type_traits<Type>::type(attr.size()), attr, null_option::NULLABLE);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,7 +53,6 @@ public:
|
|||
|
||||
template <typename Type>
|
||||
object_info_ref<Type> info() const {
|
||||
auto ref = std::ref(static_cast<const object_info<Type>&>(*info_));
|
||||
return std::ref(static_cast<const object_info<Type>&>(*info_));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ public:
|
|||
explicit session(sql::connection_pool<sql::connection> &pool);
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &table_name);
|
||||
[[nodiscard]] utils::result<void, utils::error> attach(const std::string &table_name) const;
|
||||
|
||||
utils::result<void, utils::error> create_schema() const;
|
||||
|
||||
|
|
@ -58,6 +58,9 @@ public:
|
|||
auto obj = build_select_query(data.release()).template fetch_one<Type>(*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<Type>{ obj.release() });
|
||||
|
|
@ -104,8 +107,8 @@ public:
|
|||
}
|
||||
|
||||
template<typename Type>
|
||||
void drop_table();
|
||||
void drop_table(const std::string &table_name) const;
|
||||
utils::result<void, utils::error> drop_table();
|
||||
utils::result<void, utils::error> drop_table(const std::string &table_name) const;
|
||||
|
||||
[[nodiscard]] utils::result<sql::query_result<sql::record>, utils::error> fetch(const sql::query_context &q) const;
|
||||
// [[nodiscard]] query_result<record> fetch(const std::string &sql) const;
|
||||
|
|
@ -133,8 +136,7 @@ private:
|
|||
};
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] utils::result<void, utils::error> session::attach(const std::string &table_name)
|
||||
{
|
||||
[[nodiscard]] utils::result<void, utils::error> session::attach(const std::string &table_name) const {
|
||||
return schema_->attach<Type>(table_name);
|
||||
}
|
||||
|
||||
|
|
@ -159,13 +161,14 @@ utils::result<object::object_ptr<Type>, utils::error> session::insert(Type *obj)
|
|||
}
|
||||
|
||||
template<typename Type>
|
||||
void session::drop_table()
|
||||
{
|
||||
utils::result<void, utils::error> session::drop_table() {
|
||||
auto info = schema_->info<Type>();
|
||||
if (info) {
|
||||
return drop_table(info.name);
|
||||
return drop_table(info->get().name());
|
||||
}
|
||||
|
||||
return utils::failure(info.err());
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endif //QUERY_SESSION_HPP
|
||||
|
|
|
|||
|
|
@ -62,10 +62,10 @@ private:
|
|||
|
||||
struct entity_query_data {
|
||||
std::string root_table_name;
|
||||
std::string pk_column_;
|
||||
std::vector<sql::column> columns;
|
||||
std::vector<query::join_data> joins;
|
||||
std::unique_ptr<query::basic_condition> where_clause;
|
||||
std::string pk_column_{};
|
||||
std::vector<sql::column> columns{};
|
||||
std::vector<query::join_data> joins{};
|
||||
std::unique_ptr<query::basic_condition> where_clause{};
|
||||
};
|
||||
|
||||
enum class query_build_error : std::uint8_t {
|
||||
|
|
@ -175,7 +175,7 @@ public:
|
|||
}
|
||||
|
||||
template<class ContainerType>
|
||||
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<typename ContainerType::value_type::value_type>();
|
||||
if (!info) {
|
||||
|
|
|
|||
|
|
@ -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<utils::placeholder, utils::database_type> &val);
|
||||
std::string determine_set_value(internal::basic_type_to_string_visitor &visitor, const utils::database_type &val);
|
||||
|
||||
protected:
|
||||
const query_data *data_{};
|
||||
|
|
|
|||
|
|
@ -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<class ContainerType>
|
||||
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<class ContainerType>
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -222,6 +222,9 @@ result<DestType, conversion_error> to(const SourceType &/*source*/, std::enable_
|
|||
|
||||
template < typename DestType, typename SourceType >
|
||||
result<DestType, conversion_error> to(const SourceType &source, std::enable_if_t<std::is_same_v<SourceType, const char*> &&std::is_same_v<DestType, std::string>>* = nullptr) {
|
||||
if (source == nullptr) {
|
||||
return ok(std::string{});
|
||||
}
|
||||
return ok(std::string(source));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -30,13 +30,20 @@ utils::result<void, utils::error> session::create_schema() const {
|
|||
return utils::ok<void>();
|
||||
}
|
||||
|
||||
void session::drop_table(const std::string &table_name) const {
|
||||
utils::result<void, utils::error> 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<void>();
|
||||
}
|
||||
|
||||
utils::result<sql::query_result<sql::record>, utils::error> session::fetch(const sql::query_context &q) const
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -291,8 +291,8 @@ TEST_CASE_METHOD(QueryFixture, "Test describe table", "[query][describe][table]"
|
|||
|
||||
std::vector<std::string> 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(); },
|
||||
|
|
|
|||
|
|
@ -48,11 +48,11 @@ TEST_CASE_METHOD(SessionFixture, "Use session to find object with id", "[session
|
|||
auto a380 = ses.insert<airplane>(1, "Boeing", "A380");
|
||||
REQUIRE(a380.is_ok());
|
||||
|
||||
auto res = ses.find<airplane>(2);
|
||||
REQUIRE(!result.is_ok());
|
||||
REQUIRE((result.err().ec() == orm::error_code::FailedToFindObject));
|
||||
auto find_result = ses.find<airplane>(2);
|
||||
REQUIRE(!find_result.is_ok());
|
||||
REQUIRE((find_result.err().ec() == orm::error_code::FailedToFindObject));
|
||||
|
||||
auto find_result = ses.find<airplane>(1);
|
||||
find_result = ses.find<airplane>(1);
|
||||
|
||||
REQUIRE(find_result);
|
||||
auto read_a380 = find_result.value();
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ struct person {
|
|||
unsigned int id{};
|
||||
std::string name;
|
||||
unsigned int age{};
|
||||
utils::blob image;
|
||||
utils::blob image{};
|
||||
|
||||
template<class Operator>
|
||||
void process(Operator &op) {
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ struct ingredient
|
|||
{
|
||||
unsigned int id{};
|
||||
std::string name;
|
||||
std::vector<object::object_ptr<recipe>> recipes;
|
||||
std::vector<object::object_ptr<recipe>> recipes{};
|
||||
|
||||
template<class Operator>
|
||||
void process(Operator &op) {
|
||||
|
|
@ -31,7 +31,7 @@ struct recipe
|
|||
{
|
||||
unsigned int id{};
|
||||
std::string name;
|
||||
std::vector<object::object_ptr<ingredient>> ingredients;
|
||||
std::vector<object::object_ptr<ingredient>> ingredients{};
|
||||
|
||||
template<class Operator>
|
||||
void process(Operator &op) {
|
||||
|
|
|
|||
Loading…
Reference in New Issue