From f13837e515692fc646b9169ce513da2ca59dfaa5 Mon Sep 17 00:00:00 2001 From: Sascha Kuehl Date: Thu, 1 Feb 2024 17:15:26 +0100 Subject: [PATCH] implemented query_builder::join and query_builder::on and added a test --- include/matador/sql/query_builder.hpp | 4 +++- src/sql/query_builder.cpp | 31 ++++++++++++++++++++------- test/QueryBuilderTest.cpp | 10 +++++++++ 3 files changed, 36 insertions(+), 9 deletions(-) diff --git a/include/matador/sql/query_builder.hpp b/include/matador/sql/query_builder.hpp index 39a1e14..dd2d463 100644 --- a/include/matador/sql/query_builder.hpp +++ b/include/matador/sql/query_builder.hpp @@ -80,6 +80,8 @@ private: QUERY_DELETE, QUERY_SET, QUERY_FROM, + QUERY_JOIN, + QUERY_ON, QUERY_INTO, QUERY_WHERE, QUERY_VALUES, @@ -129,7 +131,7 @@ public: query_builder& values(std::initializer_list values); query_builder& values(const std::vector &values); query_builder& from(const std::string &table, const std::string &as = ""); - query_builder& join(const std::string &table, join_type_t); + query_builder& join(const std::string &table, join_type_t, const std::string &as = ""); query_builder& on(const std::string &column, const std::string &join_column); query_builder& set(std::initializer_list key_values); query_builder& set(const std::vector &key_values); diff --git a/src/sql/query_builder.cpp b/src/sql/query_builder.cpp index 65bc2f0..d9de6db 100644 --- a/src/sql/query_builder.cpp +++ b/src/sql/query_builder.cpp @@ -10,7 +10,8 @@ namespace matador::sql { namespace detail { any_type_to_string_visitor::any_type_to_string_visitor(const dialect &d, query_context &query) -: d(d), query(query) {} +: d(d), query(query) +{} void any_type_to_string_visitor::to_string(const char *val) { @@ -52,8 +53,10 @@ query_builder::query_state_transition_map query_builder::transitions_{ {state_t::QUERY_DELETE, {state_t::QUERY_FROM}}, {state_t::QUERY_TABLE_CREATE, {state_t::QUERY_FINISH}}, {state_t::QUERY_TABLE_DROP, {state_t::QUERY_FINISH}}, -{state_t::QUERY_FROM, {state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_WHERE, state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_FINISH}}, +{state_t::QUERY_FROM, {state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_WHERE, state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_JOIN, state_t::QUERY_FINISH}}, {state_t::QUERY_SET, {state_t::QUERY_WHERE, state_t::QUERY_FINISH}}, +{state_t::QUERY_JOIN, {state_t::QUERY_ON}}, +{state_t::QUERY_ON, {state_t::QUERY_OFFSET, state_t::QUERY_LIMIT, state_t::QUERY_WHERE, state_t::QUERY_ORDER_BY, state_t::QUERY_GROUP_BY, state_t::QUERY_JOIN, state_t::QUERY_FINISH}}, {state_t::QUERY_INTO, {state_t::QUERY_VALUES}}, {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}}, @@ -324,26 +327,38 @@ query_builder &query_builder::from(const std::string &table, const std::string & if (dialect_.default_schema_name().empty()) { query_parts_.emplace_back(dialect::token_t::FROM, " " + dialect_.token_at(dialect::token_t::FROM) + - " " + dialect_.prepare_identifier(table) + - (as.empty() ? "" : " " + as)); + " " + dialect_.prepare_identifier(table) + + (as.empty() ? "" : " AS " + dialect_.prepare_identifier(as))); } else { query_parts_.emplace_back(dialect::token_t::FROM, " " + dialect_.token_at(dialect::token_t::FROM) + - " " + dialect_.prepare_identifier(dialect_.default_schema_name()) + - "." + dialect_.prepare_identifier(table) + - (as.empty() ? "" : " " + as)); + " " + dialect_.prepare_identifier(dialect_.default_schema_name()) + + "." + dialect_.prepare_identifier(table) + + (as.empty() ? "" : " AS " + dialect_.prepare_identifier(as))); } query_.table_name = table; return *this; } -query_builder &query_builder::join(const std::string &table, join_type_t) +query_builder &query_builder::join(const std::string &table, join_type_t, const std::string &as) { + transition_to(state_t::QUERY_JOIN); + + query_parts_.emplace_back(dialect::token_t::JOIN, " " + dialect_.token_at(dialect::token_t::JOIN) + + " " + dialect_.prepare_identifier(table) + + (as.empty() ? "" : " AS " + dialect_.prepare_identifier(as))); + return *this; } query_builder &query_builder::on(const std::string &column, const std::string &join_column) { + transition_to(state_t::QUERY_ON); + + query_parts_.emplace_back(dialect::token_t::ON, " " + dialect_.token_at(dialect::token_t::ON) + + " " + dialect_.prepare_identifier(column) + + "=" + dialect_.prepare_identifier(join_column)); + return *this; } diff --git a/test/QueryBuilderTest.cpp b/test/QueryBuilderTest.cpp index 4b3158c..f90ee1d 100644 --- a/test/QueryBuilderTest.cpp +++ b/test/QueryBuilderTest.cpp @@ -174,4 +174,14 @@ TEST_CASE("Create, insert and select a blob column", "[query][blob]") { REQUIRE(q.sql == R"(SELECT "id", "name", "data" FROM "person")"); REQUIRE(q.table_name == "person"); +} + +TEST_CASE("Select statement with join", "[query][join]") { + dialect d = dialect_builder::builder().create().build(); + query_builder query(d); + + auto q = query.select({"f.id", "ap.brand", "f.pilot_name"}).from("flight", "f").join("airplane", join_type_t::INNER, "ap").on("f.airplane_id", "ap.id").compile(); + + REQUIRE(q.sql == R"(SELECT "f.id", "ap.brand", "f.pilot_name" FROM "flight" AS "f" INNER JOIN "airplane" AS "ap" ON "f.airplane_id"="ap.id")"); + REQUIRE(q.table_name == "flight"); } \ No newline at end of file