From: Mu-Woong Lee Date: Fri, 10 Mar 2017 09:38:19 +0000 (+0900) Subject: Add insert() helper functions to the class Database X-Git-Tag: accepted/tizen/unified/20170414.163458^2~20 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=00714b2bc2a3d76bb7c1e58dff0e62b53cd03ff2;p=platform%2Fcore%2Fcontext%2Fcontext-common.git Add insert() helper functions to the class Database Change-Id: Id3e1bef3239974fca51102d07a809f00c7d6729f Signed-off-by: Mu-Woong Lee --- diff --git a/include/Database.h b/include/Database.h index d784fec..f8e9c8a 100644 --- a/include/Database.h +++ b/include/Database.h @@ -17,6 +17,7 @@ #ifndef __CONTEXT_DATABASE_H__ #define __CONTEXT_DATABASE_H__ +#include #include #include #include @@ -26,6 +27,7 @@ #define COL_STRING "s" struct sqlite3; +struct sqlite3_stmt; namespace ctx { @@ -33,6 +35,25 @@ namespace ctx { class EXPORT_API Database { public: + class Insertions { + public: + Insertions(Database* database, const std::string& tableName, const std::string& columns); + ~Insertions(); + + bool add(Tuple* tuple, Tuple* tupleExt = NULL); + + private: + int __bind(Tuple* tuple, int idx); + bool __execute(); + + sqlite3* __dbHandle; + sqlite3_stmt* __stmt; + std::vector> __values; + int __dimension; + + friend class Database; + }; + Database(const std::string& dbPath); virtual ~Database(); @@ -43,6 +64,11 @@ namespace ctx { bool execute(const std::string& query, const std::string& columnTypes, std::vector* columnNames, std::vector* queryResult); bool execute(const std::string& query, std::vector* queryResult); + // insert() does not consume the input tuples + bool insert(const std::string& tableName, const std::string& columns, Tuple* tuple, Tuple* tupleExt = NULL); + bool insert(const std::string& tableName, const std::string& columns, std::vector& tuples); + bool insert(Insertions& insertions); + void beginTransaction(); void endTransaction(); diff --git a/include/Tuple.h b/include/Tuple.h index 2bcce6a..e63caaa 100644 --- a/include/Tuple.h +++ b/include/Tuple.h @@ -27,9 +27,12 @@ namespace ctx { public: ~Tuple(); + unsigned int size(); + bool getAt(unsigned int idx, int64_t* val); bool getAt(unsigned int idx, double* val); bool getAt(unsigned int idx, std::string* val); + bool getAt(unsigned int idx, const char** val); static Tuple* duplicate(Tuple& tuple); diff --git a/src/database/Database.cpp b/src/database/Database.cpp index e8e63ca..5bec68e 100644 --- a/src/database/Database.cpp +++ b/src/database/Database.cpp @@ -14,6 +14,7 @@ * limitations under the License. */ +#include #include #include #include @@ -170,7 +171,33 @@ bool Database::execute(const std::string& query, const std::string& columnTypes, bool Database::execute(const std::string& query, std::vector* result) { - return execute(query, "", NULL, result); + return execute(query, EMPTY_STR, NULL, result); +} + +bool Database::insert(const std::string& tableName, const std::string& columns, Tuple* tuple, Tuple* tupleExt) +{ + Insertions insertions(this, tableName, columns); + insertions.add(tuple, tupleExt); + return insertions.__execute(); +} + +bool Database::insert(const std::string& tableName, const std::string& columns, std::vector& tuples) +{ + Insertions insertions(this, tableName, columns); + for (auto& tuple : tuples) { + if (!insertions.add(tuple, NULL)) + return false; + } + return insert(insertions); +} + +bool Database::insert(Insertions& insertions) +{ + IF_FAIL_RETURN(insertions.__dbHandle == this->__dbHandle, false); + beginTransaction(); + bool success = insertions.__execute(); + endTransaction(); + return success; } void Database::beginTransaction() @@ -195,3 +222,86 @@ void Database::endTransaction() sqlite3_exec(__dbHandle, endQuery, NULL, NULL, NULL); __transactionOn = false; } + +Database::Insertions::Insertions(Database* database, const std::string& tableName, const std::string& columns) : + __dbHandle(database->__dbHandle), + __stmt(NULL), + __dimension(0) +{ + IF_FAIL_VOID_TAG(database && !tableName.empty() && !columns.empty(), _E, "Invalid parameter"); + + size_t columnCnt = std::count(columns.begin(), columns.end(), ',') + 1; + __dimension = columnCnt; + + std::string query = "INSERT INTO [" + tableName + "] (" + columns + ") VALUES ("; + + for (size_t i = 0; i < columnCnt; ++i) { + query += "?,"; + } + + query.back() = ')'; + + int error = sqlite3_prepare_v2(__dbHandle, query.c_str(), -1, &__stmt, NULL); + IF_FAIL_VOID_TAG(error == SQLITE_OK, _E, "Preparation failed"); +} + +Database::Insertions::~Insertions() +{ + sqlite3_finalize(__stmt); +} + +bool Database::Insertions::add(Tuple* tuple, Tuple* tupleExt) +{ + IF_FAIL_RETURN(tuple, false); + __values.push_back(std::make_pair(tuple, tupleExt)); + return true; +} + +int Database::Insertions::__bind(Tuple* tuple, int idx) +{ + IF_FAIL_RETURN(tuple && idx >= 0, idx); + + const char* str = NULL; + int64_t i64 = 0; + double dbl = 0; + + for (unsigned int i = 0; i < tuple->size(); ++i) { + if (tuple->getAt(i, &str)) { + if (sqlite3_bind_text(__stmt, idx, str, -1, SQLITE_STATIC) != SQLITE_OK) + return E_FAILED; + } else if (tuple->getAt(i, &i64)) { + if (sqlite3_bind_int64(__stmt, idx, i64) != SQLITE_OK) + return E_FAILED; + } else if (tuple->getAt(i, &dbl)) { + if (sqlite3_bind_double(__stmt, idx, dbl) != SQLITE_OK) + return E_FAILED; + } else { + _W("Unknown attribute type"); + return E_FAILED; + } + ++idx; + } + + return idx; +} + +bool Database::Insertions::__execute() +{ + for (auto& iter : __values) { + Tuple* tuple = iter.first; + Tuple* tupleExt = iter.second; + + if (__bind(tupleExt, __bind(tuple, 0)) != __dimension) { + _E("Binding failed"); + sqlite3_reset(__stmt); + return false; + } + + if (sqlite3_step(__stmt) != SQLITE_DONE) { + _E("Execution failed"); + return false; + } + } + + return true; +} diff --git a/src/shared/Tuple.cpp b/src/shared/Tuple.cpp index db61a59..a8e2f16 100644 --- a/src/shared/Tuple.cpp +++ b/src/shared/Tuple.cpp @@ -77,6 +77,13 @@ bool Tuple::__verify(unsigned int idx, const GVariantType* type) return true; } +unsigned int Tuple::size() +{ + IF_FAIL_RETURN_TAG(__gVar, 0, _W, "Consumed"); + IF_FAIL_RETURN_TAG(__parse(), 0, _E, "Parsing failed"); + return static_cast(__numElements); +} + bool Tuple::getAt(unsigned int idx, int64_t* val) { IF_FAIL_RETURN(__verify(idx, G_VARIANT_TYPE_INT64), false); @@ -93,12 +100,21 @@ bool Tuple::getAt(unsigned int idx, double* val) bool Tuple::getAt(unsigned int idx, std::string* val) { + const char* str = NULL; + IF_FAIL_RETURN(getAt(idx, &str), false); + + *val = str; + return true; +} + +bool Tuple::getAt(unsigned int idx, const char** val) +{ IF_FAIL_RETURN(__verify(idx, G_VARIANT_TYPE_STRING), false); const gchar* str = g_variant_get_string(__elements[idx], NULL); IF_FAIL_RETURN_TAG(str, false, _E, "NULL string"); - *val = str; + *val = reinterpret_cast(str); return true; }