Home | History | Annotate | Download | only in jni
      1 /*
      2  * Copyright (C) 2006-2008 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 #undef LOG_TAG
     18 #define LOG_TAG "Cursor"
     19 
     20 #include <jni.h>
     21 #include <JNIHelp.h>
     22 #include <android_runtime/AndroidRuntime.h>
     23 
     24 #include <sqlite3.h>
     25 
     26 #include <utils/Log.h>
     27 
     28 #include <stdio.h>
     29 #include <string.h>
     30 #include <unistd.h>
     31 
     32 #include "sqlite3_exception.h"
     33 
     34 
     35 namespace android {
     36 
     37 static jfieldID gHandleField;
     38 static jfieldID gStatementField;
     39 
     40 
     41 #define GET_STATEMENT(env, object) \
     42         (sqlite3_stmt *)env->GetIntField(object, gStatementField)
     43 #define GET_HANDLE(env, object) \
     44         (sqlite3 *)env->GetIntField(object, gHandleField)
     45 
     46 
     47 sqlite3_stmt * compile(JNIEnv* env, jobject object,
     48                        sqlite3 * handle, jstring sqlString)
     49 {
     50     int err;
     51     jchar const * sql;
     52     jsize sqlLen;
     53     sqlite3_stmt * statement = GET_STATEMENT(env, object);
     54 
     55     // Make sure not to leak the statement if it already exists
     56     if (statement != NULL) {
     57         sqlite3_finalize(statement);
     58         env->SetIntField(object, gStatementField, 0);
     59     }
     60 
     61     // Compile the SQL
     62     sql = env->GetStringChars(sqlString, NULL);
     63     sqlLen = env->GetStringLength(sqlString);
     64     err = sqlite3_prepare16_v2(handle, sql, sqlLen * 2, &statement, NULL);
     65     env->ReleaseStringChars(sqlString, sql);
     66 
     67     if (err == SQLITE_OK) {
     68         // Store the statement in the Java object for future calls
     69         LOGV("Prepared statement %p on %p", statement, handle);
     70         env->SetIntField(object, gStatementField, (int)statement);
     71         return statement;
     72     } else {
     73         // Error messages like 'near ")": syntax error' are not
     74         // always helpful enough, so construct an error string that
     75         // includes the query itself.
     76         const char *query = env->GetStringUTFChars(sqlString, NULL);
     77         char *message = (char*) malloc(strlen(query) + 50);
     78         if (message) {
     79             strcpy(message, ", while compiling: "); // less than 50 chars
     80             strcat(message, query);
     81         }
     82         env->ReleaseStringUTFChars(sqlString, query);
     83         throw_sqlite3_exception(env, handle, message);
     84         free(message);
     85         return NULL;
     86     }
     87 }
     88 
     89 static void native_compile(JNIEnv* env, jobject object, jstring sqlString)
     90 {
     91     compile(env, object, GET_HANDLE(env, object), sqlString);
     92 }
     93 
     94 static void native_finalize(JNIEnv* env, jobject object)
     95 {
     96     int err;
     97     sqlite3_stmt * statement = GET_STATEMENT(env, object);
     98 
     99     if (statement != NULL) {
    100         sqlite3_finalize(statement);
    101         env->SetIntField(object, gStatementField, 0);
    102     }
    103 }
    104 
    105 static JNINativeMethod sMethods[] =
    106 {
    107      /* name, signature, funcPtr */
    108     {"native_compile", "(Ljava/lang/String;)V", (void *)native_compile},
    109     {"native_finalize", "()V", (void *)native_finalize},
    110 };
    111 
    112 int register_android_database_SQLiteCompiledSql(JNIEnv * env)
    113 {
    114     jclass clazz;
    115 
    116     clazz = env->FindClass("android/database/sqlite/SQLiteCompiledSql");
    117     if (clazz == NULL) {
    118         LOGE("Can't find android/database/sqlite/SQLiteCompiledSql");
    119         return -1;
    120     }
    121 
    122     gHandleField = env->GetFieldID(clazz, "nHandle", "I");
    123     gStatementField = env->GetFieldID(clazz, "nStatement", "I");
    124 
    125     if (gHandleField == NULL || gStatementField == NULL) {
    126         LOGE("Error locating fields");
    127         return -1;
    128     }
    129 
    130     return AndroidRuntime::registerNativeMethods(env,
    131         "android/database/sqlite/SQLiteCompiledSql", sMethods, NELEM(sMethods));
    132 }
    133 
    134 } // namespace android
    135