[M108 Migration][HBBTV] Implement ewk_context_register_jsplugin_mime_types API
[platform/framework/web/chromium-efl.git] / sql / error_delegate_util.cc
1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "sql/error_delegate_util.h"
6
7 #include <ostream>  // Needed to compile NOTREACHED() with operator <<.
8 #include <string>
9
10 #include "base/files/file_path.h"
11 #include "base/notreached.h"
12 #include "third_party/sqlite/sqlite3.h"
13
14 namespace sql {
15
16 bool IsErrorCatastrophic(int sqlite_error_code) {
17   // SQLite result codes are documented at https://www.sqlite.org/rescode.html
18   int primary_error_code = sqlite_error_code & 0xff;
19
20   // Within each group, error codes are sorted by their numerical values. This
21   // matches the order used by the SQLite documentation describing them.
22   switch (primary_error_code) {
23     // Group of error codes that should never be returned by SQLite.
24     //
25     // If we do get these, our database schema / query pattern / data managed to
26     // trigger a bug in SQLite. In development, we DCHECK to flag this SQLite
27     // bug. In production, we [[fallback]] to corruption handling, because the
28     // bug may be persistent, and corruption recovery will get the user unstuck.
29     case SQLITE_INTERNAL:  // Bug in SQLite.
30     case SQLITE_EMPTY:     // Marked for SQLite internal use.
31     case SQLITE_FORMAT:    // Not currently used, according to SQLite docs.
32     case SQLITE_NOTICE:    // Only used as an argument to sqlite3_log().
33     case SQLITE_WARNING:   // Only used as an argument to sqlite3_log().
34       NOTREACHED() << "SQLite returned result code marked for internal use: "
35                    << sqlite_error_code;
36       [[fallthrough]];
37
38     // Group of error codes that may only be returned by SQLite (given Chrome's
39     // usage patterns) if a database is corrupted. DCHECK would not be
40     // appropriate, since these can occur in production. Silently [[fallback]]
41     // to corruption handling.
42     case SQLITE_ERROR:
43       // Generic/fallback error code.
44       //
45       // This error code is thrown when Chrome issues an invalid SQL statement.
46       // For instance, the SQL statement may reference a table or column which
47       // doesn't exist.
48       //
49       // This can happen in two scenarios:
50       //  1. There's a programmer error, and we have an outdated SQL statement
51       //     somewhere in the code.
52       //  2. The user's database got corrupted and the expected table or column
53       //     names are no longer there.
54       //
55       // TODO(https://crbug.com/1321483): In practice, we're logging a
56       // surprisingly lot of errors of this type, and the counts aren't going
57       // down, so there must be some instances of Case #1. Log and fix those
58       // cases, then turn this back to [[fallthrough]].
59       return false;
60     case SQLITE_PERM:
61       // Failed to get the requested access mode for a newly created database.
62       // The database was just created, so error recovery will not cause data
63       // loss. Error recovery steps, such as re-creating database files, may
64       // fix the permission problems.
65       [[fallthrough]];
66     case SQLITE_CORRUPT:
67       // Some form of database corruption was detected. The sql::Recovery code
68       // may be able to recover some of the data.
69       [[fallthrough]];
70     case SQLITE_CANTOPEN:
71       // Failed to open the database, for a variety of reasons. All the reasons
72       // come down to some form of corruption. Here are some known reasons:
73       // * One of the file names (database, journal, WAL, etc.) points to a
74       //   directory, not a file. This indicates filesystem corruption. Most
75       //   likely, some app messed with the user's Chrome file. It's also
76       //   possible that the inode was corrupted and the is_dir bit flipped.
77       // * One of the file names is a symlink, and SQLite was instructed not to
78       //   follow symlinks. This should not occur in Chrome, we let SQLite use
79       //   its default symlink handling.
80       // * The WAL file has a format version that SQLite can't understand. This
81       //   should not occur in Chrome, as we don't use WAL yet.
82       [[fallthrough]];
83     case SQLITE_MISMATCH:
84       // SQLite was forced to perform an operation that involves incompatible
85       // data types. An example is attempting to store a non-integer value in a
86       // ROWID primary key.
87       //
88       // In production, database corruption can lead to this. For example, it's
89       // possible that a schema is corrupted in such a way that the ROWID
90       // primary key column's name is swapped with another column's name.
91       [[fallthrough]];
92     case SQLITE_NOLFS:
93       // The database failed to grow past the filesystem size limit. This is
94       // unlikely to happen in Chrome, but it is theoretically possible.
95       [[fallthrough]];
96     case SQLITE_NOTADB:
97       // The database header is corrupted. The sql::Recovery code will not be
98       // able to recovery any data, as SQLite will refuse to open the database.
99       return true;
100
101     // Group of result codes that are not error codes. These should never make
102     // it to error handling code. In development, we DCHECK to flag this Chrome
103     // bug. In production, we hope this is a transient error, such as a race
104     // condition.
105     case SQLITE_OK:    // Most used success code.
106     case SQLITE_ROW:   // The statement produced a row of output.
107     case SQLITE_DONE:  // A step has completed in a multi-step operation.
108       NOTREACHED() << "Called with non-error result code " << sqlite_error_code;
109       [[fallthrough]];
110
111     // Group of error codes that should not be returned by SQLite given Chrome's
112     // usage patterns, even if the database gets corrupted. In development, we
113     // DCHECK to flag this Chrome bug. In production, we hope the errors have
114     // transient causes, such as race conditions.
115     case SQLITE_LOCKED:
116       // Conflict between two concurrently executing statements in the same
117       // database connection.
118       //
119       // In theory, SQLITE_LOCKED could also signal a conflict between different
120       // connections (in the same process) sharing a page cache, but Chrome only
121       // uses private page caches.
122       NOTREACHED() << "Conflict between concurrently executing SQL statements";
123       [[fallthrough]];
124     case SQLITE_NOMEM:
125       // Out of memory. This is most likely a transient error.
126       //
127       // There's a small chance that the error is caused by trying to exchange
128       // too much data with SQLite. Most such errors result in SQLITE_TOOBIG.
129       NOTREACHED() << "SQLite reported out-of-memory: " << sqlite_error_code;
130       [[fallthrough]];
131     case SQLITE_INTERRUPT:
132       // Chrome features don't use sqlite3_interrupt().
133       NOTREACHED() << "SQLite returned INTERRUPT code: " << sqlite_error_code;
134       [[fallthrough]];
135     case SQLITE_NOTFOUND:
136       // Unknown opcode in sqlite3_file_control(). Chrome's features only use a
137       // few built-in opcodes.
138       NOTREACHED() << "SQLite returned NOTFOUND code: " << sqlite_error_code;
139       [[fallthrough]];
140     case SQLITE_MISUSE:
141       // SQLite API misuse, such as trying to use a prepared statement after it
142       // was finalized. In development, we DCHECK to flag this Chrome bug. In
143       // production, we hope this is a race condition, and therefore transient.
144       NOTREACHED() << "SQLite returned MISUSE code: " << sqlite_error_code;
145       [[fallthrough]];
146     case SQLITE_AUTH:
147       // Chrome features don't install an authorizer callback. Only WebSQL does.
148       NOTREACHED() << "SQLite returned AUTH code: " << sqlite_error_code;
149       [[fallthrough]];
150     case SQLITE_RANGE:
151       // Chrome uses DCHECKs to ensure the validity of column indexes passed to
152       // sqlite3_bind() and sqlite3_column().
153       NOTREACHED() << "SQLite returned RANGE code: " << sqlite_error_code;
154       [[fallthrough]];
155
156     // Group of error codes that should may be returned by SQLite given Chrome's
157     // usage patterns, even without database corruption. In development, we
158     // DCHECK to flag this Chrome bug. In production, we hope the errors have
159     // transient causes, such as race conditions.
160     case SQLITE_ABORT:
161       // SQLITE_ABORT may be returned when a ROLLBACK statement is executed
162       // concurrently with a pending read or write, and Chrome features are
163       // allowed to execute concurrent statements in the same transaction, under
164       // some conditions.
165       //
166       // It may be worth noting that Chrome features don't use callback routines
167       // that may abort SQL statements, such as passing a callback to
168       // sqlite3_exec().
169       [[fallthrough]];
170     case SQLITE_BUSY:
171       // Failed to grab a lock on the database. Another database connection
172       // (most likely in another process) is holding the database lock. This
173       // should not be a problem for exclusive databases, which are strongly
174       // recommended for Chrome features.
175       [[fallthrough]];
176     case SQLITE_READONLY:
177       // SQLite either failed to write to the database file or its associated
178       // files (journal, WAL, etc.), or considers it unsafe to do so.
179       //
180       // Most error codes (SQLITE_READONLY_DIRECTORY, SQLITE_READONLY_RECOVERY,
181       // SQLITE_READONLY_ROLLBACK, SQLITE_READONLY_CANTLOCK) mean that SQLite
182       // failed to write to some file, or to create a file (which entails
183       // writing to the directory containing the database).
184       //
185       // SQLITE_READONLY_CANTLOCK should never happen in Chrome, because we will
186       // only allow enabling WAL on databases that use exclusive locking.
187       //
188       // Unlike all other codes, SQLITE_READONLY_DBMOVED signals that a file was
189       // deleted or renamed. It is returned when SQLite realizes that the
190       // database file was moved or unlinked from the filesystem after it was
191       // opened, so the associated files (journal, WAL, etc.) would not be found
192       // by another SQLite instance in the event of a crash. This was observed
193       // on the iOS try bots.
194       [[fallthrough]];
195     case SQLITE_IOERR:
196       // Catch-all for many errors reported by the VFS. Some of the errors
197       // indicate media failure (SQLITE_IOERR_READ), while others indicate
198       // transient problems (SQLITE_IOERR_LOCK). In the future, we may invest in
199       // distinguishing between them. For now, since all the codes are bundled
200       // up, we must assume that the error is transient.
201       [[fallthrough]];
202     case SQLITE_FULL:
203       // The disk is full. This is definitely a transient error, and does not
204       // indicate any database corruption. While it's true that the user will be
205       // stuck in this state until some action is taken, we're unlikely to help
206       // the user if we run our recovery code or delete our databases.
207       [[fallthrough]];
208     case SQLITE_PROTOCOL:
209       // Gave up while attempting to grab a lock on a WAL database at the
210       // beginning of a transaction. In theory, this should not be a problem in
211       // Chrome, because we'll only allow enabling WAL on databases with
212       // exclusive locking. However, other software on the user's system may
213       // lock our databases in a way that triggers this error.
214       [[fallthrough]];
215     case SQLITE_SCHEMA:
216       // The database schema was changed between the time when a prepared
217       // statement was compiled, and when it was executing.
218       //
219       // This can happen in production. Databases that don't use exclusive
220       // locking (recommended but not yet required for Chrome features) may be
221       // changed from another process via legitimate use of SQLite APIs.
222       // Databases that do use exclusive locks may still be mutated on-disk, on
223       // operating systems where exclusive locks are only enforced via advisory
224       // locking.
225       //
226       // When we mandate exclusive locks for all features in Chrome, we may
227       // classify this error as database corruption, because it is an indicator
228       // that another process is interfering with Chrome's schemas.
229       [[fallthrough]];
230     case SQLITE_TOOBIG:
231       // SQLite encountered a string or blob whose length exceeds
232       // SQLITE_MAX_LENGTH, or it was asked to execute a SQL statement whose
233       // length exceeds SQLITE_MAX_SQL_LENGTH or SQLITE_LIMIT_SQL_LENGTH.
234       //
235       // A corrupted database could cause this in the following ways:
236       // * SQLite could encounter an overly large string or blob because its
237       //   size field got corrupted.
238       // * SQLite could attempt to execute an overly large SQL statement while
239       //   operating on a corrupted schema. (Some of SQLite's DDL statements
240       //   involve executing SQL that includes schema content.)
241       //
242       // However, this could also occur due to a Chrome bug where we ask SQLite
243       // to bind an overly large string or blob. So, we currently don't classify
244       // this as definitely induced by corruption.
245       [[fallthrough]];
246     case SQLITE_CONSTRAINT:
247       // This can happen in production, when executing SQL statements with the
248       // semantics of "create a record if it doesn't exist, otherwise do
249       // nothing".
250       return false;
251   }
252
253   NOTREACHED() << "SQLite returned unknown result code: " << sqlite_error_code;
254   return false;
255 }
256
257 std::string GetCorruptFileDiagnosticsInfo(
258     const base::FilePath& corrupted_file_path) {
259   std::string corrupted_file_info("Corrupted file: ");
260   corrupted_file_info +=
261       corrupted_file_path.DirName().BaseName().AsUTF8Unsafe() + "/" +
262       corrupted_file_path.BaseName().AsUTF8Unsafe() + "\n";
263   return corrupted_file_info;
264 }
265
266 }  // namespace sql