• 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 
native_bind_null(JNIEnv * env,jobject object,jint index)94 static void native_bind_null(JNIEnv* env, jobject object,
95                              jint index)
96 {
97     int err;
98     sqlite3_stmt * statement = GET_STATEMENT(env, object);
99 
100     err = sqlite3_bind_null(statement, index);
101     if (err != SQLITE_OK) {
102         char buf[32];
103         sprintf(buf, "handle %p", statement);
104         throw_sqlite3_exception(env, GET_HANDLE(env, object), buf);
105         return;
106     }
107 }
108 
native_bind_long(JNIEnv * env,jobject object,jint index,jlong value)109 static void native_bind_long(JNIEnv* env, jobject object,
110                              jint index, jlong value)
111 {
112     int err;
113     sqlite3_stmt * statement = GET_STATEMENT(env, object);
114 
115     err = sqlite3_bind_int64(statement, index, value);
116     if (err != SQLITE_OK) {
117         char buf[32];
118         sprintf(buf, "handle %p", statement);
119         throw_sqlite3_exception(env, GET_HANDLE(env, object), buf);
120         return;
121     }
122 }
123 
native_bind_double(JNIEnv * env,jobject object,jint index,jdouble value)124 static void native_bind_double(JNIEnv* env, jobject object,
125                              jint index, jdouble value)
126 {
127     int err;
128     sqlite3_stmt * statement = GET_STATEMENT(env, object);
129 
130     err = sqlite3_bind_double(statement, index, value);
131     if (err != SQLITE_OK) {
132         char buf[32];
133         sprintf(buf, "handle %p", statement);
134         throw_sqlite3_exception(env, GET_HANDLE(env, object), buf);
135         return;
136     }
137 }
138 
native_bind_string(JNIEnv * env,jobject object,jint index,jstring sqlString)139 static void native_bind_string(JNIEnv* env, jobject object,
140                                jint index, jstring sqlString)
141 {
142     int err;
143     jchar const * sql;
144     jsize sqlLen;
145     sqlite3_stmt * statement= GET_STATEMENT(env, object);
146 
147     sql = env->GetStringChars(sqlString, NULL);
148     sqlLen = env->GetStringLength(sqlString);
149     err = sqlite3_bind_text16(statement, index, sql, sqlLen * 2, SQLITE_TRANSIENT);
150     env->ReleaseStringChars(sqlString, sql);
151     if (err != SQLITE_OK) {
152         char buf[32];
153         sprintf(buf, "handle %p", statement);
154         throw_sqlite3_exception(env, GET_HANDLE(env, object), buf);
155         return;
156     }
157 }
158 
native_bind_blob(JNIEnv * env,jobject object,jint index,jbyteArray value)159 static void native_bind_blob(JNIEnv* env, jobject object,
160                                jint index, jbyteArray value)
161 {
162     int err;
163     jchar const * sql;
164     jsize sqlLen;
165     sqlite3_stmt * statement= GET_STATEMENT(env, object);
166 
167     jint len = env->GetArrayLength(value);
168     jbyte * bytes = env->GetByteArrayElements(value, NULL);
169 
170     err = sqlite3_bind_blob(statement, index, bytes, len, SQLITE_TRANSIENT);
171     env->ReleaseByteArrayElements(value, bytes, JNI_ABORT);
172 
173     if (err != SQLITE_OK) {
174         char buf[32];
175         sprintf(buf, "statement %p", statement);
176         throw_sqlite3_exception(env, GET_HANDLE(env, object), buf);
177         return;
178     }
179 }
180 
native_clear_bindings(JNIEnv * env,jobject object)181 static void native_clear_bindings(JNIEnv* env, jobject object)
182 {
183     int err;
184     sqlite3_stmt * statement = GET_STATEMENT(env, object);
185 
186     err = sqlite3_clear_bindings(statement);
187     if (err != SQLITE_OK) {
188         throw_sqlite3_exception(env, GET_HANDLE(env, object));
189         return;
190     }
191 }
192 
native_finalize(JNIEnv * env,jobject object)193 static void native_finalize(JNIEnv* env, jobject object)
194 {
195     int err;
196     sqlite3_stmt * statement = GET_STATEMENT(env, object);
197 
198     if (statement != NULL) {
199         sqlite3_finalize(statement);
200         env->SetIntField(object, gStatementField, 0);
201     }
202 }
203 
204 
205 static JNINativeMethod sMethods[] =
206 {
207      /* name, signature, funcPtr */
208     {"native_compile", "(Ljava/lang/String;)V", (void *)native_compile},
209     {"native_bind_null", "(I)V", (void *)native_bind_null},
210     {"native_bind_long", "(IJ)V", (void *)native_bind_long},
211     {"native_bind_double", "(ID)V", (void *)native_bind_double},
212     {"native_bind_string", "(ILjava/lang/String;)V", (void *)native_bind_string},
213     {"native_bind_blob", "(I[B)V", (void *)native_bind_blob},
214     {"native_clear_bindings", "()V", (void *)native_clear_bindings},
215     {"native_finalize", "()V", (void *)native_finalize},
216 };
217 
register_android_database_SQLiteProgram(JNIEnv * env)218 int register_android_database_SQLiteProgram(JNIEnv * env)
219 {
220     jclass clazz;
221 
222     clazz = env->FindClass("android/database/sqlite/SQLiteProgram");
223     if (clazz == NULL) {
224         LOGE("Can't find android/database/sqlite/SQLiteProgram");
225         return -1;
226     }
227 
228     gHandleField = env->GetFieldID(clazz, "nHandle", "I");
229     gStatementField = env->GetFieldID(clazz, "nStatement", "I");
230 
231     if (gHandleField == NULL || gStatementField == NULL) {
232         LOGE("Error locating fields");
233         return -1;
234     }
235 
236     return AndroidRuntime::registerNativeMethods(env,
237         "android/database/sqlite/SQLiteProgram", sMethods, NELEM(sMethods));
238 }
239 
240 } // namespace android
241