• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
GetTfErrorCode(int code)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>
PrintfStatus(int rc,const char * fmt,Args &&...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 
PrepareRawOrDie(sqlite3 * db,const char * sql)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 
SetPragma(Sqlite * db,const char * pragma,const StringPiece & value)84 Status SetPragma(Sqlite* db, const char* pragma, const StringPiece& value) {
85   if (value.empty()) return OkStatus();
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 
GetEnv(const char * var)99 const StringPiece GetEnv(const char* var) {
100   const char* val = std::getenv(var);
101   return (val == nullptr) ? StringPiece() : StringPiece(val);
102 }
103 
EnvPragma(Sqlite * db,const char * pragma,const char * var)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 OkStatus();
108 }
109 
110 }  // namespace
111 
112 /* static */
Open(const string & path,int flags,Sqlite ** db)113 Status Sqlite::Open(const string& path, int flags, Sqlite** db) {
114   flags |= SQLITE_OPEN_PRIVATECACHE;
115   flags |= SQLITE_OPEN_URI;
116   sqlite3* sqlite = nullptr;
117   int rc = sqlite3_open_v2(path.c_str(), &sqlite, flags, nullptr);
118   if (rc != SQLITE_OK) {
119     *db = nullptr;
120     return PrintfStatus(rc, "Sqlite::Open(%s) failed: %s", path.c_str(),
121                         sqlite3_errstr(rc));
122   }
123   CHECK_EQ(SQLITE_OK, sqlite3_extended_result_codes(sqlite, 1));
124   CHECK_EQ(SQLITE_OK, sqlite3_snapfn_init(sqlite, nullptr, nullptr));
125   // Prepare these tiny privileged statements for SqliteTransaction
126   // so it can do less work, particularly in its constructor, per
127   // Google C++ Style.
128   sqlite3_stmt* begin = PrepareRawOrDie(sqlite, "BEGIN");
129   sqlite3_stmt* commit = PrepareRawOrDie(sqlite, "COMMIT");
130   sqlite3_stmt* rollback = PrepareRawOrDie(sqlite, "ROLLBACK");
131   *db = new Sqlite(sqlite, begin, commit, rollback);
132   Status s = OkStatus();
133   // Up until 2016 the default SQLite page_size was 1024. This ensures
134   // the new default regardless of linkage unless configured otherwise.
135   s.Update(SetPragma(*db, "page_size", "4096"));
136   // TensorFlow is designed to work well in all SQLite modes. However
137   // users might find tuning some these pragmas rewarding, depending on
138   // various considerations. Pragmas are set on a best-effort basis and
139   // might be ignored.
140   s.Update(EnvPragma(*db, "secure_delete", "TF_SQLITE_SECURE_DELETE"));
141   s.Update(EnvPragma(*db, "page_size", "TF_SQLITE_PAGE_SIZE"));
142   s.Update(EnvPragma(*db, "journal_mode", "TF_SQLITE_JOURNAL_MODE"));
143   s.Update(EnvPragma(*db, "synchronous", "TF_SQLITE_SYNCHRONOUS"));
144   s.Update(EnvPragma(*db, "mmap_size", "TF_SQLITE_MMAP_SIZE"));
145   s.Update(EnvPragma(*db, "locking_mode", "TF_SQLITE_LOCKING_MODE"));
146   s.Update(EnvPragma(*db, "cache_size", "TF_SQLITE_CACHE_SIZE"));
147   s.Update(EnvPragma(*db, "auto_vacuum", "TF_SQLITE_AUTO_VACUUM"));
148   DCHECK((*db)->RefCountIsOne());
149   if (!s.ok()) {
150     (*db)->Unref();
151     *db = nullptr;
152   }
153   return s;
154 }
155 
~Sqlite()156 Sqlite::~Sqlite() {
157   sqlite3_finalize(rollback_);
158   sqlite3_finalize(commit_);
159   sqlite3_finalize(begin_);
160   CHECK_EQ(SQLITE_OK, sqlite3_close(db_));
161 }
162 
Prepare(const StringPiece & sql,SqliteStatement * stmt)163 Status Sqlite::Prepare(const StringPiece& sql, SqliteStatement* stmt) {
164   SqliteLock lock(*this);
165   sqlite3_stmt* ps = nullptr;
166   int rc = sqlite3_prepare_v2(db_, sql.data(), static_cast<int>(sql.size()),
167                               &ps, nullptr);
168   if (rc != SQLITE_OK) {
169     *stmt = SqliteStatement();
170     return PrintfStatus(rc, "Prepare() failed: [%d] %s: %.*s", rc, errmsg(),
171                         sql.size(), sql.data());
172   }
173   *stmt = SqliteStatement(this, ps);
174   return OkStatus();
175 }
176 
Step(bool * is_done)177 Status SqliteStatement::Step(bool* is_done) {
178   DCHECK(stmt_ != nullptr);
179   if (TF_PREDICT_FALSE(bind_error_ != SQLITE_OK)) {
180     *is_done = true;
181     return PrintfStatus(bind_error_, "Bind(%d) failed: %s: %s",
182                         bind_error_parameter_, sqlite3_errstr(bind_error_),
183                         sql());
184   }
185   SqliteLock lock(*db_);
186   int rc = sqlite3_step(stmt_);
187   switch (rc) {
188     case SQLITE_ROW:
189       *is_done = false;
190       return OkStatus();
191     case SQLITE_DONE:
192       *is_done = true;
193       return OkStatus();
194     default:
195       *is_done = true;
196       return PrintfStatus(rc, "Step() failed: [%d] %s: %s", rc, db_->errmsg(),
197                           sql());
198   }
199 }
200 
StepOrDie()201 bool SqliteStatement::StepOrDie() {
202   bool is_done;
203   TF_CHECK_OK(Step(&is_done));
204   return !is_done;
205 }
206 
StepOnce()207 Status SqliteStatement::StepOnce() {
208   bool is_done;
209   TF_RETURN_IF_ERROR(Step(&is_done));
210   if (TF_PREDICT_FALSE(is_done)) {
211     return errors::Internal("No rows returned: ", sql());
212   }
213   return OkStatus();
214 }
215 
StepOnceOrDie()216 const SqliteStatement& SqliteStatement::StepOnceOrDie() {
217   TF_CHECK_OK(StepOnce());
218   return *this;
219 }
220 
StepAndReset()221 Status SqliteStatement::StepAndReset() {
222   bool is_done;
223   Status s = Step(&is_done);
224   if (TF_PREDICT_FALSE(s.ok() && !is_done)) {
225     s = errors::Internal("Unexpected row: ", sql());
226   }
227   Reset();
228   return s;
229 }
230 
StepAndResetOrDie()231 void SqliteStatement::StepAndResetOrDie() { TF_CHECK_OK(StepAndReset()); }
232 
Reset()233 void SqliteStatement::Reset() {
234   if (TF_PREDICT_TRUE(stmt_ != nullptr)) {
235     sqlite3_reset(stmt_);
236     sqlite3_clear_bindings(stmt_);
237   }
238   bind_error_ = SQLITE_OK;
239   size_ = 0;
240 }
241 
SqliteTransaction(Sqlite & db)242 SqliteTransaction::SqliteTransaction(Sqlite& db) : db_(&db) {
243   sqlite3_mutex_enter(sqlite3_db_mutex(db_->db_));
244   CHECK(!db_->is_in_transaction_);
245   db_->is_in_transaction_ = true;
246   Begin();
247 }
248 
~SqliteTransaction()249 SqliteTransaction::~SqliteTransaction() {
250   // Rollback should only return an error if there's no transaction.
251   // Since the API performs auto-rollbacks in some cases, we ignore.
252   sqlite3_step(db_->rollback_);
253   sqlite3_reset(db_->rollback_);
254   sqlite3_reset(db_->begin_);
255   db_->is_in_transaction_ = false;
256   sqlite3_mutex_leave(sqlite3_db_mutex(db_->db_));
257 }
258 
Begin()259 void SqliteTransaction::Begin() {
260   // This shouldn't allocate memory or perform I/O. All it does is
261   // execute OP_AutoCommit(0, 0) a.k.a. BEGIN DEFERRED which flips
262   // the sqlite3::autoCommit bit.
263   if (sqlite3_step(db_->begin_) != SQLITE_DONE) {
264     // It shouldn't be possible for this to fail since we already
265     // performed the reentrancy check.
266     LOG(FATAL) << "BEGIN failed: " << sqlite3_errmsg(db_->db_);
267   }
268 }
269 
Commit()270 Status SqliteTransaction::Commit() {
271   int rc = sqlite3_step(db_->commit_);
272   if (rc != SQLITE_DONE) {
273     return PrintfStatus(rc, "COMMIT failed: [%d] %s", rc,
274                         sqlite3_errmsg(db_->db_));
275   }
276   sqlite3_reset(db_->commit_);
277   sqlite3_reset(db_->begin_);
278   Begin();
279   return OkStatus();
280 }
281 
282 }  // namespace tensorflow
283