Home | History | Annotate | Download | only in jni
      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