blob: eefcb74e0f70281adee1ba232f1ad8e829635321 [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
Jeff Browne5360fb2011-10-31 17:48:13 -070021namespace android {
22
23/* throw a SQLiteException with a message appropriate for the error in handle */
24void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) {
25 throw_sqlite3_exception(env, handle, NULL);
26}
27
28/* throw a SQLiteException with the given message */
29void throw_sqlite3_exception(JNIEnv* env, const char* message) {
30 throw_sqlite3_exception(env, NULL, message);
31}
32
33/* throw a SQLiteException with a message appropriate for the error in handle
34 concatenated with the given message
35 */
36void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) {
37 if (handle) {
Jeff Brown9d25fa62012-06-05 14:29:02 -070038 // get the error code and message from the SQLite connection
39 // the error message may contain more information than the error code
40 // because it is based on the extended error code rather than the simplified
41 // error code that SQLite normally returns.
Jeff Brownca309f22012-06-12 15:39:09 -070042 throw_sqlite3_exception(env, sqlite3_extended_errcode(handle),
43 sqlite3_errmsg(handle), message);
Jeff Browne5360fb2011-10-31 17:48:13 -070044 } else {
45 // we use SQLITE_OK so that a generic SQLiteException is thrown;
46 // any code not specified in the switch statement below would do.
47 throw_sqlite3_exception(env, SQLITE_OK, "unknown error", message);
48 }
49}
50
Jeff Brown9d25fa62012-06-05 14:29:02 -070051/* throw a SQLiteException for a given error code
52 * should only be used when the database connection is not available because the
53 * error information will not be quite as rich */
Jeff Browne5360fb2011-10-31 17:48:13 -070054void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) {
Jeff Brownca309f22012-06-12 15:39:09 -070055 throw_sqlite3_exception(env, errcode, "unknown error", message);
Jeff Browne5360fb2011-10-31 17:48:13 -070056}
57
58/* throw a SQLiteException for a given error code, sqlite3message, and
59 user message
60 */
61void throw_sqlite3_exception(JNIEnv* env, int errcode,
62 const char* sqlite3Message, const char* message) {
63 const char* exceptionClass;
Jeff Brownca309f22012-06-12 15:39:09 -070064 switch (errcode & 0xff) { /* mask off extended error code */
Jeff Browne5360fb2011-10-31 17:48:13 -070065 case SQLITE_IOERR:
66 exceptionClass = "android/database/sqlite/SQLiteDiskIOException";
67 break;
68 case SQLITE_CORRUPT:
69 case SQLITE_NOTADB: // treat "unsupported file format" error as corruption also
70 exceptionClass = "android/database/sqlite/SQLiteDatabaseCorruptException";
71 break;
72 case SQLITE_CONSTRAINT:
Jeff Brown75ea64f2012-01-25 19:37:13 -080073 exceptionClass = "android/database/sqlite/SQLiteConstraintException";
74 break;
Jeff Browne5360fb2011-10-31 17:48:13 -070075 case SQLITE_ABORT:
Jeff Brown75ea64f2012-01-25 19:37:13 -080076 exceptionClass = "android/database/sqlite/SQLiteAbortException";
77 break;
Jeff Browne5360fb2011-10-31 17:48:13 -070078 case SQLITE_DONE:
Jeff Brown75ea64f2012-01-25 19:37:13 -080079 exceptionClass = "android/database/sqlite/SQLiteDoneException";
Jeff Brown9d25fa62012-06-05 14:29:02 -070080 sqlite3Message = NULL; // SQLite error message is irrelevant in this case
Jeff Brown75ea64f2012-01-25 19:37:13 -080081 break;
Jeff Browne5360fb2011-10-31 17:48:13 -070082 case SQLITE_FULL:
Jeff Brown75ea64f2012-01-25 19:37:13 -080083 exceptionClass = "android/database/sqlite/SQLiteFullException";
84 break;
Jeff Browne5360fb2011-10-31 17:48:13 -070085 case SQLITE_MISUSE:
Jeff Brown75ea64f2012-01-25 19:37:13 -080086 exceptionClass = "android/database/sqlite/SQLiteMisuseException";
87 break;
Jeff Browne5360fb2011-10-31 17:48:13 -070088 case SQLITE_PERM:
Jeff Brown75ea64f2012-01-25 19:37:13 -080089 exceptionClass = "android/database/sqlite/SQLiteAccessPermException";
90 break;
Jeff Browne5360fb2011-10-31 17:48:13 -070091 case SQLITE_BUSY:
Jeff Brown75ea64f2012-01-25 19:37:13 -080092 exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException";
93 break;
Jeff Browne5360fb2011-10-31 17:48:13 -070094 case SQLITE_LOCKED:
Jeff Brown75ea64f2012-01-25 19:37:13 -080095 exceptionClass = "android/database/sqlite/SQLiteTableLockedException";
96 break;
Jeff Browne5360fb2011-10-31 17:48:13 -070097 case SQLITE_READONLY:
Jeff Brown75ea64f2012-01-25 19:37:13 -080098 exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException";
99 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700100 case SQLITE_CANTOPEN:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800101 exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException";
102 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700103 case SQLITE_TOOBIG:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800104 exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException";
105 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700106 case SQLITE_RANGE:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800107 exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException";
108 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700109 case SQLITE_NOMEM:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800110 exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException";
111 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700112 case SQLITE_MISMATCH:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800113 exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException";
114 break;
115 case SQLITE_INTERRUPT:
Jeff Brown25c93452012-05-09 18:04:34 -0700116 exceptionClass = "android/os/OperationCanceledException";
Jeff Brown75ea64f2012-01-25 19:37:13 -0800117 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700118 default:
Jeff Brown75ea64f2012-01-25 19:37:13 -0800119 exceptionClass = "android/database/sqlite/SQLiteException";
120 break;
Jeff Browne5360fb2011-10-31 17:48:13 -0700121 }
122
Jeff Brownca309f22012-06-12 15:39:09 -0700123 if (sqlite3Message) {
124 String8 fullMessage;
125 fullMessage.append(sqlite3Message);
126 fullMessage.appendFormat(" (code %d)", errcode); // print extended error code
127 if (message) {
128 fullMessage.append(": ");
129 fullMessage.append(message);
Jeff Browne5360fb2011-10-31 17:48:13 -0700130 }
Jeff Brownca309f22012-06-12 15:39:09 -0700131 jniThrowException(env, exceptionClass, fullMessage.string());
Jeff Browne5360fb2011-10-31 17:48:13 -0700132 } else {
133 jniThrowException(env, exceptionClass, message);
134 }
135}
136
137
138} // namespace android