diff --git a/column.cpp b/column.cpp index e7f083b..a3acc48 100644 --- a/column.cpp +++ b/column.cpp @@ -14,6 +14,8 @@ const char* column::name() const { return sqlite3_column_name(stmt.raw(), idx); } +#if defined(SQLITE_ENABLE_COLUMN_METADATA) + const char* column::database_name() const { return sqlite3_column_database_name(stmt.raw(), idx); } @@ -26,6 +28,8 @@ const char* column::origin_name() const { return sqlite3_column_origin_name(stmt.raw(), idx); } +#endif + int column::type() const { return sqlite3_column_type(stmt.raw(), idx); } diff --git a/column.hpp b/column.hpp index 85c6a50..b9757d7 100644 --- a/column.hpp +++ b/column.hpp @@ -21,11 +21,13 @@ class column { /** Wraps [`sqlite3_column_name()`](http://www.sqlite.org/c3ref/column_name.html) */ const char* name() const; /** Wraps [`sqlite3_column_database_name()`](http://www.sqlite.org/c3ref/column_database_name.html) */ +#if defined(SQLITE_ENABLE_COLUMN_METADATA) const char* database_name() const; /** Wraps [`sqlite3_column_table_name()`](http://www.sqlite.org/c3ref/column_database_name.html) */ const char* table_name() const; /** Wraps [`sqlite3_column_origin_name()`](http://www.sqlite.org/c3ref/column_database_name.html) */ const char* origin_name() const; +#endif // TODO: Better return type /** Wraps [`sqlite3_column_type()`](http://www.sqlite.org/c3ref/column_blob.html) */ diff --git a/connection.cpp b/connection.cpp index f8002b3..79b03bc 100644 --- a/connection.cpp +++ b/connection.cpp @@ -22,8 +22,7 @@ struct collation_data_t { namespace detail { -class connection_callback_table { -public: +struct connection_callback_table { std::unique_ptr commit_handler; std::unique_ptr rollback_handler; std::unique_ptr update_handler; @@ -53,6 +52,11 @@ connection:: connection(const std::string &filename, int flags) : handle(nullptr open(filename, flags); } +connection::connection(connection&& other) noexcept + : handle(other.handle), callbacks(std::move(other.callbacks)) { + other.handle = nullptr; +} + connection::~connection() noexcept { if (handle) { close(); @@ -100,7 +104,7 @@ bool connection::autocommit() const { return sqlite3_get_autocommit(handle); } -uint64_t connection::last_insert_rowid() const { +int64_t connection::last_insert_rowid() const { return sqlite3_last_insert_rowid(handle); } @@ -317,12 +321,12 @@ statement connection::prepare(const char *sql) { int rv; sqlite3_stmt *stmt = nullptr; - rv = sqlite3_prepare_v2(handle, sql, std::strlen(sql)+1, &stmt, nullptr); + rv = sqlite3_prepare_v2(handle, sql, int(std::strlen(sql)+1), &stmt, nullptr); if (rv != SQLITE_OK) { throw static_error(rv); } - return statement(*this, stmt); + return statement(stmt); } statement connection::prepare(const std::string &sql) { diff --git a/connection.hpp b/connection.hpp index f2e1776..8f950ba 100644 --- a/connection.hpp +++ b/connection.hpp @@ -64,7 +64,7 @@ class connection { private: sqlite3 *handle; - friend class detail::connection_callback_table; + friend struct detail::connection_callback_table; std::unique_ptr callbacks; // On-demand initialization of callback table @@ -79,8 +79,13 @@ class connection { // Don't copy, move connection(const connection&) = delete; connection& operator=(const connection&) = delete; - connection(connection&&) = default; - connection& operator=(connection&&) = default; + + connection(connection&& other) noexcept; + connection& operator=(connection&& other) noexcept { + this->~connection(); + return *::new (static_cast(this)) auto( + std::move(other)); + } /** * The database file name. @@ -132,7 +137,7 @@ class connection { */ bool autocommit() const; - uint64_t last_insert_rowid() const; + int64_t last_insert_rowid() const; /** * Get the database connection status. diff --git a/context.cpp b/context.cpp index 946266c..a2c2854 100644 --- a/context.cpp +++ b/context.cpp @@ -57,13 +57,17 @@ void context::result(const char *value, bool copy) { template<> void context::result(const std::string &value, bool copy) { - sqlite3_result_text(handle, value.c_str(), value.length(), (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); + sqlite3_result_text(handle, value.c_str(), int(value.size()), (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); } template<> void context::result(const blob &value, bool copy) { if (value.data) { +#if !defined(sqlite3_result_blob) sqlite3_result_blob(handle, value.data, value.length, (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); +#else + sqlite3_result_blob64(handle, value.data, unsigned(value.length), (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); +#endif } else { sqlite3_result_zeroblob(handle, value.length); diff --git a/context.hpp b/context.hpp index 87a9765..aa9aac3 100644 --- a/context.hpp +++ b/context.hpp @@ -12,7 +12,7 @@ namespace sqxx { // Aggregate function interoperability namespace detail { - class aggregate_data; + struct aggregate_data; } /** Wraps `struct sqlite3_context` */ @@ -90,7 +90,7 @@ class context { private: // This is used internally by our aggregate functions - friend class detail::aggregate_data; + friend struct detail::aggregate_data; void* aggregate_context(int bytes); public: diff --git a/global.cpp b/global.cpp index ee536a5..5650f02 100644 --- a/global.cpp +++ b/global.cpp @@ -97,11 +97,11 @@ bool complete(const std::string &sql) { return complete(sql.c_str()); } -uint64_t memory_used() { +int64_t memory_used() { return sqlite3_memory_used(); } -uint64_t memory_highwater(bool reset) { +int64_t memory_highwater(bool reset) { return sqlite3_memory_highwater(reset); } diff --git a/global.hpp b/global.hpp index 047fe94..ce91296 100644 --- a/global.hpp +++ b/global.hpp @@ -97,14 +97,14 @@ bool complete(const std::string &sql); * * Wraps [`sqlite3_memory_used()`](http://www.sqlite.org/c3ref/memory_highwater.html) */ -uint64_t memory_used(); +int64_t memory_used(); /** * Memory allocator statistics * * Wraps [`sqlite3_memory_highwater()`](http://www.sqlite.org/c3ref/memory_highwater.html) */ -uint64_t memory_highwater(bool reset=false); +int64_t memory_highwater(bool reset=false); /** * Pseuso-random number generator diff --git a/statement.cpp b/statement.cpp index e655362..3abba7e 100644 --- a/statement.cpp +++ b/statement.cpp @@ -9,8 +9,8 @@ namespace sqxx { -statement::statement(connection &conn_arg, sqlite3_stmt *handle_arg) - : handle(handle_arg), conn(conn_arg), completed(true) { +statement::statement(sqlite3_stmt *handle_arg) + : handle(handle_arg), completed(true) { } statement::~statement() { @@ -115,7 +115,7 @@ void statement::bind(int idx, const char *value, bool copy) { template<> void statement::bind(int idx, const std::string &value, bool copy) { - int rv = sqlite3_bind_text(handle, idx+1, value.c_str(), value.length(), (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); + int rv = sqlite3_bind_text(handle, idx+1, value.c_str(), int(value.size()), (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); if (rv != SQLITE_OK) throw static_error(rv); } @@ -123,7 +123,11 @@ void statement::bind(int idx, const std::string &value, bool copy) template<> void statement::bind(int idx, const blob &value, bool copy) { if (value.data) { +#if !defined(sqlite3_bind_blob) int rv = sqlite3_bind_blob(handle, idx+1, value.data, value.length, (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); +#else + int rv = sqlite3_bind_blob64(handle, idx+1, value.data, unsigned(value.length), (copy ? SQLITE_TRANSIENT : SQLITE_STATIC)); +#endif if (rv != SQLITE_OK) throw static_error(rv); } @@ -168,16 +172,16 @@ template<> std::string statement::val(int idx) const { // Correct order to call functions according to http://www.sqlite.org/c3ref/column_blob.html const unsigned char* text = sqlite3_column_text(handle, idx); - int bytes = sqlite3_column_bytes(handle, idx); - return std::string(reinterpret_cast(text), bytes); + auto bytes = sqlite3_column_bytes(handle, idx); + return std::string(reinterpret_cast(text), size_t(bytes)); } template<> blob statement::val(int idx) const { // Correct order to call functions according to http://www.sqlite.org/c3ref/column_blob.html const void *data = sqlite3_column_blob(handle, idx); - int bytes = sqlite3_column_bytes(handle, idx); - return blob(data, bytes); + auto bytes = sqlite3_column_bytes(handle, idx); + return blob(data, int(bytes)); } diff --git a/statement.hpp b/statement.hpp index f196c40..5ba4d7a 100644 --- a/statement.hpp +++ b/statement.hpp @@ -31,27 +31,24 @@ class statement { private: sqlite3_stmt *handle; -public: - connection &conn; - protected: bool completed; public: + statement() noexcept : handle(nullptr), completed(false) { + } + /** - * Constructs a statement object from a connection object and a C API - * statement handle. + * Constructs a statement object from a C API statement handle. * * Usually not called directly, use `connection::prepare()` instead. - * - * @conn_arg The connection object associated with the statement. A reference - * is stored and the connection object must stay alive until the constructed - * `statement` is destroyed. + * The connection object associated with the statement must stay alive + * until the `statement` is destroyed. * * @handle_arg A C API statement handle. The constructed `statement` takes * ownership of the C API handle and will close it on destruction. */ - statement(connection &conn_arg, sqlite3_stmt *handle_arg); + explicit statement(sqlite3_stmt *handle_arg); /* * Destroys the object, closing the managed C API handle, if necessary. */ @@ -61,10 +58,19 @@ class statement { statement(const statement &) = delete; /** Copy assignment is disabled */ statement& operator=(const statement&) = delete; + /** Move construction is enabled */ - statement(statement &&) = default; + statement(statement&& other) noexcept + : handle(other.handle), completed(other.completed) { + other.handle = nullptr; + } + /** Move assignment is enabled */ - statement& operator=(statement&&) = default; + statement& operator=(statement&& other) noexcept { + this->~statement(); + return *::new (static_cast(this)) auto( + std::move(other)); + } /** @@ -318,7 +324,7 @@ class statement { /** Check if all result rows have been processed */ bool done() const { return completed; } - operator bool() const { return !completed; } + explicit operator bool() const { return !completed; } class row_iterator : public std::iterator { private: diff --git a/value.cpp b/value.cpp index 2c1b04d..c9c94d4 100644 --- a/value.cpp +++ b/value.cpp @@ -38,16 +38,16 @@ template<> std::string value::val() const { // Correct order to call functions according to http://www.sqlite.org/c3ref/column_blob.html const unsigned char *text = sqlite3_value_text(handle); - int bytes = sqlite3_value_bytes(handle); - return std::string(reinterpret_cast(text), bytes); + auto bytes = sqlite3_value_bytes(handle); + return std::string(reinterpret_cast(text), size_t(bytes)); } template<> blob value::val() const { // Correct order to call functions according to http://www.sqlite.org/c3ref/column_blob.html const void *data = sqlite3_value_blob(handle); - int len = sqlite3_value_bytes(handle); - return blob(data, len); + auto len = sqlite3_value_bytes(handle); + return blob(data, int(len)); } value::operator int() const { return val(); }