backend tests progress
This commit is contained in:
parent
7c02d745c8
commit
c025fb282a
|
|
@ -234,19 +234,15 @@ sql::record mysql_connection::describe(const std::string &table)
|
|||
while (reader.fetch()) {
|
||||
|
||||
char *end = nullptr;
|
||||
// Todo: Handle error
|
||||
auto index = strtoul(reader.column(0), &end, 10);
|
||||
std::string name = reader.column(0);
|
||||
|
||||
// Todo: extract size
|
||||
auto typeinfo = determine_type_info(reader.column(1));
|
||||
end = nullptr;
|
||||
sql::null_option null_opt{sql::null_option::NULLABLE};
|
||||
if (strtoul(reader.column(2), &end, 10) == 0) {
|
||||
null_opt = sql::null_option::NOT_NULL;
|
||||
}
|
||||
// f.default_value(res->column(4));
|
||||
prototype.append({name, typeinfo.type, {typeinfo.size}, null_opt});
|
||||
prototype.append({name, typeinfo.type, {typeinfo.size}, null_opt, prototype.size()});
|
||||
}
|
||||
|
||||
return prototype;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ set(TEST_SOURCES
|
|||
../../tests/ConnectionTest.cpp
|
||||
../../tests/SessionRecordTest.cpp
|
||||
../../tests/StatementTest.cpp
|
||||
../../tests/TypeTraitsTest.cpp)
|
||||
../../tests/TypeTraitsTest.cpp
|
||||
../../tests/StatementCacheTest.cpp)
|
||||
|
||||
set(LIBRARY_TEST_TARGET mysql_tests)
|
||||
|
||||
|
|
|
|||
|
|
@ -22,8 +22,11 @@ void throw_postgres_error(PGconn *db, const std::string &source)
|
|||
|
||||
void throw_postgres_error(PGresult *res, PGconn *db, const std::string &source, const std::string &sql)
|
||||
{
|
||||
if (res == nullptr ||
|
||||
(PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||
if (res == nullptr) {
|
||||
std::stringstream msg;
|
||||
msg << "postgres error (" << source << ", " << PQerrorMessage(db) << ": " << sql;
|
||||
throw std::logic_error(msg.str());
|
||||
} else if ((PQresultStatus(res) != PGRES_COMMAND_OK &&
|
||||
PQresultStatus(res) != PGRES_TUPLES_OK)) {
|
||||
std::stringstream msg;
|
||||
msg << "postgres error (" << source << ", " << PQresultErrorField(res, PG_DIAG_SQLSTATE) << ") " << PQerrorMessage(db) << ": " << sql;
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ set(TEST_SOURCES
|
|||
../../tests/ConnectionTest.cpp
|
||||
../../tests/SessionRecordTest.cpp
|
||||
../../tests/StatementTest.cpp
|
||||
../../tests/TypeTraitsTest.cpp)
|
||||
../../tests/TypeTraitsTest.cpp
|
||||
../../tests/StatementCacheTest.cpp)
|
||||
|
||||
set(LIBRARY_TEST_TARGET postgres_tests)
|
||||
|
||||
|
|
|
|||
|
|
@ -163,7 +163,7 @@ sql::record sqlite_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);
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ set(TEST_SOURCES
|
|||
../../tests/ConnectionTest.cpp
|
||||
../../tests/SessionRecordTest.cpp
|
||||
../../tests/StatementTest.cpp
|
||||
../../tests/TypeTraitsTest.cpp)
|
||||
../../tests/TypeTraitsTest.cpp
|
||||
../../tests/StatementCacheTest.cpp)
|
||||
|
||||
set(LIBRARY_TEST_TARGET sqlite_tests)
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
#include "matador/sql/column.hpp"
|
||||
#include "matador/sql/condition.hpp"
|
||||
#include "matador/sql/session.hpp"
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
#include "connection.hpp"
|
||||
|
||||
|
|
@ -12,8 +12,10 @@ class SessionRecordFixture
|
|||
{
|
||||
public:
|
||||
SessionRecordFixture()
|
||||
: pool(matador::test::connection::dns, 4), ses(pool)
|
||||
{}
|
||||
: db(matador::test::connection::dns)
|
||||
{
|
||||
db.open();
|
||||
}
|
||||
~SessionRecordFixture() {
|
||||
drop_table_if_exists("flight");
|
||||
drop_table_if_exists("airplane");
|
||||
|
|
@ -22,13 +24,12 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
matador::sql::connection_pool<matador::sql::connection> pool;
|
||||
matador::sql::session ses;
|
||||
matador::sql::connection db;
|
||||
|
||||
private:
|
||||
void drop_table_if_exists(const std::string &table_name) {
|
||||
if (ses.table_exists(table_name)) {
|
||||
ses.drop().table(table_name).execute();
|
||||
if (db.exists(table_name)) {
|
||||
db.drop().table(table_name).execute();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -37,8 +38,8 @@ using namespace matador::sql;
|
|||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement", "[session][record]")
|
||||
{
|
||||
REQUIRE(!ses.table_exists("person"));
|
||||
ses.create()
|
||||
REQUIRE(!db.exists("person"));
|
||||
db.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
|
|
@ -46,18 +47,18 @@ TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement", "[ses
|
|||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(ses.table_exists("person"));
|
||||
REQUIRE(db.exists("person"));
|
||||
|
||||
ses.drop()
|
||||
db.drop()
|
||||
.table("person")
|
||||
.execute();
|
||||
|
||||
REQUIRE(!ses.table_exists("person"));
|
||||
REQUIRE(!db.exists("person"));
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement with foreign key", "[session][record]")
|
||||
{
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("airplane", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("brand", 255),
|
||||
|
|
@ -65,9 +66,9 @@ TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement with fo
|
|||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(ses.table_exists("airplane"));
|
||||
REQUIRE(db.exists("airplane"));
|
||||
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("flight", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_fk_column<unsigned long>("airplane_id", "airplane", "id"),
|
||||
|
|
@ -75,24 +76,24 @@ TEST_CASE_METHOD(SessionRecordFixture, " Create and drop table statement with fo
|
|||
})
|
||||
.execute();
|
||||
|
||||
REQUIRE(ses.table_exists("flight"));
|
||||
REQUIRE(db.exists("flight"));
|
||||
|
||||
ses.drop()
|
||||
db.drop()
|
||||
.table("flight")
|
||||
.execute();
|
||||
|
||||
REQUIRE(!ses.table_exists("flight"));
|
||||
REQUIRE(!db.exists("flight"));
|
||||
|
||||
ses.drop()
|
||||
db.drop()
|
||||
.table("airplane")
|
||||
.execute();
|
||||
|
||||
REQUIRE(!ses.table_exists("airplane"));
|
||||
REQUIRE(!db.exists("airplane"));
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement", "[session][record]")
|
||||
{
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
|
|
@ -100,14 +101,14 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement", "[ses
|
|||
})
|
||||
.execute();
|
||||
|
||||
auto res = ses.insert()
|
||||
auto res = db.insert()
|
||||
.into("person", {"id", "name", "age"})
|
||||
.values({7, "george", 45})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto result = ses.select({"id", "name", "age"})
|
||||
auto result = db.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.fetch_all();
|
||||
|
||||
|
|
@ -124,14 +125,14 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement", "[ses
|
|||
REQUIRE(i.at(2).template as<int>() == 45);
|
||||
}
|
||||
|
||||
ses.drop()
|
||||
db.drop()
|
||||
.table("person")
|
||||
.execute();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement with foreign key", "[session][record]")
|
||||
{
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("airplane", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("brand", 255),
|
||||
|
|
@ -139,7 +140,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement with fo
|
|||
})
|
||||
.execute();
|
||||
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("flight", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_fk_column<unsigned long>("airplane_id", "airplane", "id"),
|
||||
|
|
@ -147,31 +148,31 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute insert record statement with fo
|
|||
})
|
||||
.execute();
|
||||
|
||||
auto res = ses.insert().into("airplane", {"id", "brand", "model"}).values({1, "Airbus", "A380"}).execute();
|
||||
auto res = db.insert().into("airplane", {"id", "brand", "model"}).values({1, "Airbus", "A380"}).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
res = ses.insert().into("airplane", {"id", "brand", "model"}).values({2, "Boeing", "707"}).execute();
|
||||
res = db.insert().into("airplane", {"id", "brand", "model"}).values({2, "Boeing", "707"}).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
res = ses.insert().into("airplane", {"id", "brand", "model"}).values({3, "Boeing", "747"}).execute();
|
||||
res = db.insert().into("airplane", {"id", "brand", "model"}).values({3, "Boeing", "747"}).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto count = ses.select({count_all()}).from("airplane").fetch_value<int>();
|
||||
auto count = db.select({count_all()}).from("airplane").fetch_value<int>();
|
||||
REQUIRE(count == 3);
|
||||
|
||||
res = ses.insert().into("flight", {"id", "airplane_id", "pilot_name"}).values({4, 1, "George"}).execute();
|
||||
res = db.insert().into("flight", {"id", "airplane_id", "pilot_name"}).values({4, 1, "George"}).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
ses.drop().table("flight").execute();
|
||||
ses.drop().table("airplane").execute();
|
||||
db.drop().table("flight").execute();
|
||||
db.drop().table("airplane").execute();
|
||||
|
||||
REQUIRE(!ses.table_exists("flight"));
|
||||
REQUIRE(!ses.table_exists("airplane"));
|
||||
REQUIRE(!db.exists("flight"));
|
||||
REQUIRE(!db.exists("airplane"));
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Execute update record statement", "[session][record]")
|
||||
{
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
|
|
@ -179,14 +180,14 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute update record statement", "[ses
|
|||
})
|
||||
.execute();
|
||||
|
||||
auto res = ses.insert()
|
||||
auto res = db.insert()
|
||||
.into("person", {"id", "name", "age"})
|
||||
.values({7, "george", 45})
|
||||
.execute();
|
||||
|
||||
REQUIRE(res == 1);
|
||||
|
||||
res = ses.update("person")
|
||||
res = db.update("person")
|
||||
.set({{"id", 7},
|
||||
{"name", "jane"},
|
||||
{"age", 35}})
|
||||
|
|
@ -195,7 +196,7 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute update record statement", "[ses
|
|||
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto result = ses.select({"id", "name", "age"})
|
||||
auto result = db.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.fetch_all();
|
||||
|
||||
|
|
@ -212,12 +213,12 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute update record statement", "[ses
|
|||
REQUIRE(i.at(2).as<int>() == 35);
|
||||
}
|
||||
|
||||
ses.drop().table("person").execute();
|
||||
db.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement", "[session][record]")
|
||||
{
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
|
|
@ -225,16 +226,16 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement", "[session][r
|
|||
})
|
||||
.execute();
|
||||
|
||||
auto res = ses.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
auto res = db.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto result = ses.select({"id", "name", "age"})
|
||||
auto result = db.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.fetch_all();
|
||||
|
||||
|
|
@ -245,22 +246,22 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement", "[session][r
|
|||
}
|
||||
REQUIRE(expected_names.empty());
|
||||
|
||||
auto rec = ses.select({"id", "name", "age"})
|
||||
auto rec = db.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.fetch_one();
|
||||
REQUIRE(rec.at(1).str() == "george");
|
||||
|
||||
auto name = ses.select({"name"})
|
||||
auto name = db.select({"name"})
|
||||
.from("person")
|
||||
.fetch_value<std::string>();
|
||||
REQUIRE(name == "george");
|
||||
|
||||
ses.drop().table("person").execute();
|
||||
db.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with order by", "[session][record]")
|
||||
{
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
|
|
@ -268,16 +269,16 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with order by"
|
|||
})
|
||||
.execute();
|
||||
|
||||
auto res = ses.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
auto res = db.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({2, "jane", 32}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({3, "michael", 67}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto result = ses.select({"id", "name", "age"})
|
||||
auto result = db.select({"id", "name", "age"})
|
||||
.from("person")
|
||||
.order_by("name").asc()
|
||||
.fetch_all();
|
||||
|
|
@ -289,12 +290,12 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with order by"
|
|||
}
|
||||
REQUIRE(expected_names.empty());
|
||||
|
||||
ses.drop().table("person").execute();
|
||||
db.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with group by and order by", "[session][record]")
|
||||
{
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
|
|
@ -302,18 +303,18 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with group by
|
|||
})
|
||||
.execute();
|
||||
|
||||
auto res = ses.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
auto res = db.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({3, "michael", 13}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({3, "michael", 13}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({4, "bob", 13}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({5, "charlie", 67}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({5, "charlie", 67}).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto result = ses.select({alias(count("age"), "age_count"), "age"})
|
||||
auto result = db.select({alias(count("age"), "age_count"), "age"})
|
||||
.from("person")
|
||||
.group_by("age")
|
||||
.order_by("age_count").desc()
|
||||
|
|
@ -328,41 +329,41 @@ TEST_CASE_METHOD(SessionRecordFixture, " Execute select statement with group by
|
|||
expected_values.pop_front();
|
||||
}
|
||||
|
||||
ses.drop().table("person").execute();
|
||||
db.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Execute delete statement", "[session][record]")
|
||||
{
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
make_column<unsigned short>("age")
|
||||
}).execute();
|
||||
|
||||
auto res = ses.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
auto res = db.insert().into("person", {"id", "name", "age"}).values({1, "george", 45}).execute();
|
||||
REQUIRE(res == 1);
|
||||
res = ses.insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
||||
res = db.insert().into("person", {"id", "name", "age"}).values({2, "jane", 45}).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto count = ses.select({count_all()}).from("person").fetch_value<int>();
|
||||
auto count = db.select({count_all()}).from("person").fetch_value<int>();
|
||||
REQUIRE(count == 2);
|
||||
|
||||
res = ses.remove()
|
||||
res = db.remove()
|
||||
.from("person")
|
||||
.where("id"_col == 1)
|
||||
.execute();
|
||||
|
||||
REQUIRE(res == 1);
|
||||
|
||||
count = ses.select({count_all()}).from("person").fetch_value<int>();
|
||||
count = db.select({count_all()}).from("person").fetch_value<int>();
|
||||
REQUIRE(count == 1);
|
||||
|
||||
ses.drop().table("person").execute();
|
||||
db.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionRecordFixture, " Test quoted identifier", "[session][record]") {
|
||||
ses.create()
|
||||
db.create()
|
||||
.table("quotes", {
|
||||
make_column<std::string>("from", 255),
|
||||
make_column<std::string>("to", 255)
|
||||
|
|
@ -371,26 +372,26 @@ TEST_CASE_METHOD(SessionRecordFixture, " Test quoted identifier", "[session][rec
|
|||
// 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");
|
||||
auto fields = db.describe("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();
|
||||
db.insert().into("quotes", {"from", "to"}).values({"Berlin", "London"}).execute();
|
||||
|
||||
auto res = ses.select({"from", "to"}).from("quotes").fetch_one();
|
||||
auto res = db.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();
|
||||
db.update("quotes").set({{"from", "Hamburg"}, {"to", "New York"}}).where("from"_col == "Berlin").execute();
|
||||
|
||||
res = ses.select({"from", "to"}).from("quotes").fetch_one();
|
||||
res = db.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();
|
||||
db.drop().table("quotes").execute();
|
||||
}
|
||||
|
|
@ -13,65 +13,66 @@
|
|||
using namespace matador::sql;
|
||||
using namespace matador::test;
|
||||
|
||||
class SessionFixture
|
||||
class QueryFixture
|
||||
{
|
||||
public:
|
||||
SessionFixture()
|
||||
: pool(matador::test::connection::dns, 4), ses(pool)
|
||||
{}
|
||||
~SessionFixture() {
|
||||
QueryFixture()
|
||||
: db(matador::test::connection::dns)
|
||||
{
|
||||
db.open();
|
||||
}
|
||||
~QueryFixture() {
|
||||
drop_table_if_exists("flight");
|
||||
drop_table_if_exists("airplane");
|
||||
drop_table_if_exists("person");
|
||||
}
|
||||
|
||||
protected:
|
||||
matador::sql::connection_pool<matador::sql::connection> pool;
|
||||
matador::sql::session ses;
|
||||
matador::sql::connection db;
|
||||
|
||||
private:
|
||||
void drop_table_if_exists(const std::string &table_name) {
|
||||
if (ses.table_exists(table_name)) {
|
||||
ses.drop().table(table_name).execute();
|
||||
if (db.exists(table_name)) {
|
||||
db.drop().table(table_name).execute();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, " Create table with foreign key relation", "[session]") {
|
||||
ses.create()
|
||||
TEST_CASE_METHOD(QueryFixture, " Create table with foreign key relation", "[session]") {
|
||||
db.create()
|
||||
.table<airplane>("airplane")
|
||||
.execute();
|
||||
|
||||
REQUIRE(ses.table_exists("airplane"));
|
||||
REQUIRE(db.exists("airplane"));
|
||||
|
||||
ses.create()
|
||||
db.create()
|
||||
.table<flight>("flight")
|
||||
.execute();
|
||||
|
||||
REQUIRE(ses.table_exists("flight"));
|
||||
REQUIRE(db.exists("flight"));
|
||||
|
||||
ses.drop().table("flight").execute();
|
||||
ses.drop().table("airplane").execute();
|
||||
db.drop().table("flight").execute();
|
||||
db.drop().table("airplane").execute();
|
||||
|
||||
REQUIRE(!ses.table_exists("flight"));
|
||||
REQUIRE(!ses.table_exists("airplane"));
|
||||
REQUIRE(!db.exists("flight"));
|
||||
REQUIRE(!db.exists("airplane"));
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, " Execute select statement with where clause", "[session]") {
|
||||
ses.create()
|
||||
TEST_CASE_METHOD(QueryFixture, " Execute select statement with where clause", "[session]") {
|
||||
db.create()
|
||||
.table<person>("person")
|
||||
.execute();
|
||||
|
||||
person george{7, "george", 45};
|
||||
george.image.push_back(37);
|
||||
|
||||
auto res = ses.insert()
|
||||
auto res = db.insert()
|
||||
.into("person", george)
|
||||
.execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
// fetch person as record
|
||||
auto result_record = ses.select<person>()
|
||||
auto result_record = db.select<person>()
|
||||
.from("person")
|
||||
.where("id"_col == 7)
|
||||
.fetch_all();
|
||||
|
|
@ -90,7 +91,7 @@ TEST_CASE_METHOD(SessionFixture, " Execute select statement with where clause",
|
|||
}
|
||||
|
||||
// fetch person as person
|
||||
auto result_person = ses.select<person>()
|
||||
auto result_person = db.select<person>()
|
||||
.from("person")
|
||||
.where("id"_col == 7)
|
||||
.fetch_all<person>();
|
||||
|
|
@ -101,11 +102,11 @@ TEST_CASE_METHOD(SessionFixture, " Execute select statement with where clause",
|
|||
REQUIRE(i.age == 45);
|
||||
}
|
||||
|
||||
ses.drop().table("person").execute();
|
||||
db.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, " Execute insert statement", "[session]") {
|
||||
ses.create()
|
||||
TEST_CASE_METHOD(QueryFixture, " Execute insert statement", "[session]") {
|
||||
db.create()
|
||||
.table("person", {
|
||||
make_pk_column<unsigned long>("id"),
|
||||
make_column<std::string>("name", 255),
|
||||
|
|
@ -113,7 +114,7 @@ TEST_CASE_METHOD(SessionFixture, " Execute insert statement", "[session]") {
|
|||
})
|
||||
.execute();
|
||||
|
||||
auto res = ses.insert()
|
||||
auto res = db.insert()
|
||||
.into("person", {"id", "name", "color"})
|
||||
.values({7, "george", "green"})
|
||||
.execute();
|
||||
|
|
@ -121,7 +122,7 @@ TEST_CASE_METHOD(SessionFixture, " Execute insert statement", "[session]") {
|
|||
REQUIRE(res == 1);
|
||||
|
||||
// fetch person as record
|
||||
auto result_record = ses.select({"id", "name", "color"})
|
||||
auto result_record = db.select({"id", "name", "color"})
|
||||
.from("person")
|
||||
.where("id"_col == 7)
|
||||
.fetch_all();
|
||||
|
|
@ -139,15 +140,15 @@ TEST_CASE_METHOD(SessionFixture, " Execute insert statement", "[session]") {
|
|||
REQUIRE(i.at(2).as<std::string>() == "green");
|
||||
}
|
||||
|
||||
ses.drop().table("person").execute();
|
||||
db.drop().table("person").execute();
|
||||
}
|
||||
|
||||
TEST_CASE_METHOD(SessionFixture, " Select statement with foreign key", "[session]") {
|
||||
ses.create()
|
||||
TEST_CASE_METHOD(QueryFixture, " Select statement with foreign key", "[session]") {
|
||||
db.create()
|
||||
.table<airplane>("airplane")
|
||||
.execute();
|
||||
|
||||
ses.create()
|
||||
db.create()
|
||||
.table<flight>("flight")
|
||||
.execute();
|
||||
|
||||
|
|
@ -158,24 +159,24 @@ TEST_CASE_METHOD(SessionFixture, " Select statement with foreign key", "[session
|
|||
};
|
||||
|
||||
for (const auto &plane : planes) {
|
||||
auto res = ses.insert().into<airplane>("airplane").values(*plane).execute();
|
||||
auto res = db.insert().into<airplane>("airplane").values(*plane).execute();
|
||||
REQUIRE(res == 1);
|
||||
}
|
||||
|
||||
auto count = ses.select({count_all()}).from("airplane").fetch_value<int>();
|
||||
auto count = db.select({count_all()}).from("airplane").fetch_value<int>();
|
||||
REQUIRE(count == 3);
|
||||
|
||||
flight f4711{4, planes.at(1), "hans"};
|
||||
|
||||
auto res = ses.insert().into<flight>("flight").values(f4711).execute();
|
||||
auto res = db.insert().into<flight>("flight").values(f4711).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto f = *ses.select<flight>().from("flight").fetch_all<flight>().begin();
|
||||
auto f = *db.select<flight>().from("flight").fetch_all<flight>().begin();
|
||||
REQUIRE(f.id == 4);
|
||||
REQUIRE(f.pilot_name == "hans");
|
||||
REQUIRE(f.airplane.get() != nullptr);
|
||||
REQUIRE(f.airplane->id == 2);
|
||||
|
||||
ses.drop().table("flight").execute();
|
||||
ses.drop().table("airplane").execute();
|
||||
db.drop().table("flight").execute();
|
||||
db.drop().table("airplane").execute();
|
||||
}
|
||||
|
|
@ -5,18 +5,28 @@
|
|||
#include "matador/sql/session.hpp"
|
||||
#include "matador/sql/statement_cache.hpp"
|
||||
|
||||
#include "connection.hpp"
|
||||
|
||||
using namespace matador;
|
||||
|
||||
TEST_CASE("Acquire prepared statement", "[statement cache]") {
|
||||
sql::statement_cache cache;
|
||||
sql::connection_pool<sql::connection> pool("sqlite://sqlite.db", 4);
|
||||
class StatementCacheFixture
|
||||
{
|
||||
public:
|
||||
StatementCacheFixture()
|
||||
: pool(matador::test::connection::dns, 4), ses(pool)
|
||||
{}
|
||||
~StatementCacheFixture() = default;
|
||||
|
||||
protected:
|
||||
matador::sql::connection_pool<matador::sql::connection> pool;
|
||||
matador::sql::session ses;
|
||||
};
|
||||
|
||||
TEST_CASE_METHOD(StatementCacheFixture, " Acquire prepared statement", "[statement cache]") {
|
||||
sql::statement_cache cache;
|
||||
|
||||
sql::session s(pool);
|
||||
auto conn = pool.acquire();
|
||||
|
||||
std::string sql = R"(SELECT * FROM person WHERE name = 'george')";
|
||||
// auto &stmt = cache.acquire(sql, *conn);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -2,9 +2,7 @@
|
|||
|
||||
#include "matador/sql/column.hpp"
|
||||
#include "matador/sql/condition.hpp"
|
||||
#include "matador/sql/connection_info.hpp"
|
||||
#include "matador/sql/connection_pool.hpp"
|
||||
#include "matador/sql/session.hpp"
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
#include "connection.hpp"
|
||||
|
||||
|
|
@ -17,9 +15,10 @@ class StatementTestFixture
|
|||
{
|
||||
public:
|
||||
StatementTestFixture()
|
||||
: pool(matador::test::connection::dns, 4), ses(pool)
|
||||
: db(matador::test::connection::dns)
|
||||
{
|
||||
ses.create().table<airplane>("airplane").execute();
|
||||
db.open();
|
||||
db.create().table<airplane>("airplane").execute();
|
||||
}
|
||||
|
||||
~StatementTestFixture()
|
||||
|
|
@ -28,8 +27,7 @@ public:
|
|||
}
|
||||
|
||||
protected:
|
||||
matador::sql::connection_pool<matador::sql::connection> pool;
|
||||
matador::sql::session ses;
|
||||
matador::sql::connection db;
|
||||
|
||||
std::vector<entity<airplane>> planes{
|
||||
make_entity<airplane>(1, "Airbus", "A380"),
|
||||
|
|
@ -39,8 +37,8 @@ protected:
|
|||
|
||||
private:
|
||||
void drop_table_if_exists(const std::string &table_name) {
|
||||
if (ses.table_exists(table_name)) {
|
||||
ses.drop().table(table_name).execute();
|
||||
if (db.exists(table_name)) {
|
||||
db.drop().table(table_name).execute();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -49,7 +47,7 @@ private:
|
|||
TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement]")
|
||||
{
|
||||
SECTION("Insert with prepared statement and placeholder") {
|
||||
auto stmt = ses.insert()
|
||||
auto stmt = db.insert()
|
||||
.into<airplane>("airplane")
|
||||
.values<airplane>().prepare();
|
||||
|
||||
|
|
@ -59,7 +57,7 @@ TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement
|
|||
stmt.reset();
|
||||
}
|
||||
|
||||
auto result = ses.select<airplane>().from("airplane").fetch_all<airplane>();
|
||||
auto result = db.select<airplane>().from("airplane").fetch_all<airplane>();
|
||||
|
||||
size_t index{0};
|
||||
for (const auto &i: result) {
|
||||
|
|
@ -71,11 +69,11 @@ TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement
|
|||
|
||||
SECTION("Select with prepared statement") {
|
||||
for (const auto &plane: planes) {
|
||||
auto res = ses.insert().into<airplane>("airplane").values(*plane).execute();
|
||||
auto res = db.insert().into<airplane>("airplane").values(*plane).execute();
|
||||
REQUIRE(res == 1);
|
||||
}
|
||||
|
||||
auto stmt = ses.select<airplane>().from("airplane").where("brand"_col == _).prepare();
|
||||
auto stmt = db.select<airplane>().from("airplane").where("brand"_col == _).prepare();
|
||||
|
||||
stmt.bind(0, "Airbus");
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
#include <catch2/catch_test_macros.hpp>
|
||||
|
||||
#include "matador/sql/session.hpp"
|
||||
#include "matador/sql/connection.hpp"
|
||||
|
||||
#include "matador/utils/enum_mapper.hpp"
|
||||
|
||||
|
|
@ -14,26 +14,26 @@ class TypeTraitsTestFixture
|
|||
{
|
||||
public:
|
||||
TypeTraitsTestFixture()
|
||||
: pool(matador::test::connection::dns, 4), ses(pool)
|
||||
: db(matador::test::connection::dns)
|
||||
{
|
||||
ses.create()
|
||||
db.open();
|
||||
db.create()
|
||||
.table<location>("location")
|
||||
.execute();
|
||||
}
|
||||
|
||||
~TypeTraitsTestFixture()
|
||||
{
|
||||
ses.drop().table("location").execute();
|
||||
db.drop().table("location").execute();
|
||||
}
|
||||
|
||||
protected:
|
||||
matador::sql::connection_pool<matador::sql::connection> pool;
|
||||
matador::sql::session ses;
|
||||
matador::sql::connection db;
|
||||
|
||||
private:
|
||||
void drop_table_if_exists(const std::string &table_name) {
|
||||
if (ses.table_exists(table_name)) {
|
||||
ses.drop().table(table_name).execute();
|
||||
if (db.exists(table_name)) {
|
||||
db.drop().table(table_name).execute();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -85,10 +85,10 @@ TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with typ
|
|||
SECTION("Insert and select with direct execution") {
|
||||
location loc{1, "center", {1, 2, 3}, Color::Black};
|
||||
|
||||
auto res = ses.insert().into<location>("location").values(loc).execute();
|
||||
auto res = db.insert().into<location>("location").values(loc).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto result = ses.select<location>().from("location").fetch_all<location>();
|
||||
auto result = db.select<location>().from("location").fetch_all<location>();
|
||||
|
||||
for (const auto &l: result) {
|
||||
REQUIRE(l.name == "center");
|
||||
|
|
@ -98,11 +98,11 @@ TEST_CASE_METHOD(TypeTraitsTestFixture, "Special handling of attributes with typ
|
|||
SECTION("Insert and select with prepared statement") {
|
||||
location loc{1, "center", {1, 2, 3}, Color::Black};
|
||||
|
||||
auto stmt = ses.insert().into<location>("location").values<location>().prepare();
|
||||
auto stmt = db.insert().into<location>("location").values<location>().prepare();
|
||||
auto res = stmt.bind(loc).execute();
|
||||
REQUIRE(res == 1);
|
||||
|
||||
auto result = ses.select<location>().from("location").
|
||||
auto result = db.select<location>().from("location").
|
||||
template fetch_all<location>();
|
||||
|
||||
for (const auto &l: result) {
|
||||
|
|
|
|||
|
|
@ -4,6 +4,7 @@
|
|||
#include "matador/sql/connection_info.hpp"
|
||||
#include "matador/sql/connection_impl.hpp"
|
||||
#include "matador/sql/dialect.hpp"
|
||||
#include "matador/sql/query_intermediates.hpp"
|
||||
#include "matador/sql/query_context.hpp"
|
||||
#include "matador/sql/query_result.hpp"
|
||||
#include "matador/sql/record.hpp"
|
||||
|
|
@ -18,12 +19,11 @@ namespace matador::sql {
|
|||
class connection
|
||||
{
|
||||
public:
|
||||
explicit connection(connection_info info);
|
||||
explicit connection(const std::string& dns);
|
||||
explicit connection(connection_info info, const std::shared_ptr<table_repository> &repo = std::make_shared<table_repository>());
|
||||
explicit connection(const std::string& dns, const std::shared_ptr<table_repository> &repo = std::make_shared<table_repository>());
|
||||
connection(const connection &x);
|
||||
connection& operator=(const connection &x);
|
||||
connection(connection &&x) noexcept = default;
|
||||
connection& operator=(connection &&x) noexcept = default;
|
||||
~connection();
|
||||
|
||||
void open();
|
||||
|
|
@ -31,22 +31,41 @@ public:
|
|||
[[nodiscard]] bool is_open() const;
|
||||
[[nodiscard]] const connection_info& info() const;
|
||||
|
||||
query_create_intermediate create();
|
||||
query_drop_intermediate drop();
|
||||
template < class Type >
|
||||
query_select_intermediate select();
|
||||
query_select_intermediate select(std::initializer_list<column> columns);
|
||||
query_insert_intermediate insert();
|
||||
query_update_intermediate update(const std::string &table);
|
||||
query_delete_intermediate remove();
|
||||
|
||||
[[nodiscard]] record describe(const std::string &table_name) const;
|
||||
[[nodiscard]] bool exists(const std::string &schema_name, const std::string &table_name) const;
|
||||
[[nodiscard]] bool exists(const std::string &table_name) const;
|
||||
|
||||
query_result<record> fetch(const query_context &q) const;
|
||||
[[nodiscard]] std::unique_ptr<query_result_impl> fetch(const std::string &sql) const;
|
||||
[[nodiscard]] size_t execute(const std::string &sql) const;
|
||||
|
||||
statement prepare(query_context &&query) const;
|
||||
|
||||
const class dialect& dialect() const;
|
||||
std::shared_ptr<table_repository> tables() const;
|
||||
|
||||
private:
|
||||
connection_info connection_info_;
|
||||
std::unique_ptr<connection_impl> connection_;
|
||||
utils::logger logger_;
|
||||
const class dialect &dialect_;
|
||||
std::shared_ptr<table_repository> table_repository_;
|
||||
};
|
||||
|
||||
template<class Type>
|
||||
query_select_intermediate connection::select()
|
||||
{
|
||||
return query_select_intermediate{*this, column_generator::generate<Type>(*table_repository_)};
|
||||
}
|
||||
|
||||
}
|
||||
#endif //QUERY_CONNECTION_HPP
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ public:
|
|||
COLUMNS,
|
||||
COLUMN,
|
||||
FROM,
|
||||
JOIN,
|
||||
ON,
|
||||
INTO,
|
||||
WHERE,
|
||||
WHERE_CLAUSE,
|
||||
|
|
@ -161,6 +163,8 @@ private:
|
|||
{token_t::COLUMNS, "COLUMNS"},
|
||||
{token_t::COLUMN, "COLUMN"},
|
||||
{token_t::FROM, "FROM"},
|
||||
{token_t::JOIN, "INNER JOIN"},
|
||||
{token_t::ON, "ON"},
|
||||
{token_t::WHERE, "WHERE"},
|
||||
{token_t::AND, "AND"},
|
||||
{token_t::OR, "OR"},
|
||||
|
|
|
|||
|
|
@ -19,15 +19,15 @@
|
|||
namespace matador::sql {
|
||||
|
||||
class basic_condition;
|
||||
class session;
|
||||
class connection;
|
||||
|
||||
class query_intermediate
|
||||
{
|
||||
public:
|
||||
query_intermediate(session &db, query_builder &query);
|
||||
query_intermediate(connection &db, query_builder &query);
|
||||
|
||||
protected:
|
||||
session &session_;
|
||||
connection &connection_;
|
||||
query_builder &builder_;
|
||||
};
|
||||
|
||||
|
|
@ -130,17 +130,17 @@ public:
|
|||
class query_start_intermediate
|
||||
{
|
||||
public:
|
||||
explicit query_start_intermediate(session &s);
|
||||
explicit query_start_intermediate(connection &s);
|
||||
|
||||
protected:
|
||||
session &session_;
|
||||
connection &connection_;
|
||||
query_builder builder_;
|
||||
};
|
||||
|
||||
class query_select_intermediate : public query_start_intermediate
|
||||
{
|
||||
public:
|
||||
query_select_intermediate(session &s, const std::vector<column>& columns);
|
||||
query_select_intermediate(connection &s, const std::vector<column>& columns);
|
||||
|
||||
query_from_intermediate from(const std::string &table, const std::string &as = "");
|
||||
};
|
||||
|
|
@ -164,36 +164,38 @@ public:
|
|||
query_execute_finish values()
|
||||
{
|
||||
Type obj;
|
||||
return {session_, builder_.values(as_placeholder(obj))};
|
||||
return {connection_, builder_.values(as_placeholder(obj))};
|
||||
}
|
||||
template<class Type>
|
||||
query_execute_finish values(const Type &obj)
|
||||
{
|
||||
return {session_, builder_.values(value_extractor::extract(obj))};
|
||||
return {connection_, builder_.values(value_extractor::extract(obj))};
|
||||
}
|
||||
};
|
||||
|
||||
class query_create_intermediate : query_start_intermediate
|
||||
class query_create_intermediate : public query_start_intermediate
|
||||
{
|
||||
public:
|
||||
query_create_intermediate(session &s, table_repository &repo);
|
||||
explicit query_create_intermediate(connection &db);
|
||||
|
||||
query_execute_finish table(const std::string &table, std::initializer_list<column> columns);
|
||||
template<class Type>
|
||||
query_execute_finish table(const std::string &table_name)
|
||||
{
|
||||
const auto &info = repository_.attach<Type>(table_name);
|
||||
return {session_, builder_.table(table_name, info.prototype.columns())};
|
||||
if (!tables()->exists<Type>()) {
|
||||
tables()->attach<Type>(table_name);
|
||||
}
|
||||
return {connection_, builder_.table(table_name, column_generator::generate<Type>(*tables()))};
|
||||
}
|
||||
|
||||
private:
|
||||
table_repository &repository_;
|
||||
std::shared_ptr<table_repository> tables() const;
|
||||
};
|
||||
|
||||
class query_drop_intermediate : query_start_intermediate
|
||||
{
|
||||
public:
|
||||
explicit query_drop_intermediate(session &s);
|
||||
explicit query_drop_intermediate(connection &s);
|
||||
|
||||
query_execute_finish table(const std::string &table);
|
||||
};
|
||||
|
|
@ -201,18 +203,18 @@ public:
|
|||
class query_insert_intermediate : public query_start_intermediate
|
||||
{
|
||||
public:
|
||||
explicit query_insert_intermediate(session &s);
|
||||
explicit query_insert_intermediate(connection &s);
|
||||
|
||||
query_into_intermediate into(const std::string &table, std::initializer_list<std::string> column_names);
|
||||
template<class Type>
|
||||
query_into_intermediate into(const std::string &table)
|
||||
{
|
||||
return {session_, builder_.into(table, column_name_generator::generate<Type>())};
|
||||
return {connection_, builder_.into(table, column_name_generator::generate<Type>())};
|
||||
}
|
||||
template<class Type>
|
||||
query_execute_finish into(const std::string &table, const Type &obj)
|
||||
{
|
||||
return {session_, builder_.into(table, column_name_generator::generate<Type>())
|
||||
return {connection_, builder_.into(table, column_name_generator::generate<Type>())
|
||||
.values(value_extractor::extract(obj))};
|
||||
}
|
||||
};
|
||||
|
|
@ -236,13 +238,13 @@ public:
|
|||
class query_update_intermediate : public query_start_intermediate
|
||||
{
|
||||
public:
|
||||
query_update_intermediate(session &s, const std::string& table_name);
|
||||
query_update_intermediate(connection &s, const std::string& table_name);
|
||||
|
||||
query_set_intermediate set(std::initializer_list<key_value_pair> columns);
|
||||
template<class Type>
|
||||
query_set_intermediate set(const Type &obj)
|
||||
{
|
||||
return {session_, builder_.set(key_value_generator::generate(obj))};
|
||||
return {connection_, builder_.set(key_value_generator::generate(obj))};
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -257,7 +259,7 @@ public:
|
|||
class query_delete_intermediate : public query_start_intermediate
|
||||
{
|
||||
public:
|
||||
explicit query_delete_intermediate(session &s);
|
||||
explicit query_delete_intermediate(connection &s);
|
||||
|
||||
query_delete_from_intermediate from(const std::string &table);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -68,6 +68,8 @@ public:
|
|||
[[nodiscard]] bool empty() const;
|
||||
void clear();
|
||||
|
||||
[[nodiscard]] bool unknown() const;
|
||||
|
||||
private:
|
||||
void init();
|
||||
void add_to_map(column &col, size_t index);
|
||||
|
|
|
|||
|
|
@ -20,15 +20,6 @@ class session
|
|||
public:
|
||||
explicit session(connection_pool<connection> &pool);
|
||||
|
||||
query_create_intermediate create();
|
||||
query_drop_intermediate drop();
|
||||
template < class Type >
|
||||
query_select_intermediate select();
|
||||
query_select_intermediate select(std::initializer_list<column> columns);
|
||||
query_insert_intermediate insert();
|
||||
query_update_intermediate update(const std::string &table);
|
||||
query_delete_intermediate remove();
|
||||
|
||||
[[nodiscard]] query_result<record> fetch(const query_context &q) const;
|
||||
// [[nodiscard]] query_result<record> fetch(const std::string &sql) const;
|
||||
[[nodiscard]] size_t execute(const std::string &sql) const;
|
||||
|
|
@ -60,11 +51,5 @@ private:
|
|||
mutable std::unordered_map<std::string, record> prototypes_;
|
||||
};
|
||||
|
||||
template<class Type>
|
||||
query_select_intermediate session::select()
|
||||
{
|
||||
return query_select_intermediate{*this, column_generator::generate<Type>(table_repository_)};
|
||||
}
|
||||
|
||||
}
|
||||
#endif //QUERY_SESSION_HPP
|
||||
|
|
|
|||
|
|
@ -44,11 +44,18 @@ public:
|
|||
|
||||
[[nodiscard]] std::pair<std::string, std::string> reference(const std::type_index &ti) const;
|
||||
|
||||
template<typename Type>
|
||||
[[nodiscard]] bool exists() const
|
||||
{
|
||||
return exists(std::type_index(typeid(Type)));
|
||||
}
|
||||
|
||||
[[nodiscard]] bool exists(const std::type_index &ti) const;
|
||||
|
||||
private:
|
||||
using repository = std::unordered_map<std::type_index, table_info>;
|
||||
repository repository_;
|
||||
};
|
||||
;
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8,16 +8,17 @@
|
|||
|
||||
namespace matador::sql {
|
||||
|
||||
connection::connection(connection_info info)
|
||||
connection::connection(connection_info info, const std::shared_ptr<table_repository> &repo)
|
||||
: connection_info_(std::move(info))
|
||||
, logger_(stdout, "SQL")
|
||||
, dialect_(backend_provider::instance().connection_dialect(info.type))
|
||||
, dialect_(backend_provider::instance().connection_dialect(connection_info_.type))
|
||||
, table_repository_(repo)
|
||||
{
|
||||
connection_.reset(backend_provider::instance().create_connection(connection_info_.type, connection_info_));
|
||||
}
|
||||
|
||||
connection::connection(const std::string& dns)
|
||||
: connection(connection_info::parse(dns))
|
||||
connection::connection(const std::string& dns, const std::shared_ptr<table_repository> &repo)
|
||||
: connection(connection_info::parse(dns), repo)
|
||||
{}
|
||||
|
||||
connection::connection(const connection &x)
|
||||
|
|
@ -68,6 +69,36 @@ const connection_info &connection::info() const
|
|||
return connection_info_;
|
||||
}
|
||||
|
||||
query_create_intermediate connection::create()
|
||||
{
|
||||
return query_create_intermediate(*this);
|
||||
}
|
||||
|
||||
query_drop_intermediate connection::drop()
|
||||
{
|
||||
return query_drop_intermediate{*this};
|
||||
}
|
||||
|
||||
query_select_intermediate connection::select(std::initializer_list<column> columns)
|
||||
{
|
||||
return {*this, columns};
|
||||
}
|
||||
|
||||
query_insert_intermediate connection::insert()
|
||||
{
|
||||
return query_insert_intermediate{*this};
|
||||
}
|
||||
|
||||
query_update_intermediate connection::update(const std::string &table)
|
||||
{
|
||||
return query_update_intermediate{*this, table};
|
||||
}
|
||||
|
||||
query_delete_intermediate connection::remove()
|
||||
{
|
||||
return query_delete_intermediate{*this};
|
||||
}
|
||||
|
||||
record connection::describe(const std::string &table_name) const
|
||||
{
|
||||
return std::move(connection_->describe(table_name));
|
||||
|
|
@ -78,12 +109,41 @@ bool connection::exists(const std::string &schema_name, const std::string &table
|
|||
return connection_->exists(schema_name, table_name);
|
||||
}
|
||||
|
||||
bool connection::exists(const std::string &table_name) const
|
||||
{
|
||||
return connection_->exists(dialect_.default_schema_name(), table_name);
|
||||
}
|
||||
|
||||
size_t connection::execute(const std::string &sql) const
|
||||
{
|
||||
logger_.debug(sql);
|
||||
return connection_->execute(sql);
|
||||
}
|
||||
|
||||
query_result<record> connection::fetch(const query_context &q) const
|
||||
{
|
||||
if (q.prototype.empty() || q.prototype.unknown()) {
|
||||
const auto table_prototype = describe(q.table_name);
|
||||
for (auto &col : q.prototype) {
|
||||
if (const auto rit = table_prototype.find(col.name()); col.type() == data_type_t::type_unknown && rit != table_prototype.end()) {
|
||||
const_cast<column&>(col).type(rit->type());
|
||||
}
|
||||
}
|
||||
}
|
||||
// auto it = prototypes_.find(q.table_name);
|
||||
// if (it == prototypes_.end()) {
|
||||
// it = prototypes_.emplace(q.table_name, describe(q.table_name)).first;
|
||||
// }
|
||||
// // adjust columns from given query
|
||||
// for (auto &col : q.prototype) {
|
||||
// if (const auto rit = it->second.find(col.name()); col.type() == data_type_t::type_unknown && rit != it->second.end()) {
|
||||
// const_cast<column&>(col).type(rit->type());
|
||||
// }
|
||||
// }
|
||||
auto res = fetch(q.sql);
|
||||
return query_result<record>{std::move(res), q.prototype};
|
||||
}
|
||||
|
||||
std::unique_ptr<query_result_impl> connection::fetch(const std::string &sql) const
|
||||
{
|
||||
logger_.debug(sql);
|
||||
|
|
@ -100,4 +160,9 @@ const class dialect &connection::dialect() const
|
|||
return dialect_;
|
||||
}
|
||||
|
||||
std::shared_ptr<table_repository> connection::tables() const
|
||||
{
|
||||
return table_repository_;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,83 +5,83 @@ namespace matador::sql {
|
|||
|
||||
query_result<record> query_select_finish::fetch_all()
|
||||
{
|
||||
return session_.fetch(builder_.compile());
|
||||
return connection_.fetch(builder_.compile());
|
||||
}
|
||||
|
||||
record query_select_finish::fetch_one()
|
||||
{
|
||||
return *session_.fetch(builder_.compile()).begin().get();
|
||||
return *connection_.fetch(builder_.compile()).begin().get();
|
||||
}
|
||||
|
||||
std::unique_ptr<query_result_impl> query_select_finish::fetch()
|
||||
{
|
||||
return session_.fetch(builder_.compile().sql);
|
||||
return connection_.fetch(builder_.compile().sql);
|
||||
}
|
||||
|
||||
statement query_select_finish::prepare()
|
||||
{
|
||||
return session_.prepare(builder_.compile());
|
||||
return connection_.prepare(builder_.compile());
|
||||
}
|
||||
|
||||
query_intermediate::query_intermediate(session &db, query_builder &query)
|
||||
: session_(db), builder_(query) {}
|
||||
query_intermediate::query_intermediate(connection &db, query_builder &query)
|
||||
: connection_(db), builder_(query) {}
|
||||
|
||||
query_offset_intermediate query_order_direction_intermediate::offset(size_t offset)
|
||||
{
|
||||
return {session_, builder_};
|
||||
return {connection_, builder_};
|
||||
}
|
||||
|
||||
query_limit_intermediate query_offset_intermediate::limit(size_t limit)
|
||||
{
|
||||
return {session_, builder_};
|
||||
return {connection_, builder_};
|
||||
}
|
||||
|
||||
query_limit_intermediate query_order_direction_intermediate::limit(size_t limit)
|
||||
{
|
||||
return {session_, builder_};
|
||||
return {connection_, builder_};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_group_by_intermediate::order_by(const std::string &name)
|
||||
{
|
||||
return {session_, builder_.order_by(name)};
|
||||
return {connection_, builder_.order_by(name)};
|
||||
}
|
||||
|
||||
query_order_direction_intermediate query_order_by_intermediate::asc()
|
||||
{
|
||||
return {session_, builder_.asc()};
|
||||
return {connection_, builder_.asc()};
|
||||
}
|
||||
|
||||
query_order_direction_intermediate query_order_by_intermediate::desc()
|
||||
{
|
||||
return {session_, builder_.desc()};
|
||||
return {connection_, builder_.desc()};
|
||||
}
|
||||
|
||||
query_group_by_intermediate query_from_intermediate::group_by(const std::string &name)
|
||||
{
|
||||
return {session_, builder_.group_by(name)};
|
||||
return {connection_, builder_.group_by(name)};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_from_intermediate::order_by(const std::string &name)
|
||||
{
|
||||
return {session_, builder_.order_by(name)};
|
||||
return {connection_, builder_.order_by(name)};
|
||||
}
|
||||
|
||||
query_group_by_intermediate query_where_intermediate::group_by(const std::string &name)
|
||||
{
|
||||
return {session_, builder_.group_by(name)};
|
||||
return {connection_, builder_.group_by(name)};
|
||||
}
|
||||
|
||||
query_order_by_intermediate query_where_intermediate::order_by(const std::string &name)
|
||||
{
|
||||
return {session_, builder_.order_by(name)};
|
||||
return {connection_, builder_.order_by(name)};
|
||||
}
|
||||
|
||||
query_where_intermediate query_from_intermediate::where(const basic_condition &cond)
|
||||
{
|
||||
return query_where_intermediate{session_, builder_.where(cond)};
|
||||
return query_where_intermediate{connection_, builder_.where(cond)};
|
||||
}
|
||||
|
||||
query_select_intermediate::query_select_intermediate(session &s, const std::vector<column>& columns)
|
||||
query_select_intermediate::query_select_intermediate(connection &s, const std::vector<column>& columns)
|
||||
: query_start_intermediate(s)
|
||||
{
|
||||
builder_.select(columns);
|
||||
|
|
@ -89,10 +89,10 @@ query_select_intermediate::query_select_intermediate(session &s, const std::vect
|
|||
|
||||
query_from_intermediate query_select_intermediate::from(const std::string &table, const std::string &as)
|
||||
{
|
||||
return {session_, builder_.from(table, as)};
|
||||
return {connection_, builder_.from(table, as)};
|
||||
}
|
||||
|
||||
query_insert_intermediate::query_insert_intermediate(session &s)
|
||||
query_insert_intermediate::query_insert_intermediate(connection &s)
|
||||
: query_start_intermediate(s)
|
||||
{
|
||||
builder_.insert();
|
||||
|
|
@ -100,36 +100,40 @@ query_insert_intermediate::query_insert_intermediate(session &s)
|
|||
|
||||
query_into_intermediate query_insert_intermediate::into(const std::string &table, std::initializer_list<std::string> column_names)
|
||||
{
|
||||
return {session_, builder_.into(table, column_names)};
|
||||
return {connection_, builder_.into(table, column_names)};
|
||||
}
|
||||
|
||||
size_t query_execute_finish::execute()
|
||||
{
|
||||
return session_.execute(builder_.compile().sql);
|
||||
return connection_.execute(builder_.compile().sql);
|
||||
}
|
||||
|
||||
statement query_execute_finish::prepare()
|
||||
{
|
||||
return session_.prepare(builder_.compile());
|
||||
return connection_.prepare(builder_.compile());
|
||||
}
|
||||
|
||||
query_execute_finish query_into_intermediate::values(std::initializer_list<any_type> values)
|
||||
{
|
||||
return {session_, builder_.values(values)};
|
||||
return {connection_, builder_.values(values)};
|
||||
}
|
||||
|
||||
query_create_intermediate::query_create_intermediate(session &s, table_repository &repo)
|
||||
: query_start_intermediate(s)
|
||||
, repository_(repo) {
|
||||
query_create_intermediate::query_create_intermediate(connection &db)
|
||||
: query_start_intermediate(db) {
|
||||
builder_.create();
|
||||
}
|
||||
|
||||
query_execute_finish query_create_intermediate::table(const std::string &table, std::initializer_list<column> columns)
|
||||
{
|
||||
return {session_, builder_.table(table, columns)};
|
||||
return {connection_, builder_.table(table, columns)};
|
||||
}
|
||||
|
||||
query_drop_intermediate::query_drop_intermediate(session &s)
|
||||
std::shared_ptr<table_repository> query_create_intermediate::tables() const
|
||||
{
|
||||
return connection_.tables();
|
||||
}
|
||||
|
||||
query_drop_intermediate::query_drop_intermediate(connection &s)
|
||||
: query_start_intermediate(s)
|
||||
{
|
||||
builder_.drop();
|
||||
|
|
@ -137,20 +141,20 @@ query_drop_intermediate::query_drop_intermediate(session &s)
|
|||
|
||||
query_execute_finish query_drop_intermediate::table(const std::string &table)
|
||||
{
|
||||
return {session_, builder_.table(table)};
|
||||
return {connection_, builder_.table(table)};
|
||||
}
|
||||
|
||||
query_execute_finish query_execute_where_intermediate::limit(int limit)
|
||||
{
|
||||
return {session_, builder_.limit(limit)};
|
||||
return {connection_, builder_.limit(limit)};
|
||||
}
|
||||
|
||||
query_execute_where_intermediate query_set_intermediate::where(const basic_condition &cond)
|
||||
{
|
||||
return {session_, builder_.where(cond)};
|
||||
return {connection_, builder_.where(cond)};
|
||||
}
|
||||
|
||||
query_update_intermediate::query_update_intermediate(session &s, const std::string& table_name)
|
||||
query_update_intermediate::query_update_intermediate(connection &s, const std::string& table_name)
|
||||
: query_start_intermediate(s)
|
||||
{
|
||||
builder_.update(table_name);
|
||||
|
|
@ -158,15 +162,15 @@ query_update_intermediate::query_update_intermediate(session &s, const std::stri
|
|||
|
||||
query_set_intermediate query_update_intermediate::set(std::initializer_list<key_value_pair> columns)
|
||||
{
|
||||
return {session_, builder_.set(columns)};
|
||||
return {connection_, builder_.set(columns)};
|
||||
}
|
||||
|
||||
query_execute_where_intermediate query_delete_from_intermediate::where(const basic_condition &cond)
|
||||
{
|
||||
return {session_, builder_.where(cond)};
|
||||
return {connection_, builder_.where(cond)};
|
||||
}
|
||||
|
||||
query_delete_intermediate::query_delete_intermediate(session &s)
|
||||
query_delete_intermediate::query_delete_intermediate(connection &s)
|
||||
: query_start_intermediate(s)
|
||||
{
|
||||
builder_.remove();
|
||||
|
|
@ -174,11 +178,11 @@ query_delete_intermediate::query_delete_intermediate(session &s)
|
|||
|
||||
query_delete_from_intermediate query_delete_intermediate::from(const std::string &table)
|
||||
{
|
||||
return {session_, builder_.from(table)};
|
||||
return {connection_, builder_.from(table)};
|
||||
}
|
||||
|
||||
query_start_intermediate::query_start_intermediate(session &s)
|
||||
: session_(s)
|
||||
query_start_intermediate::query_start_intermediate(connection &s)
|
||||
: connection_(s)
|
||||
, builder_(s.dialect())
|
||||
{}
|
||||
}
|
||||
|
|
@ -1,5 +1,6 @@
|
|||
#include "matador/sql/record.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <stdexcept>
|
||||
|
||||
namespace matador::sql {
|
||||
|
|
@ -133,6 +134,13 @@ void record::clear()
|
|||
columns_by_name_.clear();
|
||||
}
|
||||
|
||||
bool record::unknown() const
|
||||
{
|
||||
return std::all_of(std::begin(columns_), std::end(columns_), [](const auto &col) {
|
||||
return col.type() == data_type_t::type_unknown;
|
||||
});
|
||||
}
|
||||
|
||||
void record::init()
|
||||
{
|
||||
size_t index{0};
|
||||
|
|
|
|||
|
|
@ -10,36 +10,6 @@ session::session(connection_pool<connection> &pool)
|
|||
: pool_(pool)
|
||||
, dialect_(backend_provider::instance().connection_dialect(pool_.info().type)) {}
|
||||
|
||||
query_create_intermediate session::create()
|
||||
{
|
||||
return query_create_intermediate{*this, table_repository_};
|
||||
}
|
||||
|
||||
query_drop_intermediate session::drop()
|
||||
{
|
||||
return query_drop_intermediate{*this};
|
||||
}
|
||||
|
||||
query_select_intermediate session::select(std::initializer_list<column> columns)
|
||||
{
|
||||
return {*this, columns};
|
||||
}
|
||||
|
||||
query_insert_intermediate session::insert()
|
||||
{
|
||||
return query_insert_intermediate{*this};
|
||||
}
|
||||
|
||||
query_update_intermediate session::update(const std::string &table)
|
||||
{
|
||||
return query_update_intermediate{*this, table};
|
||||
}
|
||||
|
||||
query_delete_intermediate session::remove()
|
||||
{
|
||||
return query_delete_intermediate{*this};
|
||||
}
|
||||
|
||||
query_result<record> session::fetch(const query_context &q) const
|
||||
{
|
||||
auto c = pool_.acquire();
|
||||
|
|
|
|||
|
|
@ -31,4 +31,9 @@ std::pair<std::string, std::string> table_repository::reference(const std::type_
|
|||
return {};
|
||||
}
|
||||
|
||||
bool table_repository::exists(const std::type_index &ti) const
|
||||
{
|
||||
return repository_.count(ti) > 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -23,7 +23,6 @@ add_executable(tests QueryBuilderTest.cpp
|
|||
models/person.hpp
|
||||
AnyTypeToVisitorTest.cpp
|
||||
ColumnTest.cpp
|
||||
StatementCacheTest.cpp
|
||||
models/coordinate.hpp
|
||||
models/location.hpp
|
||||
models/optional.hpp
|
||||
|
|
|
|||
Loading…
Reference in New Issue