Add some methods 26/286426/1
authorjh9216.park <jh9216.park@samsung.com>
Fri, 6 Jan 2023 00:15:18 +0000 (19:15 -0500)
committerjh9216.park <jh9216.park@samsung.com>
Fri, 6 Jan 2023 00:15:18 +0000 (19:15 -0500)
- Result.GetColumnCount() added
- Record.GetString() added
- AutoDbType.GetType() added
- Enhance exception handling

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

index d4239a4..b6d2180 100644 (file)
@@ -545,3 +545,59 @@ TEST_F(DatabaseTest, test_nullptr_bind) {
   auto r = db.Exec(q);
   ASSERT_TRUE(r);
 }
+
+TEST_F(DatabaseTest, test_get_column_count) {
+  SetDefault();
+  using tizen_base::_;
+  tizen_base::Database db(TEST_DB, SQLITE_OPEN_READWRITE);
+  auto r = db.Exec({ Q_SELECT });
+
+  EXPECT_TRUE(r);
+  EXPECT_EQ(r.GetColumnCount(), 4);
+}
+
+TEST_F(DatabaseTest, test_invalid_type_cast) {
+  SetDefault();
+  using tizen_base::_;
+  tizen_base::Database db(TEST_DB, SQLITE_OPEN_READWRITE);
+  auto r = db.Exec({ Q_SELECT });
+
+  EXPECT_TRUE(r);
+  auto cnt = r.GetColumnCount();
+  EXPECT_EQ(cnt, 4);
+
+  for (const auto& i : r) {
+    auto t = i.Get(0);
+    EXPECT_EQ(t.GetType(), SQLITE_TEXT);
+
+    bool error = false;
+    try {
+      int name = static_cast<int>(i.Get(0));
+      (void)name;
+    } catch (const tizen_base::DbException&) {
+      error = true;
+    }
+
+    EXPECT_TRUE(error);
+  }
+}
+
+TEST_F(DatabaseTest, test_get_string) {
+  SetDefault();
+  using tizen_base::_;
+  tizen_base::Database db(TEST_DB, SQLITE_OPEN_READWRITE);
+  auto r = db.Exec({ Q_SELECT });
+
+  EXPECT_TRUE(r);
+  auto cnt = r.GetColumnCount();
+  EXPECT_EQ(cnt, 4);
+
+  for (const auto& i : r) {
+    auto t = i.Get(1);
+    EXPECT_EQ(t.GetType(), SQLITE_INTEGER);
+
+    auto val = i.GetString(1);
+    EXPECT_TRUE(val);
+    EXPECT_EQ(*val, "1234");
+  }
+}
\ No newline at end of file
index 88cb2a6..d69c378 100644 (file)
@@ -79,17 +79,28 @@ class DbException : public std::runtime_error {
 class AutoDbType {
  public:
   AutoDbType() = default;
-  explicit AutoDbType(DbType db_type) : db_type_(db_type) {}
+  explicit AutoDbType(DbType db_type, int real_type)
+      : db_type_(db_type), real_type_(real_type) {}
+
+  int GetType() const {
+    return real_type_;
+  }
 
   explicit operator int () {
     if (!db_type_)
       throw DbException("invalid type conversion from nullopt to int");
+    if (real_type_ != SQLITE_INTEGER)
+      throw DbException("invalid type conversion to int");
+
     return std::get<int64_t>(*db_type_);
   }
 
   explicit operator int64_t () {
     if (!db_type_)
-      throw DbException("invalid type conversion from nullopt to int");
+      throw DbException("invalid type conversion from nullopt to int64_t");
+    if (real_type_ != SQLITE_INTEGER)
+      throw DbException("invalid type conversion to int64_t");
+
     return std::get<int64_t>(*db_type_);
   }
 
@@ -99,6 +110,9 @@ class AutoDbType {
           "invalid type conversion from nullopt to string");
     }
 
+    if (real_type_ != SQLITE_TEXT)
+      throw DbException("invalid type conversion to string");
+
     return std::get<std::string>(*db_type_);
   }
 
@@ -108,6 +122,9 @@ class AutoDbType {
           "invalid type conversion from nullopt to double");
     }
 
+    if (real_type_ != SQLITE_FLOAT)
+      throw DbException("invalid type conversion to double");
+
     return std::get<double>(*db_type_);
   }
 
@@ -117,41 +134,60 @@ class AutoDbType {
           "invalid type conversion from nullopt to std::vector<unsigned char>");
     }
 
+    if (real_type_ != SQLITE_BLOB)
+      throw DbException("invalid type conversion to std::vector<unsigned char>");
+
     return std::get<std::vector<unsigned char>>(*db_type_);
   }
 
   operator std::optional<int> () {
     if (!db_type_)
       return std::nullopt;
+    if (real_type_ != SQLITE_INTEGER)
+      throw DbException("invalid type conversion to int");
+
     return std::get<int64_t>(*db_type_);
   }
 
   operator std::optional<int64_t> () {
     if (!db_type_)
       return std::nullopt;
+    if (real_type_ != SQLITE_INTEGER)
+      throw DbException("invalid type conversion to int64_t");
+
     return std::get<int64_t>(*db_type_);
   }
 
   operator std::optional<std::string> () {
     if (!db_type_)
       return std::nullopt;
+    if (real_type_ != SQLITE_TEXT)
+      throw DbException("invalid type conversion to string");
+
     return std::get<std::string>(*db_type_);
   }
 
   operator std::optional<double> () {
     if (!db_type_)
       return std::nullopt;
+    if (real_type_ != SQLITE_FLOAT)
+      throw DbException("invalid type conversion to double");
+
     return std::get<double>(*db_type_);
   }
 
   operator std::optional<std::vector<unsigned char>> () {
     if (!db_type_)
       return std::nullopt;
+    if (real_type_ != SQLITE_BLOB)
+      throw DbException("invalid type conversion to std::vector<unsigned char>");
+
     return std::get<std::vector<unsigned char>>(*db_type_);
   }
 
  private:
   DbType db_type_;
+  int real_type_;
 };
 
 using _ = AutoDbType;
@@ -435,6 +471,16 @@ class Database {
      public:
       explicit Record(const sqlite3_stmt* stmt) : stmt_(stmt) {}
 
+      std::optional<std::string> GetString(int pos) const {
+        sqlite3_stmt* stmt = const_cast<sqlite3_stmt*>(stmt_);
+        const char* text = reinterpret_cast<const char*>(
+            sqlite3_column_text(stmt, pos));
+        if (!text)
+          return std::nullopt;
+
+        return text;
+      }
+
       AutoDbType Get(int pos) const {
         sqlite3_stmt* stmt = const_cast<sqlite3_stmt*>(stmt_);
         int type = sqlite3_column_type(stmt, pos);
@@ -463,7 +509,7 @@ class Database {
           throw DbException("invalid column type", type);
         }
 
-        return AutoDbType(dbt);
+        return AutoDbType(dbt, type);
       }
 
       template <typename ...Types>
@@ -594,6 +640,10 @@ class Database {
       is_done_ = is_done;
     }
 
+    size_t GetColumnCount() const {
+      return sqlite3_column_count(stmt_);
+    }
+
    private:
     friend class Database;
     Result(sqlite3_stmt* stmt, sqlite3* db, std::string query, bool is_done)