Home | History | Annotate | Download | only in db
      1 /* Copyright 2017 The TensorFlow Authors. All Rights Reserved.
      2 
      3 Licensed under the Apache License, Version 2.0 (the "License");
      4 you may not use this file except in compliance with the License.
      5 You may obtain a copy of the License at
      6 
      7     http://www.apache.org/licenses/LICENSE-2.0
      8 
      9 Unless required by applicable law or agreed to in writing, software
     10 distributed under the License is distributed on an "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 See the License for the specific language governing permissions and
     13 limitations under the License.
     14 ==============================================================================*/
     15 #include "tensorflow/core/lib/db/sqlite.h"
     16 
     17 #include "tensorflow/core/lib/core/errors.h"
     18 #include "tensorflow/core/lib/strings/stringprintf.h"
     19 
     20 extern "C" int sqlite3_snapfn_init(sqlite3*, const char**, const void*);
     21 
     22 namespace tensorflow {
     23 namespace {
     24 
     25 error::Code GetTfErrorCode(int code) {
     26   // See: https://sqlite.org/rescode.html
     27   switch (code & 0xff) {
     28     case SQLITE_OK:    // Successful result
     29     case SQLITE_ROW:   // Step has another row ready
     30     case SQLITE_DONE:  // Step has finished executing
     31       return error::OK;
     32     case SQLITE_ABORT:  // Callback routine requested an abort
     33       return error::ABORTED;
     34     case SQLITE_READONLY:  // Attempt to write a readonly database
     35     case SQLITE_MISMATCH:  // Data type mismatch
     36       return error::FAILED_PRECONDITION;
     37     case SQLITE_MISUSE:    // Library used incorrectly
     38     case SQLITE_INTERNAL:  // Internal logic error in SQLite
     39       return error::INTERNAL;
     40     case SQLITE_RANGE:  // 2nd parameter to sqlite3_bind out of range
     41       return error::OUT_OF_RANGE;
     42     case SQLITE_CANTOPEN:    // Unable to open the database file
     43     case SQLITE_CONSTRAINT:  // Abort due to constraint violation
     44     case SQLITE_NOTFOUND:    // Unknown opcode or statement parameter name
     45     case SQLITE_NOTADB:      // File opened that is not a database file
     46       return error::INVALID_ARGUMENT;
     47     case SQLITE_CORRUPT:  // The database disk image is malformed
     48       return error::DATA_LOSS;
     49     case SQLITE_AUTH:  // Authorization denied
     50     case SQLITE_PERM:  // Access permission denied
     51       return error::PERMISSION_DENIED;
     52     case SQLITE_FULL:    // Insertion failed because database is full
     53     case SQLITE_TOOBIG:  // String or BLOB exceeds size limit
     54     case SQLITE_NOLFS:   // Uses OS features not supported on host
     55       return error::RESOURCE_EXHAUSTED;
     56     case SQLITE_BUSY:      // The database file is locked
     57     case SQLITE_LOCKED:    // A table in the database is locked
     58     case SQLITE_PROTOCOL:  // Database lock protocol error
     59     case SQLITE_NOMEM:     // Out of heap or perhaps lookaside memory
     60       return error::UNAVAILABLE;
     61     case SQLITE_INTERRUPT:  // Operation terminated by sqlite3_interrupt
     62       return error::CANCELLED;
     63     case SQLITE_ERROR:   // SQL error or missing database
     64     case SQLITE_IOERR:   // Some kind of disk I/O error occurred
     65     case SQLITE_SCHEMA:  // The database schema changed
     66     default:
     67       return error::UNKNOWN;
     68   }
     69 }
     70 
     71 template <typename... Args>
     72 Status PrintfStatus(int rc, const char* fmt, Args&&... args) {
     73   return {GetTfErrorCode(rc),
     74           strings::Printf(fmt, std::forward<Args>(args)...)};
     75 }
     76 
     77 sqlite3_stmt* PrepareRawOrDie(sqlite3* db, const char* sql) {
     78   sqlite3_stmt* stmt = nullptr;
     79   int rc = sqlite3_prepare_v2(db, sql, -1, &stmt, nullptr);
     80   CHECK_EQ(SQLITE_OK, rc) << sql;
     81   return stmt;
     82 }
     83 
     84 Status SetPragma(Sqlite* db, const char* pragma, const StringPiece& value) {
     85   if (value.empty()) return Status::OK();
     86   for (auto p = value.begin(); p < value.end(); ++p) {
     87     if (!(('0' <= *p && *p <= '9') || ('A' <= *p && *p <= 'Z') ||
     88           ('a' <= *p && *p <= 'z') || *p == '-')) {
     89       return errors::InvalidArgument("Illegal pragma character");
     90     }
     91   }
     92   SqliteStatement stmt;
     93   TF_RETURN_IF_ERROR(  // We can't use Bind*() pragma statements.
     94       db->Prepare(strings::StrCat("PRAGMA ", pragma, "=", value), &stmt));
     95   bool unused_done;
     96   return stmt.Step(&unused_done);
     97 }
     98 
     99 const StringPiece GetEnv(const char* var) {
    100   const char* val = std::getenv(var);
    101   return (val == nullptr) ? StringPiece() : StringPiece(val);
    102 }
    103 
    104 Status EnvPragma(Sqlite* db, const char* pragma, const char* var) {
    105   TF_RETURN_WITH_CONTEXT_IF_ERROR(SetPragma(db, pragma, GetEnv(var)), "getenv(",
    106                                   var, ")");
    107   return Status::OK();
    108 }
    109 
    110 }  // namespace
    111 
    112 /* static */
    113 Status Sqlite::Open(const string& path, int flags, Sqlite** db) {
    114   flags |= SQLITE_OPEN_PRIVATECACHE;
    115   sqlite3* sqlite = nullptr;
    116   int rc = sqlite3_open_v2(path.c_str(), &sqlite, flags, nullptr);
    117   if (rc != SQLITE_OK) {
    118     *db = nullptr;
    119     return PrintfStatus(rc, "Sqlite::Open(%s) failed: %s", path.c_str(),
    120                         sqlite3_errstr(rc));
    121   }
    122   CHECK_EQ(SQLITE_OK, sqlite3_extended_result_codes(sqlite, 1));
    123   CHECK_EQ(SQLITE_OK, sqlite3_snapfn_init(sqlite, nullptr, nullptr));
    124   // Prepare these tiny privileged statements for SqliteTransaction
    125   // so it can do less work, particularly in its constructor, per
    126   // Google C++ Style.
    127   sqlite3_stmt* begin = PrepareRawOrDie(sqlite, "BEGIN");
    128   sqlite3_stmt* commit = PrepareRawOrDie(sqlite, "COMMIT");
    129   sqlite3_stmt* rollback = PrepareRawOrDie(sqlite, "ROLLBACK");
    130   *db = new Sqlite(sqlite, begin, commit, rollback);
    131   Status s = Status::OK();
    132   // Up until 2016 the default SQLite page_size was 1024. This ensures
    133   // the new default regardless of linkage unless configured otherwise.
    134   s.Update(SetPragma(*db, "page_size", "4096"));
    135   // TensorFlow is designed to work well in all SQLite modes. However
    136   // users might find tuning some these pragmas rewarding, depending on
    137   // various considerations. Pragmas are set on a best-effort basis and
    138   // might be ignored.
    139   s.Update(EnvPragma(*db, "secure_delete", "TF_SQLITE_SECURE_DELETE"));
    140   s.Update(EnvPragma(*db, "page_size", "TF_SQLITE_PAGE_SIZE"));
    141   s.Update(EnvPragma(*db, "journal_mode", "TF_SQLITE_JOURNAL_MODE"));
    142   s.Update(EnvPragma(*db, "synchronous", "TF_SQLITE_SYNCHRONOUS"));
    143   s.Update(EnvPragma(*db, "mmap_size", "TF_SQLITE_MMAP_SIZE"));
    144   s.Update(EnvPragma(*db, "locking_mode", "TF_SQLITE_LOCKING_MODE"));
    145   s.Update(EnvPragma(*db, "cache_size", "TF_SQLITE_CACHE_SIZE"));
    146   s.Update(EnvPragma(*db, "auto_vacuum", "TF_SQLITE_AUTO_VACUUM"));
    147   DCHECK((*db)->RefCountIsOne());
    148   if (!s.ok()) {
    149     (*db)->Unref();
    150     *db = nullptr;
    151   }
    152   return s;
    153 }
    154 
    155 Sqlite::~Sqlite() {
    156   sqlite3_finalize(rollback_);
    157   sqlite3_finalize(commit_);
    158   sqlite3_finalize(begin_);
    159   CHECK_EQ(SQLITE_OK, sqlite3_close(db_));
    160 }
    161 
    162 Status Sqlite::Prepare(const StringPiece& sql, SqliteStatement* stmt) {
    163   SqliteLock lock(*this);
    164   sqlite3_stmt* ps = nullptr;
    165   int rc = sqlite3_prepare_v2(db_, sql.data(), static_cast<int>(sql.size()),
    166                               &ps, nullptr);
    167   if (rc != SQLITE_OK) {
    168     *stmt = SqliteStatement();
    169     return PrintfStatus(rc, "Prepare() failed: [%d] %s: %.*s", rc, errmsg(),
    170                         sql.size(), sql.data());
    171   }
    172   *stmt = SqliteStatement(this, ps);
    173   return Status::OK();
    174 }
    175 
    176 Status SqliteStatement::Step(bool* is_done) {
    177   DCHECK(stmt_ != nullptr);
    178   if (TF_PREDICT_FALSE(bind_error_ != SQLITE_OK)) {
    179     *is_done = true;
    180     return PrintfStatus(bind_error_, "Bind(%d) failed: %s: %s",
    181                         bind_error_parameter_, sqlite3_errstr(bind_error_),
    182                         sql());
    183   }
    184   SqliteLock lock(*db_);
    185   int rc = sqlite3_step(stmt_);
    186   switch (rc) {
    187     case SQLITE_ROW:
    188       *is_done = false;
    189       return Status::OK();
    190     case SQLITE_DONE:
    191       *is_done = true;
    192       return Status::OK();
    193     default:
    194       *is_done = true;
    195       return PrintfStatus(rc, "Step() failed: [%d] %s: %s", rc, db_->errmsg(),
    196                           sql());
    197   }
    198 }
    199 
    200 bool SqliteStatement::StepOrDie() {
    201   bool is_done;
    202   TF_CHECK_OK(Step(&is_done));
    203   return !is_done;
    204 }
    205 
    206 Status SqliteStatement::StepOnce() {
    207   bool is_done;
    208   TF_RETURN_IF_ERROR(Step(&is_done));
    209   if (TF_PREDICT_FALSE(is_done)) {
    210     return errors::Internal("No rows returned: ", sql());
    211   }
    212   return Status::OK();
    213 }
    214 
    215 const SqliteStatement& SqliteStatement::StepOnceOrDie() {
    216   TF_CHECK_OK(StepOnce());
    217   return *this;
    218 }
    219 
    220 Status SqliteStatement::StepAndReset() {
    221   bool is_done;
    222   Status s = Step(&is_done);
    223   if (TF_PREDICT_FALSE(s.ok() && !is_done)) {
    224     s = errors::Internal("Unexpected row: ", sql());
    225   }
    226   Reset();
    227   return s;
    228 }
    229 
    230 void SqliteStatement::StepAndResetOrDie() { TF_CHECK_OK(StepAndReset()); }
    231 
    232 void SqliteStatement::Reset() {
    233   if (TF_PREDICT_TRUE(stmt_ != nullptr)) {
    234     sqlite3_reset(stmt_);
    235     sqlite3_clear_bindings(stmt_);
    236   }
    237   bind_error_ = SQLITE_OK;
    238   size_ = 0;
    239 }
    240 
    241 SqliteTransaction::SqliteTransaction(Sqlite& db) : db_(&db) {
    242   sqlite3_mutex_enter(sqlite3_db_mutex(db_->db_));
    243   CHECK(!db_->is_in_transaction_);
    244   db_->is_in_transaction_ = true;
    245   Begin();
    246 }
    247 
    248 SqliteTransaction::~SqliteTransaction() {
    249   // Rollback should only return an error if there's no transaction.
    250   // Since the API performs auto-rollbacks in some cases, we ignore.
    251   sqlite3_step(db_->rollback_);
    252   sqlite3_reset(db_->rollback_);
    253   sqlite3_reset(db_->begin_);
    254   db_->is_in_transaction_ = false;
    255   sqlite3_mutex_leave(sqlite3_db_mutex(db_->db_));
    256 }
    257 
    258 void SqliteTransaction::Begin() {
    259   // This shouldn't allocate memory or perform I/O. All it does is
    260   // execute OP_AutoCommit(0, 0) a.k.a. BEGIN DEFERRED which flips
    261   // the sqlite3::autoCommit bit.
    262   if (sqlite3_step(db_->begin_) != SQLITE_DONE) {
    263     // It shouldn't be possible for this to fail since we already
    264     // performed the reentrancy check.
    265     LOG(FATAL) << "BEGIN failed: " << sqlite3_errmsg(db_->db_);
    266   }
    267 }
    268 
    269 Status SqliteTransaction::Commit() {
    270   int rc = sqlite3_step(db_->commit_);
    271   if (rc != SQLITE_DONE) {
    272     return PrintfStatus(rc, "COMMIT failed: [%d] %s", rc,
    273                         sqlite3_errmsg(db_->db_));
    274   }
    275   sqlite3_reset(db_->commit_);
    276   sqlite3_reset(db_->begin_);
    277   Begin();
    278   return Status::OK();
    279 }
    280 
    281 }  // namespace tensorflow
    282