• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
compile(JNIEnv * env,jobject object,sqlite3 * handle,jstring sqlString)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 
native_compile(JNIEnv * env,jobject object,jstring sqlString)89 static void native_compile(JNIEnv* env, jobject object, jstring sqlString)
90 {
91     compile(env, object, GET_HANDLE(env, object), sqlString);
92 }
93 
94 
95 static JNINativeMethod sMethods[] =
96 {
97      /* name, signature, funcPtr */
98     {"native_compile", "(Ljava/lang/String;)V", (void *)native_compile},
99 };
100 
register_android_database_SQLiteCompiledSql(JNIEnv * env)101 int register_android_database_SQLiteCompiledSql(JNIEnv * env)
102 {
103     jclass clazz;
104 
105     clazz = env->FindClass("android/database/sqlite/SQLiteCompiledSql");
106     if (clazz == NULL) {
107         LOGE("Can't find android/database/sqlite/SQLiteCompiledSql");
108         return -1;
109     }
110 
111     gHandleField = env->GetFieldID(clazz, "nHandle", "I");
112     gStatementField = env->GetFieldID(clazz, "nStatement", "I");
113 
114     if (gHandleField == NULL || gStatementField == NULL) {
115         LOGE("Error locating fields");
116         return -1;
117     }
118 
119     return AndroidRuntime::registerNativeMethods(env,
120         "android/database/sqlite/SQLiteCompiledSql", sMethods, NELEM(sMethods));
121 }
122 
123 } // namespace android
124