mirror of
https://github.com/amalthea-mc/ShopChest.git
synced 2024-11-08 19:51:05 +00:00
Removed SQLite Library
This commit is contained in:
parent
246cd5d298
commit
1309591d4c
@ -1,106 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
package org.sqlite;
|
||||
|
||||
interface Codes
|
||||
{
|
||||
/** Successful result */
|
||||
public static final int SQLITE_OK = 0;
|
||||
|
||||
/** SQL error or missing database */
|
||||
public static final int SQLITE_ERROR = 1;
|
||||
|
||||
/** An internal logic error in SQLite */
|
||||
public static final int SQLITE_INTERNAL = 2;
|
||||
|
||||
/** Access permission denied */
|
||||
public static final int SQLITE_PERM = 3;
|
||||
|
||||
/** Callback routine requested an abort */
|
||||
public static final int SQLITE_ABORT = 4;
|
||||
|
||||
/** The database file is locked */
|
||||
public static final int SQLITE_BUSY = 5;
|
||||
|
||||
/** A table in the database is locked */
|
||||
public static final int SQLITE_LOCKED = 6;
|
||||
|
||||
/** A malloc() failed */
|
||||
public static final int SQLITE_NOMEM = 7;
|
||||
|
||||
/** Attempt to write a readonly database */
|
||||
public static final int SQLITE_READONLY = 8;
|
||||
|
||||
/** Operation terminated by sqlite_interrupt() */
|
||||
public static final int SQLITE_INTERRUPT = 9;
|
||||
|
||||
/** Some kind of disk I/O error occurred */
|
||||
public static final int SQLITE_IOERR = 10;
|
||||
|
||||
/** The database disk image is malformed */
|
||||
public static final int SQLITE_CORRUPT = 11;
|
||||
|
||||
/** (Internal Only) Table or record not found */
|
||||
public static final int SQLITE_NOTFOUND = 12;
|
||||
|
||||
/** Insertion failed because database is full */
|
||||
public static final int SQLITE_FULL = 13;
|
||||
|
||||
/** Unable to open the database file */
|
||||
public static final int SQLITE_CANTOPEN = 14;
|
||||
|
||||
/** Database lock protocol error */
|
||||
public static final int SQLITE_PROTOCOL = 15;
|
||||
|
||||
/** (Internal Only) Database table is empty */
|
||||
public static final int SQLITE_EMPTY = 16;
|
||||
|
||||
/** The database schema changed */
|
||||
public static final int SQLITE_SCHEMA = 17;
|
||||
|
||||
/** Too much data for one row of a table */
|
||||
public static final int SQLITE_TOOBIG = 18;
|
||||
|
||||
/** Abort due to constraint violation */
|
||||
public static final int SQLITE_CONSTRAINT = 19;
|
||||
|
||||
/** Data type mismatch */
|
||||
public static final int SQLITE_MISMATCH = 20;
|
||||
|
||||
/** Library used incorrectly */
|
||||
public static final int SQLITE_MISUSE = 21;
|
||||
|
||||
/** Uses OS features not supported on host */
|
||||
public static final int SQLITE_NOLFS = 22;
|
||||
|
||||
/** Authorization denied */
|
||||
public static final int SQLITE_AUTH = 23;
|
||||
|
||||
/** sqlite_step() has another row ready */
|
||||
public static final int SQLITE_ROW = 100;
|
||||
|
||||
/** sqlite_step() has finished executing */
|
||||
public static final int SQLITE_DONE = 101;
|
||||
|
||||
|
||||
// types returned by sqlite3_column_type()
|
||||
|
||||
public static final int SQLITE_INTEGER = 1;
|
||||
public static final int SQLITE_FLOAT = 2;
|
||||
public static final int SQLITE_TEXT = 3;
|
||||
public static final int SQLITE_BLOB = 4;
|
||||
public static final int SQLITE_NULL = 5;
|
||||
}
|
@ -1,440 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
package org.sqlite;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.net.URL;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.Connection;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Savepoint;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Struct;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
class Conn implements Connection
|
||||
{
|
||||
private final String url;
|
||||
private String fileName;
|
||||
private DB db = null;
|
||||
private MetaData meta = null;
|
||||
private boolean autoCommit = true;
|
||||
private int transactionIsolation = TRANSACTION_SERIALIZABLE;
|
||||
private int timeout = 0;
|
||||
|
||||
public Conn(String url, String fileName) throws SQLException {
|
||||
this(url, fileName, new Properties());
|
||||
}
|
||||
|
||||
public Conn(String url, String fileName, Properties prop) throws SQLException {
|
||||
this.url = url;
|
||||
this.fileName = fileName;
|
||||
|
||||
SQLiteConfig config = new SQLiteConfig(prop);
|
||||
open(config.getOpenModeFlags());
|
||||
|
||||
boolean enableSharedCache = config.isEnabledSharedCache();
|
||||
boolean enableLoadExtension = config.isEnabledLoadExtension();
|
||||
db.shared_cache(enableSharedCache);
|
||||
db.enable_load_extension(enableLoadExtension);
|
||||
|
||||
// set pragmas
|
||||
config.apply(this);
|
||||
}
|
||||
|
||||
private static final String RESOURCE_NAME_PREFIX = ":resource:";
|
||||
|
||||
private void open(int openModeFlags) throws SQLException {
|
||||
// check the path to the file exists
|
||||
if (!":memory:".equals(fileName)) {
|
||||
if (fileName.startsWith(RESOURCE_NAME_PREFIX)) {
|
||||
String resourceName = fileName.substring(RESOURCE_NAME_PREFIX.length());
|
||||
|
||||
// search the class path
|
||||
ClassLoader contextCL = Thread.currentThread().getContextClassLoader();
|
||||
URL resourceAddr = contextCL.getResource(resourceName);
|
||||
if (resourceAddr == null) {
|
||||
try {
|
||||
resourceAddr = new URL(resourceName);
|
||||
}
|
||||
catch (MalformedURLException e) {
|
||||
throw new SQLException(String.format("resource %s not found: %s", resourceName, e));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
fileName = extractResource(resourceAddr).getAbsolutePath();
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new SQLException(String.format("failed to load %s: %s", resourceName, e));
|
||||
}
|
||||
}
|
||||
else {
|
||||
File file = new File(fileName).getAbsoluteFile();
|
||||
File parent = file.getParentFile();
|
||||
if (parent != null && !parent.exists()) {
|
||||
for (File up = parent; up != null && !up.exists();) {
|
||||
parent = up;
|
||||
up = up.getParentFile();
|
||||
}
|
||||
throw new SQLException("path to '" + fileName + "': '" + parent + "' does not exist");
|
||||
}
|
||||
|
||||
// check write access if file does not exist
|
||||
try {
|
||||
// The extra check to exists() is necessary as createNewFile()
|
||||
// does not follow the JavaDoc when used on read-only shares.
|
||||
if (!file.exists() && file.createNewFile())
|
||||
file.delete();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new SQLException("opening db: '" + fileName + "': " + e.getMessage());
|
||||
}
|
||||
fileName = file.getAbsolutePath();
|
||||
}
|
||||
}
|
||||
|
||||
// tries to load native library first
|
||||
try {
|
||||
Class< ? > nativedb = Class.forName("org.sqlite.NativeDB");
|
||||
if (((Boolean) nativedb.getDeclaredMethod("load", (Class< ? >[]) null).invoke((Object) null,
|
||||
(Object[]) null)).booleanValue())
|
||||
db = (DB) nativedb.newInstance();
|
||||
|
||||
}
|
||||
catch (Exception e) {} // fall through to nested library
|
||||
|
||||
// load nested library (pure-java SQLite)
|
||||
if (db == null) {
|
||||
try {
|
||||
db = (DB) Class.forName("org.sqlite.NestedDB").newInstance();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new SQLException("no SQLite library found");
|
||||
}
|
||||
}
|
||||
|
||||
db.open(this, fileName, openModeFlags);
|
||||
setTimeout(3000);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param resourceAddr
|
||||
* @return extracted file name
|
||||
* @throws IOException
|
||||
*/
|
||||
private File extractResource(URL resourceAddr) throws IOException {
|
||||
if (resourceAddr.getProtocol().equals("file")) {
|
||||
try {
|
||||
return new File(resourceAddr.toURI());
|
||||
}
|
||||
catch (URISyntaxException e) {
|
||||
throw new IOException(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
|
||||
String dbFileName = String.format("sqlite-jdbc-tmp-%d.db", resourceAddr.hashCode());
|
||||
File dbFile = new File(tempFolder, dbFileName);
|
||||
|
||||
if (dbFile.exists()) {
|
||||
long resourceLastModified = resourceAddr.openConnection().getLastModified();
|
||||
long tmpFileLastModified = dbFile.lastModified();
|
||||
if (resourceLastModified < tmpFileLastModified) {
|
||||
return dbFile;
|
||||
}
|
||||
else {
|
||||
// remove the old DB file
|
||||
boolean deletionSucceeded = dbFile.delete();
|
||||
if (!deletionSucceeded) {
|
||||
throw new IOException("failed to remove existing DB file: " + dbFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
// String md5sum1 = SQLiteJDBCLoader.md5sum(resourceAddr.openStream());
|
||||
// String md5sum2 = SQLiteJDBCLoader.md5sum(new FileInputStream(dbFile));
|
||||
//
|
||||
// if (md5sum1.equals(md5sum2))
|
||||
// return dbFile; // no need to extract the DB file
|
||||
// else
|
||||
// {
|
||||
// }
|
||||
}
|
||||
|
||||
byte[] buffer = new byte[8192]; // 8K buffer
|
||||
FileOutputStream writer = new FileOutputStream(dbFile);
|
||||
InputStream reader = resourceAddr.openStream();
|
||||
try {
|
||||
int bytesRead = 0;
|
||||
while ((bytesRead = reader.read(buffer)) != -1) {
|
||||
writer.write(buffer, 0, bytesRead);
|
||||
}
|
||||
return dbFile;
|
||||
}
|
||||
finally {
|
||||
writer.close();
|
||||
reader.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
void setTimeout(int ms) throws SQLException {
|
||||
timeout = ms;
|
||||
db.busy_timeout(ms);
|
||||
}
|
||||
|
||||
String url() {
|
||||
return url;
|
||||
}
|
||||
|
||||
String libversion() throws SQLException {
|
||||
return db.libversion();
|
||||
}
|
||||
|
||||
DB db() {
|
||||
return db;
|
||||
}
|
||||
|
||||
private void checkOpen() throws SQLException {
|
||||
if (db == null)
|
||||
throw new SQLException("database connection closed");
|
||||
}
|
||||
|
||||
private void checkCursor(int rst, int rsc, int rsh) throws SQLException {
|
||||
if (rst != ResultSet.TYPE_FORWARD_ONLY)
|
||||
throw new SQLException("SQLite only supports TYPE_FORWARD_ONLY cursors");
|
||||
if (rsc != ResultSet.CONCUR_READ_ONLY)
|
||||
throw new SQLException("SQLite only supports CONCUR_READ_ONLY cursors");
|
||||
if (rsh != ResultSet.CLOSE_CURSORS_AT_COMMIT)
|
||||
throw new SQLException("SQLite only supports closing cursors at commit");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void finalize() throws SQLException {
|
||||
close();
|
||||
}
|
||||
|
||||
public void close() throws SQLException {
|
||||
if (db == null)
|
||||
return;
|
||||
if (meta != null)
|
||||
meta.close();
|
||||
|
||||
db.close();
|
||||
db = null;
|
||||
}
|
||||
|
||||
public boolean isClosed() throws SQLException {
|
||||
return db == null;
|
||||
}
|
||||
|
||||
public String getCatalog() throws SQLException {
|
||||
checkOpen();
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setCatalog(String catalog) throws SQLException {
|
||||
checkOpen();
|
||||
}
|
||||
|
||||
public int getHoldability() throws SQLException {
|
||||
checkOpen();
|
||||
return ResultSet.CLOSE_CURSORS_AT_COMMIT;
|
||||
}
|
||||
|
||||
public void setHoldability(int h) throws SQLException {
|
||||
checkOpen();
|
||||
if (h != ResultSet.CLOSE_CURSORS_AT_COMMIT)
|
||||
throw new SQLException("SQLite only supports CLOSE_CURSORS_AT_COMMIT");
|
||||
}
|
||||
|
||||
public int getTransactionIsolation() {
|
||||
return transactionIsolation;
|
||||
}
|
||||
|
||||
public void setTransactionIsolation(int level) throws SQLException {
|
||||
switch (level) {
|
||||
case TRANSACTION_SERIALIZABLE:
|
||||
db.exec("PRAGMA read_uncommitted = false;");
|
||||
break;
|
||||
case TRANSACTION_READ_UNCOMMITTED:
|
||||
db.exec("PRAGMA read_uncommitted = true;");
|
||||
break;
|
||||
default:
|
||||
throw new SQLException("SQLite supports only TRANSACTION_SERIALIZABLE and TRANSACTION_READ_UNCOMMITTED.");
|
||||
}
|
||||
transactionIsolation = level;
|
||||
}
|
||||
|
||||
public Map getTypeMap() throws SQLException {
|
||||
throw new SQLException("not yet implemented");
|
||||
}
|
||||
|
||||
public void setTypeMap(Map map) throws SQLException {
|
||||
throw new SQLException("not yet implemented");
|
||||
}
|
||||
|
||||
public boolean isReadOnly() throws SQLException {
|
||||
return false;
|
||||
} // FIXME
|
||||
|
||||
public void setReadOnly(boolean ro) throws SQLException {}
|
||||
|
||||
public DatabaseMetaData getMetaData() {
|
||||
if (meta == null)
|
||||
meta = new MetaData(this);
|
||||
return meta;
|
||||
}
|
||||
|
||||
public String nativeSQL(String sql) {
|
||||
return sql;
|
||||
}
|
||||
|
||||
public void clearWarnings() throws SQLException {}
|
||||
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean getAutoCommit() throws SQLException {
|
||||
checkOpen();
|
||||
return autoCommit;
|
||||
}
|
||||
|
||||
public void setAutoCommit(boolean ac) throws SQLException {
|
||||
checkOpen();
|
||||
if (autoCommit == ac)
|
||||
return;
|
||||
autoCommit = ac;
|
||||
db.exec(autoCommit ? "commit;" : "begin;");
|
||||
}
|
||||
|
||||
public void commit() throws SQLException {
|
||||
checkOpen();
|
||||
if (autoCommit)
|
||||
throw new SQLException("database in auto-commit mode");
|
||||
db.exec("commit;");
|
||||
db.exec("begin;");
|
||||
}
|
||||
|
||||
public void rollback() throws SQLException {
|
||||
checkOpen();
|
||||
if (autoCommit)
|
||||
throw new SQLException("database in auto-commit mode");
|
||||
db.exec("rollback;");
|
||||
db.exec("begin;");
|
||||
}
|
||||
|
||||
public Statement createStatement() throws SQLException {
|
||||
return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
|
||||
ResultSet.CLOSE_CURSORS_AT_COMMIT);
|
||||
}
|
||||
|
||||
public Statement createStatement(int rsType, int rsConcurr) throws SQLException {
|
||||
return createStatement(rsType, rsConcurr, ResultSet.CLOSE_CURSORS_AT_COMMIT);
|
||||
}
|
||||
|
||||
public Statement createStatement(int rst, int rsc, int rsh) throws SQLException {
|
||||
checkCursor(rst, rsc, rsh);
|
||||
return new Stmt(this);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql) throws SQLException {
|
||||
return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY,
|
||||
ResultSet.CLOSE_CURSORS_AT_COMMIT);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int rst, int rsc) throws SQLException {
|
||||
return prepareCall(sql, rst, rsc, ResultSet.CLOSE_CURSORS_AT_COMMIT);
|
||||
}
|
||||
|
||||
public CallableStatement prepareCall(String sql, int rst, int rsc, int rsh) throws SQLException {
|
||||
throw new SQLException("SQLite does not support Stored Procedures");
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql) throws SQLException {
|
||||
return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int autoC) throws SQLException {
|
||||
return prepareStatement(sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int[] colInds) throws SQLException {
|
||||
return prepareStatement(sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, String[] colNames) throws SQLException {
|
||||
return prepareStatement(sql);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int rst, int rsc) throws SQLException {
|
||||
return prepareStatement(sql, rst, rsc, ResultSet.CLOSE_CURSORS_AT_COMMIT);
|
||||
}
|
||||
|
||||
public PreparedStatement prepareStatement(String sql, int rst, int rsc, int rsh) throws SQLException {
|
||||
checkCursor(rst, rsc, rsh);
|
||||
return new PrepStmt(this, sql);
|
||||
}
|
||||
|
||||
/** Used to supply DatabaseMetaData.getDriverVersion(). */
|
||||
String getDriverVersion() {
|
||||
if (db != null) {
|
||||
String dbname = db.getClass().getName();
|
||||
if (dbname.indexOf("NestedDB") >= 0)
|
||||
return "pure";
|
||||
if (dbname.indexOf("NativeDB") >= 0)
|
||||
return "native";
|
||||
}
|
||||
return "unloaded";
|
||||
}
|
||||
|
||||
// UNUSED FUNCTIONS /////////////////////////////////////////////
|
||||
|
||||
public Savepoint setSavepoint() throws SQLException {
|
||||
throw new SQLException("unsupported by SQLite: savepoints");
|
||||
}
|
||||
|
||||
public Savepoint setSavepoint(String name) throws SQLException {
|
||||
throw new SQLException("unsupported by SQLite: savepoints");
|
||||
}
|
||||
|
||||
public void releaseSavepoint(Savepoint savepoint) throws SQLException {
|
||||
throw new SQLException("unsupported by SQLite: savepoints");
|
||||
}
|
||||
|
||||
public void rollback(Savepoint savepoint) throws SQLException {
|
||||
throw new SQLException("unsupported by SQLite: savepoints");
|
||||
}
|
||||
|
||||
public Struct createStruct(String t, Object[] attr) throws SQLException {
|
||||
throw new SQLException("unsupported by SQLite");
|
||||
}
|
||||
}
|
@ -1,444 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
package org.sqlite;
|
||||
|
||||
import java.sql.BatchUpdateException;
|
||||
import java.sql.SQLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
/*
|
||||
* This class is the interface to SQLite. It provides some helper functions
|
||||
* used by other parts of the driver. The goal of the helper functions here
|
||||
* are not only to provide functionality, but to handle contractual
|
||||
* differences between the JDBC specification and the SQLite C API.
|
||||
*
|
||||
* The process of moving SQLite weirdness into this class is incomplete.
|
||||
* You'll still find lots of code in Stmt and PrepStmt that are doing
|
||||
* implicit contract conversions. Sorry.
|
||||
*
|
||||
* The two subclasses, NativeDB and NestedDB, provide the actual access to
|
||||
* SQLite functions.
|
||||
*/
|
||||
abstract class DB implements Codes
|
||||
{
|
||||
/** The JDBC Connection that 'owns' this database instance. */
|
||||
Conn conn = null;
|
||||
|
||||
/** The "begin;"and "commit;" statement handles. */
|
||||
long begin = 0;
|
||||
long commit = 0;
|
||||
|
||||
/** Tracer for statements to avoid unfinalized statements on db close. */
|
||||
private final Map<Long, Stmt> stmts = new HashMap<Long, Stmt>();
|
||||
|
||||
// WRAPPER FUNCTIONS ////////////////////////////////////////////
|
||||
|
||||
abstract void interrupt() throws SQLException;
|
||||
|
||||
abstract void busy_timeout(int ms) throws SQLException;
|
||||
|
||||
abstract String errmsg() throws SQLException;
|
||||
|
||||
abstract String libversion() throws SQLException;
|
||||
|
||||
abstract int changes() throws SQLException;
|
||||
|
||||
abstract int shared_cache(boolean enable) throws SQLException;
|
||||
|
||||
abstract int enable_load_extension(boolean enable) throws SQLException;
|
||||
|
||||
final synchronized void exec(String sql) throws SQLException {
|
||||
long pointer = 0;
|
||||
try {
|
||||
pointer = prepare(sql);
|
||||
switch (step(pointer)) {
|
||||
case SQLITE_DONE:
|
||||
ensureAutoCommit();
|
||||
return;
|
||||
case SQLITE_ROW:
|
||||
return;
|
||||
default:
|
||||
throwex();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
finalize(pointer);
|
||||
}
|
||||
}
|
||||
|
||||
final synchronized void open(Conn conn, String file, int openFlags) throws SQLException {
|
||||
this.conn = conn;
|
||||
_open(file, openFlags);
|
||||
}
|
||||
|
||||
final synchronized void close() throws SQLException {
|
||||
// finalize any remaining statements before closing db
|
||||
synchronized (stmts) {
|
||||
Iterator i = stmts.entrySet().iterator();
|
||||
while (i.hasNext()) {
|
||||
Map.Entry entry = (Map.Entry) i.next();
|
||||
Stmt stmt = (Stmt) entry.getValue();
|
||||
finalize(((Long) entry.getKey()).longValue());
|
||||
if (stmt != null) {
|
||||
stmt.pointer = 0;
|
||||
}
|
||||
i.remove();
|
||||
}
|
||||
}
|
||||
|
||||
// remove memory used by user-defined functions
|
||||
free_functions();
|
||||
|
||||
// clean up commit object
|
||||
if (begin != 0) {
|
||||
finalize(begin);
|
||||
begin = 0;
|
||||
}
|
||||
if (commit != 0) {
|
||||
finalize(commit);
|
||||
commit = 0;
|
||||
}
|
||||
|
||||
_close();
|
||||
}
|
||||
|
||||
final synchronized void prepare(Stmt stmt) throws SQLException {
|
||||
if (stmt.pointer != 0)
|
||||
finalize(stmt);
|
||||
stmt.pointer = prepare(stmt.sql);
|
||||
stmts.put(new Long(stmt.pointer), stmt);
|
||||
}
|
||||
|
||||
final synchronized int finalize(Stmt stmt) throws SQLException {
|
||||
if (stmt.pointer == 0)
|
||||
return 0;
|
||||
int rc = SQLITE_ERROR;
|
||||
try {
|
||||
rc = finalize(stmt.pointer);
|
||||
}
|
||||
finally {
|
||||
stmts.remove(new Long(stmt.pointer));
|
||||
stmt.pointer = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
protected abstract void _open(String filename, int openFlags) throws SQLException;
|
||||
|
||||
protected abstract void _close() throws SQLException;
|
||||
|
||||
protected abstract int _exec(String sql) throws SQLException;
|
||||
|
||||
protected abstract long prepare(String sql) throws SQLException;
|
||||
|
||||
protected abstract int finalize(long stmt) throws SQLException;
|
||||
|
||||
protected abstract int step(long stmt) throws SQLException;
|
||||
|
||||
protected abstract int reset(long stmt) throws SQLException;
|
||||
|
||||
abstract int clear_bindings(long stmt) throws SQLException; // TODO remove?
|
||||
|
||||
abstract int bind_parameter_count(long stmt) throws SQLException;
|
||||
|
||||
abstract int column_count(long stmt) throws SQLException;
|
||||
|
||||
abstract int column_type(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract String column_decltype(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract String column_table_name(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract String column_name(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract String column_text(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract byte[] column_blob(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract double column_double(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract long column_long(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract int column_int(long stmt, int col) throws SQLException;
|
||||
|
||||
abstract int bind_null(long stmt, int pos) throws SQLException;
|
||||
|
||||
abstract int bind_int(long stmt, int pos, int v) throws SQLException;
|
||||
|
||||
abstract int bind_long(long stmt, int pos, long v) throws SQLException;
|
||||
|
||||
abstract int bind_double(long stmt, int pos, double v) throws SQLException;
|
||||
|
||||
abstract int bind_text(long stmt, int pos, String v) throws SQLException;
|
||||
|
||||
abstract int bind_blob(long stmt, int pos, byte[] v) throws SQLException;
|
||||
|
||||
abstract void result_null(long context) throws SQLException;
|
||||
|
||||
abstract void result_text(long context, String val) throws SQLException;
|
||||
|
||||
abstract void result_blob(long context, byte[] val) throws SQLException;
|
||||
|
||||
abstract void result_double(long context, double val) throws SQLException;
|
||||
|
||||
abstract void result_long(long context, long val) throws SQLException;
|
||||
|
||||
abstract void result_int(long context, int val) throws SQLException;
|
||||
|
||||
abstract void result_error(long context, String err) throws SQLException;
|
||||
|
||||
abstract int value_bytes(Function f, int arg) throws SQLException;
|
||||
|
||||
abstract String value_text(Function f, int arg) throws SQLException;
|
||||
|
||||
abstract byte[] value_blob(Function f, int arg) throws SQLException;
|
||||
|
||||
abstract double value_double(Function f, int arg) throws SQLException;
|
||||
|
||||
abstract long value_long(Function f, int arg) throws SQLException;
|
||||
|
||||
abstract int value_int(Function f, int arg) throws SQLException;
|
||||
|
||||
abstract int value_type(Function f, int arg) throws SQLException;
|
||||
|
||||
abstract int create_function(String name, Function f) throws SQLException;
|
||||
|
||||
abstract int destroy_function(String name) throws SQLException;
|
||||
|
||||
abstract void free_functions() throws SQLException;
|
||||
|
||||
abstract int backup(String dbName, String destFileName, ProgressObserver observer) throws SQLException;
|
||||
|
||||
abstract int restore(String dbName, String sourceFileName, ProgressObserver observer) throws SQLException;
|
||||
|
||||
public static interface ProgressObserver
|
||||
{
|
||||
public void progress(int remaining, int pageCount);
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides metadata for the columns of a statement. Returns: res[col][0] =
|
||||
* true if column constrained NOT NULL res[col][1] = true if column is part
|
||||
* of the primary key res[col][2] = true if column is auto-increment
|
||||
*/
|
||||
abstract boolean[][] column_metadata(long stmt) throws SQLException;
|
||||
|
||||
// COMPOUND FUNCTIONS ////////////////////////////////////////////
|
||||
|
||||
final synchronized String[] column_names(long stmt) throws SQLException {
|
||||
String[] names = new String[column_count(stmt)];
|
||||
for (int i = 0; i < names.length; i++)
|
||||
names[i] = column_name(stmt, i);
|
||||
return names;
|
||||
}
|
||||
|
||||
final synchronized int sqlbind(long stmt, int pos, Object v) throws SQLException {
|
||||
pos++;
|
||||
if (v == null) {
|
||||
return bind_null(stmt, pos);
|
||||
}
|
||||
else if (v instanceof Integer) {
|
||||
return bind_int(stmt, pos, ((Integer) v).intValue());
|
||||
}
|
||||
else if (v instanceof Short) {
|
||||
return bind_int(stmt, pos, ((Short) v).intValue());
|
||||
}
|
||||
else if (v instanceof Long) {
|
||||
return bind_long(stmt, pos, ((Long) v).longValue());
|
||||
}
|
||||
else if (v instanceof Float) {
|
||||
return bind_double(stmt, pos, ((Float) v).doubleValue());
|
||||
}
|
||||
else if (v instanceof Double) {
|
||||
return bind_double(stmt, pos, ((Double) v).doubleValue());
|
||||
}
|
||||
else if (v instanceof String) {
|
||||
return bind_text(stmt, pos, (String) v);
|
||||
}
|
||||
else if (v instanceof byte[]) {
|
||||
return bind_blob(stmt, pos, (byte[]) v);
|
||||
}
|
||||
else {
|
||||
throw new SQLException("unexpected param type: " + v.getClass());
|
||||
}
|
||||
}
|
||||
|
||||
final synchronized int[] executeBatch(long stmt, int count, Object[] vals) throws SQLException {
|
||||
if (count < 1)
|
||||
throw new SQLException("count (" + count + ") < 1");
|
||||
|
||||
final int params = bind_parameter_count(stmt);
|
||||
|
||||
int rc;
|
||||
int[] changes = new int[count];
|
||||
|
||||
try {
|
||||
for (int i = 0; i < count; i++) {
|
||||
reset(stmt);
|
||||
for (int j = 0; j < params; j++)
|
||||
if (sqlbind(stmt, j, vals[(i * params) + j]) != SQLITE_OK)
|
||||
throwex();
|
||||
|
||||
rc = step(stmt);
|
||||
if (rc != SQLITE_DONE) {
|
||||
reset(stmt);
|
||||
if (rc == SQLITE_ROW)
|
||||
throw new BatchUpdateException("batch entry " + i + ": query returns results", changes);
|
||||
throwex();
|
||||
}
|
||||
|
||||
changes[i] = changes();
|
||||
}
|
||||
}
|
||||
finally {
|
||||
ensureAutoCommit();
|
||||
}
|
||||
|
||||
reset(stmt);
|
||||
return changes;
|
||||
}
|
||||
|
||||
final synchronized boolean execute(Stmt stmt, Object[] vals) throws SQLException {
|
||||
if (vals != null) {
|
||||
final int params = bind_parameter_count(stmt.pointer);
|
||||
if (params != vals.length)
|
||||
throw new SQLException("assertion failure: param count (" + params + ") != value count (" + vals.length
|
||||
+ ")");
|
||||
|
||||
for (int i = 0; i < params; i++)
|
||||
if (sqlbind(stmt.pointer, i, vals[i]) != SQLITE_OK)
|
||||
throwex();
|
||||
}
|
||||
|
||||
int statusCode = step(stmt.pointer);
|
||||
switch (statusCode) {
|
||||
case SQLITE_DONE:
|
||||
reset(stmt.pointer);
|
||||
ensureAutoCommit();
|
||||
return false;
|
||||
case SQLITE_ROW:
|
||||
return true;
|
||||
case SQLITE_BUSY:
|
||||
case SQLITE_LOCKED:
|
||||
case SQLITE_MISUSE:
|
||||
throw newSQLException(statusCode);
|
||||
default:
|
||||
finalize(stmt);
|
||||
throw newSQLException(statusCode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
final synchronized boolean execute(String sql) throws SQLException {
|
||||
int statusCode = _exec(sql);
|
||||
switch (statusCode) {
|
||||
case SQLITE_OK:
|
||||
return false;
|
||||
case SQLITE_DONE:
|
||||
ensureAutoCommit();
|
||||
return false;
|
||||
case SQLITE_ROW:
|
||||
return true;
|
||||
default:
|
||||
throw newSQLException(statusCode);
|
||||
}
|
||||
}
|
||||
|
||||
final synchronized int executeUpdate(Stmt stmt, Object[] vals) throws SQLException {
|
||||
if (execute(stmt, vals))
|
||||
throw new SQLException("query returns results");
|
||||
reset(stmt.pointer);
|
||||
return changes();
|
||||
}
|
||||
|
||||
final void throwex() throws SQLException {
|
||||
throw new SQLException(errmsg());
|
||||
}
|
||||
|
||||
final void throwex(int errorCode) throws SQLException {
|
||||
throw newSQLException(errorCode);
|
||||
}
|
||||
|
||||
final void throwex(int errorCode, String errorMessage) throws SQLException {
|
||||
throw newSQLException(errorCode, errorMessage);
|
||||
}
|
||||
|
||||
static SQLException newSQLException(int errorCode, String errorMessage) throws SQLException {
|
||||
SQLiteErrorCode code = SQLiteErrorCode.getErrorCode(errorCode);
|
||||
return new SQLException(String.format("%s (%s)", code, errorMessage));
|
||||
}
|
||||
|
||||
private SQLException newSQLException(int errorCode) throws SQLException {
|
||||
return newSQLException(errorCode, errmsg());
|
||||
}
|
||||
|
||||
/*
|
||||
* SQLite and the JDBC API have very different ideas about the meaning
|
||||
* of auto-commit. Under JDBC, when executeUpdate() returns in
|
||||
* auto-commit mode (the default), the programmer assumes the data has
|
||||
* been written to disk. In SQLite however, a call to sqlite3_step()
|
||||
* with an INSERT statement can return SQLITE_OK, and yet the data is
|
||||
* still in limbo.
|
||||
*
|
||||
* This limbo appears when another statement on the database is active,
|
||||
* e.g. a SELECT. SQLite auto-commit waits until the final read
|
||||
* statement finishes, and then writes whatever updates have already
|
||||
* been OKed. So if a program crashes before the reads are complete,
|
||||
* data is lost. E.g:
|
||||
*
|
||||
* select begins
|
||||
* insert
|
||||
* select continues
|
||||
* select finishes
|
||||
*
|
||||
* Works as expected, however
|
||||
*
|
||||
* select beings
|
||||
* insert
|
||||
* select continues
|
||||
* crash
|
||||
*
|
||||
* Results in the data never being written to disk.
|
||||
*
|
||||
* As a solution, we call "commit" after every statement in auto-commit
|
||||
* mode.
|
||||
*/
|
||||
final void ensureAutoCommit() throws SQLException {
|
||||
if (!conn.getAutoCommit())
|
||||
return;
|
||||
|
||||
if (begin == 0)
|
||||
begin = prepare("begin;");
|
||||
if (commit == 0)
|
||||
commit = prepare("commit;");
|
||||
|
||||
try {
|
||||
if (step(begin) != SQLITE_DONE)
|
||||
return; // assume we are in a transaction
|
||||
if (step(commit) != SQLITE_DONE) {
|
||||
reset(commit);
|
||||
throwex();
|
||||
}
|
||||
//throw new SQLException("unable to auto-commit");
|
||||
}
|
||||
finally {
|
||||
reset(begin);
|
||||
reset(commit);
|
||||
}
|
||||
}
|
||||
}
|
@ -1,116 +0,0 @@
|
||||
//--------------------------------------
|
||||
// sqlite-jdbc Project
|
||||
//
|
||||
// ExtendedCommand.java
|
||||
// Since: Mar 12, 2010
|
||||
//
|
||||
// $URL$
|
||||
// $Author$
|
||||
//--------------------------------------
|
||||
package org.sqlite;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* parsing SQLite specific extension of SQL command
|
||||
*
|
||||
* @author leo
|
||||
*
|
||||
*/
|
||||
public class ExtendedCommand
|
||||
{
|
||||
public static interface SQLExtension
|
||||
{
|
||||
public void execute(DB db) throws SQLException;
|
||||
}
|
||||
|
||||
public static SQLExtension parse(String sql) throws SQLException {
|
||||
if (sql == null)
|
||||
return null;
|
||||
|
||||
if (sql.startsWith("backup"))
|
||||
return BackupCommand.parse(sql);
|
||||
else if (sql.startsWith("restore"))
|
||||
return RestoreCommand.parse(sql);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static String removeQuotation(String s) {
|
||||
if (s == null)
|
||||
return s;
|
||||
|
||||
if ((s.startsWith("\"") && s.endsWith("\"")) || (s.startsWith("'") && s.endsWith("'")))
|
||||
return s.substring(1, s.length() - 1);
|
||||
else
|
||||
return s;
|
||||
}
|
||||
|
||||
public static class BackupCommand implements SQLExtension
|
||||
{
|
||||
public final String srcDB;
|
||||
public final String destFile;
|
||||
|
||||
public BackupCommand(String srcDB, String destFile) {
|
||||
this.srcDB = srcDB;
|
||||
this.destFile = destFile;
|
||||
}
|
||||
|
||||
private static Pattern backupCmd = Pattern
|
||||
.compile("backup(\\s+(\"[^\"]*\"|'[^\']*\'|\\S+))?\\s+to\\s+(\"[^\"]*\"|'[^\']*\'|\\S+)");
|
||||
|
||||
public static BackupCommand parse(String sql) throws SQLException {
|
||||
if (sql != null) {
|
||||
Matcher m = backupCmd.matcher(sql);
|
||||
if (m.matches()) {
|
||||
String dbName = removeQuotation(m.group(2));
|
||||
String dest = removeQuotation(m.group(3));
|
||||
if (dbName == null || dbName.length() == 0)
|
||||
dbName = "main";
|
||||
|
||||
return new BackupCommand(dbName, dest);
|
||||
}
|
||||
}
|
||||
throw new SQLException("syntax error: " + sql);
|
||||
}
|
||||
|
||||
public void execute(DB db) throws SQLException {
|
||||
db.backup(srcDB, destFile, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class RestoreCommand implements SQLExtension
|
||||
{
|
||||
public final String targetDB;
|
||||
public final String srcFile;
|
||||
private static Pattern restoreCmd = Pattern
|
||||
.compile("restore(\\s+(\"[^\"]*\"|'[^\']*\'|\\S+))?\\s+from\\s+(\"[^\"]*\"|'[^\']*\'|\\S+)");
|
||||
|
||||
public RestoreCommand(String targetDB, String srcFile) {
|
||||
this.targetDB = targetDB;
|
||||
this.srcFile = srcFile;
|
||||
}
|
||||
|
||||
public static RestoreCommand parse(String sql) throws SQLException {
|
||||
if (sql != null) {
|
||||
Matcher m = restoreCmd.matcher(sql);
|
||||
if (m.matches()) {
|
||||
String dbName = removeQuotation(m.group(2));
|
||||
String dest = removeQuotation(m.group(3));
|
||||
if (dbName == null || dbName.length() == 0)
|
||||
dbName = "main";
|
||||
return new RestoreCommand(dbName, dest);
|
||||
}
|
||||
}
|
||||
throw new SQLException("syntax error: " + sql);
|
||||
}
|
||||
|
||||
public void execute(DB db) throws SQLException {
|
||||
db.restore(targetDB, srcFile, null);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
package org.sqlite;
|
||||
|
||||
import java.sql.*;
|
||||
|
||||
/** Provides an interface for creating SQLite user-defined functions.
|
||||
*
|
||||
* <p>A subclass of <tt>org.sqlite.Function</tt> can be registered with
|
||||
* <tt>Function.create()</tt> and called by the name it was given. All
|
||||
* functions must implement <tt>xFunc()</tt>, which is called when SQLite
|
||||
* runs the custom function.</p>
|
||||
*
|
||||
* Eg.
|
||||
*
|
||||
* <pre>
|
||||
* Class.forName("org.sqlite.JDBC");
|
||||
* Connection conn = DriverManager.getConnection("jdbc:sqlite:");
|
||||
*
|
||||
* Function.create(conn, "myFunc", new Function() {
|
||||
* protected void xFunc() {
|
||||
* System.out.println("myFunc called!");
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* conn.createStatement().execute("select myFunc();");
|
||||
* </pre>
|
||||
*
|
||||
* <p>Arguments passed to a custom function can be accessed using the
|
||||
* <tt>protected</tt> functions provided. <tt>args()</tt> returns
|
||||
* the number of arguments passed, while
|
||||
* <tt>value_<type>(int)</tt> returns the value of the specific
|
||||
* argument. Similarly a function can return a value using the
|
||||
* <tt>result(<type>)</tt> function.</p>
|
||||
*
|
||||
* <p>Aggregate functions are not yet supported, but coming soon.</p>
|
||||
*
|
||||
*/
|
||||
public abstract class Function
|
||||
{
|
||||
private Conn conn;
|
||||
private DB db;
|
||||
|
||||
long context = 0; // pointer sqlite3_context*
|
||||
long value = 0; // pointer sqlite3_value**
|
||||
int args = 0;
|
||||
|
||||
/** Registers the given function with the Connection using the
|
||||
* provided name. */
|
||||
public static final void create(Connection conn, String name, Function f)
|
||||
throws SQLException {
|
||||
if (conn == null || !(conn instanceof Conn))
|
||||
throw new SQLException("connection must be to an SQLite db");
|
||||
if (conn.isClosed())
|
||||
throw new SQLException("connection closed");
|
||||
|
||||
f.conn = (Conn)conn;
|
||||
f.db = f.conn.db();
|
||||
|
||||
if (name == null || name.length() > 255)
|
||||
throw new SQLException("invalid function name: '"+name+"'");
|
||||
|
||||
if (f.db.create_function(name, f) != Codes.SQLITE_OK)
|
||||
throw new SQLException("error creating function");
|
||||
}
|
||||
|
||||
/** Removes the named function form the Connection. */
|
||||
public static final void destroy(Connection conn, String name)
|
||||
throws SQLException {
|
||||
if (conn == null || !(conn instanceof Conn))
|
||||
throw new SQLException("connection must be to an SQLite db");
|
||||
((Conn)conn).db().destroy_function(name);
|
||||
}
|
||||
|
||||
|
||||
/** Called by SQLite as a custom function. Should access arguments
|
||||
* through <tt>value_*(int)</tt>, return results with
|
||||
* <tt>result(*)</tt> and throw errors with <tt>error(String)</tt>. */
|
||||
protected abstract void xFunc() throws SQLException;
|
||||
|
||||
|
||||
/** Returns the number of arguments passed to the function.
|
||||
* Can only be called from <tt>xFunc()</tt>. */
|
||||
protected synchronized final int args()
|
||||
throws SQLException { checkContext(); return args; }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to return a value. */
|
||||
protected synchronized final void result(byte[] value)
|
||||
throws SQLException { checkContext(); db.result_blob(context, value); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to return a value. */
|
||||
protected synchronized final void result(double value)
|
||||
throws SQLException { checkContext(); db.result_double(context,value);}
|
||||
|
||||
/** Called by <tt>xFunc</tt> to return a value. */
|
||||
protected synchronized final void result(int value)
|
||||
throws SQLException { checkContext(); db.result_int(context, value); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to return a value. */
|
||||
protected synchronized final void result(long value)
|
||||
throws SQLException { checkContext(); db.result_long(context, value); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to return a value. */
|
||||
protected synchronized final void result()
|
||||
throws SQLException { checkContext(); db.result_null(context); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to return a value. */
|
||||
protected synchronized final void result(String value)
|
||||
throws SQLException { checkContext(); db.result_text(context, value); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to throw an error. */
|
||||
protected synchronized final void error(String err)
|
||||
throws SQLException { checkContext(); db.result_error(context, err); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to access the value of an argument. */
|
||||
protected synchronized final int value_bytes(int arg)
|
||||
throws SQLException {checkValue(arg); return db.value_bytes(this,arg);}
|
||||
|
||||
/** Called by <tt>xFunc</tt> to access the value of an argument. */
|
||||
protected synchronized final String value_text(int arg)
|
||||
throws SQLException {checkValue(arg); return db.value_text(this,arg);}
|
||||
|
||||
/** Called by <tt>xFunc</tt> to access the value of an argument. */
|
||||
protected synchronized final byte[] value_blob(int arg)
|
||||
throws SQLException {checkValue(arg); return db.value_blob(this,arg); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to access the value of an argument. */
|
||||
protected synchronized final double value_double(int arg)
|
||||
throws SQLException {checkValue(arg); return db.value_double(this,arg);}
|
||||
|
||||
/** Called by <tt>xFunc</tt> to access the value of an argument. */
|
||||
protected synchronized final int value_int(int arg)
|
||||
throws SQLException {checkValue(arg); return db.value_int(this, arg); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to access the value of an argument. */
|
||||
protected synchronized final long value_long(int arg)
|
||||
throws SQLException { checkValue(arg); return db.value_long(this,arg); }
|
||||
|
||||
/** Called by <tt>xFunc</tt> to access the value of an argument. */
|
||||
protected synchronized final int value_type(int arg)
|
||||
throws SQLException {checkValue(arg); return db.value_type(this,arg); }
|
||||
|
||||
|
||||
private void checkContext() throws SQLException {
|
||||
if (conn == null || conn.db() == null || context == 0)
|
||||
throw new SQLException("no context, not allowed to read value");
|
||||
}
|
||||
|
||||
private void checkValue(int arg) throws SQLException {
|
||||
if (conn == null || conn.db() == null || value == 0)
|
||||
throw new SQLException("not in value access state");
|
||||
if (arg >= args)
|
||||
throw new SQLException("arg "+arg+" out bounds [0,"+args+")");
|
||||
}
|
||||
|
||||
|
||||
public static abstract class Aggregate
|
||||
extends Function
|
||||
implements Cloneable
|
||||
{
|
||||
protected final void xFunc() {}
|
||||
protected abstract void xStep() throws SQLException;
|
||||
protected abstract void xFinal() throws SQLException;
|
||||
|
||||
public Object clone() throws CloneNotSupportedException {
|
||||
return super.clone();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,79 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.sqlite;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.Driver;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.DriverPropertyInfo;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
public class JDBC implements Driver
|
||||
{
|
||||
public static final String PREFIX = "jdbc:sqlite:";
|
||||
|
||||
static {
|
||||
try {
|
||||
DriverManager.registerDriver(new JDBC());
|
||||
}
|
||||
catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public int getMajorVersion() {
|
||||
return SQLiteJDBCLoader.getMajorVersion();
|
||||
}
|
||||
|
||||
public int getMinorVersion() {
|
||||
return SQLiteJDBCLoader.getMinorVersion();
|
||||
}
|
||||
|
||||
public boolean jdbcCompliant() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean acceptsURL(String url) {
|
||||
return isValidURL(url);
|
||||
}
|
||||
|
||||
public static boolean isValidURL(String url) {
|
||||
return url != null && url.toLowerCase().startsWith(PREFIX);
|
||||
}
|
||||
|
||||
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException {
|
||||
return SQLiteConfig.getDriverPropertyInfo();
|
||||
}
|
||||
|
||||
public Connection connect(String url, Properties info) throws SQLException {
|
||||
return createConnection(url, info);
|
||||
}
|
||||
|
||||
static String extractAddress(String url) {
|
||||
// if no file name is given use a memory database
|
||||
return PREFIX.equalsIgnoreCase(url) ? ":memory:" : url.substring(PREFIX.length());
|
||||
}
|
||||
|
||||
public static Connection createConnection(String url, Properties prop) throws SQLException {
|
||||
if (!isValidURL(url))
|
||||
throw new SQLException("invalid database address: " + url);
|
||||
|
||||
url = url.trim();
|
||||
return new Conn(url, extractAddress(url), prop);
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.sqlite;
|
||||
|
||||
import java.sql.SQLException;
|
||||
|
||||
/** This class provides a thin JNI layer over the SQLite3 C API. */
|
||||
final class NativeDB extends DB
|
||||
{
|
||||
/** SQLite connection handle. */
|
||||
long pointer = 0;
|
||||
|
||||
private static boolean isLoaded = false;
|
||||
private static boolean loadSucceeded = false;
|
||||
|
||||
static boolean load() {
|
||||
if (isLoaded)
|
||||
return loadSucceeded == true;
|
||||
|
||||
loadSucceeded = SQLiteJDBCLoader.initialize();
|
||||
isLoaded = true;
|
||||
return loadSucceeded;
|
||||
}
|
||||
|
||||
/** linked list of all instanced UDFDatas */
|
||||
private final long udfdatalist = 0;
|
||||
|
||||
// WRAPPER FUNCTIONS ////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected native synchronized void _open(String file, int openFlags) throws SQLException;
|
||||
|
||||
@Override
|
||||
protected native synchronized void _close() throws SQLException;
|
||||
|
||||
@Override
|
||||
protected native synchronized int _exec(String sql) throws SQLException;
|
||||
|
||||
@Override
|
||||
native synchronized int shared_cache(boolean enable);
|
||||
|
||||
@Override
|
||||
native synchronized int enable_load_extension(boolean enable);
|
||||
|
||||
@Override
|
||||
native synchronized void interrupt();
|
||||
|
||||
@Override
|
||||
native synchronized void busy_timeout(int ms);
|
||||
|
||||
//native synchronized void exec(String sql) throws SQLException;
|
||||
@Override
|
||||
protected native synchronized long prepare(String sql) throws SQLException;
|
||||
|
||||
@Override
|
||||
native synchronized String errmsg();
|
||||
|
||||
@Override
|
||||
native synchronized String libversion();
|
||||
|
||||
@Override
|
||||
native synchronized int changes();
|
||||
|
||||
@Override
|
||||
protected native synchronized int finalize(long stmt);
|
||||
|
||||
@Override
|
||||
protected native synchronized int step(long stmt);
|
||||
|
||||
@Override
|
||||
protected native synchronized int reset(long stmt);
|
||||
|
||||
@Override
|
||||
native synchronized int clear_bindings(long stmt);
|
||||
|
||||
@Override
|
||||
native synchronized int bind_parameter_count(long stmt);
|
||||
|
||||
@Override
|
||||
native synchronized int column_count(long stmt);
|
||||
|
||||
@Override
|
||||
native synchronized int column_type(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized String column_decltype(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized String column_table_name(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized String column_name(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized String column_text(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized byte[] column_blob(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized double column_double(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized long column_long(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized int column_int(long stmt, int col);
|
||||
|
||||
@Override
|
||||
native synchronized int bind_null(long stmt, int pos);
|
||||
|
||||
@Override
|
||||
native synchronized int bind_int(long stmt, int pos, int v);
|
||||
|
||||
@Override
|
||||
native synchronized int bind_long(long stmt, int pos, long v);
|
||||
|
||||
@Override
|
||||
native synchronized int bind_double(long stmt, int pos, double v);
|
||||
|
||||
@Override
|
||||
native synchronized int bind_text(long stmt, int pos, String v);
|
||||
|
||||
@Override
|
||||
native synchronized int bind_blob(long stmt, int pos, byte[] v);
|
||||
|
||||
@Override
|
||||
native synchronized void result_null(long context);
|
||||
|
||||
@Override
|
||||
native synchronized void result_text(long context, String val);
|
||||
|
||||
@Override
|
||||
native synchronized void result_blob(long context, byte[] val);
|
||||
|
||||
@Override
|
||||
native synchronized void result_double(long context, double val);
|
||||
|
||||
@Override
|
||||
native synchronized void result_long(long context, long val);
|
||||
|
||||
@Override
|
||||
native synchronized void result_int(long context, int val);
|
||||
|
||||
@Override
|
||||
native synchronized void result_error(long context, String err);
|
||||
|
||||
@Override
|
||||
native synchronized int value_bytes(Function f, int arg);
|
||||
|
||||
@Override
|
||||
native synchronized String value_text(Function f, int arg);
|
||||
|
||||
@Override
|
||||
native synchronized byte[] value_blob(Function f, int arg);
|
||||
|
||||
@Override
|
||||
native synchronized double value_double(Function f, int arg);
|
||||
|
||||
@Override
|
||||
native synchronized long value_long(Function f, int arg);
|
||||
|
||||
@Override
|
||||
native synchronized int value_int(Function f, int arg);
|
||||
|
||||
@Override
|
||||
native synchronized int value_type(Function f, int arg);
|
||||
|
||||
@Override
|
||||
native synchronized int create_function(String name, Function func);
|
||||
|
||||
@Override
|
||||
native synchronized int destroy_function(String name);
|
||||
|
||||
@Override
|
||||
native synchronized void free_functions();
|
||||
|
||||
@Override
|
||||
native synchronized int backup(String dbName, String destFileName, ProgressObserver observer) throws SQLException;
|
||||
|
||||
@Override
|
||||
native synchronized int restore(String dbName, String sourceFileName, ProgressObserver observer)
|
||||
throws SQLException;
|
||||
|
||||
// COMPOUND FUNCTIONS (for optimisation) /////////////////////////
|
||||
|
||||
/**
|
||||
* Provides metadata for the columns of a statement. Returns: res[col][0] =
|
||||
* true if column constrained NOT NULL res[col][1] = true if column is part
|
||||
* of the primary key res[col][2] = true if column is auto-increment
|
||||
*/
|
||||
@Override
|
||||
native synchronized boolean[][] column_metadata(long stmt);
|
||||
|
||||
static void throwex(String msg) throws SQLException {
|
||||
throw new SQLException(msg);
|
||||
}
|
||||
}
|
@ -1,662 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
package org.sqlite;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.sql.SQLException;
|
||||
|
||||
import org.ibex.nestedvm.Runtime;
|
||||
|
||||
// FEATURE: strdup is wasteful, SQLite interface will take unterminated char*
|
||||
|
||||
/** Communicates with the Java version of SQLite provided by NestedVM. */
|
||||
final class NestedDB extends DB implements Runtime.CallJavaCB
|
||||
{
|
||||
/** database pointer */
|
||||
int handle = 0;
|
||||
|
||||
/** sqlite binary embedded in nestedvm */
|
||||
private Runtime rt = null;
|
||||
|
||||
/** user defined functions referenced by position (stored in used data) */
|
||||
private Function[] functions = null;
|
||||
private String[] funcNames = null;
|
||||
|
||||
// WRAPPER FUNCTIONS ////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
protected synchronized void _open(String filename, int openFlags) throws SQLException {
|
||||
if (handle != 0)
|
||||
throw new SQLException("DB already open");
|
||||
|
||||
// handle silly windows drive letter mapping
|
||||
if (filename.length() > 2) {
|
||||
char drive = Character.toLowerCase(filename.charAt(0));
|
||||
if (filename.charAt(1) == ':' && drive >= 'a' && drive <= 'z') {
|
||||
|
||||
// convert to nestedvm's "/c:/file" format
|
||||
filename = filename.substring(2);
|
||||
filename = filename.replace('\\', '/');
|
||||
filename = "/" + drive + ":" + filename;
|
||||
}
|
||||
}
|
||||
|
||||
// start the nestedvm runtime
|
||||
try {
|
||||
rt = (Runtime) Class.forName("org.sqlite.SQLite").newInstance();
|
||||
rt.start();
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new CausedSQLException(e);
|
||||
}
|
||||
|
||||
// callback for user defined functions
|
||||
rt.setCallJavaCB(this);
|
||||
|
||||
// open the db and retrieve sqlite3_db* pointer
|
||||
int passback = rt.xmalloc(4);
|
||||
int str = rt.strdup(filename);
|
||||
// if (call("sqlite3_open_v2", str, openFlags, 0, passback) != SQLITE_OK)
|
||||
if (call("sqlite3_open_v2", str, passback, openFlags, 0) != SQLITE_OK)
|
||||
throwex();
|
||||
handle = deref(passback);
|
||||
rt.free(str);
|
||||
rt.free(passback);
|
||||
}
|
||||
|
||||
/* callback for Runtime.CallJavaCB above */
|
||||
public int call(int xType, int context, int args, int value) {
|
||||
xUDF(xType, context, args, value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized void _close() throws SQLException {
|
||||
if (handle == 0)
|
||||
return;
|
||||
try {
|
||||
if (call("sqlite3_close", handle) != SQLITE_OK)
|
||||
throwex();
|
||||
}
|
||||
finally {
|
||||
handle = 0;
|
||||
rt.stop();
|
||||
rt = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
int shared_cache(boolean enable) throws SQLException {
|
||||
// The shared cache is per-process, so it is useless as
|
||||
// each nested connection is its own process.
|
||||
return -1;
|
||||
}
|
||||
|
||||
@Override
|
||||
int enable_load_extension(boolean enable) throws SQLException {
|
||||
// TODO enable_load_extension is not supported in pure-java mode
|
||||
//return call("sqlite3_enable_load_extension", handle, enable ? 1 : 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void interrupt() throws SQLException {
|
||||
call("sqlite3_interrupt", handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void busy_timeout(int ms) throws SQLException {
|
||||
call("sqlite3_busy_timeout", handle, ms);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized long prepare(String sql) throws SQLException {
|
||||
|
||||
int passback = rt.xmalloc(4);
|
||||
int str = rt.strdup(sql);
|
||||
int ret = call("sqlite3_prepare_v2", handle, str, -1, passback, 0);
|
||||
rt.free(str);
|
||||
if (ret != SQLITE_OK) {
|
||||
rt.free(passback);
|
||||
throwex(ret);
|
||||
}
|
||||
int pointer = deref(passback);
|
||||
rt.free(passback);
|
||||
return pointer;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized String errmsg() throws SQLException {
|
||||
return cstring(call("sqlite3_errmsg", handle));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized String libversion() throws SQLException {
|
||||
return cstring(call("sqlite3_libversion", handle));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int changes() throws SQLException {
|
||||
return call("sqlite3_changes", handle);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized int _exec(String sql) throws SQLException {
|
||||
if (rt == null)
|
||||
throw DB.newSQLException(SQLiteErrorCode.SQLITE_MISUSE.code, "attempt to use the closed conection");
|
||||
int passback = rt.xmalloc(4);
|
||||
int str = rt.strdup(sql);
|
||||
int status = call("sqlite3_exec", handle, str, 0, 0, passback);
|
||||
if (status != SQLITE_OK) {
|
||||
String errorMessage = cstring(passback);
|
||||
call("sqlite3_free", deref(passback));
|
||||
rt.free(passback);
|
||||
throwex(status, errorMessage);
|
||||
}
|
||||
rt.free(passback);
|
||||
return status;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized int finalize(long stmt) throws SQLException {
|
||||
return call("sqlite3_finalize", (int) stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized int step(long stmt) throws SQLException {
|
||||
return call("sqlite3_step", (int) stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected synchronized int reset(long stmt) throws SQLException {
|
||||
return call("sqlite3_reset", (int) stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int clear_bindings(long stmt) throws SQLException {
|
||||
return call("sqlite3_clear_bindings", (int) stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int bind_parameter_count(long stmt) throws SQLException {
|
||||
return call("sqlite3_bind_parameter_count", (int) stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int column_count(long stmt) throws SQLException {
|
||||
return call("sqlite3_column_count", (int) stmt);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int column_type(long stmt, int col) throws SQLException {
|
||||
return call("sqlite3_column_type", (int) stmt, col);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized String column_name(long stmt, int col) throws SQLException {
|
||||
return utfstring(call("sqlite3_column_name", (int) stmt, col));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized String column_text(long stmt, int col) throws SQLException {
|
||||
return utfstring(call("sqlite3_column_text", (int) stmt, col));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized byte[] column_blob(long stmt, int col) throws SQLException {
|
||||
int addr = call("sqlite3_column_blob", (int) stmt, col);
|
||||
if (addr == 0)
|
||||
return null;
|
||||
byte[] blob = new byte[call("sqlite3_column_bytes", (int) stmt, col)];
|
||||
copyin(addr, blob, blob.length);
|
||||
return blob;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized double column_double(long stmt, int col) throws SQLException {
|
||||
try {
|
||||
return Double.parseDouble(column_text(stmt, col));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return Double.NaN;
|
||||
} // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized long column_long(long stmt, int col) throws SQLException {
|
||||
try {
|
||||
return Long.parseLong(column_text(stmt, col));
|
||||
}
|
||||
catch (NumberFormatException e) {
|
||||
return 0;
|
||||
} // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int column_int(long stmt, int col) throws SQLException {
|
||||
return call("sqlite3_column_int", (int) stmt, col);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized String column_decltype(long stmt, int col) throws SQLException {
|
||||
return utfstring(call("sqlite3_column_decltype", (int) stmt, col));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized String column_table_name(long stmt, int col) throws SQLException {
|
||||
return utfstring(call("sqlite3_column_table_name", (int) stmt, col));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int bind_null(long stmt, int pos) throws SQLException {
|
||||
return call("sqlite3_bind_null", (int) stmt, pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int bind_int(long stmt, int pos, int v) throws SQLException {
|
||||
return call("sqlite3_bind_int", (int) stmt, pos, v);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int bind_long(long stmt, int pos, long v) throws SQLException {
|
||||
return bind_text(stmt, pos, Long.toString(v)); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int bind_double(long stmt, int pos, double v) throws SQLException {
|
||||
return bind_text(stmt, pos, Double.toString(v)); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int bind_text(long stmt, int pos, String v) throws SQLException {
|
||||
if (v == null)
|
||||
return bind_null(stmt, pos);
|
||||
return call("sqlite3_bind_text", (int) stmt, pos, rt.strdup(v), -1, rt.lookupSymbol("free"));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int bind_blob(long stmt, int pos, byte[] buf) throws SQLException {
|
||||
if (buf == null || buf.length < 1)
|
||||
return bind_null(stmt, pos);
|
||||
int len = buf.length;
|
||||
int blob = rt.xmalloc(len); // free()ed by sqlite3_bind_blob
|
||||
copyout(buf, blob, len);
|
||||
return call("sqlite3_bind_blob", (int) stmt, pos, blob, len, rt.lookupSymbol("free"));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void result_null(long cxt) throws SQLException {
|
||||
call("sqlite3_result_null", (int) cxt);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void result_text(long cxt, String val) throws SQLException {
|
||||
call("sqlite3_result_text", (int) cxt, rt.strdup(val), -1, rt.lookupSymbol("free"));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void result_blob(long cxt, byte[] val) throws SQLException {
|
||||
if (val == null || val.length == 0) {
|
||||
result_null(cxt);
|
||||
return;
|
||||
}
|
||||
int blob = rt.xmalloc(val.length);
|
||||
copyout(val, blob, val.length);
|
||||
call("sqlite3_result_blob", (int) cxt, blob, val.length, rt.lookupSymbol("free"));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void result_double(long cxt, double val) throws SQLException {
|
||||
result_text(cxt, Double.toString(val));
|
||||
} // TODO
|
||||
|
||||
@Override
|
||||
synchronized void result_long(long cxt, long val) throws SQLException {
|
||||
result_text(cxt, Long.toString(val));
|
||||
} // TODO
|
||||
|
||||
@Override
|
||||
synchronized void result_int(long cxt, int val) throws SQLException {
|
||||
call("sqlite3_result_int", (int) cxt, val);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized void result_error(long cxt, String err) throws SQLException {
|
||||
int str = rt.strdup(err);
|
||||
call("sqlite3_result_error", (int) cxt, str, -1);
|
||||
rt.free(str);
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int value_bytes(Function f, int arg) throws SQLException {
|
||||
return call("sqlite3_value_bytes", value(f, arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized String value_text(Function f, int arg) throws SQLException {
|
||||
return utfstring(call("sqlite3_value_text", value(f, arg)));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized byte[] value_blob(Function f, int arg) throws SQLException {
|
||||
int addr = call("sqlite3_value_blob", value(f, arg));
|
||||
if (addr == 0)
|
||||
return null;
|
||||
byte[] blob = new byte[value_bytes(f, arg)];
|
||||
copyin(addr, blob, blob.length);
|
||||
return blob;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized double value_double(Function f, int arg) throws SQLException {
|
||||
return Double.parseDouble(value_text(f, arg)); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized long value_long(Function f, int arg) throws SQLException {
|
||||
return Long.parseLong(value_text(f, arg)); // TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int value_int(Function f, int arg) throws SQLException {
|
||||
return call("sqlite3_value_int", value(f, arg));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int value_type(Function f, int arg) throws SQLException {
|
||||
return call("sqlite3_value_type", value(f, arg));
|
||||
}
|
||||
|
||||
private int value(Function f, int arg) throws SQLException {
|
||||
return deref((int) f.value + (arg * 4));
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int create_function(String name, Function func) throws SQLException {
|
||||
if (functions == null) {
|
||||
functions = new Function[10];
|
||||
funcNames = new String[10];
|
||||
}
|
||||
|
||||
// find a position
|
||||
int pos;
|
||||
for (pos = 0; pos < functions.length; pos++)
|
||||
if (functions[pos] == null)
|
||||
break;
|
||||
|
||||
if (pos == functions.length) { // expand function arrays
|
||||
Function[] fnew = new Function[functions.length * 2];
|
||||
String[] nnew = new String[funcNames.length * 2];
|
||||
System.arraycopy(functions, 0, fnew, 0, functions.length);
|
||||
System.arraycopy(funcNames, 0, nnew, 0, funcNames.length);
|
||||
functions = fnew;
|
||||
funcNames = nnew;
|
||||
}
|
||||
|
||||
// register function
|
||||
functions[pos] = func;
|
||||
funcNames[pos] = name;
|
||||
int rc;
|
||||
int str = rt.strdup(name);
|
||||
rc = call("create_function_helper", handle, str, pos, func instanceof Function.Aggregate ? 1 : 0);
|
||||
rt.free(str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
@Override
|
||||
synchronized int destroy_function(String name) throws SQLException {
|
||||
if (name == null)
|
||||
return 0;
|
||||
|
||||
// find function position number
|
||||
int pos;
|
||||
for (pos = 0; pos < funcNames.length; pos++)
|
||||
if (name.equals(funcNames[pos]))
|
||||
break;
|
||||
if (pos == funcNames.length)
|
||||
return 0;
|
||||
|
||||
functions[pos] = null;
|
||||
funcNames[pos] = null;
|
||||
|
||||
// deregister function
|
||||
int rc;
|
||||
int str = rt.strdup(name);
|
||||
rc = call("create_function_helper", handle, str, -1, 0);
|
||||
rt.free(str);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* unused as we use the user_data pointer to store a single word */
|
||||
@Override
|
||||
synchronized void free_functions() {}
|
||||
|
||||
/** Callback used by xFunc (1), xStep (2) and xFinal (3). */
|
||||
synchronized void xUDF(int xType, int context, int args, int value) {
|
||||
Function func = null;
|
||||
|
||||
try {
|
||||
int pos = call("sqlite3_user_data", context);
|
||||
func = functions[pos];
|
||||
if (func == null)
|
||||
throw new SQLException("function state inconsistent");
|
||||
|
||||
func.context = context;
|
||||
func.value = value;
|
||||
func.args = args;
|
||||
|
||||
switch (xType) {
|
||||
case 1:
|
||||
func.xFunc();
|
||||
break;
|
||||
case 2:
|
||||
((Function.Aggregate) func).xStep();
|
||||
break;
|
||||
case 3:
|
||||
((Function.Aggregate) func).xFinal();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (SQLException e) {
|
||||
try {
|
||||
String err = e.toString();
|
||||
if (err == null)
|
||||
err = "unknown error";
|
||||
int str = rt.strdup(err);
|
||||
call("sqlite3_result_error", context, str, -1);
|
||||
rt.free(str);
|
||||
}
|
||||
catch (SQLException exp) {
|
||||
exp.printStackTrace();//TODO
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if (func != null) {
|
||||
func.context = 0;
|
||||
func.value = 0;
|
||||
func.args = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Calls support function found in upstream/sqlite-metadata.patch */
|
||||
@Override
|
||||
synchronized boolean[][] column_metadata(long stmt) throws SQLException {
|
||||
int colCount = call("sqlite3_column_count", (int) stmt);
|
||||
boolean[][] meta = new boolean[colCount][3];
|
||||
int pass;
|
||||
|
||||
pass = rt.xmalloc(12); // struct metadata
|
||||
|
||||
for (int i = 0; i < colCount; i++) {
|
||||
call("column_metadata_helper", handle, (int) stmt, i, pass);
|
||||
meta[i][0] = deref(pass) == 1;
|
||||
meta[i][1] = deref(pass + 4) == 1;
|
||||
meta[i][2] = deref(pass + 8) == 1;
|
||||
}
|
||||
|
||||
rt.free(pass);
|
||||
return meta;
|
||||
}
|
||||
|
||||
@Override
|
||||
int backup(String dbName, String destFileName, ProgressObserver observer) throws SQLException {
|
||||
throw new SQLException("backup command is not supported in pure-java mode");
|
||||
}
|
||||
|
||||
@Override
|
||||
int restore(String dbName, String sourceFileName, ProgressObserver observer) throws SQLException {
|
||||
throw new SQLException("restore command is not supported in pure-java mode");
|
||||
}
|
||||
|
||||
// HELPER FUNCTIONS /////////////////////////////////////////////
|
||||
|
||||
/** safe to reuse parameter arrays as all functions are syncrhonized */
|
||||
private final int[] p0 = new int[] {}, p1 = new int[] { 0 }, p2 = new int[] { 0, 0 }, p3 = new int[] { 0, 0, 0 },
|
||||
p4 = new int[] { 0, 0, 0, 0 }, p5 = new int[] { 0, 0, 0, 0, 0 };
|
||||
|
||||
private int call(String addr, int a0) throws SQLException {
|
||||
p1[0] = a0;
|
||||
return call(addr, p1);
|
||||
}
|
||||
|
||||
private int call(String addr, int a0, int a1) throws SQLException {
|
||||
p2[0] = a0;
|
||||
p2[1] = a1;
|
||||
return call(addr, p2);
|
||||
}
|
||||
|
||||
private int call(String addr, int a0, int a1, int a2) throws SQLException {
|
||||
p3[0] = a0;
|
||||
p3[1] = a1;
|
||||
p3[2] = a2;
|
||||
return call(addr, p3);
|
||||
}
|
||||
|
||||
private int call(String addr, int a0, int a1, int a2, int a3) throws SQLException {
|
||||
p4[0] = a0;
|
||||
p4[1] = a1;
|
||||
p4[2] = a2;
|
||||
p4[3] = a3;
|
||||
return call(addr, p4);
|
||||
}
|
||||
|
||||
private int call(String addr, int a0, int a1, int a2, int a3, int a4) throws SQLException {
|
||||
p5[0] = a0;
|
||||
p5[1] = a1;
|
||||
p5[2] = a2;
|
||||
p5[3] = a3;
|
||||
p5[4] = a4;
|
||||
return call(addr, p5);
|
||||
}
|
||||
|
||||
private int call(String func, int[] args) throws SQLException {
|
||||
try {
|
||||
return rt.call(func, args);
|
||||
}
|
||||
catch (Runtime.CallException e) {
|
||||
throw new CausedSQLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Dereferences a pointer, returning the word it points to. */
|
||||
private int deref(int pointer) throws SQLException {
|
||||
try {
|
||||
return rt.memRead(pointer);
|
||||
}
|
||||
catch (Runtime.ReadFaultException e) {
|
||||
throw new CausedSQLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String utfstring(int str) throws SQLException {
|
||||
try {
|
||||
return rt.utfstring(str);
|
||||
}
|
||||
catch (Runtime.ReadFaultException e) {
|
||||
throw new CausedSQLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private String cstring(int str) throws SQLException {
|
||||
try {
|
||||
return rt.cstring(str);
|
||||
}
|
||||
catch (Runtime.ReadFaultException e) {
|
||||
throw new CausedSQLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyin(int addr, byte[] buf, int count) throws SQLException {
|
||||
try {
|
||||
rt.copyin(addr, buf, count);
|
||||
}
|
||||
catch (Runtime.ReadFaultException e) {
|
||||
throw new CausedSQLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void copyout(byte[] buf, int addr, int count) throws SQLException {
|
||||
try {
|
||||
rt.copyout(buf, addr, count);
|
||||
}
|
||||
catch (Runtime.FaultException e) {
|
||||
throw new CausedSQLException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/** Maps any exception onto an SQLException. */
|
||||
private static final class CausedSQLException extends SQLException
|
||||
{
|
||||
private final Exception cause;
|
||||
|
||||
CausedSQLException(Exception e) {
|
||||
if (e == null)
|
||||
throw new RuntimeException("null exception cause");
|
||||
cause = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable getCause() {
|
||||
return cause;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace() {
|
||||
cause.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void printStackTrace(PrintWriter s) {
|
||||
cause.printStackTrace(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Throwable fillInStackTrace() {
|
||||
return cause.fillInStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public StackTraceElement[] getStackTrace() {
|
||||
return cause.getStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
return cause.getMessage();
|
||||
}
|
||||
}
|
||||
}
|
@ -1,80 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
* Copyright 2008 Taro L. Saito
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*--------------------------------------------------------------------------*/
|
||||
//--------------------------------------
|
||||
// sqlite-jdbc Project
|
||||
//
|
||||
// OSInfo.java
|
||||
// Since: May 20, 2008
|
||||
//
|
||||
// $URL$
|
||||
// $Author$
|
||||
//--------------------------------------
|
||||
package org.sqlite;
|
||||
|
||||
/**
|
||||
* Provides OS name and architecture name.
|
||||
*
|
||||
* @author leo
|
||||
*
|
||||
*/
|
||||
public class OSInfo
|
||||
{
|
||||
public static void main(String[] args) {
|
||||
if (args.length >= 1) {
|
||||
if ("--os".equals(args[0])) {
|
||||
System.out.print(getOSName());
|
||||
return;
|
||||
}
|
||||
else if ("--arch".equals(args[0])) {
|
||||
System.out.print(getArchName());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
System.out.print(getNativeLibFolderPathForCurrentOS());
|
||||
}
|
||||
|
||||
public static String getNativeLibFolderPathForCurrentOS() {
|
||||
return getOSName() + "/" + getArchName();
|
||||
}
|
||||
|
||||
public static String getOSName() {
|
||||
return translateOSNameToFolderName(System.getProperty("os.name"));
|
||||
}
|
||||
|
||||
public static String getArchName() {
|
||||
return translateArchNameToFolderName(System.getProperty("os.arch"));
|
||||
}
|
||||
|
||||
public static String translateOSNameToFolderName(String osName) {
|
||||
if (osName.contains("Windows")) {
|
||||
return "Windows";
|
||||
}
|
||||
else if (osName.contains("Mac")) {
|
||||
return "Mac";
|
||||
}
|
||||
else if (osName.contains("Linux")) {
|
||||
return "Linux";
|
||||
}
|
||||
else {
|
||||
return osName.replaceAll("\\W", "");
|
||||
}
|
||||
}
|
||||
|
||||
public static String translateArchNameToFolderName(String archName) {
|
||||
return archName.replaceAll("\\W", "");
|
||||
}
|
||||
}
|
@ -1,330 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.sqlite;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.sql.Date;
|
||||
import java.sql.ParameterMetaData;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.Calendar;
|
||||
|
||||
final class PrepStmt extends Stmt implements PreparedStatement, ParameterMetaData, Codes
|
||||
{
|
||||
private int columnCount;
|
||||
private int paramCount;
|
||||
|
||||
PrepStmt(Conn conn, String sql) throws SQLException {
|
||||
super(conn);
|
||||
|
||||
this.sql = sql;
|
||||
db.prepare(this);
|
||||
rs.colsMeta = db.column_names(pointer);
|
||||
columnCount = db.column_count(pointer);
|
||||
paramCount = db.bind_parameter_count(pointer);
|
||||
batch = new Object[paramCount];
|
||||
batchPos = 0;
|
||||
}
|
||||
|
||||
public void clearParameters() throws SQLException {
|
||||
checkOpen();
|
||||
db.reset(pointer);
|
||||
clearBatch();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws SQLException {
|
||||
close();
|
||||
}
|
||||
|
||||
public boolean execute() throws SQLException {
|
||||
checkOpen();
|
||||
rs.close();
|
||||
db.reset(pointer);
|
||||
resultsWaiting = db.execute(this, batch);
|
||||
return columnCount != 0;
|
||||
}
|
||||
|
||||
public ResultSet executeQuery() throws SQLException {
|
||||
checkOpen();
|
||||
if (columnCount == 0)
|
||||
throw new SQLException("query does not return results");
|
||||
rs.close();
|
||||
db.reset(pointer);
|
||||
resultsWaiting = db.execute(this, batch);
|
||||
return getResultSet();
|
||||
}
|
||||
|
||||
public int executeUpdate() throws SQLException {
|
||||
checkOpen();
|
||||
if (columnCount != 0)
|
||||
throw new SQLException("query returns results");
|
||||
rs.close();
|
||||
db.reset(pointer);
|
||||
return db.executeUpdate(this, batch);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int[] executeBatch() throws SQLException {
|
||||
if (batchPos == 0)
|
||||
return new int[] {};
|
||||
try {
|
||||
return db.executeBatch(pointer, batchPos / paramCount, batch);
|
||||
}
|
||||
finally {
|
||||
clearBatch();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getUpdateCount() throws SQLException {
|
||||
checkOpen();
|
||||
if (pointer == 0 || resultsWaiting)
|
||||
return -1;
|
||||
return db.changes();
|
||||
}
|
||||
|
||||
public void addBatch() throws SQLException {
|
||||
checkOpen();
|
||||
batchPos += paramCount;
|
||||
if (batchPos + paramCount > batch.length) {
|
||||
Object[] nb = new Object[batch.length * 2];
|
||||
System.arraycopy(batch, 0, nb, 0, batch.length);
|
||||
batch = nb;
|
||||
}
|
||||
System.arraycopy(batch, batchPos - paramCount, batch, batchPos, paramCount);
|
||||
}
|
||||
|
||||
// ParameterMetaData FUNCTIONS //////////////////////////////////
|
||||
|
||||
public ParameterMetaData getParameterMetaData() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public int getParameterCount() throws SQLException {
|
||||
checkOpen();
|
||||
return paramCount;
|
||||
}
|
||||
|
||||
public String getParameterClassName(int param) throws SQLException {
|
||||
checkOpen();
|
||||
return "java.lang.String";
|
||||
}
|
||||
|
||||
public String getParameterTypeName(int pos) {
|
||||
return "VARCHAR";
|
||||
}
|
||||
|
||||
public int getParameterType(int pos) {
|
||||
return Types.VARCHAR;
|
||||
}
|
||||
|
||||
public int getParameterMode(int pos) {
|
||||
return parameterModeIn;
|
||||
}
|
||||
|
||||
public int getPrecision(int pos) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int getScale(int pos) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public int isNullable(int pos) {
|
||||
return parameterNullable;
|
||||
}
|
||||
|
||||
public boolean isSigned(int pos) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public Statement getStatement() {
|
||||
return this;
|
||||
}
|
||||
|
||||
// PARAMETER FUNCTIONS //////////////////////////////////////////
|
||||
|
||||
private void batch(int pos, Object value) throws SQLException {
|
||||
checkOpen();
|
||||
if (batch == null)
|
||||
batch = new Object[paramCount];
|
||||
batch[batchPos + pos - 1] = value;
|
||||
}
|
||||
|
||||
public void setBoolean(int pos, boolean value) throws SQLException {
|
||||
setInt(pos, value ? 1 : 0);
|
||||
}
|
||||
|
||||
public void setByte(int pos, byte value) throws SQLException {
|
||||
setInt(pos, value);
|
||||
}
|
||||
|
||||
public void setBytes(int pos, byte[] value) throws SQLException {
|
||||
batch(pos, value);
|
||||
}
|
||||
|
||||
public void setDouble(int pos, double value) throws SQLException {
|
||||
batch(pos, new Double(value));
|
||||
}
|
||||
|
||||
public void setFloat(int pos, float value) throws SQLException {
|
||||
batch(pos, new Float(value));
|
||||
}
|
||||
|
||||
public void setInt(int pos, int value) throws SQLException {
|
||||
batch(pos, new Integer(value));
|
||||
}
|
||||
|
||||
public void setLong(int pos, long value) throws SQLException {
|
||||
batch(pos, new Long(value));
|
||||
}
|
||||
|
||||
public void setNull(int pos, int u1) throws SQLException {
|
||||
setNull(pos, u1, null);
|
||||
}
|
||||
|
||||
public void setNull(int pos, int u1, String u2) throws SQLException {
|
||||
batch(pos, null);
|
||||
}
|
||||
|
||||
public void setObject(int pos, Object value) throws SQLException {
|
||||
if (value == null)
|
||||
batch(pos, null);
|
||||
else if (value instanceof java.util.Date)
|
||||
batch(pos, new Long(((java.util.Date) value).getTime()));
|
||||
else if (value instanceof Date)
|
||||
batch(pos, new Long(((Date) value).getTime()));
|
||||
else if (value instanceof Time)
|
||||
batch(pos, new Long(((Time) value).getTime()));
|
||||
else if (value instanceof Timestamp)
|
||||
batch(pos, new Long(((Timestamp) value).getTime()));
|
||||
else if (value instanceof Long)
|
||||
batch(pos, value);
|
||||
else if (value instanceof Integer)
|
||||
batch(pos, value);
|
||||
else if (value instanceof Short)
|
||||
batch(pos, new Integer(((Short) value).intValue()));
|
||||
else if (value instanceof Float)
|
||||
batch(pos, value);
|
||||
else if (value instanceof Double)
|
||||
batch(pos, value);
|
||||
else if (value instanceof Boolean)
|
||||
setBoolean(pos, ((Boolean) value).booleanValue());
|
||||
else if (value instanceof byte[])
|
||||
batch(pos, value);
|
||||
else
|
||||
batch(pos, value.toString());
|
||||
}
|
||||
|
||||
public void setObject(int p, Object v, int t) throws SQLException {
|
||||
setObject(p, v);
|
||||
}
|
||||
|
||||
public void setObject(int p, Object v, int t, int s) throws SQLException {
|
||||
setObject(p, v);
|
||||
}
|
||||
|
||||
public void setShort(int pos, short value) throws SQLException {
|
||||
setInt(pos, value);
|
||||
}
|
||||
|
||||
public void setString(int pos, String value) throws SQLException {
|
||||
batch(pos, value);
|
||||
}
|
||||
|
||||
public void setCharacterStream(int pos, Reader reader, int length) throws SQLException {
|
||||
try {
|
||||
// copy chars from reader to StringBuffer
|
||||
StringBuffer sb = new StringBuffer();
|
||||
char[] cbuf = new char[8192];
|
||||
int cnt;
|
||||
|
||||
while ((cnt = reader.read(cbuf)) > 0) {
|
||||
sb.append(cbuf, 0, cnt);
|
||||
}
|
||||
|
||||
// set as string
|
||||
setString(pos, sb.toString());
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new SQLException("Cannot read from character stream, exception message: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public void setDate(int pos, Date x) throws SQLException {
|
||||
setObject(pos, x);
|
||||
}
|
||||
|
||||
public void setDate(int pos, Date x, Calendar cal) throws SQLException {
|
||||
setObject(pos, x);
|
||||
}
|
||||
|
||||
public void setTime(int pos, Time x) throws SQLException {
|
||||
setObject(pos, x);
|
||||
}
|
||||
|
||||
public void setTime(int pos, Time x, Calendar cal) throws SQLException {
|
||||
setObject(pos, x);
|
||||
}
|
||||
|
||||
public void setTimestamp(int pos, Timestamp x) throws SQLException {
|
||||
setObject(pos, x);
|
||||
}
|
||||
|
||||
public void setTimestamp(int pos, Timestamp x, Calendar cal) throws SQLException {
|
||||
setObject(pos, x);
|
||||
}
|
||||
|
||||
public ResultSetMetaData getMetaData() throws SQLException {
|
||||
checkOpen();
|
||||
return rs;
|
||||
}
|
||||
|
||||
// UNUSED ///////////////////////////////////////////////////////
|
||||
|
||||
@Override
|
||||
public boolean execute(String sql) throws SQLException {
|
||||
throw unused();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int executeUpdate(String sql) throws SQLException {
|
||||
throw unused();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet executeQuery(String sql) throws SQLException {
|
||||
throw unused();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addBatch(String sql) throws SQLException {
|
||||
throw unused();
|
||||
}
|
||||
|
||||
private SQLException unused() {
|
||||
return new SQLException("not supported by PreparedStatment");
|
||||
}
|
||||
}
|
@ -1,540 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
package org.sqlite;
|
||||
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
import java.sql.Date;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Statement;
|
||||
import java.sql.Time;
|
||||
import java.sql.Timestamp;
|
||||
import java.sql.Types;
|
||||
import java.util.Calendar;
|
||||
|
||||
/**
|
||||
* Implements a JDBC ResultSet.
|
||||
*/
|
||||
final class RS extends Unused implements ResultSet, ResultSetMetaData, Codes
|
||||
{
|
||||
private final Stmt stmt;
|
||||
private final DB db;
|
||||
|
||||
boolean open = false; // true means have results and can iterate them
|
||||
int maxRows; // max. number of rows as set by a Statement
|
||||
String[] cols = null; // if null, the RS is closed()
|
||||
String[] colsMeta = null; // same as cols, but used by Meta interface
|
||||
boolean[][] meta = null;
|
||||
|
||||
private int limitRows; // 0 means no limit, must check against maxRows
|
||||
private int row = 0; // number of current row, starts at 1 (0 is for before loading data)
|
||||
private int lastCol; // last column accessed, for wasNull(). -1 if none
|
||||
|
||||
RS(Stmt stmt) {
|
||||
this.stmt = stmt;
|
||||
this.db = stmt.db;
|
||||
}
|
||||
|
||||
// INTERNAL FUNCTIONS ///////////////////////////////////////////
|
||||
|
||||
boolean isOpen() {
|
||||
return open;
|
||||
}
|
||||
|
||||
/* Throws SQLException if ResultSet is not open. */
|
||||
void checkOpen() throws SQLException {
|
||||
if (!open)
|
||||
throw new SQLException("ResultSet closed");
|
||||
}
|
||||
|
||||
// takes col in [1,x] form, returns in [0,x-1] form
|
||||
private int checkCol(int col) throws SQLException {
|
||||
if (colsMeta == null)
|
||||
throw new IllegalStateException("SQLite JDBC: inconsistent internal state");
|
||||
if (col < 1 || col > colsMeta.length)
|
||||
throw new SQLException("column " + col + " out of bounds [1," + colsMeta.length + "]");
|
||||
return --col;
|
||||
}
|
||||
|
||||
// takes col in [1,x] form, marks it as last accessed and returns [0,x-1]
|
||||
private int markCol(int col) throws SQLException {
|
||||
checkOpen();
|
||||
checkCol(col);
|
||||
lastCol = col;
|
||||
return --col;
|
||||
}
|
||||
|
||||
private void checkMeta() throws SQLException {
|
||||
checkCol(1);
|
||||
if (meta == null)
|
||||
meta = db.column_metadata(stmt.pointer);
|
||||
}
|
||||
|
||||
// ResultSet Functions //////////////////////////////////////////
|
||||
|
||||
public void close() throws SQLException {
|
||||
cols = null;
|
||||
colsMeta = null;
|
||||
meta = null;
|
||||
open = false;
|
||||
limitRows = 0;
|
||||
row = 0;
|
||||
lastCol = -1;
|
||||
|
||||
if (stmt == null)
|
||||
return;
|
||||
if (stmt != null && stmt.pointer != 0)
|
||||
db.reset(stmt.pointer);
|
||||
}
|
||||
|
||||
// returns col in [1,x] form
|
||||
public int findColumn(String col) throws SQLException {
|
||||
checkOpen();
|
||||
int c = -1;
|
||||
for (int i = 0; i < cols.length; i++) {
|
||||
if (col.equalsIgnoreCase(cols[i])
|
||||
|| (cols[i].toUpperCase().endsWith(col.toUpperCase()) && cols[i].charAt(cols[i].length()
|
||||
- col.length()) == '.')) {
|
||||
if (c == -1)
|
||||
c = i;
|
||||
else
|
||||
throw new SQLException("ambiguous column: '" + col + "'");
|
||||
}
|
||||
}
|
||||
if (c == -1)
|
||||
throw new SQLException("no such column: '" + col + "'");
|
||||
else
|
||||
return c + 1;
|
||||
}
|
||||
|
||||
public boolean next() throws SQLException {
|
||||
if (!open)
|
||||
return false; // finished ResultSet
|
||||
lastCol = -1;
|
||||
|
||||
// first row is loaded by execute(), so do not step() again
|
||||
if (row == 0) {
|
||||
row++;
|
||||
return true;
|
||||
}
|
||||
|
||||
// check if we are row limited by the statement or the ResultSet
|
||||
if (maxRows != 0 && row > maxRows)
|
||||
return false;
|
||||
|
||||
// do the real work
|
||||
int statusCode = db.step(stmt.pointer);
|
||||
switch (statusCode) {
|
||||
case SQLITE_DONE:
|
||||
close(); // agressive closing to avoid writer starvation
|
||||
return false;
|
||||
case SQLITE_ROW:
|
||||
row++;
|
||||
return true;
|
||||
case SQLITE_BUSY:
|
||||
default:
|
||||
db.throwex(statusCode);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public int getType() throws SQLException {
|
||||
return TYPE_FORWARD_ONLY;
|
||||
}
|
||||
|
||||
public int getFetchSize() throws SQLException {
|
||||
return limitRows;
|
||||
}
|
||||
|
||||
public void setFetchSize(int rows) throws SQLException {
|
||||
if (0 > rows || (maxRows != 0 && rows > maxRows))
|
||||
throw new SQLException("fetch size " + rows + " out of bounds " + maxRows);
|
||||
limitRows = rows;
|
||||
}
|
||||
|
||||
public int getFetchDirection() throws SQLException {
|
||||
checkOpen();
|
||||
return ResultSet.FETCH_FORWARD;
|
||||
}
|
||||
|
||||
public void setFetchDirection(int d) throws SQLException {
|
||||
checkOpen();
|
||||
if (d != ResultSet.FETCH_FORWARD)
|
||||
throw new SQLException("only FETCH_FORWARD direction supported");
|
||||
}
|
||||
|
||||
public boolean isAfterLast() throws SQLException {
|
||||
return !open;
|
||||
}
|
||||
|
||||
public boolean isBeforeFirst() throws SQLException {
|
||||
return open && row == 0;
|
||||
}
|
||||
|
||||
public boolean isFirst() throws SQLException {
|
||||
return row == 1;
|
||||
}
|
||||
|
||||
public boolean isLast() throws SQLException { // FIXME
|
||||
throw new SQLException("function not yet implemented for SQLite");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws SQLException {
|
||||
close();
|
||||
}
|
||||
|
||||
public int getRow() throws SQLException {
|
||||
return row;
|
||||
}
|
||||
|
||||
public boolean wasNull() throws SQLException {
|
||||
return db.column_type(stmt.pointer, markCol(lastCol)) == SQLITE_NULL;
|
||||
}
|
||||
|
||||
// DATA ACCESS FUNCTIONS ////////////////////////////////////////
|
||||
|
||||
public boolean getBoolean(int col) throws SQLException {
|
||||
return getInt(col) == 0 ? false : true;
|
||||
}
|
||||
|
||||
public boolean getBoolean(String col) throws SQLException {
|
||||
return getBoolean(findColumn(col));
|
||||
}
|
||||
|
||||
public byte getByte(int col) throws SQLException {
|
||||
return (byte) getInt(col);
|
||||
}
|
||||
|
||||
public byte getByte(String col) throws SQLException {
|
||||
return getByte(findColumn(col));
|
||||
}
|
||||
|
||||
public byte[] getBytes(int col) throws SQLException {
|
||||
return db.column_blob(stmt.pointer, markCol(col));
|
||||
}
|
||||
|
||||
public byte[] getBytes(String col) throws SQLException {
|
||||
return getBytes(findColumn(col));
|
||||
}
|
||||
|
||||
public Reader getCharacterStream(int col) throws SQLException {
|
||||
return new StringReader(getString(col));
|
||||
}
|
||||
|
||||
public Reader getCharacterStream(String col) throws SQLException {
|
||||
return getCharacterStream(findColumn(col));
|
||||
}
|
||||
|
||||
public Date getDate(int col) throws SQLException {
|
||||
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
||||
return null;
|
||||
return new Date(db.column_long(stmt.pointer, markCol(col)));
|
||||
}
|
||||
|
||||
public Date getDate(int col, Calendar cal) throws SQLException {
|
||||
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
||||
return null;
|
||||
if (cal == null)
|
||||
return getDate(col);
|
||||
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
|
||||
return new Date(cal.getTime().getTime());
|
||||
}
|
||||
|
||||
public Date getDate(String col) throws SQLException {
|
||||
return getDate(findColumn(col), Calendar.getInstance());
|
||||
}
|
||||
|
||||
public Date getDate(String col, Calendar cal) throws SQLException {
|
||||
return getDate(findColumn(col), cal);
|
||||
}
|
||||
|
||||
public double getDouble(int col) throws SQLException {
|
||||
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
||||
return 0;
|
||||
return db.column_double(stmt.pointer, markCol(col));
|
||||
}
|
||||
|
||||
public double getDouble(String col) throws SQLException {
|
||||
return getDouble(findColumn(col));
|
||||
}
|
||||
|
||||
public float getFloat(int col) throws SQLException {
|
||||
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
||||
return 0;
|
||||
return (float) db.column_double(stmt.pointer, markCol(col));
|
||||
}
|
||||
|
||||
public float getFloat(String col) throws SQLException {
|
||||
return getFloat(findColumn(col));
|
||||
}
|
||||
|
||||
public int getInt(int col) throws SQLException {
|
||||
return db.column_int(stmt.pointer, markCol(col));
|
||||
}
|
||||
|
||||
public int getInt(String col) throws SQLException {
|
||||
return getInt(findColumn(col));
|
||||
}
|
||||
|
||||
public long getLong(int col) throws SQLException {
|
||||
return db.column_long(stmt.pointer, markCol(col));
|
||||
}
|
||||
|
||||
public long getLong(String col) throws SQLException {
|
||||
return getLong(findColumn(col));
|
||||
}
|
||||
|
||||
public short getShort(int col) throws SQLException {
|
||||
return (short) getInt(col);
|
||||
}
|
||||
|
||||
public short getShort(String col) throws SQLException {
|
||||
return getShort(findColumn(col));
|
||||
}
|
||||
|
||||
public String getString(int col) throws SQLException {
|
||||
return db.column_text(stmt.pointer, markCol(col));
|
||||
}
|
||||
|
||||
public String getString(String col) throws SQLException {
|
||||
return getString(findColumn(col));
|
||||
}
|
||||
|
||||
public Time getTime(int col) throws SQLException {
|
||||
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
||||
return null;
|
||||
return new Time(db.column_long(stmt.pointer, markCol(col)));
|
||||
}
|
||||
|
||||
public Time getTime(int col, Calendar cal) throws SQLException {
|
||||
if (cal == null)
|
||||
return getTime(col);
|
||||
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
||||
return null;
|
||||
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
|
||||
return new Time(cal.getTime().getTime());
|
||||
}
|
||||
|
||||
public Time getTime(String col) throws SQLException {
|
||||
return getTime(findColumn(col));
|
||||
}
|
||||
|
||||
public Time getTime(String col, Calendar cal) throws SQLException {
|
||||
return getTime(findColumn(col), cal);
|
||||
}
|
||||
|
||||
public Timestamp getTimestamp(int col) throws SQLException {
|
||||
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
||||
return null;
|
||||
return new Timestamp(db.column_long(stmt.pointer, markCol(col)));
|
||||
}
|
||||
|
||||
public Timestamp getTimestamp(int col, Calendar cal) throws SQLException {
|
||||
if (cal == null)
|
||||
return getTimestamp(col);
|
||||
if (db.column_type(stmt.pointer, markCol(col)) == SQLITE_NULL)
|
||||
return null;
|
||||
cal.setTimeInMillis(db.column_long(stmt.pointer, markCol(col)));
|
||||
return new Timestamp(cal.getTime().getTime());
|
||||
}
|
||||
|
||||
public Timestamp getTimestamp(String col) throws SQLException {
|
||||
return getTimestamp(findColumn(col));
|
||||
}
|
||||
|
||||
public Timestamp getTimestamp(String c, Calendar ca) throws SQLException {
|
||||
return getTimestamp(findColumn(c), ca);
|
||||
}
|
||||
|
||||
public Object getObject(int col) throws SQLException {
|
||||
switch (db.column_type(stmt.pointer, checkCol(col))) {
|
||||
case SQLITE_INTEGER:
|
||||
long val = getLong(col);
|
||||
if (val > Integer.MAX_VALUE || val < Integer.MIN_VALUE)
|
||||
return new Long(val);
|
||||
else
|
||||
return new Integer((int) val);
|
||||
case SQLITE_FLOAT:
|
||||
return new Double(getDouble(col));
|
||||
case SQLITE_BLOB:
|
||||
return getBytes(col);
|
||||
case SQLITE_NULL:
|
||||
return null;
|
||||
case SQLITE_TEXT:
|
||||
default:
|
||||
return getString(col);
|
||||
}
|
||||
}
|
||||
|
||||
public Object getObject(String col) throws SQLException {
|
||||
return getObject(findColumn(col));
|
||||
}
|
||||
|
||||
public Statement getStatement() {
|
||||
return stmt;
|
||||
}
|
||||
|
||||
public String getCursorName() throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clearWarnings() throws SQLException {}
|
||||
|
||||
// ResultSetMetaData Functions //////////////////////////////////
|
||||
|
||||
// we do not need to check the RS is open, only that colsMeta
|
||||
// is not null, done with checkCol(int).
|
||||
|
||||
public ResultSetMetaData getMetaData() throws SQLException {
|
||||
return this;
|
||||
}
|
||||
|
||||
public String getCatalogName(int col) throws SQLException {
|
||||
return db.column_table_name(stmt.pointer, checkCol(col));
|
||||
}
|
||||
|
||||
public String getColumnClassName(int col) throws SQLException {
|
||||
checkCol(col);
|
||||
return "java.lang.Object";
|
||||
}
|
||||
|
||||
public int getColumnCount() throws SQLException {
|
||||
checkCol(1);
|
||||
return colsMeta.length;
|
||||
}
|
||||
|
||||
public int getColumnDisplaySize(int col) throws SQLException {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
public String getColumnLabel(int col) throws SQLException {
|
||||
return getColumnName(col);
|
||||
}
|
||||
|
||||
public String getColumnName(int col) throws SQLException {
|
||||
return db.column_name(stmt.pointer, checkCol(col));
|
||||
}
|
||||
|
||||
public int getColumnType(int col) throws SQLException {
|
||||
switch (db.column_type(stmt.pointer, checkCol(col))) {
|
||||
case SQLITE_INTEGER:
|
||||
return Types.INTEGER;
|
||||
case SQLITE_FLOAT:
|
||||
return Types.FLOAT;
|
||||
case SQLITE_BLOB:
|
||||
return Types.BLOB;
|
||||
case SQLITE_NULL:
|
||||
return Types.NULL;
|
||||
case SQLITE_TEXT:
|
||||
default:
|
||||
return Types.VARCHAR;
|
||||
}
|
||||
}
|
||||
|
||||
public String getColumnTypeName(int col) throws SQLException {
|
||||
switch (db.column_type(stmt.pointer, checkCol(col))) {
|
||||
case SQLITE_INTEGER:
|
||||
return "integer";
|
||||
case SQLITE_FLOAT:
|
||||
return "float";
|
||||
case SQLITE_BLOB:
|
||||
return "blob";
|
||||
case SQLITE_NULL:
|
||||
return "null";
|
||||
case SQLITE_TEXT:
|
||||
default:
|
||||
return "text";
|
||||
}
|
||||
}
|
||||
|
||||
public int getPrecision(int col) throws SQLException {
|
||||
return 0;
|
||||
} // FIXME
|
||||
|
||||
public int getScale(int col) throws SQLException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public String getSchemaName(int col) throws SQLException {
|
||||
return "";
|
||||
}
|
||||
|
||||
public String getTableName(int col) throws SQLException {
|
||||
return db.column_table_name(stmt.pointer, checkCol(col));
|
||||
}
|
||||
|
||||
public int isNullable(int col) throws SQLException {
|
||||
checkMeta();
|
||||
return meta[checkCol(col)][1] ? columnNoNulls : columnNullable;
|
||||
}
|
||||
|
||||
public boolean isAutoIncrement(int col) throws SQLException {
|
||||
checkMeta();
|
||||
return meta[checkCol(col)][2];
|
||||
}
|
||||
|
||||
public boolean isCaseSensitive(int col) throws SQLException {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isCurrency(int col) throws SQLException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isDefinitelyWritable(int col) throws SQLException {
|
||||
return true;
|
||||
} // FIXME: check db file constraints?
|
||||
|
||||
public boolean isReadOnly(int col) throws SQLException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isSearchable(int col) throws SQLException {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isSigned(int col) throws SQLException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean isWritable(int col) throws SQLException {
|
||||
return true;
|
||||
}
|
||||
|
||||
public int getConcurrency() throws SQLException {
|
||||
return CONCUR_READ_ONLY;
|
||||
}
|
||||
|
||||
public boolean rowDeleted() throws SQLException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean rowInserted() throws SQLException {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean rowUpdated() throws SQLException {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,102 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
* Copyright 2009 Taro L. Saito
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*--------------------------------------------------------------------------*/
|
||||
//--------------------------------------
|
||||
// sqlite-jdbc Project
|
||||
//
|
||||
// ResourceFinder.java
|
||||
// Since: Apr 28, 2009
|
||||
//
|
||||
// $URL$
|
||||
// $Author$
|
||||
//--------------------------------------
|
||||
package org.sqlite;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* Resource address finder for files inside the jar file
|
||||
*
|
||||
* @author leo
|
||||
*
|
||||
*/
|
||||
public class ResourceFinder
|
||||
{
|
||||
/**
|
||||
* Gets the {@link URL} of the file resource
|
||||
*
|
||||
* @param referenceClass
|
||||
* the base class for finding resources files. This method will
|
||||
* search the package containing the given referenceClass.
|
||||
* @param resourceFileName
|
||||
* the resource file name relative to the package of the
|
||||
* referenceClass
|
||||
* @return the URL of the file resource
|
||||
*/
|
||||
public static URL find(Class< ? > referenceClass, String resourceFileName)
|
||||
{
|
||||
return find(referenceClass.getClassLoader(), referenceClass.getPackage(), resourceFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the {@link URL} of the resource
|
||||
*
|
||||
* @param basePackage
|
||||
* the base package to find the resource
|
||||
* @param resourceFileName
|
||||
* the resource file name relative to the package folder
|
||||
* @return the URL of the specified resource
|
||||
*/
|
||||
public static URL find(ClassLoader classLoader, Package basePackage, String resourceFileName)
|
||||
{
|
||||
return find(classLoader, basePackage.getName(), resourceFileName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the {@link URL} of the resource
|
||||
*
|
||||
* @param packageName
|
||||
* the base package name to find the resource
|
||||
* @param resourceFileName
|
||||
* the resource file name relative to the package folder
|
||||
* @return the URL of the specified resource
|
||||
*/
|
||||
public static URL find(ClassLoader classLoader, String packageName, String resourceFileName)
|
||||
{
|
||||
String packagePath = packagePath(packageName);
|
||||
String resourcePath = packagePath + resourceFileName;
|
||||
if (!resourcePath.startsWith("/"))
|
||||
resourcePath = "/" + resourcePath;
|
||||
|
||||
return classLoader.getResource(resourcePath);
|
||||
}
|
||||
|
||||
private static String packagePath(Class< ? > referenceClass)
|
||||
{
|
||||
return packagePath(referenceClass.getPackage());
|
||||
}
|
||||
|
||||
private static String packagePath(Package basePackage)
|
||||
{
|
||||
return packagePath(basePackage.getName());
|
||||
}
|
||||
|
||||
private static String packagePath(String packageName)
|
||||
{
|
||||
String packageAsPath = packageName.replaceAll("\\.", "/");
|
||||
return packageAsPath.endsWith("/") ? packageAsPath : packageAsPath + "/";
|
||||
}
|
||||
|
||||
}
|
@ -1,449 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
* Copyright 2009 Taro L. Saito
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*--------------------------------------------------------------------------*/
|
||||
//--------------------------------------
|
||||
// sqlite-jdbc Project
|
||||
//
|
||||
// SQLiteConfig.java
|
||||
// Since: Dec 8, 2009
|
||||
//
|
||||
// $URL$
|
||||
// $Author$
|
||||
//--------------------------------------
|
||||
package org.sqlite;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.DriverManager;
|
||||
import java.sql.DriverPropertyInfo;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Statement;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* SQLite Configuration
|
||||
*
|
||||
* See also http://www.sqlite.org/pragma.html
|
||||
*
|
||||
* @author leo
|
||||
*
|
||||
*/
|
||||
public class SQLiteConfig
|
||||
{
|
||||
private final Properties pragmaTable;
|
||||
private int openModeFlag = 0x00;
|
||||
|
||||
public SQLiteConfig() {
|
||||
this(new Properties());
|
||||
}
|
||||
|
||||
public SQLiteConfig(Properties prop) {
|
||||
this.pragmaTable = prop;
|
||||
String openMode = pragmaTable.getProperty(Pragma.OPEN_MODE.pragmaName);
|
||||
if (openMode != null) {
|
||||
openModeFlag = Integer.parseInt(openMode);
|
||||
}
|
||||
else {
|
||||
// set the default open mode of SQLite3
|
||||
setOpenMode(SQLiteOpenMode.READWRITE);
|
||||
setOpenMode(SQLiteOpenMode.CREATE);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new JDBC connection using the current configuration
|
||||
*
|
||||
* @return
|
||||
* @throws SQLException
|
||||
*/
|
||||
public Connection createConnection(String url) throws SQLException {
|
||||
return JDBC.createConnection(url, toProperties());
|
||||
}
|
||||
|
||||
/**
|
||||
* Apply the current configuration to connection
|
||||
*
|
||||
* @param conn
|
||||
* @throws SQLException
|
||||
*/
|
||||
public void apply(Connection conn) throws SQLException {
|
||||
|
||||
HashSet<String> pragmaParams = new HashSet<String>();
|
||||
for (Pragma each : Pragma.values()) {
|
||||
pragmaParams.add(each.pragmaName);
|
||||
}
|
||||
|
||||
pragmaParams.remove(Pragma.OPEN_MODE.pragmaName);
|
||||
pragmaParams.remove(Pragma.SHARED_CACHE.pragmaName);
|
||||
pragmaParams.remove(Pragma.LOAD_EXTENSION.pragmaName);
|
||||
|
||||
Statement stat = conn.createStatement();
|
||||
try {
|
||||
int count = 0;
|
||||
for (Object each : pragmaTable.keySet()) {
|
||||
String key = each.toString();
|
||||
if (!pragmaParams.contains(key))
|
||||
continue;
|
||||
|
||||
String value = pragmaTable.getProperty(key);
|
||||
if (value != null) {
|
||||
String sql = String.format("pragma %s=%s", key, value);
|
||||
stat.addBatch(sql);
|
||||
count++;
|
||||
}
|
||||
}
|
||||
if (count > 0)
|
||||
stat.executeBatch();
|
||||
}
|
||||
finally {
|
||||
if (stat != null)
|
||||
stat.close();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void set(Pragma pragma, boolean flag) {
|
||||
setPragma(pragma, Boolean.toString(flag));
|
||||
}
|
||||
|
||||
private void set(Pragma pragma, int num) {
|
||||
setPragma(pragma, Integer.toString(num));
|
||||
}
|
||||
|
||||
private boolean getBoolean(Pragma pragma, String defaultValue) {
|
||||
return Boolean.parseBoolean(pragmaTable.getProperty(pragma.pragmaName, defaultValue));
|
||||
}
|
||||
|
||||
public boolean isEnabledSharedCache() {
|
||||
return getBoolean(Pragma.SHARED_CACHE, "false");
|
||||
}
|
||||
|
||||
public boolean isEnabledLoadExtension() {
|
||||
return getBoolean(Pragma.LOAD_EXTENSION, "false");
|
||||
}
|
||||
|
||||
public int getOpenModeFlags() {
|
||||
return openModeFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a pragma value. To take effect the pragma settings,
|
||||
*
|
||||
* @param pragma
|
||||
* @param value
|
||||
*/
|
||||
public void setPragma(Pragma pragma, String value) {
|
||||
pragmaTable.put(pragma.pragmaName, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert this SQLiteConfig settings into a Properties object, that can be
|
||||
* passed to the {@link DriverManager#getConnection(String, Properties)}.
|
||||
*
|
||||
* @return properties representation of this configuration
|
||||
*/
|
||||
public Properties toProperties() {
|
||||
pragmaTable.setProperty(Pragma.OPEN_MODE.pragmaName, Integer.toString(openModeFlag));
|
||||
|
||||
return pragmaTable;
|
||||
}
|
||||
|
||||
static DriverPropertyInfo[] getDriverPropertyInfo() {
|
||||
Pragma[] pragma = Pragma.values();
|
||||
DriverPropertyInfo[] result = new DriverPropertyInfo[pragma.length];
|
||||
int index = 0;
|
||||
for (Pragma p : Pragma.values()) {
|
||||
DriverPropertyInfo di = new DriverPropertyInfo(p.pragmaName, null);
|
||||
di.choices = p.choices;
|
||||
di.description = p.description;
|
||||
di.required = false;
|
||||
result[index++] = di;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static final String[] OnOff = new String[] { "true", "false" };
|
||||
|
||||
private static enum Pragma {
|
||||
|
||||
// Parameters requiring SQLite3 API invocation
|
||||
OPEN_MODE("open_mode", "Database open-mode flag", null),
|
||||
SHARED_CACHE("shared_cache", "Enablse SQLite Shared-Cache mode, native driver only", OnOff),
|
||||
LOAD_EXTENSION("enable_load_extension", "Enable SQLite load_extention() function, native driver only", OnOff),
|
||||
|
||||
// Pragmas that can be set after opening the database
|
||||
CACHE_SIZE("cache_size"),
|
||||
CASE_SENSITIVE_LIKE("case_sensitive_like", OnOff),
|
||||
COUNT_CHANGES("count_changes", OnOff),
|
||||
DEFAULT_CACHE_SIZE("default_cache_size"),
|
||||
EMPTY_RESULT_CALLBACKS("empty_result_callback", OnOff),
|
||||
ENCODING("encoding", toStringArray(Encoding.values())),
|
||||
FOREIGN_KEYS("foreign_keys", OnOff),
|
||||
FULL_COLUMN_NAMES("full_column_names", OnOff),
|
||||
FULL_SYNC("fullsync", OnOff),
|
||||
INCREMENTAL_VACUUM("incremental_vacuum"),
|
||||
JOURNAL_MODE("journal_mode", toStringArray(JournalMode.values())),
|
||||
JOURNAL_SIZE_LIMIT("journal_size_limit"),
|
||||
LEGACY_FILE_FORMAT("legacy_file_format", OnOff),
|
||||
LOCKING_MODE("locking_mode", toStringArray(LockingMode.values())),
|
||||
PAGE_SIZE("page_size"),
|
||||
MAX_PAGE_COUNT("max_page_count"),
|
||||
READ_UNCOMMITED("read_uncommited", OnOff),
|
||||
RECURSIVE_TRIGGERS("recursive_triggers", OnOff),
|
||||
REVERSE_UNORDERED_SELECTS("reverse_unordered_selects", OnOff),
|
||||
SHORT_COLUMN_NAMES("short_column_names", OnOff),
|
||||
SYNCHRONOUS("synchronous", toStringArray(SynchronousMode.values())),
|
||||
TEMP_STORE("temp_store", toStringArray(TempStore.values())),
|
||||
TEMP_STORE_DIRECTORY("temp_store_directory"),
|
||||
USER_VERSION("user_version");
|
||||
|
||||
public final String pragmaName;
|
||||
public final String[] choices;
|
||||
public final String description;
|
||||
|
||||
private Pragma(String pragmaName) {
|
||||
this(pragmaName, null);
|
||||
}
|
||||
|
||||
private Pragma(String pragmaName, String[] choices) {
|
||||
this(pragmaName, null, null);
|
||||
}
|
||||
|
||||
private Pragma(String pragmaName, String description, String[] choices) {
|
||||
this.pragmaName = pragmaName;
|
||||
this.description = description;
|
||||
this.choices = choices;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the database open mode
|
||||
*
|
||||
* @param mode
|
||||
*/
|
||||
public void setOpenMode(SQLiteOpenMode mode) {
|
||||
openModeFlag |= mode.flag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the specified database open mode flag
|
||||
*
|
||||
* @param mode
|
||||
*/
|
||||
public void resetOpenMode(SQLiteOpenMode mode) {
|
||||
openModeFlag &= ~mode.flag;
|
||||
}
|
||||
|
||||
public void setSharedCache(boolean enable) {
|
||||
set(Pragma.SHARED_CACHE, enable);
|
||||
}
|
||||
|
||||
public void enableLoadExtension(boolean enable) {
|
||||
set(Pragma.LOAD_EXTENSION, enable);
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
if (readOnly) {
|
||||
setOpenMode(SQLiteOpenMode.READONLY);
|
||||
resetOpenMode(SQLiteOpenMode.READWRITE);
|
||||
}
|
||||
else {
|
||||
setOpenMode(SQLiteOpenMode.READWRITE);
|
||||
resetOpenMode(SQLiteOpenMode.READONLY);
|
||||
}
|
||||
}
|
||||
|
||||
public void setCacheSize(int numberOfPages) {
|
||||
set(Pragma.CACHE_SIZE, numberOfPages);
|
||||
}
|
||||
|
||||
public void enableCaseSensitiveLike(boolean enable) {
|
||||
set(Pragma.CASE_SENSITIVE_LIKE, enable);
|
||||
}
|
||||
|
||||
public void enableCountChanges(boolean enable) {
|
||||
set(Pragma.COUNT_CHANGES, enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the cache size persistently across database connections
|
||||
*
|
||||
* @param numberOfPages
|
||||
*/
|
||||
public void setDefaultCacheSize(int numberOfPages) {
|
||||
set(Pragma.DEFAULT_CACHE_SIZE, numberOfPages);
|
||||
}
|
||||
|
||||
public void enableEmptyResultCallBacks(boolean enable) {
|
||||
set(Pragma.EMPTY_RESULT_CALLBACKS, enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* The common interface for retrieving the available pragma parameter
|
||||
* values.
|
||||
*
|
||||
* @author leo
|
||||
*
|
||||
*/
|
||||
private static interface PragmaValue
|
||||
{
|
||||
public String getValue();
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert the given Enum values to a string array
|
||||
*
|
||||
* @param list
|
||||
* @return
|
||||
*/
|
||||
private static String[] toStringArray(PragmaValue[] list) {
|
||||
String[] result = new String[list.length];
|
||||
for (int i = 0; i < list.length; i++) {
|
||||
result[i] = list[i].getValue();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static enum Encoding implements PragmaValue {
|
||||
UTF8("UTF-8"), UTF16("UTF-16"), UTF16_LITTLE_ENDIAN("UTF-16le"), UTF16_BIG_ENDIAN("UTF-16be");
|
||||
public final String typeName;
|
||||
|
||||
private Encoding(String typeName) {
|
||||
this.typeName = typeName;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return typeName;
|
||||
}
|
||||
}
|
||||
|
||||
public static enum JournalMode implements PragmaValue {
|
||||
DELETE, TRUNCATE, PERSIST, MEMORY, OFF;
|
||||
|
||||
public String getValue() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
public void setEncoding(Encoding encoding) {
|
||||
setPragma(Pragma.ENCODING, encoding.typeName);
|
||||
}
|
||||
|
||||
public void enforceForeignKeys(boolean enforce) {
|
||||
set(Pragma.FOREIGN_KEYS, enforce);
|
||||
}
|
||||
|
||||
public void enableFullColumnNames(boolean enable) {
|
||||
set(Pragma.FULL_COLUMN_NAMES, enable);
|
||||
}
|
||||
|
||||
public void enableFullSync(boolean enable) {
|
||||
set(Pragma.FULL_SYNC, enable);
|
||||
}
|
||||
|
||||
public void incrementalVacuum(int numberOfPagesToBeRemoved) {
|
||||
set(Pragma.INCREMENTAL_VACUUM, numberOfPagesToBeRemoved);
|
||||
}
|
||||
|
||||
public void setJournalMode(JournalMode mode) {
|
||||
setPragma(Pragma.JOURNAL_MODE, mode.name());
|
||||
}
|
||||
|
||||
// public void setJournalMode(String databaseName, JournalMode mode) {
|
||||
// setPragma(databaseName, Pragma.JOURNAL_MODE, mode.name());
|
||||
// }
|
||||
|
||||
public void setJounalSizeLimit(int limit) {
|
||||
set(Pragma.JOURNAL_SIZE_LIMIT, limit);
|
||||
}
|
||||
|
||||
public void useLegacyFileFormat(boolean use) {
|
||||
set(Pragma.LEGACY_FILE_FORMAT, use);
|
||||
}
|
||||
|
||||
public static enum LockingMode implements PragmaValue {
|
||||
NORMAL, EXCLUSIVE;
|
||||
public String getValue() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
public void setLockingMode(LockingMode mode) {
|
||||
setPragma(Pragma.LOCKING_MODE, mode.name());
|
||||
}
|
||||
|
||||
// public void setLockingMode(String databaseName, LockingMode mode) {
|
||||
// setPragma(databaseName, Pragma.LOCKING_MODE, mode.name());
|
||||
// }
|
||||
|
||||
public void setPageSize(int numBytes) {
|
||||
set(Pragma.PAGE_SIZE, numBytes);
|
||||
}
|
||||
|
||||
public void setMaxPageCount(int numPages) {
|
||||
set(Pragma.MAX_PAGE_COUNT, numPages);
|
||||
}
|
||||
|
||||
public void setReadUncommited(boolean useReadUncommitedIsolationMode) {
|
||||
set(Pragma.READ_UNCOMMITED, useReadUncommitedIsolationMode);
|
||||
}
|
||||
|
||||
public void enableRecursiveTriggers(boolean enable) {
|
||||
set(Pragma.RECURSIVE_TRIGGERS, enable);
|
||||
}
|
||||
|
||||
public void enableReverseUnorderedSelects(boolean enable) {
|
||||
set(Pragma.REVERSE_UNORDERED_SELECTS, enable);
|
||||
}
|
||||
|
||||
public void enableShortColumnNames(boolean enable) {
|
||||
set(Pragma.SHORT_COLUMN_NAMES, enable);
|
||||
}
|
||||
|
||||
public static enum SynchronousMode implements PragmaValue {
|
||||
OFF, NORMAL, FULL;
|
||||
|
||||
public String getValue() {
|
||||
return name();
|
||||
}
|
||||
}
|
||||
|
||||
public void setSynchronous(SynchronousMode mode) {
|
||||
setPragma(Pragma.SYNCHRONOUS, mode.name());
|
||||
}
|
||||
|
||||
public static enum TempStore implements PragmaValue {
|
||||
DEFAULT, FILE, MEMORY;
|
||||
|
||||
public String getValue() {
|
||||
return name();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void setTempStore(TempStore storeType) {
|
||||
setPragma(Pragma.TEMP_STORE, storeType.name());
|
||||
}
|
||||
|
||||
public void setTempStoreDirectory(String directoryName) {
|
||||
setPragma(Pragma.TEMP_STORE_DIRECTORY, String.format("'%s'", directoryName));
|
||||
}
|
||||
|
||||
public void setUserVersion(int version) {
|
||||
set(Pragma.USER_VERSION, version);
|
||||
}
|
||||
|
||||
}
|
@ -1,228 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
* Copyright 2010 Taro L. Saito
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*--------------------------------------------------------------------------*/
|
||||
//--------------------------------------
|
||||
// sqlite-jdbc Project
|
||||
//
|
||||
// SQLiteDataSource.java
|
||||
// Since: Mar 11, 2010
|
||||
//
|
||||
// $URL$
|
||||
// $Author$
|
||||
//--------------------------------------
|
||||
package org.sqlite;
|
||||
|
||||
import java.io.PrintWriter;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.sql.DataSource;
|
||||
|
||||
import org.sqlite.SQLiteConfig.Encoding;
|
||||
import org.sqlite.SQLiteConfig.JournalMode;
|
||||
import org.sqlite.SQLiteConfig.LockingMode;
|
||||
import org.sqlite.SQLiteConfig.SynchronousMode;
|
||||
import org.sqlite.SQLiteConfig.TempStore;
|
||||
|
||||
/**
|
||||
* Provides {@link DataSource} API for configuring SQLite database connection
|
||||
*
|
||||
* @author leo
|
||||
*
|
||||
*/
|
||||
public class SQLiteDataSource implements DataSource
|
||||
{
|
||||
private SQLiteConfig config;
|
||||
private transient PrintWriter logger;
|
||||
private int loginTimeout = 1;
|
||||
|
||||
private String url = JDBC.PREFIX; // use memory database in default
|
||||
|
||||
public SQLiteDataSource() {
|
||||
this.config = new SQLiteConfig(); // default configuration
|
||||
}
|
||||
|
||||
public SQLiteDataSource(SQLiteConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the configuration parameters via {@link SQLiteConfig} object
|
||||
*
|
||||
* @param config
|
||||
*/
|
||||
public void setConfig(SQLiteConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
|
||||
public SQLiteConfig getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
// configuration parameters
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
public void setSharedCache(boolean enable) {
|
||||
config.setSharedCache(enable);
|
||||
}
|
||||
|
||||
public void setLoadExtension(boolean enable) {
|
||||
config.enableLoadExtension(enable);
|
||||
}
|
||||
|
||||
public void setReadOnly(boolean readOnly) {
|
||||
config.setReadOnly(readOnly);
|
||||
}
|
||||
|
||||
public void setCacheSize(int numberOfPages) {
|
||||
config.setCacheSize(numberOfPages);
|
||||
}
|
||||
|
||||
public void setCaseSensitiveLike(boolean enable) {
|
||||
config.enableCaseSensitiveLike(enable);
|
||||
}
|
||||
|
||||
public void setCouncChanges(boolean enable) {
|
||||
config.enableCountChanges(enable);
|
||||
}
|
||||
|
||||
public void setDefaultCacheSize(int numberOfPages) {
|
||||
config.setDefaultCacheSize(numberOfPages);
|
||||
}
|
||||
|
||||
public void setEncoding(String encoding) {
|
||||
config.setEncoding(Encoding.valueOf(encoding));
|
||||
}
|
||||
|
||||
public void setEnforceForeinKeys(boolean enforce) {
|
||||
config.enforceForeignKeys(enforce);
|
||||
}
|
||||
|
||||
public void setFullColumnNames(boolean enable) {
|
||||
config.enableFullColumnNames(enable);
|
||||
}
|
||||
|
||||
public void setFullSync(boolean enable) {
|
||||
config.enableFullSync(enable);
|
||||
}
|
||||
|
||||
public void setIncrementalVacuum(int numberOfPagesToBeRemoved) {
|
||||
config.incrementalVacuum(numberOfPagesToBeRemoved);
|
||||
}
|
||||
|
||||
public void setJournalMode(String mode) {
|
||||
config.setJournalMode(JournalMode.valueOf(mode));
|
||||
}
|
||||
|
||||
public void setJournalSizeLimit(int limit) {
|
||||
config.setJounalSizeLimit(limit);
|
||||
}
|
||||
|
||||
public void setLegacyFileFormat(boolean use) {
|
||||
config.useLegacyFileFormat(use);
|
||||
}
|
||||
|
||||
public void setLockingMode(String mode) {
|
||||
config.setLockingMode(LockingMode.valueOf(mode));
|
||||
}
|
||||
|
||||
public void setPageSize(int numBytes) {
|
||||
config.setPageSize(numBytes);
|
||||
}
|
||||
|
||||
public void setMaxPageCount(int numPages) {
|
||||
config.setMaxPageCount(numPages);
|
||||
}
|
||||
|
||||
public void setReadUncommited(boolean useReadUncommitedIsolationMode) {
|
||||
config.setReadUncommited(useReadUncommitedIsolationMode);
|
||||
}
|
||||
|
||||
public void setRecursiveTriggers(boolean enable) {
|
||||
config.enableRecursiveTriggers(enable);
|
||||
}
|
||||
|
||||
public void setReverseUnorderedSelects(boolean enable) {
|
||||
config.enableReverseUnorderedSelects(enable);
|
||||
}
|
||||
|
||||
public void setShortColumnNames(boolean enable) {
|
||||
config.enableShortColumnNames(enable);
|
||||
}
|
||||
|
||||
public void setSynchronous(String mode) {
|
||||
config.setSynchronous(SynchronousMode.valueOf(mode));
|
||||
}
|
||||
|
||||
public void setTempStore(String storeType) {
|
||||
config.setTempStore(TempStore.valueOf(storeType));
|
||||
}
|
||||
|
||||
public void setTempStoreDirectory(String directoryName) {
|
||||
config.setTempStoreDirectory(directoryName);
|
||||
}
|
||||
|
||||
public void setUserVersion(int version) {
|
||||
config.setUserVersion(version);
|
||||
}
|
||||
|
||||
// codes for the DataSource interface
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
return getConnection(null, null);
|
||||
}
|
||||
|
||||
public Connection getConnection(String username, String password) throws SQLException {
|
||||
Properties p = config.toProperties();
|
||||
if (username != null)
|
||||
p.put("user", username);
|
||||
if (password != null)
|
||||
p.put("pass", password);
|
||||
return JDBC.createConnection(url, p);
|
||||
}
|
||||
|
||||
public PrintWriter getLogWriter() throws SQLException {
|
||||
return logger;
|
||||
}
|
||||
|
||||
public int getLoginTimeout() throws SQLException {
|
||||
return loginTimeout;
|
||||
}
|
||||
|
||||
public void setLogWriter(PrintWriter out) throws SQLException {
|
||||
this.logger = out;
|
||||
}
|
||||
|
||||
public void setLoginTimeout(int seconds) throws SQLException {
|
||||
loginTimeout = seconds;
|
||||
}
|
||||
|
||||
public boolean isWrapperFor(Class< ? > iface) throws SQLException {
|
||||
return iface.isInstance(this);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T unwrap(Class<T> iface) throws SQLException {
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
* Copyright 2009 Taro L. Saito
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*--------------------------------------------------------------------------*/
|
||||
//--------------------------------------
|
||||
// sqlite-jdbc Project
|
||||
//
|
||||
// SQLiteErrorCode.java
|
||||
// Since: Apr 21, 2009
|
||||
//
|
||||
// $URL$
|
||||
// $Author$
|
||||
//--------------------------------------
|
||||
package org.sqlite;
|
||||
|
||||
/**
|
||||
* SQLite3 error code
|
||||
*
|
||||
* @author leo
|
||||
* @see http://www.sqlite.org/c3ref/c_abort.html
|
||||
*
|
||||
*/
|
||||
public enum SQLiteErrorCode {
|
||||
|
||||
UNKNOWN_ERROR(-1, "unknown error"),
|
||||
SQLITE_OK(0, "Successful result"),
|
||||
/* beginning-of-error-codes */
|
||||
SQLITE_ERROR(1, "SQL error or missing database"),
|
||||
SQLITE_INTERNAL(2, "Internal logic error in SQLite"),
|
||||
SQLITE_PERM(3, " Access permission denied"),
|
||||
SQLITE_ABORT(4, " Callback routine requested an abort"),
|
||||
SQLITE_BUSY(5, " The database file is locked"),
|
||||
SQLITE_LOCKED(6, " A table in the database is locked"),
|
||||
SQLITE_NOMEM(7, " A malloc() failed"),
|
||||
SQLITE_READONLY(8, " Attempt to write a readonly database"),
|
||||
SQLITE_INTERRUPT(9, " Operation terminated by sqlite3_interrupt()"),
|
||||
SQLITE_IOERR(10, " Some kind of disk I/O error occurred"),
|
||||
SQLITE_CORRUPT(11, " The database disk image is malformed"),
|
||||
SQLITE_NOTFOUND(12, " NOT USED. Table or record not found"),
|
||||
SQLITE_FULL(13, " Insertion failed because database is full"),
|
||||
SQLITE_CANTOPEN(14, " Unable to open the database file"),
|
||||
SQLITE_PROTOCOL(15, " NOT USED. Database lock protocol error"),
|
||||
SQLITE_EMPTY(16, " Database is empty"),
|
||||
SQLITE_SCHEMA(17, " The database schema changed"),
|
||||
SQLITE_TOOBIG(18, " String or BLOB exceeds size limit"),
|
||||
SQLITE_CONSTRAINT(19, " Abort due to constraint violation"),
|
||||
SQLITE_MISMATCH(20, " Data type mismatch"),
|
||||
SQLITE_MISUSE(21, " Library used incorrectly"),
|
||||
SQLITE_NOLFS(22, " Uses OS features not supported on host"),
|
||||
SQLITE_AUTH(23, " Authorization denied"),
|
||||
SQLITE_FORMAT(24, " Auxiliary database format error"),
|
||||
SQLITE_RANGE(25, " 2nd parameter to sqlite3_bind out of range"),
|
||||
SQLITE_NOTADB(26, " File opened that is not a database file"),
|
||||
SQLITE_ROW(100, " sqlite3_step() has another row ready"),
|
||||
SQLITE_DONE(101, " sqlite3_step() has finished executing");
|
||||
|
||||
public final int code;
|
||||
public final String message;
|
||||
|
||||
private SQLiteErrorCode(int code, String message)
|
||||
{
|
||||
this.code = code;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public static SQLiteErrorCode getErrorCode(int errorCode)
|
||||
{
|
||||
for (SQLiteErrorCode each : SQLiteErrorCode.values())
|
||||
{
|
||||
if (errorCode == each.code)
|
||||
return each;
|
||||
}
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString()
|
||||
{
|
||||
return String.format("[%s] %s", this.name(), message);
|
||||
}
|
||||
}
|
@ -1,271 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
* Copyright 2007 Taro L. Saito
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*--------------------------------------------------------------------------*/
|
||||
//--------------------------------------
|
||||
// SQLite JDBC Project
|
||||
//
|
||||
// SQLite.java
|
||||
// Since: 2007/05/10
|
||||
//
|
||||
// $URL$
|
||||
// $Author$
|
||||
//--------------------------------------
|
||||
package org.sqlite;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.security.DigestInputStream;
|
||||
import java.security.MessageDigest;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.util.Properties;
|
||||
|
||||
/**
|
||||
* Set the system properties, org.sqlite.lib.path, org.sqlite.lib.name,
|
||||
* appropriately so that the SQLite JDBC driver can find *.dll, *.jnilib and
|
||||
* *.so files, according to the current OS (win, linux, mac).
|
||||
*
|
||||
* The library files are automatically extracted from this project's package
|
||||
* (JAR).
|
||||
*
|
||||
* usage: call {@link #initialize()} before using SQLite JDBC driver.
|
||||
*
|
||||
* @author leo
|
||||
*
|
||||
*/
|
||||
public class SQLiteJDBCLoader
|
||||
{
|
||||
|
||||
private static boolean extracted = false;
|
||||
|
||||
public static boolean initialize() {
|
||||
loadSQLiteNativeLibrary();
|
||||
return extracted;
|
||||
}
|
||||
|
||||
static boolean getPureJavaFlag() {
|
||||
return Boolean.parseBoolean(System.getProperty("sqlite.purejava", "false"));
|
||||
}
|
||||
|
||||
public static boolean isPureJavaMode() {
|
||||
return !isNativeMode();
|
||||
}
|
||||
|
||||
public static boolean isNativeMode() {
|
||||
if (getPureJavaFlag())
|
||||
return false;
|
||||
|
||||
// load the driver
|
||||
initialize();
|
||||
return extracted;
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the MD5 value of the input stream
|
||||
*
|
||||
* @param input
|
||||
* @return
|
||||
* @throws IOException
|
||||
* @throws NoSuchAlgorithmException
|
||||
*/
|
||||
static String md5sum(InputStream input) throws IOException {
|
||||
BufferedInputStream in = new BufferedInputStream(input);
|
||||
|
||||
try {
|
||||
MessageDigest digest = java.security.MessageDigest.getInstance("MD5");
|
||||
DigestInputStream digestInputStream = new DigestInputStream(in, digest);
|
||||
for (; digestInputStream.read() >= 0;) {
|
||||
|
||||
}
|
||||
ByteArrayOutputStream md5out = new ByteArrayOutputStream();
|
||||
md5out.write(digest.digest());
|
||||
return md5out.toString();
|
||||
}
|
||||
catch (NoSuchAlgorithmException e) {
|
||||
throw new IllegalStateException("MD5 algorithm is not available: " + e);
|
||||
}
|
||||
finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract the specified library file to the target folder
|
||||
*
|
||||
* @param libFolderForCurrentOS
|
||||
* @param libraryFileName
|
||||
* @param targetFolder
|
||||
* @return
|
||||
*/
|
||||
private static boolean extractAndLoadLibraryFile(String libFolderForCurrentOS, String libraryFileName,
|
||||
String targetFolder) {
|
||||
String nativeLibraryFilePath = libFolderForCurrentOS + "/" + libraryFileName;
|
||||
final String prefix = "sqlite-" + getVersion() + "-";
|
||||
|
||||
String extractedLibFileName = prefix + libraryFileName;
|
||||
File extractedLibFile = new File(targetFolder, extractedLibFileName);
|
||||
|
||||
try {
|
||||
if (extractedLibFile.exists()) {
|
||||
// test md5sum value
|
||||
String md5sum1 = md5sum(SQLiteJDBCLoader.class.getResourceAsStream(nativeLibraryFilePath));
|
||||
String md5sum2 = md5sum(new FileInputStream(extractedLibFile));
|
||||
|
||||
if (md5sum1.equals(md5sum2)) {
|
||||
return loadNativeLibrary(targetFolder, extractedLibFileName);
|
||||
}
|
||||
else {
|
||||
// remove old native library file
|
||||
boolean deletionSucceeded = extractedLibFile.delete();
|
||||
if (!deletionSucceeded) {
|
||||
throw new IOException("failed to remove existing native library file: "
|
||||
+ extractedLibFile.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// extract file into the current directory
|
||||
InputStream reader = SQLiteJDBCLoader.class.getResourceAsStream(nativeLibraryFilePath);
|
||||
FileOutputStream writer = new FileOutputStream(extractedLibFile);
|
||||
byte[] buffer = new byte[1024];
|
||||
int bytesRead = 0;
|
||||
while ((bytesRead = reader.read(buffer)) != -1) {
|
||||
writer.write(buffer, 0, bytesRead);
|
||||
}
|
||||
|
||||
writer.close();
|
||||
reader.close();
|
||||
|
||||
if (!System.getProperty("os.name").contains("Windows")) {
|
||||
try {
|
||||
Runtime.getRuntime().exec(new String[] { "chmod", "755", extractedLibFile.getAbsolutePath() })
|
||||
.waitFor();
|
||||
}
|
||||
catch (Throwable e) {}
|
||||
}
|
||||
|
||||
return loadNativeLibrary(targetFolder, extractedLibFileName);
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println(e.getMessage());
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static synchronized boolean loadNativeLibrary(String path, String name) {
|
||||
File libPath = new File(path, name);
|
||||
if (libPath.exists()) {
|
||||
|
||||
try {
|
||||
System.load(new File(path, name).getAbsolutePath());
|
||||
return true;
|
||||
}
|
||||
catch (UnsatisfiedLinkError e) {
|
||||
System.err.println(e);
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
private static void loadSQLiteNativeLibrary() {
|
||||
if (extracted)
|
||||
return;
|
||||
|
||||
boolean runInPureJavaMode = getPureJavaFlag();
|
||||
if (runInPureJavaMode) {
|
||||
extracted = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Try loading library from org.sqlite.lib.path library path */
|
||||
String sqliteNativeLibraryPath = System.getProperty("org.sqlite.lib.path");
|
||||
String sqliteNativeLibraryName = System.getProperty("org.sqlite.lib.name");
|
||||
if (sqliteNativeLibraryName == null)
|
||||
sqliteNativeLibraryName = System.mapLibraryName("sqlitejdbc");
|
||||
|
||||
if (sqliteNativeLibraryPath != null) {
|
||||
if (loadNativeLibrary(sqliteNativeLibraryPath, sqliteNativeLibraryName)) {
|
||||
extracted = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Load the os-dependent library from a jar file
|
||||
sqliteNativeLibraryPath = "/native/" + OSInfo.getNativeLibFolderPathForCurrentOS();
|
||||
|
||||
if (SQLiteJDBCLoader.class.getResource(sqliteNativeLibraryPath + "/" + sqliteNativeLibraryName) == null) {
|
||||
// use nested VM version
|
||||
return;
|
||||
}
|
||||
|
||||
// temporary library folder
|
||||
String tempFolder = new File(System.getProperty("java.io.tmpdir")).getAbsolutePath();
|
||||
// Try extracting the library from jar
|
||||
if (extractAndLoadLibraryFile(sqliteNativeLibraryPath, sqliteNativeLibraryName, tempFolder)) {
|
||||
extracted = true;
|
||||
return;
|
||||
}
|
||||
|
||||
extracted = false;
|
||||
return;
|
||||
}
|
||||
|
||||
private static void getNativeLibraryFolderForTheCurrentOS() {
|
||||
String osName = OSInfo.getOSName();
|
||||
String archName = OSInfo.getArchName();
|
||||
|
||||
}
|
||||
|
||||
public static int getMajorVersion() {
|
||||
String[] c = getVersion().split("\\.");
|
||||
return (c.length > 0) ? Integer.parseInt(c[0]) : 1;
|
||||
}
|
||||
|
||||
public static int getMinorVersion() {
|
||||
String[] c = getVersion().split("\\.");
|
||||
return (c.length > 1) ? Integer.parseInt(c[1]) : 0;
|
||||
}
|
||||
|
||||
public static String getVersion() {
|
||||
|
||||
URL versionFile = SQLiteJDBCLoader.class.getResource("/META-INF/maven/org.xerial/sqlite-jdbc/pom.properties");
|
||||
if (versionFile == null)
|
||||
versionFile = SQLiteJDBCLoader.class.getResource("/META-INF/maven/org.xerial/sqlite-jdbc/VERSION");
|
||||
|
||||
String version = "unknown";
|
||||
try {
|
||||
if (versionFile != null) {
|
||||
Properties versionData = new Properties();
|
||||
versionData.load(versionFile.openStream());
|
||||
version = versionData.getProperty("version", version);
|
||||
version = version.trim().replaceAll("[^0-9\\.]", "");
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
System.err.println(e);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
|
||||
}
|
@ -1,59 +0,0 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
* Copyright 2009 Taro L. Saito
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*--------------------------------------------------------------------------*/
|
||||
//--------------------------------------
|
||||
// sqlite-jdbc Project
|
||||
//
|
||||
// SQLiteOpenMode.java
|
||||
// Since: Dec 8, 2009
|
||||
//
|
||||
// $URL$
|
||||
// $Author$
|
||||
//--------------------------------------
|
||||
package org.sqlite;
|
||||
|
||||
/**
|
||||
* Database file open modes of SQLite.
|
||||
*
|
||||
* See also http://sqlite.org/c3ref/open.html
|
||||
*
|
||||
* @author leo
|
||||
*
|
||||
*/
|
||||
public enum SQLiteOpenMode {
|
||||
READONLY(0x00000001), /* Ok for int SQLITE3_open_v2() */
|
||||
READWRITE(0x00000002), /* Ok for int SQLITE3_open_v2() */
|
||||
CREATE(0x00000004), /* Ok for int SQLITE3_open_v2() */
|
||||
DELETEONCLOSE(0x00000008), /* VFS only */
|
||||
EXCLUSIVE(0x00000010), /* VFS only */
|
||||
MAIN_DB(0x00000100), /* VFS only */
|
||||
TEMP_DB(0x00000200), /* VFS only */
|
||||
TRANSIENT_DB(0x00000400), /* VFS only */
|
||||
MAIN_JOURNAL(0x00000800), /* VFS only */
|
||||
TEMP_JOURNAL(0x00001000), /* VFS only */
|
||||
SUBJOURNAL(0x00002000), /* VFS only */
|
||||
MASTER_JOURNAL(0x00004000), /* VFS only */
|
||||
NOMUTEX(0x00008000), /* Ok for int SQLITE3_open_v2() */
|
||||
FULLMUTEX(0x00010000), /* Ok for int SQLITE3_open_v2() */
|
||||
SHAREDCACHE(0x00020000), /* Ok for int SQLITE3_open_v2() */
|
||||
PRIVATECACHE(0x00040000) /* Ok for sqlite3_open_v2() */
|
||||
;
|
||||
|
||||
public final int flag;
|
||||
|
||||
private SQLiteOpenMode(int flag) {
|
||||
this.flag = flag;
|
||||
}
|
||||
}
|
@ -1,337 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
package org.sqlite;
|
||||
|
||||
import java.sql.BatchUpdateException;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.SQLWarning;
|
||||
import java.sql.Statement;
|
||||
|
||||
import org.sqlite.DB.ProgressObserver;
|
||||
import org.sqlite.ExtendedCommand.SQLExtension;
|
||||
|
||||
class Stmt extends Unused implements Statement, Codes
|
||||
{
|
||||
final Conn conn;
|
||||
final DB db;
|
||||
final RS rs;
|
||||
|
||||
long pointer;
|
||||
String sql = null;
|
||||
|
||||
int batchPos;
|
||||
Object[] batch = null;
|
||||
boolean resultsWaiting = false;
|
||||
|
||||
Stmt(Conn c) {
|
||||
conn = c;
|
||||
db = conn.db();
|
||||
rs = new RS(this);
|
||||
}
|
||||
|
||||
protected final void checkOpen() throws SQLException {
|
||||
if (pointer == 0)
|
||||
throw new SQLException("statement is not executing");
|
||||
}
|
||||
|
||||
boolean isOpen() throws SQLException {
|
||||
return (pointer != 0);
|
||||
}
|
||||
|
||||
/** Calls sqlite3_step() and sets up results. Expects a clean stmt. */
|
||||
protected boolean exec() throws SQLException {
|
||||
if (sql == null)
|
||||
throw new SQLException("SQLiteJDBC internal error: sql==null");
|
||||
if (rs.isOpen())
|
||||
throw new SQLException("SQLite JDBC internal error: rs.isOpen() on exec.");
|
||||
|
||||
boolean rc = false;
|
||||
try {
|
||||
rc = db.execute(this, null);
|
||||
}
|
||||
finally {
|
||||
resultsWaiting = rc;
|
||||
}
|
||||
|
||||
return db.column_count(pointer) != 0;
|
||||
}
|
||||
|
||||
protected boolean exec(String sql) throws SQLException {
|
||||
if (sql == null)
|
||||
throw new SQLException("SQLiteJDBC internal error: sql==null");
|
||||
if (rs.isOpen())
|
||||
throw new SQLException("SQLite JDBC internal error: rs.isOpen() on exec.");
|
||||
|
||||
boolean rc = false;
|
||||
try {
|
||||
rc = db.execute(sql);
|
||||
}
|
||||
finally {
|
||||
resultsWaiting = rc;
|
||||
}
|
||||
|
||||
return db.column_count(pointer) != 0;
|
||||
}
|
||||
|
||||
// PUBLIC INTERFACE /////////////////////////////////////////////
|
||||
|
||||
public void close() throws SQLException {
|
||||
if (pointer == 0)
|
||||
return;
|
||||
rs.close();
|
||||
batch = null;
|
||||
batchPos = 0;
|
||||
int resp = db.finalize(this);
|
||||
if (resp != SQLITE_OK && resp != SQLITE_MISUSE)
|
||||
db.throwex();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void finalize() throws SQLException {
|
||||
close();
|
||||
}
|
||||
|
||||
public boolean execute(String sql) throws SQLException {
|
||||
close();
|
||||
this.sql = sql;
|
||||
|
||||
db.prepare(this);
|
||||
return exec();
|
||||
}
|
||||
|
||||
public ResultSet executeQuery(String sql) throws SQLException {
|
||||
close();
|
||||
this.sql = sql;
|
||||
|
||||
db.prepare(this);
|
||||
if (!exec()) {
|
||||
close();
|
||||
throw new SQLException("query does not return ResultSet");
|
||||
}
|
||||
return getResultSet();
|
||||
}
|
||||
|
||||
static class BackupObserver implements ProgressObserver
|
||||
{
|
||||
public void progress(int remaining, int pageCount) {
|
||||
System.out.println(String.format("remaining:%d, page count:%d", remaining, pageCount));
|
||||
}
|
||||
}
|
||||
|
||||
public int executeUpdate(String sql) throws SQLException {
|
||||
close();
|
||||
this.sql = sql;
|
||||
|
||||
int changes = 0;
|
||||
SQLExtension ext = ExtendedCommand.parse(sql);
|
||||
if (ext != null) {
|
||||
// execute extended command
|
||||
ext.execute(db);
|
||||
}
|
||||
else {
|
||||
try {
|
||||
//db.prepare(this);
|
||||
//changes = db.executeUpdate(this, null);
|
||||
|
||||
// directly invokes the exec API to support multiple SQL statements
|
||||
int statusCode = db._exec(sql);
|
||||
if (statusCode != SQLITE_OK)
|
||||
throw DB.newSQLException(statusCode, "");
|
||||
|
||||
changes = db.changes();
|
||||
}
|
||||
finally {
|
||||
close();
|
||||
}
|
||||
}
|
||||
return changes;
|
||||
}
|
||||
|
||||
public ResultSet getResultSet() throws SQLException {
|
||||
checkOpen();
|
||||
if (rs.isOpen())
|
||||
throw new SQLException("ResultSet already requested");
|
||||
if (db.column_count(pointer) == 0)
|
||||
throw new SQLException("no ResultSet available");
|
||||
if (rs.colsMeta == null)
|
||||
rs.colsMeta = db.column_names(pointer);
|
||||
rs.cols = rs.colsMeta;
|
||||
|
||||
rs.open = resultsWaiting;
|
||||
resultsWaiting = false;
|
||||
return rs;
|
||||
}
|
||||
|
||||
/*
|
||||
* This function has a complex behaviour best understood by carefully
|
||||
* reading the JavaDoc for getMoreResults() and considering the test
|
||||
* StatementTest.execute().
|
||||
*/
|
||||
public int getUpdateCount() throws SQLException {
|
||||
if (pointer != 0 && !rs.isOpen() && !resultsWaiting && db.column_count(pointer) == 0)
|
||||
return db.changes();
|
||||
return -1;
|
||||
}
|
||||
|
||||
public void addBatch(String sql) throws SQLException {
|
||||
close();
|
||||
if (batch == null || batchPos + 1 >= batch.length) {
|
||||
Object[] nb = new Object[Math.max(10, batchPos * 2)];
|
||||
if (batch != null)
|
||||
System.arraycopy(batch, 0, nb, 0, batch.length);
|
||||
batch = nb;
|
||||
}
|
||||
batch[batchPos++] = sql;
|
||||
}
|
||||
|
||||
public void clearBatch() throws SQLException {
|
||||
batchPos = 0;
|
||||
if (batch != null)
|
||||
for (int i = 0; i < batch.length; i++)
|
||||
batch[i] = null;
|
||||
}
|
||||
|
||||
public int[] executeBatch() throws SQLException {
|
||||
// TODO: optimize
|
||||
close();
|
||||
if (batch == null || batchPos == 0)
|
||||
return new int[] {};
|
||||
|
||||
int[] changes = new int[batchPos];
|
||||
|
||||
synchronized (db) {
|
||||
try {
|
||||
for (int i = 0; i < changes.length; i++) {
|
||||
try {
|
||||
this.sql = (String) batch[i];
|
||||
db.prepare(this);
|
||||
changes[i] = db.executeUpdate(this, null);
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw new BatchUpdateException("batch entry " + i + ": " + e.getMessage(), changes);
|
||||
}
|
||||
finally {
|
||||
db.finalize(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
finally {
|
||||
clearBatch();
|
||||
}
|
||||
}
|
||||
|
||||
return changes;
|
||||
}
|
||||
|
||||
public void setCursorName(String name) {}
|
||||
|
||||
public SQLWarning getWarnings() throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void clearWarnings() throws SQLException {}
|
||||
|
||||
public Connection getConnection() throws SQLException {
|
||||
return conn;
|
||||
}
|
||||
|
||||
public void cancel() throws SQLException {
|
||||
rs.checkOpen();
|
||||
db.interrupt();
|
||||
}
|
||||
|
||||
public int getQueryTimeout() throws SQLException {
|
||||
return conn.getTimeout();
|
||||
}
|
||||
|
||||
public void setQueryTimeout(int seconds) throws SQLException {
|
||||
if (seconds < 0)
|
||||
throw new SQLException("query timeout must be >= 0");
|
||||
conn.setTimeout(1000 * seconds);
|
||||
}
|
||||
|
||||
// TODO: write test
|
||||
public int getMaxRows() throws SQLException {
|
||||
//checkOpen();
|
||||
return rs.maxRows;
|
||||
}
|
||||
|
||||
public void setMaxRows(int max) throws SQLException {
|
||||
//checkOpen();
|
||||
if (max < 0)
|
||||
throw new SQLException("max row count must be >= 0");
|
||||
rs.maxRows = max;
|
||||
}
|
||||
|
||||
public int getMaxFieldSize() throws SQLException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void setMaxFieldSize(int max) throws SQLException {
|
||||
if (max < 0)
|
||||
throw new SQLException("max field size " + max + " cannot be negative");
|
||||
}
|
||||
|
||||
public int getFetchSize() throws SQLException {
|
||||
return rs.getFetchSize();
|
||||
}
|
||||
|
||||
public void setFetchSize(int r) throws SQLException {
|
||||
rs.setFetchSize(r);
|
||||
}
|
||||
|
||||
public int getFetchDirection() throws SQLException {
|
||||
return rs.getFetchDirection();
|
||||
}
|
||||
|
||||
public void setFetchDirection(int d) throws SQLException {
|
||||
rs.setFetchDirection(d);
|
||||
}
|
||||
|
||||
/**
|
||||
* As SQLite's last_insert_rowid() function is DB-specific not statement
|
||||
* specific, this function introduces a race condition if the same
|
||||
* connection is used by two threads and both insert.
|
||||
*/
|
||||
public ResultSet getGeneratedKeys() throws SQLException {
|
||||
return ((MetaData) conn.getMetaData()).getGeneratedKeys();
|
||||
}
|
||||
|
||||
/** SQLite does not support multiple results from execute(). */
|
||||
public boolean getMoreResults() throws SQLException {
|
||||
return getMoreResults(0);
|
||||
}
|
||||
|
||||
public boolean getMoreResults(int c) throws SQLException {
|
||||
checkOpen();
|
||||
close(); // as we never have another result, clean up pointer
|
||||
return false;
|
||||
}
|
||||
|
||||
public int getResultSetConcurrency() throws SQLException {
|
||||
return ResultSet.CONCUR_READ_ONLY;
|
||||
}
|
||||
|
||||
public int getResultSetHoldability() throws SQLException {
|
||||
return ResultSet.CLOSE_CURSORS_AT_COMMIT;
|
||||
}
|
||||
|
||||
public int getResultSetType() throws SQLException {
|
||||
return ResultSet.TYPE_FORWARD_ONLY;
|
||||
}
|
||||
}
|
@ -1,244 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2007 David Crawshaw <david@zentus.com>
|
||||
*
|
||||
* Permission to use, copy, modify, and/or distribute this software for any
|
||||
* purpose with or without fee is hereby granted, provided that the above
|
||||
* copyright notice and this permission notice appear in all copies.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
*/
|
||||
|
||||
package org.sqlite;
|
||||
|
||||
import java.io.*;
|
||||
import java.math.*;
|
||||
import java.net.*;
|
||||
import java.sql.*;
|
||||
import java.util.Map;
|
||||
|
||||
/** Unused JDBC functions from Statement, PreparedStatement and ResultSet. */
|
||||
abstract class Unused
|
||||
{
|
||||
private SQLException unused() {
|
||||
return new SQLException("not implemented by SQLite JDBC driver");
|
||||
}
|
||||
|
||||
|
||||
// Statement ////////////////////////////////////////////////////
|
||||
|
||||
public void setEscapeProcessing(boolean enable)
|
||||
throws SQLException { throw unused(); }
|
||||
public boolean execute(String sql, int[] colinds)
|
||||
throws SQLException { throw unused(); }
|
||||
public boolean execute(String sql, String[] colnames)
|
||||
throws SQLException { throw unused(); }
|
||||
public int executeUpdate(String sql, int autoKeys)
|
||||
throws SQLException { throw unused(); }
|
||||
public int executeUpdate(String sql, int[] colinds)
|
||||
throws SQLException { throw unused(); }
|
||||
public int executeUpdate(String sql, String[] cols)
|
||||
throws SQLException { throw unused(); }
|
||||
public boolean execute(String sql, int autokeys)
|
||||
throws SQLException { throw unused(); }
|
||||
|
||||
|
||||
// PreparedStatement ////////////////////////////////////////////
|
||||
|
||||
public void setArray(int i, Array x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void setAsciiStream(int parameterIndex, InputStream x, int length)
|
||||
throws SQLException { throw unused(); }
|
||||
public void setBigDecimal(int parameterIndex, BigDecimal x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void setBinaryStream(int parameterIndex, InputStream x, int length)
|
||||
throws SQLException { throw unused(); }
|
||||
public void setBlob(int i, Blob x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void setClob(int i, Clob x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void setRef(int i, Ref x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void setUnicodeStream(int pos, InputStream x, int length)
|
||||
throws SQLException { throw unused(); }
|
||||
public void setURL(int pos, URL x)
|
||||
throws SQLException { throw unused(); }
|
||||
|
||||
|
||||
// ResultSet ////////////////////////////////////////////////////
|
||||
|
||||
public Array getArray(int i)
|
||||
throws SQLException { throw unused(); }
|
||||
public Array getArray(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
public InputStream getAsciiStream(int col)
|
||||
throws SQLException { throw unused(); }
|
||||
public InputStream getAsciiStream(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
public BigDecimal getBigDecimal(int col)
|
||||
throws SQLException { throw unused(); }
|
||||
public BigDecimal getBigDecimal(int col, int s)
|
||||
throws SQLException { throw unused(); }
|
||||
public BigDecimal getBigDecimal(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
public BigDecimal getBigDecimal(String col, int s)
|
||||
throws SQLException { throw unused(); }
|
||||
public InputStream getBinaryStream(int col)
|
||||
throws SQLException { throw unused(); }
|
||||
public InputStream getBinaryStream(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
public Blob getBlob(int col)
|
||||
throws SQLException { throw unused(); }
|
||||
public Blob getBlob(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
public Clob getClob(int col)
|
||||
throws SQLException { throw unused(); }
|
||||
public Clob getClob(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
public Object getObject(int col, Map map)
|
||||
throws SQLException { throw unused(); }
|
||||
public Object getObject(String col, Map map)
|
||||
throws SQLException { throw unused(); }
|
||||
public Ref getRef(int i)
|
||||
throws SQLException { throw unused(); }
|
||||
public Ref getRef(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
|
||||
public InputStream getUnicodeStream(int col)
|
||||
throws SQLException { throw unused(); }
|
||||
public InputStream getUnicodeStream(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
public URL getURL(int col)
|
||||
throws SQLException { throw unused(); }
|
||||
public URL getURL(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
|
||||
public void insertRow() throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public void moveToCurrentRow() throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public void moveToInsertRow() throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public boolean last() throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public boolean previous() throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public boolean relative(int rows) throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public boolean absolute(int row) throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public void afterLast() throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public void beforeFirst() throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
public boolean first() throws SQLException {
|
||||
throw new SQLException("ResultSet is TYPE_FORWARD_ONLY"); }
|
||||
|
||||
public void cancelRowUpdates()
|
||||
throws SQLException { throw unused(); }
|
||||
public void deleteRow()
|
||||
throws SQLException { throw unused(); }
|
||||
|
||||
public void updateArray(int col, Array x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateArray(String col, Array x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateAsciiStream(int col, InputStream x, int l)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateAsciiStream(String col, InputStream x, int l)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBigDecimal(int col, BigDecimal x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBigDecimal(String col, BigDecimal x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBinaryStream(int c, InputStream x, int l)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBinaryStream(String c, InputStream x, int l)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBlob(int col, Blob x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBlob(String col, Blob x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBoolean(int col, boolean x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBoolean(String col, boolean x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateByte(int col, byte x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateByte(String col, byte x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBytes(int col, byte[] x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateBytes(String col, byte[] x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateCharacterStream(int c, Reader x, int l)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateCharacterStream(String c, Reader r, int l)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateClob(int col, Clob x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateClob(String col, Clob x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateDate(int col, Date x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateDate(String col, Date x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateDouble(int col, double x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateDouble(String col, double x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateFloat(int col, float x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateFloat(String col, float x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateInt(int col, int x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateInt(String col, int x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateLong(int col, long x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateLong(String col, long x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateNull(int col)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateNull(String col)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateObject(int c, Object x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateObject(int c, Object x, int s)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateObject(String col, Object x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateObject(String c, Object x, int s)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateRef(int col, Ref x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateRef(String c, Ref x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateRow()
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateShort(int c, short x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateShort(String c, short x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateString(int c, String x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateString(String c, String x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateTime(int c, Time x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateTime(String c, Time x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateTimestamp(int c, Timestamp x)
|
||||
throws SQLException { throw unused(); }
|
||||
public void updateTimestamp(String c, Timestamp x)
|
||||
throws SQLException { throw unused(); }
|
||||
|
||||
public void refreshRow()
|
||||
throws SQLException { throw unused(); }
|
||||
}
|
Loading…
Reference in New Issue
Block a user