diff options
Diffstat (limited to 'sqlite-jdbc/src/main/native')
-rw-r--r-- | sqlite-jdbc/src/main/native/sqlite_jni.c | 4404 | ||||
-rw-r--r-- | sqlite-jdbc/src/main/native/sqlite_jni.h | 657 | ||||
-rw-r--r-- | sqlite-jdbc/src/main/native/sqlite_jni_defs.h | 39 |
3 files changed, 5100 insertions, 0 deletions
diff --git a/sqlite-jdbc/src/main/native/sqlite_jni.c b/sqlite-jdbc/src/main/native/sqlite_jni.c new file mode 100644 index 0000000..1333d24 --- /dev/null +++ b/sqlite-jdbc/src/main/native/sqlite_jni.c @@ -0,0 +1,4404 @@ +#include "JNIHelp.h" +#include "sqlite_jni_defs.h" + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +#if HAVE_SQLITE2 +#include "sqlite.h" +#endif + +#if HAVE_SQLITE3 +#include "sqlite3.h" +#undef HAVE_SQLITE_COMPILE +#define HAVE_SQLITE_COMPILE 1 +#undef HAVE_SQLITE_PROGRESS_HANDLER +#define HAVE_SQLITE_PROGRESS_HANDLER 1 +#undef HAVE_SQLITE_TRACE +#define HAVE_SQLITE_TRACE 1 +#if !HAVE_SQLITE3_MALLOC +#define sqlite3_malloc malloc +#define sqlite3_free free +#endif +#if !HAVE_SQLITE3_BIND_PARAMETER_COUNT +#define sqlite3_bind_parameter_count(dummy) (1000) +#endif +#endif + +#if HAVE_SQLITE2 && HAVE_SQLITE3 +#define HAVE_BOTH_SQLITE 1 +#endif + +#define CANT_PASS_VALIST_AS_CHARPTR + +#include "sqlite_jni.h" + +#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR) +#define MAX_PARAMS 256 +#else +#define MAX_PARAMS 32 +#endif + +/* free memory proc */ + +typedef void (freemem)(void *); + +/* internal handle for SQLite database */ + +typedef struct { + void *sqlite; /* SQLite handle */ +#if HAVE_BOTH_SQLITE + int is3; /* True for SQLITE3 handle */ +#endif + int ver; /* version code */ + jobject bh; /* BusyHandler object */ + jobject cb; /* Callback object */ + jobject ai; /* Authorizer object */ + jobject tr; /* Trace object */ + jobject ph; /* ProgressHandler object */ + JNIEnv *env; /* Java environment for callbacks */ + int row1; /* true while processing first row */ + int haveutf; /* true for SQLite UTF-8 support */ + jstring enc; /* encoding or 0 */ + struct hfunc *funcs; /* SQLite user defined function handles */ +#if HAVE_SQLITE_COMPILE + struct hvm *vms; /* Compiled SQLite VMs */ +#endif +#if HAVE_SQLITE3 + sqlite3_stmt *stmt; /* For callback() */ +#endif +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + struct hbl *blobs; /* SQLite3 blob handles */ +#endif +} handle; + +/* internal handle for SQLite user defined function */ + +typedef struct hfunc { + struct hfunc *next; /* next function */ +#if HAVE_BOTH_SQLITE + int is3; /* True for SQLITE3 handle */ +#endif + jobject fc; /* FunctionContext object */ + jobject fi; /* Function object */ + jobject db; /* Database object */ + handle *h; /* SQLite database handle */ + void *sf; /* SQLite function handle */ + JNIEnv *env; /* Java environment for callbacks */ +} hfunc; + +#if HAVE_SQLITE_COMPILE +/* internal handle for SQLite VM (sqlite_compile()) */ + +typedef struct hvm { + struct hvm *next; /* next vm handle */ +#if HAVE_BOTH_SQLITE + int is3; /* True for SQLITE3 handle */ +#endif + void *vm; /* SQLite 2/3 VM/statement */ + char *tail; /* tail SQL string */ + int tail_len; /* only for SQLite3/prepare */ + handle *h; /* SQLite database handle */ + handle hh; /* fake SQLite database handle */ +} hvm; +#endif + +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO +/* internal handle for sqlite3_blob */ + +typedef struct hbl { + struct hbl *next; /* next blob handle */ + sqlite3_blob *blob; /* SQLite3 blob */ + handle *h; /* SQLite database handle */ +} hbl; +#endif + +/* ISO to/from UTF-8 translation */ + +typedef struct { + char *result; /* translated C string result */ + char *tofree; /* memory to be free'd, or 0 */ + jstring jstr; /* resulting Java string or 0 */ +} transstr; + +/* static cached weak class refs, field and method ids */ + +static jclass C_java_lang_String = 0; + +static jfieldID F_SQLite_Database_handle = 0; +static jfieldID F_SQLite_Database_error_code = 0; +static jfieldID F_SQLite_FunctionContext_handle = 0; +static jfieldID F_SQLite_Vm_handle = 0; +static jfieldID F_SQLite_Vm_error_code = 0; +static jfieldID F_SQLite_Stmt_handle = 0; +static jfieldID F_SQLite_Stmt_error_code = 0; +static jfieldID F_SQLite_Blob_handle = 0; +static jfieldID F_SQLite_Blob_size = 0; + +static jmethodID M_java_lang_String_getBytes = 0; +static jmethodID M_java_lang_String_getBytes2 = 0; +static jmethodID M_java_lang_String_initBytes = 0; +static jmethodID M_java_lang_String_initBytes2 = 0; + +static const char xdigits[] = "0123456789ABCDEF"; + +static void +seterr(JNIEnv *env, jobject obj, int err) +{ + jvalue v; + + v.j = 0; + v.i = (jint) err; + (*env)->SetIntField(env, obj, F_SQLite_Database_error_code, v.i); +} + +#if HAVE_SQLITE_COMPILE +static void +setvmerr(JNIEnv *env, jobject obj, int err) +{ + jvalue v; + + v.j = 0; + v.i = (jint) err; + (*env)->SetIntField(env, obj, F_SQLite_Vm_error_code, v.i); +} + +#if HAVE_SQLITE3 +static void +setstmterr(JNIEnv *env, jobject obj, int err) +{ + jvalue v; + + v.j = 0; + v.i = (jint) err; + (*env)->SetIntField(env, obj, F_SQLite_Stmt_error_code, v.i); +} + +static int +jstrlen(const jchar *jstr) +{ + int len = 0; + + if (jstr) { + while (*jstr++) { + len++; + } + } + return len; +} +#endif +#endif + +static void * +gethandle(JNIEnv *env, jobject obj) +{ + jvalue v; + + v.j = (*env)->GetLongField(env, obj, F_SQLite_Database_handle); + return (void *) v.l; +} + +#if HAVE_SQLITE_COMPILE +static void * +gethvm(JNIEnv *env, jobject obj) +{ + jvalue v; + + v.j = (*env)->GetLongField(env, obj, F_SQLite_Vm_handle); + return (void *) v.l; +} + +#if HAVE_SQLITE3 +static void * +gethstmt(JNIEnv *env, jobject obj) +{ + jvalue v; + + v.j = (*env)->GetLongField(env, obj, F_SQLite_Stmt_handle); + return (void *) v.l; +} +#endif +#endif + +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO +static void * +gethbl(JNIEnv *env, jobject obj) +{ + jvalue v; + + v.j = (*env)->GetLongField(env, obj, F_SQLite_Blob_handle); + return (void *) v.l; +} +#endif + +static void +delglobrefp(JNIEnv *env, jobject *obj) +{ + if (*obj) { + (*env)->DeleteGlobalRef(env, *obj); + *obj = 0; + } +} + +static jobject +globrefpop(JNIEnv *env, jobject *obj) +{ + jobject ret = 0; + + if (*obj) { + ret = *obj; + *obj = 0; + } + return ret; +} + +static void +globrefset(JNIEnv *env, jobject obj, jobject *ref) +{ + if (ref) { + if (obj) { + *ref = (*env)->NewGlobalRef(env, obj); + } else { + *ref = 0; + } + } +} + +static void +freep(char **strp) +{ + if (strp && *strp) { + free(*strp); + *strp = 0; + } +} + +static void +throwex(JNIEnv *env, const char *msg) +{ + jclass except = (*env)->FindClass(env, "SQLite/Exception"); + + (*env)->ExceptionClear(env); + if (except) { + (*env)->ThrowNew(env, except, msg); + } +} + +static void +throwoom(JNIEnv *env, const char *msg) +{ + jclass except = (*env)->FindClass(env, "java/lang/OutOfMemoryError"); + + (*env)->ExceptionClear(env); + if (except) { + (*env)->ThrowNew(env, except, msg); + } +} + +static void +throwclosed(JNIEnv *env) +{ + throwex(env, "database already closed"); +} + +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO +static void +throwioex(JNIEnv *env, const char *msg) +{ + jclass except = (*env)->FindClass(env, "java/io/IOException"); + + (*env)->ExceptionClear(env); + if (except) { + (*env)->ThrowNew(env, except, msg); + } +} +#endif + +static void +transfree(transstr *dest) +{ + dest->result = 0; + freep(&dest->tofree); +} + +static char * +trans2iso(JNIEnv *env, int haveutf, jstring enc, jstring src, + transstr *dest) +{ + jbyteArray bytes = 0; + jthrowable exc; + + dest->result = 0; + dest->tofree = 0; + if (haveutf) { + const jsize utfLength = (*env)->GetStringUTFLength(env, src); + dest->result = dest->tofree = malloc(utfLength + 1); + if (!dest->tofree) { + throwoom(env, "string translation failed"); + return dest->result; + } + (*env)->GetStringUTFRegion(env, src, 0, utfLength, dest->result); + return dest->result; + } + if (enc) { + bytes = (*env)->CallObjectMethod(env, src, + M_java_lang_String_getBytes2, enc); + } else { + bytes = (*env)->CallObjectMethod(env, src, + M_java_lang_String_getBytes); + } + exc = (*env)->ExceptionOccurred(env); + if (!exc) { + jint len = (*env)->GetArrayLength(env, bytes); + dest->tofree = malloc(len + 1); + if (!dest->tofree) { + throwoom(env, "string translation failed"); + return dest->result; + } + dest->result = dest->tofree; + (*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *) dest->result); + dest->result[len] = '\0'; + } else { + (*env)->DeleteLocalRef(env, exc); + } + return dest->result; +} + +static jstring +trans2utf(JNIEnv *env, int haveutf, jstring enc, const char *src, + transstr *dest) +{ + jbyteArray bytes = 0; + int len; + + dest->result = 0; + dest->tofree = 0; + dest->jstr = 0; + if (!src) { + return dest->jstr; + } + if (haveutf) { + dest->jstr = (*env)->NewStringUTF(env, src); + return dest->jstr; + } + len = strlen(src); + bytes = (*env)->NewByteArray(env, len); + if (bytes) { + (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) src); + if (enc) { + dest->jstr = + (*env)->NewObject(env, C_java_lang_String, + M_java_lang_String_initBytes2, bytes, enc); + } else { + dest->jstr = + (*env)->NewObject(env, C_java_lang_String, + M_java_lang_String_initBytes, bytes); + } + (*env)->DeleteLocalRef(env, bytes); + return dest->jstr; + } + throwoom(env, "string translation failed"); + return dest->jstr; +} + +#if HAVE_SQLITE2 +static int +busyhandler(void *udata, const char *table, int count) +{ + handle *h = (handle *) udata; + JNIEnv *env = h->env; + int ret = 0; + + if (env && h->bh) { + transstr tabstr; + jclass cls = (*env)->GetObjectClass(env, h->bh); + jmethodID mid = (*env)->GetMethodID(env, cls, "busy", + "(Ljava/lang/String;I)Z"); + + if (mid == 0) { + (*env)->DeleteLocalRef(env, cls); + return ret; + } + trans2utf(env, h->haveutf, h->enc, table, &tabstr); + ret = (*env)->CallBooleanMethod(env, h->bh, mid, tabstr.jstr, + (jint) count) + != JNI_FALSE; + (*env)->DeleteLocalRef(env, tabstr.jstr); + (*env)->DeleteLocalRef(env, cls); + } + return ret; +} +#endif + +#if HAVE_SQLITE3 +static int +busyhandler3(void *udata, int count) +{ + handle *h = (handle *) udata; + JNIEnv *env = h->env; + int ret = 0; + + if (env && h->bh) { + jclass cls = (*env)->GetObjectClass(env, h->bh); + jmethodID mid = (*env)->GetMethodID(env, cls, "busy", + "(Ljava/lang/String;I)Z"); + + if (mid == 0) { + (*env)->DeleteLocalRef(env, cls); + return ret; + } + ret = (*env)->CallBooleanMethod(env, h->bh, mid, 0, (jint) count) + != JNI_FALSE; + (*env)->DeleteLocalRef(env, cls); + } + return ret; +} +#endif + +static int +progresshandler(void *udata) +{ + handle *h = (handle *) udata; + JNIEnv *env = h->env; + int ret = 0; + + if (env && h->ph) { + jclass cls = (*env)->GetObjectClass(env, h->ph); + jmethodID mid = (*env)->GetMethodID(env, cls, "progress", "()Z"); + + if (mid == 0) { + (*env)->DeleteLocalRef(env, cls); + return ret; + } + ret = (*env)->CallBooleanMethod(env, h->ph, mid) != JNI_TRUE; + (*env)->DeleteLocalRef(env, cls); + } + return ret; +} + +static int +callback(void *udata, int ncol, char **data, char **cols) +{ + handle *h = (handle *) udata; + JNIEnv *env = h->env; + + if (env && h->cb) { + jthrowable exc; + jclass cls = (*env)->GetObjectClass(env, h->cb); + jmethodID mid; + jobjectArray arr = 0; + jint i; + + if (h->row1) { + mid = (*env)->GetMethodID(env, cls, "columns", + "([Ljava/lang/String;)V"); + + if (mid) { + arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0); + for (i = 0; i < ncol; i++) { + if (cols[i]) { + transstr col; + + trans2utf(env, h->haveutf, h->enc, cols[i], &col); + (*env)->SetObjectArrayElement(env, arr, i, col.jstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, col.jstr); + } + } + h->row1 = 0; + (*env)->CallVoidMethod(env, h->cb, mid, arr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, arr); + } +#if HAVE_BOTH_SQLITE + if (h->is3) { + mid = (*env)->GetMethodID(env, cls, "types", + "([Ljava/lang/String;)V"); + + if (mid && h->stmt) { + arr = (*env)->NewObjectArray(env, ncol, + C_java_lang_String, 0); + for (i = 0; i < ncol; i++) { + const char *ctype = + sqlite3_column_decltype(h->stmt, i); + + if (!ctype) { + switch (sqlite3_column_type(h->stmt, i)) { + case SQLITE_INTEGER: ctype = "integer"; break; + case SQLITE_FLOAT: ctype = "double"; break; + default: +#if defined(SQLITE_TEXT) && defined(SQLITE3_TEXT) && (SQLITE_TEXT != SQLITE3_TEXT) + case SQLITE_TEXT: +#else +#ifdef SQLITE3_TEXT + case SQLITE3_TEXT: +#endif +#endif + ctype = "text"; break; + case SQLITE_BLOB: ctype = "blob"; break; + case SQLITE_NULL: ctype = "null"; break; + } + } + if (ctype) { + transstr ty; + + trans2utf(env, 1, 0, ctype, &ty); + (*env)->SetObjectArrayElement(env, arr, i, + ty.jstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, ty.jstr); + } + } + (*env)->CallVoidMethod(env, h->cb, mid, arr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, arr); + } + } else { + if (h->ver >= 0x020506 && cols[ncol]) { + mid = (*env)->GetMethodID(env, cls, "types", + "([Ljava/lang/String;)V"); + + if (mid) { + arr = (*env)->NewObjectArray(env, ncol, + C_java_lang_String, 0); + for (i = 0; i < ncol; i++) { + if (cols[i + ncol]) { + transstr ty; + + trans2utf(env, h->haveutf, h->enc, + cols[i + ncol], &ty); + (*env)->SetObjectArrayElement(env, arr, i, + ty.jstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, ty.jstr); + } + } + (*env)->CallVoidMethod(env, h->cb, mid, arr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, arr); + } + } + } +#else +#if HAVE_SQLITE2 + if (h->ver >= 0x020506 && cols[ncol]) { + mid = (*env)->GetMethodID(env, cls, "types", + "([Ljava/lang/String;)V"); + + if (mid) { + arr = (*env)->NewObjectArray(env, ncol, + C_java_lang_String, 0); + for (i = 0; i < ncol; i++) { + if (cols[i + ncol]) { + transstr ty; + + trans2utf(env, h->haveutf, h->enc, + cols[i + ncol], &ty); + (*env)->SetObjectArrayElement(env, arr, i, + ty.jstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, ty.jstr); + } + } + (*env)->CallVoidMethod(env, h->cb, mid, arr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, arr); + } + } +#endif +#if HAVE_SQLITE3 + mid = (*env)->GetMethodID(env, cls, "types", + "([Ljava/lang/String;)V"); + + if (mid && h->stmt) { + arr = (*env)->NewObjectArray(env, ncol, + C_java_lang_String, 0); + for (i = 0; i < ncol; i++) { + const char *ctype = sqlite3_column_decltype(h->stmt, i); + + if (!ctype) { + switch (sqlite3_column_type(h->stmt, i)) { + case SQLITE_INTEGER: ctype = "integer"; break; + case SQLITE_FLOAT: ctype = "double"; break; + default: +#if defined(SQLITE_TEXT) && defined(SQLITE3_TEXT) && (SQLITE_TEXT != SQLITE3_TEXT) + case SQLITE_TEXT: +#else +#ifdef SQLITE3_TEXT + case SQLITE3_TEXT: +#endif +#endif + ctype = "text"; break; + case SQLITE_BLOB: ctype = "blob"; break; + case SQLITE_NULL: ctype = "null"; break; + } + } + if (ctype) { + transstr ty; + + trans2utf(env, 1, 0, ctype, &ty); + (*env)->SetObjectArrayElement(env, arr, i, ty.jstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, ty.jstr); + } + } + (*env)->CallVoidMethod(env, h->cb, mid, arr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, arr); + } +#endif +#endif + } + mid = (*env)->GetMethodID(env, cls, "newrow", + "([Ljava/lang/String;)Z"); + if (mid) { + jboolean rc; + + if (data) { + arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0); + } else { + arr = 0; + } + for (i = 0; arr && i < ncol; i++) { + if (data[i]) { + transstr dats; + + trans2utf(env, h->haveutf, h->enc, data[i], &dats); + (*env)->SetObjectArrayElement(env, arr, i, dats.jstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + (*env)->DeleteLocalRef(env, dats.jstr); + } + } + rc = (*env)->CallBooleanMethod(env, h->cb, mid, arr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return 1; + } + if (arr) { + (*env)->DeleteLocalRef(env, arr); + } + (*env)->DeleteLocalRef(env, cls); + return rc != JNI_FALSE; + } + } + return 0; +} + +static void +doclose(JNIEnv *env, jobject obj, int final) +{ + handle *h = gethandle(env, obj); + + if (h) { + hfunc *f; +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + hbl *bl; +#endif +#if HAVE_SQLITE_COMPILE + hvm *v; + + while ((v = h->vms)) { + h->vms = v->next; + v->next = 0; + v->h = 0; + if (v->vm) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_finalize((sqlite3_stmt *) v->vm); + } else { + sqlite_finalize((sqlite_vm *) v->vm, 0); + } +#else +#if HAVE_SQLITE2 + sqlite_finalize((sqlite_vm *) v->vm, 0); +#endif +#if HAVE_SQLITE3 + sqlite3_finalize((sqlite3_stmt *) v->vm); +#endif +#endif + v->vm = 0; + } + } +#endif + if (h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_close((sqlite3 *) h->sqlite); + } else { + sqlite_close((sqlite *) h->sqlite); + } +#else +#if HAVE_SQLITE2 + sqlite_close((sqlite *) h->sqlite); +#endif +#if HAVE_SQLITE3 + sqlite3_close((sqlite3 *) h->sqlite); +#endif +#endif + h->sqlite = 0; + } + while ((f = h->funcs)) { + h->funcs = f->next; + f->h = 0; + f->sf = 0; + f->env = 0; + if (f->fc) { + (*env)->SetLongField(env, f->fc, + F_SQLite_FunctionContext_handle, 0); + } + delglobrefp(env, &f->db); + delglobrefp(env, &f->fi); + delglobrefp(env, &f->fc); + free(f); + } +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + while ((bl = h->blobs)) { + h->blobs = bl->next; + bl->next = 0; + bl->h = 0; + if (bl->blob) { + sqlite3_blob_close(bl->blob); + } + bl->blob = 0; + } +#endif + delglobrefp(env, &h->bh); + delglobrefp(env, &h->cb); + delglobrefp(env, &h->ai); + delglobrefp(env, &h->tr); + delglobrefp(env, &h->ph); + delglobrefp(env, &h->enc); + free(h); + (*env)->SetLongField(env, obj, F_SQLite_Database_handle, 0); + return; + } + if (!final) { + throwclosed(env); + } +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1close(JNIEnv *env, jobject obj) +{ + doclose(env, obj, 0); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1finalize(JNIEnv *env, jobject obj) +{ + doclose(env, obj, 1); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1busy_1timeout(JNIEnv *env, jobject obj, jint ms) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_busy_timeout((sqlite3 * ) h->sqlite, ms); + } else { + sqlite_busy_timeout((sqlite *) h->sqlite, ms); + } +#else +#if HAVE_SQLITE2 + sqlite_busy_timeout((sqlite *) h->sqlite, ms); +#endif +#if HAVE_SQLITE3 + sqlite3_busy_timeout((sqlite3 * ) h->sqlite, ms); +#endif +#endif + return; + } + throwclosed(env); +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Database_version(JNIEnv *env, jclass cls) +{ + /* CHECK THIS */ +#if HAVE_BOTH_SQLITE + return (*env)->NewStringUTF(env, sqlite_libversion()); +#else +#if HAVE_SQLITE2 + return (*env)->NewStringUTF(env, sqlite_libversion()); +#else + return (*env)->NewStringUTF(env, sqlite3_libversion()); +#endif +#endif +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Database_dbversion(JNIEnv *env, jobject obj) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + return (*env)->NewStringUTF(env, sqlite3_libversion()); + } else { + return (*env)->NewStringUTF(env, sqlite_libversion()); + } +#else +#if HAVE_SQLITE2 + return (*env)->NewStringUTF(env, sqlite_libversion()); +#else + return (*env)->NewStringUTF(env, sqlite3_libversion()); +#endif +#endif + } + return (*env)->NewStringUTF(env, "unknown"); +} + +JNIEXPORT jlong JNICALL +Java_SQLite_Database__1last_1insert_1rowid(JNIEnv *env, jobject obj) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + return (jlong) sqlite3_last_insert_rowid((sqlite3 *) h->sqlite); + } else { + return (jlong) sqlite_last_insert_rowid((sqlite *) h->sqlite); + } +#else +#if HAVE_SQLITE2 + return (jlong) sqlite_last_insert_rowid((sqlite *) h->sqlite); +#endif +#if HAVE_SQLITE3 + return (jlong) sqlite3_last_insert_rowid((sqlite3 *) h->sqlite); +#endif +#endif + } + throwclosed(env); + return (jlong) 0; +} + +JNIEXPORT jlong JNICALL +Java_SQLite_Database__1changes(JNIEnv *env, jobject obj) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + return (jlong) sqlite3_changes((sqlite3 *) h->sqlite); + } else { + return (jlong) sqlite_changes((sqlite *) h->sqlite); + } +#else +#if HAVE_SQLITE2 + return (jlong) sqlite_changes((sqlite *) h->sqlite); +#endif +#if HAVE_SQLITE3 + return (jlong) sqlite3_changes((sqlite3 *) h->sqlite); +#endif +#endif + } + throwclosed(env); + return (jlong) 0; +} + +JNIEXPORT jboolean JNICALL +Java_SQLite_Database__1complete(JNIEnv *env, jclass cls, jstring sql) +{ + transstr sqlstr; + jboolean result; + + if (!sql) { + return JNI_FALSE; + } +#if HAVE_BOTH_SQLITE || HAVE_SQLITE3 + /* CHECK THIS */ + trans2iso(env, 1, 0, sql, &sqlstr); + result = sqlite3_complete(sqlstr.result) ? JNI_TRUE : JNI_FALSE; +#else + trans2iso(env, strcmp(sqlite_libencoding(), "UTF-8") == 0, 0, + sql, &sqlstr); + result = sqlite_complete(sqlstr.result) ? JNI_TRUE : JNI_FALSE; +#endif + transfree(&sqlstr); + return result; +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1interrupt(JNIEnv *env, jobject obj) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_interrupt((sqlite3 *) h->sqlite); + } else { + sqlite_interrupt((sqlite *) h->sqlite); + } +#else +#if HAVE_SQLITE2 + sqlite_interrupt((sqlite *) h->sqlite); +#endif +#if HAVE_SQLITE3 + sqlite3_interrupt((sqlite3 *) h->sqlite); +#endif +#endif + return; + } + throwclosed(env); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1open(JNIEnv *env, jobject obj, jstring file, jint mode) +{ + handle *h = gethandle(env, obj); + jthrowable exc; + char *err = 0; + transstr filename; + int maj, min, lev; + + if (h) { + if (h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_close((sqlite3 *) h->sqlite); + } else { + sqlite_close((sqlite *) h->sqlite); + } + h->is3 = 0; +#else +#if HAVE_SQLITE2 + sqlite_close((sqlite *) h->sqlite); +#endif +#if HAVE_SQLITE3 + sqlite3_close((sqlite3 *) h->sqlite); +#endif +#endif + h->sqlite = 0; + } + } else { + h = malloc(sizeof (handle)); + if (!h) { + throwoom(env, "unable to get SQLite handle"); + return; + } + h->sqlite = 0; + h->bh = h->cb = h->ai = h->tr = h->ph = 0; + /* CHECK THIS */ +#if HAVE_BOTH_SQLITE + h->is3 = 0; + h->stmt = 0; + h->haveutf = 1; +#else +#if HAVE_SQLITE2 + h->haveutf = strcmp(sqlite_libencoding(), "UTF-8") == 0; +#endif +#if HAVE_SQLITE3 + h->stmt = 0; + h->haveutf = 1; +#endif +#endif + h->enc = 0; + h->funcs = 0; + h->ver = 0; +#if HAVE_SQLITE_COMPILE + h->vms = 0; +#endif +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + h->blobs = 0; +#endif + } + h->env = 0; + if (!file) { + throwex(env, err ? err : "invalid file name"); + return; + } + trans2iso(env, h->haveutf, h->enc, file, &filename); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } +#if HAVE_BOTH_SQLITE + { + FILE *f = fopen(filename.result, "rb"); + int c_0 = EOF; + + if (f) { + c_0 = fgetc(f); + fclose(f); + } + if (c_0 != '*') { + int rc = sqlite3_open(filename.result, (sqlite3 **) &h->sqlite); + + if (rc == SQLITE_OK) { + h->is3 = 1; + } else if (h->sqlite) { + sqlite3_close((sqlite3 *) h->sqlite); + h->sqlite = 0; + } + } else { + h->sqlite = (void *) sqlite_open(filename.result, + (int) mode, &err); + } + } +#else +#if HAVE_SQLITE2 + h->sqlite = (void *) sqlite_open(filename.result, (int) mode, &err); +#endif +#if HAVE_SQLITE3 + if (sqlite3_open(filename.result, (sqlite3 **) &h->sqlite) != SQLITE_OK) { + if (h->sqlite) { + sqlite3_close((sqlite3 *) h->sqlite); + h->sqlite = 0; + } + } +#endif +#endif + transfree(&filename); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); +#if HAVE_SQLITE2 + if (err) { + sqlite_freemem(err); + } +#endif + if (h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_close((sqlite3 *) h->sqlite); + h->is3 = 0; + } else { + sqlite_close((sqlite *) h->sqlite); + } +#else +#if HAVE_SQLITE2 + sqlite_close((sqlite *) h->sqlite); +#endif +#if HAVE_SQLITE3 + sqlite3_close((sqlite3 *) h->sqlite); +#endif +#endif + } + h->sqlite = 0; + return; + } + if (h->sqlite) { + jvalue v; + + v.j = 0; + v.l = (jobject) h; + (*env)->SetLongField(env, obj, F_SQLite_Database_handle, v.j); +#if HAVE_SQLITE2 + if (err) { + sqlite_freemem(err); + } +#endif +#if HAVE_BOTH_SQLITE + if (h->is3) { + sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev); + } else { + sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev); + } +#else +#if HAVE_SQLITE2 + sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev); +#endif +#if HAVE_SQLITE3 + sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev); +#endif +#endif + h->ver = ((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (lev & 0xFF); + return; + } + throwex(env, err ? err : "unknown error in open"); +#if HAVE_SQLITE2 + if (err) { + sqlite_freemem(err); + } +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1open_1aux_1file(JNIEnv *env, jobject obj, jstring file) +{ + handle *h = gethandle(env, obj); +#if HAVE_SQLITE_OPEN_AUX_FILE + jboolean b; + jthrowable exc; + char *err = 0; + transstr filename; + int ret; +#endif + + if (h && h->sqlite) { +#if HAVE_SQLITE_OPEN_AUX_FILE +#if HAVE_BOTH_SQLITE + if (h->is3) { + throwex(env, "unsupported"); + } +#endif + trans2iso(env, h->haveutf, h->enc, file, &filename); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + ret = sqlite_open_aux_file((sqlite *) h->sqlite, + filename.result, &err); + transfree(&filename); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + if (err) { + sqlite_freemem(err); + } + return; + } + if (ret != SQLITE_OK) { + throwex(env, err ? err : sqlite_error_string(ret)); + } + if (err) { + sqlite_freemem(err); + } +#else + throwex(env, "unsupported"); +#endif + return; + } + throwclosed(env); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1busy_1handler(JNIEnv *env, jobject obj, jobject bh) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { + delglobrefp(env, &h->bh); + globrefset(env, bh, &h->bh); +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_busy_handler((sqlite3 *) h->sqlite, busyhandler3, h); + } else { + sqlite_busy_handler((sqlite *) h->sqlite, busyhandler, h); + } +#else +#if HAVE_SQLITE2 + sqlite_busy_handler((sqlite *) h->sqlite, busyhandler, h); +#endif +#if HAVE_SQLITE3 + sqlite3_busy_handler((sqlite3 *) h->sqlite, busyhandler3, h); +#endif +#endif + return; + } + throwclosed(env); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2 + (JNIEnv *env, jobject obj, jstring sql, jobject cb) +{ + handle *h = gethandle(env, obj); + freemem *freeproc; + + if (!sql) { + throwex(env, "invalid SQL statement"); + return; + } + if (h) { + if (h->sqlite) { + jthrowable exc; + int rc; + char *err = 0; + transstr sqlstr; + jobject oldcb = globrefpop(env, &h->cb); + + globrefset(env, cb, &h->cb); + h->env = env; + h->row1 = 1; + trans2iso(env, h->haveutf, h->enc, sql, &sqlstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } +#if HAVE_BOTH_SQLITE + if (h->is3) { + rc = sqlite3_exec((sqlite3 *) h->sqlite, sqlstr.result, + callback, h, &err); + freeproc = (freemem *) sqlite3_free; + } else { + rc = sqlite_exec((sqlite *) h->sqlite, sqlstr.result, + callback, h, &err); + freeproc = (freemem *) sqlite_freemem; + } +#else +#if HAVE_SQLITE2 + rc = sqlite_exec((sqlite *) h->sqlite, sqlstr.result, + callback, h, &err); + freeproc = (freemem *) sqlite_freemem; +#endif +#if HAVE_SQLITE3 + rc = sqlite3_exec((sqlite3 *) h->sqlite, sqlstr.result, + callback, h, &err); + freeproc = (freemem *) sqlite3_free; +#endif +#endif + transfree(&sqlstr); + exc = (*env)->ExceptionOccurred(env); + delglobrefp(env, &h->cb); + h->cb = oldcb; + if (exc) { + (*env)->DeleteLocalRef(env, exc); + if (err) { + freeproc(err); + } + return; + } + if (rc != SQLITE_OK) { + char msg[128]; + + seterr(env, obj, rc); + if (!err) { + sprintf(msg, "error %d in sqlite*_exec", rc); + } + throwex(env, err ? err : msg); + } + if (err) { + freeproc(err); + } + return; + } + } + throwclosed(env); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2 + (JNIEnv *env, jobject obj, jstring sql, jobject cb, jobjectArray args) +{ + handle *h = gethandle(env, obj); + freemem *freeproc = 0; + + if (!sql) { + throwex(env, "invalid SQL statement"); + return; + } + if (h) { + if (h->sqlite) { + jthrowable exc; + int rc = SQLITE_ERROR, nargs, i; + char *err = 0, *p; + const char *str = (*env)->GetStringUTFChars(env, sql, NULL); + transstr sqlstr; + struct args { + char *arg; + jobject obj; + transstr trans; + } *argv = 0; + char **cargv = 0; + jobject oldcb = globrefpop(env, &h->cb); + + globrefset(env, cb, &h->cb); + p = (char *) str; + nargs = 0; + while (*p) { + if (*p == '%') { + ++p; + if (*p == 'q' || *p == 's') { + nargs++; + if (nargs > MAX_PARAMS) { + (*env)->ReleaseStringUTFChars(env, sql, str); + delglobrefp(env, &h->cb); + h->cb = oldcb; + throwex(env, "too much SQL parameters"); + return; + } + } else if (h->ver >= 0x020500 && *p == 'Q') { + nargs++; + if (nargs > MAX_PARAMS) { + (*env)->ReleaseStringUTFChars(env, sql, str); + delglobrefp(env, &h->cb); + h->cb = oldcb; + throwex(env, "too much SQL parameters"); + return; + } + } else if (*p != '%') { + (*env)->ReleaseStringUTFChars(env, sql, str); + delglobrefp(env, &h->cb); + h->cb = oldcb; + throwex(env, "bad % specification in query"); + return; + } + } + ++p; + } + cargv = malloc((sizeof (*argv) + sizeof (char *)) + * MAX_PARAMS); + if (!cargv) { + (*env)->ReleaseStringUTFChars(env, sql, str); + delglobrefp(env, &h->cb); + h->cb = oldcb; + throwoom(env, "unable to allocate arg vector"); + return; + } + argv = (struct args *) (cargv + MAX_PARAMS); + for (i = 0; i < MAX_PARAMS; i++) { + cargv[i] = 0; + argv[i].arg = 0; + argv[i].obj = 0; + argv[i].trans.result = argv[i].trans.tofree = 0; + } + exc = 0; + for (i = 0; i < nargs; i++) { + jobject so = (*env)->GetObjectArrayElement(env, args, i); + + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + break; + } + if (so) { + argv[i].obj = so; + argv[i].arg = cargv[i] = + trans2iso(env, h->haveutf, h->enc, argv[i].obj, + &argv[i].trans); + } + } + if (exc) { + for (i = 0; i < nargs; i++) { + if (argv[i].obj) { + transfree(&argv[i].trans); + } + } + freep((char **) &cargv); + (*env)->ReleaseStringUTFChars(env, sql, str); + delglobrefp(env, &h->cb); + h->cb = oldcb; + return; + } + h->env = env; + h->row1 = 1; + trans2iso(env, h->haveutf, h->enc, sql, &sqlstr); + exc = (*env)->ExceptionOccurred(env); + if (!exc) { +#if HAVE_BOTH_SQLITE + if (h->is3) { +#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR) + char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv); +#else + char *s = sqlite3_mprintf(sqlstr.result, + cargv[0], cargv[1], + cargv[2], cargv[3], + cargv[4], cargv[5], + cargv[6], cargv[7], + cargv[8], cargv[9], + cargv[10], cargv[11], + cargv[12], cargv[13], + cargv[14], cargv[15], + cargv[16], cargv[17], + cargv[18], cargv[19], + cargv[20], cargv[21], + cargv[22], cargv[23], + cargv[24], cargv[25], + cargv[26], cargv[27], + cargv[28], cargv[29], + cargv[30], cargv[31]); +#endif + + if (s) { + rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback, + h, &err); + sqlite3_free(s); + } else { + rc = SQLITE_NOMEM; + } + freeproc = (freemem *) sqlite3_free; + } else { +#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR) + rc = sqlite_exec_vprintf((sqlite *) h->sqlite, + sqlstr.result, callback, h, &err, + (char *) cargv); +#else + rc = sqlite_exec_printf((sqlite *) h->sqlite, + sqlstr.result, callback, + h, &err, + cargv[0], cargv[1], + cargv[2], cargv[3], + cargv[4], cargv[5], + cargv[6], cargv[7], + cargv[8], cargv[9], + cargv[10], cargv[11], + cargv[12], cargv[13], + cargv[14], cargv[15], + cargv[16], cargv[17], + cargv[18], cargv[19], + cargv[20], cargv[21], + cargv[22], cargv[23], + cargv[24], cargv[25], + cargv[26], cargv[27], + cargv[28], cargv[29], + cargv[30], cargv[31]); +#endif + freeproc = (freemem *) sqlite_freemem; + } +#else +#if HAVE_SQLITE2 +#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR) + rc = sqlite_exec_vprintf((sqlite *) h->sqlite, sqlstr.result, + callback, h, &err, (char *) cargv); +#else + rc = sqlite_exec_printf((sqlite *) h->sqlite, sqlstr.result, + callback, h, &err, + cargv[0], cargv[1], + cargv[2], cargv[3], + cargv[4], cargv[5], + cargv[6], cargv[7], + cargv[8], cargv[9], + cargv[10], cargv[11], + cargv[12], cargv[13], + cargv[14], cargv[15], + cargv[16], cargv[17], + cargv[18], cargv[19], + cargv[20], cargv[21], + cargv[22], cargv[23], + cargv[24], cargv[25], + cargv[26], cargv[27], + cargv[28], cargv[29], + cargv[30], cargv[31]); +#endif + freeproc = (freemem *) sqlite_freemem; +#endif +#if HAVE_SQLITE3 +#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR) + char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv); +#else + char *s = sqlite3_mprintf(sqlstr.result, + cargv[0], cargv[1], + cargv[2], cargv[3], + cargv[4], cargv[5], + cargv[6], cargv[7], + cargv[8], cargv[9], + cargv[10], cargv[11], + cargv[12], cargv[13], + cargv[14], cargv[15], + cargv[16], cargv[17], + cargv[18], cargv[19], + cargv[20], cargv[21], + cargv[22], cargv[23], + cargv[24], cargv[25], + cargv[26], cargv[27], + cargv[28], cargv[29], + cargv[30], cargv[31]); +#endif + + if (s) { + rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback, + h, &err); + sqlite3_free(s); + } else { + rc = SQLITE_NOMEM; + } + freeproc = (freemem *) sqlite3_free; +#endif +#endif + exc = (*env)->ExceptionOccurred(env); + } + for (i = 0; i < nargs; i++) { + if (argv[i].obj) { + transfree(&argv[i].trans); + } + } + transfree(&sqlstr); + (*env)->ReleaseStringUTFChars(env, sql, str); + freep((char **) &cargv); + delglobrefp(env, &h->cb); + h->cb = oldcb; + if (exc) { + (*env)->DeleteLocalRef(env, exc); + if (err && freeproc) { + freeproc(err); + } + return; + } + if (rc != SQLITE_OK) { + char msg[128]; + + seterr(env, obj, rc); + if (!err) { + sprintf(msg, "error %d in sqlite*_exec", rc); + } + throwex(env, err ? err : msg); + } + if (err && freeproc) { + freeproc(err); + } + return; + } + } + throwclosed(env); +} + +static hfunc * +getfunc(JNIEnv *env, jobject obj) +{ + jvalue v; + + v.j = (*env)->GetLongField(env, obj, F_SQLite_FunctionContext_handle); + return (hfunc *) v.l; +} + +#if HAVE_SQLITE2 +static void +call_common(sqlite_func *sf, int isstep, int nargs, const char **args) +{ + hfunc *f = (hfunc *) sqlite_user_data(sf); + + if (f && f->env && f->fi) { + JNIEnv *env = f->env; + jclass cls = (*env)->GetObjectClass(env, f->fi); + jmethodID mid = + (*env)->GetMethodID(env, cls, + isstep ? "step" : "function", + "(LSQLite/FunctionContext;[Ljava/lang/String;)V"); + jobjectArray arr; + int i; + + if (mid == 0) { + (*env)->DeleteLocalRef(env, cls); + return; + } + arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0); + for (i = 0; i < nargs; i++) { + if (args[i]) { + transstr arg; + jthrowable exc; + + trans2utf(env, f->h->haveutf, f->h->enc, args[i], &arg); + (*env)->SetObjectArrayElement(env, arr, i, arg.jstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + (*env)->DeleteLocalRef(env, arg.jstr); + } + } + f->sf = sf; + (*env)->CallVoidMethod(env, f->fi, mid, f->fc, arr); + (*env)->DeleteLocalRef(env, arr); + (*env)->DeleteLocalRef(env, cls); + } +} + +static void +call_func(sqlite_func *sf, int nargs, const char **args) +{ + call_common(sf, 0, nargs, args); +} + +static void +call_step(sqlite_func *sf, int nargs, const char **args) +{ + call_common(sf, 1, nargs, args); +} + +static void +call_final(sqlite_func *sf) +{ + hfunc *f = (hfunc *) sqlite_user_data(sf); + + if (f && f->env && f->fi) { + JNIEnv *env = f->env; + jclass cls = (*env)->GetObjectClass(env, f->fi); + jmethodID mid = (*env)->GetMethodID(env, cls, "last_step", + "(LSQLite/FunctionContext;)V"); + if (mid == 0) { + (*env)->DeleteLocalRef(env, cls); + return; + } + f->sf = sf; + (*env)->CallVoidMethod(env, f->fi, mid, f->fc); + (*env)->DeleteLocalRef(env, cls); + } +} +#endif + +#if HAVE_SQLITE3 +static void +call3_common(sqlite3_context *sf, int isstep, int nargs, sqlite3_value **args) +{ + hfunc *f = (hfunc *) sqlite3_user_data(sf); + + if (f && f->env && f->fi) { + JNIEnv *env = f->env; + jclass cls = (*env)->GetObjectClass(env, f->fi); + jmethodID mid = + (*env)->GetMethodID(env, cls, + isstep ? "step" : "function", + "(LSQLite/FunctionContext;[Ljava/lang/String;)V"); + jobjectArray arr; + int i; + + if (mid == 0) { + (*env)->DeleteLocalRef(env, cls); + return; + } + arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0); + for (i = 0; i < nargs; i++) { + if (args[i]) { + transstr arg; + jthrowable exc; + + trans2utf(env, 1, 0, (char *) sqlite3_value_text(args[i]), + &arg); + (*env)->SetObjectArrayElement(env, arr, i, arg.jstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + (*env)->DeleteLocalRef(env, arg.jstr); + } + } + f->sf = sf; + (*env)->CallVoidMethod(env, f->fi, mid, f->fc, arr); + (*env)->DeleteLocalRef(env, arr); + (*env)->DeleteLocalRef(env, cls); + } +} + +static void +call3_func(sqlite3_context *sf, int nargs, sqlite3_value **args) +{ + call3_common(sf, 0, nargs, args); +} + +static void +call3_step(sqlite3_context *sf, int nargs, sqlite3_value **args) +{ + call3_common(sf, 1, nargs, args); +} + +static void +call3_final(sqlite3_context *sf) +{ + hfunc *f = (hfunc *) sqlite3_user_data(sf); + + if (f && f->env && f->fi) { + JNIEnv *env = f->env; + jclass cls = (*env)->GetObjectClass(env, f->fi); + jmethodID mid = (*env)->GetMethodID(env, cls, "last_step", + "(LSQLite/FunctionContext;)V"); + if (mid == 0) { + (*env)->DeleteLocalRef(env, cls); + return; + } + f->sf = sf; + (*env)->CallVoidMethod(env, f->fi, mid, f->fc); + (*env)->DeleteLocalRef(env, cls); + } +} +#endif + +static void +mkfunc_common(JNIEnv *env, int isagg, jobject obj, jstring name, + jint nargs, jobject fi) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { + jclass cls = (*env)->FindClass(env, "SQLite/FunctionContext"); + jobject fc; + hfunc *f; + int ret; + transstr namestr; + jvalue v; + jthrowable exc; + + fc = (*env)->AllocObject(env, cls); + if (!fi) { + throwex(env, "null SQLite.Function not allowed"); + return; + } + f = malloc(sizeof (hfunc)); + if (!f) { + throwoom(env, "unable to get SQLite.FunctionContext handle"); + return; + } + globrefset(env, fc, &f->fc); + globrefset(env, fi, &f->fi); + globrefset(env, obj, &f->db); + f->h = h; + f->next = h->funcs; + h->funcs = f; + f->sf = 0; + f->env = env; + v.j = 0; + v.l = (jobject) f; + (*env)->SetLongField(env, f->fc, F_SQLite_FunctionContext_handle, v.j); + trans2iso(env, h->haveutf, h->enc, name, &namestr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } +#if HAVE_BOTH_SQLITE + f->is3 = h->is3; + if (h->is3) { + ret = sqlite3_create_function((sqlite3 *) h->sqlite, + namestr.result, + (int) nargs, + SQLITE_UTF8, f, + isagg ? NULL : call3_func, + isagg ? call3_step : NULL, + isagg ? call3_final : NULL); + + } else { + if (isagg) { + ret = sqlite_create_aggregate((sqlite *) h->sqlite, + namestr.result, + (int) nargs, + call_step, call_final, f); + } else { + ret = sqlite_create_function((sqlite *) h->sqlite, + namestr.result, + (int) nargs, + call_func, f); + } + } +#else +#if HAVE_SQLITE2 + if (isagg) { + ret = sqlite_create_aggregate((sqlite *) h->sqlite, namestr.result, + (int) nargs, + call_step, call_final, f); + } else { + ret = sqlite_create_function((sqlite *) h->sqlite, namestr.result, + (int) nargs, + call_func, f); + } +#endif +#if HAVE_SQLITE3 + ret = sqlite3_create_function((sqlite3 *) h->sqlite, + namestr.result, + (int) nargs, + SQLITE_UTF8, f, + isagg ? NULL : call3_func, + isagg ? call3_step : NULL, + isagg ? call3_final : NULL); +#endif +#endif + transfree(&namestr); + if (ret != SQLITE_OK) { + throwex(env, "error creating function/aggregate"); + } + return; + } + throwclosed(env); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1create_1aggregate(JNIEnv *env, jobject obj, + jstring name, jint nargs, jobject fi) +{ + mkfunc_common(env, 1, obj, name, nargs, fi); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1create_1function(JNIEnv *env, jobject obj, + jstring name, jint nargs, jobject fi) +{ + mkfunc_common(env, 0, obj, name, nargs, fi); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1function_1type(JNIEnv *env, jobject obj, + jstring name, jint type) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { +#if HAVE_BOTH_SQLITE + if (h->is3) { + return; + } +#endif +#if HAVE_SQLITE2 +#if HAVE_SQLITE_FUNCTION_TYPE + { + int ret; + transstr namestr; + jthrowable exc; + + trans2iso(env, h->haveutf, h->enc, name, &namestr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + ret = sqlite_function_type(h->sqlite, namestr.result, (int) type); + transfree(&namestr); + if (ret != SQLITE_OK) { + throwex(env, sqlite_error_string(ret)); + } + } +#endif +#endif + return; + } + throwclosed(env); +} + +JNIEXPORT jint JNICALL +Java_SQLite_FunctionContext_count(JNIEnv *env, jobject obj) +{ + hfunc *f = getfunc(env, obj); + jint r = 0; + + if (f && f->sf) { +#if HAVE_SQLITE_BOTH + if (f->is3) { + r = (jint) sqlite3_aggregate_count((sqlite3_context *) f->sf); + } else { + r = (jint) sqlite_aggregate_count((sqlite_func *) f->sf); + } +#else +#if HAVE_SQLITE2 + r = (jint) sqlite_aggregate_count((sqlite_func *) f->sf); +#endif +#if HAVE_SQLITE3 + r = (jint) sqlite3_aggregate_count((sqlite3_context *) f->sf); +#endif +#endif + } + return r; +} + +JNIEXPORT void JNICALL +Java_SQLite_FunctionContext_set_1error(JNIEnv *env, jobject obj, jstring err) +{ + hfunc *f = getfunc(env, obj); + + if (f && f->sf) { +#if HAVE_BOTH_SQLITE + if (!f->is3) { + transstr errstr; + jthrowable exc; + + trans2iso(env, f->h->haveutf, f->h->enc, err, &errstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + sqlite_set_result_error((sqlite_func *) f->sf, + errstr.result, -1); + transfree(&errstr); + } else if (err) { + jsize len = (*env)->GetStringLength(env, err) * sizeof (jchar); + const jchar *str = (*env)->GetStringChars(env, err, 0); + + sqlite3_result_error16((sqlite3_context *) f->sf, str, len); + (*env)->ReleaseStringChars(env, err, str); + } else { + sqlite3_result_error((sqlite3_context *) f->sf, + "null error text", -1); + } +#else +#if HAVE_SQLITE2 + transstr errstr; + jthrowable exc; + + trans2iso(env, f->h->haveutf, f->h->enc, err, &errstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + sqlite_set_result_error((sqlite_func *) f->sf, errstr.result, -1); + transfree(&errstr); +#endif +#if HAVE_SQLITE3 + if (err) { + jsize len = (*env)->GetStringLength(env, err) * sizeof (jchar); + const jchar *str = (*env)->GetStringChars(env, err, 0); + + sqlite3_result_error16((sqlite3_context *) f->sf, str, len); + (*env)->ReleaseStringChars(env, err, str); + } else { + sqlite3_result_error((sqlite3_context *) f->sf, + "null error text", -1); + } +#endif +#endif + } +} + +JNIEXPORT void JNICALL +Java_SQLite_FunctionContext_set_1result__D(JNIEnv *env, jobject obj, jdouble d) +{ + hfunc *f = getfunc(env, obj); + + if (f && f->sf) { +#if HAVE_BOTH_SQLITE + if (f->is3) { + sqlite3_result_double((sqlite3_context *) f->sf, (double) d); + } else { + sqlite_set_result_double((sqlite_func *) f->sf, (double) d); + } +#else +#if HAVE_SQLITE2 + sqlite_set_result_double((sqlite_func *) f->sf, (double) d); +#endif +#if HAVE_SQLITE3 + sqlite3_result_double((sqlite3_context *) f->sf, (double) d); +#endif +#endif + } +} + +JNIEXPORT void JNICALL +Java_SQLite_FunctionContext_set_1result__I(JNIEnv *env, jobject obj, jint i) +{ + hfunc *f = getfunc(env, obj); + + if (f && f->sf) { +#if HAVE_BOTH_SQLITE + if (f->is3) { + sqlite3_result_int((sqlite3_context *) f->sf, (int) i); + } else { + sqlite_set_result_int((sqlite_func *) f->sf, (int) i); + } +#else +#if HAVE_SQLITE2 + sqlite_set_result_int((sqlite_func *) f->sf, (int) i); +#endif +#if HAVE_SQLITE3 + sqlite3_result_int((sqlite3_context *) f->sf, (int) i); +#endif +#endif + } +} + +JNIEXPORT void JNICALL +Java_SQLite_FunctionContext_set_1result__Ljava_lang_String_2(JNIEnv *env, + jobject obj, + jstring ret) +{ + hfunc *f = getfunc(env, obj); + + if (f && f->sf) { +#if HAVE_BOTH_SQLITE + if (!f->is3) { + transstr retstr; + jthrowable exc; + + trans2iso(env, f->h->haveutf, f->h->enc, ret, &retstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + sqlite_set_result_string((sqlite_func *) f->sf, + retstr.result, -1); + transfree(&retstr); + } else if (ret) { + jsize len = (*env)->GetStringLength(env, ret) * sizeof (jchar); + const jchar *str = (*env)->GetStringChars(env, ret, 0); + + sqlite3_result_text16((sqlite3_context *) f->sf, str, len, + SQLITE_TRANSIENT); + (*env)->ReleaseStringChars(env, ret, str); + } else { + sqlite3_result_null((sqlite3_context *) f->sf); + } +#else +#if HAVE_SQLITE2 + transstr retstr; + jthrowable exc; + + trans2iso(env, f->h->haveutf, f->h->enc, ret, &retstr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + sqlite_set_result_string((sqlite_func *) f->sf, retstr.result, -1); + transfree(&retstr); +#endif +#if HAVE_SQLITE3 + if (ret) { + jsize len = (*env)->GetStringLength(env, ret) * sizeof (jchar); + const jchar *str = (*env)->GetStringChars(env, ret, 0); + + sqlite3_result_text16((sqlite3_context *) f->sf, str, len, + SQLITE_TRANSIENT); + (*env)->ReleaseStringChars(env, ret, str); + } else { + sqlite3_result_null((sqlite3_context *) f->sf); + } +#endif +#endif + } +} + +JNIEXPORT void JNICALL +Java_SQLite_FunctionContext_set_1result___3B(JNIEnv *env, jobject obj, + jbyteArray b) +{ +#if HAVE_SQLITE3 + hfunc *f = getfunc(env, obj); + + if (f && f->sf) { +#if HAVE_BOTH_SQLITE + if (!f->is3) { + /* silently ignored */ + return; + } +#endif + if (b) { + jsize len; + jbyte *data; + + len = (*env)->GetArrayLength(env, b); + data = (*env)->GetByteArrayElements(env, b, 0); + sqlite3_result_blob((sqlite3_context *) f->sf, + data, len, SQLITE_TRANSIENT); + (*env)->ReleaseByteArrayElements(env, b, data, 0); + } else { + sqlite3_result_null((sqlite3_context *) f->sf); + } + } +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_FunctionContext_set_1result_1zeroblob(JNIEnv *env, jobject obj, + jint n) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_RESULT_ZEROBLOB + hfunc *f = getfunc(env, obj); + + if (f && f->sf) { +#if HAVE_BOTH_SQLITE + if (!f->is3) { + /* silently ignored */ + return; + } +#endif + sqlite3_result_zeroblob((sqlite3_context *) f->sf, n); + } +#endif +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Database_error_1string(JNIEnv *env, jclass c, jint err) +{ +#if HAVE_SQLITE2 + return (*env)->NewStringUTF(env, sqlite_error_string((int) err)); +#else + return (*env)->NewStringUTF(env, "unkown error"); +#endif +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Database__1errmsg(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { +#if HAVE_BOTH_SQLITE + if (!h->is3) { + return 0; + } +#endif + return (*env)->NewStringUTF(env, + sqlite3_errmsg((sqlite3 *) h->sqlite)); + } +#endif + return 0; +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1set_1encoding(JNIEnv *env, jobject obj, jstring enc) +{ + handle *h = gethandle(env, obj); + + if (h && !h->haveutf) { +#if HAVE_BOTH_SQLITE + if (!h->is3) { + delglobrefp(env, &h->enc); + h->enc = enc; + globrefset(env, enc, &h->enc); + } +#else +#if HAVE_SQLITE2 + delglobrefp(env, &h->enc); + h->enc = enc; + globrefset(env, enc, &h->enc); +#endif +#endif + } +} + +#if HAVE_SQLITE_SET_AUTHORIZER +static int +doauth(void *arg, int what, const char *arg1, const char *arg2, + const char *arg3, const char *arg4) +{ + handle *h = (handle *) arg; + JNIEnv *env = h->env; + + if (env && h->ai) { + jthrowable exc; + jclass cls = (*env)->GetObjectClass(env, h->ai); + jmethodID mid; + jint i = what; + + mid = (*env)->GetMethodID(env, cls, "authorize", + "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I"); + if (mid) { + jstring s1 = 0, s2 = 0, s3 = 0, s4 = 0; + transstr tr; + + if (arg1) { + trans2utf(env, h->haveutf, h->enc, arg1, &tr); + s1 = tr.jstr; + } + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return SQLITE_DENY; + } + if (arg2) { + trans2utf(env, h->haveutf, h->enc, arg2, &tr); + s2 = tr.jstr; + } + if (arg3) { + trans2utf(env, h->haveutf, h->enc, arg3, &tr); + s3 = tr.jstr; + } + if (arg4) { + trans2utf(env, h->haveutf, h->enc, arg4, &tr); + s4 = tr.jstr; + } + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return SQLITE_DENY; + } + i = (*env)->CallIntMethod(env, h->ai, mid, i, s1, s2, s3, s4); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return SQLITE_DENY; + } + (*env)->DeleteLocalRef(env, s4); + (*env)->DeleteLocalRef(env, s3); + (*env)->DeleteLocalRef(env, s2); + (*env)->DeleteLocalRef(env, s1); + if (i != SQLITE_OK && i != SQLITE_IGNORE) { + i = SQLITE_DENY; + } + return (int) i; + } + } + return SQLITE_DENY; +} +#endif + +JNIEXPORT void JNICALL +Java_SQLite_Database__1set_1authorizer(JNIEnv *env, jobject obj, jobject auth) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { + delglobrefp(env, &h->ai); + globrefset(env, auth, &h->ai); +#if HAVE_SQLITE_SET_AUTHORIZER + h->env = env; +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_set_authorizer((sqlite3 *) h->sqlite, + h->ai ? doauth : 0, h); + } else { + sqlite_set_authorizer((sqlite *) h->sqlite, + h->ai ? doauth : 0, h); + } +#else +#if HAVE_SQLITE2 + sqlite_set_authorizer((sqlite *) h->sqlite, h->ai ? doauth : 0, h); +#endif +#if HAVE_SQLITE3 + sqlite3_set_authorizer((sqlite3 *) h->sqlite, h->ai ? doauth : 0, h); +#endif +#endif +#endif + return; + } + throwclosed(env); +} + +#if HAVE_SQLITE_TRACE +static void +dotrace(void *arg, const char *msg) +{ + handle *h = (handle *) arg; + JNIEnv *env = h->env; + + if (env && h->tr && msg) { + jthrowable exc; + jclass cls = (*env)->GetObjectClass(env, h->tr); + jmethodID mid; + + mid = (*env)->GetMethodID(env, cls, "trace", "(Ljava/lang/String;)V"); + if (mid) { + transstr tr; + + trans2utf(env, h->haveutf, h->enc, msg, &tr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + (*env)->ExceptionClear(env); + return; + } + (*env)->CallVoidMethod(env, h->tr, mid, tr.jstr); + (*env)->ExceptionClear(env); + (*env)->DeleteLocalRef(env, tr.jstr); + return; + } + } + return; +} +#endif + +JNIEXPORT void JNICALL +Java_SQLite_Database__1trace(JNIEnv *env, jobject obj, jobject tr) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { + delglobrefp(env, &h->tr); + globrefset(env, tr, &h->tr); +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_trace((sqlite3 *) h->sqlite, h->tr ? dotrace : 0, h); + } else { +#if HAVE_SQLITE_TRACE + sqlite_trace((sqlite *) h->sqlite, h->tr ? dotrace : 0, h); +#endif + } +#else +#if HAVE_SQLITE2 +#if HAVE_SQLITE_TRACE + sqlite_trace((sqlite *) h->sqlite, h->tr ? dotrace : 0, h); +#endif +#endif +#if HAVE_SQLITE3 + sqlite3_trace((sqlite3 *) h->sqlite, h->tr ? dotrace : 0, h); +#endif +#endif + return; + } + throwclosed(env); +} + +#if HAVE_SQLITE_COMPILE +static void +dovmfinal(JNIEnv *env, jobject obj, int final) +{ + hvm *v = gethvm(env, obj); + + if (v) { + if (v->h) { + handle *h = v->h; + hvm *vv, **vvp; + + vvp = &h->vms; + vv = *vvp; + while (vv) { + if (vv == v) { + *vvp = vv->next; + break; + } + vvp = &vv->next; + vv = *vvp; + } + } + if (v->vm) { +#if HAVE_BOTH_SQLITE + if (v->is3) { + sqlite3_finalize((sqlite3_stmt *) v->vm); + } else { + sqlite_finalize((sqlite_vm *) v->vm, 0); + } +#else +#if HAVE_SQLITE2 + sqlite_finalize((sqlite_vm *) v->vm, 0); +#endif +#if HAVE_SQLITE3 + sqlite3_finalize((sqlite3_stmt *) v->vm); +#endif +#endif + v->vm = 0; + } + free(v); + (*env)->SetLongField(env, obj, F_SQLite_Vm_handle, 0); + return; + } + if (!final) { + throwex(env, "vm already closed"); + } +} +#endif + +#if HAVE_SQLITE3 +static void +dostmtfinal(JNIEnv *env, jobject obj) +{ + hvm *v = gethstmt(env, obj); + + if (v) { + if (v->h) { + handle *h = v->h; + hvm *vv, **vvp; + + vvp = &h->vms; + vv = *vvp; + while (vv) { + if (vv == v) { + *vvp = vv->next; + break; + } + vvp = &vv->next; + vv = *vvp; + } + } + if (v->vm) { + sqlite3_finalize((sqlite3_stmt *) v->vm); + } + v->vm = 0; + free(v); + (*env)->SetLongField(env, obj, F_SQLite_Stmt_handle, 0); + } +} +#endif + +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO +static void +doblobfinal(JNIEnv *env, jobject obj) +{ + hbl *bl = gethbl(env, obj); + + if (bl) { + if (bl->h) { + handle *h = bl->h; + hbl *blc, **blp; + + blp = &h->blobs; + blc = *blp; + while (blc) { + if (blc == bl) { + *blp = blc->next; + break; + } + blp = &blc->next; + blc = *blp; + } + } + if (bl->blob) { + sqlite3_blob_close(bl->blob); + } + bl->blob = 0; + free(bl); + (*env)->SetLongField(env, obj, F_SQLite_Blob_handle, 0); + (*env)->SetIntField(env, obj, F_SQLite_Blob_size, 0); + } +} +#endif + +JNIEXPORT void JNICALL +Java_SQLite_Vm_stop(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE_COMPILE + dovmfinal(env, obj, 0); +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Vm_finalize(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE_COMPILE + dovmfinal(env, obj, 1); +#endif +} + +#if HAVE_SQLITE_COMPILE +#if HAVE_SQLITE3 +static void +free_tab(void *mem) +{ + char **p = (char **) mem; + int i, n; + + if (!p) { + return; + } + p -= 1; + mem = (void *) p; + n = ((int *) p)[0]; + p += n * 2 + 2 + 1; + for (i = 0; i < n; i++) { + if (p[i]) { + free(p[i]); + } + } + free(mem); +} +#endif +#endif + +JNIEXPORT jboolean JNICALL +Java_SQLite_Vm_step(JNIEnv *env, jobject obj, jobject cb) +{ +#if HAVE_SQLITE_COMPILE + hvm *v = gethvm(env, obj); + + if (v && v->vm && v->h) { + jthrowable exc; + int ret, ncol = 0; +#if HAVE_SQLITE3 + freemem *freeproc = 0; + const char **blob = 0; +#endif + const char **data = 0, **cols = 0; + + v->h->env = env; +#if HAVE_BOTH_SQLITE + if (v->is3) { + ret = sqlite3_step((sqlite3_stmt *) v->vm); + if (ret == SQLITE_ROW) { + ncol = sqlite3_data_count((sqlite3_stmt *) v->vm); + if (ncol > 0) { + data = calloc(ncol * 3 + 3 + 1, sizeof (char *)); + if (data) { + data[0] = (const char *) ncol; + ++data; + cols = data + ncol + 1; + blob = cols + ncol + 1; + freeproc = free_tab; + } else { + ret = SQLITE_NOMEM; + } + } + if (ret != SQLITE_NOMEM) { + int i; + + for (i = 0; i < ncol; i++) { + cols[i] = + sqlite3_column_name((sqlite3_stmt *) v->vm, i); + if (sqlite3_column_type((sqlite3_stmt *) v->vm, i) + == SQLITE_BLOB) { + unsigned char *src = (unsigned char *) + sqlite3_column_blob((sqlite3_stmt *) v->vm, i); + int n = + sqlite3_column_bytes((sqlite3_stmt *) v->vm, + i); + + if (src) { + data[i] = malloc(n * 2 + 4); + if (data[i]) { + int k; + char *p = (char *) data[i]; + + blob[i] = data[i]; + *p++ = 'X'; + *p++ = '\''; + for (k = 0; k < n; k++) { + *p++ = xdigits[src[k] >> 4]; + *p++ = xdigits[src[k] & 0x0F]; + } + *p++ = '\''; + *p++ = '\0'; + } + } + } else { + data[i] = (const char *) + sqlite3_column_text((sqlite3_stmt *) v->vm, i); + } + } + } + } + } else { + ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols); + } +#else +#if HAVE_SQLITE2 + ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols); +#endif +#if HAVE_SQLITE3 + ret = sqlite3_step((sqlite3_stmt *) v->vm); + if (ret == SQLITE_ROW) { + ncol = sqlite3_data_count((sqlite3_stmt *) v->vm); + if (ncol > 0) { + data = calloc(ncol * 3 + 3 + 1, sizeof (char *)); + if (data) { + data[0] = (const char *) ncol; + ++data; + cols = data + ncol + 1; + blob = cols + ncol + 1; + freeproc = free_tab; + } else { + ret = SQLITE_NOMEM; + } + } + if (ret != SQLITE_NOMEM) { + int i; + + for (i = 0; i < ncol; i++) { + cols[i] = sqlite3_column_name((sqlite3_stmt *) v->vm, i); + if (sqlite3_column_type((sqlite3_stmt *) v->vm, i) + == SQLITE_BLOB) { + unsigned char *src = (unsigned char *) + sqlite3_column_blob((sqlite3_stmt *) v->vm, i); + int n = + sqlite3_column_bytes((sqlite3_stmt *) v->vm, i); + + if (src) { + data[i] = malloc(n * 2 + 4); + if (data[i]) { + int k; + char *p = (char *) data[i]; + + blob[i] = data[i]; + *p++ = 'X'; + *p++ = '\''; + for (k = 0; k < n; k++) { + *p++ = xdigits[src[k] >> 4]; + *p++ = xdigits[src[k] & 0x0F]; + } + *p++ = '\''; + *p++ = '\0'; + } + } + } else { + data[i] = (char *) + sqlite3_column_text((sqlite3_stmt *) v->vm, i); + } + } + } + } +#endif +#endif + if (ret == SQLITE_ROW) { + v->hh.cb = cb; + v->hh.env = env; +#if HAVE_BOTH_SQLITE + if (v->is3) { + v->hh.stmt = (sqlite3_stmt *) v->vm; + } +#else +#if HAVE_SQLITE3 + v->hh.stmt = (sqlite3_stmt *) v->vm; +#endif +#endif + callback((void *) &v->hh, ncol, (char **) data, (char **) cols); +#if HAVE_SQLITE3 + if (data && freeproc) { + freeproc((void *) data); + } +#endif + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + goto dofin; + } + return JNI_TRUE; + } else if (ret == SQLITE_DONE) { +dofin: +#if HAVE_BOTH_SQLITE + if (v->is3) { + sqlite3_finalize((sqlite3_stmt *) v->vm); + } else { + sqlite_finalize((sqlite_vm *) v->vm, 0); + } +#else +#if HAVE_SQLITE2 + sqlite_finalize((sqlite_vm *) v->vm, 0); +#endif +#if HAVE_SQLITE3 + sqlite3_finalize((sqlite3_stmt *) v->vm); +#endif +#endif + v->vm = 0; + return JNI_FALSE; + } +#if HAVE_BOTH_SQLITE + if (v->is3) { + sqlite3_finalize((sqlite3_stmt *) v->vm); + } else { + sqlite_finalize((sqlite_vm *) v->vm, 0); + } +#else +#if HAVE_SQLITE2 + sqlite_finalize((sqlite_vm *) v->vm, 0); +#endif +#if HAVE_SQLITE3 + sqlite3_finalize((sqlite3_stmt *) v->vm); +#endif +#endif + setvmerr(env, obj, ret); + v->vm = 0; + throwex(env, "error in step"); + return JNI_FALSE; + } + throwex(env, "vm already closed"); +#else + throwex(env, "unsupported"); +#endif + return JNI_FALSE; +} + +JNIEXPORT jboolean JNICALL +Java_SQLite_Vm_compile(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE_COMPILE + hvm *v = gethvm(env, obj); + void *svm = 0; + char *err = 0; + const char *tail; + int ret; + + if (v && v->vm) { +#if HAVE_BOTH_SQLITE + if (v->is3) { + sqlite3_finalize((sqlite3_stmt *) v->vm); + } else { + sqlite_finalize((sqlite_vm *) v->vm, 0); + } +#else +#if HAVE_SQLITE2 + sqlite_finalize((sqlite_vm *) v->vm, 0); +#endif +#if HAVE_SQLITE3 + sqlite3_finalize((sqlite3_stmt *) v->vm); +#endif +#endif + v->vm = 0; + } + if (v && v->h && v->h->sqlite) { + if (!v->tail) { + return JNI_FALSE; + } + v->h->env = env; +#if HAVE_BOTH_SQLITE + if (v->is3) { +#if HAVE_SQLITE3_PREPARE_V2 + ret = sqlite3_prepare_v2((sqlite3 *) v->h->sqlite, v->tail, -1, + (sqlite3_stmt **) &svm, &tail); +#else + ret = sqlite3_prepare((sqlite3 *) v->h->sqlite, v->tail, -1, + (sqlite3_stmt **) &svm, &tail); +#endif + if (ret != SQLITE_OK) { + if (svm) { + sqlite3_finalize((sqlite3_stmt *) svm); + svm = 0; + } + } + } else { + ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail, + &tail, (sqlite_vm **) &svm, &err); + if (ret != SQLITE_OK) { + if (svm) { + sqlite_finalize((sqlite_vm *) svm, 0); + svm = 0; + } + } + } +#else +#if HAVE_SQLITE2 + ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail, + &tail, (sqlite_vm **) &svm, &err); + if (ret != SQLITE_OK) { + if (svm) { + sqlite_finalize((sqlite_vm *) svm, 0); + svm = 0; + } + } +#endif +#if HAVE_SQLITE3 +#if HAVE_SQLITE3_PREPARE_V2 + ret = sqlite3_prepare_v2((sqlite3 *) v->h->sqlite, + v->tail, -1, (sqlite3_stmt **) &svm, &tail); +#else + ret = sqlite3_prepare((sqlite3 *) v->h->sqlite, + v->tail, -1, (sqlite3_stmt **) &svm, &tail); +#endif + if (ret != SQLITE_OK) { + if (svm) { + sqlite3_finalize((sqlite3_stmt *) svm); + svm = 0; + } + } +#endif +#endif + if (ret != SQLITE_OK) { + setvmerr(env, obj, ret); + v->tail = 0; + throwex(env, err ? err : "error in compile/prepare"); +#if HAVE_SQLITE2 + if (err) { + sqlite_freemem(err); + } +#endif + return JNI_FALSE; + } +#if HAVE_SQLITE2 + if (err) { + sqlite_freemem(err); + } +#endif + if (!svm) { + v->tail = 0; + return JNI_FALSE; + } + v->vm = svm; + v->tail = (char *) tail; + v->hh.row1 = 1; + return JNI_TRUE; + } + throwex(env, "vm already closed"); +#else + throwex(env, "unsupported"); +#endif + return JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_SQLite_Database_vm_1compile(JNIEnv *env, jobject obj, jstring sql, + jobject vm) +{ +#if HAVE_SQLITE_COMPILE + handle *h = gethandle(env, obj); + void *svm = 0; + hvm *v; + char *err = 0; + const char *tail; + transstr tr; + jvalue vv; + int ret; + jthrowable exc; + + if (!h) { + throwclosed(env); + return; + } + if (!vm) { + throwex(env, "null vm"); + return; + } + if (!sql) { + throwex(env, "null sql"); + return; + } + trans2iso(env, h->haveutf, h->enc, sql, &tr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + h->env = env; +#if HAVE_BOTH_SQLITE + if (h->is3) { +#if HAVE_SQLITE3_PREPARE_V2 + ret = sqlite3_prepare_v2((sqlite3 *) h->sqlite, tr.result, -1, + (sqlite3_stmt **) &svm, &tail); +#else + ret = sqlite3_prepare((sqlite3 *) h->sqlite, tr.result, -1, + (sqlite3_stmt **) &svm, &tail); +#endif + if (ret != SQLITE_OK) { + if (svm) { + sqlite3_finalize((sqlite3_stmt *) svm); + svm = 0; + } + } + } else { + ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail, + (sqlite_vm **) &svm, &err); + if (ret != SQLITE_OK) { + if (svm) { + sqlite_finalize((sqlite_vm *) svm, 0); + } + } + } +#else +#if HAVE_SQLITE2 + ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail, + (sqlite_vm **) &svm, &err); + if (ret != SQLITE_OK) { + if (svm) { + sqlite_finalize((sqlite_vm *) svm, 0); + svm = 0; + } + } +#endif +#if HAVE_SQLITE3 +#if HAVE_SQLITE3_PREPARE_V2 + ret = sqlite3_prepare_v2((sqlite3 *) h->sqlite, tr.result, -1, + (sqlite3_stmt **) &svm, &tail); +#else + ret = sqlite3_prepare((sqlite3 *) h->sqlite, tr.result, -1, + (sqlite3_stmt **) &svm, &tail); +#endif + if (ret != SQLITE_OK) { + if (svm) { + sqlite3_finalize((sqlite3_stmt *) svm); + svm = 0; + } + } +#endif +#endif + if (ret != SQLITE_OK) { + transfree(&tr); + setvmerr(env, vm, ret); + throwex(env, err ? err : "error in prepare/compile"); +#if HAVE_SQLITE2 + if (err) { + sqlite_freemem(err); + } +#endif + return; + } +#if HAVE_SQLITE2 + if (err) { + sqlite_freemem(err); + } +#endif + if (!svm) { + transfree(&tr); + return; + } + v = malloc(sizeof (hvm) + strlen(tail) + 1); + if (!v) { + transfree(&tr); +#if HAVE_BOTH_SQLITE + if (h->is3) { + sqlite3_finalize((sqlite3_stmt *) svm); + } else { + sqlite_finalize((sqlite_vm *) svm, 0); + } +#else +#if HAVE_SQLITE2 + sqlite_finalize((sqlite_vm *) svm, 0); +#endif +#if HAVE_SQLITE3 + sqlite3_finalize((sqlite3_stmt *) svm); +#endif +#endif + throwoom(env, "unable to get SQLite handle"); + return; + } + v->next = h->vms; + h->vms = v; + v->vm = svm; + v->h = h; + v->tail = (char *) (v + 1); +#if HAVE_BOTH_SQLITE + v->is3 = v->hh.is3 = h->is3; +#endif + strcpy(v->tail, tail); + v->hh.sqlite = 0; + v->hh.haveutf = h->haveutf; + v->hh.ver = h->ver; + v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0; + v->hh.row1 = 1; + v->hh.enc = h->enc; + v->hh.funcs = 0; + v->hh.vms = 0; + v->hh.env = 0; + vv.j = 0; + vv.l = (jobject) v; + (*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j); +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Database_vm_1compile_1args(JNIEnv *env, + jobject obj, jstring sql, + jobject vm, jobjectArray args) +{ +#if HAVE_SQLITE_COMPILE +#if HAVE_SQLITE3 + handle *h = gethandle(env, obj); +#endif + +#if HAVE_BOTH_SQLITE + if (h && !h->is3) { + throwex(env, "unsupported"); + return; + } +#else +#if HAVE_SQLITE2 + throwex(env, "unsupported"); +#endif +#endif +#if HAVE_SQLITE3 + if (!h || !h->sqlite) { + throwclosed(env); + return; + } + if (!vm) { + throwex(env, "null vm"); + return; + } + if (!sql) { + throwex(env, "null sql"); + return; + } else { + void *svm = 0; + hvm *v; + jvalue vv; + jthrowable exc; + int rc = SQLITE_ERROR, nargs, i; + char *p; + const char *str = (*env)->GetStringUTFChars(env, sql, NULL); + const char *tail; + transstr sqlstr; + struct args { + char *arg; + jobject obj; + transstr trans; + } *argv = 0; + char **cargv = 0; + + p = (char *) str; + nargs = 0; + while (*p) { + if (*p == '%') { + ++p; + if (*p == 'q' || *p == 'Q' || *p == 's') { + nargs++; + if (nargs > MAX_PARAMS) { + (*env)->ReleaseStringUTFChars(env, sql, str); + throwex(env, "too much SQL parameters"); + return; + } + } else if (*p != '%') { + (*env)->ReleaseStringUTFChars(env, sql, str); + throwex(env, "bad % specification in query"); + return; + } + } + ++p; + } + cargv = malloc((sizeof (*argv) + sizeof (char *)) * MAX_PARAMS); + if (!cargv) { + (*env)->ReleaseStringUTFChars(env, sql, str); + throwoom(env, "unable to allocate arg vector"); + return; + } + argv = (struct args *) (cargv + MAX_PARAMS); + for (i = 0; i < MAX_PARAMS; i++) { + cargv[i] = 0; + argv[i].arg = 0; + argv[i].obj = 0; + argv[i].trans.result = argv[i].trans.tofree = 0; + } + exc = 0; + for (i = 0; i < nargs; i++) { + jobject so = (*env)->GetObjectArrayElement(env, args, i); + + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + break; + } + if (so) { + argv[i].obj = so; + argv[i].arg = cargv[i] = + trans2iso(env, 1, 0, argv[i].obj, &argv[i].trans); + } + } + if (exc) { + for (i = 0; i < nargs; i++) { + if (argv[i].obj) { + transfree(&argv[i].trans); + } + } + freep((char **) &cargv); + (*env)->ReleaseStringUTFChars(env, sql, str); + return; + } + h->row1 = 1; + trans2iso(env, 1, 0, sql, &sqlstr); + exc = (*env)->ExceptionOccurred(env); + if (!exc) { +#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR) + char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv); +#else + char *s = sqlite3_mprintf(sqlstr.result, + cargv[0], cargv[1], + cargv[2], cargv[3], + cargv[4], cargv[5], + cargv[6], cargv[7], + cargv[8], cargv[9], + cargv[10], cargv[11], + cargv[12], cargv[13], + cargv[14], cargv[15], + cargv[16], cargv[17], + cargv[18], cargv[19], + cargv[20], cargv[21], + cargv[22], cargv[23], + cargv[24], cargv[25], + cargv[26], cargv[27], + cargv[28], cargv[29], + cargv[30], cargv[31]); +#endif + if (!s) { + rc = SQLITE_NOMEM; + } else { +#if HAVE_SQLITE3_PREPARE_V2 + rc = sqlite3_prepare_v2((sqlite3 *) h->sqlite, s, -1, + (sqlite3_stmt **) &svm, &tail); +#else + rc = sqlite3_prepare((sqlite3 *) h->sqlite, s, -1, + (sqlite3_stmt **) &svm, &tail); +#endif + if (rc != SQLITE_OK) { + if (svm) { + sqlite3_finalize((sqlite3_stmt *) svm); + svm = 0; + } + } + } + if (rc != SQLITE_OK) { + sqlite3_free(s); + for (i = 0; i < nargs; i++) { + if (argv[i].obj) { + transfree(&argv[i].trans); + } + } + freep((char **) &cargv); + transfree(&sqlstr); + (*env)->ReleaseStringUTFChars(env, sql, str); + setvmerr(env, vm, rc); + throwex(env, "error in prepare"); + return; + } + v = malloc(sizeof (hvm) + strlen(tail) + 1); + if (!v) { + sqlite3_free(s); + for (i = 0; i < nargs; i++) { + if (argv[i].obj) { + transfree(&argv[i].trans); + } + } + freep((char **) &cargv); + transfree(&sqlstr); + (*env)->ReleaseStringUTFChars(env, sql, str); + sqlite3_finalize((sqlite3_stmt *) svm); + setvmerr(env, vm, SQLITE_NOMEM); + throwoom(env, "unable to get SQLite handle"); + return; + } + v->next = h->vms; + h->vms = v; + v->vm = svm; + v->h = h; + v->tail = (char *) (v + 1); +#if HAVE_BOTH_SQLITE + v->is3 = v->hh.is3 = h->is3; +#endif + strcpy(v->tail, tail); + sqlite3_free(s); + v->hh.sqlite = 0; + v->hh.haveutf = h->haveutf; + v->hh.ver = h->ver; + v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0; + v->hh.row1 = 1; + v->hh.enc = h->enc; + v->hh.funcs = 0; + v->hh.vms = 0; + v->hh.env = 0; + vv.j = 0; + vv.l = (jobject) v; + (*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j); + } + for (i = 0; i < nargs; i++) { + if (argv[i].obj) { + transfree(&argv[i].trans); + } + } + freep((char **) &cargv); + transfree(&sqlstr); + (*env)->ReleaseStringUTFChars(env, sql, str); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + } + } +#endif +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_FunctionContext_internal_1init(JNIEnv *env, jclass cls) +{ + F_SQLite_FunctionContext_handle = + (*env)->GetFieldID(env, cls, "handle", "J"); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1progress_1handler(JNIEnv *env, jobject obj, jint n, + jobject ph) +{ + handle *h = gethandle(env, obj); + + if (h && h->sqlite) { + /* CHECK THIS */ +#if HAVE_SQLITE_PROGRESS_HANDLER + delglobrefp(env, &h->ph); +#if HAVE_BOTH_SQLITE + if (h->is3) { + if (ph) { + globrefset(env, ph, &h->ph); + sqlite3_progress_handler((sqlite3 *) h->sqlite, + n, progresshandler, h); + } else { + sqlite3_progress_handler((sqlite3 *) h->sqlite, + 0, 0, 0); + } + } else { + if (ph) { + globrefset(env, ph, &h->ph); + sqlite_progress_handler((sqlite *) h->sqlite, + n, progresshandler, h); + } else { + sqlite_progress_handler((sqlite *) h->sqlite, + 0, 0, 0); + } + } +#else +#if HAVE_SQLITE2 + if (ph) { + globrefset(env, ph, &h->ph); + sqlite_progress_handler((sqlite *) h->sqlite, + n, progresshandler, h); + } else { + sqlite_progress_handler((sqlite *) h->sqlite, + 0, 0, 0); + } +#endif +#if HAVE_SQLITE3 + if (ph) { + globrefset(env, ph, &h->ph); + sqlite3_progress_handler((sqlite3 *) h->sqlite, + n, progresshandler, h); + } else { + sqlite3_progress_handler((sqlite3 *) h->sqlite, + 0, 0, 0); + } +#endif +#endif + return; +#else + throwex(env, "unsupported"); + return; +#endif + } + throwclosed(env); +} + +JNIEXPORT jboolean JNICALL +Java_SQLite_Database_is3(JNIEnv *env, jobject obj) +{ +#if HAVE_BOTH_SQLITE + handle *h = gethandle(env, obj); + + if (h) { + return h->is3 ? JNI_TRUE : JNI_FALSE; + } + return JNI_FALSE; +#else +#if HAVE_SQLITE2 + return JNI_FALSE; +#endif +#if HAVE_SQLITE3 + return JNI_TRUE; +#endif +#endif +} + +JNIEXPORT jboolean JNICALL +Java_SQLite_Stmt_prepare(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 + hvm *v = gethstmt(env, obj); + void *svm = 0; + char *tail; + int ret; + + if (v && v->vm) { + sqlite3_finalize((sqlite3_stmt *) v->vm); + v->vm = 0; + } + if (v && v->h && v->h->sqlite) { + if (!v->tail) { + return JNI_FALSE; + } + v->h->env = env; +#if HAVE_SQLITE3_PREPARE16_V2 + ret = sqlite3_prepare16_v2((sqlite3 *) v->h->sqlite, + v->tail, -1, (sqlite3_stmt **) &svm, + (const void **) &tail); +#else + ret = sqlite3_prepare16((sqlite3 *) v->h->sqlite, + v->tail, -1, (sqlite3_stmt **) &svm, + (const void **) &tail); +#endif + if (ret != SQLITE_OK) { + if (svm) { + sqlite3_finalize((sqlite3_stmt *) svm); + svm = 0; + } + } + if (ret != SQLITE_OK) { + const char *err = sqlite3_errmsg(v->h->sqlite); + + setstmterr(env, obj, ret); + v->tail = 0; + throwex(env, err ? err : "error in compile/prepare"); + return JNI_FALSE; + } + if (!svm) { + v->tail = 0; + return JNI_FALSE; + } + v->vm = svm; + v->tail = (char *) tail; + v->hh.row1 = 1; + return JNI_TRUE; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_SQLite_Database_stmt_1prepare(JNIEnv *env, jobject obj, jstring sql, + jobject stmt) +{ +#if HAVE_SQLITE3 + handle *h = gethandle(env, obj); + void *svm = 0; + hvm *v; + jvalue vv; + jsize len16; + const jchar *sql16, *tail = 0; + int ret; + + if (!h) { + throwclosed(env); + return; + } + if (!stmt) { + throwex(env, "null stmt"); + return; + } + if (!sql) { + throwex(env, "null sql"); + return; + } +#ifdef HAVE_BOTH_SQLITE + if (!h->is3) { + throwex(env, "only on SQLite3 database"); + return; + } +#endif + len16 = (*env)->GetStringLength(env, sql) * sizeof (jchar); + if (len16 < 1) { + return; + } + h->env = env; + sql16 = (*env)->GetStringChars(env, sql, 0); +#if HAVE_SQLITE3_PREPARE16_V2 + ret = sqlite3_prepare16_v2((sqlite3 *) h->sqlite, sql16, len16, + (sqlite3_stmt **) &svm, (const void **) &tail); +#else + ret = sqlite3_prepare16((sqlite3 *) h->sqlite, sql16, len16, + (sqlite3_stmt **) &svm, (const void **) &tail); +#endif + if (ret != SQLITE_OK) { + if (svm) { + sqlite3_finalize((sqlite3_stmt *) svm); + svm = 0; + } + } + if (ret != SQLITE_OK) { + const char *err = sqlite3_errmsg(h->sqlite); + + (*env)->ReleaseStringChars(env, sql, sql16); + setstmterr(env, stmt, ret); + throwex(env, err ? err : "error in prepare"); + return; + } + if (!svm) { + (*env)->ReleaseStringChars(env, sql, sql16); + return; + } + len16 = len16 + sizeof (jchar) - ((char *) tail - (char *) sql16); + if (len16 < (jsize) sizeof (jchar)) { + len16 = sizeof (jchar); + } + v = malloc(sizeof (hvm) + len16); + if (!v) { + (*env)->ReleaseStringChars(env, sql, sql16); + sqlite3_finalize((sqlite3_stmt *) svm); + throwoom(env, "unable to get SQLite handle"); + return; + } + v->next = h->vms; + h->vms = v; + v->vm = svm; + v->h = h; + v->tail = (char *) (v + 1); +#if HAVE_BOTH_SQLITE + v->is3 = v->hh.is3 = 1; +#endif + memcpy(v->tail, tail, len16); + len16 /= sizeof (jchar); + ((jchar *) v->tail)[len16 - 1] = 0; + (*env)->ReleaseStringChars(env, sql, sql16); + v->hh.sqlite = 0; + v->hh.haveutf = h->haveutf; + v->hh.ver = h->ver; + v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0; + v->hh.row1 = 1; + v->hh.enc = h->enc; + v->hh.funcs = 0; + v->hh.vms = 0; + v->hh.env = 0; + vv.j = 0; + vv.l = (jobject) v; + (*env)->SetLongField(env, stmt, F_SQLite_Stmt_handle, vv.j); +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT jboolean JNICALL +Java_SQLite_Stmt_step(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ret; + + ret = sqlite3_step((sqlite3_stmt *) v->vm); + if (ret == SQLITE_ROW) { + return JNI_TRUE; + } + if (ret != SQLITE_DONE) { + const char *err = sqlite3_errmsg(v->h->sqlite); + + setstmterr(env, obj, ret); + throwex(env, err ? err : "error in step"); + } + return JNI_FALSE; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return JNI_FALSE; +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_close(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ret; + + ret = sqlite3_finalize((sqlite3_stmt *) v->vm); + v->vm = 0; + if (ret != SQLITE_OK) { + const char *err = sqlite3_errmsg(v->h->sqlite); + + setstmterr(env, obj, ret); + throwex(env, err ? err : "error in close"); + } + return; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return; +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_reset(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + sqlite3_reset((sqlite3_stmt *) v->vm); + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_clear_1bindings(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_CLEAR_BINDINGS + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + sqlite3_clear_bindings((sqlite3_stmt *) v->vm); + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_bind__II(JNIEnv *env, jobject obj, jint pos, jint val) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + int ret; + + if (pos < 1 || pos > npar) { + throwex(env, "parameter position out of bounds"); + return; + } + ret = sqlite3_bind_int((sqlite3_stmt *) v->vm, pos, val); + if (ret != SQLITE_OK) { + setstmterr(env, obj, ret); + throwex(env, "bind failed"); + } + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_bind__IJ(JNIEnv *env, jobject obj, jint pos, jlong val) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + int ret; + + if (pos < 1 || pos > npar) { + throwex(env, "parameter position out of bounds"); + return; + } + ret = sqlite3_bind_int64((sqlite3_stmt *) v->vm, pos, val); + if (ret != SQLITE_OK) { + setstmterr(env, obj, ret); + throwex(env, "bind failed"); + } + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_bind__ID(JNIEnv *env, jobject obj, jint pos, jdouble val) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + int ret; + + if (pos < 1 || pos > npar) { + throwex(env, "parameter position out of bounds"); + return; + } + ret = sqlite3_bind_double((sqlite3_stmt *) v->vm, pos, val); + if (ret != SQLITE_OK) { + setstmterr(env, obj, ret); + throwex(env, "bind failed"); + } + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_bind__I_3B(JNIEnv *env, jobject obj, jint pos, jbyteArray val) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + int ret; + jint len; + char *data = 0; + + if (pos < 1 || pos > npar) { + throwex(env, "parameter position out of bounds"); + return; + } + if (val) { + len = (*env)->GetArrayLength(env, val); + if (len > 0) { + data = sqlite3_malloc(len); + if (!data) { + throwoom(env, "unable to get blob parameter"); + return; + } + (*env)->GetByteArrayRegion(env, val, 0, len, (jbyte *) data); + ret = sqlite3_bind_blob((sqlite3_stmt *) v->vm, + pos, data, len, sqlite3_free); + } else { + ret = sqlite3_bind_blob((sqlite3_stmt *) v->vm, + pos, "", 0, SQLITE_STATIC); + } + } else { + ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos); + } + if (ret != SQLITE_OK) { + if (data) { + sqlite3_free(data); + } + setstmterr(env, obj, ret); + throwex(env, "bind failed"); + } + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_bind__ILjava_lang_String_2(JNIEnv *env, jobject obj, + jint pos, jstring val) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + int ret; + jsize len; + char *data = 0; + + if (pos < 1 || pos > npar) { + throwex(env, "parameter position out of bounds"); + return; + } + if (val) { + const jsize charCount = (*env)->GetStringLength(env, val); + len = charCount * sizeof(jchar); + if (len > 0) { + data = sqlite3_malloc(len); + if (!data) { + throwoom(env, "unable to get blob parameter"); + return; + } + + (*env)->GetStringRegion(env, val, 0, charCount, (jchar*) data); + ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm, + pos, data, len, sqlite3_free); + } else { + ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm, pos, "", 0, + SQLITE_STATIC); + } + } else { + ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos); + } + if (ret != SQLITE_OK) { + if (data) { + sqlite3_free(data); + } + setstmterr(env, obj, ret); + throwex(env, "bind failed"); + } + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_bind__I(JNIEnv *env, jobject obj, jint pos) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + int ret; + + if (pos < 1 || pos > npar) { + throwex(env, "parameter position out of bounds"); + return; + } + ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos); + if (ret != SQLITE_OK) { + setstmterr(env, obj, ret); + throwex(env, "bind failed"); + } + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_bind_1zeroblob(JNIEnv *env, jobject obj, jint pos, jint len) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_ZEROBLOB + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + int ret; + + if (pos < 1 || pos > npar) { + throwex(env, "parameter position out of bounds"); + return; + } + ret = sqlite3_bind_zeroblob((sqlite3_stmt *) v->vm, pos, len); + if (ret != SQLITE_OK) { + setstmterr(env, obj, ret); + throwex(env, "bind failed"); + } + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT jint JNICALL +Java_SQLite_Stmt_bind_1parameter_1count(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + return sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Stmt_bind_1parameter_1name(JNIEnv *env, jobject obj, jint pos) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_PARAMETER_NAME + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm); + const char *name; + + if (pos < 1 || pos > npar) { + throwex(env, "parameter position out of bounds"); + return 0; + } + name = sqlite3_bind_parameter_name((sqlite3_stmt *) v->vm, pos); + if (name) { + return (*env)->NewStringUTF(env, name); + } + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jint JNICALL +Java_SQLite_Stmt_bind_1parameter_1index(JNIEnv *env, jobject obj, + jstring name) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_PARAMETER_INDEX + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int pos; + const char *n; + transstr namestr; + jthrowable exc; + + n = trans2iso(env, 1, 0, name, &namestr); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return -1; + } + pos = sqlite3_bind_parameter_index((sqlite3_stmt *) v->vm, n); + transfree(&namestr); + return pos; + } else { + throwex(env, "stmt already closed"); + } +#else + throwex(env, "unsupported"); +#endif + return -1; +} + +JNIEXPORT jint JNICALL +Java_SQLite_Stmt_column_1int(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm); + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + return sqlite3_column_int((sqlite3_stmt *) v->vm, col); + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jlong JNICALL +Java_SQLite_Stmt_column_1long(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm); + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + return sqlite3_column_int64((sqlite3_stmt *) v->vm, col); + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jdouble JNICALL +Java_SQLite_Stmt_column_1double(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm); + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + return sqlite3_column_double((sqlite3_stmt *) v->vm, col); + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jbyteArray JNICALL +Java_SQLite_Stmt_column_1bytes(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm); + int nbytes; + const jbyte *data; + jbyteArray b = 0; + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + data = sqlite3_column_blob((sqlite3_stmt *) v->vm, col); + if (data) { + nbytes = sqlite3_column_bytes((sqlite3_stmt *) v->vm, col); + } else { + return 0; + } + b = (*env)->NewByteArray(env, nbytes); + if (!b) { + throwoom(env, "unable to get blob column data"); + return 0; + } + (*env)->SetByteArrayRegion(env, b, 0, nbytes, data); + return b; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Stmt_column_1string(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm); + int nbytes; + const jchar *data; + jstring b = 0; + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + data = sqlite3_column_text16((sqlite3_stmt *) v->vm, col); + if (data) { + nbytes = sqlite3_column_bytes16((sqlite3_stmt *) v->vm, col); + } else { + return 0; + } + nbytes /= sizeof (jchar); + b = (*env)->NewString(env, data, nbytes); + if (!b) { + throwoom(env, "unable to get string column data"); + return 0; + } + return b; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jint JNICALL +Java_SQLite_Stmt_column_1type(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm); + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + return sqlite3_column_type((sqlite3_stmt *) v->vm, col); + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jint JNICALL +Java_SQLite_Stmt_column_1count(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + return sqlite3_column_count((sqlite3_stmt *) v->vm); + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Stmt_column_1table_1name(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_TABLE_NAME16 + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm); + const jchar *str; + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + str = sqlite3_column_table_name16((sqlite3_stmt *) v->vm, col); + if (str) { + return (*env)->NewString(env, str, jstrlen(str)); + } + return 0; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Stmt_column_1database_1name(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_DATABASE_NAME16 + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm); + const jchar *str; + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + str = sqlite3_column_database_name16((sqlite3_stmt *) v->vm, col); + if (str) { + return (*env)->NewString(env, str, jstrlen(str)); + } + return 0; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Stmt_column_1decltype(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm); + const jchar *str; + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + str = sqlite3_column_decltype16((sqlite3_stmt *) v->vm, col); + if (str) { + return (*env)->NewString(env, str, jstrlen(str)); + } + return 0; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jstring JNICALL +Java_SQLite_Stmt_column_1origin_1name(JNIEnv *env, jobject obj, jint col) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_ORIGIN_NAME16 + hvm *v = gethstmt(env, obj); + + if (v && v->vm && v->h) { + int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm); + const jchar *str; + + if (col < 0 || col >= ncol) { + throwex(env, "column out of bounds"); + return 0; + } + str = sqlite3_column_origin_name16((sqlite3_stmt *) v->vm, col); + if (str) { + return (*env)->NewString(env, str, jstrlen(str)); + } + return 0; + } + throwex(env, "stmt already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_finalize(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE + dostmtfinal(env, obj); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Database__1open_1blob(JNIEnv *env, jobject obj, + jstring dbname, jstring table, + jstring column, jlong row, + jboolean rw, jobject blobj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + handle *h = gethandle(env, obj); + hbl *bl; + jthrowable exc; + transstr dbn, tbl, col; + sqlite3_blob *blob; + jvalue vv; + int ret; + + if (!blobj) { + throwex(env, "null blob"); + return; + } + if (h && h->sqlite) { + trans2iso(env, h->haveutf, h->enc, dbname, &dbn); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + (*env)->DeleteLocalRef(env, exc); + return; + } + trans2iso(env, h->haveutf, h->enc, table, &tbl); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + transfree(&dbn); + (*env)->DeleteLocalRef(env, exc); + return; + } + trans2iso(env, h->haveutf, h->enc, column, &col); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + transfree(&tbl); + transfree(&dbn); + (*env)->DeleteLocalRef(env, exc); + return; + } + ret = sqlite3_blob_open(h->sqlite, + dbn.result, tbl.result, col.result, + row, rw, &blob); + transfree(&col); + transfree(&tbl); + transfree(&dbn); + if (ret != SQLITE_OK) { + const char *err = sqlite3_errmsg(h->sqlite); + + seterr(env, obj, ret); + throwex(env, err ? err : "error in blob open"); + return; + } + bl = malloc(sizeof (hbl)); + if (!bl) { + sqlite3_blob_close(blob); + throwoom(env, "unable to get SQLite blob handle"); + return; + } + bl->next = h->blobs; + h->blobs = bl; + bl->blob = blob; + bl->h = h; + vv.j = 0; + vv.l = (jobject) bl; + (*env)->SetLongField(env, blobj, F_SQLite_Blob_handle, vv.j); + (*env)->SetIntField(env, blobj, F_SQLite_Blob_size, + sqlite3_blob_bytes(blob)); + return; + } + throwex(env, "not an open database"); +#else + throwex(env, "unsupported"); +#endif +} + +JNIEXPORT jint JNICALL +Java_SQLite_Blob_write(JNIEnv *env , jobject obj, jbyteArray b, jint off, + jint pos, jint len) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + hbl *bl = gethbl(env, obj); + + if (bl && bl->h && bl->blob) { + jbyte *buf; + jthrowable exc; + int ret; + + if (len <= 0) { + return 0; + } + buf = malloc(len); + if (!buf) { + throwoom(env, "out of buffer space for blob"); + return 0; + } + (*env)->GetByteArrayRegion(env, b, off, len, buf); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + free(buf); + return 0; + } + ret = sqlite3_blob_write(bl->blob, buf, len, pos); + free(buf); + if (ret != SQLITE_OK) { + throwioex(env, "blob write error"); + return 0; + } + return len; + } + throwex(env, "blob already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT jint JNICALL +Java_SQLite_Blob_read(JNIEnv *env , jobject obj, jbyteArray b, jint off, + jint pos, jint len) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + hbl *bl = gethbl(env, obj); + + if (bl && bl->h && bl->blob) { + jbyte *buf; + jthrowable exc; + int ret; + + if (len <= 0) { + return 0; + } + buf = malloc(len); + if (!buf) { + throwoom(env, "out of buffer space for blob"); + return 0; + } + ret = sqlite3_blob_read(bl->blob, buf, len, pos); + if (ret != SQLITE_OK) { + free(buf); + throwioex(env, "blob read error"); + return 0; + } + (*env)->SetByteArrayRegion(env, b, off, len, buf); + free(buf); + exc = (*env)->ExceptionOccurred(env); + if (exc) { + return 0; + } + return len; + } + throwex(env, "blob already closed"); +#else + throwex(env, "unsupported"); +#endif + return 0; +} + +JNIEXPORT void JNICALL +Java_SQLite_Blob_close(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + doblobfinal(env, obj); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Blob_finalize(JNIEnv *env, jobject obj) +{ +#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO + doblobfinal(env, obj); +#endif +} + +JNIEXPORT void JNICALL +Java_SQLite_Stmt_internal_1init(JNIEnv *env, jclass cls) +{ + F_SQLite_Stmt_handle = + (*env)->GetFieldID(env, cls, "handle", "J"); + F_SQLite_Stmt_error_code = + (*env)->GetFieldID(env, cls, "error_code", "I"); +} + +JNIEXPORT void JNICALL +Java_SQLite_Vm_internal_1init(JNIEnv *env, jclass cls) +{ + F_SQLite_Vm_handle = + (*env)->GetFieldID(env, cls, "handle", "J"); + F_SQLite_Vm_error_code = + (*env)->GetFieldID(env, cls, "error_code", "I"); +} + +JNIEXPORT void JNICALL +Java_SQLite_Blob_internal_1init(JNIEnv *env, jclass cls) +{ + F_SQLite_Blob_handle = + (*env)->GetFieldID(env, cls, "handle", "J"); + F_SQLite_Blob_size = + (*env)->GetFieldID(env, cls, "size", "I"); +} + +JNIEXPORT void JNICALL +Java_SQLite_Database_internal_1init(JNIEnv *env, jclass cls) +{ +//#ifndef JNI_VERSION_1_2 + jclass jls = (*env)->FindClass(env, "java/lang/String"); + + C_java_lang_String = (*env)->NewGlobalRef(env, jls); +//#endif + F_SQLite_Database_handle = + (*env)->GetFieldID(env, cls, "handle", "J"); + F_SQLite_Database_error_code = + (*env)->GetFieldID(env, cls, "error_code", "I"); + M_java_lang_String_getBytes = + (*env)->GetMethodID(env, C_java_lang_String, "getBytes", "()[B"); + M_java_lang_String_getBytes2 = + (*env)->GetMethodID(env, C_java_lang_String, "getBytes", + "(Ljava/lang/String;)[B"); + M_java_lang_String_initBytes = + (*env)->GetMethodID(env, C_java_lang_String, "<init>", "([B)V"); + M_java_lang_String_initBytes2 = + (*env)->GetMethodID(env, C_java_lang_String, "<init>", + "([BLjava/lang/String;)V"); +} + +#ifdef JNI_VERSION_1_2 +JNIEXPORT jint JNICALL +JNI_OnLoad(JavaVM *vm, void *reserved) +{ + JNIEnv *env; + jclass cls; + +#ifndef _WIN32 +#if HAVE_SQLITE2 + if (strcmp(sqlite_libencoding(), "UTF-8") != 0) { + fprintf(stderr, "WARNING: using non-UTF SQLite2 engine\n"); + } +#endif +#endif + if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) { + return JNI_ERR; + } + cls = (*env)->FindClass(env, "java/lang/String"); + if (!cls) { + return JNI_ERR; + } + C_java_lang_String = (*env)->NewWeakGlobalRef(env, cls); + return JNI_VERSION_1_2; +} + +JNIEXPORT void JNICALL +JNI_OnUnload(JavaVM *vm, void *reserved) +{ + JNIEnv *env; + + if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) { + return; + } + if (C_java_lang_String) { + (*env)->DeleteWeakGlobalRef(env, C_java_lang_String); + C_java_lang_String = 0; + } +} +#endif diff --git a/sqlite-jdbc/src/main/native/sqlite_jni.h b/sqlite-jdbc/src/main/native/sqlite_jni.h new file mode 100644 index 0000000..cdb7692 --- /dev/null +++ b/sqlite-jdbc/src/main/native/sqlite_jni.h @@ -0,0 +1,657 @@ +/* DO NOT EDIT THIS FILE - it is machine generated */ +#include <jni.h> +/* Header for class SQLite_Database */ + +#ifndef _Included_SQLite_Database +#define _Included_SQLite_Database +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: SQLite_Database + * Method: _open + * Signature: (Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1open + (JNIEnv *, jobject, jstring, jint); + +/* + * Class: SQLite_Database + * Method: _open_aux_file + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1open_1aux_1file + (JNIEnv *, jobject, jstring); + +/* + * Class: SQLite_Database + * Method: _finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1finalize + (JNIEnv *, jobject); + +/* + * Class: SQLite_Database + * Method: _close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1close + (JNIEnv *, jobject); + +/* + * Class: SQLite_Database + * Method: _exec + * Signature: (Ljava/lang/String;LSQLite/Callback;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2 + (JNIEnv *, jobject, jstring, jobject); + +/* + * Class: SQLite_Database + * Method: _exec + * Signature: (Ljava/lang/String;LSQLite/Callback;[Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2 + (JNIEnv *, jobject, jstring, jobject, jobjectArray); + +/* + * Class: SQLite_Database + * Method: _last_insert_rowid + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_SQLite_Database__1last_1insert_1rowid + (JNIEnv *, jobject); + +/* + * Class: SQLite_Database + * Method: _interrupt + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1interrupt + (JNIEnv *, jobject); + +/* + * Class: SQLite_Database + * Method: _changes + * Signature: ()J + */ +JNIEXPORT jlong JNICALL Java_SQLite_Database__1changes + (JNIEnv *, jobject); + +/* + * Class: SQLite_Database + * Method: _busy_handler + * Signature: (LSQLite/BusyHandler;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1busy_1handler + (JNIEnv *, jobject, jobject); + +/* + * Class: SQLite_Database + * Method: _busy_timeout + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1busy_1timeout + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Database + * Method: _complete + * Signature: (Ljava/lang/String;)Z + */ +JNIEXPORT jboolean JNICALL Java_SQLite_Database__1complete + (JNIEnv *, jclass, jstring); + +/* + * Class: SQLite_Database + * Method: version + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Database_version + (JNIEnv *, jclass); + +/* + * Class: SQLite_Database + * Method: dbversion + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Database_dbversion + (JNIEnv *, jobject); + +/* + * Class: SQLite_Database + * Method: _create_function + * Signature: (Ljava/lang/String;ILSQLite/Function;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1create_1function + (JNIEnv *, jobject, jstring, jint, jobject); + +/* + * Class: SQLite_Database + * Method: _create_aggregate + * Signature: (Ljava/lang/String;ILSQLite/Function;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1create_1aggregate + (JNIEnv *, jobject, jstring, jint, jobject); + +/* + * Class: SQLite_Database + * Method: _function_type + * Signature: (Ljava/lang/String;I)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1function_1type + (JNIEnv *, jobject, jstring, jint); + +/* + * Class: SQLite_Database + * Method: _errmsg + * Signature: ()Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Database__1errmsg + (JNIEnv *, jobject); + +/* + * Class: SQLite_Database + * Method: error_string + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Database_error_1string + (JNIEnv *, jclass, jint); + +/* + * Class: SQLite_Database + * Method: _set_encoding + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1set_1encoding + (JNIEnv *, jobject, jstring); + +/* + * Class: SQLite_Database + * Method: _set_authorizer + * Signature: (LSQLite/Authorizer;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1set_1authorizer + (JNIEnv *, jobject, jobject); + +/* + * Class: SQLite_Database + * Method: _trace + * Signature: (LSQLite/Trace;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1trace + (JNIEnv *, jobject, jobject); + +/* + * Class: SQLite_Database + * Method: is3 + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_SQLite_Database_is3 + (JNIEnv *, jobject); + +/* + * Class: SQLite_Database + * Method: vm_compile + * Signature: (Ljava/lang/String;LSQLite/Vm;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database_vm_1compile + (JNIEnv *, jobject, jstring, jobject); + +/* + * Class: SQLite_Database + * Method: vm_compile_args + * Signature: (Ljava/lang/String;LSQLite/Vm;[Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database_vm_1compile_1args + (JNIEnv *, jobject, jstring, jobject, jobjectArray); + +/* + * Class: SQLite_Database + * Method: stmt_prepare + * Signature: (Ljava/lang/String;LSQLite/Stmt;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database_stmt_1prepare + (JNIEnv *, jobject, jstring, jobject); + +/* + * Class: SQLite_Database + * Method: _open_blob + * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZLSQLite/Blob;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1open_1blob + (JNIEnv *, jobject, jstring, jstring, jstring, jlong, jboolean, jobject); + +/* + * Class: SQLite_Database + * Method: _progress_handler + * Signature: (ILSQLite/ProgressHandler;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Database__1progress_1handler + (JNIEnv *, jobject, jint, jobject); + +/* + * Class: SQLite_Database + * Method: internal_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Database_internal_1init + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class SQLite_Vm */ + +#ifndef _Included_SQLite_Vm +#define _Included_SQLite_Vm +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: SQLite_Vm + * Method: step + * Signature: (LSQLite/Callback;)Z + */ +JNIEXPORT jboolean JNICALL Java_SQLite_Vm_step + (JNIEnv *, jobject, jobject); + +/* + * Class: SQLite_Vm + * Method: compile + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_SQLite_Vm_compile + (JNIEnv *, jobject); + +/* + * Class: SQLite_Vm + * Method: stop + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Vm_stop + (JNIEnv *, jobject); + +/* + * Class: SQLite_Vm + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Vm_finalize + (JNIEnv *, jobject); + +/* + * Class: SQLite_Vm + * Method: internal_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Vm_internal_1init + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class SQLite_FunctionContext */ + +#ifndef _Included_SQLite_FunctionContext +#define _Included_SQLite_FunctionContext +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: SQLite_FunctionContext + * Method: set_result + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__Ljava_lang_String_2 + (JNIEnv *, jobject, jstring); + +/* + * Class: SQLite_FunctionContext + * Method: set_result + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__I + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_FunctionContext + * Method: set_result + * Signature: (D)V + */ +JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__D + (JNIEnv *, jobject, jdouble); + +/* + * Class: SQLite_FunctionContext + * Method: set_error + * Signature: (Ljava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1error + (JNIEnv *, jobject, jstring); + +/* + * Class: SQLite_FunctionContext + * Method: set_result + * Signature: ([B)V + */ +JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result___3B + (JNIEnv *, jobject, jbyteArray); + +/* + * Class: SQLite_FunctionContext + * Method: set_result_zeroblob + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result_1zeroblob + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_FunctionContext + * Method: count + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_SQLite_FunctionContext_count + (JNIEnv *, jobject); + +/* + * Class: SQLite_FunctionContext + * Method: internal_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_FunctionContext_internal_1init + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class SQLite_Stmt */ + +#ifndef _Included_SQLite_Stmt +#define _Included_SQLite_Stmt +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: SQLite_Stmt + * Method: prepare + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_SQLite_Stmt_prepare + (JNIEnv *, jobject); + +/* + * Class: SQLite_Stmt + * Method: step + * Signature: ()Z + */ +JNIEXPORT jboolean JNICALL Java_SQLite_Stmt_step + (JNIEnv *, jobject); + +/* + * Class: SQLite_Stmt + * Method: close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_close + (JNIEnv *, jobject); + +/* + * Class: SQLite_Stmt + * Method: reset + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_reset + (JNIEnv *, jobject); + +/* + * Class: SQLite_Stmt + * Method: clear_bindings + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_clear_1bindings + (JNIEnv *, jobject); + +/* + * Class: SQLite_Stmt + * Method: bind + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__II + (JNIEnv *, jobject, jint, jint); + +/* + * Class: SQLite_Stmt + * Method: bind + * Signature: (IJ)V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__IJ + (JNIEnv *, jobject, jint, jlong); + +/* + * Class: SQLite_Stmt + * Method: bind + * Signature: (ID)V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__ID + (JNIEnv *, jobject, jint, jdouble); + +/* + * Class: SQLite_Stmt + * Method: bind + * Signature: (I[B)V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__I_3B + (JNIEnv *, jobject, jint, jbyteArray); + +/* + * Class: SQLite_Stmt + * Method: bind + * Signature: (ILjava/lang/String;)V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__ILjava_lang_String_2 + (JNIEnv *, jobject, jint, jstring); + +/* + * Class: SQLite_Stmt + * Method: bind + * Signature: (I)V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__I + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: bind_zeroblob + * Signature: (II)V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_bind_1zeroblob + (JNIEnv *, jobject, jint, jint); + +/* + * Class: SQLite_Stmt + * Method: bind_parameter_count + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_SQLite_Stmt_bind_1parameter_1count + (JNIEnv *, jobject); + +/* + * Class: SQLite_Stmt + * Method: bind_parameter_name + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Stmt_bind_1parameter_1name + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: bind_parameter_index + * Signature: (Ljava/lang/String;)I + */ +JNIEXPORT jint JNICALL Java_SQLite_Stmt_bind_1parameter_1index + (JNIEnv *, jobject, jstring); + +/* + * Class: SQLite_Stmt + * Method: column_int + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1int + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_long + * Signature: (I)J + */ +JNIEXPORT jlong JNICALL Java_SQLite_Stmt_column_1long + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_double + * Signature: (I)D + */ +JNIEXPORT jdouble JNICALL Java_SQLite_Stmt_column_1double + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_bytes + * Signature: (I)[B + */ +JNIEXPORT jbyteArray JNICALL Java_SQLite_Stmt_column_1bytes + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_string + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1string + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_type + * Signature: (I)I + */ +JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1type + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_count + * Signature: ()I + */ +JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1count + (JNIEnv *, jobject); + +/* + * Class: SQLite_Stmt + * Method: column_table_name + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1table_1name + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_database_name + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1database_1name + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_decltype + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1decltype + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: column_origin_name + * Signature: (I)Ljava/lang/String; + */ +JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1origin_1name + (JNIEnv *, jobject, jint); + +/* + * Class: SQLite_Stmt + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_finalize + (JNIEnv *, jobject); + +/* + * Class: SQLite_Stmt + * Method: internal_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Stmt_internal_1init + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif +/* Header for class SQLite_Blob */ + +#ifndef _Included_SQLite_Blob +#define _Included_SQLite_Blob +#ifdef __cplusplus +extern "C" { +#endif +/* + * Class: SQLite_Blob + * Method: close + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Blob_close + (JNIEnv *, jobject); + +/* + * Class: SQLite_Blob + * Method: write + * Signature: ([BIII)I + */ +JNIEXPORT jint JNICALL Java_SQLite_Blob_write + (JNIEnv *, jobject, jbyteArray, jint, jint, jint); + +/* + * Class: SQLite_Blob + * Method: read + * Signature: ([BIII)I + */ +JNIEXPORT jint JNICALL Java_SQLite_Blob_read + (JNIEnv *, jobject, jbyteArray, jint, jint, jint); + +/* + * Class: SQLite_Blob + * Method: finalize + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Blob_finalize + (JNIEnv *, jobject); + +/* + * Class: SQLite_Blob + * Method: internal_init + * Signature: ()V + */ +JNIEXPORT void JNICALL Java_SQLite_Blob_internal_1init + (JNIEnv *, jclass); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/sqlite-jdbc/src/main/native/sqlite_jni_defs.h b/sqlite-jdbc/src/main/native/sqlite_jni_defs.h new file mode 100644 index 0000000..91b2378 --- /dev/null +++ b/sqlite-jdbc/src/main/native/sqlite_jni_defs.h @@ -0,0 +1,39 @@ +/* + * Copyright 2007, The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#define HAVE_SQLITE2 0 +#define HAVE_SQLITE3 1 +#define HAVE_SQLITE_FUNCTION_TYPE 0 +#define HAVE_SQLITE_OPEN_AUX_FILE 0 +#define HAVE_SQLITE_SET_AUTHORIZER 0 +#define HAVE_SQLITE_TRACE 0 +#define HAVE_SQLITE_COMPILE 0 +#define HAVE_SQLITE_PROGRESS_HANDLER 0 +#define HAVE_SQLITE3_MALLOC 1 +#define HAVE_SQLITE3_PREPARE_V2 0 +#define HAVE_SQLITE3_PREPARE16_V2 0 +#define HAVE_SQLITE3_BIND_ZEROBLOB 0 +#define HAVE_SQLITE3_CLEAR_BINDINGS 0 +#define HAVE_SQLITE3_COLUMN_TABLE_NAME16 0 +#define HAVE_SQLITE3_COLUMN_DATABASE_NAME16 0 +#define HAVE_SQLITE3_COLUMN_ORIGIN_NAME16 0 +#define HAVE_SQLITE3_BIND_PARAMETER_COUNT 1 +#define HAVE_SQLITE3_BIND_PARAMETER_NAME 1 +#define HAVE_SQLITE3_BIND_PARAMETER_INDEX 1 +#define HAVE_SQLITE3_RESULT_ZEROBLOB 0 +#define HAVE_SQLITE3_INCRBLOBIO 0 + + |