From 2f586daf18e4d3b15e1b96576d85f7090163bb2d Mon Sep 17 00:00:00 2001 From: "sangwan.kwon" Date: Tue, 16 Jan 2018 16:22:42 +0900 Subject: [PATCH] Support DISTINCT constraint on select clause Change-Id: I562cd17bf2b6a1f8be7f66ce0678214735224c6b Signed-off-by: sangwan.kwon --- include/klay/db/query-builder/column.hxx | 11 ++++++++ include/klay/db/query-builder/table.hxx | 28 +++++++++++++++++++-- include/klay/db/query-builder/test-main.cpp | 3 +++ 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/include/klay/db/query-builder/column.hxx b/include/klay/db/query-builder/column.hxx index d24ae73..0a58869 100644 --- a/include/klay/db/query-builder/column.hxx +++ b/include/klay/db/query-builder/column.hxx @@ -18,4 +18,15 @@ Column make_column(const std::string& name, F O::*field) { return {name, field}; } +template +struct Distinct { + Type value; +}; + +template +auto distinct(Args&&... args) -> decltype(Distinct>()) +{ + return {std::make_tuple(std::forward(args)...)}; +} + } // namespace qxx diff --git a/include/klay/db/query-builder/table.hxx b/include/klay/db/query-builder/table.hxx index 8e2829e..cc81ef4 100644 --- a/include/klay/db/query-builder/table.hxx +++ b/include/klay/db/query-builder/table.hxx @@ -20,6 +20,9 @@ public: template Self select(ColumnTypes&&... cts); + template + Self select(Distinct distinct); + Self selectAll(void); template @@ -44,6 +47,9 @@ private: template friend Table make_table(const std::string& name, Cs&& ...columns); + template + Self selectInternal(ColumnTuple&& ct, bool distinct = false); + template std::vector getColumnNames(Cs&& tuple); @@ -97,15 +103,33 @@ Table::Table(const std::string& name, ImplType impl) template template Table Table::select(ColumnTypes&&... cts) +{ + auto columnTuple = std::make_tuple(std::forward(cts)...); + + return this->selectInternal(std::move(columnTuple)); +} + +template +template +Table Table::select(Distinct distinct) +{ + return this->selectInternal(std::move(distinct.value), true); +} + +template +template +Table Table::selectInternal(ColumnTuple&& ct, bool distinct) { this->cache.clear(); - auto columnTuple = std::make_tuple(std::forward(cts)...); - auto columnNames = this->getColumnNames(std::move(columnTuple)); + auto columnNames = this->getColumnNames(std::move(ct)); std::stringstream ss; ss << "SELECT "; + if (distinct) + ss << "DISTINCT "; + for (const auto& c : columnNames) ss << c << " "; diff --git a/include/klay/db/query-builder/test-main.cpp b/include/klay/db/query-builder/test-main.cpp index b6842e7..ee13df2 100644 --- a/include/klay/db/query-builder/test-main.cpp +++ b/include/klay/db/query-builder/test-main.cpp @@ -30,6 +30,8 @@ int main() { expr(&Admin::pkg) == "dpm"); std::string select6 = admin.selectAll().where(expr(&Admin::uid) > 3 || expr(&Admin::pkg) == "dpm"); + std::string select7 = admin.select(distinct(&Admin::uid, &Admin::key)) + .where(expr(&Admin::id) > 3); std::cout << select1 << '\n'; // SELECT id pkg uid key FROM admin std::cout << select2 << '\n'; // SELECT id uid key FROM admin @@ -37,6 +39,7 @@ int main() { std::cout << select4 << '\n'; // SELECT * FROM admin WHERE uid = ? std::cout << select5 << '\n'; // SELECT * FROM admin WHERE uid = ? AND pkg = ? std::cout << select6 << '\n'; // SELECT * FROM admin WHERE uid = ? OR pkg = ? + std::cout << select7 << '\n'; // SELECT DISTINCT uid key FROM admin WHERE id = ? int uid = 0, id = 1; std::string update1 = admin.update(&Admin::id, &Admin::pkg, &Admin::uid, &Admin::key); -- 2.34.1