query-builder: Bind operand to update clause
authorSangwan Kwon <sangwan.kwon@samsung.com>
Tue, 18 Feb 2020 03:42:47 +0000 (12:42 +0900)
committer권상완/Security 2Lab(SR)/Engineer/삼성전자 <sangwan.kwon@samsung.com>
Tue, 18 Feb 2020 09:14:41 +0000 (18:14 +0900)
ex) AdminTable.update(Admin::Id = id, Admin::Pkg = "pkg");
  - Before: "UPDATE admin SET id = ?, pkg = ?"
  - After: "UPDATE admin SET id = 1, pkg = 'pkg'"

Signed-off-by: Sangwan Kwon <sangwan.kwon@samsung.com>
src/vist/policy/policy-storage.cpp
src/vist/query-builder/column.hpp
src/vist/query-builder/crud.hpp
src/vist/query-builder/expression.hpp
src/vist/query-builder/tests/query-builder.cpp

index 6fe7a7cf4c9b9f5d5428d017c87ca52d0ed0a434..e4f4f4aa193d2febcb6648e8b6121c39f206bd39 100644 (file)
@@ -193,12 +193,9 @@ void PolicyStorage::activate(const std::string& admin, bool state)
                THROW(ErrCode::LogicError) << "Not exist admin: " << admin;
 
        DEBUG(VIST) << "Activate admin: " << admin;
-       /// Admin::Activated
-       std::string query = schema::AdminTable.update(Admin::Activated)
+       std::string query = schema::AdminTable.update(Admin::Activated = static_cast<int>(state))
                                                                                  .where(Admin::Name == admin);
        database::Statement stmt(*this->database, query);
-       stmt.bind(1, static_cast<int>(state));
-       stmt.bind(2, admin);
        if (!stmt.exec())
                THROW(ErrCode::RuntimeError) << stmt.getErrorMessage();
 
