android_database_SQLiteCommon.cpp revision 9d25fa67a9291d469fa4006b2a373c8429132536
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
19namespace android {
20
21/* throw a SQLiteException with a message appropriate for the error in handle */
22void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) {
23    throw_sqlite3_exception(env, handle, NULL);
24}
25
26/* throw a SQLiteException with the given message */
27void 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 */
34void throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) {
35    if (handle) {
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);
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
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 */
51void throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) {
52    char temp[21];
53    sprintf(temp, "error code %d", errcode);
54    throw_sqlite3_exception(env, errcode, temp, message);
55}
56
57/* throw a SQLiteException for a given error code, sqlite3message, and
58   user message
59 */
60void 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:
72            exceptionClass = "android/database/sqlite/SQLiteConstraintException";
73            break;
74        case SQLITE_ABORT:
75            exceptionClass = "android/database/sqlite/SQLiteAbortException";
76            break;
77        case SQLITE_DONE:
78            exceptionClass = "android/database/sqlite/SQLiteDoneException";
79            sqlite3Message = NULL; // SQLite error message is irrelevant in this case
80            break;
81        case SQLITE_FULL:
82            exceptionClass = "android/database/sqlite/SQLiteFullException";
83            break;
84        case SQLITE_MISUSE:
85            exceptionClass = "android/database/sqlite/SQLiteMisuseException";
86            break;
87        case SQLITE_PERM:
88            exceptionClass = "android/database/sqlite/SQLiteAccessPermException";
89            break;
90        case SQLITE_BUSY:
91            exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException";
92            break;
93        case SQLITE_LOCKED:
94            exceptionClass = "android/database/sqlite/SQLiteTableLockedException";
95            break;
96        case SQLITE_READONLY:
97            exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException";
98            break;
99        case SQLITE_CANTOPEN:
100            exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException";
101            break;
102        case SQLITE_TOOBIG:
103            exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException";
104            break;
105        case SQLITE_RANGE:
106            exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException";
107            break;
108        case SQLITE_NOMEM:
109            exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException";
110            break;
111        case SQLITE_MISMATCH:
112            exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException";
113            break;
114        case SQLITE_INTERRUPT:
115            exceptionClass = "android/os/OperationCanceledException";
116            break;
117        default:
118            exceptionClass = "android/database/sqlite/SQLiteException";
119            break;
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
142