Index: gears/database2/connection.h =================================================================== --- gears/database2/connection.h (revision 1754) +++ gears/database2/connection.h (working copy) @@ -26,51 +26,85 @@ #ifndef GEARS_DATABASE2_CONNECTION_H__ #define GEARS_DATABASE2_CONNECTION_H__ +#include + #include "gears/base/common/common.h" #include "gears/base/common/js_types.h" #include "gears/base/common/scoped_refptr.h" #include "gears/base/common/security_model.h" #include "gears/base/common/string16.h" +#include "gears/third_party/scoped_ptr/scoped_ptr.h" #include "gears/third_party/sqlite_google/preprocessed/sqlite3.h" -class Database2Values; +// used to store value-type pairs +struct Database2Variant { + Database2Variant() : type(JSPARAM_NULL) {} + ~Database2Variant() { + if (type == JSPARAM_STRING16) { delete string_value; } + } + JsParamType type; + union { + int int_value; + double double_value; + std::string16 *string_value; + }; +}; + +// Represents a consumer of results, produced by Connection::Execute method. +// Conceptually, it is a forward-only cursor over a result set. The cursor +// allows creating new rows and assigning the values in one row at a time. +// The proper execution sequence is: +// 1) Init -- to initialize the result set. This method can be only called once +// for a given instance. Re-initialization is not supported. +// 2) HandleNewRow -- to create a new row (no rows exist in a newly initialized +// result set. +// 3) HandleColumn* -- to set a value in a row. The index value must be between 0 and +// column_count, specified in the Init class Database2RowHandlerInterface { public: - Database2RowHandlerInterface() {}; - ~Database2RowHandlerInterface() {}; - - virtual void Begin() = 0; - // TODO(dimitri.glazkov): Add row data parameter(s) - virtual void HandleRow() = 0; - virtual void End() = 0; - - DISALLOW_EVIL_CONSTRUCTORS(Database2RowHandlerInterface); + // initialize the handler with an array of column names + // the method takes ownership of the array + virtual void Init(int column_count, std::string16 *column_names) = 0; + virtual void HandleNewRow() = 0; + virtual bool HandleColumnInt(int index, int value) = 0; + virtual bool HandleColumnDouble(int index, double value) = 0; + // The implementation must copy the string value argument. + virtual bool HandleColumnString(int index, const std::string16 &value) = 0; + virtual bool HandleColumnNull(int index) = 0; + virtual void HandleStats(int64 last_insert_rowid, int rows_affected) = 0; }; // Encapsulates database operations, opens and closes database connection class Database2Connection : public RefCounted { public: - // lazily initialized - Database2Connection(const std::string16 &name, - const SecurityOrigin &origin) : - name_(name), origin_(origin) {} + Database2Connection(const std::string16 &name, + const SecurityOrigin &origin) : + name_(name), origin_(origin), handle_(NULL), bogus_version_(false) {} ~Database2Connection() { - // close connection + if (handle_) { + sqlite3_close(handle_); + } } bool OpenAndVerifyVersion(const std::string16 &database_version); bool Execute(const std::string16 &statement, - Database2Values *arguments, + int num_arguments, + Database2Variant *arguments, Database2RowHandlerInterface *row_handler); bool Begin(); void Rollback(); bool Commit(); int error_code() const { return error_code_; } - std::string16 error_message() const { return error_message_; } + const std::string16 &error_message() const { return error_message_; } private: + // populates error code and error message fields using sqlite_wrapper helpers + // and if the sqlite3 returned SQLITE_CORRUPT code, poisons the database + void SetAndHandleError(int error_code, + const char16 *summary, + int sqlite_result_code); bool bogus_version_; int expected_version_; @@ -84,4 +118,38 @@ DISALLOW_EVIL_CONSTRUCTORS(Database2Connection); }; +// Used for marshaling of results from the database thread to the main thread. +// Implements a row handler that stores all of supplied data, and a CopyTo +// method to apply the data to another row handler. +class Database2BufferingRowHandler : public Database2RowHandlerInterface { + public: + Database2BufferingRowHandler() : column_count_(0) {} + ~Database2BufferingRowHandler() { + // remove all rows + for(unsigned int i = 0; i < rows_.size(); ++i) { + delete[] rows_[i]; + } + } + + // Database2RowHandlerInterface + virtual void Init(int column_count, std::string16 *column_names); + virtual void HandleNewRow(); + virtual bool HandleColumnInt(int index, int value); + virtual bool HandleColumnDouble(int index, double value); + virtual bool HandleColumnString(int index, const std::string16 &value); + virtual bool HandleColumnNull(int index); + virtual void HandleStats(int64 last_insert_rowid, int rows_affected); + + bool CopyTo(Database2RowHandlerInterface *target); + private: + + std::vector rows_; + scoped_array column_names_; + int rows_affected_; + int64 last_insert_rowid_; + int column_count_; + + DISALLOW_EVIL_CONSTRUCTORS(Database2BufferingRowHandler); +}; + #endif // GEARS_DATABASE2_CONNECTION_H__