From ba3db4aa7842c8a36257d874e7895c74ae23aadb Mon Sep 17 00:00:00 2001 From: Sascha Kuehl Date: Sun, 5 Nov 2023 19:51:30 +0100 Subject: [PATCH] add missing sql execute statements in connection --- include/matador/sql/connection.hpp | 8 +- .../matador/sql/connection_intermediates.hpp | 165 ++++++++++++++++-- include/matador/sql/key_value_pair.hpp | 4 +- src/sql/connection.cpp | 37 +++- src/sql/connection_intermediates.cpp | 120 +++++++++++-- src/sql/query_builder.cpp | 2 +- test/builder.cpp | 20 +-- test/connection.cpp | 87 ++++++++- 8 files changed, 392 insertions(+), 51 deletions(-) diff --git a/include/matador/sql/connection.hpp b/include/matador/sql/connection.hpp index 110d733..a8d90cb 100644 --- a/include/matador/sql/connection.hpp +++ b/include/matador/sql/connection.hpp @@ -13,9 +13,15 @@ class connection { public: connection(); + query_create_intermediate create(); + query_drop_intermediate drop(); query_select_intermediate select(std::initializer_list column_names); + query_insert_intermediate insert(); + query_update_intermediate update(const std::string &table); + query_delete_intermediate remove(); - result execute(const std::string &sql); + result fetch(const std::string &sql); + std::pair execute(const std::string &sql); private: dialect dialect_; diff --git a/include/matador/sql/connection_intermediates.hpp b/include/matador/sql/connection_intermediates.hpp index 57f22e4..b7e77f7 100644 --- a/include/matador/sql/connection_intermediates.hpp +++ b/include/matador/sql/connection_intermediates.hpp @@ -1,6 +1,8 @@ #ifndef QUERY_CONNECTION_INTERMEDIATES_HPP #define QUERY_CONNECTION_INTERMEDIATES_HPP +#include "matador/sql/column.hpp" +#include "matador/sql/key_value_pair.hpp" #include "matador/sql/result.hpp" #include @@ -11,63 +13,188 @@ class basic_condition; class connection; class query_builder; -struct query_intermediate +class query_intermediate { +public: query_intermediate(connection &db, query_builder &query); - connection &db; - query_builder &query; +protected: + connection& db(); + query_builder& query(); + +private: + connection &db_; + query_builder &query_; }; -struct query_finish : query_intermediate +class query_select_finish : public query_intermediate { +protected: using query_intermediate::query_intermediate; +public: result fetch_all(); result fetch_one(); result fetch_value(); }; -struct query_order_direction_intermediate : query_finish +class query_limit_intermediate : public query_select_finish { - using query_finish::query_finish; +public: + using query_select_finish::query_select_finish; }; -struct query_group_by_intermediate : query_finish -{ - using query_finish::query_finish; - - -}; -struct query_order_by_intermediate : query_intermediate +class query_offset_intermediate : public query_intermediate { +public: using query_intermediate::query_intermediate; + + query_limit_intermediate limit(size_t limit); +}; + +class query_order_direction_intermediate : public query_select_finish +{ +public: + using query_select_finish::query_select_finish; + + query_offset_intermediate offset(size_t offset); + query_limit_intermediate limit(size_t limit); +}; + +class query_order_by_intermediate; + +class query_group_by_intermediate : public query_select_finish +{ +public: + using query_select_finish::query_select_finish; + + query_order_by_intermediate order_by(const std::string &name); +}; + +class query_order_by_intermediate : public query_intermediate +{ +public: + using query_intermediate::query_intermediate; + query_order_direction_intermediate asc(); query_order_direction_intermediate desc(); - }; -struct query_where_intermediate : query_finish +class query_where_intermediate : public query_select_finish { - using query_finish::query_finish; +public: + using query_select_finish::query_select_finish; + + query_group_by_intermediate group_by(const std::string &name); + query_order_by_intermediate order_by(const std::string &name); }; -struct query_from_intermediate : query_finish +class query_from_intermediate : public query_select_finish { - using query_finish::query_finish; +public: + using query_select_finish::query_select_finish; query_where_intermediate where(const basic_condition &cond); query_group_by_intermediate group_by(const std::string &name); query_order_by_intermediate order_by(const std::string &name); }; -struct query_select_intermediate : query_intermediate +class query_select_intermediate : public query_intermediate { +public: using query_intermediate::query_intermediate; query_from_intermediate from(const std::string &table, const std::string &as = ""); }; +class query_execute_finish : public query_intermediate +{ +public: + using query_intermediate::query_intermediate; + + std::pair execute(); +}; + +class query_into_intermediate : public query_intermediate +{ +public: + using query_intermediate::query_intermediate; + + query_execute_finish values(std::initializer_list values); +}; + +class query_create_drop_finish : public query_intermediate +{ +public: + using query_intermediate::query_intermediate; + + void execute(); +}; + +class query_create_intermediate : query_intermediate +{ +public: + using query_intermediate::query_intermediate; + + query_create_drop_finish table(const std::string &table, std::initializer_list columns); +}; + +class query_drop_intermediate : query_intermediate +{ +public: + using query_intermediate::query_intermediate; + + query_create_drop_finish table(const std::string &table); +}; + +class query_insert_intermediate : public query_intermediate +{ +public: + using query_intermediate::query_intermediate; + + query_into_intermediate into(const std::string &table, std::initializer_list column_names); +}; + +class query_execute_where_intermediate : public query_execute_finish +{ +public: + using query_execute_finish::query_execute_finish; + + query_execute_finish limit(int limit); +}; + +class query_set_intermediate : public query_execute_finish +{ +public: + using query_execute_finish::query_execute_finish; + + query_execute_where_intermediate where(const basic_condition &cond); +}; + +class query_update_intermediate : public query_intermediate +{ +public: + using query_intermediate::query_intermediate; + + query_set_intermediate set(std::initializer_list columns); +}; + +class query_delete_from_intermediate : public query_execute_finish +{ +public: + using query_execute_finish::query_execute_finish; + + query_execute_where_intermediate where(const basic_condition &cond); +}; + +class query_delete_intermediate : public query_intermediate +{ +public: + using query_intermediate::query_intermediate; + + query_delete_from_intermediate from(const std::string &table, const std::string &as = ""); +}; + } #endif //QUERY_CONNECTION_INTERMEDIATES_HPP diff --git a/include/matador/sql/key_value_pair.hpp b/include/matador/sql/key_value_pair.hpp index 6d55761..d5222b4 100644 --- a/include/matador/sql/key_value_pair.hpp +++ b/include/matador/sql/key_value_pair.hpp @@ -21,8 +21,8 @@ public: key_value_pair(const std::string &name, any_type value); key_value_pair(const char *name, any_type value); - const std::string& name() const; - const any_type& value() const; + [[nodiscard]] const std::string& name() const; + [[nodiscard]] const any_type& value() const; private: std::string name_; diff --git a/src/sql/connection.cpp b/src/sql/connection.cpp index 4ad4990..fcc5727 100644 --- a/src/sql/connection.cpp +++ b/src/sql/connection.cpp @@ -6,8 +6,43 @@ namespace matador::sql { connection::connection() : query_(dialect_) {} -result connection::execute(const std::string &sql) { +query_create_intermediate connection::create() +{ + return query_create_intermediate{*this, query_.create()}; +} + +query_drop_intermediate connection::drop() +{ + return query_drop_intermediate{*this, query_.drop()}; +} + +query_select_intermediate connection::select(std::initializer_list column_names) +{ + return query_select_intermediate{*this, query_.select(column_names)}; +} + +query_insert_intermediate connection::insert() +{ + return query_insert_intermediate{*this, query_.insert()}; +} + +query_update_intermediate connection::update(const std::string &table) +{ + return query_update_intermediate{*this, query_.update(table)}; +} + +query_delete_intermediate connection::remove() +{ + return query_delete_intermediate{*this, query_.remove()}; +} + +result connection::fetch(const std::string &sql) +{ return {sql}; } +std::pair connection::execute(const std::string &sql) +{ + return {0, sql}; +} } diff --git a/src/sql/connection_intermediates.cpp b/src/sql/connection_intermediates.cpp index cca5ea1..2847144 100644 --- a/src/sql/connection_intermediates.cpp +++ b/src/sql/connection_intermediates.cpp @@ -3,58 +3,146 @@ #include "matador/sql/query_builder.hpp" namespace matador::sql { - -result query_finish::fetch_all() +connection &query_intermediate::db() { - return db.execute(query.compile()); + return db_; } -result query_finish::fetch_one() +query_builder &query_intermediate::query() { - return db.execute(query.compile()); + return query_; } -result query_finish::fetch_value() +result query_select_finish::fetch_all() { - return db.execute(query.compile()); + return db().fetch(query().compile()); +} + +result query_select_finish::fetch_one() +{ + return db().fetch(query().compile()); +} + +result query_select_finish::fetch_value() +{ + return db().fetch(query().compile()); } query_intermediate::query_intermediate(connection &db, query_builder &query) -: db(db), query(query) {} +: db_(db), query_(query) {} + +query_offset_intermediate query_order_direction_intermediate::offset(size_t offset) +{ + return {db(), query()}; +} + +query_limit_intermediate query_offset_intermediate::limit(size_t limit) +{ + return {db(), query()}; +} + +query_limit_intermediate query_order_direction_intermediate::limit(size_t limit) +{ + return {db(), query()}; +} + +query_order_by_intermediate query_group_by_intermediate::order_by(const std::string &name) +{ + return {db(), query().order_by(name)}; +} query_order_direction_intermediate query_order_by_intermediate::asc() { - return {db, query.asc()}; + return {db(), query().asc()}; } query_order_direction_intermediate query_order_by_intermediate::desc() { - return {db, query.desc()}; + return {db(), query().desc()}; } query_group_by_intermediate query_from_intermediate::group_by(const std::string &name) { - return {db, query.group_by(name)}; + return {db(), query().group_by(name)}; } query_order_by_intermediate query_from_intermediate::order_by(const std::string &name) { - return {db, query.order_by(name)}; + return {db(), query().order_by(name)}; +} + +query_group_by_intermediate query_where_intermediate::group_by(const std::string &name) +{ + return {db(), query().group_by(name)}; +} + +query_order_by_intermediate query_where_intermediate::order_by(const std::string &name) +{ + return {db(), query().order_by(name)}; } query_where_intermediate query_from_intermediate::where(const basic_condition &cond) { - return query_where_intermediate{db, query.where(cond)}; + return query_where_intermediate{db(), query().where(cond)}; } query_from_intermediate query_select_intermediate::from(const std::string &table, const std::string &as) { - return {db, query.from(table, as)}; + return {db(), query().from(table, as)}; } -query_select_intermediate connection::select(std::initializer_list column_names) +query_into_intermediate query_insert_intermediate::into(const std::string &table, std::initializer_list column_names) { - return query_select_intermediate{*this, query_.select(column_names)}; + return {db(), query().into(table, column_names)}; } +std::pair query_execute_finish::execute() +{ + return db().execute(query().compile()); +} + +query_execute_finish query_into_intermediate::values(std::initializer_list values) +{ + return {db(), query().values(values)}; +} + +void query_create_drop_finish::execute() +{ + db().execute(query().compile()); +} + +query_create_drop_finish query_create_intermediate::table(const std::string &table, std::initializer_list columns) +{ + return {db(), query().table(table, columns)}; +} + +query_create_drop_finish query_drop_intermediate::table(const std::string &table) +{ + return {db(), query().table(table)}; +} + +query_execute_finish query_execute_where_intermediate::limit(int limit) +{ + return {db(), query().limit(limit)}; +} + +query_execute_where_intermediate query_set_intermediate::where(const basic_condition &cond) +{ + return {db(), query().where(cond)}; +} + +query_set_intermediate query_update_intermediate::set(std::initializer_list columns) +{ + return {db(), query().set(columns)}; +} + +query_execute_where_intermediate query_delete_from_intermediate::where(const basic_condition &cond) +{ + return {db(), query().where(cond)}; +} + +query_delete_from_intermediate query_delete_intermediate::from(const std::string &table, const std::string &as) +{ + return {db(), query().from(table, as)}; +} } \ No newline at end of file diff --git a/src/sql/query_builder.cpp b/src/sql/query_builder.cpp index 42db3e1..549c43f 100644 --- a/src/sql/query_builder.cpp +++ b/src/sql/query_builder.cpp @@ -38,7 +38,7 @@ query_builder::query_state_transition_map query_builder::transitions_{ {state_t::QUERY_WHERE, {state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_FINISH}}, {state_t::QUERY_ORDER_BY, {state_t::QUERY_ORDER_DIRECTION}}, {state_t::QUERY_ORDER_DIRECTION, {state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_FINISH}}, - {state_t::QUERY_GROUP_BY, {state_t::QUERY_FINISH}}, + {state_t::QUERY_GROUP_BY, {state_t::QUERY_ORDER_BY, state_t::QUERY_FINISH}}, {state_t::QUERY_OFFSET, {state_t::QUERY_LIMIT}}, {state_t::QUERY_LIMIT, {state_t::QUERY_FINISH}}, {state_t::QUERY_VALUES, {state_t::QUERY_FINISH}}, diff --git a/test/builder.cpp b/test/builder.cpp index 21a9795..bcfea9f 100644 --- a/test/builder.cpp +++ b/test/builder.cpp @@ -7,7 +7,7 @@ using namespace matador::sql; -TEST_CASE("Create table", "[query]") { +TEST_CASE("Create table sql statement string", "[query]") { dialect d; query_builder query(d); const auto sql = query.create().table("person", { @@ -19,7 +19,7 @@ TEST_CASE("Create table", "[query]") { REQUIRE(sql == R"##(CREATE TABLE "person" ("id" BIGINT NOT NULL PRIMARY KEY, "name" VARCHAR(255), "age" INTEGER))##"); } -TEST_CASE("Drop table", "[query]") { +TEST_CASE("Drop table sql statement string", "[query]") { dialect d; query_builder query(d); const auto sql = query.drop().table("person").compile(); @@ -27,7 +27,7 @@ TEST_CASE("Drop table", "[query]") { REQUIRE(sql == R"(DROP TABLE "person")"); } -TEST_CASE("Select", "[query]") { +TEST_CASE("Select sql statement string", "[query]") { dialect d; query_builder query(d); const auto sql = query.select({"id", "name", "age"}).from("person").compile(); @@ -35,7 +35,7 @@ TEST_CASE("Select", "[query]") { REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person")"); } -TEST_CASE("Insert", "[query]") { +TEST_CASE("Insert sql statement string", "[query]") { dialect d; query_builder query(d); const auto sql = query.insert().into("person", { @@ -45,7 +45,7 @@ TEST_CASE("Insert", "[query]") { REQUIRE(sql == R"(INSERT INTO "person" ("id", "name", "age") VALUES (7, 'george', 65))"); } -TEST_CASE("Update", "[query]") { +TEST_CASE("Update sql statement string", "[query]") { dialect d; query_builder query(d); const auto sql = query.update("person").set({ @@ -57,7 +57,7 @@ TEST_CASE("Update", "[query]") { REQUIRE(sql == R"(UPDATE "person" SET "id"=7, "name"='george', "age"=65)"); } -TEST_CASE("Delete", "[query]") { +TEST_CASE("Delete sql statement string", "[query]") { dialect d; query_builder query(d); const auto sql = query.remove().from("person").compile(); @@ -65,7 +65,7 @@ TEST_CASE("Delete", "[query]") { REQUIRE(sql == R"(DELETE FROM "person")"); } -TEST_CASE("Where", "[query]") { +TEST_CASE("Select sql statement string with where clause", "[query]") { dialect d; query_builder query(d); auto sql = query.select({"id", "name", "age"}) @@ -83,7 +83,7 @@ TEST_CASE("Where", "[query]") { REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" WHERE ("id" = ? AND "age" > 50))"); } -TEST_CASE("OrderBy", "[query]") { +TEST_CASE("Select sql statement string with order by", "[query]") { dialect d; query_builder query(d); const auto sql = query.select({"id", "name", "age"}) @@ -94,7 +94,7 @@ TEST_CASE("OrderBy", "[query]") { REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" ORDER BY "name" ASC)"); } -TEST_CASE("GroupBy", "[query]") { +TEST_CASE("Select sql statement string with group by", "[query]") { dialect d; query_builder query(d); const auto sql = query.select({"id", "name", "age"}) @@ -105,7 +105,7 @@ TEST_CASE("GroupBy", "[query]") { REQUIRE(sql == R"(SELECT "id", "name", "age" FROM "person" GROUP BY "age")"); } -TEST_CASE("Limit", "[query]") { +TEST_CASE("Select sql statement string with offset and limit", "[query]") { dialect d; query_builder query(d); const auto sql = query.select({"id", "name", "age"}) diff --git a/test/connection.cpp b/test/connection.cpp index c7674c2..1f61d50 100644 --- a/test/connection.cpp +++ b/test/connection.cpp @@ -6,7 +6,31 @@ using namespace matador::sql; -TEST_CASE("CSelect", "[connection]") { +TEST_CASE("Execute create table statement", "[connection]") { + connection c; + + c.create() + .table("person", { + make_pk_column("id"), + make_column("name", 255), + make_column("age") + }).execute(); + + REQUIRE(true); +// REQUIRE(res.sql == R"(SELECT "id", "name", "color" FROM "person" WHERE "id" = 8)"); +} + +TEST_CASE("Execute drop table statement", "[connection]") { + connection c; + + c.drop() + .table("person").execute(); + + REQUIRE(true); +// REQUIRE(res.sql == R"(SELECT "id", "name", "color" FROM "person" WHERE "id" = 8)"); +} + +TEST_CASE("Execute select statement with where clause", "[connection]") { connection c; auto res = c.select({"id", "name", "color"}) @@ -15,4 +39,65 @@ TEST_CASE("CSelect", "[connection]") { .fetch_all(); REQUIRE(res.sql == R"(SELECT "id", "name", "color" FROM "person" WHERE "id" = 8)"); +} + +TEST_CASE("Execute select statement with order by", "[connection]") { + connection c; + + auto res = c.select({"id", "name", "color"}) + .from("person") + .where("id"_col == 8) + .order_by("name").desc() + .fetch_all(); + + REQUIRE(res.sql == R"(SELECT "id", "name", "color" FROM "person" WHERE "id" = 8 ORDER BY "name" DESC)"); +} + +TEST_CASE("Execute select statement with group by and order by", "[connection]") { + connection c; + + auto res = c.select({"id", "name", "color"}) + .from("person") + .where("id"_col == 8) + .group_by("color") + .order_by("name").asc() + .fetch_all(); + + REQUIRE(res.sql == R"(SELECT "id", "name", "color" FROM "person" WHERE "id" = 8 GROUP BY "color" ORDER BY "name" ASC)"); +} + +TEST_CASE("Execute insert statement", "[connection]") { + connection c; + + auto res = c.insert() + .into("person", {"id", "name", "color"}) + .values({7, "george", "green"}) + .execute(); + + REQUIRE(res.second == R"(INSERT INTO "person" ("id", "name", "color") VALUES (7, 'george', 'green'))"); +} + +TEST_CASE("Execute update statement", "[connection]") { + connection c; + + auto res = c.update("person") + .set({ + {"name", "george"}, + {"color", "green"} + }) + .where("id"_col == 9) + .execute(); + + REQUIRE(res.second == R"(UPDATE "person" SET "name"='george', "color"='green' WHERE "id" = 9)"); +} + +TEST_CASE("Execute delete statement", "[connection]") { + connection c; + + auto res = c.remove() + .from("person", "p") + .where("id"_col == 9) + .execute(); + + REQUIRE(res.second == R"(DELETE FROM "person" p WHERE "id" = 9)"); } \ No newline at end of file