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 #include <utils/String8.h> 20 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) { 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. 42 throw_sqlite3_exception(env, sqlite3_extended_errcode(handle), 43 sqlite3_errmsg(handle), message); 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 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 */ 54 void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) { 55 throw_sqlite3_exception(env, errcode, "unknown error", message); 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; 64 switch (errcode & 0xff) { /* mask off extended error code */ 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: 73 exceptionClass = "android/database/sqlite/SQLiteConstraintException"; 74 break; 75 case SQLITE_ABORT: 76 exceptionClass = "android/database/sqlite/SQLiteAbortException"; 77 break; 78 case SQLITE_DONE: 79 exceptionClass = "android/database/sqlite/SQLiteDoneException"; 80 sqlite3Message = NULL; // SQLite error message is irrelevant in this case 81 break; 82 case SQLITE_FULL: 83 exceptionClass = "android/database/sqlite/SQLiteFullException"; 84 break; 85 case SQLITE_MISUSE: 86 exceptionClass = "android/database/sqlite/SQLiteMisuseException"; 87 break; 88 case SQLITE_PERM: 89 exceptionClass = "android/database/sqlite/SQLiteAccessPermException"; 90 break; 91 case SQLITE_BUSY: 92 exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException"; 93 break; 94 case SQLITE_LOCKED: 95 exceptionClass = "android/database/sqlite/SQLiteTableLockedException"; 96 break; 97 case SQLITE_READONLY: 98 exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException"; 99 break; 100 case SQLITE_CANTOPEN: 101 exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException"; 102 break; 103 case SQLITE_TOOBIG: 104 exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException"; 105 break; 106 case SQLITE_RANGE: 107 exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException"; 108 break; 109 case SQLITE_NOMEM: 110 exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException"; 111 break; 112 case SQLITE_MISMATCH: 113 exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException"; 114 break; 115 case SQLITE_INTERRUPT: 116 exceptionClass = "android/os/OperationCanceledException"; 117 break; 118 default: 119 exceptionClass = "android/database/sqlite/SQLiteException"; 120 break; 121 } 122 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); 130 } 131 jniThrowException(env, exceptionClass, fullMessage.string()); 132 } else { 133 jniThrowException(env, exceptionClass, message); 134 } 135 } 136 137 138 } // namespace android 139