Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 1 | /* |
| 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 Brown | ca309f2 | 2012-06-12 15:39:09 -0700 | [diff] [blame] | 19 | #include <utils/String8.h> |
| 20 | |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 21 | namespace android { |
| 22 | |
| 23 | /* throw a SQLiteException with a message appropriate for the error in handle */ |
| 24 | void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) { |
| 25 | throw_sqlite3_exception(env, handle, NULL); |
| 26 | } |
| 27 | |
| 28 | /* throw a SQLiteException with the given message */ |
| 29 | void 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 | */ |
| 36 | void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) { |
| 37 | if (handle) { |
Jeff Brown | 9d25fa6 | 2012-06-05 14:29:02 -0700 | [diff] [blame] | 38 | // 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 Brown | ca309f2 | 2012-06-12 15:39:09 -0700 | [diff] [blame] | 42 | throw_sqlite3_exception(env, sqlite3_extended_errcode(handle), |
| 43 | sqlite3_errmsg(handle), message); |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 44 | } 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 Brown | 9d25fa6 | 2012-06-05 14:29:02 -0700 | [diff] [blame] | 51 | /* 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 Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 54 | void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) { |
Jeff Brown | ca309f2 | 2012-06-12 15:39:09 -0700 | [diff] [blame] | 55 | throw_sqlite3_exception(env, errcode, "unknown error", message); |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 56 | } |
| 57 | |
| 58 | /* throw a SQLiteException for a given error code, sqlite3message, and |
| 59 | user message |
| 60 | */ |
| 61 | void throw_sqlite3_exception(JNIEnv* env, int errcode, |
| 62 | const char* sqlite3Message, const char* message) { |
| 63 | const char* exceptionClass; |
Jeff Brown | ca309f2 | 2012-06-12 15:39:09 -0700 | [diff] [blame] | 64 | switch (errcode & 0xff) { /* mask off extended error code */ |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 65 | 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 Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 73 | exceptionClass = "android/database/sqlite/SQLiteConstraintException"; |
| 74 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 75 | case SQLITE_ABORT: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 76 | exceptionClass = "android/database/sqlite/SQLiteAbortException"; |
| 77 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 78 | case SQLITE_DONE: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 79 | exceptionClass = "android/database/sqlite/SQLiteDoneException"; |
Jeff Brown | 9d25fa6 | 2012-06-05 14:29:02 -0700 | [diff] [blame] | 80 | sqlite3Message = NULL; // SQLite error message is irrelevant in this case |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 81 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 82 | case SQLITE_FULL: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 83 | exceptionClass = "android/database/sqlite/SQLiteFullException"; |
| 84 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 85 | case SQLITE_MISUSE: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 86 | exceptionClass = "android/database/sqlite/SQLiteMisuseException"; |
| 87 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 88 | case SQLITE_PERM: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 89 | exceptionClass = "android/database/sqlite/SQLiteAccessPermException"; |
| 90 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 91 | case SQLITE_BUSY: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 92 | exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException"; |
| 93 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 94 | case SQLITE_LOCKED: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 95 | exceptionClass = "android/database/sqlite/SQLiteTableLockedException"; |
| 96 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 97 | case SQLITE_READONLY: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 98 | exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException"; |
| 99 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 100 | case SQLITE_CANTOPEN: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 101 | exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException"; |
| 102 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 103 | case SQLITE_TOOBIG: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 104 | exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException"; |
| 105 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 106 | case SQLITE_RANGE: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 107 | exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException"; |
| 108 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 109 | case SQLITE_NOMEM: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 110 | exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException"; |
| 111 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 112 | case SQLITE_MISMATCH: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 113 | exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException"; |
| 114 | break; |
| 115 | case SQLITE_INTERRUPT: |
Jeff Brown | 25c9345 | 2012-05-09 18:04:34 -0700 | [diff] [blame] | 116 | exceptionClass = "android/os/OperationCanceledException"; |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 117 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 118 | default: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 119 | exceptionClass = "android/database/sqlite/SQLiteException"; |
| 120 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 121 | } |
| 122 | |
Jeff Brown | ca309f2 | 2012-06-12 15:39:09 -0700 | [diff] [blame] | 123 | 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 Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 130 | } |
Jeff Brown | ca309f2 | 2012-06-12 15:39:09 -0700 | [diff] [blame] | 131 | jniThrowException(env, exceptionClass, fullMessage.string()); |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 132 | } else { |
| 133 | jniThrowException(env, exceptionClass, message); |
| 134 | } |
| 135 | } |
| 136 | |
| 137 | |
| 138 | } // namespace android |