backend tests progress
This commit is contained in:
parent
e171147915
commit
7c02d745c8
2
Todo.md
2
Todo.md
|
|
@ -3,6 +3,4 @@
|
||||||
- Add is_valid() method to connection & connection_impl
|
- Add is_valid() method to connection & connection_impl
|
||||||
- Read in entity fields
|
- Read in entity fields
|
||||||
- Add special handling for update in backends
|
- Add special handling for update in backends
|
||||||
- Add PostgreSQL backend
|
|
||||||
- Add MySQL/MariaDB backend
|
|
||||||
- Add ODBC/SQL Server backend
|
- Add ODBC/SQL Server backend
|
||||||
|
|
@ -145,7 +145,7 @@ sql::record postgres_connection::describe(const std::string &table)
|
||||||
while (reader.fetch()) {
|
while (reader.fetch()) {
|
||||||
char *end = nullptr;
|
char *end = nullptr;
|
||||||
// Todo: Handle error
|
// 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);
|
std::string name = reader.column(1);
|
||||||
|
|
||||||
// Todo: extract size
|
// Todo: extract size
|
||||||
|
|
@ -156,7 +156,7 @@ sql::record postgres_connection::describe(const std::string &table)
|
||||||
null_opt = sql::null_option::NOT_NULL;
|
null_opt = sql::null_option::NOT_NULL;
|
||||||
}
|
}
|
||||||
// f.default_value(res->column(4));
|
// 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);
|
return std::move(prototype);
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@ public:
|
||||||
drop_table_if_exists("flight");
|
drop_table_if_exists("flight");
|
||||||
drop_table_if_exists("airplane");
|
drop_table_if_exists("airplane");
|
||||||
drop_table_if_exists("person");
|
drop_table_if_exists("person");
|
||||||
|
drop_table_if_exists("quotes");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
@ -34,7 +35,7 @@ private:
|
||||||
|
|
||||||
using namespace matador::sql;
|
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"));
|
REQUIRE(!ses.table_exists("person"));
|
||||||
ses.create()
|
ses.create()
|
||||||
|
|
@ -54,7 +55,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement", "[ses
|
||||||
REQUIRE(!ses.table_exists("person"));
|
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()
|
ses.create()
|
||||||
.table("airplane", {
|
.table("airplane", {
|
||||||
|
|
@ -89,7 +90,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement with fo
|
||||||
REQUIRE(!ses.table_exists("airplane"));
|
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()
|
ses.create()
|
||||||
.table("person", {
|
.table("person", {
|
||||||
|
|
@ -128,7 +129,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement", "[ses
|
||||||
.execute();
|
.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()
|
ses.create()
|
||||||
.table("airplane", {
|
.table("airplane", {
|
||||||
|
|
@ -168,7 +169,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement with fo
|
||||||
REQUIRE(!ses.table_exists("airplane"));
|
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()
|
ses.create()
|
||||||
.table("person", {
|
.table("person", {
|
||||||
|
|
@ -214,7 +215,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute update record statement", "[ses
|
||||||
ses.drop().table("person").execute();
|
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()
|
ses.create()
|
||||||
.table("person", {
|
.table("person", {
|
||||||
|
|
@ -257,7 +258,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement", "[session re
|
||||||
ses.drop().table("person").execute();
|
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()
|
ses.create()
|
||||||
.table("person", {
|
.table("person", {
|
||||||
|
|
@ -291,7 +292,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with order by"
|
||||||
ses.drop().table("person").execute();
|
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()
|
ses.create()
|
||||||
.table("person", {
|
.table("person", {
|
||||||
|
|
@ -330,7 +331,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with group by
|
||||||
ses.drop().table("person").execute();
|
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()
|
ses.create()
|
||||||
.table("person", {
|
.table("person", {
|
||||||
|
|
@ -359,3 +360,37 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute delete statement", "[session re
|
||||||
|
|
||||||
ses.drop().table("person").execute();
|
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();
|
||||||
|
}
|
||||||
|
|
@ -37,7 +37,7 @@ public:
|
||||||
: column(std::move(name), data_type_traits<Type>::builtin_type(attr.size()), attr, null_opt)
|
: 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>
|
template<typename Type>
|
||||||
column(std::string name, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt)
|
column(std::string name, std::string ref_table, std::string ref_column, utils::field_attributes attr, null_option null_opt)
|
||||||
|
|
|
||||||
|
|
@ -39,10 +39,13 @@ public:
|
||||||
|
|
||||||
statement prepare(query_context &&query) const;
|
statement prepare(query_context &&query) const;
|
||||||
|
|
||||||
|
const class dialect& dialect() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
connection_info connection_info_;
|
connection_info connection_info_;
|
||||||
std::unique_ptr<connection_impl> connection_;
|
std::unique_ptr<connection_impl> connection_;
|
||||||
utils::logger logger_;
|
utils::logger logger_;
|
||||||
|
const class dialect &dialect_;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -24,8 +24,8 @@ public:
|
||||||
record() = default;
|
record() = default;
|
||||||
record(std::initializer_list<column> columns);
|
record(std::initializer_list<column> columns);
|
||||||
explicit record(const std::vector<column> &columns);
|
explicit record(const std::vector<column> &columns);
|
||||||
record(const record&) = default;
|
record(const record &x);
|
||||||
record& operator=(const record&) = default;
|
record& operator=(const record &x);
|
||||||
record(record&&) noexcept = default;
|
record(record&&) noexcept = default;
|
||||||
record& operator=(record&&) noexcept = default;
|
record& operator=(record&&) noexcept = default;
|
||||||
~record() = default;
|
~record() = default;
|
||||||
|
|
@ -45,8 +45,8 @@ public:
|
||||||
|
|
||||||
void append(column col);
|
void append(column col);
|
||||||
|
|
||||||
bool has_primary_key() const;
|
[[nodiscard]] bool has_primary_key() const;
|
||||||
const column& primary_key() const;
|
[[nodiscard]] const column& primary_key() const;
|
||||||
|
|
||||||
[[nodiscard]] const std::vector<column>& columns() const;
|
[[nodiscard]] const std::vector<column>& columns() const;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@ column::column(std::string name, std::string alias)
|
||||||
: name_(std::move(name)), attributes_(utils::null_attributes), alias_(std::move(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)
|
column::column(std::string name, data_type_t type, utils::field_attributes attr, null_option null_opt, size_t index)
|
||||||
: name_(std::move(name)), type_(type), attributes_(attr), null_option_(null_opt)
|
: 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,
|
column::column(std::string name, data_type_t type, size_t index, std::string ref_table, std::string ref_column,
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ namespace matador::sql {
|
||||||
connection::connection(connection_info info)
|
connection::connection(connection_info info)
|
||||||
: connection_info_(std::move(info))
|
: connection_info_(std::move(info))
|
||||||
, logger_(stdout, "SQL")
|
, logger_(stdout, "SQL")
|
||||||
|
, dialect_(backend_provider::instance().connection_dialect(info.type))
|
||||||
{
|
{
|
||||||
connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_));
|
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::connection(const connection &x)
|
||||||
: connection_info_(x.connection_info_)
|
: connection_info_(x.connection_info_)
|
||||||
, logger_(x.logger_)
|
, logger_(x.logger_)
|
||||||
|
, dialect_(x.dialect_)
|
||||||
{
|
{
|
||||||
if (x.connection_) {
|
if (x.connection_) {
|
||||||
throw std::runtime_error("couldn't copy connection with valid connection impl");
|
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_);
|
return statement(connection_->prepare(std::move(query)), logger_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const class dialect &connection::dialect() const
|
||||||
|
{
|
||||||
|
return dialect_;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,30 @@ record::record(const std::vector<column> &columns)
|
||||||
init();
|
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
|
const std::vector<column> &record::columns() const
|
||||||
{
|
{
|
||||||
return columns_;
|
return columns_;
|
||||||
|
|
@ -37,6 +61,7 @@ const column &record::primary_key() const
|
||||||
|
|
||||||
const column &record::at(const std::string &name) 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;
|
return columns_by_name_.at(name).first;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue