Home | History | Annotate | Download | only in SQLite
      1 package SQLite;
      2 
      3 /**
      4  * Main class wrapping an SQLite database.
      5  */
      6 
      7 public 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.parseDouble(s); // android-changed: performance
    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