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 | |
| 19 | namespace android { |
| 20 | |
| 21 | /* throw a SQLiteException with a message appropriate for the error in handle */ |
| 22 | void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) { |
| 23 | throw_sqlite3_exception(env, handle, NULL); |
| 24 | } |
| 25 | |
| 26 | /* throw a SQLiteException with the given message */ |
| 27 | void throw_sqlite3_exception(JNIEnv* env, const char* message) { |
| 28 | throw_sqlite3_exception(env, NULL, message); |
| 29 | } |
| 30 | |
| 31 | /* throw a SQLiteException with a message appropriate for the error in handle |
| 32 | concatenated with the given message |
| 33 | */ |
| 34 | void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) { |
| 35 | if (handle) { |
Jeff Brown | 9d25fa6 | 2012-06-05 14:29:02 -0700 | [diff] [blame^] | 36 | // get the error code and message from the SQLite connection |
| 37 | // the error message may contain more information than the error code |
| 38 | // because it is based on the extended error code rather than the simplified |
| 39 | // error code that SQLite normally returns. |
| 40 | throw_sqlite3_exception(env, sqlite3_errcode(handle), sqlite3_errmsg(handle), message); |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 41 | } else { |
| 42 | // we use SQLITE_OK so that a generic SQLiteException is thrown; |
| 43 | // any code not specified in the switch statement below would do. |
| 44 | throw_sqlite3_exception(env, SQLITE_OK, "unknown error", message); |
| 45 | } |
| 46 | } |
| 47 | |
Jeff Brown | 9d25fa6 | 2012-06-05 14:29:02 -0700 | [diff] [blame^] | 48 | /* throw a SQLiteException for a given error code |
| 49 | * should only be used when the database connection is not available because the |
| 50 | * error information will not be quite as rich */ |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 51 | void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) { |
Jeff Brown | 9d25fa6 | 2012-06-05 14:29:02 -0700 | [diff] [blame^] | 52 | char temp[21]; |
| 53 | sprintf(temp, "error code %d", errcode); |
| 54 | throw_sqlite3_exception(env, errcode, temp, message); |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 55 | } |
| 56 | |
| 57 | /* throw a SQLiteException for a given error code, sqlite3message, and |
| 58 | user message |
| 59 | */ |
| 60 | void throw_sqlite3_exception(JNIEnv* env, int errcode, |
| 61 | const char* sqlite3Message, const char* message) { |
| 62 | const char* exceptionClass; |
| 63 | switch (errcode) { |
| 64 | case SQLITE_IOERR: |
| 65 | exceptionClass = "android/database/sqlite/SQLiteDiskIOException"; |
| 66 | break; |
| 67 | case SQLITE_CORRUPT: |
| 68 | case SQLITE_NOTADB: // treat "unsupported file format" error as corruption also |
| 69 | exceptionClass = "android/database/sqlite/SQLiteDatabaseCorruptException"; |
| 70 | break; |
| 71 | case SQLITE_CONSTRAINT: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 72 | exceptionClass = "android/database/sqlite/SQLiteConstraintException"; |
| 73 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 74 | case SQLITE_ABORT: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 75 | exceptionClass = "android/database/sqlite/SQLiteAbortException"; |
| 76 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 77 | case SQLITE_DONE: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 78 | exceptionClass = "android/database/sqlite/SQLiteDoneException"; |
Jeff Brown | 9d25fa6 | 2012-06-05 14:29:02 -0700 | [diff] [blame^] | 79 | sqlite3Message = NULL; // SQLite error message is irrelevant in this case |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 80 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 81 | case SQLITE_FULL: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 82 | exceptionClass = "android/database/sqlite/SQLiteFullException"; |
| 83 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 84 | case SQLITE_MISUSE: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 85 | exceptionClass = "android/database/sqlite/SQLiteMisuseException"; |
| 86 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 87 | case SQLITE_PERM: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 88 | exceptionClass = "android/database/sqlite/SQLiteAccessPermException"; |
| 89 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 90 | case SQLITE_BUSY: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 91 | exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException"; |
| 92 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 93 | case SQLITE_LOCKED: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 94 | exceptionClass = "android/database/sqlite/SQLiteTableLockedException"; |
| 95 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 96 | case SQLITE_READONLY: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 97 | exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException"; |
| 98 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 99 | case SQLITE_CANTOPEN: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 100 | exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException"; |
| 101 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 102 | case SQLITE_TOOBIG: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 103 | exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException"; |
| 104 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 105 | case SQLITE_RANGE: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 106 | exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException"; |
| 107 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 108 | case SQLITE_NOMEM: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 109 | exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException"; |
| 110 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 111 | case SQLITE_MISMATCH: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 112 | exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException"; |
| 113 | break; |
| 114 | case SQLITE_INTERRUPT: |
Jeff Brown | 25c9345 | 2012-05-09 18:04:34 -0700 | [diff] [blame] | 115 | exceptionClass = "android/os/OperationCanceledException"; |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 116 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 117 | default: |
Jeff Brown | 75ea64f | 2012-01-25 19:37:13 -0800 | [diff] [blame] | 118 | exceptionClass = "android/database/sqlite/SQLiteException"; |
| 119 | break; |
Jeff Brown | e5360fb | 2011-10-31 17:48:13 -0700 | [diff] [blame] | 120 | } |
| 121 | |
| 122 | if (sqlite3Message != NULL && message != NULL) { |
| 123 | char* fullMessage = (char *)malloc(strlen(sqlite3Message) + strlen(message) + 3); |
| 124 | if (fullMessage != NULL) { |
| 125 | strcpy(fullMessage, sqlite3Message); |
| 126 | strcat(fullMessage, ": "); |
| 127 | strcat(fullMessage, message); |
| 128 | jniThrowException(env, exceptionClass, fullMessage); |
| 129 | free(fullMessage); |
| 130 | } else { |
| 131 | jniThrowException(env, exceptionClass, sqlite3Message); |
| 132 | } |
| 133 | } else if (sqlite3Message != NULL) { |
| 134 | jniThrowException(env, exceptionClass, sqlite3Message); |
| 135 | } else { |
| 136 | jniThrowException(env, exceptionClass, message); |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | |
| 141 | } // namespace android |