// file : odb/sqlite/statement.hxx // copyright : Copyright (c) 2005-2015 Code Synthesis Tools CC // 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 LIBODB_SQLITE_EXPORT 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