EXPECT_TRUE(ret);
}
+TEST_F(DatabaseTest, test_set_empty_string_as_null) {
+ tizen_base::Database db(TEST_DB, SQLITE_OPEN_READWRITE);
+ auto q = tizen_base::Database::Sql(Q_INSERT)
+ .SetEmptyStringAsNull(true)
+ .Bind("")
+ .Bind(1234)
+ .Bind(9.216)
+ .SetEmptyVectorAsNull(true)
+ .Bind(std::vector<unsigned char> {});
+ auto r = db.Exec(q);
+ EXPECT_TRUE(static_cast<bool>(r));
+
+ r = db.Exec({ Q_SELECT });
+ auto rec = r.GetFirstRecord();
+ std::optional<std::string> ret1 = rec->Get(0);
+ EXPECT_FALSE(ret1);
+ std::optional<std::vector<unsigned char>> ret2 = rec->Get(3);
+ EXPECT_FALSE(ret2);
+}
+
TEST_F(DatabaseTest, test_select) {
SetDefault();
using tizen_base::_;
class AutoDbType {
public:
AutoDbType() = default;
- AutoDbType(DbType db_type) : db_type_(db_type) {}
+ explicit AutoDbType(DbType db_type) : db_type_(db_type) {}
explicit operator int () {
if (!db_type_)
return *this;
}
- TransactionGuard(sqlite3* db) : db_(db) {
+ explicit TransactionGuard(sqlite3* db) : db_(db) {
if (sqlite3_exec(db, "BEGIN DEFERRED", nullptr, nullptr, nullptr)
!= SQLITE_OK) {
throw std::runtime_error("begin transaction failed");
Sql(std::string query) : query_(std::move(query)) {}
Sql& Bind(std::string val) {
- bindings_.push_back(DbType(std::move(val)));
+ if (empty_string_as_null_ && val.empty())
+ bindings_.push_back(DbType(std::nullopt));
+ else
+ bindings_.push_back(DbType(std::move(val)));
return *this;
}
}
Sql& Bind(std::vector<unsigned char> val) {
- bindings_.push_back(DbType(std::move(val)));
+ if (empty_vector_as_null_ && val.empty())
+ bindings_.push_back(DbType(std::nullopt));
+ else
+ bindings_.push_back(DbType(std::move(val)));
return *this;
}
}
Sql& Bind(int pos, std::string val) {
- binding_map_[pos] = DbType(std::move(val));
+ if (empty_string_as_null_ && val.empty())
+ binding_map_[pos] = DbType(std::nullopt);
+ else
+ binding_map_[pos] = DbType(std::move(val));
return *this;
}
}
Sql& Bind(int pos, std::vector<unsigned char> val) {
- binding_map_[pos] = DbType(std::move(val));
+ if (empty_vector_as_null_ && val.empty())
+ binding_map_[pos] = DbType(std::nullopt);
+ else
+ binding_map_[pos] = DbType(std::move(val));
return *this;
}
}
Sql& Bind(std::string name, std::string val) {
- binding_name_map_[std::move(name)] = DbType(std::move(val));
+ if (empty_string_as_null_ && val.empty())
+ binding_name_map_[std::move(name)] = DbType(std::nullopt);
+ else
+ binding_name_map_[std::move(name)] = DbType(std::move(val));
return *this;
}
}
Sql& Bind(std::string name, std::vector<unsigned char> val) {
- binding_name_map_[std::move(name)] = DbType(std::move(val));
+ if (empty_vector_as_null_ && val.empty())
+ binding_name_map_[std::move(name)] = DbType(std::nullopt);
+ else
+ binding_name_map_[std::move(name)] = DbType(std::move(val));
return *this;
}
return query_;
}
+ Sql& SetEmptyStringAsNull(bool as_null) {
+ empty_string_as_null_ = as_null;
+ return *this;
+ }
+
+ Sql& SetEmptyVectorAsNull(bool as_null) {
+ empty_vector_as_null_ = as_null;
+ return *this;
+ }
+
Sql& Reset() {
bindings_.clear();
binding_map_.clear();
binding_name_map_.clear();
+ empty_string_as_null_ = false;
+ empty_vector_as_null_ = false;
return *this;
}
std::vector<DbType> bindings_;
std::map<int, DbType> binding_map_;
std::map<std::string, DbType> binding_name_map_;
+ bool empty_string_as_null_ = false;
+ bool empty_vector_as_null_ = false;
};
class Result {
class Record {
public:
- Record(const sqlite3_stmt* stmt) : stmt_(stmt) {}
+ explicit Record(const sqlite3_stmt* stmt) : stmt_(stmt) {}
AutoDbType Get(int pos) const {
sqlite3_stmt* stmt = const_cast<sqlite3_stmt*>(stmt_);
class Iterator {
public:
- Iterator(sqlite3_stmt* stmt) : stmt_(stmt) {}
+ explicit Iterator(sqlite3_stmt* stmt) : stmt_(stmt) {}
Record operator*() { return Record(stmt_); }