android_database_SQLiteCommon.cpp revision 25c934533fb81aa08e379ffe60e390dbbd12440c
1e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/*
2e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Copyright (C) 2011 The Android Open Source Project
3e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown *
4e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Licensed under the Apache License, Version 2.0 (the "License");
5e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * you may not use this file except in compliance with the License.
6e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * You may obtain a copy of the License at
7e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown *
8e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown *      http://www.apache.org/licenses/LICENSE-2.0
9e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown *
10e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * Unless required by applicable law or agreed to in writing, software
11e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * distributed under the License is distributed on an "AS IS" BASIS,
12e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * See the License for the specific language governing permissions and
14e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown * limitations under the License.
15e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */
16e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
17e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown#include "android_database_SQLiteCommon.h"
18e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
19e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownnamespace android {
20e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
21e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/* throw a SQLiteException with a message appropriate for the error in handle */
22e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownvoid throw_sqlite3_exception(JNIEnv* env, sqlite3* handle) {
23e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    throw_sqlite3_exception(env, handle, NULL);
24e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown}
25e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
26e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/* throw a SQLiteException with the given message */
27e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownvoid throw_sqlite3_exception(JNIEnv* env, const char* message) {
28e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    throw_sqlite3_exception(env, NULL, message);
29e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown}
30e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
31e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/* throw a SQLiteException with a message appropriate for the error in handle
32e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown   concatenated with the given message
33e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */
34e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownvoid throw_sqlite3_exception(JNIEnv* env, sqlite3* handle, const char* message) {
35e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    if (handle) {
36e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        throw_sqlite3_exception(env, sqlite3_errcode(handle),
37e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                                sqlite3_errmsg(handle), message);
38e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    } else {
39e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        // we use SQLITE_OK so that a generic SQLiteException is thrown;
40e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        // any code not specified in the switch statement below would do.
41e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        throw_sqlite3_exception(env, SQLITE_OK, "unknown error", message);
42e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    }
43e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown}
44e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
45e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/* throw a SQLiteException for a given error code */
46e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownvoid throw_sqlite3_exception_errcode(JNIEnv* env, int errcode, const char* message) {
47e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    if (errcode == SQLITE_DONE) {
48e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        throw_sqlite3_exception(env, errcode, NULL, message);
49e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    } else {
50e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        char temp[21];
51e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        sprintf(temp, "error code %d", errcode);
52e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        throw_sqlite3_exception(env, errcode, temp, message);
53e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    }
54e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown}
55e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
56e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown/* throw a SQLiteException for a given error code, sqlite3message, and
57e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown   user message
58e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown */
59e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brownvoid throw_sqlite3_exception(JNIEnv* env, int errcode,
60e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown                             const char* sqlite3Message, const char* message) {
61e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    const char* exceptionClass;
62e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    switch (errcode) {
63e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_IOERR:
64e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            exceptionClass = "android/database/sqlite/SQLiteDiskIOException";
65e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            break;
66e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_CORRUPT:
67e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_NOTADB: // treat "unsupported file format" error as corruption also
68e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            exceptionClass = "android/database/sqlite/SQLiteDatabaseCorruptException";
69e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            break;
70e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_CONSTRAINT:
7175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteConstraintException";
7275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
73e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_ABORT:
7475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteAbortException";
7575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
76e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_DONE:
7775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteDoneException";
7875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
79e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_FULL:
8075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteFullException";
8175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
82e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_MISUSE:
8375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteMisuseException";
8475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
85e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_PERM:
8675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteAccessPermException";
8775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
88e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_BUSY:
8975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteDatabaseLockedException";
9075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
91e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_LOCKED:
9275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteTableLockedException";
9375ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
94e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_READONLY:
9575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteReadOnlyDatabaseException";
9675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
97e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_CANTOPEN:
9875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteCantOpenDatabaseException";
9975ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
100e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_TOOBIG:
10175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteBlobTooBigException";
10275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
103e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_RANGE:
10475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteBindOrColumnIndexOutOfRangeException";
10575ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
106e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_NOMEM:
10775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteOutOfMemoryException";
10875ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
109e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        case SQLITE_MISMATCH:
11075ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteDatatypeMismatchException";
11175ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
11275ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown        case SQLITE_INTERRUPT:
11325c934533fb81aa08e379ffe60e390dbbd12440cJeff Brown            exceptionClass = "android/os/OperationCanceledException";
11475ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
115e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        default:
11675ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            exceptionClass = "android/database/sqlite/SQLiteException";
11775ea64fc54f328d37b115cfb1ded1e45c30380edJeff Brown            break;
118e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    }
119e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
120e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    if (sqlite3Message != NULL && message != NULL) {
121e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        char* fullMessage = (char *)malloc(strlen(sqlite3Message) + strlen(message) + 3);
122e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        if (fullMessage != NULL) {
123e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            strcpy(fullMessage, sqlite3Message);
124e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            strcat(fullMessage, ": ");
125e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            strcat(fullMessage, message);
126e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            jniThrowException(env, exceptionClass, fullMessage);
127e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            free(fullMessage);
128e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        } else {
129e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown            jniThrowException(env, exceptionClass, sqlite3Message);
130e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        }
131e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    } else if (sqlite3Message != NULL) {
132e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        jniThrowException(env, exceptionClass, sqlite3Message);
133e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    } else {
134e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown        jniThrowException(env, exceptionClass, message);
135e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown    }
136e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown}
137e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
138e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown
139e5360fbf3efe85427f7e7f59afe7bbeddb4949acJeff Brown} // namespace android
140