diff --git a/backends/mysql/src/mysql_connection.cpp b/backends/mysql/src/mysql_connection.cpp index f2e4109..e7796b4 100644 --- a/backends/mysql/src/mysql_connection.cpp +++ b/backends/mysql/src/mysql_connection.cpp @@ -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; diff --git a/backends/mysql/test/CMakeLists.txt b/backends/mysql/test/CMakeLists.txt index cb8bcd2..7aa4292 100644 --- a/backends/mysql/test/CMakeLists.txt +++ b/backends/mysql/test/CMakeLists.txt @@ -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) diff --git a/backends/postgres/src/postgres_error.cpp b/backends/postgres/src/postgres_error.cpp index a904aa9..11a93d8 100644 --- a/backends/postgres/src/postgres_error.cpp +++ b/backends/postgres/src/postgres_error.cpp @@ -22,9 +22,12 @@ 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 && - PQresultStatus(res) != PGRES_TUPLES_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; throw std::logic_error(msg.str()); diff --git a/backends/postgres/test/CMakeLists.txt b/backends/postgres/test/CMakeLists.txt index 492ceb6..8e6323d 100644 --- a/backends/postgres/test/CMakeLists.txt +++ b/backends/postgres/test/CMakeLists.txt @@ -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) diff --git a/backends/sqlite/src/sqlite_connection.cpp b/backends/sqlite/src/sqlite_connection.cpp index 83f0584..9ab0612 100644 --- a/backends/sqlite/src/sqlite_connection.cpp +++ b/backends/sqlite/src/sqlite_connection.cpp @@ -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); diff --git a/backends/sqlite/test/CMakeLists.txt b/backends/sqlite/test/CMakeLists.txt index dacc99a..24666b4 100644 --- a/backends/sqlite/test/CMakeLists.txt +++ b/backends/sqlite/test/CMakeLists.txt @@ -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) diff --git a/backends/tests/SessionRecordTest.cpp b/backends/tests/SessionRecordTest.cpp index 8245e08..b88ae47 100644 --- a/backends/tests/SessionRecordTest.cpp +++ b/backends/tests/SessionRecordTest.cpp @@ -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 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("id"), make_column("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("id"), make_column("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("id"), make_fk_column("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("id"), make_column("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() == 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("id"), make_column("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("id"), make_fk_column("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(); + auto count = db.select({count_all()}).from("airplane").fetch_value(); 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("id"), make_column("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() == 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("id"), make_column("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(); 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("id"), make_column("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("id"), make_column("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("id"), make_column("name", 255), make_column("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(); + auto count = db.select({count_all()}).from("person").fetch_value(); 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(); + count = db.select({count_all()}).from("person").fetch_value(); 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("from", 255), make_column("to", 255) @@ -371,26 +372,26 @@ TEST_CASE_METHOD(SessionRecordFixture, " Test quoted identifier", "[session][rec // check table description std::vector columns = { "from", "to"}; std::vector 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(); } \ No newline at end of file diff --git a/backends/tests/SessionTest.cpp b/backends/tests/SessionTest.cpp index a4acbc1..1c20c5e 100644 --- a/backends/tests/SessionTest.cpp +++ b/backends/tests/SessionTest.cpp @@ -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 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") .execute(); - REQUIRE(ses.table_exists("airplane")); + REQUIRE(db.exists("airplane")); - ses.create() + db.create() .table("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") .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() + auto result_record = db.select() .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() + auto result_person = db.select() .from("person") .where("id"_col == 7) .fetch_all(); @@ -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("id"), make_column("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() == "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") .execute(); - ses.create() + db.create() .table("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").values(*plane).execute(); + auto res = db.insert().into("airplane").values(*plane).execute(); REQUIRE(res == 1); } - auto count = ses.select({count_all()}).from("airplane").fetch_value(); + auto count = db.select({count_all()}).from("airplane").fetch_value(); REQUIRE(count == 3); flight f4711{4, planes.at(1), "hans"}; - auto res = ses.insert().into("flight").values(f4711).execute(); + auto res = db.insert().into("flight").values(f4711).execute(); REQUIRE(res == 1); - auto f = *ses.select().from("flight").fetch_all().begin(); + auto f = *db.select().from("flight").fetch_all().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(); } \ No newline at end of file diff --git a/test/StatementCacheTest.cpp b/backends/tests/StatementCacheTest.cpp similarity index 51% rename from test/StatementCacheTest.cpp rename to backends/tests/StatementCacheTest.cpp index daeec46..479e6bb 100644 --- a/test/StatementCacheTest.cpp +++ b/backends/tests/StatementCacheTest.cpp @@ -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 pool("sqlite://sqlite.db", 4); +class StatementCacheFixture +{ +public: + StatementCacheFixture() + : pool(matador::test::connection::dns, 4), ses(pool) + {} + ~StatementCacheFixture() = default; + +protected: + matador::sql::connection_pool 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); - - - } \ No newline at end of file diff --git a/backends/tests/StatementTest.cpp b/backends/tests/StatementTest.cpp index 628b4ac..53f5882 100644 --- a/backends/tests/StatementTest.cpp +++ b/backends/tests/StatementTest.cpp @@ -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").execute(); + db.open(); + db.create().table("airplane").execute(); } ~StatementTestFixture() @@ -28,8 +27,7 @@ public: } protected: - matador::sql::connection_pool pool; - matador::sql::session ses; + matador::sql::connection db; std::vector> planes{ make_entity(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") .values().prepare(); @@ -59,7 +57,7 @@ TEST_CASE_METHOD(StatementTestFixture, " Create prepared statement", "[statement stmt.reset(); } - auto result = ses.select().from("airplane").fetch_all(); + auto result = db.select().from("airplane").fetch_all(); 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").values(*plane).execute(); + auto res = db.insert().into("airplane").values(*plane).execute(); REQUIRE(res == 1); } - auto stmt = ses.select().from("airplane").where("brand"_col == _).prepare(); + auto stmt = db.select().from("airplane").where("brand"_col == _).prepare(); stmt.bind(0, "Airbus"); diff --git a/backends/tests/TypeTraitsTest.cpp b/backends/tests/TypeTraitsTest.cpp index 5ebf633..7b34c36 100644 --- a/backends/tests/TypeTraitsTest.cpp +++ b/backends/tests/TypeTraitsTest.cpp @@ -1,6 +1,6 @@ #include -#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") .execute(); } ~TypeTraitsTestFixture() { - ses.drop().table("location").execute(); + db.drop().table("location").execute(); } protected: - matador::sql::connection_pool 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").values(loc).execute(); + auto res = db.insert().into("location").values(loc).execute(); REQUIRE(res == 1); - auto result = ses.select().from("location").fetch_all(); + auto result = db.select().from("location").fetch_all(); 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").values().prepare(); + auto stmt = db.insert().into("location").values().prepare(); auto res = stmt.bind(loc).execute(); REQUIRE(res == 1); - auto result = ses.select().from("location"). + auto result = db.select().from("location"). template fetch_all(); for (const auto &l: result) { diff --git a/include/matador/sql/connection.hpp b/include/matador/sql/connection.hpp index 885bb6d..f2fdef0 100644 --- a/include/matador/sql/connection.hpp +++ b/include/matador/sql/connection.hpp @@ -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 &repo = std::make_shared()); + explicit connection(const std::string& dns, const std::shared_ptr &repo = std::make_shared()); 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 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 fetch(const query_context &q) const; [[nodiscard]] std::unique_ptr 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 tables() const; private: connection_info connection_info_; std::unique_ptr connection_; utils::logger logger_; const class dialect &dialect_; + std::shared_ptr table_repository_; }; +template +query_select_intermediate connection::select() +{ + return query_select_intermediate{*this, column_generator::generate(*table_repository_)}; +} + } #endif //QUERY_CONNECTION_HPP diff --git a/include/matador/sql/dialect.hpp b/include/matador/sql/dialect.hpp index a69e780..fb4cb61 100644 --- a/include/matador/sql/dialect.hpp +++ b/include/matador/sql/dialect.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"}, diff --git a/include/matador/sql/query_intermediates.hpp b/include/matador/sql/query_intermediates.hpp index c1efc72..e365b1c 100644 --- a/include/matador/sql/query_intermediates.hpp +++ b/include/matador/sql/query_intermediates.hpp @@ -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& columns); + query_select_intermediate(connection &s, const std::vector& 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 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 columns); template query_execute_finish table(const std::string &table_name) { - const auto &info = repository_.attach(table_name); - return {session_, builder_.table(table_name, info.prototype.columns())}; + if (!tables()->exists()) { + tables()->attach(table_name); + } + return {connection_, builder_.table(table_name, column_generator::generate(*tables()))}; } private: - table_repository &repository_; + std::shared_ptr 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 column_names); template query_into_intermediate into(const std::string &table) { - return {session_, builder_.into(table, column_name_generator::generate())}; + return {connection_, builder_.into(table, column_name_generator::generate())}; } template query_execute_finish into(const std::string &table, const Type &obj) { - return {session_, builder_.into(table, column_name_generator::generate()) + return {connection_, builder_.into(table, column_name_generator::generate()) .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 columns); template 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); }; diff --git a/include/matador/sql/record.hpp b/include/matador/sql/record.hpp index 08d148b..38cfc50 100644 --- a/include/matador/sql/record.hpp +++ b/include/matador/sql/record.hpp @@ -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); diff --git a/include/matador/sql/session.hpp b/include/matador/sql/session.hpp index 8400936..4e54976 100644 --- a/include/matador/sql/session.hpp +++ b/include/matador/sql/session.hpp @@ -20,15 +20,6 @@ class session public: explicit session(connection_pool &pool); - query_create_intermediate create(); - query_drop_intermediate drop(); - template < class Type > - query_select_intermediate select(); - query_select_intermediate select(std::initializer_list columns); - query_insert_intermediate insert(); - query_update_intermediate update(const std::string &table); - query_delete_intermediate remove(); - [[nodiscard]] query_result fetch(const query_context &q) const; // [[nodiscard]] query_result fetch(const std::string &sql) const; [[nodiscard]] size_t execute(const std::string &sql) const; @@ -60,11 +51,5 @@ private: mutable std::unordered_map prototypes_; }; -template -query_select_intermediate session::select() -{ - return query_select_intermediate{*this, column_generator::generate(table_repository_)}; -} - } #endif //QUERY_SESSION_HPP diff --git a/include/matador/sql/table_repository.hpp b/include/matador/sql/table_repository.hpp index 32d8771..f4ce580 100644 --- a/include/matador/sql/table_repository.hpp +++ b/include/matador/sql/table_repository.hpp @@ -44,11 +44,18 @@ public: [[nodiscard]] std::pair reference(const std::type_index &ti) const; + template + [[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; repository repository_; }; -; } diff --git a/src/sql/connection.cpp b/src/sql/connection.cpp index b18526b..9f6d83d 100644 --- a/src/sql/connection.cpp +++ b/src/sql/connection.cpp @@ -8,16 +8,17 @@ namespace matador::sql { -connection::connection(connection_info info) +connection::connection(connection_info info, const std::shared_ptr &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 &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 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 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(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(col).type(rit->type()); +// } +// } + auto res = fetch(q.sql); + return query_result{std::move(res), q.prototype}; +} + std::unique_ptr 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 connection::tables() const +{ + return table_repository_; +} + } diff --git a/src/sql/query_intermediates.cpp b/src/sql/query_intermediates.cpp index cf0bb8c..6bad0d2 100644 --- a/src/sql/query_intermediates.cpp +++ b/src/sql/query_intermediates.cpp @@ -5,83 +5,83 @@ namespace matador::sql { query_result 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_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& columns) +query_select_intermediate::query_select_intermediate(connection &s, const std::vector& 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 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 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 columns) { - return {session_, builder_.table(table, columns)}; + return {connection_, builder_.table(table, columns)}; } -query_drop_intermediate::query_drop_intermediate(session &s) +std::shared_ptr 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 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()) {} } \ No newline at end of file diff --git a/src/sql/record.cpp b/src/sql/record.cpp index 867807c..1b934cd 100644 --- a/src/sql/record.cpp +++ b/src/sql/record.cpp @@ -1,5 +1,6 @@ #include "matador/sql/record.hpp" +#include #include 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}; diff --git a/src/sql/session.cpp b/src/sql/session.cpp index 37f4edb..d9b9366 100644 --- a/src/sql/session.cpp +++ b/src/sql/session.cpp @@ -10,36 +10,6 @@ session::session(connection_pool &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 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 session::fetch(const query_context &q) const { auto c = pool_.acquire(); diff --git a/src/sql/table_repository.cpp b/src/sql/table_repository.cpp index af6e4c1..6ba2432 100644 --- a/src/sql/table_repository.cpp +++ b/src/sql/table_repository.cpp @@ -31,4 +31,9 @@ std::pair table_repository::reference(const std::type_ return {}; } +bool table_repository::exists(const std::type_index &ti) const +{ + return repository_.count(ti) > 0; +} + } \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index bfda9e8..ba093c0 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -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