sqlite_jni.c revision 417deb1db112103aff04231b6ca79772ff7d3a21
1#include "JNIHelp.h"
2#include "sqlite_jni_defs.h"
3
4#include <stdlib.h>
5#include <stdio.h>
6#include <string.h>
7
8#if HAVE_SQLITE2
9#include "sqlite.h"
10#endif
11
12#if HAVE_SQLITE3
13#include "sqlite3.h"
14#undef  HAVE_SQLITE_COMPILE
15#define HAVE_SQLITE_COMPILE 1
16#undef  HAVE_SQLITE_PROGRESS_HANDLER
17#define HAVE_SQLITE_PROGRESS_HANDLER 1
18#undef  HAVE_SQLITE_TRACE
19#define HAVE_SQLITE_TRACE 1
20#if !HAVE_SQLITE3_MALLOC
21#define sqlite3_malloc malloc
22#define sqlite3_free   free
23#endif
24#if !HAVE_SQLITE3_BIND_PARAMETER_COUNT
25#define sqlite3_bind_parameter_count(dummy) (1000)
26#endif
27#endif
28
29#if HAVE_SQLITE2 && HAVE_SQLITE3
30#define HAVE_BOTH_SQLITE 1
31#endif
32
33#define CANT_PASS_VALIST_AS_CHARPTR
34
35#include "sqlite_jni.h"
36
37#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
38#define MAX_PARAMS 256
39#else
40#define MAX_PARAMS 32
41#endif
42
43/* free memory proc */
44
45typedef void (freemem)(void *);
46
47/* internal handle for SQLite database */
48
49typedef struct {
50    void *sqlite;		/* SQLite handle */
51#if HAVE_BOTH_SQLITE
52    int is3;			/* True for SQLITE3 handle */
53#endif
54    int ver;			/* version code */
55    jobject bh;			/* BusyHandler object */
56    jobject cb;			/* Callback object */
57    jobject ai;			/* Authorizer object */
58    jobject tr;			/* Trace object */
59    jobject ph;			/* ProgressHandler object */
60    JNIEnv *env;		/* Java environment for callbacks */
61    int row1;			/* true while processing first row */
62    int haveutf;		/* true for SQLite UTF-8 support */
63    jstring enc;		/* encoding or 0 */
64    struct hfunc *funcs;	/* SQLite user defined function handles */
65#if HAVE_SQLITE_COMPILE
66    struct hvm *vms;		/* Compiled SQLite VMs */
67#endif
68#if HAVE_SQLITE3
69    sqlite3_stmt *stmt;		/* For callback() */
70#endif
71#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
72  struct hbl *blobs;		/* SQLite3 blob handles */
73#endif
74} handle;
75
76/* internal handle for SQLite user defined function */
77
78typedef struct hfunc {
79    struct hfunc *next;		/* next function */
80#if HAVE_BOTH_SQLITE
81    int is3;			/* True for SQLITE3 handle */
82#endif
83    jobject fc;			/* FunctionContext object */
84    jobject fi;			/* Function object */
85    jobject db;			/* Database object */
86    handle *h;			/* SQLite database handle */
87    void *sf;			/* SQLite function handle */
88    JNIEnv *env;		/* Java environment for callbacks */
89} hfunc;
90
91#if HAVE_SQLITE_COMPILE
92/* internal handle for SQLite VM (sqlite_compile()) */
93
94typedef struct hvm {
95    struct hvm *next;		/* next vm handle */
96#if HAVE_BOTH_SQLITE
97    int is3;			/* True for SQLITE3 handle */
98#endif
99    void *vm;			/* SQLite 2/3 VM/statement */
100    char *tail;			/* tail SQL string */
101    int tail_len;		/* only for SQLite3/prepare */
102    handle *h;			/* SQLite database handle */
103    handle hh;			/* fake SQLite database handle */
104} hvm;
105#endif
106
107#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
108/* internal handle for sqlite3_blob */
109
110typedef struct hbl {
111    struct hbl *next;		/* next blob handle */
112    sqlite3_blob *blob;		/* SQLite3 blob */
113    handle *h;			/* SQLite database handle */
114} hbl;
115#endif
116
117/* ISO to/from UTF-8 translation */
118
119typedef struct {
120    char *result;		/* translated C string result */
121    char *tofree;		/* memory to be free'd, or 0 */
122    jstring jstr;		/* resulting Java string or 0 */
123} transstr;
124
125/* static cached weak class refs, field and method ids */
126
127static jclass C_java_lang_String = 0;
128
129static jfieldID F_SQLite_Database_handle = 0;
130static jfieldID F_SQLite_Database_error_code = 0;
131static jfieldID F_SQLite_FunctionContext_handle = 0;
132static jfieldID F_SQLite_Vm_handle = 0;
133static jfieldID F_SQLite_Vm_error_code = 0;
134static jfieldID F_SQLite_Stmt_handle = 0;
135static jfieldID F_SQLite_Stmt_error_code = 0;
136static jfieldID F_SQLite_Blob_handle = 0;
137static jfieldID F_SQLite_Blob_size = 0;
138
139static jmethodID M_java_lang_String_getBytes = 0;
140static jmethodID M_java_lang_String_getBytes2 = 0;
141static jmethodID M_java_lang_String_initBytes = 0;
142static jmethodID M_java_lang_String_initBytes2 = 0;
143
144static const char xdigits[] = "0123456789ABCDEF";
145
146static void
147seterr(JNIEnv *env, jobject obj, int err)
148{
149    jvalue v;
150
151    v.j = 0;
152    v.i = (jint) err;
153    (*env)->SetIntField(env, obj, F_SQLite_Database_error_code, v.i);
154}
155
156#if HAVE_SQLITE_COMPILE
157static void
158setvmerr(JNIEnv *env, jobject obj, int err)
159{
160    jvalue v;
161
162    v.j = 0;
163    v.i = (jint) err;
164    (*env)->SetIntField(env, obj, F_SQLite_Vm_error_code, v.i);
165}
166
167#if HAVE_SQLITE3
168static void
169setstmterr(JNIEnv *env, jobject obj, int err)
170{
171    jvalue v;
172
173    v.j = 0;
174    v.i = (jint) err;
175    (*env)->SetIntField(env, obj, F_SQLite_Stmt_error_code, v.i);
176}
177
178static int
179jstrlen(const jchar *jstr)
180{
181    int len = 0;
182
183    if (jstr) {
184        while (*jstr++) {
185	    len++;
186	}
187    }
188    return len;
189}
190#endif
191#endif
192
193static void *
194gethandle(JNIEnv *env, jobject obj)
195{
196    jvalue v;
197
198    v.j = (*env)->GetLongField(env, obj, F_SQLite_Database_handle);
199    return (void *) v.l;
200}
201
202#if HAVE_SQLITE_COMPILE
203static void *
204gethvm(JNIEnv *env, jobject obj)
205{
206    jvalue v;
207
208    v.j = (*env)->GetLongField(env, obj, F_SQLite_Vm_handle);
209    return (void *) v.l;
210}
211
212#if HAVE_SQLITE3
213static void *
214gethstmt(JNIEnv *env, jobject obj)
215{
216    jvalue v;
217
218    v.j = (*env)->GetLongField(env, obj, F_SQLite_Stmt_handle);
219    return (void *) v.l;
220}
221#endif
222#endif
223
224#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
225static void *
226gethbl(JNIEnv *env, jobject obj)
227{
228    jvalue v;
229
230    v.j = (*env)->GetLongField(env, obj, F_SQLite_Blob_handle);
231    return (void *) v.l;
232}
233#endif
234
235static void
236delglobrefp(JNIEnv *env, jobject *obj)
237{
238    if (*obj) {
239	(*env)->DeleteGlobalRef(env, *obj);
240	*obj = 0;
241    }
242}
243
244static jobject
245globrefpop(JNIEnv *env, jobject *obj)
246{
247    jobject ret = 0;
248
249    if (*obj) {
250	ret = *obj;
251	*obj = 0;
252    }
253    return ret;
254}
255
256static void
257globrefset(JNIEnv *env, jobject obj, jobject *ref)
258{
259    if (ref) {
260	if (obj) {
261	    *ref = (*env)->NewGlobalRef(env, obj);
262	} else {
263	    *ref = 0;
264	}
265    }
266}
267
268static void
269freep(char **strp)
270{
271    if (strp && *strp) {
272	free(*strp);
273	*strp = 0;
274    }
275}
276
277static void
278throwex(JNIEnv *env, const char *msg)
279{
280    jclass except = (*env)->FindClass(env, "SQLite/Exception");
281
282    (*env)->ExceptionClear(env);
283    if (except) {
284	(*env)->ThrowNew(env, except, msg);
285    }
286}
287
288static void
289throwoom(JNIEnv *env, const char *msg)
290{
291    jclass except = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
292
293    (*env)->ExceptionClear(env);
294    if (except) {
295	(*env)->ThrowNew(env, except, msg);
296    }
297}
298
299static void
300throwclosed(JNIEnv *env)
301{
302    throwex(env, "database already closed");
303}
304
305#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
306static void
307throwioex(JNIEnv *env, const char *msg)
308{
309    jclass except = (*env)->FindClass(env, "java/io/IOException");
310
311    (*env)->ExceptionClear(env);
312    if (except) {
313	(*env)->ThrowNew(env, except, msg);
314    }
315}
316#endif
317
318static void
319transfree(transstr *dest)
320{
321    dest->result = 0;
322    freep(&dest->tofree);
323}
324
325static char *
326trans2iso(JNIEnv *env, int haveutf, jstring enc, jstring src,
327	  transstr *dest)
328{
329    jbyteArray bytes = 0;
330    jthrowable exc;
331
332    dest->result = 0;
333    dest->tofree = 0;
334    if (haveutf) {
335        const jsize utfLength = (*env)->GetStringUTFLength(env, src);
336        dest->result = dest->tofree = malloc(utfLength + 1);
337        if (!dest->tofree) {
338            throwoom(env, "string translation failed");
339            return dest->result;
340        }
341        (*env)->GetStringUTFRegion(env, src, 0, utfLength, dest->result);
342        return dest->result;
343    }
344    if (enc) {
345	bytes = (*env)->CallObjectMethod(env, src,
346					 M_java_lang_String_getBytes2, enc);
347    } else {
348	bytes = (*env)->CallObjectMethod(env, src,
349					 M_java_lang_String_getBytes);
350    }
351    exc = (*env)->ExceptionOccurred(env);
352    if (!exc) {
353	jint len = (*env)->GetArrayLength(env, bytes);
354	dest->tofree = malloc(len + 1);
355	if (!dest->tofree) {
356	    throwoom(env, "string translation failed");
357	    return dest->result;
358	}
359	dest->result = dest->tofree;
360	(*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *) dest->result);
361	dest->result[len] = '\0';
362    } else {
363	(*env)->DeleteLocalRef(env, exc);
364    }
365    return dest->result;
366}
367
368static jstring
369trans2utf(JNIEnv *env, int haveutf, jstring enc, const char *src,
370	  transstr *dest)
371{
372    jbyteArray bytes = 0;
373    int len;
374
375    dest->result = 0;
376    dest->tofree = 0;
377    dest->jstr = 0;
378    if (!src) {
379	return dest->jstr;
380    }
381    if (haveutf) {
382	dest->jstr = (*env)->NewStringUTF(env, src);
383	return dest->jstr;
384    }
385    len = strlen(src);
386    bytes = (*env)->NewByteArray(env, len);
387    if (bytes) {
388	(*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) src);
389	if (enc) {
390	    dest->jstr =
391		(*env)->NewObject(env, C_java_lang_String,
392				  M_java_lang_String_initBytes2, bytes, enc);
393	} else {
394	    dest->jstr =
395		(*env)->NewObject(env, C_java_lang_String,
396				  M_java_lang_String_initBytes, bytes);
397	}
398	(*env)->DeleteLocalRef(env, bytes);
399	return dest->jstr;
400    }
401    throwoom(env, "string translation failed");
402    return dest->jstr;
403}
404
405#if HAVE_SQLITE2
406static int
407busyhandler(void *udata, const char *table, int count)
408{
409    handle *h = (handle *) udata;
410    JNIEnv *env = h->env;
411    int ret = 0;
412
413    if (env && h->bh) {
414	transstr tabstr;
415	jclass cls = (*env)->GetObjectClass(env, h->bh);
416	jmethodID mid = (*env)->GetMethodID(env, cls, "busy",
417					    "(Ljava/lang/String;I)Z");
418
419	if (mid == 0) {
420	    (*env)->DeleteLocalRef(env, cls);
421	    return ret;
422	}
423	trans2utf(env, h->haveutf, h->enc, table, &tabstr);
424	ret = (*env)->CallBooleanMethod(env, h->bh, mid, tabstr.jstr,
425					(jint) count)
426	      != JNI_FALSE;
427	(*env)->DeleteLocalRef(env, tabstr.jstr);
428	(*env)->DeleteLocalRef(env, cls);
429    }
430    return ret;
431}
432#endif
433
434#if HAVE_SQLITE3
435static int
436busyhandler3(void *udata, int count)
437{
438    handle *h = (handle *) udata;
439    JNIEnv *env = h->env;
440    int ret = 0;
441
442    if (env && h->bh) {
443	jclass cls = (*env)->GetObjectClass(env, h->bh);
444	jmethodID mid = (*env)->GetMethodID(env, cls, "busy",
445					    "(Ljava/lang/String;I)Z");
446
447	if (mid == 0) {
448	    (*env)->DeleteLocalRef(env, cls);
449	    return ret;
450	}
451	ret = (*env)->CallBooleanMethod(env, h->bh, mid, 0, (jint) count)
452	    != JNI_FALSE;
453	(*env)->DeleteLocalRef(env, cls);
454    }
455    return ret;
456}
457#endif
458
459static int
460progresshandler(void *udata)
461{
462    handle *h = (handle *) udata;
463    JNIEnv *env = h->env;
464    int ret = 0;
465
466    if (env && h->ph) {
467	jclass cls = (*env)->GetObjectClass(env, h->ph);
468	jmethodID mid = (*env)->GetMethodID(env, cls, "progress", "()Z");
469
470	if (mid == 0) {
471	    (*env)->DeleteLocalRef(env, cls);
472	    return ret;
473	}
474	ret = (*env)->CallBooleanMethod(env, h->ph, mid) != JNI_TRUE;
475	(*env)->DeleteLocalRef(env, cls);
476    }
477    return ret;
478}
479
480static int
481callback(void *udata, int ncol, char **data, char **cols)
482{
483    handle *h = (handle *) udata;
484    JNIEnv *env = h->env;
485
486    if (env && h->cb) {
487	jthrowable exc;
488	jclass cls = (*env)->GetObjectClass(env, h->cb);
489	jmethodID mid;
490	jobjectArray arr = 0;
491	jint i;
492
493	if (h->row1) {
494	    mid = (*env)->GetMethodID(env, cls, "columns",
495				      "([Ljava/lang/String;)V");
496
497	    if (mid) {
498		arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0);
499		for (i = 0; i < ncol; i++) {
500		    if (cols[i]) {
501			transstr col;
502
503			trans2utf(env, h->haveutf, h->enc, cols[i], &col);
504			(*env)->SetObjectArrayElement(env, arr, i, col.jstr);
505			exc = (*env)->ExceptionOccurred(env);
506			if (exc) {
507			    (*env)->DeleteLocalRef(env, exc);
508			    return 1;
509			}
510			(*env)->DeleteLocalRef(env, col.jstr);
511		    }
512		}
513		h->row1 = 0;
514		(*env)->CallVoidMethod(env, h->cb, mid, arr);
515		exc = (*env)->ExceptionOccurred(env);
516		if (exc) {
517		    (*env)->DeleteLocalRef(env, exc);
518		    return 1;
519		}
520		(*env)->DeleteLocalRef(env, arr);
521	    }
522#if HAVE_BOTH_SQLITE
523	    if (h->is3) {
524		mid = (*env)->GetMethodID(env, cls, "types",
525					  "([Ljava/lang/String;)V");
526
527		if (mid && h->stmt) {
528		    arr = (*env)->NewObjectArray(env, ncol,
529						 C_java_lang_String, 0);
530		    for (i = 0; i < ncol; i++) {
531			const char *ctype =
532			    sqlite3_column_decltype(h->stmt, i);
533
534			if (!ctype) {
535			    switch (sqlite3_column_type(h->stmt, i)) {
536			    case SQLITE_INTEGER: ctype = "integer"; break;
537			    case SQLITE_FLOAT:   ctype = "double";  break;
538			    default:
539#if defined(SQLITE_TEXT) && defined(SQLITE3_TEXT) && (SQLITE_TEXT != SQLITE3_TEXT)
540			    case SQLITE_TEXT:
541#else
542#ifdef SQLITE3_TEXT
543			    case SQLITE3_TEXT:
544#endif
545#endif
546						 ctype = "text";    break;
547			    case SQLITE_BLOB:    ctype = "blob";    break;
548			    case SQLITE_NULL:    ctype = "null";    break;
549			    }
550			}
551			if (ctype) {
552			    transstr ty;
553
554			    trans2utf(env, 1, 0, ctype, &ty);
555			    (*env)->SetObjectArrayElement(env, arr, i,
556							  ty.jstr);
557			    exc = (*env)->ExceptionOccurred(env);
558			    if (exc) {
559				(*env)->DeleteLocalRef(env, exc);
560				return 1;
561			    }
562			    (*env)->DeleteLocalRef(env, ty.jstr);
563			}
564		    }
565		    (*env)->CallVoidMethod(env, h->cb, mid, arr);
566		    exc = (*env)->ExceptionOccurred(env);
567		    if (exc) {
568			(*env)->DeleteLocalRef(env, exc);
569			return 1;
570		    }
571		    (*env)->DeleteLocalRef(env, arr);
572		}
573	    } else {
574		if (h->ver >= 0x020506 && cols[ncol]) {
575		    mid = (*env)->GetMethodID(env, cls, "types",
576					      "([Ljava/lang/String;)V");
577
578		    if (mid) {
579			arr = (*env)->NewObjectArray(env, ncol,
580						     C_java_lang_String, 0);
581			for (i = 0; i < ncol; i++) {
582			    if (cols[i + ncol]) {
583				transstr ty;
584
585				trans2utf(env, h->haveutf, h->enc,
586					  cols[i + ncol], &ty);
587				(*env)->SetObjectArrayElement(env, arr, i,
588							      ty.jstr);
589				exc = (*env)->ExceptionOccurred(env);
590				if (exc) {
591				    (*env)->DeleteLocalRef(env, exc);
592				    return 1;
593				}
594				(*env)->DeleteLocalRef(env, ty.jstr);
595			    }
596			}
597			(*env)->CallVoidMethod(env, h->cb, mid, arr);
598			exc = (*env)->ExceptionOccurred(env);
599			if (exc) {
600			    (*env)->DeleteLocalRef(env, exc);
601			    return 1;
602			}
603			(*env)->DeleteLocalRef(env, arr);
604		    }
605		}
606	    }
607#else
608#if HAVE_SQLITE2
609	    if (h->ver >= 0x020506 && cols[ncol]) {
610		mid = (*env)->GetMethodID(env, cls, "types",
611					  "([Ljava/lang/String;)V");
612
613		if (mid) {
614		    arr = (*env)->NewObjectArray(env, ncol,
615						 C_java_lang_String, 0);
616		    for (i = 0; i < ncol; i++) {
617			if (cols[i + ncol]) {
618			    transstr ty;
619
620			    trans2utf(env, h->haveutf, h->enc,
621				      cols[i + ncol], &ty);
622			    (*env)->SetObjectArrayElement(env, arr, i,
623							  ty.jstr);
624			    exc = (*env)->ExceptionOccurred(env);
625			    if (exc) {
626				(*env)->DeleteLocalRef(env, exc);
627				return 1;
628			    }
629			    (*env)->DeleteLocalRef(env, ty.jstr);
630			}
631		    }
632		    (*env)->CallVoidMethod(env, h->cb, mid, arr);
633		    exc = (*env)->ExceptionOccurred(env);
634		    if (exc) {
635			(*env)->DeleteLocalRef(env, exc);
636			return 1;
637		    }
638		    (*env)->DeleteLocalRef(env, arr);
639		}
640	    }
641#endif
642#if HAVE_SQLITE3
643	    mid = (*env)->GetMethodID(env, cls, "types",
644				      "([Ljava/lang/String;)V");
645
646	    if (mid && h->stmt) {
647		arr = (*env)->NewObjectArray(env, ncol,
648					     C_java_lang_String, 0);
649		for (i = 0; i < ncol; i++) {
650		    const char *ctype = sqlite3_column_decltype(h->stmt, i);
651
652		    if (!ctype) {
653			switch (sqlite3_column_type(h->stmt, i)) {
654			case SQLITE_INTEGER: ctype = "integer"; break;
655			case SQLITE_FLOAT:   ctype = "double";  break;
656			default:
657#if defined(SQLITE_TEXT) && defined(SQLITE3_TEXT) && (SQLITE_TEXT != SQLITE3_TEXT)
658			case SQLITE_TEXT:
659#else
660#ifdef SQLITE3_TEXT
661			case SQLITE3_TEXT:
662#endif
663#endif
664					     ctype = "text";    break;
665			case SQLITE_BLOB:    ctype = "blob";    break;
666			case SQLITE_NULL:    ctype = "null";    break;
667			}
668		    }
669		    if (ctype) {
670			transstr ty;
671
672			trans2utf(env, 1, 0, ctype, &ty);
673			(*env)->SetObjectArrayElement(env, arr, i, ty.jstr);
674			exc = (*env)->ExceptionOccurred(env);
675			if (exc) {
676			    (*env)->DeleteLocalRef(env, exc);
677			    return 1;
678			}
679			(*env)->DeleteLocalRef(env, ty.jstr);
680		    }
681		}
682		(*env)->CallVoidMethod(env, h->cb, mid, arr);
683		exc = (*env)->ExceptionOccurred(env);
684		if (exc) {
685		    (*env)->DeleteLocalRef(env, exc);
686		    return 1;
687		}
688		(*env)->DeleteLocalRef(env, arr);
689	    }
690#endif
691#endif
692	}
693	mid = (*env)->GetMethodID(env, cls, "newrow",
694				  "([Ljava/lang/String;)Z");
695	if (mid) {
696	    jboolean rc;
697
698	    if (data) {
699		arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0);
700	    } else {
701		arr = 0;
702	    }
703	    for (i = 0; arr && i < ncol; i++) {
704		if (data[i]) {
705		    transstr dats;
706
707		    trans2utf(env, h->haveutf, h->enc, data[i], &dats);
708		    (*env)->SetObjectArrayElement(env, arr, i, dats.jstr);
709		    exc = (*env)->ExceptionOccurred(env);
710		    if (exc) {
711			(*env)->DeleteLocalRef(env, exc);
712			return 1;
713		    }
714		    (*env)->DeleteLocalRef(env, dats.jstr);
715		}
716	    }
717	    rc = (*env)->CallBooleanMethod(env, h->cb, mid, arr);
718	    exc = (*env)->ExceptionOccurred(env);
719	    if (exc) {
720		(*env)->DeleteLocalRef(env, exc);
721		return 1;
722	    }
723	    if (arr) {
724		(*env)->DeleteLocalRef(env, arr);
725	    }
726	    (*env)->DeleteLocalRef(env, cls);
727	    return rc != JNI_FALSE;
728	}
729    }
730    return 0;
731}
732
733static void
734doclose(JNIEnv *env, jobject obj, int final)
735{
736    handle *h = gethandle(env, obj);
737
738    if (h) {
739	hfunc *f;
740#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
741	hbl *bl;
742#endif
743#if HAVE_SQLITE_COMPILE
744	hvm *v;
745
746	while ((v = h->vms)) {
747	    h->vms = v->next;
748	    v->next = 0;
749	    v->h = 0;
750	    if (v->vm) {
751#if HAVE_BOTH_SQLITE
752		if (h->is3) {
753		    sqlite3_finalize((sqlite3_stmt *) v->vm);
754		} else {
755		    sqlite_finalize((sqlite_vm *) v->vm, 0);
756		}
757#else
758#if HAVE_SQLITE2
759		sqlite_finalize((sqlite_vm *) v->vm, 0);
760#endif
761#if HAVE_SQLITE3
762		sqlite3_finalize((sqlite3_stmt *) v->vm);
763#endif
764#endif
765		v->vm = 0;
766	    }
767	}
768#endif
769	if (h->sqlite) {
770#if HAVE_BOTH_SQLITE
771	    if (h->is3) {
772		sqlite3_close((sqlite3 *) h->sqlite);
773	    } else {
774		sqlite_close((sqlite *) h->sqlite);
775	    }
776#else
777#if HAVE_SQLITE2
778	    sqlite_close((sqlite *) h->sqlite);
779#endif
780#if HAVE_SQLITE3
781	    sqlite3_close((sqlite3 *) h->sqlite);
782#endif
783#endif
784	    h->sqlite = 0;
785	}
786	while ((f = h->funcs)) {
787	    h->funcs = f->next;
788	    f->h = 0;
789	    f->sf = 0;
790	    f->env = 0;
791	    if (f->fc) {
792		(*env)->SetLongField(env, f->fc,
793				     F_SQLite_FunctionContext_handle, 0);
794	    }
795	    delglobrefp(env, &f->db);
796	    delglobrefp(env, &f->fi);
797	    delglobrefp(env, &f->fc);
798	    free(f);
799	}
800#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
801	while ((bl = h->blobs)) {
802	    h->blobs = bl->next;
803	    bl->next = 0;
804	    bl->h = 0;
805	    if (bl->blob) {
806	        sqlite3_blob_close(bl->blob);
807	    }
808	    bl->blob = 0;
809	}
810#endif
811	delglobrefp(env, &h->bh);
812	delglobrefp(env, &h->cb);
813	delglobrefp(env, &h->ai);
814	delglobrefp(env, &h->tr);
815	delglobrefp(env, &h->ph);
816	delglobrefp(env, &h->enc);
817	free(h);
818	(*env)->SetLongField(env, obj, F_SQLite_Database_handle, 0);
819	return;
820    }
821    if (!final) {
822	throwclosed(env);
823    }
824}
825
826JNIEXPORT void JNICALL
827Java_SQLite_Database__1close(JNIEnv *env, jobject obj)
828{
829    doclose(env, obj, 0);
830}
831
832JNIEXPORT void JNICALL
833Java_SQLite_Database__1finalize(JNIEnv *env, jobject obj)
834{
835    doclose(env, obj, 1);
836}
837
838JNIEXPORT void JNICALL
839Java_SQLite_Database__1busy_1timeout(JNIEnv *env, jobject obj, jint ms)
840{
841    handle *h = gethandle(env, obj);
842
843    if (h && h->sqlite) {
844#if HAVE_BOTH_SQLITE
845	if (h->is3) {
846	    sqlite3_busy_timeout((sqlite3 * ) h->sqlite, ms);
847	} else {
848	    sqlite_busy_timeout((sqlite *) h->sqlite, ms);
849	}
850#else
851#if HAVE_SQLITE2
852	sqlite_busy_timeout((sqlite *) h->sqlite, ms);
853#endif
854#if HAVE_SQLITE3
855	sqlite3_busy_timeout((sqlite3 * ) h->sqlite, ms);
856#endif
857#endif
858	return;
859    }
860    throwclosed(env);
861}
862
863JNIEXPORT jstring JNICALL
864Java_SQLite_Database_version(JNIEnv *env, jclass cls)
865{
866    /* CHECK THIS */
867#if HAVE_BOTH_SQLITE
868    return (*env)->NewStringUTF(env, sqlite_libversion());
869#else
870#if HAVE_SQLITE2
871    return (*env)->NewStringUTF(env, sqlite_libversion());
872#else
873    return (*env)->NewStringUTF(env, sqlite3_libversion());
874#endif
875#endif
876}
877
878JNIEXPORT jstring JNICALL
879Java_SQLite_Database_dbversion(JNIEnv *env, jobject obj)
880{
881    handle *h = gethandle(env, obj);
882
883    if (h && h->sqlite) {
884#if HAVE_BOTH_SQLITE
885	if (h->is3) {
886	    return (*env)->NewStringUTF(env, sqlite3_libversion());
887	} else {
888	    return (*env)->NewStringUTF(env, sqlite_libversion());
889	}
890#else
891#if HAVE_SQLITE2
892	return (*env)->NewStringUTF(env, sqlite_libversion());
893#else
894	return (*env)->NewStringUTF(env, sqlite3_libversion());
895#endif
896#endif
897    }
898    return (*env)->NewStringUTF(env, "unknown");
899}
900
901JNIEXPORT jlong JNICALL
902Java_SQLite_Database__1last_1insert_1rowid(JNIEnv *env, jobject obj)
903{
904    handle *h = gethandle(env, obj);
905
906    if (h && h->sqlite) {
907#if HAVE_BOTH_SQLITE
908	if (h->is3) {
909	    return (jlong) sqlite3_last_insert_rowid((sqlite3 *) h->sqlite);
910	} else {
911	    return (jlong) sqlite_last_insert_rowid((sqlite *) h->sqlite);
912	}
913#else
914#if HAVE_SQLITE2
915	return (jlong) sqlite_last_insert_rowid((sqlite *) h->sqlite);
916#endif
917#if HAVE_SQLITE3
918	return (jlong) sqlite3_last_insert_rowid((sqlite3 *) h->sqlite);
919#endif
920#endif
921    }
922    throwclosed(env);
923    return (jlong) 0;
924}
925
926JNIEXPORT jlong JNICALL
927Java_SQLite_Database__1changes(JNIEnv *env, jobject obj)
928{
929    handle *h = gethandle(env, obj);
930
931    if (h && h->sqlite) {
932#if HAVE_BOTH_SQLITE
933	if (h->is3) {
934	    return (jlong) sqlite3_changes((sqlite3 *) h->sqlite);
935	} else {
936	    return (jlong) sqlite_changes((sqlite *) h->sqlite);
937	}
938#else
939#if HAVE_SQLITE2
940	return (jlong) sqlite_changes((sqlite *) h->sqlite);
941#endif
942#if HAVE_SQLITE3
943	return (jlong) sqlite3_changes((sqlite3 *) h->sqlite);
944#endif
945#endif
946    }
947    throwclosed(env);
948    return (jlong) 0;
949}
950
951JNIEXPORT jboolean JNICALL
952Java_SQLite_Database__1complete(JNIEnv *env, jclass cls, jstring sql)
953{
954    transstr sqlstr;
955    jboolean result;
956
957    if (!sql) {
958	return JNI_FALSE;
959    }
960#if HAVE_BOTH_SQLITE || HAVE_SQLITE3
961    /* CHECK THIS */
962    trans2iso(env, 1, 0, sql, &sqlstr);
963    result = sqlite3_complete(sqlstr.result) ? JNI_TRUE : JNI_FALSE;
964#else
965    trans2iso(env, strcmp(sqlite_libencoding(), "UTF-8") == 0, 0,
966	      sql, &sqlstr);
967    result = sqlite_complete(sqlstr.result) ? JNI_TRUE : JNI_FALSE;
968#endif
969    transfree(&sqlstr);
970    return result;
971}
972
973JNIEXPORT void JNICALL
974Java_SQLite_Database__1interrupt(JNIEnv *env, jobject obj)
975{
976    handle *h = gethandle(env, obj);
977
978    if (h && h->sqlite) {
979#if HAVE_BOTH_SQLITE
980	if (h->is3) {
981	    sqlite3_interrupt((sqlite3 *) h->sqlite);
982	} else {
983	    sqlite_interrupt((sqlite *) h->sqlite);
984	}
985#else
986#if HAVE_SQLITE2
987	sqlite_interrupt((sqlite *) h->sqlite);
988#endif
989#if HAVE_SQLITE3
990	sqlite3_interrupt((sqlite3 *) h->sqlite);
991#endif
992#endif
993	return;
994    }
995    throwclosed(env);
996}
997
998JNIEXPORT void JNICALL
999Java_SQLite_Database__1open(JNIEnv *env, jobject obj, jstring file, jint mode)
1000{
1001    handle *h = gethandle(env, obj);
1002    jthrowable exc;
1003    char *err = 0;
1004    transstr filename;
1005    int maj, min, lev;
1006
1007    if (h) {
1008	if (h->sqlite) {
1009#if HAVE_BOTH_SQLITE
1010	    if (h->is3) {
1011		sqlite3_close((sqlite3 *) h->sqlite);
1012	    } else {
1013		sqlite_close((sqlite *) h->sqlite);
1014	    }
1015	    h->is3 = 0;
1016#else
1017#if HAVE_SQLITE2
1018	    sqlite_close((sqlite *) h->sqlite);
1019#endif
1020#if HAVE_SQLITE3
1021	    sqlite3_close((sqlite3 *) h->sqlite);
1022#endif
1023#endif
1024	    h->sqlite = 0;
1025	}
1026    } else {
1027	h = malloc(sizeof (handle));
1028	if (!h) {
1029	    throwoom(env, "unable to get SQLite handle");
1030	    return;
1031	}
1032	h->sqlite = 0;
1033	h->bh = h->cb = h->ai = h->tr = h->ph = 0;
1034	/* CHECK THIS */
1035#if HAVE_BOTH_SQLITE
1036	h->is3 = 0;
1037	h->stmt = 0;
1038	h->haveutf = 1;
1039#else
1040#if HAVE_SQLITE2
1041	h->haveutf = strcmp(sqlite_libencoding(), "UTF-8") == 0;
1042#endif
1043#if HAVE_SQLITE3
1044	h->stmt = 0;
1045	h->haveutf = 1;
1046#endif
1047#endif
1048	h->enc = 0;
1049	h->funcs = 0;
1050	h->ver = 0;
1051#if HAVE_SQLITE_COMPILE
1052	h->vms = 0;
1053#endif
1054#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
1055	h->blobs = 0;
1056#endif
1057    }
1058    h->env = 0;
1059    if (!file) {
1060	throwex(env, err ? err : "invalid file name");
1061	return;
1062    }
1063    trans2iso(env, h->haveutf, h->enc, file, &filename);
1064    exc = (*env)->ExceptionOccurred(env);
1065    if (exc) {
1066	(*env)->DeleteLocalRef(env, exc);
1067	return;
1068    }
1069#if HAVE_BOTH_SQLITE
1070    {
1071	FILE *f = fopen(filename.result, "rb");
1072	int c_0 = EOF;
1073
1074	if (f) {
1075	    c_0 = fgetc(f);
1076	    fclose(f);
1077	}
1078	if (c_0 != '*') {
1079	    int rc = sqlite3_open(filename.result, (sqlite3 **) &h->sqlite);
1080
1081	    if (rc == SQLITE_OK) {
1082		h->is3 = 1;
1083	    } else if (h->sqlite) {
1084	        sqlite3_close((sqlite3 *) h->sqlite);
1085		h->sqlite = 0;
1086	    }
1087	} else {
1088	    h->sqlite = (void *) sqlite_open(filename.result,
1089					     (int) mode, &err);
1090	}
1091    }
1092#else
1093#if HAVE_SQLITE2
1094    h->sqlite = (void *) sqlite_open(filename.result, (int) mode, &err);
1095#endif
1096#if HAVE_SQLITE3
1097    if (sqlite3_open(filename.result, (sqlite3 **) &h->sqlite) != SQLITE_OK) {
1098        if (h->sqlite) {
1099	    sqlite3_close((sqlite3 *) h->sqlite);
1100	    h->sqlite = 0;
1101	}
1102    }
1103#endif
1104#endif
1105    transfree(&filename);
1106    exc = (*env)->ExceptionOccurred(env);
1107    if (exc) {
1108	(*env)->DeleteLocalRef(env, exc);
1109#if HAVE_SQLITE2
1110	if (err) {
1111	    sqlite_freemem(err);
1112	}
1113#endif
1114	if (h->sqlite) {
1115#if HAVE_BOTH_SQLITE
1116	    if (h->is3) {
1117		sqlite3_close((sqlite3 *) h->sqlite);
1118		h->is3 = 0;
1119	    } else {
1120		sqlite_close((sqlite *) h->sqlite);
1121	    }
1122#else
1123#if HAVE_SQLITE2
1124	    sqlite_close((sqlite *) h->sqlite);
1125#endif
1126#if HAVE_SQLITE3
1127	    sqlite3_close((sqlite3 *) h->sqlite);
1128#endif
1129#endif
1130	}
1131	h->sqlite = 0;
1132	return;
1133    }
1134    if (h->sqlite) {
1135	jvalue v;
1136
1137	v.j = 0;
1138	v.l = (jobject) h;
1139	(*env)->SetLongField(env, obj, F_SQLite_Database_handle, v.j);
1140#if HAVE_SQLITE2
1141	if (err) {
1142	    sqlite_freemem(err);
1143	}
1144#endif
1145#if HAVE_BOTH_SQLITE
1146	if (h->is3) {
1147	    sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev);
1148	} else {
1149	    sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev);
1150	}
1151#else
1152#if HAVE_SQLITE2
1153	sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev);
1154#endif
1155#if HAVE_SQLITE3
1156	sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev);
1157#endif
1158#endif
1159	h->ver = ((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (lev & 0xFF);
1160	return;
1161    }
1162    throwex(env, err ? err : "unknown error in open");
1163#if HAVE_SQLITE2
1164    if (err) {
1165	sqlite_freemem(err);
1166    }
1167#endif
1168}
1169
1170JNIEXPORT void JNICALL
1171Java_SQLite_Database__1open_1aux_1file(JNIEnv *env, jobject obj, jstring file)
1172{
1173    handle *h = gethandle(env, obj);
1174#if HAVE_SQLITE_OPEN_AUX_FILE
1175    jboolean b;
1176    jthrowable exc;
1177    char *err = 0;
1178    transstr filename;
1179    int ret;
1180#endif
1181
1182    if (h && h->sqlite) {
1183#if HAVE_SQLITE_OPEN_AUX_FILE
1184#if HAVE_BOTH_SQLITE
1185	if (h->is3) {
1186	    throwex(env, "unsupported");
1187	}
1188#endif
1189	trans2iso(env, h->haveutf, h->enc, file, &filename);
1190	exc = (*env)->ExceptionOccurred(env);
1191	if (exc) {
1192	    (*env)->DeleteLocalRef(env, exc);
1193	    return;
1194	}
1195	ret = sqlite_open_aux_file((sqlite *) h->sqlite,
1196				   filename.result, &err);
1197	transfree(&filename);
1198	exc = (*env)->ExceptionOccurred(env);
1199	if (exc) {
1200	    (*env)->DeleteLocalRef(env, exc);
1201	    if (err) {
1202		sqlite_freemem(err);
1203	    }
1204	    return;
1205	}
1206	if (ret != SQLITE_OK) {
1207	    throwex(env, err ? err : sqlite_error_string(ret));
1208	}
1209	if (err) {
1210	    sqlite_freemem(err);
1211	}
1212#else
1213	throwex(env, "unsupported");
1214#endif
1215	return;
1216    }
1217    throwclosed(env);
1218}
1219
1220JNIEXPORT void JNICALL
1221Java_SQLite_Database__1busy_1handler(JNIEnv *env, jobject obj, jobject bh)
1222{
1223    handle *h = gethandle(env, obj);
1224
1225    if (h && h->sqlite) {
1226	delglobrefp(env, &h->bh);
1227	globrefset(env, bh, &h->bh);
1228#if HAVE_BOTH_SQLITE
1229	if (h->is3) {
1230	    sqlite3_busy_handler((sqlite3 *) h->sqlite, busyhandler3, h);
1231	} else {
1232	    sqlite_busy_handler((sqlite *) h->sqlite, busyhandler, h);
1233	}
1234#else
1235#if HAVE_SQLITE2
1236	sqlite_busy_handler((sqlite *) h->sqlite, busyhandler, h);
1237#endif
1238#if HAVE_SQLITE3
1239	sqlite3_busy_handler((sqlite3 *) h->sqlite, busyhandler3, h);
1240#endif
1241#endif
1242	return;
1243    }
1244    throwclosed(env);
1245}
1246
1247JNIEXPORT void JNICALL
1248Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2
1249    (JNIEnv *env, jobject obj, jstring sql, jobject cb)
1250{
1251    handle *h = gethandle(env, obj);
1252    freemem *freeproc;
1253
1254    if (!sql) {
1255	throwex(env, "invalid SQL statement");
1256	return;
1257    }
1258    if (h) {
1259	if (h->sqlite) {
1260	    jthrowable exc;
1261	    int rc;
1262	    char *err = 0;
1263	    transstr sqlstr;
1264	    jobject oldcb = globrefpop(env, &h->cb);
1265
1266	    globrefset(env, cb, &h->cb);
1267	    h->env = env;
1268	    h->row1 = 1;
1269	    trans2iso(env, h->haveutf, h->enc, sql, &sqlstr);
1270	    exc = (*env)->ExceptionOccurred(env);
1271	    if (exc) {
1272		(*env)->DeleteLocalRef(env, exc);
1273		return;
1274	    }
1275#if HAVE_BOTH_SQLITE
1276	    if (h->is3) {
1277		rc = sqlite3_exec((sqlite3 *) h->sqlite, sqlstr.result,
1278				  callback, h, &err);
1279		freeproc = (freemem *) sqlite3_free;
1280	    } else {
1281		rc = sqlite_exec((sqlite *) h->sqlite, sqlstr.result,
1282				 callback, h, &err);
1283		freeproc = (freemem *) sqlite_freemem;
1284	    }
1285#else
1286#if HAVE_SQLITE2
1287	    rc = sqlite_exec((sqlite *) h->sqlite, sqlstr.result,
1288			     callback, h, &err);
1289	    freeproc = (freemem *) sqlite_freemem;
1290#endif
1291#if HAVE_SQLITE3
1292	    rc = sqlite3_exec((sqlite3 *) h->sqlite, sqlstr.result,
1293			      callback, h, &err);
1294	    freeproc = (freemem *) sqlite3_free;
1295#endif
1296#endif
1297	    transfree(&sqlstr);
1298	    exc = (*env)->ExceptionOccurred(env);
1299	    delglobrefp(env, &h->cb);
1300	    h->cb = oldcb;
1301	    if (exc) {
1302		(*env)->DeleteLocalRef(env, exc);
1303		if (err) {
1304		    freeproc(err);
1305		}
1306		return;
1307	    }
1308	    if (rc != SQLITE_OK) {
1309		char msg[128];
1310
1311		seterr(env, obj, rc);
1312		if (!err) {
1313		    sprintf(msg, "error %d in sqlite*_exec", rc);
1314		}
1315		throwex(env, err ? err : msg);
1316	    }
1317	    if (err) {
1318		freeproc(err);
1319	    }
1320	    return;
1321	}
1322    }
1323    throwclosed(env);
1324}
1325
1326JNIEXPORT void JNICALL
1327Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2
1328    (JNIEnv *env, jobject obj, jstring sql, jobject cb, jobjectArray args)
1329{
1330    handle *h = gethandle(env, obj);
1331    freemem *freeproc = 0;
1332
1333    if (!sql) {
1334	throwex(env, "invalid SQL statement");
1335	return;
1336    }
1337    if (h) {
1338	if (h->sqlite) {
1339	    jthrowable exc;
1340	    int rc = SQLITE_ERROR, nargs, i;
1341	    char *err = 0, *p;
1342	    const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
1343	    transstr sqlstr;
1344	    struct args {
1345		char *arg;
1346		jobject obj;
1347		transstr trans;
1348	    } *argv = 0;
1349	    char **cargv = 0;
1350	    jobject oldcb = globrefpop(env, &h->cb);
1351
1352	    globrefset(env, cb, &h->cb);
1353	    p = (char *) str;
1354	    nargs = 0;
1355	    while (*p) {
1356		if (*p == '%') {
1357		    ++p;
1358		    if (*p == 'q' || *p == 's') {
1359			nargs++;
1360			if (nargs > MAX_PARAMS) {
1361			    (*env)->ReleaseStringUTFChars(env, sql, str);
1362			    delglobrefp(env, &h->cb);
1363			    h->cb = oldcb;
1364			    throwex(env, "too much SQL parameters");
1365			    return;
1366			}
1367		    } else if (h->ver >= 0x020500 && *p == 'Q') {
1368			nargs++;
1369			if (nargs > MAX_PARAMS) {
1370			    (*env)->ReleaseStringUTFChars(env, sql, str);
1371			    delglobrefp(env, &h->cb);
1372			    h->cb = oldcb;
1373			    throwex(env, "too much SQL parameters");
1374			    return;
1375			}
1376		    } else if (*p != '%') {
1377			(*env)->ReleaseStringUTFChars(env, sql, str);
1378			delglobrefp(env, &h->cb);
1379			h->cb = oldcb;
1380			throwex(env, "bad % specification in query");
1381			return;
1382		    }
1383		}
1384		++p;
1385	    }
1386	    cargv = malloc((sizeof (*argv) + sizeof (char *))
1387			   * MAX_PARAMS);
1388	    if (!cargv) {
1389		(*env)->ReleaseStringUTFChars(env, sql, str);
1390		delglobrefp(env, &h->cb);
1391		h->cb = oldcb;
1392		throwoom(env, "unable to allocate arg vector");
1393		return;
1394	    }
1395	    argv = (struct args *) (cargv + MAX_PARAMS);
1396	    for (i = 0; i < MAX_PARAMS; i++) {
1397		cargv[i] = 0;
1398		argv[i].arg = 0;
1399		argv[i].obj = 0;
1400		argv[i].trans.result = argv[i].trans.tofree = 0;
1401	    }
1402	    exc = 0;
1403	    for (i = 0; i < nargs; i++) {
1404		jobject so = (*env)->GetObjectArrayElement(env, args, i);
1405
1406		exc = (*env)->ExceptionOccurred(env);
1407		if (exc) {
1408		    (*env)->DeleteLocalRef(env, exc);
1409		    break;
1410		}
1411		if (so) {
1412		    argv[i].obj = so;
1413		    argv[i].arg = cargv[i] =
1414			trans2iso(env, h->haveutf, h->enc, argv[i].obj,
1415				  &argv[i].trans);
1416		}
1417	    }
1418	    if (exc) {
1419		for (i = 0; i < nargs; i++) {
1420		    if (argv[i].obj) {
1421			transfree(&argv[i].trans);
1422		    }
1423		}
1424		freep((char **) &cargv);
1425		(*env)->ReleaseStringUTFChars(env, sql, str);
1426		delglobrefp(env, &h->cb);
1427		h->cb = oldcb;
1428		return;
1429	    }
1430	    h->env = env;
1431	    h->row1 = 1;
1432	    trans2iso(env, h->haveutf, h->enc, sql, &sqlstr);
1433	    exc = (*env)->ExceptionOccurred(env);
1434	    if (!exc) {
1435#if HAVE_BOTH_SQLITE
1436		if (h->is3) {
1437#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
1438		    char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
1439#else
1440		    char *s = sqlite3_mprintf(sqlstr.result,
1441					      cargv[0], cargv[1],
1442					      cargv[2], cargv[3],
1443					      cargv[4], cargv[5],
1444					      cargv[6], cargv[7],
1445					      cargv[8], cargv[9],
1446					      cargv[10], cargv[11],
1447					      cargv[12], cargv[13],
1448					      cargv[14], cargv[15],
1449					      cargv[16], cargv[17],
1450					      cargv[18], cargv[19],
1451					      cargv[20], cargv[21],
1452					      cargv[22], cargv[23],
1453					      cargv[24], cargv[25],
1454					      cargv[26], cargv[27],
1455					      cargv[28], cargv[29],
1456					      cargv[30], cargv[31]);
1457#endif
1458
1459		    if (s) {
1460			rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback,
1461					  h, &err);
1462			sqlite3_free(s);
1463		    } else {
1464			rc = SQLITE_NOMEM;
1465		    }
1466		    freeproc = (freemem *) sqlite3_free;
1467		} else {
1468#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
1469		    rc = sqlite_exec_vprintf((sqlite *) h->sqlite,
1470					     sqlstr.result, callback, h, &err,
1471					     (char *) cargv);
1472#else
1473		    rc = sqlite_exec_printf((sqlite *) h->sqlite,
1474					    sqlstr.result, callback,
1475					    h, &err,
1476					    cargv[0], cargv[1],
1477					    cargv[2], cargv[3],
1478					    cargv[4], cargv[5],
1479					    cargv[6], cargv[7],
1480					    cargv[8], cargv[9],
1481					    cargv[10], cargv[11],
1482					    cargv[12], cargv[13],
1483					    cargv[14], cargv[15],
1484					    cargv[16], cargv[17],
1485					    cargv[18], cargv[19],
1486					    cargv[20], cargv[21],
1487					    cargv[22], cargv[23],
1488					    cargv[24], cargv[25],
1489					    cargv[26], cargv[27],
1490					    cargv[28], cargv[29],
1491					    cargv[30], cargv[31]);
1492#endif
1493		    freeproc = (freemem *) sqlite_freemem;
1494		}
1495#else
1496#if HAVE_SQLITE2
1497#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
1498		rc = sqlite_exec_vprintf((sqlite *) h->sqlite, sqlstr.result,
1499					 callback, h, &err, (char *) cargv);
1500#else
1501		rc = sqlite_exec_printf((sqlite *) h->sqlite, sqlstr.result,
1502					callback, h, &err,
1503					cargv[0], cargv[1],
1504					cargv[2], cargv[3],
1505					cargv[4], cargv[5],
1506					cargv[6], cargv[7],
1507					cargv[8], cargv[9],
1508					cargv[10], cargv[11],
1509					cargv[12], cargv[13],
1510					cargv[14], cargv[15],
1511					cargv[16], cargv[17],
1512					cargv[18], cargv[19],
1513					cargv[20], cargv[21],
1514					cargv[22], cargv[23],
1515					cargv[24], cargv[25],
1516					cargv[26], cargv[27],
1517					cargv[28], cargv[29],
1518					cargv[30], cargv[31]);
1519#endif
1520		freeproc = (freemem *) sqlite_freemem;
1521#endif
1522#if HAVE_SQLITE3
1523#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
1524		char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
1525#else
1526		char *s = sqlite3_mprintf(sqlstr.result,
1527					  cargv[0], cargv[1],
1528					  cargv[2], cargv[3],
1529					  cargv[4], cargv[5],
1530					  cargv[6], cargv[7],
1531					  cargv[8], cargv[9],
1532					  cargv[10], cargv[11],
1533					  cargv[12], cargv[13],
1534					  cargv[14], cargv[15],
1535					  cargv[16], cargv[17],
1536					  cargv[18], cargv[19],
1537					  cargv[20], cargv[21],
1538					  cargv[22], cargv[23],
1539					  cargv[24], cargv[25],
1540					  cargv[26], cargv[27],
1541					  cargv[28], cargv[29],
1542					  cargv[30], cargv[31]);
1543#endif
1544
1545		if (s) {
1546		    rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback,
1547				      h, &err);
1548		    sqlite3_free(s);
1549		} else {
1550		    rc = SQLITE_NOMEM;
1551		}
1552		freeproc = (freemem *) sqlite3_free;
1553#endif
1554#endif
1555		exc = (*env)->ExceptionOccurred(env);
1556	    }
1557	    for (i = 0; i < nargs; i++) {
1558		if (argv[i].obj) {
1559		    transfree(&argv[i].trans);
1560		}
1561	    }
1562	    transfree(&sqlstr);
1563	    (*env)->ReleaseStringUTFChars(env, sql, str);
1564	    freep((char **) &cargv);
1565	    delglobrefp(env, &h->cb);
1566	    h->cb = oldcb;
1567	    if (exc) {
1568		(*env)->DeleteLocalRef(env, exc);
1569		if (err && freeproc) {
1570		    freeproc(err);
1571		}
1572		return;
1573	    }
1574	    if (rc != SQLITE_OK) {
1575		char msg[128];
1576
1577		seterr(env, obj, rc);
1578		if (!err) {
1579		    sprintf(msg, "error %d in sqlite*_exec", rc);
1580		}
1581		throwex(env, err ? err : msg);
1582	    }
1583	    if (err && freeproc) {
1584		freeproc(err);
1585	    }
1586	    return;
1587	}
1588    }
1589    throwclosed(env);
1590}
1591
1592static hfunc *
1593getfunc(JNIEnv *env, jobject obj)
1594{
1595    jvalue v;
1596
1597    v.j = (*env)->GetLongField(env, obj, F_SQLite_FunctionContext_handle);
1598    return (hfunc *) v.l;
1599}
1600
1601#if HAVE_SQLITE2
1602static void
1603call_common(sqlite_func *sf, int isstep, int nargs, const char **args)
1604{
1605    hfunc *f = (hfunc *) sqlite_user_data(sf);
1606
1607    if (f && f->env && f->fi) {
1608	JNIEnv *env = f->env;
1609	jclass cls = (*env)->GetObjectClass(env, f->fi);
1610	jmethodID mid =
1611	    (*env)->GetMethodID(env, cls,
1612				isstep ? "step" : "function",
1613				"(LSQLite/FunctionContext;[Ljava/lang/String;)V");
1614	jobjectArray arr;
1615	int i;
1616
1617	if (mid == 0) {
1618	    (*env)->DeleteLocalRef(env, cls);
1619	    return;
1620	}
1621	arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
1622	for (i = 0; i < nargs; i++) {
1623	    if (args[i]) {
1624		transstr arg;
1625		jthrowable exc;
1626
1627		trans2utf(env, f->h->haveutf, f->h->enc, args[i], &arg);
1628		(*env)->SetObjectArrayElement(env, arr, i, arg.jstr);
1629		exc = (*env)->ExceptionOccurred(env);
1630		if (exc) {
1631		    (*env)->DeleteLocalRef(env, exc);
1632		    return;
1633		}
1634		(*env)->DeleteLocalRef(env, arg.jstr);
1635	    }
1636	}
1637	f->sf = sf;
1638	(*env)->CallVoidMethod(env, f->fi, mid, f->fc, arr);
1639	(*env)->DeleteLocalRef(env, arr);
1640	(*env)->DeleteLocalRef(env, cls);
1641    }
1642}
1643
1644static void
1645call_func(sqlite_func *sf, int nargs, const char **args)
1646{
1647    call_common(sf, 0, nargs, args);
1648}
1649
1650static void
1651call_step(sqlite_func *sf, int nargs, const char **args)
1652{
1653    call_common(sf, 1, nargs, args);
1654}
1655
1656static void
1657call_final(sqlite_func *sf)
1658{
1659    hfunc *f = (hfunc *) sqlite_user_data(sf);
1660
1661    if (f && f->env && f->fi) {
1662	JNIEnv *env = f->env;
1663	jclass cls = (*env)->GetObjectClass(env, f->fi);
1664	jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
1665					    "(LSQLite/FunctionContext;)V");
1666	if (mid == 0) {
1667	    (*env)->DeleteLocalRef(env, cls);
1668	    return;
1669	}
1670	f->sf = sf;
1671	(*env)->CallVoidMethod(env, f->fi, mid, f->fc);
1672	(*env)->DeleteLocalRef(env, cls);
1673    }
1674}
1675#endif
1676
1677#if HAVE_SQLITE3
1678static void
1679call3_common(sqlite3_context *sf, int isstep, int nargs, sqlite3_value **args)
1680{
1681    hfunc *f = (hfunc *) sqlite3_user_data(sf);
1682
1683    if (f && f->env && f->fi) {
1684	JNIEnv *env = f->env;
1685	jclass cls = (*env)->GetObjectClass(env, f->fi);
1686	jmethodID mid =
1687	    (*env)->GetMethodID(env, cls,
1688				isstep ? "step" : "function",
1689				"(LSQLite/FunctionContext;[Ljava/lang/String;)V");
1690	jobjectArray arr;
1691	int i;
1692
1693	if (mid == 0) {
1694	    (*env)->DeleteLocalRef(env, cls);
1695	    return;
1696	}
1697	arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
1698	for (i = 0; i < nargs; i++) {
1699	    if (args[i]) {
1700		transstr arg;
1701		jthrowable exc;
1702
1703		trans2utf(env, 1, 0, (char *) sqlite3_value_text(args[i]),
1704			  &arg);
1705		(*env)->SetObjectArrayElement(env, arr, i, arg.jstr);
1706		exc = (*env)->ExceptionOccurred(env);
1707		if (exc) {
1708		    (*env)->DeleteLocalRef(env, exc);
1709		    return;
1710		}
1711		(*env)->DeleteLocalRef(env, arg.jstr);
1712	    }
1713	}
1714	f->sf = sf;
1715	(*env)->CallVoidMethod(env, f->fi, mid, f->fc, arr);
1716	(*env)->DeleteLocalRef(env, arr);
1717	(*env)->DeleteLocalRef(env, cls);
1718    }
1719}
1720
1721static void
1722call3_func(sqlite3_context *sf, int nargs, sqlite3_value **args)
1723{
1724    call3_common(sf, 0, nargs, args);
1725}
1726
1727static void
1728call3_step(sqlite3_context *sf, int nargs, sqlite3_value **args)
1729{
1730    call3_common(sf, 1, nargs, args);
1731}
1732
1733static void
1734call3_final(sqlite3_context *sf)
1735{
1736    hfunc *f = (hfunc *) sqlite3_user_data(sf);
1737
1738    if (f && f->env && f->fi) {
1739	JNIEnv *env = f->env;
1740	jclass cls = (*env)->GetObjectClass(env, f->fi);
1741	jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
1742					    "(LSQLite/FunctionContext;)V");
1743	if (mid == 0) {
1744	    (*env)->DeleteLocalRef(env, cls);
1745	    return;
1746	}
1747	f->sf = sf;
1748	(*env)->CallVoidMethod(env, f->fi, mid, f->fc);
1749	(*env)->DeleteLocalRef(env, cls);
1750    }
1751}
1752#endif
1753
1754static void
1755mkfunc_common(JNIEnv *env, int isagg, jobject obj, jstring name,
1756	      jint nargs, jobject fi)
1757{
1758    handle *h = gethandle(env, obj);
1759
1760    if (h && h->sqlite) {
1761	jclass cls = (*env)->FindClass(env, "SQLite/FunctionContext");
1762	jobject fc;
1763	hfunc *f;
1764	int ret;
1765	transstr namestr;
1766	jvalue v;
1767	jthrowable exc;
1768
1769	fc = (*env)->AllocObject(env, cls);
1770	if (!fi) {
1771	    throwex(env, "null SQLite.Function not allowed");
1772	    return;
1773	}
1774	f = malloc(sizeof (hfunc));
1775	if (!f) {
1776	    throwoom(env, "unable to get SQLite.FunctionContext handle");
1777	    return;
1778	}
1779	globrefset(env, fc, &f->fc);
1780	globrefset(env, fi, &f->fi);
1781	globrefset(env, obj, &f->db);
1782	f->h = h;
1783	f->next = h->funcs;
1784	h->funcs = f;
1785	f->sf = 0;
1786	f->env = env;
1787	v.j = 0;
1788	v.l = (jobject) f;
1789	(*env)->SetLongField(env, f->fc, F_SQLite_FunctionContext_handle, v.j);
1790	trans2iso(env, h->haveutf, h->enc, name, &namestr);
1791	exc = (*env)->ExceptionOccurred(env);
1792	if (exc) {
1793	    (*env)->DeleteLocalRef(env, exc);
1794	    return;
1795	}
1796#if HAVE_BOTH_SQLITE
1797	f->is3 = h->is3;
1798	if (h->is3) {
1799	    ret = sqlite3_create_function((sqlite3 *) h->sqlite,
1800					  namestr.result,
1801					  (int) nargs,
1802					  SQLITE_UTF8, f,
1803					  isagg ? NULL : call3_func,
1804					  isagg ? call3_step : NULL,
1805					  isagg ? call3_final : NULL);
1806
1807	} else {
1808	    if (isagg) {
1809		ret = sqlite_create_aggregate((sqlite *) h->sqlite,
1810					      namestr.result,
1811					      (int) nargs,
1812					      call_step, call_final, f);
1813	    } else {
1814		ret = sqlite_create_function((sqlite *) h->sqlite,
1815					     namestr.result,
1816					     (int) nargs,
1817					     call_func, f);
1818	    }
1819	}
1820#else
1821#if HAVE_SQLITE2
1822	if (isagg) {
1823	    ret = sqlite_create_aggregate((sqlite *) h->sqlite, namestr.result,
1824					  (int) nargs,
1825					  call_step, call_final, f);
1826	} else {
1827	    ret = sqlite_create_function((sqlite *) h->sqlite, namestr.result,
1828					 (int) nargs,
1829					 call_func, f);
1830	}
1831#endif
1832#if HAVE_SQLITE3
1833	ret = sqlite3_create_function((sqlite3 *) h->sqlite,
1834				      namestr.result,
1835				      (int) nargs,
1836				      SQLITE_UTF8, f,
1837				      isagg ? NULL : call3_func,
1838				      isagg ? call3_step : NULL,
1839				      isagg ? call3_final : NULL);
1840#endif
1841#endif
1842	transfree(&namestr);
1843	if (ret != SQLITE_OK) {
1844	    throwex(env, "error creating function/aggregate");
1845	}
1846	return;
1847    }
1848    throwclosed(env);
1849}
1850
1851JNIEXPORT void JNICALL
1852Java_SQLite_Database__1create_1aggregate(JNIEnv *env, jobject obj,
1853					 jstring name, jint nargs, jobject fi)
1854{
1855    mkfunc_common(env, 1, obj, name, nargs, fi);
1856}
1857
1858JNIEXPORT void JNICALL
1859Java_SQLite_Database__1create_1function(JNIEnv *env, jobject obj,
1860					jstring name, jint nargs, jobject fi)
1861{
1862    mkfunc_common(env, 0, obj, name, nargs, fi);
1863}
1864
1865JNIEXPORT void JNICALL
1866Java_SQLite_Database__1function_1type(JNIEnv *env, jobject obj,
1867				      jstring name, jint type)
1868{
1869    handle *h = gethandle(env, obj);
1870
1871    if (h && h->sqlite) {
1872#if HAVE_BOTH_SQLITE
1873	if (h->is3) {
1874	    return;
1875	}
1876#endif
1877#if HAVE_SQLITE2
1878#if HAVE_SQLITE_FUNCTION_TYPE
1879	{
1880	    int ret;
1881	    transstr namestr;
1882	    jthrowable exc;
1883
1884	    trans2iso(env, h->haveutf, h->enc, name, &namestr);
1885	    exc = (*env)->ExceptionOccurred(env);
1886	    if (exc) {
1887		(*env)->DeleteLocalRef(env, exc);
1888		return;
1889	    }
1890	    ret = sqlite_function_type(h->sqlite, namestr.result, (int) type);
1891	    transfree(&namestr);
1892	    if (ret != SQLITE_OK) {
1893		throwex(env, sqlite_error_string(ret));
1894	    }
1895	}
1896#endif
1897#endif
1898	return;
1899    }
1900    throwclosed(env);
1901}
1902
1903JNIEXPORT jint JNICALL
1904Java_SQLite_FunctionContext_count(JNIEnv *env, jobject obj)
1905{
1906    hfunc *f = getfunc(env, obj);
1907    jint r = 0;
1908
1909    if (f && f->sf) {
1910#if HAVE_SQLITE_BOTH
1911	if (f->is3) {
1912	    r = (jint) sqlite3_aggregate_count((sqlite3_context *) f->sf);
1913	} else {
1914	    r = (jint) sqlite_aggregate_count((sqlite_func *) f->sf);
1915	}
1916#else
1917#if HAVE_SQLITE2
1918	r = (jint) sqlite_aggregate_count((sqlite_func *) f->sf);
1919#endif
1920#if HAVE_SQLITE3
1921	r = (jint) sqlite3_aggregate_count((sqlite3_context *) f->sf);
1922#endif
1923#endif
1924    }
1925    return r;
1926}
1927
1928JNIEXPORT void JNICALL
1929Java_SQLite_FunctionContext_set_1error(JNIEnv *env, jobject obj, jstring err)
1930{
1931    hfunc *f = getfunc(env, obj);
1932
1933    if (f && f->sf) {
1934#if HAVE_BOTH_SQLITE
1935	if (!f->is3) {
1936	    transstr errstr;
1937	    jthrowable exc;
1938
1939	    trans2iso(env, f->h->haveutf, f->h->enc, err, &errstr);
1940	    exc = (*env)->ExceptionOccurred(env);
1941	    if (exc) {
1942	        (*env)->DeleteLocalRef(env, exc);
1943		return;
1944	    }
1945	    sqlite_set_result_error((sqlite_func *) f->sf,
1946				    errstr.result, -1);
1947	    transfree(&errstr);
1948	} else if (err) {
1949	    jsize len = (*env)->GetStringLength(env, err) * sizeof (jchar);
1950	    const jchar *str = (*env)->GetStringChars(env, err, 0);
1951
1952	    sqlite3_result_error16((sqlite3_context *) f->sf, str, len);
1953	    (*env)->ReleaseStringChars(env, err, str);
1954	} else {
1955	    sqlite3_result_error((sqlite3_context *) f->sf,
1956				 "null error text", -1);
1957	}
1958#else
1959#if HAVE_SQLITE2
1960	transstr errstr;
1961	jthrowable exc;
1962
1963	trans2iso(env, f->h->haveutf, f->h->enc, err, &errstr);
1964	exc = (*env)->ExceptionOccurred(env);
1965	if (exc) {
1966	    (*env)->DeleteLocalRef(env, exc);
1967	    return;
1968	}
1969	sqlite_set_result_error((sqlite_func *) f->sf, errstr.result, -1);
1970	transfree(&errstr);
1971#endif
1972#if HAVE_SQLITE3
1973	if (err) {
1974	    jsize len = (*env)->GetStringLength(env, err) * sizeof (jchar);
1975	    const jchar *str = (*env)->GetStringChars(env, err, 0);
1976
1977	    sqlite3_result_error16((sqlite3_context *) f->sf, str, len);
1978	    (*env)->ReleaseStringChars(env, err, str);
1979	} else {
1980	    sqlite3_result_error((sqlite3_context *) f->sf,
1981				 "null error text", -1);
1982	}
1983#endif
1984#endif
1985    }
1986}
1987
1988JNIEXPORT void JNICALL
1989Java_SQLite_FunctionContext_set_1result__D(JNIEnv *env, jobject obj, jdouble d)
1990{
1991    hfunc *f = getfunc(env, obj);
1992
1993    if (f && f->sf) {
1994#if HAVE_BOTH_SQLITE
1995	if (f->is3) {
1996	    sqlite3_result_double((sqlite3_context *) f->sf, (double) d);
1997	} else {
1998	    sqlite_set_result_double((sqlite_func *) f->sf, (double) d);
1999	}
2000#else
2001#if HAVE_SQLITE2
2002	sqlite_set_result_double((sqlite_func *) f->sf, (double) d);
2003#endif
2004#if HAVE_SQLITE3
2005	sqlite3_result_double((sqlite3_context *) f->sf, (double) d);
2006#endif
2007#endif
2008    }
2009}
2010
2011JNIEXPORT void JNICALL
2012Java_SQLite_FunctionContext_set_1result__I(JNIEnv *env, jobject obj, jint i)
2013{
2014    hfunc *f = getfunc(env, obj);
2015
2016    if (f && f->sf) {
2017#if HAVE_BOTH_SQLITE
2018	if (f->is3) {
2019	    sqlite3_result_int((sqlite3_context *) f->sf, (int) i);
2020	} else {
2021	    sqlite_set_result_int((sqlite_func *) f->sf, (int) i);
2022	}
2023#else
2024#if HAVE_SQLITE2
2025	sqlite_set_result_int((sqlite_func *) f->sf, (int) i);
2026#endif
2027#if HAVE_SQLITE3
2028	sqlite3_result_int((sqlite3_context *) f->sf, (int) i);
2029#endif
2030#endif
2031    }
2032}
2033
2034JNIEXPORT void JNICALL
2035Java_SQLite_FunctionContext_set_1result__Ljava_lang_String_2(JNIEnv *env,
2036							     jobject obj,
2037							     jstring ret)
2038{
2039    hfunc *f = getfunc(env, obj);
2040
2041    if (f && f->sf) {
2042#if HAVE_BOTH_SQLITE
2043	if (!f->is3) {
2044	    transstr retstr;
2045	    jthrowable exc;
2046
2047	    trans2iso(env, f->h->haveutf, f->h->enc, ret, &retstr);
2048	    exc = (*env)->ExceptionOccurred(env);
2049	    if (exc) {
2050	        (*env)->DeleteLocalRef(env, exc);
2051		return;
2052	    }
2053	    sqlite_set_result_string((sqlite_func *) f->sf,
2054				     retstr.result, -1);
2055	    transfree(&retstr);
2056	} else if (ret) {
2057	    jsize len = (*env)->GetStringLength(env, ret) * sizeof (jchar);
2058	    const jchar *str = (*env)->GetStringChars(env, ret, 0);
2059
2060	    sqlite3_result_text16((sqlite3_context *) f->sf, str, len,
2061				  SQLITE_TRANSIENT);
2062	    (*env)->ReleaseStringChars(env, ret, str);
2063	} else {
2064	    sqlite3_result_null((sqlite3_context *) f->sf);
2065	}
2066#else
2067#if HAVE_SQLITE2
2068	transstr retstr;
2069	jthrowable exc;
2070
2071	trans2iso(env, f->h->haveutf, f->h->enc, ret, &retstr);
2072	exc = (*env)->ExceptionOccurred(env);
2073	if (exc) {
2074	    (*env)->DeleteLocalRef(env, exc);
2075	    return;
2076	}
2077	sqlite_set_result_string((sqlite_func *) f->sf, retstr.result, -1);
2078	transfree(&retstr);
2079#endif
2080#if HAVE_SQLITE3
2081	if (ret) {
2082	    jsize len = (*env)->GetStringLength(env, ret) * sizeof (jchar);
2083	    const jchar *str = (*env)->GetStringChars(env, ret, 0);
2084
2085	    sqlite3_result_text16((sqlite3_context *) f->sf, str, len,
2086				  SQLITE_TRANSIENT);
2087	    (*env)->ReleaseStringChars(env, ret, str);
2088	} else {
2089	    sqlite3_result_null((sqlite3_context *) f->sf);
2090	}
2091#endif
2092#endif
2093    }
2094}
2095
2096JNIEXPORT void JNICALL
2097Java_SQLite_FunctionContext_set_1result___3B(JNIEnv *env, jobject obj,
2098					     jbyteArray b)
2099{
2100#if HAVE_SQLITE3
2101    hfunc *f = getfunc(env, obj);
2102
2103    if (f && f->sf) {
2104#if HAVE_BOTH_SQLITE
2105	if (!f->is3) {
2106	    /* silently ignored */
2107	    return;
2108	}
2109#endif
2110	if (b) {
2111	    jsize len;
2112	    jbyte *data;
2113
2114	    len = (*env)->GetArrayLength(env, b);
2115	    data = (*env)->GetByteArrayElements(env, b, 0);
2116	    sqlite3_result_blob((sqlite3_context *) f->sf,
2117				data, len, SQLITE_TRANSIENT);
2118	    (*env)->ReleaseByteArrayElements(env, b, data, 0);
2119	} else {
2120	    sqlite3_result_null((sqlite3_context *) f->sf);
2121	}
2122    }
2123#endif
2124}
2125
2126JNIEXPORT void JNICALL
2127Java_SQLite_FunctionContext_set_1result_1zeroblob(JNIEnv *env, jobject obj,
2128						  jint n)
2129{
2130#if HAVE_SQLITE3 && HAVE_SQLITE3_RESULT_ZEROBLOB
2131    hfunc *f = getfunc(env, obj);
2132
2133    if (f && f->sf) {
2134#if HAVE_BOTH_SQLITE
2135	if (!f->is3) {
2136	    /* silently ignored */
2137	    return;
2138	}
2139#endif
2140	sqlite3_result_zeroblob((sqlite3_context *) f->sf, n);
2141    }
2142#endif
2143}
2144
2145JNIEXPORT jstring JNICALL
2146Java_SQLite_Database_error_1string(JNIEnv *env, jclass c, jint err)
2147{
2148#if HAVE_SQLITE2
2149    return (*env)->NewStringUTF(env, sqlite_error_string((int) err));
2150#else
2151    return (*env)->NewStringUTF(env, "unkown error");
2152#endif
2153}
2154
2155JNIEXPORT jstring JNICALL
2156Java_SQLite_Database__1errmsg(JNIEnv *env, jobject obj)
2157{
2158#if HAVE_SQLITE3
2159    handle *h = gethandle(env, obj);
2160
2161    if (h && h->sqlite) {
2162#if HAVE_BOTH_SQLITE
2163	if (!h->is3) {
2164	    return 0;
2165	}
2166#endif
2167	return (*env)->NewStringUTF(env,
2168				    sqlite3_errmsg((sqlite3 *) h->sqlite));
2169    }
2170#endif
2171    return 0;
2172}
2173
2174JNIEXPORT void JNICALL
2175Java_SQLite_Database__1set_1encoding(JNIEnv *env, jobject obj, jstring enc)
2176{
2177    handle *h = gethandle(env, obj);
2178
2179    if (h && !h->haveutf) {
2180#if HAVE_BOTH_SQLITE
2181	if (!h->is3) {
2182	    delglobrefp(env, &h->enc);
2183	    h->enc = enc;
2184	    globrefset(env, enc, &h->enc);
2185	}
2186#else
2187#if HAVE_SQLITE2
2188	delglobrefp(env, &h->enc);
2189	h->enc = enc;
2190	globrefset(env, enc, &h->enc);
2191#endif
2192#endif
2193    }
2194}
2195
2196#if HAVE_SQLITE_SET_AUTHORIZER
2197static int
2198doauth(void *arg, int what, const char *arg1, const char *arg2,
2199       const char *arg3, const char *arg4)
2200{
2201    handle *h = (handle *) arg;
2202    JNIEnv *env = h->env;
2203
2204    if (env && h->ai) {
2205	jthrowable exc;
2206	jclass cls = (*env)->GetObjectClass(env, h->ai);
2207	jmethodID mid;
2208	jint i = what;
2209
2210	mid = (*env)->GetMethodID(env, cls, "authorize",
2211				  "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I");
2212	if (mid) {
2213	    jstring s1 = 0, s2 = 0, s3 = 0, s4 = 0;
2214	    transstr tr;
2215
2216	    if (arg1) {
2217		trans2utf(env, h->haveutf, h->enc, arg1, &tr);
2218		s1 = tr.jstr;
2219	    }
2220	    exc = (*env)->ExceptionOccurred(env);
2221	    if (exc) {
2222		(*env)->DeleteLocalRef(env, exc);
2223		return SQLITE_DENY;
2224	    }
2225	    if (arg2) {
2226		trans2utf(env, h->haveutf, h->enc, arg2, &tr);
2227		s2 = tr.jstr;
2228	    }
2229	    if (arg3) {
2230		trans2utf(env, h->haveutf, h->enc, arg3, &tr);
2231		s3 = tr.jstr;
2232	    }
2233	    if (arg4) {
2234		trans2utf(env, h->haveutf, h->enc, arg4, &tr);
2235		s4 = tr.jstr;
2236	    }
2237	    exc = (*env)->ExceptionOccurred(env);
2238	    if (exc) {
2239		(*env)->DeleteLocalRef(env, exc);
2240		return SQLITE_DENY;
2241	    }
2242	    i = (*env)->CallIntMethod(env, h->ai, mid, i, s1, s2, s3, s4);
2243	    exc = (*env)->ExceptionOccurred(env);
2244	    if (exc) {
2245		(*env)->DeleteLocalRef(env, exc);
2246		return SQLITE_DENY;
2247	    }
2248	    (*env)->DeleteLocalRef(env, s4);
2249	    (*env)->DeleteLocalRef(env, s3);
2250	    (*env)->DeleteLocalRef(env, s2);
2251	    (*env)->DeleteLocalRef(env, s1);
2252	    if (i != SQLITE_OK && i != SQLITE_IGNORE) {
2253		i = SQLITE_DENY;
2254	    }
2255	    return (int) i;
2256	}
2257    }
2258    return SQLITE_DENY;
2259}
2260#endif
2261
2262JNIEXPORT void JNICALL
2263Java_SQLite_Database__1set_1authorizer(JNIEnv *env, jobject obj, jobject auth)
2264{
2265    handle *h = gethandle(env, obj);
2266
2267    if (h && h->sqlite) {
2268	delglobrefp(env, &h->ai);
2269	globrefset(env, auth, &h->ai);
2270#if HAVE_SQLITE_SET_AUTHORIZER
2271	h->env = env;
2272#if HAVE_BOTH_SQLITE
2273	if (h->is3) {
2274	    sqlite3_set_authorizer((sqlite3 *) h->sqlite,
2275				   h->ai ? doauth : 0, h);
2276	} else {
2277	    sqlite_set_authorizer((sqlite *) h->sqlite,
2278				  h->ai ? doauth : 0, h);
2279	}
2280#else
2281#if HAVE_SQLITE2
2282	sqlite_set_authorizer((sqlite *) h->sqlite, h->ai ? doauth : 0, h);
2283#endif
2284#if HAVE_SQLITE3
2285	sqlite3_set_authorizer((sqlite3 *) h->sqlite, h->ai ? doauth : 0, h);
2286#endif
2287#endif
2288#endif
2289	return;
2290    }
2291    throwclosed(env);
2292}
2293
2294#if HAVE_SQLITE_TRACE
2295static void
2296dotrace(void *arg, const char *msg)
2297{
2298    handle *h = (handle *) arg;
2299    JNIEnv *env = h->env;
2300
2301    if (env && h->tr && msg) {
2302	jthrowable exc;
2303	jclass cls = (*env)->GetObjectClass(env, h->tr);
2304	jmethodID mid;
2305
2306	mid = (*env)->GetMethodID(env, cls, "trace", "(Ljava/lang/String;)V");
2307	if (mid) {
2308	    transstr tr;
2309
2310	    trans2utf(env, h->haveutf, h->enc, msg, &tr);
2311	    exc = (*env)->ExceptionOccurred(env);
2312	    if (exc) {
2313		(*env)->DeleteLocalRef(env, exc);
2314		(*env)->ExceptionClear(env);
2315		return;
2316	    }
2317	    (*env)->CallVoidMethod(env, h->tr, mid, tr.jstr);
2318	    (*env)->ExceptionClear(env);
2319	    (*env)->DeleteLocalRef(env, tr.jstr);
2320	    return;
2321	}
2322    }
2323    return;
2324}
2325#endif
2326
2327JNIEXPORT void JNICALL
2328Java_SQLite_Database__1trace(JNIEnv *env, jobject obj, jobject tr)
2329{
2330    handle *h = gethandle(env, obj);
2331
2332    if (h && h->sqlite) {
2333	delglobrefp(env, &h->tr);
2334	globrefset(env, tr, &h->tr);
2335#if HAVE_BOTH_SQLITE
2336	if (h->is3) {
2337	    sqlite3_trace((sqlite3 *) h->sqlite, h->tr ? dotrace : 0, h);
2338	} else {
2339#if HAVE_SQLITE_TRACE
2340	    sqlite_trace((sqlite *) h->sqlite, h->tr ? dotrace : 0, h);
2341#endif
2342	}
2343#else
2344#if HAVE_SQLITE2
2345#if HAVE_SQLITE_TRACE
2346	sqlite_trace((sqlite *) h->sqlite, h->tr ? dotrace : 0, h);
2347#endif
2348#endif
2349#if HAVE_SQLITE3
2350	sqlite3_trace((sqlite3 *) h->sqlite, h->tr ? dotrace : 0, h);
2351#endif
2352#endif
2353	return;
2354    }
2355    throwclosed(env);
2356}
2357
2358#if HAVE_SQLITE_COMPILE
2359static void
2360dovmfinal(JNIEnv *env, jobject obj, int final)
2361{
2362    hvm *v = gethvm(env, obj);
2363
2364    if (v) {
2365	if (v->h) {
2366	    handle *h = v->h;
2367	    hvm *vv, **vvp;
2368
2369	    vvp = &h->vms;
2370	    vv = *vvp;
2371	    while (vv) {
2372		if (vv == v) {
2373		    *vvp = vv->next;
2374		    break;
2375		}
2376		vvp = &vv->next;
2377		vv = *vvp;
2378	    }
2379	}
2380	if (v->vm) {
2381#if HAVE_BOTH_SQLITE
2382	    if (v->is3) {
2383		sqlite3_finalize((sqlite3_stmt *) v->vm);
2384	    } else {
2385		sqlite_finalize((sqlite_vm *) v->vm, 0);
2386	    }
2387#else
2388#if HAVE_SQLITE2
2389	    sqlite_finalize((sqlite_vm *) v->vm, 0);
2390#endif
2391#if HAVE_SQLITE3
2392	    sqlite3_finalize((sqlite3_stmt *) v->vm);
2393#endif
2394#endif
2395	    v->vm = 0;
2396	}
2397	free(v);
2398	(*env)->SetLongField(env, obj, F_SQLite_Vm_handle, 0);
2399	return;
2400    }
2401    if (!final) {
2402	throwex(env, "vm already closed");
2403    }
2404}
2405#endif
2406
2407#if HAVE_SQLITE3
2408static void
2409dostmtfinal(JNIEnv *env, jobject obj)
2410{
2411    hvm *v = gethstmt(env, obj);
2412
2413    if (v) {
2414	if (v->h) {
2415	    handle *h = v->h;
2416	    hvm *vv, **vvp;
2417
2418	    vvp = &h->vms;
2419	    vv = *vvp;
2420	    while (vv) {
2421		if (vv == v) {
2422		    *vvp = vv->next;
2423		    break;
2424		}
2425		vvp = &vv->next;
2426		vv = *vvp;
2427	    }
2428	}
2429	if (v->vm) {
2430	    sqlite3_finalize((sqlite3_stmt *) v->vm);
2431	}
2432	v->vm = 0;
2433	free(v);
2434	(*env)->SetLongField(env, obj, F_SQLite_Stmt_handle, 0);
2435    }
2436}
2437#endif
2438
2439#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
2440static void
2441doblobfinal(JNIEnv *env, jobject obj)
2442{
2443    hbl *bl = gethbl(env, obj);
2444
2445    if (bl) {
2446	if (bl->h) {
2447	    handle *h = bl->h;
2448	    hbl *blc, **blp;
2449
2450	    blp = &h->blobs;
2451	    blc = *blp;
2452	    while (blc) {
2453		if (blc == bl) {
2454		    *blp = blc->next;
2455		    break;
2456		}
2457		blp = &blc->next;
2458		blc = *blp;
2459	    }
2460	}
2461	if (bl->blob) {
2462	    sqlite3_blob_close(bl->blob);
2463	}
2464	bl->blob = 0;
2465	free(bl);
2466	(*env)->SetLongField(env, obj, F_SQLite_Blob_handle, 0);
2467	(*env)->SetIntField(env, obj, F_SQLite_Blob_size, 0);
2468    }
2469}
2470#endif
2471
2472JNIEXPORT void JNICALL
2473Java_SQLite_Vm_stop(JNIEnv *env, jobject obj)
2474{
2475#if HAVE_SQLITE_COMPILE
2476    dovmfinal(env, obj, 0);
2477#else
2478    throwex(env, "unsupported");
2479#endif
2480}
2481
2482JNIEXPORT void JNICALL
2483Java_SQLite_Vm_finalize(JNIEnv *env, jobject obj)
2484{
2485#if HAVE_SQLITE_COMPILE
2486    dovmfinal(env, obj, 1);
2487#endif
2488}
2489
2490#if HAVE_SQLITE_COMPILE
2491#if HAVE_SQLITE3
2492static void
2493free_tab(void *mem)
2494{
2495    char **p = (char **) mem;
2496    int i, n;
2497
2498    if (!p) {
2499	return;
2500    }
2501    p -= 1;
2502    mem = (void *) p;
2503    n = ((int *) p)[0];
2504    p += n * 2 + 2 + 1;
2505    for (i = 0; i < n; i++) {
2506	if (p[i]) {
2507	    free(p[i]);
2508	}
2509    }
2510    free(mem);
2511}
2512#endif
2513#endif
2514
2515JNIEXPORT jboolean JNICALL
2516Java_SQLite_Vm_step(JNIEnv *env, jobject obj, jobject cb)
2517{
2518#if HAVE_SQLITE_COMPILE
2519    hvm *v = gethvm(env, obj);
2520
2521    if (v && v->vm && v->h) {
2522	jthrowable exc;
2523	int ret, ncol = 0;
2524#if HAVE_SQLITE3
2525	freemem *freeproc = 0;
2526	const char **blob = 0;
2527#endif
2528	const char **data = 0, **cols = 0;
2529
2530	v->h->env = env;
2531#if HAVE_BOTH_SQLITE
2532	if (v->is3) {
2533	    ret = sqlite3_step((sqlite3_stmt *) v->vm);
2534	    if (ret == SQLITE_ROW) {
2535		ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
2536		if (ncol > 0) {
2537		    data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
2538		    if (data) {
2539			data[0] = (const char *) ncol;
2540			++data;
2541			cols = data + ncol + 1;
2542			blob = cols + ncol + 1;
2543			freeproc = free_tab;
2544		    } else {
2545			ret = SQLITE_NOMEM;
2546		    }
2547		}
2548		if (ret != SQLITE_NOMEM) {
2549		    int i;
2550
2551		    for (i = 0; i < ncol; i++) {
2552			cols[i] =
2553			    sqlite3_column_name((sqlite3_stmt *) v->vm, i);
2554			if (sqlite3_column_type((sqlite3_stmt *) v->vm, i)
2555			    == SQLITE_BLOB) {
2556			    unsigned char *src = (unsigned char *)
2557				sqlite3_column_blob((sqlite3_stmt *) v->vm, i);
2558			    int n =
2559				sqlite3_column_bytes((sqlite3_stmt *) v->vm,
2560						     i);
2561
2562			    if (src) {
2563				data[i] = malloc(n * 2 + 4);
2564				if (data[i]) {
2565				    int k;
2566				    char *p = (char *) data[i];
2567
2568				    blob[i] = data[i];
2569				    *p++ = 'X';
2570				    *p++ = '\'';
2571				    for (k = 0; k < n; k++) {
2572					*p++ = xdigits[src[k] >> 4];
2573					*p++ = xdigits[src[k] & 0x0F];
2574				    }
2575				    *p++ = '\'';
2576				    *p++ = '\0';
2577				}
2578			    }
2579			} else {
2580			    data[i] = (const char *)
2581				sqlite3_column_text((sqlite3_stmt *) v->vm, i);
2582			}
2583		    }
2584		}
2585	    }
2586	} else {
2587	    ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols);
2588	}
2589#else
2590#if HAVE_SQLITE2
2591	ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols);
2592#endif
2593#if HAVE_SQLITE3
2594	ret = sqlite3_step((sqlite3_stmt *) v->vm);
2595	if (ret == SQLITE_ROW) {
2596	    ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
2597	    if (ncol > 0) {
2598		data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
2599		if (data) {
2600		    data[0] = (const char *) ncol;
2601		    ++data;
2602		    cols = data + ncol + 1;
2603		    blob = cols + ncol + 1;
2604		    freeproc = free_tab;
2605		} else {
2606		    ret = SQLITE_NOMEM;
2607		}
2608	    }
2609	    if (ret != SQLITE_NOMEM) {
2610		int i;
2611
2612		for (i = 0; i < ncol; i++) {
2613		    cols[i] = sqlite3_column_name((sqlite3_stmt *) v->vm, i);
2614		    if (sqlite3_column_type((sqlite3_stmt *) v->vm, i)
2615			== SQLITE_BLOB) {
2616			unsigned char *src = (unsigned char *)
2617			    sqlite3_column_blob((sqlite3_stmt *) v->vm, i);
2618			int n =
2619			    sqlite3_column_bytes((sqlite3_stmt *) v->vm, i);
2620
2621			if (src) {
2622			    data[i] = malloc(n * 2 + 4);
2623			    if (data[i]) {
2624				int k;
2625				char *p = (char *) data[i];
2626
2627				blob[i] = data[i];
2628				*p++ = 'X';
2629				*p++ = '\'';
2630				for (k = 0; k < n; k++) {
2631				    *p++ = xdigits[src[k] >> 4];
2632				    *p++ = xdigits[src[k] & 0x0F];
2633				}
2634				*p++ = '\'';
2635				*p++ = '\0';
2636			    }
2637			}
2638		    } else {
2639			data[i] = (char *)
2640			    sqlite3_column_text((sqlite3_stmt *) v->vm, i);
2641		    }
2642		}
2643	    }
2644	}
2645#endif
2646#endif
2647	if (ret == SQLITE_ROW) {
2648	    v->hh.cb = cb;
2649	    v->hh.env = env;
2650#if HAVE_BOTH_SQLITE
2651	    if (v->is3) {
2652		v->hh.stmt = (sqlite3_stmt *) v->vm;
2653	    }
2654#else
2655#if HAVE_SQLITE3
2656	    v->hh.stmt = (sqlite3_stmt *) v->vm;
2657#endif
2658#endif
2659	    callback((void *) &v->hh, ncol, (char **) data, (char **) cols);
2660#if HAVE_SQLITE3
2661	    if (data && freeproc) {
2662		freeproc((void *) data);
2663	    }
2664#endif
2665	    exc = (*env)->ExceptionOccurred(env);
2666	    if (exc) {
2667		(*env)->DeleteLocalRef(env, exc);
2668		goto dofin;
2669	    }
2670	    return JNI_TRUE;
2671	} else if (ret == SQLITE_DONE) {
2672dofin:
2673#if HAVE_BOTH_SQLITE
2674	    if (v->is3) {
2675		sqlite3_finalize((sqlite3_stmt *) v->vm);
2676	    } else {
2677		sqlite_finalize((sqlite_vm *) v->vm, 0);
2678	    }
2679#else
2680#if HAVE_SQLITE2
2681	    sqlite_finalize((sqlite_vm *) v->vm, 0);
2682#endif
2683#if HAVE_SQLITE3
2684	    sqlite3_finalize((sqlite3_stmt *) v->vm);
2685#endif
2686#endif
2687	    v->vm = 0;
2688	    return JNI_FALSE;
2689	}
2690#if HAVE_BOTH_SQLITE
2691	if (v->is3) {
2692	    sqlite3_finalize((sqlite3_stmt *) v->vm);
2693	} else {
2694	    sqlite_finalize((sqlite_vm *) v->vm, 0);
2695	}
2696#else
2697#if HAVE_SQLITE2
2698	sqlite_finalize((sqlite_vm *) v->vm, 0);
2699#endif
2700#if HAVE_SQLITE3
2701	sqlite3_finalize((sqlite3_stmt *) v->vm);
2702#endif
2703#endif
2704	setvmerr(env, obj, ret);
2705	v->vm = 0;
2706	throwex(env, "error in step");
2707	return JNI_FALSE;
2708    }
2709    throwex(env, "vm already closed");
2710#else
2711    throwex(env, "unsupported");
2712#endif
2713    return JNI_FALSE;
2714}
2715
2716JNIEXPORT jboolean JNICALL
2717Java_SQLite_Vm_compile(JNIEnv *env, jobject obj)
2718{
2719#if HAVE_SQLITE_COMPILE
2720    hvm *v = gethvm(env, obj);
2721    void *svm = 0;
2722    char *err = 0;
2723    const char *tail;
2724    int ret;
2725
2726    if (v && v->vm) {
2727#if HAVE_BOTH_SQLITE
2728	if (v->is3) {
2729	    sqlite3_finalize((sqlite3_stmt *) v->vm);
2730	} else {
2731	    sqlite_finalize((sqlite_vm *) v->vm, 0);
2732	}
2733#else
2734#if HAVE_SQLITE2
2735	sqlite_finalize((sqlite_vm *) v->vm, 0);
2736#endif
2737#if HAVE_SQLITE3
2738	sqlite3_finalize((sqlite3_stmt *) v->vm);
2739#endif
2740#endif
2741	v->vm = 0;
2742    }
2743    if (v && v->h && v->h->sqlite) {
2744	if (!v->tail) {
2745	    return JNI_FALSE;
2746	}
2747	v->h->env = env;
2748#if HAVE_BOTH_SQLITE
2749	if (v->is3) {
2750#if HAVE_SQLITE3_PREPARE_V2
2751	    ret = sqlite3_prepare_v2((sqlite3 *) v->h->sqlite, v->tail, -1,
2752				     (sqlite3_stmt **) &svm, &tail);
2753#else
2754	    ret = sqlite3_prepare((sqlite3 *) v->h->sqlite, v->tail, -1,
2755				  (sqlite3_stmt **) &svm, &tail);
2756#endif
2757	    if (ret != SQLITE_OK) {
2758		if (svm) {
2759		    sqlite3_finalize((sqlite3_stmt *) svm);
2760		    svm = 0;
2761		}
2762	    }
2763	} else {
2764	    ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail,
2765				 &tail, (sqlite_vm **) &svm, &err);
2766	    if (ret != SQLITE_OK) {
2767		if (svm) {
2768		    sqlite_finalize((sqlite_vm *) svm, 0);
2769		    svm = 0;
2770		}
2771	    }
2772	}
2773#else
2774#if HAVE_SQLITE2
2775	ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail,
2776			     &tail, (sqlite_vm **) &svm, &err);
2777	if (ret != SQLITE_OK) {
2778	    if (svm) {
2779		sqlite_finalize((sqlite_vm *) svm, 0);
2780		svm = 0;
2781	    }
2782	}
2783#endif
2784#if HAVE_SQLITE3
2785#if HAVE_SQLITE3_PREPARE_V2
2786	ret = sqlite3_prepare_v2((sqlite3 *) v->h->sqlite,
2787				 v->tail, -1, (sqlite3_stmt **) &svm, &tail);
2788#else
2789	ret = sqlite3_prepare((sqlite3 *) v->h->sqlite,
2790			      v->tail, -1, (sqlite3_stmt **) &svm, &tail);
2791#endif
2792	if (ret != SQLITE_OK) {
2793	    if (svm) {
2794		sqlite3_finalize((sqlite3_stmt *) svm);
2795		svm = 0;
2796	    }
2797	}
2798#endif
2799#endif
2800	if (ret != SQLITE_OK) {
2801	    setvmerr(env, obj, ret);
2802	    v->tail = 0;
2803	    throwex(env, err ? err : "error in compile/prepare");
2804#if HAVE_SQLITE2
2805	    if (err) {
2806		sqlite_freemem(err);
2807	    }
2808#endif
2809	    return JNI_FALSE;
2810	}
2811#if HAVE_SQLITE2
2812	if (err) {
2813	    sqlite_freemem(err);
2814	}
2815#endif
2816	if (!svm) {
2817	    v->tail = 0;
2818	    return JNI_FALSE;
2819	}
2820	v->vm = svm;
2821	v->tail = (char *) tail;
2822	v->hh.row1 = 1;
2823	return JNI_TRUE;
2824    }
2825    throwex(env, "vm already closed");
2826#else
2827    throwex(env, "unsupported");
2828#endif
2829    return JNI_FALSE;
2830}
2831
2832JNIEXPORT void JNICALL
2833Java_SQLite_Database_vm_1compile(JNIEnv *env, jobject obj, jstring sql,
2834				 jobject vm)
2835{
2836#if HAVE_SQLITE_COMPILE
2837    handle *h = gethandle(env, obj);
2838    void *svm = 0;
2839    hvm *v;
2840    char *err = 0;
2841    const char *tail;
2842    transstr tr;
2843    jvalue vv;
2844    int ret;
2845    jthrowable exc;
2846
2847    if (!h) {
2848	throwclosed(env);
2849	return;
2850    }
2851    if (!vm) {
2852	throwex(env, "null vm");
2853	return;
2854    }
2855    if (!sql) {
2856	throwex(env, "null sql");
2857	return;
2858    }
2859    trans2iso(env, h->haveutf, h->enc, sql, &tr);
2860    exc = (*env)->ExceptionOccurred(env);
2861    if (exc) {
2862	(*env)->DeleteLocalRef(env, exc);
2863	return;
2864    }
2865    h->env = env;
2866#if HAVE_BOTH_SQLITE
2867    if (h->is3) {
2868#if HAVE_SQLITE3_PREPARE_V2
2869	ret = sqlite3_prepare_v2((sqlite3 *) h->sqlite, tr.result, -1,
2870				 (sqlite3_stmt **) &svm, &tail);
2871#else
2872	ret = sqlite3_prepare((sqlite3 *) h->sqlite, tr.result, -1,
2873			      (sqlite3_stmt **) &svm, &tail);
2874#endif
2875	if (ret != SQLITE_OK) {
2876	    if (svm) {
2877		sqlite3_finalize((sqlite3_stmt *) svm);
2878		svm = 0;
2879	    }
2880	}
2881    } else {
2882	ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail,
2883			     (sqlite_vm **) &svm, &err);
2884	if (ret != SQLITE_OK) {
2885	    if (svm) {
2886		sqlite_finalize((sqlite_vm *) svm, 0);
2887	    }
2888	}
2889    }
2890#else
2891#if HAVE_SQLITE2
2892    ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail,
2893			 (sqlite_vm **) &svm, &err);
2894    if (ret != SQLITE_OK) {
2895	if (svm) {
2896	    sqlite_finalize((sqlite_vm *) svm, 0);
2897	    svm = 0;
2898	}
2899    }
2900#endif
2901#if HAVE_SQLITE3
2902#if HAVE_SQLITE3_PREPARE_V2
2903    ret = sqlite3_prepare_v2((sqlite3 *) h->sqlite, tr.result, -1,
2904			     (sqlite3_stmt **) &svm, &tail);
2905#else
2906    ret = sqlite3_prepare((sqlite3 *) h->sqlite, tr.result, -1,
2907			  (sqlite3_stmt **) &svm, &tail);
2908#endif
2909    if (ret != SQLITE_OK) {
2910	if (svm) {
2911	    sqlite3_finalize((sqlite3_stmt *) svm);
2912	    svm = 0;
2913	}
2914    }
2915#endif
2916#endif
2917    if (ret != SQLITE_OK) {
2918	transfree(&tr);
2919	setvmerr(env, vm, ret);
2920	throwex(env, err ? err : "error in prepare/compile");
2921#if HAVE_SQLITE2
2922	if (err) {
2923	    sqlite_freemem(err);
2924	}
2925#endif
2926	return;
2927    }
2928#if HAVE_SQLITE2
2929    if (err) {
2930	sqlite_freemem(err);
2931    }
2932#endif
2933    if (!svm) {
2934	transfree(&tr);
2935	return;
2936    }
2937    v = malloc(sizeof (hvm) + strlen(tail) + 1);
2938    if (!v) {
2939	transfree(&tr);
2940#if HAVE_BOTH_SQLITE
2941	if (h->is3) {
2942	    sqlite3_finalize((sqlite3_stmt *) svm);
2943	} else {
2944	    sqlite_finalize((sqlite_vm *) svm, 0);
2945	}
2946#else
2947#if HAVE_SQLITE2
2948	sqlite_finalize((sqlite_vm *) svm, 0);
2949#endif
2950#if HAVE_SQLITE3
2951	sqlite3_finalize((sqlite3_stmt *) svm);
2952#endif
2953#endif
2954	throwoom(env, "unable to get SQLite handle");
2955	return;
2956    }
2957    v->next = h->vms;
2958    h->vms = v;
2959    v->vm = svm;
2960    v->h = h;
2961    v->tail = (char *) (v + 1);
2962#if HAVE_BOTH_SQLITE
2963    v->is3 = v->hh.is3 = h->is3;
2964#endif
2965    strcpy(v->tail, tail);
2966    v->hh.sqlite = 0;
2967    v->hh.haveutf = h->haveutf;
2968    v->hh.ver = h->ver;
2969    v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
2970    v->hh.row1 = 1;
2971    v->hh.enc = h->enc;
2972    v->hh.funcs = 0;
2973    v->hh.vms = 0;
2974    v->hh.env = 0;
2975    vv.j = 0;
2976    vv.l = (jobject) v;
2977    (*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j);
2978#else
2979    throwex(env, "unsupported");
2980#endif
2981}
2982
2983JNIEXPORT void JNICALL
2984Java_SQLite_Database_vm_1compile_1args(JNIEnv *env,
2985				       jobject obj, jstring sql,
2986				       jobject vm, jobjectArray args)
2987{
2988#if HAVE_SQLITE_COMPILE
2989#if HAVE_SQLITE3
2990    handle *h = gethandle(env, obj);
2991#endif
2992
2993#if HAVE_BOTH_SQLITE
2994    if (h && !h->is3) {
2995	throwex(env, "unsupported");
2996	return;
2997    }
2998#else
2999#if HAVE_SQLITE2
3000    throwex(env, "unsupported");
3001#endif
3002#endif
3003#if HAVE_SQLITE3
3004    if (!h || !h->sqlite) {
3005	throwclosed(env);
3006	return;
3007    }
3008    if (!vm) {
3009	throwex(env, "null vm");
3010	return;
3011    }
3012    if (!sql) {
3013	throwex(env, "null sql");
3014	return;
3015    } else {
3016	void *svm = 0;
3017	hvm *v;
3018	jvalue vv;
3019	jthrowable exc;
3020	int rc = SQLITE_ERROR, nargs, i;
3021	char *p;
3022	const char *str = (*env)->GetStringUTFChars(env, sql, NULL);
3023	const char *tail;
3024	transstr sqlstr;
3025	struct args {
3026	    char *arg;
3027	    jobject obj;
3028	    transstr trans;
3029	} *argv = 0;
3030	char **cargv = 0;
3031
3032	p = (char *) str;
3033	nargs = 0;
3034	while (*p) {
3035	    if (*p == '%') {
3036		++p;
3037		if (*p == 'q' || *p == 'Q' || *p == 's') {
3038		    nargs++;
3039		    if (nargs > MAX_PARAMS) {
3040			(*env)->ReleaseStringUTFChars(env, sql, str);
3041			throwex(env, "too much SQL parameters");
3042			return;
3043		    }
3044		} else if (*p != '%') {
3045		    (*env)->ReleaseStringUTFChars(env, sql, str);
3046		    throwex(env, "bad % specification in query");
3047		    return;
3048		}
3049	    }
3050	    ++p;
3051	}
3052	cargv = malloc((sizeof (*argv) + sizeof (char *)) * MAX_PARAMS);
3053	if (!cargv) {
3054	    (*env)->ReleaseStringUTFChars(env, sql, str);
3055	    throwoom(env, "unable to allocate arg vector");
3056	    return;
3057	}
3058	argv = (struct args *) (cargv + MAX_PARAMS);
3059	for (i = 0; i < MAX_PARAMS; i++) {
3060	    cargv[i] = 0;
3061	    argv[i].arg = 0;
3062	    argv[i].obj = 0;
3063	    argv[i].trans.result = argv[i].trans.tofree = 0;
3064	}
3065	exc = 0;
3066	for (i = 0; i < nargs; i++) {
3067	    jobject so = (*env)->GetObjectArrayElement(env, args, i);
3068
3069	    exc = (*env)->ExceptionOccurred(env);
3070	    if (exc) {
3071		(*env)->DeleteLocalRef(env, exc);
3072		break;
3073	    }
3074	    if (so) {
3075		argv[i].obj = so;
3076		argv[i].arg = cargv[i] =
3077		    trans2iso(env, 1, 0, argv[i].obj, &argv[i].trans);
3078	    }
3079	}
3080	if (exc) {
3081	    for (i = 0; i < nargs; i++) {
3082		if (argv[i].obj) {
3083		    transfree(&argv[i].trans);
3084		}
3085	    }
3086	    freep((char **) &cargv);
3087	    (*env)->ReleaseStringUTFChars(env, sql, str);
3088	    return;
3089	}
3090	h->row1 = 1;
3091	trans2iso(env, 1, 0, sql, &sqlstr);
3092	exc = (*env)->ExceptionOccurred(env);
3093	if (!exc) {
3094#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
3095	    char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
3096#else
3097	    char *s = sqlite3_mprintf(sqlstr.result,
3098				      cargv[0], cargv[1],
3099				      cargv[2], cargv[3],
3100				      cargv[4], cargv[5],
3101				      cargv[6], cargv[7],
3102				      cargv[8], cargv[9],
3103				      cargv[10], cargv[11],
3104				      cargv[12], cargv[13],
3105				      cargv[14], cargv[15],
3106				      cargv[16], cargv[17],
3107				      cargv[18], cargv[19],
3108				      cargv[20], cargv[21],
3109				      cargv[22], cargv[23],
3110				      cargv[24], cargv[25],
3111				      cargv[26], cargv[27],
3112				      cargv[28], cargv[29],
3113				      cargv[30], cargv[31]);
3114#endif
3115	    if (!s) {
3116		rc = SQLITE_NOMEM;
3117	    } else {
3118#if HAVE_SQLITE3_PREPARE_V2
3119		rc = sqlite3_prepare_v2((sqlite3 *) h->sqlite, s, -1,
3120					(sqlite3_stmt **) &svm, &tail);
3121#else
3122		rc = sqlite3_prepare((sqlite3 *) h->sqlite, s, -1,
3123				      (sqlite3_stmt **) &svm, &tail);
3124#endif
3125		if (rc != SQLITE_OK) {
3126		    if (svm) {
3127			sqlite3_finalize((sqlite3_stmt *) svm);
3128			svm = 0;
3129		    }
3130		}
3131	    }
3132	    if (rc != SQLITE_OK) {
3133		sqlite3_free(s);
3134		for (i = 0; i < nargs; i++) {
3135		    if (argv[i].obj) {
3136			transfree(&argv[i].trans);
3137		    }
3138		}
3139		freep((char **) &cargv);
3140		transfree(&sqlstr);
3141		(*env)->ReleaseStringUTFChars(env, sql, str);
3142		setvmerr(env, vm, rc);
3143		throwex(env, "error in prepare");
3144		return;
3145	    }
3146	    v = malloc(sizeof (hvm) + strlen(tail) + 1);
3147	    if (!v) {
3148		sqlite3_free(s);
3149		for (i = 0; i < nargs; i++) {
3150		    if (argv[i].obj) {
3151			transfree(&argv[i].trans);
3152		    }
3153		}
3154		freep((char **) &cargv);
3155		transfree(&sqlstr);
3156		(*env)->ReleaseStringUTFChars(env, sql, str);
3157		sqlite3_finalize((sqlite3_stmt *) svm);
3158		setvmerr(env, vm, SQLITE_NOMEM);
3159		throwoom(env, "unable to get SQLite handle");
3160		return;
3161	    }
3162	    v->next = h->vms;
3163	    h->vms = v;
3164	    v->vm = svm;
3165	    v->h = h;
3166	    v->tail = (char *) (v + 1);
3167#if HAVE_BOTH_SQLITE
3168	    v->is3 = v->hh.is3 = h->is3;
3169#endif
3170	    strcpy(v->tail, tail);
3171	    sqlite3_free(s);
3172	    v->hh.sqlite = 0;
3173	    v->hh.haveutf = h->haveutf;
3174	    v->hh.ver = h->ver;
3175	    v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
3176	    v->hh.row1 = 1;
3177	    v->hh.enc = h->enc;
3178	    v->hh.funcs = 0;
3179	    v->hh.vms = 0;
3180	    v->hh.env = 0;
3181	    vv.j = 0;
3182	    vv.l = (jobject) v;
3183	    (*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j);
3184	}
3185	for (i = 0; i < nargs; i++) {
3186	    if (argv[i].obj) {
3187		transfree(&argv[i].trans);
3188	    }
3189	}
3190	freep((char **) &cargv);
3191	transfree(&sqlstr);
3192	(*env)->ReleaseStringUTFChars(env, sql, str);
3193	if (exc) {
3194	    (*env)->DeleteLocalRef(env, exc);
3195	}
3196    }
3197#endif
3198#else
3199    throwex(env, "unsupported");
3200#endif
3201}
3202
3203JNIEXPORT void JNICALL
3204Java_SQLite_FunctionContext_internal_1init(JNIEnv *env, jclass cls)
3205{
3206    F_SQLite_FunctionContext_handle =
3207	(*env)->GetFieldID(env, cls, "handle", "J");
3208}
3209
3210JNIEXPORT void JNICALL
3211Java_SQLite_Database__1progress_1handler(JNIEnv *env, jobject obj, jint n,
3212					 jobject ph)
3213{
3214    handle *h = gethandle(env, obj);
3215
3216    if (h && h->sqlite) {
3217	/* CHECK THIS */
3218#if HAVE_SQLITE_PROGRESS_HANDLER
3219	delglobrefp(env, &h->ph);
3220#if HAVE_BOTH_SQLITE
3221	if (h->is3) {
3222	    if (ph) {
3223		globrefset(env, ph, &h->ph);
3224		sqlite3_progress_handler((sqlite3 *) h->sqlite,
3225					 n, progresshandler, h);
3226	    } else {
3227		sqlite3_progress_handler((sqlite3 *) h->sqlite,
3228					 0, 0, 0);
3229	    }
3230	} else {
3231	    if (ph) {
3232		globrefset(env, ph, &h->ph);
3233		sqlite_progress_handler((sqlite *) h->sqlite,
3234					n, progresshandler, h);
3235	    } else {
3236		sqlite_progress_handler((sqlite *) h->sqlite,
3237					0, 0, 0);
3238	    }
3239	}
3240#else
3241#if HAVE_SQLITE2
3242	if (ph) {
3243	    globrefset(env, ph, &h->ph);
3244	    sqlite_progress_handler((sqlite *) h->sqlite,
3245				    n, progresshandler, h);
3246	} else {
3247	    sqlite_progress_handler((sqlite *) h->sqlite,
3248				    0, 0, 0);
3249	}
3250#endif
3251#if HAVE_SQLITE3
3252	if (ph) {
3253	    globrefset(env, ph, &h->ph);
3254	    sqlite3_progress_handler((sqlite3 *) h->sqlite,
3255				     n, progresshandler, h);
3256	} else {
3257	    sqlite3_progress_handler((sqlite3 *) h->sqlite,
3258				     0, 0, 0);
3259	}
3260#endif
3261#endif
3262	return;
3263#else
3264	throwex(env, "unsupported");
3265	return;
3266#endif
3267    }
3268    throwclosed(env);
3269}
3270
3271JNIEXPORT jboolean JNICALL
3272Java_SQLite_Database_is3(JNIEnv *env, jobject obj)
3273{
3274#if HAVE_BOTH_SQLITE
3275    handle *h = gethandle(env, obj);
3276
3277    if (h) {
3278	return h->is3 ? JNI_TRUE : JNI_FALSE;
3279    }
3280    return JNI_FALSE;
3281#else
3282#if HAVE_SQLITE2
3283    return JNI_FALSE;
3284#endif
3285#if HAVE_SQLITE3
3286    return JNI_TRUE;
3287#endif
3288#endif
3289}
3290
3291JNIEXPORT jboolean JNICALL
3292Java_SQLite_Stmt_prepare(JNIEnv *env, jobject obj)
3293{
3294#if HAVE_SQLITE3
3295    hvm *v = gethstmt(env, obj);
3296    void *svm = 0;
3297    char *tail;
3298    int ret;
3299
3300    if (v && v->vm) {
3301	sqlite3_finalize((sqlite3_stmt *) v->vm);
3302	v->vm = 0;
3303    }
3304    if (v && v->h && v->h->sqlite) {
3305	if (!v->tail) {
3306	    return JNI_FALSE;
3307	}
3308	v->h->env = env;
3309#if HAVE_SQLITE3_PREPARE16_V2
3310	ret = sqlite3_prepare16_v2((sqlite3 *) v->h->sqlite,
3311				   v->tail, -1, (sqlite3_stmt **) &svm,
3312				   (const void **) &tail);
3313#else
3314	ret = sqlite3_prepare16((sqlite3 *) v->h->sqlite,
3315				v->tail, -1, (sqlite3_stmt **) &svm,
3316				(const void **) &tail);
3317#endif
3318	if (ret != SQLITE_OK) {
3319	    if (svm) {
3320		sqlite3_finalize((sqlite3_stmt *) svm);
3321		svm = 0;
3322	    }
3323	}
3324	if (ret != SQLITE_OK) {
3325	    const char *err = sqlite3_errmsg(v->h->sqlite);
3326
3327	    setstmterr(env, obj, ret);
3328	    v->tail = 0;
3329	    throwex(env, err ? err : "error in compile/prepare");
3330	    return JNI_FALSE;
3331	}
3332	if (!svm) {
3333	    v->tail = 0;
3334	    return JNI_FALSE;
3335	}
3336	v->vm = svm;
3337	v->tail = (char *) tail;
3338	v->hh.row1 = 1;
3339	return JNI_TRUE;
3340    }
3341    throwex(env, "stmt already closed");
3342#else
3343    throwex(env, "unsupported");
3344#endif
3345    return JNI_FALSE;
3346}
3347
3348JNIEXPORT void JNICALL
3349Java_SQLite_Database_stmt_1prepare(JNIEnv *env, jobject obj, jstring sql,
3350				   jobject stmt)
3351{
3352#if HAVE_SQLITE3
3353    handle *h = gethandle(env, obj);
3354    void *svm = 0;
3355    hvm *v;
3356    jvalue vv;
3357    jsize len16;
3358    const jchar *sql16, *tail = 0;
3359    int ret;
3360
3361    if (!h) {
3362	throwclosed(env);
3363	return;
3364    }
3365    if (!stmt) {
3366	throwex(env, "null stmt");
3367	return;
3368    }
3369    if (!sql) {
3370	throwex(env, "null sql");
3371	return;
3372    }
3373#ifdef HAVE_BOTH_SQLITE
3374    if (!h->is3) {
3375	throwex(env, "only on SQLite3 database");
3376	return;
3377    }
3378#endif
3379    len16 = (*env)->GetStringLength(env, sql) * sizeof (jchar);
3380    if (len16 < 1) {
3381        return;
3382    }
3383    h->env = env;
3384    sql16 = (*env)->GetStringChars(env, sql, 0);
3385#if HAVE_SQLITE3_PREPARE16_V2
3386    ret = sqlite3_prepare16_v2((sqlite3 *) h->sqlite, sql16, len16,
3387			       (sqlite3_stmt **) &svm, (const void **) &tail);
3388#else
3389    ret = sqlite3_prepare16((sqlite3 *) h->sqlite, sql16, len16,
3390			    (sqlite3_stmt **) &svm, (const void **) &tail);
3391#endif
3392    if (ret != SQLITE_OK) {
3393	if (svm) {
3394	    sqlite3_finalize((sqlite3_stmt *) svm);
3395	    svm = 0;
3396	}
3397    }
3398    if (ret != SQLITE_OK) {
3399	const char *err = sqlite3_errmsg(h->sqlite);
3400
3401        (*env)->ReleaseStringChars(env, sql, sql16);
3402	setstmterr(env, stmt, ret);
3403	throwex(env, err ? err : "error in prepare");
3404	return;
3405    }
3406    if (!svm) {
3407        (*env)->ReleaseStringChars(env, sql, sql16);
3408	return;
3409    }
3410    len16 = len16 + sizeof (jchar) - ((char *) tail - (char *) sql16);
3411    if (len16 < (jsize) sizeof (jchar)) {
3412        len16 = sizeof (jchar);
3413    }
3414    v = malloc(sizeof (hvm) + len16);
3415    if (!v) {
3416        (*env)->ReleaseStringChars(env, sql, sql16);
3417	sqlite3_finalize((sqlite3_stmt *) svm);
3418	throwoom(env, "unable to get SQLite handle");
3419	return;
3420    }
3421    v->next = h->vms;
3422    h->vms = v;
3423    v->vm = svm;
3424    v->h = h;
3425    v->tail = (char *) (v + 1);
3426#if HAVE_BOTH_SQLITE
3427    v->is3 = v->hh.is3 = 1;
3428#endif
3429    memcpy(v->tail, tail, len16);
3430    len16 /= sizeof (jchar);
3431    ((jchar *) v->tail)[len16 - 1] = 0;
3432    (*env)->ReleaseStringChars(env, sql, sql16);
3433    v->hh.sqlite = 0;
3434    v->hh.haveutf = h->haveutf;
3435    v->hh.ver = h->ver;
3436    v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
3437    v->hh.row1 = 1;
3438    v->hh.enc = h->enc;
3439    v->hh.funcs = 0;
3440    v->hh.vms = 0;
3441    v->hh.env = 0;
3442    vv.j = 0;
3443    vv.l = (jobject) v;
3444    (*env)->SetLongField(env, stmt, F_SQLite_Stmt_handle, vv.j);
3445#else
3446    throwex(env, "unsupported");
3447#endif
3448}
3449
3450JNIEXPORT jboolean JNICALL
3451Java_SQLite_Stmt_step(JNIEnv *env, jobject obj)
3452{
3453#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3454    hvm *v = gethstmt(env, obj);
3455
3456    if (v && v->vm && v->h) {
3457	int ret;
3458
3459	ret = sqlite3_step((sqlite3_stmt *) v->vm);
3460	if (ret == SQLITE_ROW) {
3461	    return JNI_TRUE;
3462	}
3463	if (ret != SQLITE_DONE) {
3464	    const char *err = sqlite3_errmsg(v->h->sqlite);
3465
3466	    setstmterr(env, obj, ret);
3467	    throwex(env, err ? err : "error in step");
3468	}
3469	return JNI_FALSE;
3470    }
3471    throwex(env, "stmt already closed");
3472#else
3473    throwex(env, "unsupported");
3474#endif
3475    return JNI_FALSE;
3476}
3477
3478JNIEXPORT void JNICALL
3479Java_SQLite_Stmt_close(JNIEnv *env, jobject obj)
3480{
3481#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3482    hvm *v = gethstmt(env, obj);
3483
3484    if (v && v->vm && v->h) {
3485	int ret;
3486
3487	ret = sqlite3_finalize((sqlite3_stmt *) v->vm);
3488	v->vm = 0;
3489	if (ret != SQLITE_OK) {
3490	    const char *err = sqlite3_errmsg(v->h->sqlite);
3491
3492	    setstmterr(env, obj, ret);
3493	    throwex(env, err ? err : "error in close");
3494	}
3495	return;
3496    }
3497    throwex(env, "stmt already closed");
3498#else
3499    throwex(env, "unsupported");
3500#endif
3501    return;
3502}
3503
3504JNIEXPORT void JNICALL
3505Java_SQLite_Stmt_reset(JNIEnv *env, jobject obj)
3506{
3507#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3508    hvm *v = gethstmt(env, obj);
3509
3510    if (v && v->vm && v->h) {
3511	sqlite3_reset((sqlite3_stmt *) v->vm);
3512    } else {
3513	throwex(env, "stmt already closed");
3514    }
3515#else
3516    throwex(env, "unsupported");
3517#endif
3518}
3519
3520JNIEXPORT void JNICALL
3521Java_SQLite_Stmt_clear_1bindings(JNIEnv *env, jobject obj)
3522{
3523#if HAVE_SQLITE3 && HAVE_SQLITE3_CLEAR_BINDINGS
3524    hvm *v = gethstmt(env, obj);
3525
3526    if (v && v->vm && v->h) {
3527	sqlite3_clear_bindings((sqlite3_stmt *) v->vm);
3528    } else {
3529	throwex(env, "stmt already closed");
3530    }
3531#else
3532    throwex(env, "unsupported");
3533#endif
3534}
3535
3536JNIEXPORT void JNICALL
3537Java_SQLite_Stmt_bind__II(JNIEnv *env, jobject obj, jint pos, jint val)
3538{
3539#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3540    hvm *v = gethstmt(env, obj);
3541
3542    if (v && v->vm && v->h) {
3543	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3544	int ret;
3545
3546	if (pos < 1 || pos > npar) {
3547	    throwex(env, "parameter position out of bounds");
3548	    return;
3549	}
3550	ret = sqlite3_bind_int((sqlite3_stmt *) v->vm, pos, val);
3551	if (ret != SQLITE_OK) {
3552	    setstmterr(env, obj, ret);
3553	    throwex(env, "bind failed");
3554	}
3555    } else {
3556        throwex(env, "stmt already closed");
3557    }
3558#else
3559    throwex(env, "unsupported");
3560#endif
3561}
3562
3563JNIEXPORT void JNICALL
3564Java_SQLite_Stmt_bind__IJ(JNIEnv *env, jobject obj, jint pos, jlong val)
3565{
3566#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3567    hvm *v = gethstmt(env, obj);
3568
3569    if (v && v->vm && v->h) {
3570	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3571	int ret;
3572
3573	if (pos < 1 || pos > npar) {
3574	    throwex(env, "parameter position out of bounds");
3575	    return;
3576	}
3577	ret = sqlite3_bind_int64((sqlite3_stmt *) v->vm, pos, val);
3578	if (ret != SQLITE_OK) {
3579	    setstmterr(env, obj, ret);
3580	    throwex(env, "bind failed");
3581	}
3582    } else {
3583        throwex(env, "stmt already closed");
3584    }
3585#else
3586    throwex(env, "unsupported");
3587#endif
3588}
3589
3590JNIEXPORT void JNICALL
3591Java_SQLite_Stmt_bind__ID(JNIEnv *env, jobject obj, jint pos, jdouble val)
3592{
3593#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3594    hvm *v = gethstmt(env, obj);
3595
3596    if (v && v->vm && v->h) {
3597	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3598	int ret;
3599
3600	if (pos < 1 || pos > npar) {
3601	    throwex(env, "parameter position out of bounds");
3602	    return;
3603	}
3604	ret = sqlite3_bind_double((sqlite3_stmt *) v->vm, pos, val);
3605	if (ret != SQLITE_OK) {
3606	    setstmterr(env, obj, ret);
3607	    throwex(env, "bind failed");
3608	}
3609    } else {
3610        throwex(env, "stmt already closed");
3611    }
3612#else
3613    throwex(env, "unsupported");
3614#endif
3615}
3616
3617JNIEXPORT void JNICALL
3618Java_SQLite_Stmt_bind__I_3B(JNIEnv *env, jobject obj, jint pos, jbyteArray val)
3619{
3620#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3621    hvm *v = gethstmt(env, obj);
3622
3623    if (v && v->vm && v->h) {
3624	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3625	int ret;
3626	jint len;
3627	char *data = 0;
3628
3629	if (pos < 1 || pos > npar) {
3630	    throwex(env, "parameter position out of bounds");
3631	    return;
3632	}
3633	if (val) {
3634	    len = (*env)->GetArrayLength(env, val);
3635	    if (len > 0) {
3636	        data = sqlite3_malloc(len);
3637		if (!data) {
3638		    throwoom(env, "unable to get blob parameter");
3639		    return;
3640		}
3641		(*env)->GetByteArrayRegion(env, val, 0, len, (jbyte *) data);
3642		ret = sqlite3_bind_blob((sqlite3_stmt *) v->vm,
3643					pos, data, len, sqlite3_free);
3644	    } else {
3645		ret = sqlite3_bind_blob((sqlite3_stmt *) v->vm,
3646					pos, "", 0, SQLITE_STATIC);
3647	    }
3648	} else {
3649	    ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
3650	}
3651	if (ret != SQLITE_OK) {
3652	    if (data) {
3653	        sqlite3_free(data);
3654	    }
3655	    setstmterr(env, obj, ret);
3656	    throwex(env, "bind failed");
3657	}
3658    } else {
3659        throwex(env, "stmt already closed");
3660    }
3661#else
3662    throwex(env, "unsupported");
3663#endif
3664}
3665
3666JNIEXPORT void JNICALL
3667Java_SQLite_Stmt_bind__ILjava_lang_String_2(JNIEnv *env, jobject obj,
3668					    jint pos, jstring val)
3669{
3670#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3671    hvm *v = gethstmt(env, obj);
3672
3673    if (v && v->vm && v->h) {
3674	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3675	int ret;
3676	jsize len;
3677	char *data = 0;
3678
3679	if (pos < 1 || pos > npar) {
3680	    throwex(env, "parameter position out of bounds");
3681	    return;
3682	}
3683	if (val) {
3684	    const jsize charCount = (*env)->GetStringLength(env, val);
3685	    len = charCount * sizeof(jchar);
3686	    if (len > 0) {
3687		data = sqlite3_malloc(len);
3688		if (!data) {
3689		    throwoom(env, "unable to get blob parameter");
3690		    return;
3691		}
3692
3693		(*env)->GetStringRegion(env, val, 0, charCount, (jchar*) data);
3694		ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm,
3695					  pos, data, len, sqlite3_free);
3696	    } else {
3697	        ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm, pos, "", 0,
3698					  SQLITE_STATIC);
3699	    }
3700	} else {
3701	    ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
3702	}
3703	if (ret != SQLITE_OK) {
3704	    if (data) {
3705	        sqlite3_free(data);
3706	    }
3707	    setstmterr(env, obj, ret);
3708	    throwex(env, "bind failed");
3709	}
3710    } else {
3711        throwex(env, "stmt already closed");
3712    }
3713#else
3714    throwex(env, "unsupported");
3715#endif
3716}
3717
3718JNIEXPORT void JNICALL
3719Java_SQLite_Stmt_bind__I(JNIEnv *env, jobject obj, jint pos)
3720{
3721#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3722    hvm *v = gethstmt(env, obj);
3723
3724    if (v && v->vm && v->h) {
3725	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3726	int ret;
3727
3728	if (pos < 1 || pos > npar) {
3729	    throwex(env, "parameter position out of bounds");
3730	    return;
3731	}
3732	ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
3733	if (ret != SQLITE_OK) {
3734	    setstmterr(env, obj, ret);
3735	    throwex(env, "bind failed");
3736	}
3737    } else {
3738        throwex(env, "stmt already closed");
3739    }
3740#else
3741    throwex(env, "unsupported");
3742#endif
3743}
3744
3745JNIEXPORT void JNICALL
3746Java_SQLite_Stmt_bind_1zeroblob(JNIEnv *env, jobject obj, jint pos, jint len)
3747{
3748#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_ZEROBLOB
3749    hvm *v = gethstmt(env, obj);
3750
3751    if (v && v->vm && v->h) {
3752	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3753	int ret;
3754
3755	if (pos < 1 || pos > npar) {
3756	    throwex(env, "parameter position out of bounds");
3757	    return;
3758	}
3759	ret = sqlite3_bind_zeroblob((sqlite3_stmt *) v->vm, pos, len);
3760	if (ret != SQLITE_OK) {
3761	    setstmterr(env, obj, ret);
3762	    throwex(env, "bind failed");
3763	}
3764    } else {
3765        throwex(env, "stmt already closed");
3766    }
3767#else
3768    throwex(env, "unsupported");
3769#endif
3770}
3771
3772JNIEXPORT jint JNICALL
3773Java_SQLite_Stmt_bind_1parameter_1count(JNIEnv *env, jobject obj)
3774{
3775#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3776    hvm *v = gethstmt(env, obj);
3777
3778    if (v && v->vm && v->h) {
3779	return sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3780    }
3781    throwex(env, "stmt already closed");
3782#else
3783    throwex(env, "unsupported");
3784#endif
3785    return 0;
3786}
3787
3788JNIEXPORT jstring JNICALL
3789Java_SQLite_Stmt_bind_1parameter_1name(JNIEnv *env, jobject obj, jint pos)
3790{
3791#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_PARAMETER_NAME
3792    hvm *v = gethstmt(env, obj);
3793
3794    if (v && v->vm && v->h) {
3795	int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
3796	const char *name;
3797
3798	if (pos < 1 || pos > npar) {
3799	    throwex(env, "parameter position out of bounds");
3800	    return 0;
3801	}
3802	name = sqlite3_bind_parameter_name((sqlite3_stmt *) v->vm, pos);
3803	if (name) {
3804	    return (*env)->NewStringUTF(env, name);
3805	}
3806    } else {
3807        throwex(env, "stmt already closed");
3808    }
3809#else
3810    throwex(env, "unsupported");
3811#endif
3812    return 0;
3813}
3814
3815JNIEXPORT jint JNICALL
3816Java_SQLite_Stmt_bind_1parameter_1index(JNIEnv *env, jobject obj,
3817					jstring name)
3818{
3819#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_PARAMETER_INDEX
3820    hvm *v = gethstmt(env, obj);
3821
3822    if (v && v->vm && v->h) {
3823        int pos;
3824	const char *n;
3825	transstr namestr;
3826	jthrowable exc;
3827
3828	n = trans2iso(env, 1, 0, name, &namestr);
3829	exc = (*env)->ExceptionOccurred(env);
3830	if (exc) {
3831	    (*env)->DeleteLocalRef(env, exc);
3832	    return -1;
3833	}
3834        pos = sqlite3_bind_parameter_index((sqlite3_stmt *) v->vm, n);
3835	transfree(&namestr);
3836	return pos;
3837    } else {
3838        throwex(env, "stmt already closed");
3839    }
3840#else
3841    throwex(env, "unsupported");
3842#endif
3843    return -1;
3844}
3845
3846JNIEXPORT jint JNICALL
3847Java_SQLite_Stmt_column_1int(JNIEnv *env, jobject obj, jint col)
3848{
3849#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3850    hvm *v = gethstmt(env, obj);
3851
3852    if (v && v->vm && v->h) {
3853	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
3854
3855	if (col < 0 || col >= ncol) {
3856	    throwex(env, "column out of bounds");
3857	    return 0;
3858	}
3859	return sqlite3_column_int((sqlite3_stmt *) v->vm, col);
3860    }
3861    throwex(env, "stmt already closed");
3862#else
3863    throwex(env, "unsupported");
3864#endif
3865    return 0;
3866}
3867
3868JNIEXPORT jlong JNICALL
3869Java_SQLite_Stmt_column_1long(JNIEnv *env, jobject obj, jint col)
3870{
3871#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3872    hvm *v = gethstmt(env, obj);
3873
3874    if (v && v->vm && v->h) {
3875	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
3876
3877	if (col < 0 || col >= ncol) {
3878	    throwex(env, "column out of bounds");
3879	    return 0;
3880	}
3881	return sqlite3_column_int64((sqlite3_stmt *) v->vm, col);
3882    }
3883    throwex(env, "stmt already closed");
3884#else
3885    throwex(env, "unsupported");
3886#endif
3887    return 0;
3888}
3889
3890JNIEXPORT jdouble JNICALL
3891Java_SQLite_Stmt_column_1double(JNIEnv *env, jobject obj, jint col)
3892{
3893#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3894    hvm *v = gethstmt(env, obj);
3895
3896    if (v && v->vm && v->h) {
3897	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
3898
3899	if (col < 0 || col >= ncol) {
3900	    throwex(env, "column out of bounds");
3901	    return 0;
3902	}
3903	return sqlite3_column_double((sqlite3_stmt *) v->vm, col);
3904    }
3905    throwex(env, "stmt already closed");
3906#else
3907    throwex(env, "unsupported");
3908#endif
3909    return 0;
3910}
3911
3912JNIEXPORT jbyteArray JNICALL
3913Java_SQLite_Stmt_column_1bytes(JNIEnv *env, jobject obj, jint col)
3914{
3915#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3916    hvm *v = gethstmt(env, obj);
3917
3918    if (v && v->vm && v->h) {
3919	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
3920	int nbytes;
3921	const jbyte *data;
3922	jbyteArray b = 0;
3923
3924	if (col < 0 || col >= ncol) {
3925	    throwex(env, "column out of bounds");
3926	    return 0;
3927	}
3928	data = sqlite3_column_blob((sqlite3_stmt *) v->vm, col);
3929	if (data) {
3930	    nbytes = sqlite3_column_bytes((sqlite3_stmt *) v->vm, col);
3931	} else {
3932	    return 0;
3933	}
3934	b = (*env)->NewByteArray(env, nbytes);
3935	if (!b) {
3936	    throwoom(env, "unable to get blob column data");
3937	    return 0;
3938	}
3939	(*env)->SetByteArrayRegion(env, b, 0, nbytes, data);
3940	return b;
3941    }
3942    throwex(env, "stmt already closed");
3943#else
3944    throwex(env, "unsupported");
3945#endif
3946    return 0;
3947}
3948
3949JNIEXPORT jstring JNICALL
3950Java_SQLite_Stmt_column_1string(JNIEnv *env, jobject obj, jint col)
3951{
3952#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3953    hvm *v = gethstmt(env, obj);
3954
3955    if (v && v->vm && v->h) {
3956	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
3957	int nbytes;
3958	const jchar *data;
3959	jstring b = 0;
3960
3961	if (col < 0 || col >= ncol) {
3962	    throwex(env, "column out of bounds");
3963	    return 0;
3964	}
3965	data = sqlite3_column_text16((sqlite3_stmt *) v->vm, col);
3966	if (data) {
3967	    nbytes = sqlite3_column_bytes16((sqlite3_stmt *) v->vm, col);
3968	} else {
3969	    return 0;
3970	}
3971	nbytes /= sizeof (jchar);
3972	b = (*env)->NewString(env, data, nbytes);
3973	if (!b) {
3974	    throwoom(env, "unable to get string column data");
3975	    return 0;
3976	}
3977	return b;
3978    }
3979    throwex(env, "stmt already closed");
3980#else
3981    throwex(env, "unsupported");
3982#endif
3983    return 0;
3984}
3985
3986JNIEXPORT jint JNICALL
3987Java_SQLite_Stmt_column_1type(JNIEnv *env, jobject obj, jint col)
3988{
3989#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
3990    hvm *v = gethstmt(env, obj);
3991
3992    if (v && v->vm && v->h) {
3993	int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
3994
3995	if (col < 0 || col >= ncol) {
3996	    throwex(env, "column out of bounds");
3997	    return 0;
3998	}
3999	return sqlite3_column_type((sqlite3_stmt *) v->vm, col);
4000    }
4001    throwex(env, "stmt already closed");
4002#else
4003    throwex(env, "unsupported");
4004#endif
4005    return 0;
4006}
4007
4008JNIEXPORT jint JNICALL
4009Java_SQLite_Stmt_column_1count(JNIEnv *env, jobject obj)
4010{
4011#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
4012    hvm *v = gethstmt(env, obj);
4013
4014    if (v && v->vm && v->h) {
4015	return sqlite3_column_count((sqlite3_stmt *) v->vm);
4016    }
4017    throwex(env, "stmt already closed");
4018#else
4019    throwex(env, "unsupported");
4020#endif
4021    return 0;
4022}
4023
4024JNIEXPORT jstring JNICALL
4025Java_SQLite_Stmt_column_1table_1name(JNIEnv *env, jobject obj, jint col)
4026{
4027#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_TABLE_NAME16
4028    hvm *v = gethstmt(env, obj);
4029
4030    if (v && v->vm && v->h) {
4031	int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
4032        const jchar *str;
4033
4034	if (col < 0 || col >= ncol) {
4035	    throwex(env, "column out of bounds");
4036	    return 0;
4037	}
4038	str = sqlite3_column_table_name16((sqlite3_stmt *) v->vm, col);
4039	if (str) {
4040	    return (*env)->NewString(env, str, jstrlen(str));
4041	}
4042	return 0;
4043    }
4044    throwex(env, "stmt already closed");
4045#else
4046    throwex(env, "unsupported");
4047#endif
4048    return 0;
4049}
4050
4051JNIEXPORT jstring JNICALL
4052Java_SQLite_Stmt_column_1database_1name(JNIEnv *env, jobject obj, jint col)
4053{
4054#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_DATABASE_NAME16
4055    hvm *v = gethstmt(env, obj);
4056
4057    if (v && v->vm && v->h) {
4058	int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
4059        const jchar *str;
4060
4061	if (col < 0 || col >= ncol) {
4062	    throwex(env, "column out of bounds");
4063	    return 0;
4064	}
4065	str = sqlite3_column_database_name16((sqlite3_stmt *) v->vm, col);
4066	if (str) {
4067	    return (*env)->NewString(env, str, jstrlen(str));
4068	}
4069	return 0;
4070    }
4071    throwex(env, "stmt already closed");
4072#else
4073    throwex(env, "unsupported");
4074#endif
4075    return 0;
4076}
4077
4078JNIEXPORT jstring JNICALL
4079Java_SQLite_Stmt_column_1decltype(JNIEnv *env, jobject obj, jint col)
4080{
4081#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
4082    hvm *v = gethstmt(env, obj);
4083
4084    if (v && v->vm && v->h) {
4085	int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
4086        const jchar *str;
4087
4088	if (col < 0 || col >= ncol) {
4089	    throwex(env, "column out of bounds");
4090	    return 0;
4091	}
4092	str = sqlite3_column_decltype16((sqlite3_stmt *) v->vm, col);
4093	if (str) {
4094	    return (*env)->NewString(env, str, jstrlen(str));
4095	}
4096	return 0;
4097    }
4098    throwex(env, "stmt already closed");
4099#else
4100    throwex(env, "unsupported");
4101#endif
4102    return 0;
4103}
4104
4105JNIEXPORT jstring JNICALL
4106Java_SQLite_Stmt_column_1origin_1name(JNIEnv *env, jobject obj, jint col)
4107{
4108#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_ORIGIN_NAME16
4109    hvm *v = gethstmt(env, obj);
4110
4111    if (v && v->vm && v->h) {
4112	int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
4113        const jchar *str;
4114
4115	if (col < 0 || col >= ncol) {
4116	    throwex(env, "column out of bounds");
4117	    return 0;
4118	}
4119	str = sqlite3_column_origin_name16((sqlite3_stmt *) v->vm, col);
4120	if (str) {
4121	    return (*env)->NewString(env, str, jstrlen(str));
4122	}
4123	return 0;
4124    }
4125    throwex(env, "stmt already closed");
4126#else
4127    throwex(env, "unsupported");
4128#endif
4129    return 0;
4130}
4131
4132JNIEXPORT void JNICALL
4133Java_SQLite_Stmt_finalize(JNIEnv *env, jobject obj)
4134{
4135#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
4136    dostmtfinal(env, obj);
4137#endif
4138}
4139
4140JNIEXPORT void JNICALL
4141Java_SQLite_Database__1open_1blob(JNIEnv *env, jobject obj,
4142				  jstring dbname, jstring table,
4143				  jstring column, jlong row,
4144				  jboolean rw, jobject blobj)
4145{
4146#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
4147    handle *h = gethandle(env, obj);
4148    hbl *bl;
4149    jthrowable exc;
4150    transstr dbn, tbl, col;
4151    sqlite3_blob *blob;
4152    jvalue vv;
4153    int ret;
4154
4155    if (!blobj) {
4156	throwex(env, "null blob");
4157	return;
4158    }
4159    if (h && h->sqlite) {
4160        trans2iso(env, h->haveutf, h->enc, dbname, &dbn);
4161	exc = (*env)->ExceptionOccurred(env);
4162	if (exc) {
4163	    (*env)->DeleteLocalRef(env, exc);
4164	    return;
4165	}
4166        trans2iso(env, h->haveutf, h->enc, table, &tbl);
4167	exc = (*env)->ExceptionOccurred(env);
4168	if (exc) {
4169	    transfree(&dbn);
4170	    (*env)->DeleteLocalRef(env, exc);
4171	    return;
4172	}
4173        trans2iso(env, h->haveutf, h->enc, column, &col);
4174	exc = (*env)->ExceptionOccurred(env);
4175	if (exc) {
4176	    transfree(&tbl);
4177	    transfree(&dbn);
4178	    (*env)->DeleteLocalRef(env, exc);
4179	    return;
4180	}
4181	ret = sqlite3_blob_open(h->sqlite,
4182				dbn.result, tbl.result, col.result,
4183				row, rw, &blob);
4184	transfree(&col);
4185	transfree(&tbl);
4186	transfree(&dbn);
4187	if (ret != SQLITE_OK) {
4188	    const char *err = sqlite3_errmsg(h->sqlite);
4189
4190	    seterr(env, obj, ret);
4191	    throwex(env, err ? err : "error in blob open");
4192	    return;
4193	}
4194	bl = malloc(sizeof (hbl));
4195	if (!bl) {
4196	    sqlite3_blob_close(blob);
4197	    throwoom(env, "unable to get SQLite blob handle");
4198	    return;
4199	}
4200	bl->next = h->blobs;
4201	h->blobs = bl;
4202	bl->blob = blob;
4203	bl->h = h;
4204	vv.j = 0;
4205	vv.l = (jobject) bl;
4206	(*env)->SetLongField(env, blobj, F_SQLite_Blob_handle, vv.j);
4207	(*env)->SetIntField(env, blobj, F_SQLite_Blob_size,
4208			    sqlite3_blob_bytes(blob));
4209	return;
4210    }
4211    throwex(env, "not an open database");
4212#else
4213    throwex(env, "unsupported");
4214#endif
4215}
4216
4217JNIEXPORT jint JNICALL
4218Java_SQLite_Blob_write(JNIEnv *env , jobject obj, jbyteArray b, jint off,
4219		       jint pos, jint len)
4220{
4221#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
4222    hbl *bl = gethbl(env, obj);
4223
4224    if (bl && bl->h && bl->blob) {
4225        jbyte *buf;
4226	jthrowable exc;
4227	int ret;
4228
4229	if (len <= 0) {
4230	    return 0;
4231	}
4232	buf = malloc(len);
4233	if (!buf) {
4234	    throwoom(env, "out of buffer space for blob");
4235	    return 0;
4236	}
4237	(*env)->GetByteArrayRegion(env, b, off, len, buf);
4238	exc = (*env)->ExceptionOccurred(env);
4239	if (exc) {
4240	    free(buf);
4241	    return 0;
4242	}
4243	ret = sqlite3_blob_write(bl->blob, buf, len, pos);
4244	free(buf);
4245	if (ret != SQLITE_OK) {
4246	    throwioex(env, "blob write error");
4247	    return 0;
4248	}
4249	return len;
4250    }
4251    throwex(env, "blob already closed");
4252#else
4253    throwex(env, "unsupported");
4254#endif
4255    return 0;
4256}
4257
4258JNIEXPORT jint JNICALL
4259Java_SQLite_Blob_read(JNIEnv *env , jobject obj, jbyteArray b, jint off,
4260		      jint pos, jint len)
4261{
4262#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
4263    hbl *bl = gethbl(env, obj);
4264
4265    if (bl && bl->h && bl->blob) {
4266        jbyte *buf;
4267	jthrowable exc;
4268	int ret;
4269
4270	if (len <= 0) {
4271	    return 0;
4272	}
4273	buf = malloc(len);
4274	if (!buf) {
4275	    throwoom(env, "out of buffer space for blob");
4276	    return 0;
4277	}
4278	ret = sqlite3_blob_read(bl->blob, buf, len, pos);
4279	if (ret != SQLITE_OK) {
4280	    free(buf);
4281	    throwioex(env, "blob read error");
4282	    return 0;
4283	}
4284	(*env)->SetByteArrayRegion(env, b, off, len, buf);
4285	free(buf);
4286	exc = (*env)->ExceptionOccurred(env);
4287	if (exc) {
4288	    return 0;
4289	}
4290	return len;
4291    }
4292    throwex(env, "blob already closed");
4293#else
4294    throwex(env, "unsupported");
4295#endif
4296    return 0;
4297}
4298
4299JNIEXPORT void JNICALL
4300Java_SQLite_Blob_close(JNIEnv *env, jobject obj)
4301{
4302#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
4303    doblobfinal(env, obj);
4304#endif
4305}
4306
4307JNIEXPORT void JNICALL
4308Java_SQLite_Blob_finalize(JNIEnv *env, jobject obj)
4309{
4310#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
4311    doblobfinal(env, obj);
4312#endif
4313}
4314
4315JNIEXPORT void JNICALL
4316Java_SQLite_Stmt_internal_1init(JNIEnv *env, jclass cls)
4317{
4318    F_SQLite_Stmt_handle =
4319	(*env)->GetFieldID(env, cls, "handle", "J");
4320    F_SQLite_Stmt_error_code =
4321	(*env)->GetFieldID(env, cls, "error_code", "I");
4322}
4323
4324JNIEXPORT void JNICALL
4325Java_SQLite_Vm_internal_1init(JNIEnv *env, jclass cls)
4326{
4327    F_SQLite_Vm_handle =
4328	(*env)->GetFieldID(env, cls, "handle", "J");
4329    F_SQLite_Vm_error_code =
4330	(*env)->GetFieldID(env, cls, "error_code", "I");
4331}
4332
4333JNIEXPORT void JNICALL
4334Java_SQLite_Blob_internal_1init(JNIEnv *env, jclass cls)
4335{
4336    F_SQLite_Blob_handle =
4337	(*env)->GetFieldID(env, cls, "handle", "J");
4338    F_SQLite_Blob_size =
4339	(*env)->GetFieldID(env, cls, "size", "I");
4340}
4341
4342JNIEXPORT void JNICALL
4343Java_SQLite_Database_internal_1init(JNIEnv *env, jclass cls)
4344{
4345//#ifndef JNI_VERSION_1_2
4346    jclass jls = (*env)->FindClass(env, "java/lang/String");
4347
4348    C_java_lang_String = (*env)->NewGlobalRef(env, jls);
4349//#endif
4350    F_SQLite_Database_handle =
4351	(*env)->GetFieldID(env, cls, "handle", "J");
4352    F_SQLite_Database_error_code =
4353	(*env)->GetFieldID(env, cls, "error_code", "I");
4354    M_java_lang_String_getBytes =
4355	(*env)->GetMethodID(env, C_java_lang_String, "getBytes", "()[B");
4356    M_java_lang_String_getBytes2 =
4357	(*env)->GetMethodID(env, C_java_lang_String, "getBytes",
4358			    "(Ljava/lang/String;)[B");
4359    M_java_lang_String_initBytes =
4360	(*env)->GetMethodID(env, C_java_lang_String, "<init>", "([B)V");
4361    M_java_lang_String_initBytes2 =
4362	(*env)->GetMethodID(env, C_java_lang_String, "<init>",
4363			    "([BLjava/lang/String;)V");
4364}
4365
4366#ifdef JNI_VERSION_1_2
4367JNIEXPORT jint JNICALL
4368JNI_OnLoad(JavaVM *vm, void *reserved)
4369{
4370    JNIEnv *env;
4371    jclass cls;
4372
4373#ifndef _WIN32
4374#if HAVE_SQLITE2
4375    if (strcmp(sqlite_libencoding(), "UTF-8") != 0) {
4376	fprintf(stderr, "WARNING: using non-UTF SQLite2 engine\n");
4377    }
4378#endif
4379#endif
4380    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) {
4381	return JNI_ERR;
4382    }
4383    cls = (*env)->FindClass(env, "java/lang/String");
4384    if (!cls) {
4385	return JNI_ERR;
4386    }
4387    C_java_lang_String = (*env)->NewWeakGlobalRef(env, cls);
4388    return JNI_VERSION_1_2;
4389}
4390
4391JNIEXPORT void JNICALL
4392JNI_OnUnload(JavaVM *vm, void *reserved)
4393{
4394    JNIEnv *env;
4395
4396    if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) {
4397	return;
4398    }
4399    if (C_java_lang_String) {
4400	(*env)->DeleteWeakGlobalRef(env, C_java_lang_String);
4401	C_java_lang_String = 0;
4402    }
4403}
4404#endif
4405