diff --git a/include/sqlpp11/sqlite3/bind_result.h b/include/sqlpp11/sqlite3/bind_result.h index eba79c3b..68458858 100644 --- a/include/sqlpp11/sqlite3/bind_result.h +++ b/include/sqlpp11/sqlite3/bind_result.h @@ -197,7 +197,7 @@ namespace sqlpp *value = (reinterpret_cast(sqlite3_column_text(_handle->sqlite_statement, static_cast(index)))); - *len = sqlite3_column_bytes(_handle->sqlite_statement, static_cast(index)); + *len = static_cast(sqlite3_column_bytes(_handle->sqlite_statement, static_cast(index))); } void _bind_blob_result(size_t index, const uint8_t** value, size_t* len) @@ -207,7 +207,7 @@ namespace sqlpp *value = (reinterpret_cast(sqlite3_column_blob(_handle->sqlite_statement, static_cast(index)))); - *len = sqlite3_column_bytes(_handle->sqlite_statement, static_cast(index)); + *len = static_cast(sqlite3_column_bytes(_handle->sqlite_statement, static_cast(index))); } void _bind_date_result(size_t index, ::sqlpp::chrono::day_point* value, bool* is_null) diff --git a/include/sqlpp11/sqlite3/connection.h b/include/sqlpp11/sqlite3/connection.h index 8fd8483a..79b3ae63 100644 --- a/include/sqlpp11/sqlite3/connection.h +++ b/include/sqlpp11/sqlite3/connection.h @@ -64,51 +64,53 @@ namespace sqlpp namespace detail { + inline void handle_cleanup(::sqlite3* sqlite) + { + sqlite3_close(sqlite); + } + struct connection_handle { connection_config config; - ::sqlite3* sqlite; + std::unique_ptr<::sqlite3, void (*)(::sqlite3*)> sqlite; - connection_handle(connection_config conf) : config(conf), sqlite(nullptr) + connection_handle(connection_config conf) : config(conf), sqlite(nullptr, handle_cleanup) { #ifdef SQLPP_DYNAMIC_LOADING init_sqlite(""); #endif - auto rc = sqlite3_open_v2(conf.path_to_database.c_str(), &sqlite, conf.flags, + ::sqlite3* sqlite_ptr; + const auto rc = sqlite3_open_v2(conf.path_to_database.c_str(), &sqlite_ptr, conf.flags, conf.vfs.empty() ? nullptr : conf.vfs.c_str()); if (rc != SQLITE_OK) { - const std::string msg = sqlite3_errmsg(sqlite); - sqlite3_close(sqlite); + const std::string msg = sqlite3_errmsg(sqlite_ptr); + sqlite3_close(sqlite_ptr); throw sqlpp::exception("Sqlite3 error: Can't open database: " + msg); } + + sqlite.reset(sqlite_ptr); + #ifdef SQLITE_HAS_CODEC if (conf.password.size() > 0) { - int ret = sqlite3_key(sqlite, conf.password.data(), conf.password.size()); + int ret = sqlite3_key(sqlite.get(), conf.password.data(), conf.password.size()); if (ret != SQLITE_OK) { - const std::string msg = sqlite3_errmsg(sqlite); - sqlite3_close(sqlite); + const std::string msg = sqlite3_errmsg(sqlite.get()); + sqlite3_close(sqlite.get()); throw sqlpp::exception("Sqlite3 error: Can't set password to database: " + msg); } } #endif } - connection_handle() - { - auto rc = sqlite3_close(sqlite); - if (rc != SQLITE_OK) - { - std::cerr << "Sqlite3 error: Can't close database: " << sqlite3_errmsg(sqlite) << std::endl; - } - } connection_handle(const connection_handle&) = delete; - connection_handle(connection_handle&&) = delete; + connection_handle(connection_handle&&) = default; connection_handle& operator=(const connection_handle&) = delete; - connection_handle& operator=(connection_handle&&) = delete; + connection_handle& operator=(connection_handle&&) = default; + ~connection_handle() = default; }; inline detail::prepared_statement_handle_t prepare_statement(detail::connection_handle& handle, @@ -119,13 +121,13 @@ namespace sqlpp detail::prepared_statement_handle_t result(nullptr, handle.config.debug); - auto rc = sqlite3_prepare_v2(handle.sqlite, statement.c_str(), static_cast(statement.size()), + auto rc = sqlite3_prepare_v2(handle.sqlite.get(), statement.c_str(), static_cast(statement.size()), &result.sqlite_statement, nullptr); if (rc != SQLITE_OK) { throw sqlpp::exception( - "Sqlite3 error: Could not prepare statement: " + std::string(sqlite3_errmsg(handle.sqlite)) + + "Sqlite3 error: Could not prepare statement: " + std::string(sqlite3_errmsg(handle.sqlite.get())) + " (statement was >>" + (rc == SQLITE_TOOBIG ? statement.substr(0, 128) + "..." : statement) + "<<\n"); } @@ -145,7 +147,7 @@ namespace sqlpp if (handle.config.debug) std::cerr << "Sqlite3 debug: sqlite3_step return code: " << rc << std::endl; throw sqlpp::exception("Sqlite3 error: Could not execute statement: " + - std::string(sqlite3_errmsg(handle.sqlite))); + std::string(sqlite3_errmsg(handle.sqlite.get()))); } } } // namespace detail @@ -188,7 +190,7 @@ namespace sqlpp class SQLPP11_SQLITE3_EXPORT connection : public sqlpp::connection { - std::unique_ptr _handle; + detail::connection_handle _handle; enum class transaction_status_type { none, @@ -202,7 +204,7 @@ namespace sqlpp bind_result_t select_impl(const std::string& statement) { std::unique_ptr prepared( - new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement))); + new detail::prepared_statement_handle_t(prepare_statement(_handle, statement))); if (!prepared) { throw sqlpp::exception("Sqlite3 error: Could not store result set"); @@ -213,31 +215,31 @@ namespace sqlpp size_t insert_impl(const std::string& statement) { - auto prepared = prepare_statement(*_handle, statement); - execute_statement(*_handle, prepared); + auto prepared = prepare_statement(_handle, statement); + execute_statement(_handle, prepared); - return sqlite3_last_insert_rowid(_handle->sqlite); + return static_cast(sqlite3_last_insert_rowid(_handle.sqlite.get())); } size_t update_impl(const std::string& statement) { - auto prepared = prepare_statement(*_handle, statement); - execute_statement(*_handle, prepared); - return sqlite3_changes(_handle->sqlite); + auto prepared = prepare_statement(_handle, statement); + execute_statement(_handle, prepared); + return static_cast(sqlite3_changes(_handle.sqlite.get())); } size_t remove_impl(const std::string& statement) { - auto prepared = prepare_statement(*_handle, statement); - execute_statement(*_handle, prepared); - return sqlite3_changes(_handle->sqlite); + auto prepared = prepare_statement(_handle, statement); + execute_statement(_handle, prepared); + return static_cast(sqlite3_changes(_handle.sqlite.get())); } // prepared execution prepared_statement_t prepare_impl(const std::string& statement) { return {std::unique_ptr( - new detail::prepared_statement_handle_t(prepare_statement(*_handle, statement)))}; + new detail::prepared_statement_handle_t(prepare_statement(_handle, statement)))}; } bind_result_t run_prepared_select_impl(prepared_statement_t& prepared_statement) @@ -247,30 +249,30 @@ namespace sqlpp size_t run_prepared_insert_impl(prepared_statement_t& prepared_statement) { - execute_statement(*_handle, *prepared_statement._handle.get()); + execute_statement(_handle, *prepared_statement._handle.get()); - return sqlite3_last_insert_rowid(_handle->sqlite); + return static_cast(sqlite3_last_insert_rowid(_handle.sqlite.get())); } size_t run_prepared_update_impl(prepared_statement_t& prepared_statement) { - execute_statement(*_handle, *prepared_statement._handle.get()); + execute_statement(_handle, *prepared_statement._handle.get()); - return sqlite3_changes(_handle->sqlite); + return static_cast(sqlite3_changes(_handle.sqlite.get())); } size_t run_prepared_remove_impl(prepared_statement_t& prepared_statement) { - execute_statement(*_handle, *prepared_statement._handle.get()); + execute_statement(_handle, *prepared_statement._handle.get()); - return sqlite3_changes(_handle->sqlite); + return static_cast(sqlite3_changes(_handle.sqlite.get())); } size_t run_prepared_execute_impl(prepared_statement_t& prepared_statement) { - execute_statement(*_handle, *prepared_statement._handle.get()); + execute_statement(_handle, *prepared_statement._handle.get()); - return sqlite3_changes(_handle->sqlite); + return static_cast(sqlite3_changes(_handle.sqlite.get())); } public: @@ -296,7 +298,7 @@ namespace sqlpp return ::sqlpp::serialize(t, context); } - connection(connection_config config) : _handle(new detail::connection_handle(std::move(config))) + connection(connection_config config) : _handle(std::move(config)) { } @@ -411,9 +413,9 @@ namespace sqlpp //! execute arbitrary command (e.g. create a table) size_t execute(const std::string& statement) { - auto prepared = prepare_statement(*_handle, statement); - execute_statement(*_handle, prepared); - return sqlite3_changes(_handle->sqlite); + auto prepared = prepare_statement(_handle, statement); + execute_statement(_handle, prepared); + return static_cast(sqlite3_changes(_handle.sqlite.get())); } template < @@ -488,7 +490,7 @@ namespace sqlpp auto prepare(const T& t) -> decltype(this->_prepare(t, typename sqlpp::prepare_check_t<_serializer_context_t, T>::type{})) { - sqlpp::prepare_check_t<_serializer_context_t, T>{}; + (void) sqlpp::prepare_check_t<_serializer_context_t, T>{}; return _prepare(t, sqlpp::prepare_check_t<_serializer_context_t, T>{}); } @@ -508,8 +510,8 @@ namespace sqlpp //! get the currently active transaction isolation level sqlpp::isolation_level get_default_isolation_level() { - auto stmt = prepare_statement(*_handle, "pragma read_uncommitted"); - execute_statement(*_handle, stmt); + auto stmt = prepare_statement(_handle, "pragma read_uncommitted"); + execute_statement(_handle, stmt); int level = sqlite3_column_int(stmt.sqlite_statement, 0); @@ -525,8 +527,8 @@ namespace sqlpp } _transaction_status = transaction_status_type::maybe; - auto prepared = prepare_statement(*_handle, "BEGIN"); - execute_statement(*_handle, prepared); + auto prepared = prepare_statement(_handle, "BEGIN"); + execute_statement(_handle, prepared); _transaction_status = transaction_status_type::active; } @@ -538,8 +540,8 @@ namespace sqlpp throw sqlpp::exception("Sqlite3 error: Cannot commit a finished or failed transaction"); } _transaction_status = transaction_status_type::maybe; - auto prepared = prepare_statement(*_handle, "COMMIT"); - execute_statement(*_handle, prepared); + auto prepared = prepare_statement(_handle, "COMMIT"); + execute_statement(_handle, prepared); _transaction_status = transaction_status_type::none; } @@ -556,8 +558,8 @@ namespace sqlpp std::cerr << "Sqlite3 warning: Rolling back unfinished transaction" << std::endl; } _transaction_status = transaction_status_type::maybe; - auto prepared = prepare_statement(*_handle, "ROLLBACK"); - execute_statement(*_handle, prepared); + auto prepared = prepare_statement(_handle, "ROLLBACK"); + execute_statement(_handle, prepared); _transaction_status = transaction_status_type::none; } @@ -570,19 +572,19 @@ namespace sqlpp //! get the last inserted id uint64_t last_insert_id() noexcept { - return sqlite3_last_insert_rowid(_handle->sqlite); + return static_cast(sqlite3_last_insert_rowid(_handle.sqlite.get())); } ::sqlite3* native_handle() { - return _handle->sqlite; + return _handle.sqlite.get(); } schema_t attach(const connection_config& config, const std::string name) { auto prepared = - prepare_statement(*_handle, "ATTACH '" + escape(config.path_to_database) + "' AS " + escape(name)); - execute_statement(*_handle, prepared); + prepare_statement(_handle, "ATTACH '" + escape(config.path_to_database) + "' AS " + escape(name)); + execute_statement(_handle, prepared); return {name}; } diff --git a/include/sqlpp11/sqlite3/connection_config.h b/include/sqlpp11/sqlite3/connection_config.h index 1affb84e..4f7603dc 100644 --- a/include/sqlpp11/sqlite3/connection_config.h +++ b/include/sqlpp11/sqlite3/connection_config.h @@ -41,6 +41,8 @@ namespace sqlpp } connection_config(const connection_config&) = default; connection_config(connection_config&&) = default; + connection_config& operator=(const connection_config&) = default; + connection_config& operator=(connection_config&&) = default; connection_config(std::string path, int fl = 0, std::string vf = "", bool dbg = false,std::string password="") : path_to_database(std::move(path)), flags(fl), vfs(std::move(vf)), debug(dbg),password(password) diff --git a/tests/sqlite3/usage/Sample.cpp b/tests/sqlite3/usage/Sample.cpp index 01e70a94..61fb9169 100644 --- a/tests/sqlite3/usage/Sample.cpp +++ b/tests/sqlite3/usage/Sample.cpp @@ -37,7 +37,6 @@ #include #include -SQLPP_ALIAS_PROVIDER(left) SQLPP_ALIAS_PROVIDER(pragma) SQLPP_ALIAS_PROVIDER(sub) @@ -103,8 +102,8 @@ int Sample(int, char*[]) .from(tab) .unconditionally())) { - int x = row.alpha; - int a = row.max; + int64_t x = row.alpha; + int64_t a = row.max; std::cout << x << ", " << a << std::endl; } tx.commit(); @@ -136,7 +135,7 @@ int Sample(int, char*[]) std::cerr << "--------" << std::endl; ps.params.alpha = sqlpp::eval(db, "last_insert_rowid()"); - ps.params.gamma = "false"; + ps.params.gamma = false; for (const auto& row : db(ps)) { std::cerr << "bound result: alpha: " << row.alpha << std::endl; @@ -188,7 +187,7 @@ int Sample(int, char*[]) auto x = custom_query(sqlpp::verbatim("PRAGMA user_version = "), 1); db(x); - int pragmaValue = + const int64_t pragmaValue = db(custom_query(sqlpp::verbatim("PRAGMA user_version")).with_result_type_of(select(sqlpp::value(1).as(pragma)))) .front() .pragma; diff --git a/tests/sqlite3/usage/Select.cpp b/tests/sqlite3/usage/Select.cpp index 2422bb56..4001d473 100644 --- a/tests/sqlite3/usage/Select.cpp +++ b/tests/sqlite3/usage/Select.cpp @@ -38,8 +38,6 @@ #include #include -SQLPP_ALIAS_PROVIDER(left) - namespace sql = sqlpp::sqlite3; const auto tab = TabSample{}; @@ -143,8 +141,8 @@ int Select(int, char*[]) auto tx = start_transaction(db); for (const auto& row : db(select(all_of(tab), select(max(tab.alpha)).from(tab)).from(tab).unconditionally())) { - int x = row.alpha; - int a = row.max; + const int64_t x = row.alpha; + const int64_t a = row.max; std::cout << ">>>" << x << ", " << a << std::endl; } for (const auto& row : @@ -161,8 +159,8 @@ int Select(int, char*[]) for (const auto& row : db(select(all_of(tab), select(trim(tab.beta)).from(tab)).from(tab).unconditionally())) { - int x = row.alpha; - std::string a = row.trim; + const int64_t x = row.alpha; + const std::string a = row.trim; std::cout << ">>>" << x << ", " << a << std::endl; } diff --git a/tests/sqlite3/usage/Transaction.cpp b/tests/sqlite3/usage/Transaction.cpp index 90ba4a6f..027f5816 100644 --- a/tests/sqlite3/usage/Transaction.cpp +++ b/tests/sqlite3/usage/Transaction.cpp @@ -57,7 +57,7 @@ int Transaction(int, char*[]) std::cout << "Expecting default isolation level = 1, is " << static_cast(current_level) << std::endl; assert(current_level == sqlpp::isolation_level::serializable); - int pragmaValue = db(custom_query(sqlpp::verbatim("PRAGMA read_uncommitted")) + int64_t pragmaValue = db(custom_query(sqlpp::verbatim("PRAGMA read_uncommitted")) .with_result_type_of(select(sqlpp::value(1).as(pragma)))) .front() .pragma;