@@ -236,13 +233,10 @@ void PolicyStorage::update(const std::string& admin,
        if (this->definitions.find(policy) == this->definitions.end())
                THROW(ErrCode::LogicError) << "Not exist policy: " << policy;
 
-       std::string query = schema::PolicyManagedTable.update(PolicyManaged::Value)
+       std::string query = schema::PolicyManagedTable.update(PolicyManaged::Value = value.dump())
                                                                                                  .where(PolicyManaged::Admin == admin &&
                                                                                                                 PolicyManaged::Policy == policy);
        database::Statement stmt(*this->database, query);
-       stmt.bind(1, value.dump());
-       stmt.bind(2, admin);
-       stmt.bind(3, policy);
        if (!stmt.exec())
                THROW(ErrCode::RuntimeError) << stmt.getErrorMessage();
 
index b37b5140e50795dfe279fce13e2ec7296d050141..bb3c8771c42079094d39c67fb782ae578699a472 100644 (file)
@@ -37,6 +37,8 @@ struct Column final {
        std::string name;
        Type type;
 
+       template<typename Value>
+       Assign<Column<Object, Field>, Value> operator=(Value value) const;
        template<typename Value>
        Equal<Column<Object, Field>, Value> operator==(Value value) const;
        template<typename Value>
@@ -45,6 +47,13 @@ struct Column final {
        Lesser<Column<Object, Field>, Value> operator<(Value value) const;
 };
 
+template<typename Object, typename Field>
+template<typename Value>
+Assign<Column<Object, Field>, Value> Column<Object, Field>::operator=(Value value) const
+{
+       return {*this, value};
+}
+
 template<typename Object, typename Field>
 template<typename Value>
 Equal<Column<Object, Field>, Value> Column<Object, Field>::operator==(Value value) const
index 616fe0332938ff46a7e477d3b97f459ef6abe450..cfdc2a03df5e513f24b3475f0d31c19390bc170c 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <string>
 #include <sstream>
+#include <tuple>
 
 namespace vist {
 namespace tsqb {
@@ -36,8 +37,8 @@ public:
 
        T& selectAll(void);
 
-       template<typename... ColumnTypes>
-       T& update(ColumnTypes&&... cts);
+       template<typename... AssginExpressions>
+       T& update(AssginExpressions&&... expression);
 
        template<typename... ColumnTypes>
        T& insert(ColumnTypes&&... cts);
@@ -123,26 +124,29 @@ T& Crud<T>::selectAll(void)
 }
 
 template<typename T>
-template<typename... ColumnTypes>
-T& Crud<T>::update(ColumnTypes&&... cts)
+template<typename... AssginExpressions>
+T& Crud<T>::update(AssginExpressions&&... expression)
 {
        static_cast<T*>(this)->cache.clear();
 
-       auto columnNames = static_cast<T*>(this)->getColumnNames(std::forward<ColumnTypes>(cts)...);
-
        std::stringstream ss;
        ss << "UPDATE " << static_cast<T*>(this)->name << " ";
        ss << "SET ";
 
-       unsigned int i = 0;
-       for (const auto& c : columnNames) {
-               ss << c << " = ?";
+       auto closure = [&ss, this](const auto&... iter) {
+               (static_cast<void>( /// Make fold expression possible
+                       (ss << static_cast<T*>(this)->getColumnName(iter.l) /// Column name
+                               << " " << static_cast<std::string>(iter) << " " /// Assign operator
+                               << iter.r << ", ") /// Value
+               ), ...); /// Process fold expression
+       };
+       std::apply(closure, std::tuple(expression...));
 
-               if (i++ < columnNames.size() - 1)
-                       ss << ", ";
-       }
+       std::string raw = ss.str();
+       if (raw.size() > 2)
+               raw.erase(raw.end() - 2, raw.end()); /// Remove last ", "
 
-       static_cast<T*>(this)->cache.emplace_back(ss.str());
+       static_cast<T*>(this)->cache.emplace_back(std::move(raw));
 
        return *(static_cast<T*>(this));
 }
index a88c4b8a77a2424ccb5a25dbeb3ca2b39fecb9b1..fccf73ec82a2897ff2491f4ef7afde0f82880b8c 100644 (file)
@@ -80,6 +80,16 @@ struct Lesser : public Binary<L, R> {
        }
 };
 
+template<typename L, typename R>
+struct Assign : public Binary<L, R> {
+       using Binary<L, R>::Binary;
+
+       operator std::string() const
+       {
+               return "=";
+       }
+};
+
 template<typename L, typename R>
 struct Equal : public Binary<L, R> {
        using Binary<L, R>::Binary;
index 41f016adfd1f78f532f1234b8d02c893a179a86f..c1765bb1e1ea1475c9f82b9a53d76cbfed7ae3c5 100644 (file)
@@ -124,15 +124,16 @@ TEST(QueryBuilderTsqbTests, SELECT_WHERE)
 TEST(QueryBuilderTsqbTests, UPDATE)
 {
        int uid = 0, id = 1;
-       std::string update1 = admin.update(Admin::Id, Admin::Pkg, Admin::Uid, Admin::Key);
-       std::string update2 = admin.update(Admin::Key).where((Admin::Uid == uid) &&
-                                                                                                                (Admin::Id == id));
-       std::string update3 = admin.update(Admin::Key, Admin::Pkg)
+       std::string update1 = admin.update(Admin::Id = id, Admin::Pkg = "pkg",
+                                                                          Admin::Uid = uid, Admin::Key = "key");
+       std::string update2 = admin.update(Admin::Key = "key").where((Admin::Uid == uid) &&
+                                                                                                                                (Admin::Id == id));
+       std::string update3 = admin.update(Admin::Key = "key", Admin::Pkg = "pkg")
                                                           .where((Admin::Uid == 0) && (Admin::Id == 1));
 
-       EXPECT_EQ(update1, "UPDATE admin SET id = ?, pkg = ?, uid = ?, key = ?");
-       EXPECT_EQ(update2, "UPDATE admin SET key = ? WHERE uid = 0 AND id = 1");
-       EXPECT_EQ(update3, "UPDATE admin SET key = ?, pkg = ? WHERE uid = 0 AND id = 1");
+       EXPECT_EQ(update1, "UPDATE admin SET id = 1, pkg = 'pkg', uid = 0, key = 'key'");
+       EXPECT_EQ(update2, "UPDATE admin SET key = 'key' WHERE uid = 0 AND id = 1");
+       EXPECT_EQ(update3, "UPDATE admin SET key = 'key', pkg = 'pkg' WHERE uid = 0 AND id = 1");
 }
 
 TEST(QueryBuilderTsqbTests, DELETE)