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