backend tests progress

This commit is contained in:
Sascha Kuehl 2024-01-31 07:21:06 +01:00
parent e171147915
commit 7c02d745c8
9 changed files with 88 additions and 20 deletions

View File

@ -3,6 +3,4 @@
- Add is_valid() method to connection & connection_impl
- Read in entity fields
- Add special handling for update in backends
- Add PostgreSQL backend
- Add MySQL/MariaDB backend
- Add ODBC/SQL Server backend

View File

@ -145,7 +145,7 @@ sql::record postgres_connection::describe(const std::string &table)
while (reader.fetch()) {
char *end = nullptr;
// Todo: Handle error
auto index = strtoul(reader.column(0), &end, 10);
auto index = strtoul(reader.column(0), &end, 10) - 1;
std::string name = reader.column(1);
// Todo: extract size
@ -156,7 +156,7 @@ sql::record postgres_connection::describe(const std::string &table)
null_opt = sql::null_option::NOT_NULL;
}
// f.default_value(res->column(4));
prototype.append({name, type, utils::null_attributes, null_opt});
prototype.append({name, type, utils::null_attributes, null_opt, index});
}
return std::move(prototype);

View File

@ -18,6 +18,7 @@ public:
drop_table_if_exists("flight");
drop_table_if_exists("airplane");
drop_table_if_exists("person");
drop_table_if_exists("quotes");
}
protected:
@ -34,7 +35,7 @@ private:
using namespace matador::sql;
TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement", "[session][record]")
{
REQUIRE(!ses.table_exists("person"));
ses.create()
@ -54,7 +55,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement", "[ses
REQUIRE(!ses.table_exists("person"));
}
TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement with foreign key", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement with foreign key", "[session][record]")
{
ses.create()
.table("airplane", {
@ -89,7 +90,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement with fo
REQUIRE(!ses.table_exists("airplane"));
}
TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement", "[session][record]")
{
ses.create()
.table("person", {
@ -128,7 +129,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement", "[ses
.execute();
}
TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement with foreign key", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement with foreign key", "[session][record]")
{
ses.create()
.table("airplane", {
@ -168,7 +169,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement with fo
REQUIRE(!ses.table_exists("airplane"));
}
TEST_CASE_METHOD(SessionRecordFixture, " Execute update record statement", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Execute update record statement", "[session][record]")
{
ses.create()
.table("person", {
@ -214,7 +215,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute update record statement", "[ses
ses.drop().table("person").execute();
}
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement", "[session][record]")
{
ses.create()
.table("person", {
@ -257,7 +258,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement", "[session re
ses.drop().table("person").execute();
}
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with order by", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with order by", "[session][record]")
{
ses.create()
.table("person", {
@ -291,7 +292,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with order by"
ses.drop().table("person").execute();
}
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with group by and order by", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with group by and order by", "[session][record]")
{
ses.create()
.table("person", {
@ -330,7 +331,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with group by
ses.drop().table("person").execute();
}
TEST_CASE_METHOD(SessionRecordFixture, " Execute delete statement", "[session record]")
TEST_CASE_METHOD(SessionRecordFixture, " Execute delete statement", "[session][record]")
{
ses.create()
.table("person", {
@ -359,3 +360,37 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute delete statement", "[session re
ses.drop().table("person").execute();
}
TEST_CASE_METHOD(SessionRecordFixture, " Test quoted identifier", "[session][record]") {
ses.create()
.table("quotes", {
make_column<std::string>("from", 255),
make_column<std::string>("to", 255)
}).execute();
// check table description
std::vector<std::string> columns = { "from", "to"};
std::vector<data_type_t> types = {data_type_t::type_varchar, data_type_t::type_varchar};
auto fields = ses.describe_table("quotes");
for (const auto &field : fields) {
REQUIRE(field.name() == columns[field.index()]);
REQUIRE(field.type() == types[field.index()]);
}
ses.insert().into("quotes", {"from", "to"}).values({"Berlin", "London"}).execute();
auto res = ses.select({"from", "to"}).from("quotes").fetch_one();
REQUIRE("Berlin" == res.at("from").str());
REQUIRE("London" == res.at("to").str());
ses.update("quotes").set({{"from", "Hamburg"}, {"to", "New York"}}).where("from"_col == "Berlin").execute();
res = ses.select({"from", "to"}).from("quotes").fetch_one();
REQUIRE("Hamburg" == res.at("from").str());
REQUIRE("New York" == res.at("to").str());
ses.drop().table("quotes").execute();
}

View File

@ -37,7 +37,7 @@ public:
: column(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr, null_opt)
{}
column(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt);
column(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt, size_t index = 0);
template<typename Type>
column(std::string name, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt)

View File

@ -39,10 +39,13 @@ public:
statement prepare(query_context &&query) const;
const class dialect& dialect() const;
private:
connection_info connection_info_;
std::unique_ptr<connection_impl> connection_;
utils::logger logger_;
const class dialect &dialect_;
};
}

View File

@ -24,8 +24,8 @@ public:
record() = default;
record(std::initializer_list<column> columns);
explicit record(const std::vector<column> &columns);
record(const record&) = default;
record& operator=(const record&) = default;
record(const record &x);
record& operator=(const record &x);
record(record&&) noexcept = default;
record& operator=(record&&) noexcept = default;
~record() = default;
@ -45,8 +45,8 @@ public:
void append(column col);
bool has_primary_key() const;
const column& primary_key() const;
[[nodiscard]] bool has_primary_key() const;
[[nodiscard]] const column& primary_key() const;
[[nodiscard]] const std::vector<column>& columns() const;

View File

@ -16,8 +16,8 @@ column::column(std::string name, std::string alias)
: name_(std::move(name)), attributes_(utils::null_attributes), alias_(std::move(alias))
{}
column::column(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt)
: name_(std::move(name)), type_(type), attributes_(attr), null_option_(null_opt)
column::column(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt, size_t index)
: name_(std::move(name)), index_(index), type_(type), attributes_(attr), null_option_(null_opt)
{}
column::column(std::string name, data_type_t type, size_t index, std::string ref_table, std::string ref_column,

View File

@ -11,6 +11,7 @@ namespace matador::sql {
connection::connection(connection_info info)
: connection_info_(std::move(info))
, logger_(stdout, "SQL")
, dialect_(backend_provider::instance().connection_dialect(info.type))
{
connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_));
}
@ -22,6 +23,7 @@ connection::connection(const std::string& dns)
connection::connection(const connection &x)
: connection_info_(x.connection_info_)
, logger_(x.logger_)
, dialect_(x.dialect_)
{
if (x.connection_) {
throw std::runtime_error("couldn't copy connection with valid connection impl");
@ -93,4 +95,9 @@ statement connection::prepare(query_context &&query) const
return statement(connection_->prepare(std::move(query)), logger_);
}
const class dialect &connection::dialect() const
{
return dialect_;
}
}

View File

@ -16,6 +16,30 @@ record::record(const std::vector<column> &columns)
init();
}
record::record(const record &x)
: columns_(x.columns_)
, pk_index_(x.pk_index_)
{
for (auto& col : columns_) {
add_to_map(col, col.index());
}
}
record &record::operator=(const record &x)
{
if (&x == this) {
return *this;
}
columns_ = x.columns_;
columns_by_name_.clear();
pk_index_ = x.pk_index_;
for (auto& col : columns_) {
add_to_map(col, col.index());
}
return *this;
}
const std::vector<column> &record::columns() const
{
return columns_;
@ -37,6 +61,7 @@ const column &record::primary_key() const
const column &record::at(const std::string &name) const
{
auto ref = columns_by_name_.at(name).first;
return columns_by_name_.at(name).first;
}