123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637 |
- // SQLite Database
- #include "db/db_sqlite3.h"
- #include <assert.h>
- static const char kNULL[] = "\0\0\0";
- namespace ndb
- {
-
- //////////////////////////////////////////////////////////////////////////////
- // SQLiteDB
- SQLiteDB::SQLiteDB()
- {
- sqlite3_ = NULL;
- }
-
- SQLiteDB::SQLiteDB(SQLiteDB& src)
- {
- sqlite3_ = src.sqlite3_;
- src.sqlite3_ = NULL;
- }
-
- SQLiteDB::~SQLiteDB()
- {
- Interrupt();
- Close();
- }
-
- SQLiteDB& SQLiteDB::operator=(SQLiteDB& src)
- {
- Interrupt();
- Close();
-
- sqlite3_ = src.sqlite3_;
- src.sqlite3_ = NULL;
- return *this;
- }
-
- bool SQLiteDB::Open(int flags)
- {
- return Open(":memory:", "", flags);
- }
- bool SQLiteDB::Open(const char* filename,
- const std::string &key,
- int flags/* = modeReadWrite|modeCreate|modeSerialized*/)
- {
- Interrupt();
- Close();
-
- if (filename == NULL)
- return false;
-
- int r = sqlite3_open_v2(filename, &sqlite3_, flags, NULL);
- if (r != SQLITE_OK)
- {
- Close();
- }
- else
- {
- if (key.length())
- {
- if( SQLITE_OK != sqlite3_key(sqlite3_,key.c_str(),(int)key.length()))
- r = sqlite3_rekey(sqlite3_,key.c_str(),(int)key.length());
- }
- }
-
-
- return r == SQLITE_OK;
- }
- bool SQLiteDB::Close()
- {
- if (sqlite3_ == NULL)
- return true;
-
- /*
- * If sqlite3_close() is called on a database connection that still has
- * outstanding prepared statements or BLOB handles, then it returns SQLITE_BUSY
- */
- if (SQLITE_OK != sqlite3_close(sqlite3_))
- return false;
-
- sqlite3_ = NULL;
- return true;
- }
-
- bool SQLiteDB::Compact()
- {
- if (SQLITE_OK != Query("VACUUM"))
- return false;
-
- return true;
- }
-
- bool SQLiteDB::IsValid() const
- {
- return sqlite3_ != NULL;
- }
-
- int SQLiteDB::GetLastErrorCode() const
- {
- if (sqlite3_ == NULL)
- return SQLITE_OK;
- return sqlite3_errcode(sqlite3_);
- }
-
- int SQLiteDB::GetLastExtendedErrorCode() const
- {
- if (sqlite3_ == NULL)
- return SQLITE_OK;
- return sqlite3_extended_errcode(sqlite3_);
- }
-
- const char* SQLiteDB::GetLastErrorMessage() const
- {
- assert(sqlite3_);
- if (sqlite3_ == NULL)
- return kNULL;
- return sqlite3_errmsg(sqlite3_);
- }
-
- int SQLiteDB::GetChanges() const
- {
- assert(sqlite3_);
- if (sqlite3_ == NULL)
- return -1;
- return sqlite3_changes(sqlite3_);
- }
-
- int SQLiteDB::GetTotalChanges() const
- {
- assert(sqlite3_);
- if (sqlite3_ == NULL)
- return -1;
- return sqlite3_total_changes(sqlite3_);
- }
- bool SQLiteDB::DoesTableExist(const char* table_name) const
- {
- return DoesTableOrIndexExist(table_name, "table");
- }
- bool SQLiteDB::DoesIndexExist(const char* index_name) const
- {
- return DoesTableOrIndexExist(index_name, "index");
- }
- bool SQLiteDB::DoesTableOrIndexExist(
- const char* name, const char* type) const
- {
- SQLiteStatement stat;
- Query(stat, "SELECT name FROM sqlite_master WHERE type=? AND name=?");
- if (!stat.IsValid())
- return false;
- // Bind is 1 based
- stat.BindText(1, type);
- stat.BindText(2, name);
- return stat.NextRow() == SQLITE_ROW;
- }
- bool SQLiteDB::DoesColumnExist(
- const char* table_name, const char* column_name) const
- {
- std::string sql("PRAGMA TABLE_INFO(");
- sql.append(table_name);
- sql.append(")");
- SQLiteStatement stat;
- Query(stat, sql.c_str(), (int)sql.size());
- if (!stat.IsValid())
- return false;
- while (stat.NextRow() == SQLITE_ROW) {
- if (!strcmp(stat.GetTextField(1), column_name))
- return true;
- }
- return false;
- }
-
- sqlite3_int64 SQLiteDB::GetLastInsertRowId() const
- {
- assert(sqlite3_);
- if (sqlite3_ == NULL)
- return -1;
- return sqlite3_last_insert_rowid(sqlite3_);
- }
-
- int SQLiteDB::Query(SQLiteStatement& statement, const char* sql_text, int length) const
- {
- statement.Finalize();
-
- if (!sqlite3_ || !sql_text)
- return SQLITE_MISUSE;
-
- /*
- * SQLite documents say:
- * If the caller knows that the supplied string is nul-terminated,
- * then there is a small performance advantage to be gained by passing an nByte parameter
- * that is equal to the number of bytes in the input string including the nul-terminator bytes.
- */
- if (length < 0)
- length = (int)strlen(sql_text) + 1;
-
- return sqlite3_prepare_v2(sqlite3_, sql_text, length, &statement.stmt_, NULL);
- }
-
- int SQLiteDB::Query(const char* sql_text, SQLiteQueryDelegate delegate, void* param) const
- {
- if (!sqlite3_ || !sql_text)
- return SQLITE_MISUSE;
- return sqlite3_exec(sqlite3_, sql_text, delegate, param, NULL);
- }
-
- int SQLiteDB::Query(const char* sql_text, SQLiteResultTable& table) const
- {
- if (!sqlite3_ || !sql_text)
- return SQLITE_MISUSE;
- // 先清空结果表
- table.Free();
- int r = sqlite3_get_table(sqlite3_, sql_text,
- &table.result_column_, &table.row_, &table.col_, NULL);
- if (r == SQLITE_OK)
- table.result_ = table.result_column_ + table.col_;
- return r;
- }
-
- void SQLiteDB::Interrupt()
- {
- if (!sqlite3_)
- return;
- sqlite3_interrupt(sqlite3_);
- }
-
- int SQLiteDB::SetBusyTimeout(int ms)
- {
- if (!sqlite3_)
- return SQLITE_MISUSE;
- return sqlite3_busy_timeout(sqlite3_, ms);
- }
-
- int SQLiteDB::GetVersion()
- {
- return sqlite3_libversion_number();
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
- // SQLiteResultTable
- SQLiteResultTable::SQLiteResultTable()
- {
- Reset();
- }
- SQLiteResultTable::SQLiteResultTable(SQLiteResultTable& src)
- {
- row_ = src.row_;
- col_ = src.col_;
- result_ = src.result_;
- result_column_ = src.result_column_;
-
- src.Reset();
- }
- SQLiteResultTable::~SQLiteResultTable()
- {
- Free();
- }
- SQLiteResultTable& SQLiteResultTable::operator=(SQLiteResultTable& src)
- {
- row_ = src.row_;
- col_ = src.col_;
- result_ = src.result_;
- result_column_ = src.result_column_;
-
- src.Reset();
-
- return *this;
- }
- void SQLiteResultTable::Free()
- {
- if (result_column_ != NULL)
- {
- sqlite3_free_table(result_column_);
- Reset();
- }
- }
- void SQLiteResultTable::Reset()
- {
- row_ = 0;
- col_ = 0;
- result_ = NULL;
- result_column_ = NULL;
- }
-
- bool SQLiteResultTable::IsEmpty() const
- {
- return result_column_ == 0;
- }
- int SQLiteResultTable::GetRowCount() const
- {
- return row_;
- }
- int SQLiteResultTable::GetColumnCount() const
- {
- return col_;
- }
-
- const char* SQLiteResultTable::GetValue(int row, int col) const
- {
- if (!result_ || row >= row_ ||
- col >= col_ || row < 0 || col < 0)
- {
- return 0;
- }
-
- return result_[row * col_ + col];
- }
- const char** const SQLiteResultTable::operator[](int row) const
- {
- // 为了效率,这里不检查越界,就像STL那样
- return (const char**)result_ + row * col_;
- }
-
- const char* SQLiteResultTable::GetColumnName(int col) const
- {
- if (!result_column_ || col < 0 || col >= col_)
- return 0;
-
- return result_column_[col];
- }
-
-
- //////////////////////////////////////////////////////////////////////////////
- // SQLiteStatement
- SQLiteStatement::SQLiteStatement()
- {
- stmt_ = NULL;
- eof_ = true;
- }
-
- SQLiteStatement::SQLiteStatement(SQLiteStatement& src)
- {
- stmt_ = src.stmt_;
- eof_ = src.eof_;
- src.stmt_ = NULL;
- src.eof_ = true;
- }
-
- SQLiteStatement::~SQLiteStatement()
- {
- Finalize();
- }
-
- SQLiteStatement& SQLiteStatement::operator=(SQLiteStatement& src)
- {
- Finalize();
-
- stmt_ = src.stmt_;
- eof_ = src.eof_;
- src.stmt_ = NULL;
- src.eof_ = true;
-
- return *this;
- }
-
- int SQLiteStatement::Finalize()
- {
- int r = SQLITE_OK;
- if (stmt_ != NULL)
- {
- r = sqlite3_finalize(stmt_);
- if (r == SQLITE_OK)
- {
- stmt_ = NULL;
- eof_ = true;
- }
- }
- return r;
- }
-
- int SQLiteStatement::Rewind()
- {
- int r = SQLITE_MISUSE;
- if (stmt_ != NULL)
- {
- r = sqlite3_reset(stmt_);
- if (SQLITE_OK == r)
- {
- eof_ = false;
- return SQLITE_OK;
- }
- }
- return r;
- }
-
- int SQLiteStatement::NextRow()
- {
- if (stmt_ == NULL)
- return SQLITE_MISUSE;
-
- int r = sqlite3_step(stmt_);
-
- if (r == SQLITE_DONE)
- eof_ = true;
-
- return r;
- }
-
- bool SQLiteStatement::IsEof()
- {
- return eof_;
- }
-
- bool SQLiteStatement::IsNullField(int col)
- {
- return GetFieldValue(col) != NULL;
- }
-
- const void* SQLiteStatement::GetBlobField(int col)
- {
- if (stmt_ == NULL)
- return NULL;
- return sqlite3_column_blob(stmt_, col);
- }
-
- int SQLiteStatement::GetBytesField(int col)
- {
- if (stmt_ == NULL)
- return 0;
- return sqlite3_column_bytes(stmt_, col);
- }
-
- int SQLiteStatement::GetBytes16Field(int col)
- {
- if (stmt_ == NULL)
- return 0;
- return sqlite3_column_bytes16(stmt_, col);
- }
-
- double SQLiteStatement::GetDoubleField(int col)
- {
- if (stmt_ == NULL)
- return 0.0;
- return sqlite3_column_double(stmt_, col);
- }
-
- int SQLiteStatement::GetIntField(int col)
- {
- if (stmt_ == NULL)
- return 0;
- return sqlite3_column_int(stmt_, col);
- }
-
- sqlite3_int64 SQLiteStatement::GetInt64Field(int col)
- {
- if (stmt_ == NULL)
- return 0;
- return sqlite3_column_int64(stmt_, col);
- }
-
- const char* SQLiteStatement::GetTextField(int col)
- {
- if (stmt_ == NULL)
- return NULL;
- return (const char*)sqlite3_column_text(stmt_, col);
- }
-
- const void* SQLiteStatement::GetText16Field(int col)
- {
- if (stmt_ == NULL)
- return NULL;
- return sqlite3_column_text16(stmt_, col);
- }
-
- int SQLiteStatement::GetTypeField(int col)
- {
- if (stmt_ == NULL)
- return 0;
- return sqlite3_column_type(stmt_, col);
- }
-
- sqlite3_value* SQLiteStatement::GetFieldValue(int col)
- {
- if (stmt_ == NULL)
- return NULL;
- return sqlite3_column_value(stmt_, col);
- }
-
- int SQLiteStatement::GetFieldBytes(int col)
- {
- if (stmt_ == NULL)
- return 0;
- return sqlite3_column_bytes(stmt_, col);
- }
-
- int SQLiteStatement::GetFieldBytes16(int col)
- {
- if (stmt_ == NULL)
- return 0;
- return sqlite3_column_bytes16(stmt_, col);
- }
-
- int SQLiteStatement::BindBlob(int index, const void* data, int size_in_bytes)
- {
- if (stmt_ != NULL)
- return sqlite3_bind_blob(stmt_, index, data, size_in_bytes, SQLITE_STATIC);
- return SQLITE_MISUSE;
- }
-
- int SQLiteStatement::BindDouble(int index, double data)
- {
- if (stmt_ != NULL)
- return sqlite3_bind_double(stmt_, index, data);
- return SQLITE_MISUSE;
- }
-
- int SQLiteStatement::BindInt(int index, int data)
- {
- if (stmt_ != NULL)
- return sqlite3_bind_int(stmt_, index, data);
- return SQLITE_MISUSE;
- }
-
- int SQLiteStatement::BindInt64(int index, int64_t data)
- {
- if (stmt_ != NULL)
- return sqlite3_bind_int64(stmt_, index, data);
- return SQLITE_MISUSE;
- }
-
- int SQLiteStatement::BindNull(int index)
- {
- if (stmt_ != NULL)
- return sqlite3_bind_null(stmt_, index);
- return SQLITE_MISUSE;
- }
- int SQLiteStatement::BindText(int index, const char* data)
- {
- return BindText(index, data, (int)strlen(data));
- }
-
- int SQLiteStatement::BindText(int index, const char* data, int size_in_bytes)
- {
- if (stmt_ != NULL)
- return sqlite3_bind_text(stmt_, index, data, size_in_bytes, SQLITE_STATIC);
- return SQLITE_MISUSE;
- }
- int SQLiteStatement::BindText16(int index, const wchar_t* data)
- {
- return BindText16(index, data, (int)wcslen(data) * sizeof(wchar_t));
- }
- int SQLiteStatement::BindText16(int index, const wchar_t* data, int size_in_bytes)
- {
- if (stmt_ != NULL)
- return sqlite3_bind_text16(stmt_, index, data, size_in_bytes, SQLITE_STATIC);
- return SQLITE_MISUSE;
- }
- int SQLiteStatement::BindValue(int index, const sqlite3_value* data)
- {
- if (stmt_ != NULL && data != NULL)
- return sqlite3_bind_value(stmt_, index, data);
- return SQLITE_MISUSE;
- }
- int SQLiteStatement::BindZeroBlob(int index, int size)
- {
- if (stmt_ != NULL)
- return sqlite3_bind_zeroblob(stmt_, index, size);
- return SQLITE_MISUSE;
- }
- //////////////////////////////////////////////////////////////////////////////
- // SQLiteAutoTransaction
- SQLiteAutoTransaction::SQLiteAutoTransaction(SQLiteDB* db)
- : db_(db), need_commit_(false)
- {
- Begin();
- }
-
- SQLiteAutoTransaction::~SQLiteAutoTransaction()
- {
- if (need_commit_)
- Commit();
- }
-
- bool SQLiteAutoTransaction::Begin()
- {
- bool result = false;
- if (db_ && !need_commit_)
- {
- if (db_->Query("BEGIN") == SQLITE_OK)
- result = true;
- need_commit_ = true;
- }
- return result;
- }
- bool SQLiteAutoTransaction::Commit()
- {
- bool result = 0;
- if (db_ != NULL)
- {
- if (db_->Query("END") == SQLITE_OK)
- result = true;
- need_commit_ = false;
- }
- return result;
- }
- bool SQLiteAutoTransaction::Rollback()
- {
- bool result = false;
- if (db_ != NULL)
- {
- if (db_->Query("ROLLBACK") == SQLITE_OK)
- result = true;
- need_commit_ = false;
- }
- return result;
- }
- } // namespace ndb
|