query-builder: Bind operand to insert clause
authorSangwan Kwon <sangwan.kwon@samsung.com>
Tue, 18 Feb 2020 04:30:19 +0000 (13:30 +0900)
committer권상완/Security 2Lab(SR)/Engineer/삼성전자 <sangwan.kwon@samsung.com>
Tue, 18 Feb 2020 09:14:41 +0000 (18:14 +0900)
ex) AdminTable.insert(Admin::Id = id, Admin::Pkg = "pkg", Admin::Key = "key");
  - Before: "INSERT INTO admin (id, pkg, key) VALUES (?, ?, ?)"
  - Afater: "INSERT INTO admin (id, pkg, key) VALUES (0, 'pkg', 'key')"

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

index e4f4f4aa193d2febcb6648e8b6121c39f206bd39..3a3dcb74f38103b25085c0433310c3897be8529b 100644 (file)
@@ -124,11 +124,10 @@ void PolicyStorage::define(const std::string& policy, const PolicyValue& ivalue)
 
        PolicyDefinition pd = { policy, ivalue.dump() };
 
-       std::string query = schema::PolicyDefinitionTable.insert(PolicyDefinition::Name,
-                                                                                                                        PolicyDefinition::Ivalue);
+       std::string query =
+               schema::PolicyDefinitionTable.insert(PolicyDefinition::Name = pd.name,
+                                                                                        PolicyDefinition::Ivalue = pd.ivalue);
        database::Statement stmt(*database, query);
-       stmt.bind(1, pd.name);
-       stmt.bind(2, pd.ivalue);
        if (!stmt.exec())
                THROW(ErrCode::RuntimeError) << stmt.getErrorMessage();
 
@@ -147,10 +146,9 @@ void PolicyStorage::enroll(const std::string& name)
        /// Make admin deactivated as default.
        Admin admin = {name , 0};
 
-       std::string query = schema::AdminTable.insert(Admin::Name, Admin::Activated);
+       std::string query = schema::AdminTable.insert(Admin::Name = admin.name,
+                                                                                                 Admin::Activated = admin.activated);
        database::Statement stmt(*database, query);
-       stmt.bind(1, admin.name);
-       stmt.bind(2, admin.activated);
        if (!stmt.exec())
                THROW(ErrCode::RuntimeError) << stmt.getErrorMessage();
 
index cfdc2a03df5e513f24b3475f0d31c19390bc170c..3895aca5f0f3be4b43b7b1e36badad9eddfd21f6 100644 (file)
@@ -153,33 +153,46 @@ T& Crud<T>::update(AssginExpressions&&... expression)
 
 template<typename T>
 template<typename... ColumnTypes>
-T& Crud<T>::insert(ColumnTypes&&... cts)
+T& Crud<T>::insert(ColumnTypes&&... expression)
 {
        static_cast<T*>(this)->cache.clear();
 
-       auto columnNames = static_cast<T*>(this)->getColumnNames(std::forward<ColumnTypes>(cts)...);
-
-       std::stringstream ss;
-       ss << "INSERT INTO " << static_cast<T*>(this)->name << " (";
-
-       const int columnCount = columnNames.size();
-       for (int i = 0; i < columnCount; i++) {
-               ss << columnNames[i];
-               if (i < columnCount - 1)
-                       ss << ", ";
+       std::string query;
+       { 
+               std::stringstream ss;
+               ss << "INSERT INTO " << static_cast<T*>(this)->name << " (";
+
+               auto onColumn = [&ss, this](const auto&... iter) {
+                       (static_cast<void>( /// Make fold expression possible
+                               (ss << static_cast<T*>(this)->getColumnName(iter.l) << ", ") /// Column name
+                       ), ...); /// Process fold expression
+               };
+               std::apply(onColumn, std::tuple(expression...));
+
+               /// Remove last ", "
+               query = ss.str();
+               if (query.size() > 2)
+                       query.erase(query.end() - 2, query.end());
        }
 
-       ss << ") VALUES (";
+       query += ") VALUES (";
 
-       for (int i = 0; i < columnCount; i++) {
-               ss << "?";
-               if (i < columnCount - 1)
-                       ss << ", ";
+       {
+               std::stringstream ss;
+               auto onValue = [&ss](const auto&... iter) {
+                       (static_cast<void>((ss << iter.r) << ", "), ...); /// Process fold expression
+               };
+               std::apply(onValue, std::tuple(expression...));
+
+               /// Remove last ", "
+               query += ss.str();
+               if (query.size() > 2)
+                       query.erase(query.end() - 2, query.end());
        }
 
-       ss << ")";
+       query += ")";
 
-       static_cast<T*>(this)->cache.emplace_back(ss.str());
+       static_cast<T*>(this)->cache.emplace_back(std::move(query));
 
        return *(static_cast<T*>(this));
 }
index fccf73ec82a2897ff2491f4ef7afde0f82880b8c..eb6526d5d4e977a3b20db948f639636d5135a0a8 100644 (file)
@@ -60,6 +60,19 @@ struct Binary<L, const char*> : public Expression {
        }
 };
 
+template<typename L>
+struct Binary<L, std::string> : public Expression {
+       L l;
+       std::string r;
+
+       /// Make r to 'r'
+       Binary(L l, std::string r) : l(l), r("'" + r + "'")
+       {
+               using FieldType = typename L::FieldType;
+               type::assert_compare(FieldType(), std::string());
+       }
+};
+
 template<typename L, typename R>
 struct Greater : public Binary<L, R> {
        using Binary<L, R>::Binary;
index c1765bb1e1ea1475c9f82b9a53d76cbfed7ae3c5..c783acc148da6f0193fc2b839129a1147c72fb6a 100644 (file)
@@ -148,11 +148,23 @@ TEST(QueryBuilderTsqbTests, DELETE)
 
 TEST(QueryBuilderTsqbTests, INSERT)
 {
-       std::string insert1 = AdminTable.insert(Admin::Id, Admin::Pkg, Admin::Uid, Admin::Key);
-       std::string insert2 = AdminTable.insert(Admin::Id, Admin::Pkg, Admin::Key);
-
-       EXPECT_EQ(insert1, "INSERT INTO admin (id, pkg, uid, key) VALUES (?, ?, ?, ?)");
-       EXPECT_EQ(insert2, "INSERT INTO admin (id, pkg, key) VALUES (?, ?, ?)");
+       int id = 0;
+       std::string pkg = "pkg";
+       int uid = 1;
+       std::string key = "key";
+
+       std::string insert1 = AdminTable.insert(Admin::Id = id,
+                                                                                       Admin::Pkg = pkg,
+                                                                                       Admin::Uid = uid,
+                                                                                       Admin::Key = key);
+       std::string insert2 = AdminTable.insert(Admin::Id = id,
+                                                                                       Admin::Pkg = pkg,
+                                                                                       Admin::Key = key);
+
+       EXPECT_EQ(insert1, "INSERT INTO admin (id, pkg, uid, key) "
+                                          "VALUES (0, 'pkg', 1, 'key')");
+       EXPECT_EQ(insert2, "INSERT INTO admin (id, pkg, key) "
+                                          "VALUES (0, 'pkg', 'key')");
 }
 
 TEST(QueryBuilderTsqbTests, TYPE_SAFE)