From e5d0186db99492a139237067bab841a5b83463af Mon Sep 17 00:00:00 2001 From: Karen Arutyunov Date: Wed, 24 Jan 2024 19:01:19 +0300 Subject: Turn libodb-sqlite repository into package for muti-package repository --- libodb-sqlite/odb/sqlite/statement.hxx | 392 +++++++++++++++++++++++++++++++++ 1 file changed, 392 insertions(+) create mode 100644 libodb-sqlite/odb/sqlite/statement.hxx (limited to 'libodb-sqlite/odb/sqlite/statement.hxx') diff --git a/libodb-sqlite/odb/sqlite/statement.hxx b/libodb-sqlite/odb/sqlite/statement.hxx new file mode 100644 index 0000000..9eeea7b --- /dev/null +++ b/libodb-sqlite/odb/sqlite/statement.hxx @@ -0,0 +1,392 @@ +// file : odb/sqlite/statement.hxx +// license : GNU GPL v2; see accompanying LICENSE file + +#ifndef ODB_SQLITE_STATEMENT_HXX +#define ODB_SQLITE_STATEMENT_HXX + +#include + +#include + +#include +#include // std::size_t +#include // std::strlen, std::memcpy +#include + +#include + +#include +#include +#include +#include +#include + +#include + +namespace odb +{ + namespace sqlite + { + class connection; + + class LIBODB_SQLITE_EXPORT statement: public odb::statement, + public active_object + { + public: + typedef sqlite::connection connection_type; + + virtual + ~statement () = 0; + + sqlite3_stmt* + handle () const + { + return stmt_; + } + + virtual const char* + text () const; + + virtual connection_type& + connection () + { + return conn_; + } + + // A statement can be empty. This is used to handle situations + // where a SELECT or UPDATE statement ends up not having any + // columns after processing. An empty statement cannot be + // executed. + // + bool + empty () const + { + return stmt_ == 0; + } + + protected: + // We keep two versions to take advantage of std::string COW. + // + statement (connection_type& conn, + const std::string& text, + statement_kind sk, + const binding* process, + bool optimize) + : active_object (conn) + { + init (text.c_str (), text.size (), sk, process, optimize); + } + + statement (connection_type& conn, + const char* text, + statement_kind sk, + const binding* process, + bool optimize) + : active_object (conn) + { + init (text, std::strlen (text), sk, process, optimize); + } + + statement (connection_type& conn, + const char* text, + std::size_t text_size, + statement_kind sk, + const binding* process, + bool optimize) + : active_object (conn) + { + init (text, text_size, sk, process, optimize); + } + + protected: + // Return true if we bound any stream parameters. + // + bool + bind_param (const bind*, std::size_t count); + + // Extract row columns into the bound buffers. If the truncated + // argument is true, then only truncated columns are extracted. + // Return true if all the data was extracted successfully and + // false if one or more columns were truncated. + // + bool + bind_result (const bind*, std::size_t count, bool truncated = false); + + // Stream (so to speak) parameters. + // + struct stream_data + { + std::string db; + std::string table; + long long rowid; + }; + + void + stream_param (const bind*, std::size_t count, const stream_data&); + + friend void + update_hook (void*, const char*, const char*, long long); + + // Active state. + // + protected: + bool + active () const + { + return active_; + } + + void + active (bool active) + { + assert (active); + + if (!active_) + { + list_add (); + active_ = true; + } + } + + int + reset () + { + int r (SQLITE_OK); + + if (active_) + { + r = sqlite3_reset (stmt_); + list_remove (); + active_ = false; + } + + return r; + } + + // The active_object interface. + // + virtual void + clear (); + + protected: + auto_handle stmt_; + +#if SQLITE_VERSION_NUMBER < 3005003 + std::string text_; +#endif + + bool active_; + + private: + void + init (const char* text, + std::size_t text_size, + statement_kind, + const binding* process, + bool optimize); + }; + + class LIBODB_SQLITE_EXPORT generic_statement: public statement + { + public: + generic_statement (connection_type&, const std::string& text); + generic_statement (connection_type&, const char* text); + generic_statement (connection_type&, + const char* text, + std::size_t text_size); + + unsigned long long + execute (); + + private: + generic_statement (const generic_statement&); + generic_statement& operator= (const generic_statement&); + + private: + bool result_set_; + }; + + class LIBODB_SQLITE_EXPORT select_statement: public statement + { + public: + select_statement (connection_type& conn, + const std::string& text, + bool process_text, + bool optimize_text, + binding& param, + binding& result); + + select_statement (connection_type& conn, + const char* text, + bool process_text, + bool optimize_text, + binding& param, + binding& result); + + select_statement (connection_type& conn, + const std::string& text, + bool process_text, + bool optimize_text, + binding& result); + + select_statement (connection_type& conn, + const char* text, + bool process_text, + bool optimize_text, + binding& result); + + // Common select interface expected by the generated code. + // + public: + enum result + { + success, + no_data, + truncated + }; + + void + execute (); + + // Load next row columns into bound buffers. + // + result + fetch () + { + return next () ? load () : no_data; + } + + // Reload truncated columns into bound buffers. + // + void + refetch () + { + reload (); + } + + // Free the result set. + // + void + free_result (); + + // More fine-grained SQLite-specific interface that splits fetch() + // into next() and load(). + // + public: + // Return false if there is no more rows. You should call next() + // until it returns false or, alternatively, call free_result (). + // Otherwise the statement will remain unfinished. + // + bool + next (); + + result + load (); + + void + reload (); + + private: + select_statement (const select_statement&); + select_statement& operator= (const select_statement&); + + private: + bool done_; + binding* param_; + binding& result_; + }; + + struct auto_result + { + explicit auto_result (select_statement& s): s_ (s) {} + ~auto_result () {s_.free_result ();} + + private: + auto_result (const auto_result&); + auto_result& operator= (const auto_result&); + + private: + select_statement& s_; + }; + + class LIBODB_SQLITE_EXPORT insert_statement: public statement + { + public: + insert_statement (connection_type& conn, + const std::string& text, + bool process_text, + binding& param, + binding* returning); + + insert_statement (connection_type& conn, + const char* text, + bool process_text, + binding& param, + binding* returning); + + // Return true if successful and false if the row is a duplicate. + // All other errors are reported by throwing exceptions. + // + bool + execute (); + + private: + insert_statement (const insert_statement&); + insert_statement& operator= (const insert_statement&); + + private: + binding& param_; + binding* returning_; + }; + + class LIBODB_SQLITE_EXPORT update_statement: public statement + { + public: + update_statement (connection_type& conn, + const std::string& text, + bool process_text, + binding& param); + + update_statement (connection_type& conn, + const char* text, + bool process_text, + binding& param); + + unsigned long long + execute (); + + private: + update_statement (const update_statement&); + update_statement& operator= (const update_statement&); + + private: + binding& param_; + }; + + class LIBODB_SQLITE_EXPORT delete_statement: public statement + { + public: + delete_statement (connection_type& conn, + const std::string& text, + binding& param); + + delete_statement (connection_type& conn, + const char* text, + binding& param); + + unsigned long long + execute (); + + private: + delete_statement (const delete_statement&); + delete_statement& operator= (const delete_statement&); + + private: + binding& param_; + }; + } +} + +#include + +#endif // ODB_SQLITE_STATEMENT_HXX -- cgit v1.1