Support DISTINCT constraint on select clause 11/167211/2
authorsangwan.kwon <sangwan.kwon@samsung.com>
Tue, 16 Jan 2018 07:22:42 +0000 (16:22 +0900)
committersangwan kwon <sangwan.kwon@samsung.com>
Thu, 18 Jan 2018 07:37:28 +0000 (07:37 +0000)
Change-Id: I562cd17bf2b6a1f8be7f66ce0678214735224c6b
Signed-off-by: sangwan.kwon <sangwan.kwon@samsung.com>
include/klay/db/query-builder/column.hxx
include/klay/db/query-builder/table.hxx
include/klay/db/query-builder/test-main.cpp

index d24ae736fa85e35e6197caeaa31c912adedef104..0a58869f379bad29653bb174d8e334caea8cd0b0 100644 (file)
@@ -18,4 +18,15 @@ Column<O, F> make_column(const std::string& name, F O::*field) {
        return {name, field};
 }
 
+template<typename Type>
+struct Distinct {
+       Type value;
+};
+
+template<typename... Args>
+auto distinct(Args&&... args) -> decltype(Distinct<std::tuple<Args...>>())
+{
+       return {std::make_tuple(std::forward<Args>(args)...)};
+}
+
 } // namespace qxx
index 8e2829e71c2eae5e84795a0e8fec4e3cec264d18..cc81ef49bb655f0184411c45859c97804857252c 100644 (file)
@@ -20,6 +20,9 @@ public:
        template<typename... ColumnTypes>
        Self select(ColumnTypes&&... cts);
 
+       template<typename Type>
+       Self select(Distinct<Type> distinct);
+
        Self selectAll(void);
 
        template<typename... ColumnTypes>
@@ -44,6 +47,9 @@ private:
        template<typename ...Cs>
        friend Table<Cs...> make_table(const std::string& name, Cs&& ...columns);
 
+       template<typename ColumnTuple>
+       Self selectInternal(ColumnTuple&& ct, bool distinct = false);
+
        template<typename Cs>
        std::vector<std::string> getColumnNames(Cs&& tuple);
 
@@ -97,15 +103,33 @@ Table<Columns...>::Table(const std::string& name, ImplType impl)
 template<typename... Columns>
 template<typename... ColumnTypes>
 Table<Columns...> Table<Columns...>::select(ColumnTypes&&... cts)
+{
+       auto columnTuple = std::make_tuple(std::forward<ColumnTypes>(cts)...);
+
+       return this->selectInternal(std::move(columnTuple));
+}
+
+template<typename... Columns>
+template<typename Type>
+Table<Columns...> Table<Columns...>::select(Distinct<Type> distinct)
+{
+       return this->selectInternal(std::move(distinct.value), true);
+}
+
+template<typename... Columns>
+template<typename ColumnTuple>
+Table<Columns...> Table<Columns...>::selectInternal(ColumnTuple&& ct, bool distinct)
 {
        this->cache.clear();
 
-       auto columnTuple = std::make_tuple(std::forward<ColumnTypes>(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 << " ";
 
index b6842e74a65bad8ffe6a16c42aa88b632eb84500..ee13df2598142e814da9f58fb34f1dd2fc36031f 100644 (file)
@@ -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);