Database.java revision 7a647e8547e57ca573541be55b3728ef7ce376fe
1package SQLite;
2
3/**
4 * Main class wrapping an SQLite database.
5 */
6
7public class Database {
8
9    /**
10     * Internal handle for the native SQLite API.
11     */
12
13    protected long handle = 0;
14
15    /**
16     * Internal last error code for exec() methods.
17     */
18
19    protected int error_code = 0;
20
21    /**
22     * Open an SQLite database file.
23     *
24     * @param filename the name of the database file
25     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
26     */
27
28    public void open(String filename, int mode) throws SQLite.Exception {
29	if ((mode & 0200) != 0) {
30	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
31		   SQLite.Constants.SQLITE_OPEN_CREATE;
32	} else if ((mode & 0400) != 0) {
33	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
34	}
35	synchronized(this) {
36	    try {
37		_open4(filename, mode, null, false);
38	    } catch (SQLite.Exception se) {
39		throw se;
40	    } catch (java.lang.OutOfMemoryError me) {
41		throw me;
42	    } catch (Throwable t) {
43		_open(filename, mode);
44	    }
45	}
46    }
47
48    /**
49     * Open an SQLite database file.
50     *
51     * @param filename the name of the database file
52     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
53     * @param vfs VFS name (for SQLite >= 3.5)
54     */
55
56    public void open(String filename, int mode, String vfs)
57	throws SQLite.Exception {
58	if ((mode & 0200) != 0) {
59	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
60		   SQLite.Constants.SQLITE_OPEN_CREATE;
61	} else if ((mode & 0400) != 0) {
62	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
63	}
64	synchronized(this) {
65	    try {
66		_open4(filename, mode, vfs, false);
67	    } catch (SQLite.Exception se) {
68		throw se;
69	    } catch (java.lang.OutOfMemoryError me) {
70		throw me;
71	    } catch (Throwable t) {
72		_open(filename, mode);
73	    }
74	}
75    }
76
77    /**
78     * Open an SQLite database file.
79     *
80     * @param filename the name of the database file
81     * @param mode open mode (e.g. SQLITE_OPEN_READONLY)
82     * @param vfs VFS name (for SQLite >= 3.5)
83     * @param ver2 flag to force version on create (false = SQLite3, true = SQLite2)
84     */
85
86    public void open(String filename, int mode, String vfs, boolean ver2)
87	throws SQLite.Exception {
88	if ((mode & 0200) != 0) {
89	    mode = SQLite.Constants.SQLITE_OPEN_READWRITE |
90		   SQLite.Constants.SQLITE_OPEN_CREATE;
91	} else if ((mode & 0400) != 0) {
92	    mode = SQLite.Constants.SQLITE_OPEN_READONLY;
93	}
94	synchronized(this) {
95	    try {
96		_open4(filename, mode, vfs, ver2);
97	    } catch (SQLite.Exception se) {
98		throw se;
99	    } catch (java.lang.OutOfMemoryError me) {
100		throw me;
101	    } catch (Throwable t) {
102		_open(filename, mode);
103	    }
104	}
105    }
106
107    /*
108     * For backward compatibility to older sqlite.jar, sqlite_jni
109     */
110
111    private native void _open(String filename, int mode)
112	throws SQLite.Exception;
113
114    /*
115     * Newer full interface
116     */
117
118    private native void _open4(String filename, int mode, String vfs,
119			       boolean ver2)
120	throws SQLite.Exception;
121
122    /**
123     * Open SQLite auxiliary database file for temporary
124     * tables.
125     *
126     * @param filename the name of the auxiliary file or null
127     */
128
129    public void open_aux_file(String filename) throws SQLite.Exception {
130	synchronized(this) {
131	    _open_aux_file(filename);
132	}
133    }
134
135    private native void _open_aux_file(String filename)
136	throws SQLite.Exception;
137
138    /**
139     * Destructor for object.
140     */
141
142    protected void finalize() {
143	synchronized(this) {
144	    _finalize();
145	}
146    }
147
148    private native void _finalize();
149
150    /**
151     * Close the underlying SQLite database file.
152     */
153
154    public void close()	throws SQLite.Exception {
155	synchronized(this) {
156	    _close();
157	}
158    }
159
160    private native void _close()
161	throws SQLite.Exception;
162
163    /**
164     * Execute an SQL statement and invoke callback methods
165     * for each row of the result set.<P>
166     *
167     * It the method fails, an SQLite.Exception is thrown and
168     * an error code is set, which later can be retrieved by
169     * the last_error() method.
170     *
171     * @param sql the SQL statement to be executed
172     * @param cb the object implementing the callback methods
173     */
174
175    public void exec(String sql, SQLite.Callback cb) throws SQLite.Exception {
176	synchronized(this) {
177	    _exec(sql, cb);
178	}
179    }
180
181    private native void _exec(String sql, SQLite.Callback cb)
182	throws SQLite.Exception;
183
184    /**
185     * Execute an SQL statement and invoke callback methods
186     * for each row of the result set. Each '%q' or %Q in the
187     * statement string is substituted by its corresponding
188     * element in the argument vector.
189     * <BR><BR>
190     * Example:<BR>
191     * <PRE>
192     *   String args[] = new String[1];
193     *   args[0] = "tab%";
194     *   db.exec("select * from sqlite_master where type like '%q'",
195     *           null, args);
196     * </PRE>
197     *
198     * It the method fails, an SQLite.Exception is thrown and
199     * an error code is set, which later can be retrieved by
200     * the last_error() method.
201     *
202     * @param sql the SQL statement to be executed
203     * @param cb the object implementing the callback methods
204     * @param args arguments for the SQL statement, '%q' substitution
205     */
206
207    public void exec(String sql, SQLite.Callback cb,
208		     String args[]) throws SQLite.Exception {
209	synchronized(this) {
210	    _exec(sql, cb, args);
211	}
212    }
213
214    private native void _exec(String sql, SQLite.Callback cb, String args[])
215	throws SQLite.Exception;
216
217    /**
218     * Return the row identifier of the last inserted
219     * row.
220     */
221
222    public long last_insert_rowid() {
223	synchronized(this) {
224	    return _last_insert_rowid();
225	}
226    }
227
228    private native long _last_insert_rowid();
229
230    /**
231     * Abort the current SQLite operation.
232     */
233
234    public void interrupt() {
235	synchronized(this) {
236	    _interrupt();
237	}
238    }
239
240    private native void _interrupt();
241
242    /**
243     * Return the number of changed rows for the last statement.
244     */
245
246    public long changes() {
247	synchronized(this) {
248	    return _changes();
249	}
250    }
251
252    private native long _changes();
253
254    /**
255     * Establish a busy callback method which gets called when
256     * an SQLite table is locked.
257     *
258     * @param bh the object implementing the busy callback method
259     */
260
261    public void busy_handler(SQLite.BusyHandler bh) {
262	synchronized(this) {
263	    _busy_handler(bh);
264	}
265    }
266
267    private native void _busy_handler(SQLite.BusyHandler bh);
268
269    /**
270     * Set the timeout for waiting for an SQLite table to become
271     * unlocked.
272     *
273     * @param ms number of millisecond to wait
274     */
275
276    public void busy_timeout(int ms) {
277	synchronized(this) {
278	    _busy_timeout(ms);
279	}
280    }
281
282    private native void _busy_timeout(int ms);
283
284    /**
285     * Convenience method to retrieve an entire result
286     * set into memory.
287     *
288     * @param sql the SQL statement to be executed
289     * @param maxrows the max. number of rows to retrieve
290     * @return result set
291     */
292
293    public TableResult get_table(String sql, int maxrows)
294	throws SQLite.Exception {
295	TableResult ret = new TableResult(maxrows);
296	if (!is3()) {
297	    try {
298		exec(sql, ret);
299	    } catch (SQLite.Exception e) {
300		if (maxrows <= 0 || !ret.atmaxrows) {
301		    throw e;
302		}
303	    }
304	} else {
305	    synchronized(this) {
306		/* only one statement !!! */
307		Vm vm = compile(sql);
308		set_last_error(vm.error_code);
309		if (ret.maxrows > 0) {
310		    while (ret.nrows < ret.maxrows && vm.step(ret)) {
311			set_last_error(vm.error_code);
312		    }
313		} else {
314		    while (vm.step(ret)) {
315			set_last_error(vm.error_code);
316		    }
317		}
318		vm.finalize();
319	    }
320	}
321	return ret;
322    }
323
324    /**
325     * Convenience method to retrieve an entire result
326     * set into memory.
327     *
328     * @param sql the SQL statement to be executed
329     * @return result set
330     */
331
332    public TableResult get_table(String sql) throws SQLite.Exception {
333	return get_table(sql, 0);
334    }
335
336    /**
337     * Convenience method to retrieve an entire result
338     * set into memory.
339     *
340     * @param sql the SQL statement to be executed
341     * @param maxrows the max. number of rows to retrieve
342     * @param args arguments for the SQL statement, '%q' substitution
343     * @return result set
344     */
345
346    public TableResult get_table(String sql, int maxrows, String args[])
347	throws SQLite.Exception {
348	TableResult ret = new TableResult(maxrows);
349	if (!is3()) {
350	    try {
351		exec(sql, ret, args);
352	    } catch (SQLite.Exception e) {
353		if (maxrows <= 0 || !ret.atmaxrows) {
354		    throw e;
355		}
356	    }
357	} else {
358	    synchronized(this) {
359		/* only one statement !!! */
360		Vm vm = compile(sql, args);
361		set_last_error(vm.error_code);
362		if (ret.maxrows > 0) {
363		    while (ret.nrows < ret.maxrows && vm.step(ret)) {
364			set_last_error(vm.error_code);
365		    }
366		} else {
367		    while (vm.step(ret)) {
368			set_last_error(vm.error_code);
369		    }
370		}
371		vm.finalize();
372	    }
373	}
374	return ret;
375    }
376
377    /**
378     * Convenience method to retrieve an entire result
379     * set into memory.
380     *
381     * @param sql the SQL statement to be executed
382     * @param args arguments for the SQL statement, '%q' substitution
383     * @return result set
384     */
385
386    public TableResult get_table(String sql, String args[])
387	throws SQLite.Exception {
388	return get_table(sql, 0, args);
389    }
390
391    /**
392     * Convenience method to retrieve an entire result
393     * set into memory.
394     *
395     * @param sql the SQL statement to be executed
396     * @param args arguments for the SQL statement, '%q' substitution
397     * @param tbl TableResult to receive result set
398     * @return result set
399     */
400
401    public void get_table(String sql, String args[], TableResult tbl)
402	throws SQLite.Exception {
403	tbl.clear();
404	if (!is3()) {
405	    try {
406		exec(sql, tbl, args);
407	    } catch (SQLite.Exception e) {
408		if (tbl.maxrows <= 0 || !tbl.atmaxrows) {
409		    throw e;
410		}
411	    }
412	} else {
413	    synchronized(this) {
414		/* only one statement !!! */
415		Vm vm = compile(sql, args);
416		if (tbl.maxrows > 0) {
417		    while (tbl.nrows < tbl.maxrows && vm.step(tbl)) {
418			set_last_error(vm.error_code);
419		    }
420		} else {
421		    while (vm.step(tbl)) {
422			set_last_error(vm.error_code);
423		    }
424		}
425		vm.finalize();
426	    }
427	}
428    }
429
430    /**
431     * See if an SQL statement is complete.
432     * Returns true if the input string comprises
433     * one or more complete SQL statements.
434     *
435     * @param sql the SQL statement to be checked
436     */
437
438    public synchronized static boolean complete(String sql) {
439	return _complete(sql);
440    }
441
442    private native static boolean _complete(String sql);
443
444    /**
445     * Return SQLite version number as string.
446     * Don't rely on this when both SQLite 2 and 3 are compiled
447     * into the native part. Use the class method in this case.
448     */
449
450    public native static String version();
451
452    /**
453     * Return SQLite version number as string.
454     * If the database is not open, <tt>unknown</tt> is returned.
455     */
456
457    public native String dbversion();
458
459    /**
460     * Create regular function.
461     *
462     * @param name the name of the new function
463     * @param nargs number of arguments to function
464     * @param f interface of function
465     */
466
467    public void create_function(String name, int nargs, Function f) {
468	synchronized(this) {
469	    _create_function(name, nargs, f);
470	}
471    }
472
473    private native void _create_function(String name, int nargs, Function f);
474
475    /**
476     * Create aggregate function.
477     *
478     * @param name the name of the new function
479     * @param nargs number of arguments to function
480     * @param f interface of function
481     */
482
483    public void create_aggregate(String name, int nargs, Function f) {
484	synchronized(this) {
485	    _create_aggregate(name, nargs, f);
486	}
487    }
488
489    private native void _create_aggregate(String name, int nargs, Function f);
490
491    /**
492     * Set function return type. Only available in SQLite 2.6.0 and
493     * above, otherwise a no-op.
494     *
495     * @param name the name of the function whose return type is to be set
496     * @param type return type code, e.g. SQLite.Constants.SQLITE_NUMERIC
497     */
498
499    public void function_type(String name, int type) {
500	synchronized(this) {
501	    _function_type(name, type);
502	}
503    }
504
505    private native void _function_type(String name, int type);
506
507    /**
508     * Return the code of the last error occured in
509     * any of the exec() methods. The value is valid
510     * after an Exception has been reported by one of
511     * these methods. See the <A HREF="Constants.html">Constants</A>
512     * class for possible values.
513     *
514     * @return SQLite error code
515     */
516
517    public int last_error() {
518	return error_code;
519    }
520
521    /**
522     * Internal: set error code.
523     * @param error_code new error code
524     */
525
526    protected void set_last_error(int error_code) {
527	this.error_code = error_code;
528    }
529
530    /**
531     * Return last error message of SQLite3 engine.
532     *
533     * @return error string or null
534     */
535
536    public String error_message() {
537	synchronized(this) {
538	    return _errmsg();
539	}
540    }
541
542    private native String _errmsg();
543
544    /**
545     * Return error string given SQLite error code (SQLite2).
546     *
547     * @param error_code the error code
548     * @return error string
549     */
550
551    public static native String error_string(int error_code);
552
553    /**
554     * Set character encoding.
555     * @param enc name of encoding
556     */
557
558    public void set_encoding(String enc) throws SQLite.Exception {
559	synchronized(this) {
560	    _set_encoding(enc);
561	}
562    }
563
564    private native void _set_encoding(String enc)
565	throws SQLite.Exception;
566
567    /**
568     * Set authorizer function. Only available in SQLite 2.7.6 and
569     * above, otherwise a no-op.
570     *
571     * @param auth the authorizer function
572     */
573
574    public void set_authorizer(Authorizer auth) {
575	synchronized(this) {
576	    _set_authorizer(auth);
577	}
578    }
579
580    private native void _set_authorizer(Authorizer auth);
581
582    /**
583     * Set trace function. Only available in SQLite 2.7.6 and above,
584     * otherwise a no-op.
585     *
586     * @param tr the trace function
587     */
588
589    public void trace(Trace tr) {
590	synchronized(this) {
591	    _trace(tr);
592	}
593    }
594
595    private native void _trace(Trace tr);
596
597    /**
598     * Compile and return SQLite VM for SQL statement. Only available
599     * in SQLite 2.8.0 and above, otherwise a no-op.
600     *
601     * @param sql SQL statement to be compiled
602     * @return a Vm object
603     */
604
605    public Vm compile(String sql) throws SQLite.Exception {
606	synchronized(this) {
607	    Vm vm = new Vm();
608	    vm_compile(sql, vm);
609	    return vm;
610	}
611    }
612
613    /**
614     * Compile and return SQLite VM for SQL statement. Only available
615     * in SQLite 3.0 and above, otherwise a no-op.
616     *
617     * @param sql SQL statement to be compiled
618     * @param args arguments for the SQL statement, '%q' substitution
619     * @return a Vm object
620     */
621
622    public Vm compile(String sql, String args[]) throws SQLite.Exception {
623	synchronized(this) {
624	    Vm vm = new Vm();
625	    vm_compile_args(sql, vm, args);
626	    return vm;
627	}
628    }
629
630    /**
631     * Prepare and return SQLite3 statement for SQL. Only available
632     * in SQLite 3.0 and above, otherwise a no-op.
633     *
634     * @param sql SQL statement to be prepared
635     * @return a Stmt object
636     */
637
638    public Stmt prepare(String sql) throws SQLite.Exception {
639	synchronized(this) {
640	    Stmt stmt = new Stmt();
641	    stmt_prepare(sql, stmt);
642	    return stmt;
643	}
644    }
645
646    /**
647     * Open an SQLite3 blob. Only available in SQLite 3.4.0 and above.
648     * @param db database name
649     * @param table table name
650     * @param column column name
651     * @param row row identifier
652     * @param rw if true, open for read-write, else read-only
653     * @return a Blob object
654     */
655
656    public Blob open_blob(String db, String table, String column,
657			  long row, boolean rw) throws SQLite.Exception {
658	synchronized(this) {
659	    Blob blob = new Blob();
660	    _open_blob(db, table, column, row, rw, blob);
661	    return blob;
662	}
663    }
664
665    /**
666     * Check type of open database.
667     * @return true if SQLite3 database
668     */
669
670    public native boolean is3();
671
672    /**
673     * Internal compile method.
674     * @param sql SQL statement
675     * @param vm Vm object
676     */
677
678    private native void vm_compile(String sql, Vm vm)
679	throws SQLite.Exception;
680
681    /**
682     * Internal compile method, SQLite 3.0 only.
683     * @param sql SQL statement
684     * @param args arguments for the SQL statement, '%q' substitution
685     * @param vm Vm object
686     */
687
688    private native void vm_compile_args(String sql, Vm vm, String args[])
689	throws SQLite.Exception;
690
691    /**
692     * Internal SQLite3 prepare method.
693     * @param sql SQL statement
694     * @param stmt Stmt object
695     */
696
697    private native void stmt_prepare(String sql, Stmt stmt)
698	throws SQLite.Exception;
699
700    /**
701     * Internal SQLite open blob method.
702     * @param db database name
703     * @param table table name
704     * @param column column name
705     * @param row row identifier
706     * @param rw if true, open for read-write, else read-only
707     * @param blob Blob object
708     */
709
710    private native void _open_blob(String db, String table, String column,
711				   long row, boolean rw, Blob blob)
712	throws SQLite.Exception;
713
714    /**
715     * Establish a progress callback method which gets called after
716     * N SQLite VM opcodes.
717     *
718     * @param n number of SQLite VM opcodes until callback is invoked
719     * @param p the object implementing the progress callback method
720     */
721
722    public void progress_handler(int n, SQLite.ProgressHandler p) {
723	synchronized(this) {
724	    _progress_handler(n, p);
725	}
726    }
727
728    private native void _progress_handler(int n, SQLite.ProgressHandler p);
729
730    /**
731     * Specify key for encrypted database. To be called
732     * right after open() on SQLite3 databases.
733     * Not available in public releases of SQLite.
734     *
735     * @param ekey the key as byte array
736     */
737
738    public void key(byte[] ekey) throws SQLite.Exception {
739	synchronized(this) {
740	    _key(ekey);
741	}
742    }
743
744    /**
745     * Specify key for encrypted database. To be called
746     * right after open() on SQLite3 databases.
747     * Not available in public releases of SQLite.
748     *
749     * @param skey the key as String
750     */
751
752    public void key(String skey) throws SQLite.Exception {
753	synchronized(this) {
754	    byte ekey[] = null;
755	    if (skey != null && skey.length() > 0) {
756		ekey = new byte[skey.length()];
757		for (int i = 0; i< skey.length(); i++) {
758		    char c = skey.charAt(i);
759		    ekey[i] = (byte) ((c & 0xff) ^ (c >> 8));
760		}
761	    }
762	    _key(ekey);
763	}
764    }
765
766    private native void _key(byte[] ekey);
767
768    /**
769     * Change the key of a encrypted database. The
770     * SQLite3 database must have been open()ed.
771     * Not available in public releases of SQLite.
772     *
773     * @param ekey the key as byte array
774     */
775
776    public void rekey(byte[] ekey) throws SQLite.Exception {
777	synchronized(this) {
778	    _rekey(ekey);
779	}
780    }
781
782    /**
783     * Change the key of a encrypted database. The
784     * SQLite3 database must have been open()ed.
785     * Not available in public releases of SQLite.
786     *
787     * @param skey the key as String
788     */
789
790    public void rekey(String skey) throws SQLite.Exception {
791	synchronized(this) {
792	    byte ekey[] = null;
793	    if (skey != null && skey.length() > 0) {
794		ekey = new byte[skey.length()];
795		for (int i = 0; i< skey.length(); i++) {
796		    char c = skey.charAt(i);
797		    ekey[i] = (byte) ((c & 0xff) ^ (c >> 8));
798		}
799	    }
800	    _rekey(ekey);
801	}
802    }
803
804    private native void _rekey(byte[] ekey);
805
806    /**
807     * Enable/disable shared cache mode (SQLite 3.x only).
808     *
809     * @param onoff boolean to enable or disable shared cache
810     * @return boolean when true, function supported/succeeded
811     */
812
813    protected static native boolean _enable_shared_cache(boolean onoff);
814
815    /**
816     * Internal native initializer.
817     */
818
819    private static native void internal_init();
820
821    /**
822     * Make long value from julian date for java.lang.Date
823     *
824     * @param d double value (julian date in SQLite3 format)
825     * @return long
826     */
827
828    public static long long_from_julian(double d) {
829	d -= 2440587.5;
830	d *= 86400000.0;
831	return (long) d;
832    }
833
834    /**
835     * Make long value from julian date for java.lang.Date
836     *
837     * @param s string (double value) (julian date in SQLite3 format)
838     * @return long
839     */
840
841    public static long long_from_julian(String s) throws SQLite.Exception {
842	try {
843	    double d = Double.valueOf(s).doubleValue();
844	    return long_from_julian(d);
845	} catch (java.lang.Exception ee) {
846	    throw new SQLite.Exception("not a julian date");
847	}
848    }
849
850    /**
851     * Make julian date value from java.lang.Date
852     *
853     * @param ms millisecond value of java.lang.Date
854     * @return double
855     */
856
857    public static double julian_from_long(long ms) {
858	double adj = (ms < 0) ? 0 : 0.5;
859	double d = (ms + adj) / 86400000.0 + 2440587.5;
860	return d;
861    }
862
863    /**
864     * Static initializer to load the native part.
865     */
866
867    static {
868	try {
869	    String path = System.getProperty("SQLite.library.path");
870	    if (path == null || path.length() == 0) {
871		System.loadLibrary("sqlite_jni");
872	    } else {
873		try {
874		    java.lang.reflect.Method mapLibraryName;
875		    Class param[] = new Class[1];
876		    param[0] = String.class;
877		    mapLibraryName = System.class.getMethod("mapLibraryName",
878							    param);
879		    Object args[] = new Object[1];
880		    args[0] = "sqlite_jni";
881		    String mapped = (String) mapLibraryName.invoke(null, args);
882		    System.load(path + java.io.File.separator + mapped);
883		} catch (Throwable t) {
884		    System.err.println("Unable to load sqlite_jni from" +
885				       "SQLite.library.path=" + path +
886				       ", trying system default: " + t);
887		    System.loadLibrary("sqlite_jni");
888		}
889	    }
890	} catch (Throwable t) {
891	    System.err.println("Unable to load sqlite_jni: " + t);
892	}
893	/*
894	 * Call native initializer functions now, since the
895	 * native part could have been linked statically, i.e.
896	 * the try/catch above would have failed in that case.
897	 */
898	try {
899	    internal_init();
900	    new FunctionContext();
901	} catch (java.lang.Exception e) {
902	}
903    }
904}
905
906