sequence tests progress
This commit is contained in:
parent
6bdf281eab
commit
86c9e6b1cd
|
|
@ -38,6 +38,8 @@ public:
|
||||||
utils::result<std::vector<object::attribute>, utils::error> describe(const std::string& table) override;
|
utils::result<std::vector<object::attribute>, utils::error> describe(const std::string& table) override;
|
||||||
utils::result<bool, utils::error> exists(const std::string &schema_name, const std::string &table_name) override;
|
utils::result<bool, utils::error> exists(const std::string &schema_name, const std::string &table_name) override;
|
||||||
|
|
||||||
|
utils::result<bool, utils::error> sequence_exists(const std::string &schema_name, const std::string &sequence_name) override;
|
||||||
|
|
||||||
[[nodiscard]] std::string to_escaped_string( const utils::blob_type_t& value ) const override;
|
[[nodiscard]] std::string to_escaped_string( const utils::blob_type_t& value ) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
||||||
|
|
@ -298,6 +298,10 @@ utils::result<bool, utils::error> postgres_connection::exists(const std::string
|
||||||
return utils::ok(*result == 1);
|
return utils::ok(*result == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::result<bool, utils::error> postgres_connection::sequence_exists(const std::string& schema_name, const std::string& sequence_name) {
|
||||||
|
return utils::ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
std::string postgres_connection::to_escaped_string(const utils::blob_type_t &value) const {
|
std::string postgres_connection::to_escaped_string(const utils::blob_type_t &value) const {
|
||||||
size_t escapedDataLength;
|
size_t escapedDataLength;
|
||||||
unsigned char *escapedData = PQescapeByteaConn(conn_, value.data(), value.size(), &escapedDataLength);
|
unsigned char *escapedData = PQescapeByteaConn(conn_, value.data(), value.size(), &escapedDataLength);
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,8 @@ set(TEST_SOURCES
|
||||||
../../../test/utils/record_printer.hpp
|
../../../test/utils/record_printer.hpp
|
||||||
../../../test/utils/record_printer.cpp
|
../../../test/utils/record_printer.cpp
|
||||||
../../../test/models/model_metas.hpp
|
../../../test/models/model_metas.hpp
|
||||||
|
../../../test/backends/SequenceFixture.hpp
|
||||||
|
../../../test/backends/SequenceFixture.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
set(LIBRARY_TEST_TARGET PostgresTests)
|
set(LIBRARY_TEST_TARGET PostgresTests)
|
||||||
|
|
|
||||||
|
|
@ -26,7 +26,6 @@ public:
|
||||||
|
|
||||||
private:
|
private:
|
||||||
class table table_;
|
class table table_;
|
||||||
utils::generator_type generator_type_{};
|
|
||||||
std::unique_ptr<abstract_pk_generator> pk_generator_;
|
std::unique_ptr<abstract_pk_generator> pk_generator_;
|
||||||
const object::repository_node& node_;
|
const object::repository_node& node_;
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -141,7 +141,7 @@ public:
|
||||||
template<class Collection>
|
template<class Collection>
|
||||||
static void on_has_many(const char * /*id*/, Collection &/*con*/, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
static void on_has_many(const char * /*id*/, Collection &/*con*/, const char * /*join_column*/, const utils::foreign_attributes & ) {}
|
||||||
template<class Collection>
|
template<class Collection>
|
||||||
void on_has_many_to_many(const char *id, Collection &con, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes & ) {
|
void on_has_many_to_many(const char *id, Collection &container, const char *join_column, const char *inverse_join_column, const utils::foreign_attributes & ) {
|
||||||
if (id == nullptr || join_column == nullptr || inverse_join_column == nullptr) {
|
if (id == nullptr || join_column == nullptr || inverse_join_column == nullptr) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -151,13 +151,13 @@ public:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto rel_it = schema_.find(std::string{id});
|
const auto it = schema_.find(std::string{id});
|
||||||
if (rel_it == schema_.end()) {
|
if (it == schema_.end()) {
|
||||||
throw query_builder_exception(query_build_error::UnknownType);
|
throw query_builder_exception(query_build_error::UnknownType);
|
||||||
}
|
}
|
||||||
const table &rel_table = rel_it->second.table();
|
const table &relation_table = it->second.table();
|
||||||
|
|
||||||
for (auto &obj : con) {
|
for (auto &obj : container) {
|
||||||
if (!obj) {
|
if (!obj) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
@ -179,7 +179,7 @@ public:
|
||||||
insert_step rel_step{};
|
insert_step rel_step{};
|
||||||
rel_step.query = executable_query{
|
rel_step.query = executable_query{
|
||||||
query::query::insert()
|
query::query::insert()
|
||||||
.into(rel_table, {table_column{&rel_table, join_column}, table_column{&rel_table, inverse_join_column}})
|
.into(relation_table, {table_column{&relation_table, join_column}, table_column{&relation_table, inverse_join_column}})
|
||||||
.values({utils::database_type{current_entity_pk_}, utils::database_type{fk.value}})
|
.values({utils::database_type{current_entity_pk_}, utils::database_type{fk.value}})
|
||||||
};
|
};
|
||||||
relation_steps_.push_back(std::move(rel_step));
|
relation_steps_.push_back(std::move(rel_step));
|
||||||
|
|
|
||||||
|
|
@ -135,6 +135,9 @@ public:
|
||||||
[[nodiscard]] utils::result<bool, utils::error> exists(const std::string &schema_name, const std::string &table_name) const;
|
[[nodiscard]] utils::result<bool, utils::error> exists(const std::string &schema_name, const std::string &table_name) const;
|
||||||
[[nodiscard]] utils::result<bool, utils::error> exists(const std::string &table_name) const;
|
[[nodiscard]] utils::result<bool, utils::error> exists(const std::string &table_name) const;
|
||||||
|
|
||||||
|
|
||||||
|
[[nodiscard]] utils::result<bool, utils::error> sequence_exists(const std::string &sequence_name) const;
|
||||||
|
|
||||||
[[nodiscard]] utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(const query_context &ctx) const override;
|
[[nodiscard]] utils::result<std::unique_ptr<query_result_impl>, utils::error> fetch(const query_context &ctx) const override;
|
||||||
[[nodiscard]] utils::result<execute_result, utils::error> execute(const query_context &ctx) const override;
|
[[nodiscard]] utils::result<execute_result, utils::error> execute(const query_context &ctx) const override;
|
||||||
[[nodiscard]] utils::result<statement, utils::error> prepare(const query_context &ctx) override;
|
[[nodiscard]] utils::result<statement, utils::error> prepare(const query_context &ctx) override;
|
||||||
|
|
|
||||||
|
|
@ -42,6 +42,8 @@ public:
|
||||||
virtual utils::result<std::vector<object::attribute>, utils::error> describe(const std::string &table) = 0;
|
virtual utils::result<std::vector<object::attribute>, utils::error> describe(const std::string &table) = 0;
|
||||||
virtual utils::result<bool, utils::error> exists(const std::string &schema_name, const std::string &table_name) = 0;
|
virtual utils::result<bool, utils::error> exists(const std::string &schema_name, const std::string &table_name) = 0;
|
||||||
|
|
||||||
|
virtual utils::result<bool, utils::error> sequence_exists(const std::string &schema_name, const std::string &sequence_name) = 0;
|
||||||
|
|
||||||
[[nodiscard]] const class dialect &dialect() const;
|
[[nodiscard]] const class dialect &dialect() const;
|
||||||
|
|
||||||
[[nodiscard]] virtual std::string to_escaped_string(const utils::blob_type_t &value) const = 0;
|
[[nodiscard]] virtual std::string to_escaped_string(const utils::blob_type_t &value) const = 0;
|
||||||
|
|
|
||||||
|
|
@ -163,6 +163,10 @@ utils::result<bool, utils::error> connection::exists(const std::string &table_na
|
||||||
return connection_->exists(dialect().default_schema_name(), table_name);
|
return connection_->exists(dialect().default_schema_name(), table_name);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::result<bool, utils::error> connection::sequence_exists(const std::string& sequence_name) const {
|
||||||
|
return connection_->sequence_exists(sequence_name);
|
||||||
|
}
|
||||||
|
|
||||||
bool has_unknown_columns(const std::vector<object::attribute> &columns) {
|
bool has_unknown_columns(const std::vector<object::attribute> &columns) {
|
||||||
return std::any_of(std::begin(columns), std::end(columns), [](const auto &col) {
|
return std::any_of(std::begin(columns), std::end(columns), [](const auto &col) {
|
||||||
return col.type() == utils::basic_type::Null;
|
return col.type() == utils::basic_type::Null;
|
||||||
|
|
|
||||||
|
|
@ -47,5 +47,6 @@ void QueryFixture::drop_table_if_exists(const std::string &table_name) const {
|
||||||
}
|
}
|
||||||
return utils::ok(true);
|
return utils::ok(true);
|
||||||
});
|
});
|
||||||
|
REQUIRE(result);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,35 @@
|
||||||
|
#include "SequenceFixture.hpp"
|
||||||
|
|
||||||
|
#include "matador/query/query.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/dialect.hpp"
|
||||||
|
|
||||||
|
#include "connection.hpp"
|
||||||
|
|
||||||
|
#include "catch2/catch_test_macros.hpp"
|
||||||
|
|
||||||
|
namespace matador::test {
|
||||||
|
SequenceFixture::SequenceFixture()
|
||||||
|
: db(connection::dns)
|
||||||
|
, repo(db.dialect().default_schema_name()) {
|
||||||
|
REQUIRE(db.open());
|
||||||
|
}
|
||||||
|
|
||||||
|
SequenceFixture::~SequenceFixture() {
|
||||||
|
while (!sequences_to_drop.empty()) {
|
||||||
|
drop_sequence_if_exists(sequences_to_drop.top());
|
||||||
|
sequences_to_drop.pop();
|
||||||
|
}
|
||||||
|
REQUIRE(repo.drop(db));
|
||||||
|
REQUIRE(db.close());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceFixture::check_sequence_exists(const std::string& sequence_name) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceFixture::check_sequence_not_exists(const std::string& sequence_name) const {
|
||||||
|
}
|
||||||
|
|
||||||
|
void SequenceFixture::drop_sequence_if_exists(const std::string& sequence_name) const {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
#ifndef MATADOR_SEQUENCE_FIXTURE_HPP
|
||||||
|
#define MATADOR_SEQUENCE_FIXTURE_HPP
|
||||||
|
|
||||||
|
|
||||||
|
#include "matador/query/schema.hpp"
|
||||||
|
|
||||||
|
#include "matador/sql/connection.hpp"
|
||||||
|
|
||||||
|
#include <stack>
|
||||||
|
|
||||||
|
namespace matador::test {
|
||||||
|
class SequenceFixture {
|
||||||
|
public:
|
||||||
|
SequenceFixture();
|
||||||
|
~SequenceFixture();
|
||||||
|
|
||||||
|
void check_sequence_exists(const std::string &sequence_name) const;
|
||||||
|
void check_sequence_not_exists(const std::string &sequence_name) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
sql::connection db;
|
||||||
|
std::stack <std::string> sequences_to_drop;
|
||||||
|
query::schema repo;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void drop_sequence_if_exists(const std::string &sequence_name) const;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif //MATADOR_SEQUENCE_FIXTURE_HPP
|
||||||
|
|
@ -70,6 +70,11 @@ utils::result<bool, utils::error> test_connection::exists(const std::string &/*s
|
||||||
return utils::ok(false);
|
return utils::ok(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
utils::result<bool, utils::error> test_connection::sequence_exists(const std::string& /*schema_name*/,
|
||||||
|
const std::string& /*sequence_name*/) {
|
||||||
|
return utils::ok(false);
|
||||||
|
}
|
||||||
|
|
||||||
std::string test_connection::to_escaped_string(const utils::blob_type_t &value) const {
|
std::string test_connection::to_escaped_string(const utils::blob_type_t &value) const {
|
||||||
return utils::to_string(value);
|
return utils::to_string(value);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ public:
|
||||||
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> prepare(const sql::query_context &context) override;
|
utils::result<std::unique_ptr<sql::statement_impl>, utils::error> prepare(const sql::query_context &context) override;
|
||||||
utils::result<std::vector<object::attribute>, utils::error> describe(const std::string &table) override;
|
utils::result<std::vector<object::attribute>, utils::error> describe(const std::string &table) override;
|
||||||
utils::result<bool, utils::error> exists(const std::string &schema_name, const std::string &table_name) override;
|
utils::result<bool, utils::error> exists(const std::string &schema_name, const std::string &table_name) override;
|
||||||
|
utils::result<bool, utils::error> sequence_exists(const std::string &schema_name, const std::string &sequence_name) override;
|
||||||
|
|
||||||
[[nodiscard]] std::string to_escaped_string( const utils::blob_type_t& value ) const override;
|
[[nodiscard]] std::string to_escaped_string( const utils::blob_type_t& value ) const override;
|
||||||
|
|
||||||
|
|
|
||||||
48
todo.md
48
todo.md
|
|
@ -1,5 +1,27 @@
|
||||||
# Todo
|
# Todo
|
||||||
|
|
||||||
|
Order of next steps:
|
||||||
|
1. Finish pk generator
|
||||||
|
- classes
|
||||||
|
- detection on schema attach
|
||||||
|
- tests
|
||||||
|
2. PK accessor class
|
||||||
|
- extract from `insert_query_builder` class
|
||||||
|
- get(), set(), is_null/valid/set()
|
||||||
|
- detection on schema attach
|
||||||
|
- tests
|
||||||
|
3. Add owner-awareness to the collection class
|
||||||
|
- add owner field
|
||||||
|
- bind owner on session insert
|
||||||
|
- tests
|
||||||
|
4. Finish `insert_query_builder`
|
||||||
|
- collect all inserts for entities with relations
|
||||||
|
- tests
|
||||||
|
5. Finish `session::insert` method
|
||||||
|
- use `insert_query_builder`
|
||||||
|
- correct handling of pk generator
|
||||||
|
- tests
|
||||||
|
|
||||||
- move `prepare_*` methods from `dialect` to `query_compiler`
|
- move `prepare_*` methods from `dialect` to `query_compiler`
|
||||||
- add `insert_query_builder` and `update_update_builder` (returning multiple statements)
|
- add `insert_query_builder` and `update_update_builder` (returning multiple statements)
|
||||||
- finish fetch eager many-to-many relations
|
- finish fetch eager many-to-many relations
|
||||||
|
|
@ -18,32 +40,6 @@
|
||||||
7. Extend `session::insert` logic to use pk generator
|
7. Extend `session::insert` logic to use pk generator
|
||||||
8. Add generator to `schema_node` or `table` class when attaching type
|
8. Add generator to `schema_node` or `table` class when attaching type
|
||||||
|
|
||||||
```cpp
|
|
||||||
struct abstract_pk_generator {
|
|
||||||
virtual ~abstract_pk_generator() = default;
|
|
||||||
virtual int64_t next_id() = 0;
|
|
||||||
virtual std::vector<int64_t> next_ids(int count) = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct sequence_pk_generator : abstract_pk_generator {
|
|
||||||
explicit sequence_pk_generator(const std::string& sequence_name)
|
|
||||||
: query_(query::query::select().nextval(sequence_name)) {}
|
|
||||||
int64_t next_id(sql::executor& exec) override {
|
|
||||||
return query_.fetch_value<int64_t>(exec);
|
|
||||||
}
|
|
||||||
std::vector<int64_t> next_ids(int count) override;
|
|
||||||
private:
|
|
||||||
query::fetchable_query query_;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct table_pk_generator : abstract_pk_generator {
|
|
||||||
explicit table_pk_generator(const std::string& table_name);
|
|
||||||
int64_t next_id() override;
|
|
||||||
std::vector<int64_t> next_ids(int count) override;
|
|
||||||
private:
|
|
||||||
std::string table_name_;
|
|
||||||
};
|
|
||||||
```
|
|
||||||
|
|
||||||
__Proposal for polymorphic classes:__
|
__Proposal for polymorphic classes:__
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue