Fix a bug 80/285480/1
authorjh9216.park <jh9216.park@samsung.com>
Tue, 13 Dec 2022 10:15:29 +0000 (05:15 -0500)
committerjh9216.park <jh9216.park@samsung.com>
Tue, 13 Dec 2022 10:15:29 +0000 (05:15 -0500)
- In case of SQLITE_DONE, class 'Result' should be considered to handle
empty selection

Change-Id: Id58595a9ab464d998221286d7e58fca36f2960e4
Signed-off-by: jh9216.park <jh9216.park@samsung.com>
tests/tizen-database_unittests/src/test_database.cc
tizen-database/database.hpp

index 36421c0e52a179c5a430944c8c1577f6b61723ca..a58276723c0b166075ed996e5467e8032673d3ef 100644 (file)
@@ -266,6 +266,7 @@ TEST_F(DatabaseTest, test_select) {
   auto r = db.Exec({ Q_SELECT });
 
   EXPECT_TRUE(static_cast<bool>(r));
+  int cnt = 0;
   for (const auto& i : r) {
     auto [name, num, val, data] = i.Get<_, _, _, _>();
     EXPECT_EQ(static_cast<std::string>(name), "gogo");
@@ -277,7 +278,10 @@ TEST_F(DatabaseTest, test_select) {
     EXPECT_EQ(v[1], '2');
     EXPECT_EQ(v[2], '1');
     EXPECT_EQ(v[3], '6');
+    cnt++;
   }
+
+  EXPECT_EQ(cnt, 2);
 }
 
 TEST_F(DatabaseTest, test_select2) {
@@ -312,6 +316,21 @@ TEST_F(DatabaseTest, test_select3) {
   }
 }
 
+TEST_F(DatabaseTest, test_select4) {
+  using tizen_base::_;
+  tizen_base::Database db(TEST_DB, SQLITE_OPEN_READWRITE);
+  auto r = db.Exec({ Q_SELECT });
+
+  int cnt = 0;
+  EXPECT_TRUE(static_cast<bool>(r));
+  for (const auto& i : r) {
+    (void)i;
+    cnt++;
+  }
+
+  EXPECT_EQ(cnt, 0);
+}
+
 TEST_F(DatabaseTest, test_ToVector) {
   SetDefault();
 
index 32140b0ed2f344b60a4b6cb64f68f4e1013110c1..971425103bcf697a1eb2e78a6179ac1cfffae648 100644 (file)
@@ -348,6 +348,8 @@ class Database {
     Result(Result&& r) noexcept {
       stmt_ = r.stmt_;
       r.stmt_ = nullptr;
+      query_ = std::move(r.query_);
+      is_done_ = r.is_done_;
     }
 
     Result& operator = (Result&& r) noexcept {
@@ -356,6 +358,8 @@ class Database {
           sqlite3_finalize(stmt_);
         stmt_ = r.stmt_;
         r.stmt_ = nullptr;
+        query_ = std::move(r.query_);
+        is_done_ = r.is_done_;
       }
 
       return *this;
@@ -432,6 +436,8 @@ class Database {
     };
 
     Iterator begin() const {
+      if (is_done_)
+        return Iterator(nullptr);
       return Iterator(stmt_);
     }
 
@@ -518,14 +524,19 @@ class Database {
       return query_;
     }
 
+    void SetDone(bool is_done) {
+      is_done_ = is_done;
+    }
+
    private:
     friend class Database;
-    Result(sqlite3_stmt* stmt, sqlite3* db, std::string query)
-        : stmt_(stmt), db_(db), query_(std::move(query)) {}
+    Result(sqlite3_stmt* stmt, sqlite3* db, std::string query, bool is_done)
+        : stmt_(stmt), db_(db), query_(std::move(query)), is_done_(is_done) {}
 
     sqlite3_stmt* stmt_ = nullptr;
     sqlite3* db_ = nullptr;
     std::string query_;
+    bool is_done_;
   };
 
   Database(std::string db, int flags) {
@@ -596,7 +607,7 @@ class Database {
     int r = sqlite3_prepare_v2(db_, sql.GetQuery().c_str(),
         -1, &stmt, nullptr);
     if (r != SQLITE_OK) {
-      return { nullptr, nullptr, "" };
+      return { nullptr, nullptr, "", true };
     }
 
     std::unique_ptr<sqlite3_stmt, decltype(sqlite3_finalize)*> stmt_auto(stmt,
@@ -619,13 +630,14 @@ class Database {
 
     r = sqlite3_step(stmt);
     if (r != SQLITE_ROW && r != SQLITE_DONE) {
-      return { nullptr, db_, "" };
+      return { nullptr, db_, "", true };
     }
 
-    return { stmt_auto.release(), db_, sql.GetQuery() };
+    return { stmt_auto.release(), db_, sql.GetQuery(),
+        r == SQLITE_DONE ? true : false };
   }
 
-  bool Exec(const Sql& sql, const Result& previous_stmt) {
+  bool Exec(const Sql& sql, Result& previous_stmt) {
     if (sql.GetQuery() != previous_stmt.GetQuery())
       throw DbException("Query is different");
 
@@ -657,6 +669,7 @@ class Database {
     if (r != SQLITE_ROW && r != SQLITE_DONE)
       return false;
 
+    previous_stmt.SetDone(r == SQLITE_DONE ? true : false);
     return true;
   }