blob: daa20876ba65424f7c279ae8d41baeb06715bb5c [file] [log] [blame]
Jeff Browne5360fb2011-10-31 17:48:13 -07001/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "android_database_SQLiteCommon.h"
18
Jeff Brownca309f22012-06-12 15:39:09 -070019#include <utils/String8.h>
20
Fyodor Kupolov6e98f462018-01-19 12:45:11 -080021#include <map>
22
Jeff Browne5360fb2011-10-31 17:48:13 -070023namespace android {
24
Fyodor Kupolov6e98f462018-01-19 12:45:11 -080025static const std::map<int, std::string> sErrorCodesMap = {
26 // Primary Result Code List
27 {4, "SQLITE_ABORT"},
28 {23, "SQLITE_AUTH"},
29 {5, "SQLITE_BUSY"},
30 {14, "SQLITE_CANTOPEN"},
31 {19, "SQLITE_CONSTRAINT"},
32 {11, "SQLITE_CORRUPT"},
33 {101, "SQLITE_DONE"},
34 {16, "SQLITE_EMPTY"},
35 {1, "SQLITE_ERROR"},
36 {24, "SQLITE_FORMAT"},
37 {13, "SQLITE_FULL"},
38 {2, "SQLITE_INTERNAL"},
39 {9, "SQLITE_INTERRUPT"},
40 {10, "SQLITE_IOERR"},
41 {6, "SQLITE_LOCKED"},
42 {20, "SQLITE_MISMATCH"},
43 {21, "SQLITE_MISUSE"},
44 {22, "SQLITE_NOLFS"},
45 {7, "SQLITE_NOMEM"},
46 {26, "SQLITE_NOTADB"},
47 {12, "SQLITE_NOTFOUND"},
48 {27, "SQLITE_NOTICE"},
49 {0, "SQLITE_OK"},
50 {3, "SQLITE_PERM"},
51 {15, "SQLITE_PROTOCOL"},
52 {25, "SQLITE_RANGE"},
53 {8, "SQLITE_READONLY"},
54 {100, "SQLITE_ROW"},
55 {17, "SQLITE_SCHEMA"},
56 {18, "SQLITE_TOOBIG"},
57 {28, "SQLITE_WARNING"},
58 // Extended Result Code List
59 {516, "SQLITE_ABORT_ROLLBACK"},
60 {261, "SQLITE_BUSY_RECOVERY"},
61 {517, "SQLITE_BUSY_SNAPSHOT"},
62 {1038, "SQLITE_CANTOPEN_CONVPATH"},
63 {782, "SQLITE_CANTOPEN_FULLPATH"},
64 {526, "SQLITE_CANTOPEN_ISDIR"},
65 {270, "SQLITE_CANTOPEN_NOTEMPDIR"},
66 {275, "SQLITE_CONSTRAINT_CHECK"},
67 {531, "SQLITE_CONSTRAINT_COMMITHOOK"},
68 {787, "SQLITE_CONSTRAINT_FOREIGNKEY"},
69 {1043, "SQLITE_CONSTRAINT_FUNCTION"},
70 {1299, "SQLITE_CONSTRAINT_NOTNULL"},
71 {1555, "SQLITE_CONSTRAINT_PRIMARYKEY"},
72 {2579, "SQLITE_CONSTRAINT_ROWID"},
73 {1811, "SQLITE_CONSTRAINT_TRIGGER"},
74 {2067, "SQLITE_CONSTRAINT_UNIQUE"},
75 {2323, "SQLITE_CONSTRAINT_VTAB"},
76 {267, "SQLITE_CORRUPT_VTAB"},
77 {3338, "SQLITE_IOERR_ACCESS"},
78 {2826, "SQLITE_IOERR_BLOCKED"},
79 {3594, "SQLITE_IOERR_CHECKRESERVEDLOCK"},
80 {4106, "SQLITE_IOERR_CLOSE"},
81 {6666, "SQLITE_IOERR_CONVPATH"},
82 {2570, "SQLITE_IOERR_DELETE"},
83 {5898, "SQLITE_IOERR_DELETE_NOENT"},
84 {4362, "SQLITE_IOERR_DIR_CLOSE"},
85 {1290, "SQLITE_IOERR_DIR_FSYNC"},
86 {1802, "SQLITE_IOERR_FSTAT"},
87 {1034, "SQLITE_IOERR_FSYNC"},
88 {6410, "SQLITE_IOERR_GETTEMPPATH"},
89 {3850, "SQLITE_IOERR_LOCK"},
90 {6154, "SQLITE_IOERR_MMAP"},
91 {3082, "SQLITE_IOERR_NOMEM"},
92 {2314, "SQLITE_IOERR_RDLOCK"},
93 {266, "SQLITE_IOERR_READ"},
94 {5642, "SQLITE_IOERR_SEEK"},
95 {5130, "SQLITE_IOERR_SHMLOCK"},
96 {5386, "SQLITE_IOERR_SHMMAP"},
97 {4618, "SQLITE_IOERR_SHMOPEN"},
98 {4874, "SQLITE_IOERR_SHMSIZE"},
99 {522, "SQLITE_IOERR_SHORT_READ"},
100 {1546, "SQLITE_IOERR_TRUNCATE"},
101 {2058, "SQLITE_IOERR_UNLOCK"},
102 {778, "SQLITE_IOERR_WRITE"},
103 {262, "SQLITE_LOCKED_SHAREDCACHE"},
104 {539, "SQLITE_NOTICE_RECOVER_ROLLBACK"},
105 {283, "SQLITE_NOTICE_RECOVER_WAL"},
106 {256, "SQLITE_OK_LOAD_PERMANENTLY"},
107 {520, "SQLITE_READONLY_CANTLOCK"},
108 {1032, "SQLITE_READONLY_DBMOVED"},
109 {264, "SQLITE_READONLY_RECOVERY"},
110 {776, "SQLITE_READONLY_ROLLBACK"},
111 {284, "SQLITE_WARNING_AUTOINDEX"},
112};
113
114static std::string sqlite3_error_code_to_msg(int errcode) {
115 auto it = sErrorCodesMap.find(errcode);
116 if (it != sErrorCodesMap.end()) {
117 return std::to_string(errcode) + " " + it->second;
118 } else {
119 return std::to_string(errcode);
120 }
121}
122
Jeff Browne5360fb2011-10-31 17:48:13 -0700123/* throw a SQLiteException with a message appropriate for the error in handle */
124void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) {
125 throw_sqlite3_exception(env, handle, NULL);
126}
127
128/* throw a SQLiteException with the given message */
129void throw_sqlite3_exception(JNIEnv* env, const char* message) {
130 throw_sqlite3_exception(env, NULL, message);
131}
132
133/* throw a SQLiteException with a message appropriate for the error in handle
134 concatenated with the given message
135 */
136void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) {
137 if (handle) {
Jeff Brown9d25fa62012-06-05 14:29:02 -0700138 // get the error code and message from the SQLite connection
139 // the error message may contain more information than the error code
140 // because it is based on the extended error code rather than the simplified
141 // error code that SQLite normally returns.
Jeff Brownca309f22012-06-12 15:39:09 -0700142 throw_sqlite3_exception(env, sqlite3_extended_errcode(handle),
143 sqlite3_errmsg(handle), message);
Jeff Browne5360fb2011-10-31 17:48:13 -0700144 } else {
145 // we use SQLITE_OK so that a generic SQLiteException is thrown;
146 // any code not specified in the switch statement below would do.
147 throw_sqlite3_exception(env, SQLITE_OK, "unknown error", message);
148 }
149}
150
Jeff Brown9d25fa62012-06-05 14:29:02 -0700151/* throw a SQLiteException for a given error code
152 * should only be used when the database connection is not available because the
153 * error information will not be quite as rich */
Jeff Browne5360fb2011-10-31 17:48:13 -0700154void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) {
Jeff Brownca309f22012-06-12 15:39:09 -0700155 throw_sqlite3_exception(env, errcode, "unknown error", message);
Jeff Browne5360fb2011-10-31 17:48:13 -0700156}
157
158/* throw a SQLiteException for a given error code, sqlite3message, and
159 user message
160 */
161void throw_sqlite3_exception(JNIEnv* env, int errcode,
162 const char* sqlite3Message, const char* message) {
163 const char* exceptionClass;
Jeff Brownca309f22012-06-12 15:39:09 -0700164 switch (errcode & 0xff) { /* mask off extended error code */
Jeff Browne5360fb2011-10-31 17:48:13 -0700165 case SQLITE_IOERR:
166 exceptionClass = "android/database/sqlite/SQLiteDiskIOException";
167 break;
168 case SQLITE_CORRUPT:
169 case SQLITE_NOTADB: // treat "unsupported file format" error as corruption also
170 exceptionClass = "android/database/sqlite/SQLiteDatabaseCorruptException";
171 break;
172 case SQLITE_CONSTRAINT:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800173 exceptionClass = "android/database/sqlite/SQLiteConstraintException";
174 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700175 case SQLITE_ABORT:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800176 exceptionClass = "android/database/sqlite/SQLiteAbortException";
177 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700178 case SQLITE_DONE:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800179 exceptionClass = "android/database/sqlite/SQLiteDoneException";
Jeff Brown9d25fa62012-06-05 14:29:02 -0700180 sqlite3Message = NULL; // SQLite error message is irrelevant in this case
Jeff Brown75ea64f2012-01-25 19:37:13 -0800181 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700182 case SQLITE_FULL:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800183 exceptionClass = "android/database/sqlite/SQLiteFullException";
184 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700185 case SQLITE_MISUSE:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800186 exceptionClass = "android/database/sqlite/SQLiteMisuseException";
187 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700188 case SQLITE_PERM:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800189 exceptionClass = "android/database/sqlite/SQLiteAccessPermException";
190 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700191 case SQLITE_BUSY:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800192 exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException";
193 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700194 case SQLITE_LOCKED:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800195 exceptionClass = "android/database/sqlite/SQLiteTableLockedException";
196 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700197 case SQLITE_READONLY:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800198 exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException";
199 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700200 case SQLITE_CANTOPEN:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800201 exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException";
202 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700203 case SQLITE_TOOBIG:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800204 exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException";
205 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700206 case SQLITE_RANGE:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800207 exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException";
208 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700209 case SQLITE_NOMEM:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800210 exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException";
211 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700212 case SQLITE_MISMATCH:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800213 exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException";
214 break;
215 case SQLITE_INTERRUPT:
Jeff Brown25c93452012-05-09 18:04:34 -0700216 exceptionClass = "android/os/OperationCanceledException";
Jeff Brown75ea64f2012-01-25 19:37:13 -0800217 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700218 default:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800219 exceptionClass = "android/database/sqlite/SQLiteException";
220 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700221 }
222
Jeff Brownca309f22012-06-12 15:39:09 -0700223 if (sqlite3Message) {
224 String8 fullMessage;
225 fullMessage.append(sqlite3Message);
Andreas Gampef02798b2018-01-22 17:55:17 -0800226 std::string errcode_msg = sqlite3_error_code_to_msg(errcode);
227 fullMessage.appendFormat(" (code %s)", errcode_msg.c_str()); // print extended error code
Jeff Brownca309f22012-06-12 15:39:09 -0700228 if (message) {
229 fullMessage.append(": ");
230 fullMessage.append(message);
Jeff Browne5360fb2011-10-31 17:48:13 -0700231 }
Jeff Brownca309f22012-06-12 15:39:09 -0700232 jniThrowException(env, exceptionClass, fullMessage.string());
Jeff Browne5360fb2011-10-31 17:48:13 -0700233 } else {
234 jniThrowException(env, exceptionClass, message);
235 }
236}
237
238
239} // namespace android