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