+ *
+ * @param table the name of the locked table
+ * @param count number of times the table was locked
+ */
+
+ public boolean busy(String table, int count);
+}
diff --git a/sql/src/main/java/SQLite/Callback.java b/sql/src/main/java/SQLite/Callback.java
new file mode 100644
index 0000000..3eeb605
--- /dev/null
+++ b/sql/src/main/java/SQLite/Callback.java
@@ -0,0 +1,68 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's query results.
+ *
+ * Example:
+ *
+ *
+ * class TableFmt implements SQLite.Callback {
+ * public void columns(String cols[]) {
+ * System.out.println("<TH><TR>");
+ * for (int i = 0; i < cols.length; i++) {
+ * System.out.println("<TD>" + cols[i] + "</TD>");
+ * }
+ * System.out.println("</TR></TH>");
+ * }
+ * public boolean newrow(String cols[]) {
+ * System.out.println("<TR>");
+ * for (int i = 0; i < cols.length; i++) {
+ * System.out.println("<TD>" + cols[i] + "</TD>");
+ * }
+ * System.out.println("</TR>");
+ * return false;
+ * }
+ * }
+ * ...
+ * SQLite.Database db = new SQLite.Database();
+ * db.open("db", 0);
+ * System.out.println("<TABLE>");
+ * db.exec("select * from TEST", new TableFmt());
+ * System.out.println("</TABLE>");
+ * ...
+ *
+ */
+
+public interface Callback {
+
+ /**
+ * Reports column names of the query result.
+ * This method is invoked first (and once) when
+ * the SQLite engine returns the result set.
+ *
+ * @param coldata string array holding the column names
+ */
+
+ public void columns(String coldata[]);
+
+ /**
+ * Reports type names of the columns of the query result.
+ * This is available from SQLite 2.6.0 on and needs
+ * the PRAGMA show_datatypes to be turned on.
+ *
+ * @param types string array holding column types
+ */
+
+ public void types(String types[]);
+
+ /**
+ * Reports row data of the query result.
+ * This method is invoked for each row of the
+ * result set. If true is returned the running
+ * SQLite query is aborted.
+ *
+ * @param rowdata string array holding the column values of the row
+ */
+
+ public boolean newrow(String rowdata[]);
+}
diff --git a/sql/src/main/java/SQLite/Constants.java b/sql/src/main/java/SQLite/Constants.java
new file mode 100644
index 0000000..4e636b9
--- /dev/null
+++ b/sql/src/main/java/SQLite/Constants.java
@@ -0,0 +1,157 @@
+/* DO NOT EDIT */
+
+package SQLite;
+
+/**
+ * Container for SQLite constants.
+ */
+
+public final class Constants {
+ /*
+ * Error code: 0
+ */
+ public static final int SQLITE_OK = 0;
+ /*
+ * Error code: 1
+ */
+ public static final int SQLITE_ERROR = 1;
+ /*
+ * Error code: 2
+ */
+ public static final int SQLITE_INTERNAL = 2;
+ /*
+ * Error code: 3
+ */
+ public static final int SQLITE_PERM = 3;
+ /*
+ * Error code: 4
+ */
+ public static final int SQLITE_ABORT = 4;
+ /*
+ * Error code: 5
+ */
+ public static final int SQLITE_BUSY = 5;
+ /*
+ * Error code: 6
+ */
+ public static final int SQLITE_LOCKED = 6;
+ /*
+ * Error code: 7
+ */
+ public static final int SQLITE_NOMEM = 7;
+ /*
+ * Error code: 8
+ */
+ public static final int SQLITE_READONLY = 8;
+ /*
+ * Error code: 9
+ */
+ public static final int SQLITE_INTERRUPT = 9;
+ /*
+ * Error code: 10
+ */
+ public static final int SQLITE_IOERR = 10;
+ /*
+ * Error code: 11
+ */
+ public static final int SQLITE_CORRUPT = 11;
+ /*
+ * Error code: 12
+ */
+ public static final int SQLITE_NOTFOUND = 12;
+ /*
+ * Error code: 13
+ */
+ public static final int SQLITE_FULL = 13;
+ /*
+ * Error code: 14
+ */
+ public static final int SQLITE_CANTOPEN = 14;
+ /*
+ * Error code: 15
+ */
+ public static final int SQLITE_PROTOCOL = 15;
+ /*
+ * Error code: 16
+ */
+ public static final int SQLITE_EMPTY = 16;
+ /*
+ * Error code: 17
+ */
+ public static final int SQLITE_SCHEMA = 17;
+ /*
+ * Error code: 18
+ */
+ public static final int SQLITE_TOOBIG = 18;
+ /*
+ * Error code: 19
+ */
+ public static final int SQLITE_CONSTRAINT = 19;
+ /*
+ * Error code: 20
+ */
+ public static final int SQLITE_MISMATCH = 20;
+ /*
+ * Error code: 21
+ */
+ public static final int SQLITE_MISUSE = 21;
+ /*
+ * Error code: 22
+ */
+ public static final int SQLITE_NOLFS = 22;
+ /*
+ * Error code: 23
+ */
+ public static final int SQLITE_AUTH = 23;
+ /*
+ * Error code: 24
+ */
+ public static final int SQLITE_FORMAT = 24;
+ /*
+ * Error code: 25
+ */
+ public static final int SQLITE_RANGE = 25;
+ /*
+ * Error code: 26
+ */
+ public static final int SQLITE_NOTADB = 26;
+ public static final int SQLITE_ROW = 100;
+ public static final int SQLITE_DONE = 101;
+ public static final int SQLITE_INTEGER = 1;
+ public static final int SQLITE_FLOAT = 2;
+ public static final int SQLITE_BLOB = 4;
+ public static final int SQLITE_NULL = 5;
+ public static final int SQLITE3_TEXT = 3;
+ public static final int SQLITE_NUMERIC = -1;
+ public static final int SQLITE_TEXT = 3;
+ public static final int SQLITE2_TEXT = -2;
+ public static final int SQLITE_ARGS = -3;
+ public static final int SQLITE_COPY = 0;
+ public static final int SQLITE_CREATE_INDEX = 1;
+ public static final int SQLITE_CREATE_TABLE = 2;
+ public static final int SQLITE_CREATE_TEMP_INDEX = 3;
+ public static final int SQLITE_CREATE_TEMP_TABLE = 4;
+ public static final int SQLITE_CREATE_TEMP_TRIGGER = 5;
+ public static final int SQLITE_CREATE_TEMP_VIEW = 6;
+ public static final int SQLITE_CREATE_TRIGGER = 7;
+ public static final int SQLITE_CREATE_VIEW = 8;
+ public static final int SQLITE_DELETE = 9;
+ public static final int SQLITE_DROP_INDEX = 10;
+ public static final int SQLITE_DROP_TABLE = 11;
+ public static final int SQLITE_DROP_TEMP_INDEX = 12;
+ public static final int SQLITE_DROP_TEMP_TABLE = 13;
+ public static final int SQLITE_DROP_TEMP_TRIGGER = 14;
+ public static final int SQLITE_DROP_TEMP_VIEW = 15;
+ public static final int SQLITE_DROP_TRIGGER = 16;
+ public static final int SQLITE_DROP_VIEW = 17;
+ public static final int SQLITE_INSERT = 18;
+ public static final int SQLITE_PRAGMA = 19;
+ public static final int SQLITE_READ = 20;
+ public static final int SQLITE_SELECT = 21;
+ public static final int SQLITE_TRANSACTION = 22;
+ public static final int SQLITE_UPDATE = 23;
+ public static final int SQLITE_ATTACH = 24;
+ public static final int SQLITE_DETACH = 25;
+ public static final int SQLITE_DENY = 1;
+ public static final int SQLITE_IGNORE = 2;
+}
diff --git a/sql/src/main/java/SQLite/Database.java b/sql/src/main/java/SQLite/Database.java
new file mode 100644
index 0000000..dcaaf9d
--- /dev/null
+++ b/sql/src/main/java/SQLite/Database.java
@@ -0,0 +1,615 @@
+package SQLite;
+
+/**
+ * Main class wrapping an SQLite database.
+ */
+
+public class Database {
+
+ /**
+ * Internal handle for the native SQLite API.
+ */
+
+ protected long handle = 0;
+
+ /**
+ * Internal last error code for exec() methods.
+ */
+
+ protected int error_code = 0;
+
+ /**
+ * Open an SQLite database file.
+ *
+ * @param filename the name of the database file
+ * @param mode open mode, currently ignored
+ */
+
+ public void open(String filename, int mode) throws SQLite.Exception {
+ synchronized(this) {
+ _open(filename, mode);
+ }
+ }
+
+ private native void _open(String filename, int mode)
+ throws SQLite.Exception;
+
+ /**
+ * Open SQLite auxiliary database file for temporary
+ * tables.
+ *
+ * @param filename the name of the auxiliary file or null
+ */
+
+ public void open_aux_file(String filename) throws SQLite.Exception {
+ synchronized(this) {
+ _open_aux_file(filename);
+ }
+ }
+
+ private native void _open_aux_file(String filename)
+ throws SQLite.Exception;
+
+ /**
+ * Destructor for object.
+ */
+
+ protected void finalize() {
+ synchronized(this) {
+ _finalize();
+ }
+ }
+
+ private native void _finalize();
+
+ /**
+ * Close the underlying SQLite database file.
+ */
+
+ public void close() throws SQLite.Exception {
+ synchronized(this) {
+ _close();
+ }
+ }
+
+ private native void _close()
+ throws SQLite.Exception;
+
+ /**
+ * Execute an SQL statement and invoke callback methods
+ * for each row of the result set.
+ *
+ * It the method fails, an SQLite.Exception is thrown and
+ * an error code is set, which later can be retrieved by
+ * the last_error() method.
+ *
+ * @param sql the SQL statement to be executed
+ * @param cb the object implementing the callback methods
+ */
+
+ public void exec(String sql, SQLite.Callback cb) throws SQLite.Exception {
+ synchronized(this) {
+ _exec(sql, cb);
+ }
+ }
+
+ private native void _exec(String sql, SQLite.Callback cb)
+ throws SQLite.Exception;
+
+ /**
+ * Execute an SQL statement and invoke callback methods
+ * for each row of the result set. Each '%q' or %Q in the
+ * statement string is substituted by its corresponding
+ * element in the argument vector.
+ *
+ * Example:
+ *
+ * String args[] = new String[1];
+ * args[0] = "tab%";
+ * db.exec("select * from sqlite_master where type like '%q'",
+ * null, args);
+ *
+ *
+ * It the method fails, an SQLite.Exception is thrown and
+ * an error code is set, which later can be retrieved by
+ * the last_error() method.
+ *
+ * @param sql the SQL statement to be executed
+ * @param cb the object implementing the callback methods
+ * @param args arguments for the SQL statement, '%q' substitution
+ */
+
+ public void exec(String sql, SQLite.Callback cb,
+ String args[]) throws SQLite.Exception {
+ synchronized(this) {
+ _exec(sql, cb, args);
+ }
+ }
+
+ private native void _exec(String sql, SQLite.Callback cb, String args[])
+ throws SQLite.Exception;
+
+ /**
+ * Return the row identifier of the last inserted
+ * row.
+ */
+
+ public long last_insert_rowid() {
+ synchronized(this) {
+ return _last_insert_rowid();
+ }
+ }
+
+ private native long _last_insert_rowid();
+
+ /**
+ * Abort the current SQLite operation.
+ */
+
+ public void interrupt() {
+ synchronized(this) {
+ _interrupt();
+ }
+ }
+
+ private native void _interrupt();
+
+ /**
+ * Return the number of changed rows for the last statement.
+ */
+
+ public long changes() {
+ synchronized(this) {
+ return _changes();
+ }
+ }
+
+ private native long _changes();
+
+ /**
+ * Establish a busy callback method which gets called when
+ * an SQLite table is locked.
+ *
+ * @param bh the object implementing the busy callback method
+ */
+
+ public void busy_handler(SQLite.BusyHandler bh) {
+ synchronized(this) {
+ _busy_handler(bh);
+ }
+ }
+
+ private native void _busy_handler(SQLite.BusyHandler bh);
+
+ /**
+ * Set the timeout for waiting for an SQLite table to become
+ * unlocked.
+ *
+ * @param ms number of millisecond to wait
+ */
+
+ public void busy_timeout(int ms) {
+ synchronized(this) {
+ _busy_timeout(ms);
+ }
+ }
+
+ private native void _busy_timeout(int ms);
+
+ /**
+ * Convenience method to retrieve an entire result
+ * set into memory.
+ *
+ * @param sql the SQL statement to be executed
+ * @return result set
+ */
+
+ public TableResult get_table(String sql) throws SQLite.Exception {
+ TableResult ret = new TableResult();
+ if (!is3()) {
+ exec(sql, ret);
+ } else {
+ synchronized(this) {
+ /* only one statement !!! */
+ Vm vm = compile(sql);
+ set_last_error(vm.error_code);
+ while (vm.step(ret)) {
+ set_last_error(vm.error_code);
+ }
+ vm.finalize();
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Convenience method to retrieve an entire result
+ * set into memory.
+ *
+ * @param sql the SQL statement to be executed
+ * @param args arguments for the SQL statement, '%q' substitution
+ * @return result set
+ */
+
+ public TableResult get_table(String sql, String args[])
+ throws SQLite.Exception {
+ TableResult ret = new TableResult();
+ if (!is3()) {
+ exec(sql, ret, args);
+ } else {
+ synchronized(this) {
+ /* only one statement !!! */
+ Vm vm = compile(sql, args);
+ set_last_error(vm.error_code);
+ while (vm.step(ret)) {
+ set_last_error(vm.error_code);
+ }
+ vm.finalize();
+ }
+ }
+ return ret;
+ }
+
+ /**
+ * Convenience method to retrieve an entire result
+ * set into memory.
+ *
+ * @param sql the SQL statement to be executed
+ * @param args arguments for the SQL statement, '%q' substitution
+ * @param tbl TableResult to receive result set
+ * @return result set
+ */
+
+ public void get_table(String sql, String args[], TableResult tbl)
+ throws SQLite.Exception {
+ tbl.clear();
+ if (!is3()) {
+ exec(sql, tbl, args);
+ } else {
+ synchronized(this) {
+ /* only one statement !!! */
+ Vm vm = compile(sql, args);
+ while (vm.step(tbl)) {
+ }
+ vm.finalize();
+ }
+ }
+ }
+
+ /**
+ * See if an SQL statement is complete.
+ * Returns true if the input string comprises
+ * one or more complete SQL statements.
+ *
+ * @param sql the SQL statement to be checked
+ */
+
+ public synchronized static boolean complete(String sql) {
+ return _complete(sql);
+ }
+
+ private native static boolean _complete(String sql);
+
+ /**
+ * Return SQLite version number as string.
+ * Don't rely on this when both SQLite 2 and 3 are compiled
+ * into the native part. Use the class method in this case.
+ */
+
+ public native static String version();
+
+ /**
+ * Return SQLite version number as string.
+ * If the database is not open, unknown is returned.
+ */
+
+ public native String dbversion();
+
+ /**
+ * Create regular function.
+ *
+ * @param name the name of the new function
+ * @param nargs number of arguments to function
+ * @param f interface of function
+ */
+
+ public void create_function(String name, int nargs, Function f) {
+ synchronized(this) {
+ _create_function(name, nargs, f);
+ }
+ }
+
+ private native void _create_function(String name, int nargs, Function f);
+
+ /**
+ * Create aggregate function.
+ *
+ * @param name the name of the new function
+ * @param nargs number of arguments to function
+ * @param f interface of function
+ */
+
+ public void create_aggregate(String name, int nargs, Function f) {
+ synchronized(this) {
+ _create_aggregate(name, nargs, f);
+ }
+ }
+
+ private native void _create_aggregate(String name, int nargs, Function f);
+
+ /**
+ * Set function return type. Only available in SQLite 2.6.0 and
+ * above, otherwise a no-op.
+ *
+ * @param name the name of the function whose return type is to be set
+ * @param type return type code, e.g. SQLite.Constants.SQLITE_NUMERIC
+ */
+
+ public void function_type(String name, int type) {
+ synchronized(this) {
+ _function_type(name, type);
+ }
+ }
+
+ private native void _function_type(String name, int type);
+
+ /**
+ * Return the code of the last error occured in
+ * any of the exec() methods. The value is valid
+ * after an Exception has been reported by one of
+ * these methods. See the Constants
+ * class for possible values.
+ *
+ * @return SQLite error code
+ */
+
+ public int last_error() {
+ return error_code;
+ }
+
+ /**
+ * Internal: set error code.
+ * @param error_code new error code
+ */
+
+ protected void set_last_error(int error_code) {
+ this.error_code = error_code;
+ }
+
+ /**
+ * Return last error message of SQLite3 engine.
+ *
+ * @return error string or null
+ */
+
+ public String error_message() {
+ synchronized(this) {
+ return _errmsg();
+ }
+ }
+
+ private native String _errmsg();
+
+ /**
+ * Return error string given SQLite error code (SQLite2).
+ *
+ * @param error_code the error code
+ * @return error string
+ */
+
+ public static native String error_string(int error_code);
+
+ /**
+ * Set character encoding.
+ * @param enc name of encoding
+ */
+
+ public void set_encoding(String enc) throws SQLite.Exception {
+ synchronized(this) {
+ _set_encoding(enc);
+ }
+ }
+
+ private native void _set_encoding(String enc)
+ throws SQLite.Exception;
+
+ /**
+ * Set authorizer function. Only available in SQLite 2.7.6 and
+ * above, otherwise a no-op.
+ *
+ * @param auth the authorizer function
+ */
+
+ public void set_authorizer(Authorizer auth) {
+ synchronized(this) {
+ _set_authorizer(auth);
+ }
+ }
+
+ private native void _set_authorizer(Authorizer auth);
+
+ /**
+ * Set trace function. Only available in SQLite 2.7.6 and above,
+ * otherwise a no-op.
+ *
+ * @param tr the trace function
+ */
+
+ public void trace(Trace tr) {
+ synchronized(this) {
+ _trace(tr);
+ }
+ }
+
+ private native void _trace(Trace tr);
+
+ /**
+ * Compile and return SQLite VM for SQL statement. Only available
+ * in SQLite 2.8.0 and above, otherwise a no-op.
+ *
+ * @param sql SQL statement to be compiled
+ * @return a Vm object
+ */
+
+ public Vm compile(String sql) throws SQLite.Exception {
+ synchronized(this) {
+ Vm vm = new Vm();
+ vm_compile(sql, vm);
+ return vm;
+ }
+ }
+
+ /**
+ * Compile and return SQLite VM for SQL statement. Only available
+ * in SQLite 3.0 and above, otherwise a no-op.
+ *
+ * @param sql SQL statement to be compiled
+ * @param args arguments for the SQL statement, '%q' substitution
+ * @return a Vm object
+ */
+
+ public Vm compile(String sql, String args[]) throws SQLite.Exception {
+ synchronized(this) {
+ Vm vm = new Vm();
+ vm_compile_args(sql, vm, args);
+ return vm;
+ }
+ }
+
+ /**
+ * Prepare and return SQLite3 statement for SQL. Only available
+ * in SQLite 3.0 and above, otherwise a no-op.
+ *
+ * @param sql SQL statement to be prepared
+ * @return a Stmt object
+ */
+
+ public Stmt prepare(String sql) throws SQLite.Exception {
+ synchronized(this) {
+ Stmt stmt = new Stmt();
+ stmt_prepare(sql, stmt);
+ return stmt;
+ }
+ }
+
+ /**
+ * Open an SQLite3 blob. Only available in SQLite 3.4.0 and above.
+ * @param db database name
+ * @param table table name
+ * @param column column name
+ * @param row row identifier
+ * @param rw if true, open for read-write, else read-only
+ * @return a Blob object
+ */
+
+ public Blob open_blob(String db, String table, String column,
+ long row, boolean rw) throws SQLite.Exception {
+ synchronized(this) {
+ Blob blob = new Blob();
+ _open_blob(db, table, column, row, rw, blob);
+ return blob;
+ }
+ }
+
+ /**
+ * Check type of open database.
+ * @return true if SQLite3 database
+ */
+
+ public native boolean is3();
+
+ /**
+ * Internal compile method.
+ * @param sql SQL statement
+ * @param vm Vm object
+ */
+
+ private native void vm_compile(String sql, Vm vm)
+ throws SQLite.Exception;
+
+ /**
+ * Internal compile method, SQLite 3.0 only.
+ * @param sql SQL statement
+ * @param args arguments for the SQL statement, '%q' substitution
+ * @param vm Vm object
+ */
+
+ private native void vm_compile_args(String sql, Vm vm, String args[])
+ throws SQLite.Exception;
+
+ /**
+ * Internal SQLite3 prepare method.
+ * @param sql SQL statement
+ * @param stmt Stmt object
+ */
+
+ private native void stmt_prepare(String sql, Stmt stmt)
+ throws SQLite.Exception;
+
+ /**
+ * Internal SQLite open blob method.
+ * @param db database name
+ * @param table table name
+ * @param column column name
+ * @param row row identifier
+ * @param rw if true, open for read-write, else read-only
+ * @param blob Blob object
+ */
+
+ private native void _open_blob(String db, String table, String column,
+ long row, boolean rw, Blob blob)
+ throws SQLite.Exception;
+
+ /**
+ * Establish a progress callback method which gets called after
+ * N SQLite VM opcodes.
+ *
+ * @param n number of SQLite VM opcodes until callback is invoked
+ * @param p the object implementing the progress callback method
+ */
+
+ public void progress_handler(int n, SQLite.ProgressHandler p) {
+ synchronized(this) {
+ _progress_handler(n, p);
+ }
+ }
+
+ private native void _progress_handler(int n, SQLite.ProgressHandler p);
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ /**
+ * Static initializer to load the native part.
+ */
+
+ static {
+ try {
+// String path = System.getProperty("SQLite.library.path");
+// if (path == null || path.length() == 0){
+// System.loadLibrary("sqlite_jni");
+// } else {
+// try {
+// java.lang.reflect.Method mapLibraryName;
+// Class param[] = new Class[1];
+// param[0] = String.class;
+// mapLibraryName = System.class.getMethod("mapLibraryName",
+// param);
+// Object args[] = new Object[1];
+// args[0] = "sqlite_jni";
+// String mapped = (String) mapLibraryName.invoke(null, args);
+// System.load(path + java.io.File.separator + mapped);
+// } catch (Throwable t) {
+// System.loadLibrary("sqlite_jni");
+// }
+// }
+ internal_init();
+ } catch (Throwable t) {
+ System.err.println("Unable to load sqlite: " + t);
+ }
+ }
+}
+
diff --git a/sql/src/main/java/SQLite/Exception.java b/sql/src/main/java/SQLite/Exception.java
new file mode 100644
index 0000000..cc26b99
--- /dev/null
+++ b/sql/src/main/java/SQLite/Exception.java
@@ -0,0 +1,18 @@
+package SQLite;
+
+/**
+ * Class for SQLite related exceptions.
+ */
+
+public class Exception extends java.lang.Exception {
+
+ /**
+ * Construct a new SQLite exception.
+ *
+ * @param string error message
+ */
+
+ public Exception(String string) {
+ super(string);
+ }
+}
diff --git a/sql/src/main/java/SQLite/Function.java b/sql/src/main/java/SQLite/Function.java
new file mode 100644
index 0000000..5aa5e33
--- /dev/null
+++ b/sql/src/main/java/SQLite/Function.java
@@ -0,0 +1,59 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's user defined functions.
+ * Each callback method receives a
+ * FunctionContext object
+ * which is used to set the function result or error code.
+ *
");
+ for (i = 0; i < args.length; i++) {
+ pw.print("
" + html_quote(args[i]) + "
");
+ }
+ pw.println("
");
+ break;
+ case MODE_Insert:
+ if (args.length == 0) {
+ break;
+ }
+ tname = tableName;
+ if (destTable != null) {
+ tname = destTable;
+ }
+ pw.print("INSERT INTO " + tname + " VALUES(");
+ for (i = 0; i < args.length; i++) {
+ String tsep = i > 0 ? "," : "";
+ if (args[i] == null) {
+ pw.print(tsep + "NULL");
+ } else if (is_numeric(args[i])) {
+ pw.print(tsep + args[i]);
+ } else {
+ pw.print(tsep + sql_quote(args[i]));
+ }
+ }
+ pw.println(");");
+ break;
+ case MODE_Insert2:
+ if (args.length == 0) {
+ break;
+ }
+ tname = tableName;
+ if (destTable != null) {
+ tname = destTable;
+ }
+ pw.print("INSERT INTO " + tname + " VALUES(");
+ for (i = 0; i < args.length; i++) {
+ String tsep = i > 0 ? "," : "";
+ pw.print(tsep + args[i]);
+ }
+ pw.println(");");
+ break;
+ }
+ return false;
+ }
+
+ void do_meta(String line) {
+ StringTokenizer st = new StringTokenizer(line.toLowerCase());
+ int n = st.countTokens();
+ if (n <= 0) {
+ return;
+ }
+ String cmd = st.nextToken();
+ String args[] = new String[n - 1];
+ int i = 0;
+ while (st.hasMoreTokens()) {
+ args[i] = st.nextToken();
+ ++i;
+ }
+ if (cmd.compareTo(".dump") == 0) {
+ new DBDump(this, args);
+ return;
+ }
+ if (cmd.compareTo(".echo") == 0) {
+ if (args.length > 0 &&
+ (args[0].startsWith("y") || args[0].startsWith("on"))) {
+ echo = true;
+ }
+ return;
+ }
+ if (cmd.compareTo(".exit") == 0) {
+ try {
+ db.close();
+ } catch (Exception e) {
+ }
+ System.exit(0);
+ }
+ if (cmd.compareTo(".header") == 0) {
+ if (args.length > 0 &&
+ (args[0].startsWith("y") || args[0].startsWith("on"))) {
+ showHeader = true;
+ }
+ return;
+ }
+ if (cmd.compareTo(".help") == 0) {
+ pw.println(".dump ?TABLE? ... Dump database in text fmt");
+ pw.println(".echo ON|OFF Command echo on or off");
+ pw.println(".enc ?NAME? Change encoding");
+ pw.println(".exit Exit program");
+ pw.println(".header ON|OFF Display headers on or off");
+ pw.println(".help This message");
+ pw.println(".mode MODE Set output mode to\n" +
+ " line, column, insert\n" +
+ " list, or html");
+ pw.println(".mode insert TABLE Generate SQL insert stmts");
+ pw.println(".schema ?PATTERN? List table schema");
+ pw.println(".separator STRING Set separator string");
+ pw.println(".tables ?PATTERN? List table names");
+ return;
+ }
+ if (cmd.compareTo(".mode") == 0) {
+ if (args.length > 0) {
+ if (args[0].compareTo("line") == 0) {
+ mode = Shell.MODE_Line;
+ } else if (args[0].compareTo("column") == 0) {
+ mode = Shell.MODE_Column;
+ } else if (args[0].compareTo("list") == 0) {
+ mode = Shell.MODE_List;
+ } else if (args[0].compareTo("html") == 0) {
+ mode = Shell.MODE_Html;
+ } else if (args[0].compareTo("insert") == 0) {
+ mode = Shell.MODE_Insert;
+ if (args.length > 1) {
+ destTable = args[1];
+ }
+ }
+ }
+ return;
+ }
+ if (cmd.compareTo(".separator") == 0) {
+ if (args.length > 0) {
+ sep = args[0];
+ }
+ return;
+ }
+ if (cmd.compareTo(".tables") == 0) {
+ TableResult t = null;
+ if (args.length > 0) {
+ try {
+ String qarg[] = new String[1];
+ qarg[0] = args[0];
+ t = db.get_table("SELECT name FROM sqlite_master " +
+ "WHERE type='table' AND " +
+ "name LIKE '%%%q%%' " +
+ "ORDER BY name", qarg);
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ } else {
+ try {
+ t = db.get_table("SELECT name FROM sqlite_master " +
+ "WHERE type='table' ORDER BY name");
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ }
+ if (t != null) {
+ for (i = 0; i < t.nrows; i++) {
+ String tab = ((String[]) t.rows.elementAt(i))[0];
+ if (tab != null) {
+ pw.println(tab);
+ }
+ }
+ }
+ return;
+ }
+ if (cmd.compareTo(".schema") == 0) {
+ if (args.length > 0) {
+ try {
+ String qarg[] = new String[1];
+ qarg[0] = args[0];
+ db.exec("SELECT sql FROM sqlite_master " +
+ "WHERE type!='meta' AND " +
+ "name LIKE '%%%q%%' AND " +
+ "sql NOTNULL " +
+ "ORDER BY type DESC, name",
+ this, qarg);
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ } else {
+ try {
+ db.exec("SELECT sql FROM sqlite_master " +
+ "WHERE type!='meta' AND " +
+ "sql NOTNULL " +
+ "ORDER BY tbl_name, type DESC, name",
+ this);
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ }
+ return;
+ }
+ if (cmd.compareTo(".enc") == 0) {
+ try {
+ db.set_encoding(args.length > 0 ? args[0] : null);
+ } catch (Exception e) {
+ err.println("" + e);
+ err.flush();
+ }
+ return;
+ }
+ err.println("Unknown command '" + cmd + "'");
+ err.flush();
+ }
+
+ String read_line(BufferedReader is, String prompt) {
+ try {
+ if (prompt != null) {
+ pw.print(prompt);
+ pw.flush();
+ }
+ String line = is.readLine();
+ return line;
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ void do_input(BufferedReader is) {
+ String line, sql = null;
+ String prompt = "SQLITE> ";
+ while ((line = read_line(is, prompt)) != null) {
+ if (echo) {
+ pw.println(line);
+ }
+ if (line.length() > 0 && line.charAt(0) == '.') {
+ do_meta(line);
+ } else {
+ if (sql == null) {
+ sql = line;
+ } else {
+ sql = sql + " " + line;
+ }
+ if (Database.complete(sql)) {
+ try {
+ db.exec(sql, this);
+ } catch (Exception e) {
+ if (!echo) {
+ err.println(sql);
+ }
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ sql = null;
+ prompt = "SQLITE> ";
+ } else {
+ prompt = "SQLITE? ";
+ }
+ }
+ pw.flush();
+ }
+ if (sql != null) {
+ err.println("Incomplete SQL: " + sql);
+ err.flush();
+ }
+ }
+
+ void do_cmd(String sql) {
+ if (db == null) {
+ return;
+ }
+ if (sql.length() > 0 && sql.charAt(0) == '.') {
+ do_meta(sql);
+ } else {
+ try {
+ db.exec(sql, this);
+ } catch (Exception e) {
+ err.println("SQL Error: " + e);
+ err.flush();
+ }
+ }
+ }
+
+ public static void main(String args[]) {
+ Shell s = new Shell(System.out, System.err);
+ s.mode = Shell.MODE_List;
+ s.sep = "|";
+ s.showHeader = false;
+ s.db = new Database();
+ String dbname = null, sql = null;
+ for (int i = 0; i < args.length; i++) {
+ if(args[i].compareTo("-html") ==0) {
+ s.mode = Shell.MODE_Html;
+ } else if (args[i].compareTo("-list") == 0) {
+ s.mode = Shell.MODE_List;
+ } else if (args[i].compareTo("-line") == 0) {
+ s.mode = Shell.MODE_Line;
+ } else if (i < args.length - 1 &&
+ args[i].compareTo("-separator") == 0) {
+ ++i;
+ s.sep = args[i];
+ } else if (args[i].compareTo("-header") == 0) {
+ s.showHeader = true;
+ } else if (args[i].compareTo("-noheader") == 0) {
+ s.showHeader = false;
+ } else if (args[i].compareTo("-echo") == 0) {
+ s.echo = true;
+ } else if (dbname == null) {
+ dbname = args[i];
+ } else if (sql == null) {
+ sql = args[i];
+ } else {
+ System.err.println("Arguments: ?OPTIONS? FILENAME ?SQL?");
+ System.exit(1);
+ }
+ }
+ if (dbname == null) {
+ System.err.println("No database file given");
+ System.exit(1);
+ }
+ try {
+ s.db.open(dbname, 0);
+ } catch (Exception e) {
+ System.err.println("Unable to open database: " + e);
+ System.exit(1);
+ }
+ if (sql != null) {
+ s.do_cmd(sql);
+ } else {
+ // BEGIN android-modified
+ BufferedReader is =
+ new BufferedReader(new InputStreamReader(System.in), 8192);
+ // END android-modified
+ s.do_input(is);
+ }
+ try {
+ s.db.close();
+ } catch (Exception ee) {
+ }
+ }
+}
+
+/**
+ * Internal class for dumping an entire database.
+ * It contains a special callback interface to traverse the
+ * tables of the current database and output create SQL statements
+ * and for the data insert SQL statements.
+ */
+
+class DBDump implements Callback {
+ Shell s;
+
+ DBDump(Shell s, String tables[]) {
+ this.s = s;
+ s.pw.println("BEGIN TRANSACTION;");
+ if (tables == null || tables.length == 0) {
+ try {
+ s.db.exec("SELECT name, type, sql FROM sqlite_master " +
+ "WHERE type!='meta' AND sql NOT NULL " +
+ "ORDER BY substr(type,2,1), name", this);
+ } catch (Exception e) {
+ s.err.println("SQL Error: " + e);
+ s.err.flush();
+ }
+ } else {
+ String arg[] = new String[1];
+ for (int i = 0; i < tables.length; i++) {
+ arg[0] = tables[i];
+ try {
+ s.db.exec("SELECT name, type, sql FROM sqlite_master " +
+ "WHERE tbl_name LIKE '%q' AND type!='meta' " +
+ " AND sql NOT NULL " +
+ " ORDER BY substr(type,2,1), name",
+ this, arg);
+ } catch (Exception e) {
+ s.err.println("SQL Error: " + e);
+ s.err.flush();
+ }
+ }
+ }
+ s.pw.println("COMMIT;");
+ }
+
+ public void columns(String col[]) {
+ /* Empty body to satisfy SQLite.Callback interface. */
+ }
+
+ public void types(String args[]) {
+ /* Empty body to satisfy SQLite.Callback interface. */
+ }
+
+ public boolean newrow(String args[]) {
+ if (args.length != 3) {
+ return true;
+ }
+ s.pw.println(args[2] + ";");
+ if (args[1].compareTo("table") == 0) {
+ Shell s2 = (Shell) s.clone();
+ s2.mode = Shell.MODE_Insert;
+ s2.set_table_name(args[0]);
+ String qargs[] = new String[1];
+ qargs[0] = args[0];
+ try {
+ if (s2.db.is3()) {
+ TableResult t = null;
+ t = s2.db.get_table("PRAGMA table_info('%q')", qargs);
+ String query;
+ if (t != null) {
+ StringBuffer sb = new StringBuffer();
+ String sep = "";
+
+ sb.append("SELECT ");
+ for (int i = 0; i < t.nrows; i++) {
+ String col = ((String[]) t.rows.elementAt(i))[1];
+ sb.append(sep + "quote(" +
+ Shell.sql_quote_dbl(col) + ")");
+ sep = ",";
+ }
+ sb.append(" from '%q'");
+ query = sb.toString();
+ s2.mode = Shell.MODE_Insert2;
+ } else {
+ query = "SELECT * from '%q'";
+ }
+ s2.db.exec(query, s2, qargs);
+ } else {
+ s2.db.exec("SELECT * from '%q'", s2, qargs);
+ }
+ } catch (Exception e) {
+ s.err.println("SQL Error: " + e);
+ s.err.flush();
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/sql/src/main/java/SQLite/Stmt.java b/sql/src/main/java/SQLite/Stmt.java
new file mode 100644
index 0000000..c4f72ed
--- /dev/null
+++ b/sql/src/main/java/SQLite/Stmt.java
@@ -0,0 +1,288 @@
+package SQLite;
+
+/**
+ * Class to represent compiled SQLite3 statement.
+ *
+ * Note, that all native methods of this class are
+ * not synchronized, i.e. it is up to the caller
+ * to ensure that only one thread is in these
+ * methods at any one time.
+ */
+
+public class Stmt {
+
+ /**
+ * Internal handle for the SQLite3 statement.
+ */
+
+ private long handle = 0;
+
+ /**
+ * Internal last error code for prepare()/step() methods.
+ */
+
+ protected int error_code = 0;
+
+ /**
+ * Prepare the next SQL statement for the Stmt instance.
+ * @return true when the next piece of the SQL statement sequence
+ * has been prepared, false on end of statement sequence.
+ */
+
+ public native boolean prepare() throws SQLite.Exception;
+
+ /**
+ * Perform one step of compiled SQLite3 statement.
+ *
+ * Example:
+ *
+ * ...
+ * try {
+ * Stmt s = db.prepare("select * from x; select * from y;");
+ * s.bind(...);
+ * ...
+ * s.bind(...);
+ * while (s.step(cb)) {
+ * Object o = s.value(...);
+ * ...
+ * }
+ * // s.reset() for re-execution or
+ * // s.prepare() for the next piece of SQL
+ * while (s.prepare()) {
+ * s.bind(...);
+ * ...
+ * s.bind(...);
+ * while (s.step(cb)) {
+ * Object o = s.value(...);
+ * ...
+ * }
+ * }
+ * } catch (SQLite.Exception e) {
+ * s.close();
+ * }
+ *
+ *
+ * @return true when row data is available, false on end
+ * of result set.
+ */
+
+ public native boolean step() throws SQLite.Exception;
+
+ /**
+ * Close the compiled SQLite3 statement.
+ */
+
+ public native void close() throws SQLite.Exception;
+
+ /**
+ * Reset the compiled SQLite3 statement without
+ * clearing parameter bindings.
+ */
+
+ public native void reset() throws SQLite.Exception;
+
+ /**
+ * Clear all bound parameters of the compiled SQLite3 statement.
+ */
+
+ public native void clear_bindings() throws SQLite.Exception;
+
+ /**
+ * Bind positional integer value to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter
+ */
+
+ public native void bind(int pos, int value) throws SQLite.Exception;
+
+ /**
+ * Bind positional long value to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter
+ */
+
+ public native void bind(int pos, long value) throws SQLite.Exception;
+
+ /**
+ * Bind positional double value to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter
+ */
+
+ public native void bind(int pos, double value) throws SQLite.Exception;
+
+ /**
+ * Bind positional byte array to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter, may be null
+ */
+
+ public native void bind(int pos, byte[] value) throws SQLite.Exception;
+
+ /**
+ * Bind positional String to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param value value of parameter, may be null
+ */
+
+ public native void bind(int pos, String value) throws SQLite.Exception;
+
+ /**
+ * Bind positional SQL null to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ */
+
+ public native void bind(int pos) throws SQLite.Exception;
+
+ /**
+ * Bind positional zero'ed blob to compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @param length byte size of zero blob
+ */
+
+ public native void bind_zeroblob(int pos, int length)
+ throws SQLite.Exception;
+
+ /**
+ * Return number of parameters in compiled SQLite3 statement.
+ * @return int number of parameters
+ */
+
+ public native int bind_parameter_count() throws SQLite.Exception;
+
+ /**
+ * Return name of parameter in compiled SQLite3 statement.
+ * @param pos parameter index, 1-based
+ * @return String parameter name
+ */
+
+ public native String bind_parameter_name(int pos) throws SQLite.Exception;
+
+ /**
+ * Return index of named parameter in compiled SQLite3 statement.
+ * @param name of parameter
+ * @return int index of parameter, 1-based
+ */
+
+ public native int bind_parameter_index(String name)
+ throws SQLite.Exception;
+
+
+ /**
+ * Retrieve integer column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return int column value
+ */
+
+ public native int column_int(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve long column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return long column value
+ */
+ public native long column_long(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve double column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return double column value
+ */
+ public native double column_double(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve blob column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return byte[] column value
+ */
+ public native byte[] column_bytes(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve string column from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String column value
+ */
+ public native String column_string(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve column type from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return column type code, e.g. SQLite.Constants.SQLITE_INTEGER
+ */
+ public native int column_type(int col) throws SQLite.Exception;
+
+ /**
+ * Retrieve number of columns of exec'ed SQLite3 statement.
+ * @return int number of columns
+ */
+
+ public native int column_count() throws SQLite.Exception;
+
+ /**
+ * Retrieve column data as object from exec'ed SQLite3 statement.
+ * @param col column number, 0-based
+ * @return Object or null
+ */
+
+ public Object column(int col) throws SQLite.Exception {
+ switch (column_type(col)) {
+ case Constants.SQLITE_INTEGER:
+ return new Long(column_long(col));
+ case Constants.SQLITE_FLOAT:
+ return new Double(column_double(col));
+ case Constants.SQLITE_BLOB:
+ return column_bytes(col);
+ case Constants.SQLITE3_TEXT:
+ return column_string(col);
+ }
+ return null;
+ }
+
+ /**
+ * Return table name of column of SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String or null
+ */
+
+ public native String column_table_name(int col) throws SQLite.Exception;
+
+ /**
+ * Return database name of column of SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String or null
+ */
+
+ public native String column_database_name(int col) throws SQLite.Exception;
+
+ /**
+ * Return declared column type of SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String or null
+ */
+
+ public native String column_decltype(int col) throws SQLite.Exception;
+
+ /**
+ * Return origin column name of column of SQLite3 statement.
+ * @param col column number, 0-based
+ * @return String or null
+ */
+
+ public native String column_origin_name(int col) throws SQLite.Exception;
+
+ /**
+ * Destructor for object.
+ */
+
+ protected native void finalize();
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ static {
+ internal_init();
+ }
+}
diff --git a/sql/src/main/java/SQLite/StringEncoder.java b/sql/src/main/java/SQLite/StringEncoder.java
new file mode 100644
index 0000000..c2f20ad
--- /dev/null
+++ b/sql/src/main/java/SQLite/StringEncoder.java
@@ -0,0 +1,201 @@
+package SQLite;
+
+/**
+ * String encoder/decoder for SQLite.
+ *
+ * This module was kindly donated by Eric van der Maarel of Nedap N.V.
+ *
+ * This encoder was implemented based on an original idea from an anonymous
+ * author in the source code of the SQLite distribution.
+ * I feel obliged to provide a quote from the original C-source code:
+ *
+ * "The author disclaims copyright to this source code. In place of
+ * a legal notice, here is a blessing:
+ *
+ * May you do good and not evil.
+ * May you find forgiveness for yourself and forgive others.
+ * May you share freely, never taking more than you give."
+ *
+ */
+
+public class StringEncoder {
+
+ /**
+ * Encodes the given byte array into a string that can be used by
+ * the SQLite database. The database cannot handle null (0x00) and
+ * the character '\'' (0x27). The encoding consists of escaping
+ * these characters with a reserved character (0x01). The escaping
+ * is applied after determining and applying a shift that minimizes
+ * the number of escapes required.
+ * With this encoding the data of original size n is increased to a
+ * maximum of 1+(n*257)/254.
+ * For sufficiently large n the overhead is thus less than 1.2%.
+ * @param a the byte array to be encoded. A null reference is handled as
+ * an empty array.
+ * @return the encoded bytes as a string. When an empty array is
+ * provided a string of length 1 is returned, the value of
+ * which is bogus.
+ * When decoded with this class' decode method
+ * a string of size 1 will return an empty byte array.
+ */
+
+ public static String encode(byte[] a) {
+ // check input
+ if (a == null || a.length == 0) {
+ // bogus shift, no data
+ return "x";
+ }
+ // determine count
+ int[] cnt = new int[256];
+ for (int i = 0 ; i < a.length; i++) {
+ cnt[a[i] & 0xff]++;
+ }
+ // determine shift for minimum number of escapes
+ int shift = 1;
+ int nEscapes = a.length;
+ for (int i = 1; i < 256; i++) {
+ if (i == '\'') {
+ continue;
+ }
+ int sum = cnt[i] + cnt[(i + 1) & 0xff] + cnt[(i + '\'') & 0xff];
+ if (sum < nEscapes) {
+ nEscapes = sum;
+ shift = i;
+ if (nEscapes == 0) {
+ // cannot become smaller
+ break;
+ }
+ }
+ }
+ // construct encoded output
+ int outLen = a.length + nEscapes + 1;
+ StringBuffer out = new StringBuffer(outLen);
+ out.append((char)shift);
+ for (int i = 0; i < a.length; i++) {
+ // apply shift
+ char c = (char)((a[i] - shift)&0xff);
+ // insert escapes
+ if (c == 0) { // forbidden
+ out.append((char)1);
+ out.append((char)1);
+ } else if (c == 1) { // escape character
+ out.append((char)1);
+ out.append((char)2);
+ } else if (c == '\'') { // forbidden
+ out.append((char)1);
+ out.append((char)3);
+ } else {
+ out.append(c);
+ }
+ }
+ return out.toString();
+ }
+
+ /**
+ * Decodes the given string that is assumed to be a valid encoding
+ * of a byte array. Typically the given string is generated by
+ * this class' encode method.
+ * @param s the given string encoding.
+ * @return the byte array obtained from the decoding.
+ * @throws IllegalArgumentException when the string given is not
+ * a valid encoded string for this encoder.
+ */
+
+ public static byte[] decode(String s) {
+ char[] a = s.toCharArray();
+ if (a.length > 2 && a[0] == 'X' &&
+ a[1] == '\'' && a[a.length-1] == '\'') {
+ // SQLite3 BLOB syntax
+ byte[] result = new byte[(a.length-3)/2];
+ for (int i = 2, k = 0; i < a.length - 1; i += 2, k++) {
+ byte tmp = (byte) (a[i] - '0');
+ if (tmp > 15) {
+ tmp -= 0x20;
+ }
+ result[k] = (byte) (tmp << 4);
+ tmp = (byte) (a[i+1] - '0');
+ if (tmp > 15) {
+ tmp -= 0x20;
+ }
+ result[k] |= tmp;
+ }
+ return result;
+ }
+ // first element is the shift
+ byte[] result = new byte[a.length-1];
+ int i = 0;
+ int shift = s.charAt(i++);
+ int j = 0;
+ while (i < s.length()) {
+ int c;
+ if ((c = s.charAt(i++)) == 1) { // escape character found
+ if ((c = s.charAt(i++)) == 1) {
+ c = 0;
+ } else if (c == 2) {
+ c = 1;
+ } else if (c == 3) {
+ c = '\'';
+ } else {
+ throw new IllegalArgumentException(
+ "invalid string passed to decoder: " + j);
+ }
+ }
+ // do shift
+ result[j++] = (byte)((c + shift) & 0xff);
+ }
+ int outLen = j;
+ // provide array of correct length
+ if (result.length != outLen) {
+ result = byteCopy(result, 0, outLen, new byte[outLen]);
+ }
+ return result;
+ }
+
+ /**
+ * Copies count elements from source, starting at element with
+ * index offset, to the given target.
+ * @param source the source.
+ * @param offset the offset.
+ * @param count the number of elements to be copied.
+ * @param target the target to be returned.
+ * @return the target being copied to.
+ */
+
+ private static byte[] byteCopy(byte[] source, int offset,
+ int count, byte[] target) {
+ for (int i = offset, j = 0; i < offset + count; i++, j++) {
+ target[j] = source[i];
+ }
+ return target;
+ }
+
+
+ static final char[] xdigits = {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ /**
+ * Encodes the given byte array into SQLite3 blob notation, ie X'..'
+ * @param a the byte array to be encoded. A null reference is handled as
+ * an empty array.
+ * @return the encoded bytes as a string.
+ */
+
+ public static String encodeX(byte[] a) {
+ // check input
+ if (a == null || a.length == 0) {
+ return "X''";
+ }
+ int outLen = a.length + 3;
+ StringBuffer out = new StringBuffer(outLen);
+ out.append('X');
+ out.append('\'');
+ for (int i = 0; i < a.length; i++) {
+ out.append(xdigits[a[i] >> 4]);
+ out.append(xdigits[a[i] & 0x0F]);
+ }
+ out.append('\'');
+ return out.toString();
+ }
+}
diff --git a/sql/src/main/java/SQLite/TableResult.java b/sql/src/main/java/SQLite/TableResult.java
new file mode 100644
index 0000000..1a7fb57
--- /dev/null
+++ b/sql/src/main/java/SQLite/TableResult.java
@@ -0,0 +1,133 @@
+package SQLite;
+
+import java.util.Vector;
+
+/**
+ * Class representing an SQLite result set as
+ * returned by the
+ * Database.get_table
+ * convenience method.
+ *
+ * Example:
+ *
+ *
+ * ...
+ * SQLite.Database db = new SQLite.Database();
+ * db.open("db", 0);
+ * System.out.print(db.get_table("select * from TEST"));
+ * ...
+ *
+ */
+
+public class TableResult implements Callback {
+
+ /**
+ * Number of columns in the result set.
+ */
+
+ public int ncolumns;
+
+ /**
+ * Number of rows in the result set.
+ */
+
+ public int nrows;
+
+ /**
+ * Column names of the result set.
+ */
+
+ public String column[];
+
+ /**
+ * Types of columns of the result set or null.
+ */
+
+ public String types[];
+
+ /**
+ * Rows of the result set. Each row is stored as a String array.
+ */
+
+ public Vector rows;
+
+ /**
+ * Create an empty result set.
+ */
+
+ public TableResult() {
+ clear();
+ }
+
+ /**
+ * Clear result set.
+ */
+
+ public void clear() {
+ column = new String[0];
+ types = null;
+ rows = new Vector();
+ ncolumns = nrows = 0;
+ }
+
+ /**
+ * Callback method used while the query is executed.
+ */
+
+ public void columns(String coldata[]) {
+ column = coldata;
+ ncolumns = column.length;
+ }
+
+ /**
+ * Callback method used while the query is executed.
+ */
+
+ public void types(String types[]) {
+ this.types = types;
+ }
+
+ /**
+ * Callback method used while the query is executed.
+ */
+
+ public boolean newrow(String rowdata[]) {
+ if (rowdata != null) {
+ rows.addElement(rowdata);
+ nrows++;
+ }
+ return false;
+ }
+
+ /**
+ * Make String representation of result set.
+ */
+
+ public String toString() {
+ StringBuffer sb = new StringBuffer();
+ int i;
+ for (i = 0; i < ncolumns; i++) {
+ sb.append(column[i] == null ? "NULL" : column[i]);
+ sb.append('|');
+ }
+ sb.append('\n');
+ for (i = 0; i < nrows; i++) {
+ int k;
+ String row[] = (String[]) rows.elementAt(i);
+ for (k = 0; k < ncolumns; k++) {
+ sb.append(row[k] == null ? "NULL" : row[k]);
+ sb.append('|');
+ }
+ sb.append('\n');
+ }
+ return sb.toString();
+ }
+}
diff --git a/sql/src/main/java/SQLite/Trace.java b/sql/src/main/java/SQLite/Trace.java
new file mode 100644
index 0000000..19ed2a1
--- /dev/null
+++ b/sql/src/main/java/SQLite/Trace.java
@@ -0,0 +1,17 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's trace function.
+ */
+
+public interface Trace {
+
+ /**
+ * Callback to trace (ie log) one SQL statement.
+ *
+ * @param stmt SQL statement string
+ */
+
+ public void trace(String stmt);
+}
+
diff --git a/sql/src/main/java/SQLite/Vm.java b/sql/src/main/java/SQLite/Vm.java
new file mode 100644
index 0000000..9856ed0
--- /dev/null
+++ b/sql/src/main/java/SQLite/Vm.java
@@ -0,0 +1,78 @@
+package SQLite;
+
+/**
+ * Class to represent compiled SQLite VM.
+ */
+
+public class Vm {
+
+ /**
+ * Internal handle for the compiled SQLite VM.
+ */
+
+ private long handle = 0;
+
+ /**
+ * Internal last error code for compile()/step() methods.
+ */
+
+ protected int error_code = 0;
+
+ /**
+ * Perform one step on compiled SQLite VM.
+ * The result row is passed to the given callback interface.
+ *
+ * Example:
+ *
+ * ...
+ * try {
+ * Vm vm = db.compile("select * from x; select * from y;");
+ * while (vm.step(cb)) {
+ * ...
+ * }
+ * while (vm.compile()) {
+ * while (vm.step(cb)) {
+ * ...
+ * }
+ * }
+ * } catch (SQLite.Exception e) {
+ * }
+ *
+ *
+ * @param cb the object implementing the callback methods.
+ * @return true as long as more row data can be retrieved,
+ * false, otherwise.
+ */
+
+ public native boolean step(Callback cb) throws SQLite.Exception;
+
+ /**
+ * Compile the next SQL statement for the SQLite VM instance.
+ * @return true when SQL statement has been compiled, false
+ * on end of statement sequence.
+ */
+
+ public native boolean compile() throws SQLite.Exception;
+
+ /**
+ * Abort the compiled SQLite VM.
+ */
+
+ public native void stop() throws SQLite.Exception;
+
+ /**
+ * Destructor for object.
+ */
+
+ protected native void finalize();
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ static {
+ internal_init();
+ }
+}
diff --git a/sql/src/main/java/java/sql/Array.java b/sql/src/main/java/java/sql/Array.java
new file mode 100644
index 0000000..6113c46
--- /dev/null
+++ b/sql/src/main/java/java/sql/Array.java
@@ -0,0 +1,178 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.util.Map;
+
+/**
+ * A Java representation of the SQL {@code ARRAY} type.
+ *
+ * @since Android 1.0
+ */
+public interface Array {
+
+ /**
+ * Retrieves the contents of the SQL {@code ARRAY} value as a Java array
+ * object.
+ *
+ * @return A Java array containing the elements of this Array
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Object getArray() throws SQLException;
+
+ /**
+ * Returns part of the SQL {@code ARRAY} associated with this array,
+ * starting at a particular {@code index} and comprising up to {@code count}
+ * successive elements of the SQL array.
+ *
+ * @param index
+ * the start position in the array where the values are
+ * retrieved.
+ * @param count
+ * the number of elements to retrieve.
+ * @return A Java array containing the desired set of elements from this Array
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Object getArray(long index, int count) throws SQLException;
+
+ /**
+ * Returns part of the SQL {@code ARRAY} associated with this array,
+ * starting at a particular {@code index} and comprising up to {@code count}
+ * successive elements of the SQL array.
+ *
+ * @param index
+ * the start position in the array where the values are
+ * retrieved.
+ * @param count
+ * the number of elements to retrieve.
+ * @param map
+ * the map defining the correspondence between SQL type names
+ * and Java types.
+ * @return A Java array containing the desired set of elements from this Array
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Object getArray(long index, int count, Map> map)
+ throws SQLException;
+
+ /**
+ * Returns the data from the underlying SQL {@code ARRAY} as a Java array.
+ *
+ * @param map
+ * the map defining the correspondence between SQL type names
+ * and Java types.
+ * @return A Java array containing the elements of this array
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Object getArray(Map> map) throws SQLException;
+
+ /**
+ * Returns the JDBC type of the entries in this array's underlying
+ * SQL array.
+ *
+ * @return An integer constant from the {@code java.sql.Types} class
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public int getBaseType() throws SQLException;
+
+ /**
+ * Returns the SQL type name of the entries in this array's underlying
+ * SQL array.
+ *
+ * @return The database specific name or a fully-qualified SQL type name.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getBaseTypeName() throws SQLException;
+
+ /**
+ * Returns a ResultSet object which holds the entries of the SQL {@code
+ * ARRAY} associated with this array.
+ *
+ * @return the elements of the array as a {@code ResultSet}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getResultSet() throws SQLException;
+
+ /**
+ * Returns a {@code ResultSet} object that holds the entries of a subarray,
+ * beginning at a particular index and comprising up to {@code count}
+ * successive entries.
+ *
+ * @param index
+ * the start position in the array where the values are
+ * retrieved.
+ * @param count
+ * the number of elements to retrieve.
+ * @return the elements of the array as a {@code ResultSet}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getResultSet(long index, int count) throws SQLException;
+
+ /**
+ * Returns a {@code ResultSet} object that holds the entries of a subarray,
+ * beginning at a particular index and comprising up to {@code count}
+ * successive entries.
+ *
+ * @param index
+ * the start position in the array where the values are
+ * retrieved.
+ * @param count
+ * the number of elements to retrieve.
+ * @param map
+ * the map defining the correspondence between SQL type names
+ * and Java types.
+ * @return the {@code ResultSet} the array's custom type values. if a
+ * database error has occurred.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getResultSet(long index, int count,
+ Map> map) throws SQLException;
+
+ /**
+ * Returns a {@code ResultSet} object which holds the entries of the SQL
+ * {@code ARRAY} associated with this array.
+ *
+ * @param map
+ * the map defining the correspondence between SQL type names
+ * and Java types.
+ * @return the array as a {@code ResultSet}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getResultSet(Map> map)
+ throws SQLException;
+
+}
diff --git a/sql/src/main/java/java/sql/BatchUpdateException.java b/sql/src/main/java/java/sql/BatchUpdateException.java
new file mode 100644
index 0000000..36a7ef9
--- /dev/null
+++ b/sql/src/main/java/java/sql/BatchUpdateException.java
@@ -0,0 +1,170 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.Serializable;
+
+/**
+ * This exception is thrown if a problem occurs during a batch update operation.
+ *
+ * A {@code BatchUpdateException} provides additional information about the
+ * problem that occurred, compared with a standard {@code SQLException}. It
+ * supplies update counts for successful commands which were executed before the
+ * exception was encountered.
+ *
+ * The element order in the array of update counts matches the order that the
+ * commands were added to the batch operation.
+ *
+ * Once a batch update command fails and a {@code BatchUpdateException} is
+ * thrown, the JDBC driver may continue processing the remaining commands in the
+ * batch. If the driver does process more commands after the problem occurs, the
+ * array returned by {@code BatchUpdateException.getUpdateCounts} has an element
+ * for every command in the batch, not only those that executed successfully. In
+ * this case, the array element for any command which encountered a problem is
+ * set to {@code Statement.EXECUTE_FAILED}.
+ *
+ *
+ * @since Android 1.0
+ */
+public class BatchUpdateException extends SQLException implements Serializable {
+
+ private static final long serialVersionUID = 5977529877145521757L;
+
+ private int[] updateCounts = null;
+
+ /**
+ * Creates a default {@code BatchUpdateException} with the parameters
+ * reason, SQLState, and update counts set to {@code
+ * null} and the vendor code set to 0.
+ *
+ * @since Android 1.0
+ */
+ public BatchUpdateException() {
+ super();
+ }
+
+ /**
+ * Creates a {@code BatchUpdateException} with the {@code updateCounts} set
+ * to the supplied value. All other fields are set to their
+ * default values.
+ *
+ * @param updateCounts
+ * the array of {@code updateCounts} giving the number of
+ * successful updates (or another status code) for each command
+ * in the batch that was attempted.
+ * @since Android 1.0
+ */
+ public BatchUpdateException(int[] updateCounts) {
+ super();
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Creates a {@code BatchUpdateException} with the {@code updateCounts} and
+ * {@code reason} set to the supplied values. All other fields are set to their
+ * default values.
+ *
+ * @param reason
+ * the message providing information about the source of this
+ * exception.
+ * @param updateCounts
+ * the array of {@code updateCounts} giving the number of
+ * successful updates (or another status code) for each command
+ * in the batch that was attempted.
+ * @since Android 1.0
+ */
+ public BatchUpdateException(String reason, int[] updateCounts) {
+ super(reason);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Creates a {@code BatchUpdateException} with the {@code reason}, {@code
+ * SQLState} and {@code updateCounts} set to the supplied values. All other
+ * fields are set to their default values.
+ *
+ * @param reason
+ * the message providing information about the source of this
+ * exception.
+ * @param SQLState
+ * the X/OPEN value to use for the {@code SQLState}
+ * @param updateCounts
+ * the array of {@code updateCounts} giving the number of
+ * successful updates (or another status code) for each command
+ * in the batch that was attempted.
+ * @since Android 1.0
+ */
+ public BatchUpdateException(String reason, String SQLState,
+ int[] updateCounts) {
+ super(reason, SQLState);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Creates a {@code BatchUpdateException} for the case where all relevant
+ * information is provided.
+ *
+ * @param reason
+ * the message providing information about the source of this
+ * exception.
+ * @param SQLState
+ * the X/OPEN value to use for the {@code SQLState}.
+ * @param vendorCode
+ * the value to use for the vendor error code.
+ * @param updateCounts
+ * the array of {@code updateCounts} giving the number of
+ * successful updates (or another status code) for each command
+ * in the batch that was attempted.
+ * @since Android 1.0
+ */
+ public BatchUpdateException(String reason, String SQLState, int vendorCode,
+ int[] updateCounts) {
+ super(reason, SQLState, vendorCode);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Gets the update count array giving status information for every
+ * command that was attempted in the batch.
+ *
+ * If a batch update command fails and a {@code BatchUpdateException} is
+ * thrown, the JDBC driver may continue processing the remaining commands in
+ * the batch. If the driver does so, the array returned by {@code
+ * BatchUpdateException.getUpdateCounts} has an element for every command in
+ * the batch, not only those that executed successfully. In this case, the
+ * array element for any command which encountered a problem is set to
+ * {@code Statement.EXECUTE_FAILED}.
+ *
+ * @return an array that contains the successful update counts, before this
+ * exception was thrown. Alternatively, if the driver continues to
+ * process commands following an error, for each successive command
+ * there is a corresponding element in the array giving one of the
+ * following status values:
+ *
+ *
the number of successful updates
{@code
+ * Statement.SUCCESS_NO_INFO} indicating that the command completed
+ * successfully, but the amount of altered rows is unknown.
+ *
{@code Statement.EXECUTE_FAILED} indicating that the command
+ * was unsuccessful.
+ *
+ * @since Android 1.0
+ */
+ public int[] getUpdateCounts() {
+ return updateCounts;
+ }
+}
diff --git a/sql/src/main/java/java/sql/Blob.java b/sql/src/main/java/java/sql/Blob.java
new file mode 100644
index 0000000..e6d9b19
--- /dev/null
+++ b/sql/src/main/java/java/sql/Blob.java
@@ -0,0 +1,182 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.OutputStream;
+import java.io.InputStream;
+
+/**
+ * A Java interface representing the SQL {@code BLOB} type.
+ *
+ * An SQL {@code BLOB} type stores a large array of binary data (bytes) as the
+ * value in a column of a database.
+ *
+ * The {@code java.sql.Blob} interface provides methods for setting and
+ * retrieving data in the {@code Blob}, for querying {@code Blob} data length,
+ * and for searching for data within the {@code Blob}.
+ *
+ * @since Android 1.0
+ */
+public interface Blob {
+
+ /**
+ * Retrieves this {@code Blob} object as a binary stream.
+ *
+ * @return a binary {@code InputStream} giving access to the {@code Blob}
+ * data.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public InputStream getBinaryStream() throws SQLException;
+
+ /**
+ * Gets a portion of the value of this {@code Blob} as an array of bytes.
+ *
+ * @param pos
+ * the position of the first byte in the {@code Blob} to get,
+ * where the first byte in the {@code Blob} has position 1.
+ * @param length
+ * the number of bytes to get.
+ * @return a byte array containing the data from the {@code Blob}, starting
+ * at {@code pos} and is up to {@code length} bytes long.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public byte[] getBytes(long pos, int length) throws SQLException;
+
+ /**
+ * Gets the number of bytes in this {@code Blob} object.
+ *
+ * @return a {@code long} value with the length of the {@code Blob} in
+ * bytes.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public long length() throws SQLException;
+
+ /**
+ * Search for the position in this {@code Blob} at which a specified pattern
+ * begins, starting at a specified position within the {@code Blob}.
+ *
+ * @param pattern
+ * a {@code Blob} containing the pattern of data to search for in
+ * this {@code Blob}.
+ * @param start
+ * the position within this {@code Blob} to start the search,
+ * where the first position in the {@code Blob} is {@code 1}.
+ * @return a {@code long} value with the position at which the pattern
+ * begins. Returns {@code -1} if the pattern is not found in this
+ * {@code Blob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public long position(Blob pattern, long start) throws SQLException;
+
+ /**
+ * Search for the position in this {@code Blob} at which the specified
+ * pattern begins, starting at a specified position within the {@code Blob}.
+ *
+ * @param pattern
+ * a byte array containing the pattern of data to search for in
+ * this {@code Blob}.
+ * @param start
+ * the position within this {@code Blob} to start the search,
+ * where the first position in the {@code Blob} is {@code 1}.
+ * @return a {@code long} value with the position at which the pattern
+ * begins. Returns {@code -1} if the pattern is not found in this
+ * {@code Blob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public long position(byte[] pattern, long start) throws SQLException;
+
+ /**
+ * Gets a stream that can be used to write binary data to this {@code Blob}.
+ *
+ * @param pos
+ * the position within this {@code Blob} at which to start
+ * writing, where the first position in the {@code Blob} is
+ * {@code 1}.
+ * @return a binary {@code InputStream} which can be used to write data into
+ * the {@code Blob} starting at the specified position.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public OutputStream setBinaryStream(long pos) throws SQLException;
+
+ /**
+ * Writes a specified array of bytes to this {@code Blob} object, starting
+ * at a specified position. Returns the number of bytes written.
+ *
+ * @param pos
+ * the position within this {@code Blob} at which to start
+ * writing, where the first position in the {@code Blob} is
+ * {@code 1}.
+ * @param theBytes
+ * an array of bytes to write into the {@code Blob}.
+ * @return an integer containing the number of bytes written to the {@code
+ * Blob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public int setBytes(long pos, byte[] theBytes) throws SQLException;
+
+ /**
+ * Writes a portion of a specified byte array to this {@code Blob}. Returns
+ * the number of bytes written.
+ *
+ * @param pos
+ * the position within this {@code Blob} at which to start
+ * writing, where the first position in the {@code Blob} is
+ * {@code 1}.
+ * @param theBytes
+ * an array of bytes to write into the {@code Blob}.
+ * @param offset
+ * the offset into the byte array from which to start writing
+ * data - the first byte in the array has offset {@code 0}.
+ * @param len
+ * the length of data to write in number of bytes.
+ * @return an integer containing the number of bytes written to the {@code
+ * Blob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public int setBytes(long pos, byte[] theBytes, int offset, int len)
+ throws SQLException;
+
+ /**
+ * Truncate the value of this {@code Blob} object to a specified length in
+ * bytes.
+ *
+ * @param len
+ * the length of data in bytes after which this {@code Blob}
+ * is to be truncated.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Blob}.
+ * @since Android 1.0
+ */
+ public void truncate(long len) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/CallableStatement.java b/sql/src/main/java/java/sql/CallableStatement.java
new file mode 100644
index 0000000..7a90041
--- /dev/null
+++ b/sql/src/main/java/java/sql/CallableStatement.java
@@ -0,0 +1,1483 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.math.BigDecimal;
+import java.util.Calendar;
+import java.util.Map;
+import java.net.URL;
+import java.io.InputStream;
+import java.io.Reader;
+
+/**
+ * An interface used to call Stored Procedures.
+ *
+ * The JDBC API provides an SQL escape syntax allowing Stored Procedures
+ * to be called in a standard way for all databases. The JDBC escape syntax has
+ * two forms. One form includes a result parameter. The second form does not
+ * include a result parameter. Where the result parameter is used, it must be
+ * declared as an {@code OUT} parameter. Other parameters can be declared as
+ * {@code IN}, {@code OUT}, or {@code INOUT}. Parameters are referenced either by
+ * name or by a numerical index starting at 1.
+ *
{@code IN} parameters are set before calling the procedure,
+ * using the setter methods which are inherited from {@code PreparedStatement}.
+ * For {@code OUT} parameters, their type must be registered before executing
+ * the stored procedure. The values are retrieved using the getter methods
+ * defined in the {@code CallableStatement} interface.
+ *
+ * {@code CallableStatement}s can return one or more {@code ResultSets}. In the
+ * event that multiple {@code ResultSets} are returned, they are accessed using
+ * the methods inherited from the {@code Statement} interface.
+ *
+ *
+ * @since Android 1.0
+ */
+public interface CallableStatement extends PreparedStatement {
+
+ /**
+ * Gets the value of a specified JDBC {@code ARRAY} parameter as a
+ * {@code java.sql.Array}.
+ *
+ * @param parameterIndex
+ * the parameter index, where the first parameter has
+ * index 1.
+ * @return a {@code java.sql.Array} containing the parameter value.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Array getArray(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code ARRAY} parameter as a {@code
+ * java.sql.Array}.
+ *
+ * @param parameterName
+ * the desired parameter's name.
+ * @return a {@code java.sql.Array} containing the parameter's value.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Array getArray(String parameterName) throws SQLException;
+
+ /**
+ * Returns a new {@link BigDecimal} representation of the JDBC {@code
+ * NUMERIC} parameter specified by the input index.
+ *
+ * @param parameterIndex
+ * the parameter number index where the first parameter has index
+ * 1.
+ * @return a {@code java.math.BigDecimal} representing the value of the
+ * specified parameter. The value {@code null} is returned if
+ * the parameter in question is an SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public BigDecimal getBigDecimal(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns a new {@link BigDecimal} representation of the JDBC {@code
+ * NUMERIC} parameter specified by the input index. The number of digits
+ * after the decimal point is specified by {@code scale}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param scale
+ * the number of digits after the decimal point to get.
+ * @return a {@code java.math.BigDecimal} representing the value of the
+ * specified parameter. The value {@code null} is returned if
+ * the parameter in question is an SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @deprecated Use {@link #getBigDecimal(int)} or
+ * {@link #getBigDecimal(String)}
+ * @since Android 1.0
+ */
+ @Deprecated
+ public BigDecimal getBigDecimal(int parameterIndex, int scale)
+ throws SQLException;
+
+ /**
+ * Returns a new {@link BigDecimal} representation of the JDBC {@code
+ * NUMERIC} parameter specified by the input name.
+ *
+ * @param parameterName
+ * the desired parameter's name.
+ * @return a {@code java.math.BigDecimal} representing the value of the
+ * specified parameter. The value {@code null} is returned if
+ * the parameter in question is an SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public BigDecimal getBigDecimal(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code BLOB} parameter as a {@code
+ * java.sql.Blob}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return a {@code java.sql.Blob} representing the value of the
+ * specified parameter. The value {@code null} is returned if
+ * the parameter in question is an SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Blob getBlob(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code BLOB} parameter as a {@code
+ * java.sql.Blob}.
+ *
+ * @param parameterName
+ * the desired parameter's name.
+ * @return a {@code java.sql.Blob} representing the value of the
+ * specified parameter. The value {@code null} is returned if
+ * the parameter in question is an SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Blob getBlob(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code BIT} parameter as a boolean.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return a {@code boolean} representing the parameter value. {@code false}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public boolean getBoolean(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code BIT} parameter as a {@code
+ * boolean}.
+ *
+ * @param parameterName
+ * the desired parameter's name.
+ * @return a {@code boolean} representation of the value of the parameter.
+ * {@code false} is returned if the SQL value is {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public boolean getBoolean(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code TINYINT} parameter as a {@code
+ * byte}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return a {@code byte} representation of the value of the parameter.
+ * {@code 0} is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public byte getByte(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code TINYINT} parameter as a Java
+ * {@code byte}.
+ *
+ * @param parameterName
+ * the desired parameter's name.
+ * @return a {@code byte} representation of the value of the parameter.
+ * {@code 0} is returned if the SQL value is {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public byte getByte(String parameterName) throws SQLException;
+
+ /**
+ * Returns a byte array representation of the indexed JDBC {@code BINARY} or
+ * {@code VARBINARY} parameter.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return an array of bytes giving the value of the parameter. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public byte[] getBytes(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns a byte array representation of the named JDBC {@code BINARY} or
+ * {@code VARBINARY} parameter.
+ *
+ * @param parameterName
+ * the name of the parameter.
+ * @return an array of bytes giving the value of the parameter. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public byte[] getBytes(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code CLOB} parameter as a {@code
+ * java.sql.Clob}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return a {@code java.sql.Clob} representing the value of the
+ * parameter. {@code null} is returned if the value is SQL
+ * {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Clob
+ * @since Android 1.0
+ */
+ public Clob getClob(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code CLOB} parameter as a {@code
+ * java.sql.Clob}.
+ *
+ * @param parameterName
+ * the name of the parameter.
+ * @return a {@code java.sql.Clob} with the value of the parameter. {@code
+ * null} is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Clob
+ * @since Android 1.0
+ */
+ public Clob getClob(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code DATE} parameter as a {@code
+ * java.sql.Date}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return the {@code java.sql.Date} representing the parameter's value.
+ * {@code null} is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Date
+ * @since Android 1.0
+ */
+ public Date getDate(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code DATE} parameter as a {@code
+ * java.sql.Date}, using the specified {@code Calendar} to construct the date.
+ *
+ * The JDBC driver uses the calendar to create the Date using a particular
+ * timezone and locale. The default behavior of the driver is to use the Java
+ * virtual machine default settings.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param cal
+ * the {@code Calendar} to use to construct the date
+ * @return the {@code java.sql.Date} giving the parameter's value. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Date
+ * @since Android 1.0
+ */
+ public Date getDate(int parameterIndex, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code DATE} parameter as a {@code
+ * java.sql.Date}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @return the {@code java.sql.Date} giving the parameter's value. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Date
+ * @since Android 1.0
+ */
+ public Date getDate(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code DATE} parameter as a {@code
+ * java.sql.Date}, using the specified {@code Calendar} to construct the date.
+ *
+ * The JDBC driver uses the calendar to create the date using a particular
+ * timezone and locale. The default behavior of the driver is to use the Java
+ * virtual machine default settings.
+ *
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @param cal
+ * used for creating the returned {@code Date}.
+ * @return the {@code java.sql.Date} giving the parameter's value. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Date
+ * @since Android 1.0
+ */
+ public Date getDate(String parameterName, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code DOUBLE} parameter as a
+ * {@code double}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return the parameter's value as a {@code double}. {@code 0.0}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public double getDouble(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code DOUBLE} parameter as a
+ * {@code double}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @return the parameter's value as a {@code double}. {@code 0.0}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public double getDouble(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code FLOAT} parameter as a {@code
+ * float}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return the parameter's value as a {@code float}. {@code 0.0}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public float getFloat(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code FLOAT} parameter as a Java
+ * {@code float}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @return the parameter's value as a {@code float}. {@code 0.0}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public float getFloat(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code INTEGER} parameter as an
+ * {@code int}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return the {@code int} giving the parameter's value. {@code 0}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public int getInt(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code INTEGER} parameter as an
+ * {@code int}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @return the {@code int} giving the parameter's value. {@code 0}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public int getInt(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code BIGINT} parameter as a
+ * {@code long}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return the {@code long} giving the parameter's value. {@code 0}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public long getLong(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of the specified JDBC {@code BIGINT} parameter as a
+ * {@code long}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @return the {@code long} giving the parameter's value. {@code 0}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public long getLong(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of the specified parameter as a Java {@code Object}.
+ *
+ * The object type returned is the JDBC type registered for the parameter
+ * with a {@code registerOutParameter} call. If a parameter was registered
+ * as a {@code java.sql.Types.OTHER} then it may hold abstract types that
+ * are particular to the connected database.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return an Object holding the value of the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Object getObject(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of the specified parameter as an {@code Object}. The
+ * {@code Map} gives the correspondence between SQL types and Java classes.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param map
+ * the {@code Map} giving the correspondence between SQL
+ * types and Java classes.
+ * @return an Object holding the value of the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Object getObject(int parameterIndex, Map> map)
+ throws SQLException;
+
+ /**
+ * Gets the value of the specified parameter as an {@code Object}.
+ *
+ * The object type returned is the JDBC type that was registered for
+ * the parameter by an earlier call to {@link #registerOutParameter}.
+ * If a parameter was registered as a {@code java.sql.Types.OTHER}
+ * then it may hold abstract types that are particular to the
+ * connected database.
+ *
+ *
+ * @param parameterName
+ * the parameter name.
+ * @return the Java {@code Object} representation of the value of the
+ * parameter.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Object getObject(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified parameter as an {@code Object}. The
+ * actual return type is determined by the {@code Map} parameter which
+ * gives the correspondence between SQL types and Java classes.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param map
+ * the {@code Map} of SQL types to their Java counterparts
+ * @return an {@code Object} holding the value of the parameter.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Object getObject(String parameterName, Map> map)
+ throws SQLException;
+
+ /**
+ * Gets the value of a specified SQL {@code REF()}
+ * parameter as a {@code java.sql.Ref}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return a {@code java.sql.Ref} with the parameter value. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Ref getRef(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified SQL {@code REF()}
+ * parameter as a {@code java.sql.Ref}.
+ *
+ * @param parameterName
+ * the desired parameter's name.
+ * @return the parameter's value in the form of a {@code
+ * java.sql.Ref}. A {@code null} reference is returned if the
+ * parameter's value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @see Ref
+ * @since Android 1.0
+ */
+ public Ref getRef(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code SMALLINT} parameter as a
+ * {@code short}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return the parameter's value as a {@code short}. 0 is returned
+ * if the parameter's value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public short getShort(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code SMALLINT} parameter as a
+ * {@code short}.
+ *
+ * @param parameterName
+ * the desired parameter's name.
+ * @return the parameter's value as a {@code short}. 0 is returned
+ * if the parameter's value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public short getShort(String parameterName) throws SQLException;
+
+ /**
+ * Returns the indexed parameter's value as a {@code String}. The
+ * parameter value must be one of the JDBC types {@code CHAR},
+ * {@code VARCHAR} or {@code LONGVARCHAR}.
+ *
+ * The {@code String} corresponding to a {@code CHAR} of fixed length
+ * will be of identical length to the value in the database inclusive
+ * of padding characters.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return the parameter's value as a {@code String}. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public String getString(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns the named parameter's value as a string. The parameter value must
+ * be one of the JDBC types {@code CHAR}, {@code VARCHAR} or {@code
+ * LONGVARCHAR}.
+ *
+ * The string corresponding to a {@code CHAR} of fixed length will be of
+ * identical length to the value in the database inclusive of padding
+ * characters.
+ *
+ *
+ * @param parameterName
+ * the desired parameter's name.
+ * @return the parameter's value as a {@code String}. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public String getString(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code TIME} parameter as a {@code
+ * java.sql.Time}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return the parameter's value as a {@code java.sql.Time}.
+ * {@code null} is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Time
+ * @since Android 1.0
+ */
+ public Time getTime(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code TIME} parameter as a {@code
+ * java.sql.Time}, using the supplied {@code Calendar} to construct the
+ * time. The JDBC driver uses the calendar to handle specific timezones
+ * and locales in order to determine {@code Time}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param cal
+ * the calendar to use in constructing {@code Time}.
+ * @return the parameter's value as a {@code java.sql.Time}.
+ * {@code null} is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Time
+ * @see java.util.Calendar
+ * @since Android 1.0
+ */
+ public Time getTime(int parameterIndex, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code TIME} parameter as a {@code
+ * java.sql.Time}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @return a new {@code java.sql.Time} with the parameter's value. A {@code
+ * null} reference is returned for an SQL value of {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Time
+ * @since Android 1.0
+ */
+ public Time getTime(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code TIME} parameter as a {@code
+ * java.sql.Time}, using the supplied {@code Calendar} to construct
+ * the time. The JDBC driver uses the calendar to handle specific
+ * timezones and locales when creating {@code Time}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @param cal
+ * used for creating the returned {@code Time}
+ * @return a new {@code java.sql.Time} with the parameter's value. A {@code
+ * null} reference is returned for an SQL value of {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Time
+ * @see java.util.Calendar
+ * @since Android 1.0
+ */
+ public Time getTime(String parameterName, Calendar cal) throws SQLException;
+
+ /**
+ * Returns the indexed parameter's {@code TIMESTAMP} value as a {@code
+ * java.sql.Timestamp}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return the parameter's value as a {@code java.sql.Timestamp}. A
+ * {@code null} reference is returned for an SQL value of {@code
+ * NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Timestamp
+ * @since Android 1.0
+ */
+ public Timestamp getTimestamp(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns the indexed parameter's {@code TIMESTAMP} value as a {@code
+ * java.sql.Timestamp}. The JDBC driver uses the supplied {@code Calendar}
+ * to handle specific timezones and locales when creating the result.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param cal
+ * used for creating the returned {@code Timestamp}
+ * @return the parameter's value as a {@code java.sql.Timestamp}. A
+ * {@code null} reference is returned for an SQL value of {@code
+ * NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Timestamp
+ * @since Android 1.0
+ */
+ public Timestamp getTimestamp(int parameterIndex, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Returns the named parameter's {@code TIMESTAMP} value as a {@code
+ * java.sql.Timestamp}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @return the parameter's value as a {@code java.sql.Timestamp}. A
+ * {@code null} reference is returned for an SQL value of {@code
+ * NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Timestamp
+ * @since Android 1.0
+ */
+ public Timestamp getTimestamp(String parameterName) throws SQLException;
+
+ /**
+ * Returns the indexed parameter's {@code TIMESTAMP} value as a {@code
+ * java.sql.Timestamp}. The JDBC driver uses the supplied {@code Calendar}
+ * to handle specific timezones and locales when creating the result.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @param cal
+ * used for creating the returned {@code Timestamp}
+ * @return the parameter's value as a {@code java.sql.Timestamp}. A
+ * {@code null} reference is returned for an SQL value of {@code
+ * NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Timestamp
+ * @since Android 1.0
+ */
+ public Timestamp getTimestamp(String parameterName, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC {@code DATALINK} parameter as a
+ * {@code java.net.URL}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @return a {@code URL} giving the parameter's value. {@code null}
+ * is returned if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see java.net.URL
+ * @since Android 1.0
+ */
+ public URL getURL(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns the named parameter's JDBC {@code DATALINK} value in a new Java
+ * {@code java.net.URL}.
+ *
+ * @param parameterName
+ * the name of the desired parameter.
+ * @return a new {@code java.net.URL} encapsulating the parameter value. A
+ * {@code null} reference is returned for an SQL value of {@code
+ * NULL}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see java.net.URL
+ * @since Android 1.0
+ */
+ public URL getURL(String parameterName) throws SQLException;
+
+ /**
+ * Defines the type of a specified {@code OUT} parameter. All {@code OUT}
+ * parameters must have their type defined before a stored procedure is
+ * executed.
+ *
+ * The type supplied in the {@code sqlType} parameter fixes the
+ * type that will be returned by the getter methods of
+ * {@code CallableStatement}.
+ * If a database specific type is expected for a parameter, the Type {@code
+ * java.sql.Types.OTHER} should be used. Note that there is another variant
+ * of this method for User Defined Types or a {@code REF} type.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param sqlType
+ * the JDBC type as defined by {@code java.sql.Types}. The JDBC
+ * types {@code NUMERIC} and {@code DECIMAL} should be defined
+ * using {@link #registerOutParameter(int, int, int)}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Types
+ * @since Android 1.0
+ */
+ public void registerOutParameter(int parameterIndex, int sqlType)
+ throws SQLException;
+
+ /**
+ * Defines the Type of a specified {@code OUT} parameter. All {@code OUT}
+ * parameters must have their type defined before a stored procedure is
+ * executed. This version of the {@code registerOutParameter} method, which
+ * has a scale parameter, should be used for the JDBC types {@code NUMERIC}
+ * and {@code DECIMAL}, where there is a need to specify the number of
+ * digits expected after the decimal point.
+ *
+ * The type supplied in the {@code sqlType} parameter fixes the
+ * type that will be returned by the getter methods of
+ * {@code CallableStatement}.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param sqlType
+ * the JDBC type as defined by {@code java.sql.Types}.
+ * @param scale
+ * the number of digits after the decimal point. Must be greater
+ * than or equal to 0.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Types
+ * @since Android 1.0
+ */
+ public void registerOutParameter(int parameterIndex, int sqlType, int scale)
+ throws SQLException;
+
+ /**
+ * Defines the Type of a specified {@code OUT} parameter. This variant
+ * of the method is designed for use with parameters that are
+ * User Defined Types (UDT) or a {@code REF} type, although it
+ * can be used for any type.
+ *
+ * @param paramIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param sqlType
+ * a JDBC type expressed as a constant from {@link Types}.
+ * @param typeName
+ * an SQL type name. For a {@code REF} type, this name should be
+ * the fully qualified name of the referenced type.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Ref
+ * @since Android 1.0
+ */
+ public void registerOutParameter(int paramIndex, int sqlType,
+ String typeName) throws SQLException;
+
+ /**
+ * Defines the Type of a specified {@code OUT} parameter. All OUT parameters
+ * must have their Type defined before a stored procedure is executed.
+ *
+ * The type supplied in the {@code sqlType} parameter fixes the
+ * type that will be returned by the getter methods of
+ * {@code CallableStatement}.
+ * If a database-specific type is expected for a parameter, the Type {@code
+ * java.sql.Types.OTHER} should be used. Note that there is another variant
+ * of this method for User Defined Types or a {@code REF} type.
+ *
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param sqlType
+ * a JDBC type expressed as a constant from {@link Types}. Types
+ * {@code NUMERIC} and {@code DECIMAL} should be defined using
+ * the variant of this method that takes a {@code scale}
+ * parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void registerOutParameter(String parameterName, int sqlType)
+ throws SQLException;
+
+ /**
+ * Defines the Type of a specified {@code OUT} parameter. All {@code OUT}
+ * parameters must have their Type defined before a stored procedure is
+ * executed. This version of the {@code registerOutParameter} method, which
+ * has a scale parameter, should be used for the JDBC types {@code NUMERIC}
+ * and {@code DECIMAL}, where there is a need to specify the number of
+ * digits expected after the decimal point.
+ *
+ * The type supplied in the {@code sqlType} parameter fixes the
+ * type that will be returned by the getter methods of
+ * {@code CallableStatement}.
+ *
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param sqlType
+ * a JDBC type expressed as a constant from {@link Types}.
+ * @param scale
+ * the number of digits after the decimal point. Must be greater
+ * than or equal to 0.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void registerOutParameter(String parameterName, int sqlType,
+ int scale) throws SQLException;
+
+ /**
+ * Defines the Type of a specified {@code OUT} parameter. This variant of
+ * the method is designed for use with parameters that are User Defined
+ * Types (UDT) or a {@code REF} type, although it can be used for any
+ * type.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param sqlType
+ * a JDBC type expressed as a constant from {@link Types}
+ * @param typeName
+ * the fully qualified name of an SQL structured type. For a
+ * {@code REF} type, this name should be the fully qualified name
+ * of the referenced type.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void registerOutParameter(String parameterName, int sqlType,
+ String typeName) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the content of a supplied
+ * {@code InputStream}, which has a specified number of bytes.
+ *
+ * This is a good method for setting an SQL {@code LONVARCHAR} parameter
+ * where the length of the data is large. Data is read from the {@code
+ * InputStream} until end-of-file is reached or the specified number of
+ * bytes is copied.
+ *
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theInputStream
+ * the ASCII input stream carrying the data to update the
+ * parameter with.
+ * @param length
+ * the number of bytes in the {@code InputStream} to copy to the
+ * parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setAsciiStream(String parameterName,
+ InputStream theInputStream, int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.math.BigDecimal} value.
+ *
+ * @param parameterName
+ * the name of the parameter.
+ * @param theBigDecimal
+ * the {@code java.math.BigInteger} value to set.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setBigDecimal(String parameterName, BigDecimal theBigDecimal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the content of a supplied
+ * binary {@code InputStream}, which has a specified number of bytes.
+ *
+ * Use this method when a large amount of data needs to be set into a
+ * {@code LONGVARBINARY} parameter.
+ *
+ *
+ * @param parameterName
+ * the name of the parameter.
+ * @param theInputStream
+ * the binary {@code InputStream} carrying the data to update the
+ * parameter.
+ * @param length
+ * the number of bytes in the {@code InputStream} to copy to the
+ * parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setBinaryStream(String parameterName,
+ InputStream theInputStream, int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code boolean}
+ * value.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theBoolean
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setBoolean(String parameterName, boolean theBoolean)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code byte} value.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theByte
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setByte(String parameterName, byte theByte) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied array of bytes. The
+ * array is mapped to {@code VARBINARY} or else {@code LONGVARBINARY} in the
+ * connected database.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theBytes
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setBytes(String parameterName, byte[] theBytes)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the character content of a
+ * {@code Reader} object, with the specified length of character data.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param reader
+ * the new value with which to update the parameter.
+ * @param length
+ * a count of the characters contained in {@code reader}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setCharacterStream(String parameterName, Reader reader,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Date} value.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theDate
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setDate(String parameterName, Date theDate) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Date} value, using a supplied calendar to map the date. The
+ * calendar allows the application to control the timezone used to compute
+ * the SQL {@code DATE} in the database. In case that no calendar is
+ * supplied, the driver uses the default timezone of the Java virtual
+ * machine.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theDate
+ * the new value with which to update the parameter.
+ * @param cal
+ * a {@code Calendar} to use to construct the SQL {@code DATE}
+ * value.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see java.util.Calendar
+ * @see Date
+ * @since Android 1.0
+ */
+ public void setDate(String parameterName, Date theDate, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code double}
+ * value.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theDouble
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setDouble(String parameterName, double theDouble)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to to a supplied {@code float}
+ * value.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theFloat
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setFloat(String parameterName, float theFloat)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code int} value.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theInt
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setInt(String parameterName, int theInt) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code long} value.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theLong
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setLong(String parameterName, long theLong) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to SQL {@code NULL}. Don't use
+ * this version of {@code setNull} for User Defined Types (UDT) or
+ * for {@code REF} type parameters.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param sqlType
+ * a JDBC type expressed as a constant from {@link Types}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setNull(String parameterName, int sqlType) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to be SQL {@code NULL} where the
+ * parameter type is either {@code REF} or user defined (e.g. {@code STRUCT}
+ * , {@code JAVA_OBJECT} etc).
+ *
+ * For reasons of portability, the caller is expected to supply both the SQL
+ * type code and type name (which is just the parameter name if the type is
+ * user defined, referred to as a {@code UDT}, or the name of the referenced
+ * type in case of a {@code REF} type).
+ *
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param sqlType
+ * a JDBC type expressed as a constant from {@link Types}.
+ * @param typeName
+ * if the target parameter is a user defined type then this
+ * should contain the full type name. The fully qualified name of
+ * a {@code UDT} or {@code REF} type is ignored if the parameter
+ * is not a {@code UDT}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Types
+ * @since Android 1.0
+ */
+ public void setNull(String parameterName, int sqlType, String typeName)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object. Prior to
+ * issuing this request to the connected database {@code theObject} is
+ * transformed to the corresponding SQL type according to the standard Java
+ * to SQL mapping rules.
+ *
+ * If the object's class implements the interface {@code SQLData}, the JDBC
+ * driver calls {@code SQLData.writeSQL} to write it to the SQL data stream.
+ * If {@code theObject} implements any of the following interfaces then the
+ * driver is in charge of mapping the value to the appropriate SQL type.
+ *
{@link Ref}
+ *
{@link Struct}
+ *
{@link Array}
+ *
{@link Clob}
+ *
{@link Blob}
+ *
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theObject
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error occurs.
+ * @see SQLData
+ * @since Android 1.0
+ */
+ public void setObject(String parameterName, Object theObject)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ *
+ * The parameter {@code theObject} is converted to the given {@code
+ * targetSqlType} before it is sent to the database. If the object has a
+ * custom mapping (its class implements the interface {@code SQLData}), the
+ * JDBC driver calls the method {@code SQLData.writeSQL} to write it to the
+ * SQL data stream. If {@code theObject} is an instance of one of the
+ * following types
+ *
+ *
{@link Ref}
+ *
{@link Struct}
+ *
{@link Array}
+ *
{@link Clob}
+ *
{@link Blob}
+ *
+ * then the driver is in charge of mapping the value to the appropriate
+ * SQL type and deliver it to the database.
+ *
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theObject
+ * the new value with which to update the parameter.
+ * @param targetSqlType
+ * a JDBC type expressed as a constant from {@link Types}.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see SQLData
+ * @since Android 1.0
+ */
+ public void setObject(String parameterName, Object theObject,
+ int targetSqlType) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ *
+ * The object is converted to the given {@code targetSqlType} before it is
+ * sent to the database. If the object has a custom mapping (its class
+ * implements the interface {@code SQLData}), the JDBC driver calls the
+ * method {@code SQLData.writeSQL} to write it to the SQL data stream. If
+ * {@code theObject} implements any of the following interfaces
+ *
+ *
{@link Ref}
+ *
{@link Struct}
+ *
{@link Array}
+ *
{@link Clob}
+ *
{@link Blob}
+ *
+ * then the driver is charge of mapping the value to the appropriate
+ * SQL type.
+ *
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theObject
+ * the new value with which to update the parameter.
+ * @param targetSqlType
+ * a JDBC type expressed as a constant from {@link Types}.
+ * @param scale
+ * where applicable, the number of digits after the decimal.
+ * point.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see SQLData
+ * @since Android 1.0
+ */
+ public void setObject(String parameterName, Object theObject,
+ int targetSqlType, int scale) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code short}
+ * value.
+ *
+ * @param parameterName
+ * the name of the parameter.
+ * @param theShort
+ * a short value to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setShort(String parameterName, short theShort)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code String}.
+ *
+ * @param parameterName
+ * the name of the parameter.
+ * @param theString
+ * a {@code String} value to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void setString(String parameterName, String theString)
+ throws SQLException;
+
+ /**
+ * Sets the value of the parameter named {@code parameterName} to the value
+ * of the supplied {@code java.sql.Time}.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theTime
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Time
+ * @since Android 1.0
+ */
+ public void setTime(String parameterName, Time theTime) throws SQLException;
+
+ /**
+ * Sets the value of the parameter named {@code parameterName} to the value
+ * of the supplied {@code java.sql.Time} using the supplied calendar.
+ *
+ * The driver uses the supplied {@code Calendar} to create the SQL
+ * {@code TIME} value, which allows it to use a custom timezone -
+ * otherwise the driver uses the default timezone of the Java
+ * virtual machine.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theTime
+ * the new value with which to update the parameter.
+ * @param cal
+ * used for creating the new SQL {@code TIME} value.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Time
+ * @since Android 1.0
+ */
+ public void setTime(String parameterName, Time theTime, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Timestamp} value.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theTimestamp
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Timestamp
+ * @since Android 1.0
+ */
+ public void setTimestamp(String parameterName, Timestamp theTimestamp)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Timestamp} value, using the supplied calendar.
+ *
+ * The driver uses the supplied calendar to create the SQL {@code TIMESTAMP}
+ * value, which allows it to use a custom timezone - otherwise the driver
+ * uses the default timezone of the Java virtual machine.
+ *
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theTimestamp
+ * the new value with which to update the parameter.
+ * @param cal
+ * used for creating the new SQL {@code TIME} value.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Timestamp
+ * @see java.util.Calendar
+ * @since Android 1.0
+ */
+ public void setTimestamp(String parameterName, Timestamp theTimestamp,
+ Calendar cal) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the supplied {@code
+ * java.net.URL}.
+ *
+ * @param parameterName
+ * the parameter name.
+ * @param theURL
+ * the new value with which to update the parameter.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see java.net.URL
+ * @since Android 1.0
+ */
+ public void setURL(String parameterName, URL theURL) throws SQLException;
+
+ /**
+ * Gets whether the value of the last {@code OUT} parameter read was SQL
+ * {@code NULL}.
+ *
+ * @return true if the last parameter was SQL {@code NULL}, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public boolean wasNull() throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/Clob.java b/sql/src/main/java/java/sql/Clob.java
new file mode 100644
index 0000000..339d4e5
--- /dev/null
+++ b/sql/src/main/java/java/sql/Clob.java
@@ -0,0 +1,192 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.io.OutputStream;
+import java.io.Writer;
+
+/**
+ * A Java interface mapping for the SQL CLOB type.
+ *
+ * An SQL {@code CLOB} type stores a large array of characters as the value in a
+ * column of a database.
+ *
+ * The {@code java.sql.Clob} interface provides methods for setting and
+ * retrieving data in the {@code Clob}, for querying {@code Clob} data length,
+ * for searching for data within the {@code Clob}.
+ *
+ * @since Android 1.0
+ */
+public interface Clob {
+
+ /**
+ * Gets the value of this {@code Clob} object as an ASCII stream.
+ *
+ * @return an ASCII {@code InputStream} giving access to the
+ * {@code Clob} data.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public InputStream getAsciiStream() throws SQLException;
+
+ /**
+ * Gets the data of this {@code Clob} object in a {@code java.io.Reader}.
+ *
+ * @return a character stream Reader object giving access to the {@code
+ * Clob} data.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public Reader getCharacterStream() throws SQLException;
+
+ /**
+ * Gets a copy of a specified substring in this {@code Clob}.
+ *
+ * @param pos
+ * the index of the start of the substring in the {@code Clob}.
+ * @param length
+ * the length of the data to retrieve.
+ * @return A string containing the requested data.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public String getSubString(long pos, int length) throws SQLException;
+
+ /**
+ * Retrieves the number of characters in this {@code Clob} object.
+ *
+ * @return a long value with the number of character in this {@code Clob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public long length() throws SQLException;
+
+ /**
+ * Retrieves the character position at which a specified {@code Clob} object
+ * appears in this {@code Clob} object.
+ *
+ * @param searchstr
+ * the specified {@code Clob} to search for.
+ * @param start
+ * the position within this {@code Clob} to start the search
+ * @return a long value with the position at which the specified {@code
+ * Clob} occurs within this {@code Clob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public long position(Clob searchstr, long start) throws SQLException;
+
+ /**
+ * Retrieves the character position at which a specified substring appears
+ * in this {@code Clob} object.
+ *
+ * @param searchstr
+ * the string to search for.
+ * @param start
+ * the position at which to start the search within this {@code
+ * Clob}.
+ * @return a long value with the position at which the specified string
+ * occurs within this {@code Clob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public long position(String searchstr, long start) throws SQLException;
+
+ /**
+ * Retrieves a stream which can be used to write Ascii characters to this
+ * {@code Clob} object, starting at specified position.
+ *
+ * @param pos
+ * the position at which to start the writing.
+ * @return an OutputStream which can be used to write ASCII characters to
+ * this {@code Clob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public OutputStream setAsciiStream(long pos) throws SQLException;
+
+ /**
+ * Retrieves a stream which can be used to write a stream of unicode
+ * characters to this {@code Clob} object, at a specified position.
+ *
+ * @param pos
+ * the position at which to start the writing.
+ * @return a Writer which can be used to write unicode characters to this
+ * {@code Clob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public Writer setCharacterStream(long pos) throws SQLException;
+
+ /**
+ * Writes a given Java String to this {@code Clob} object at a specified
+ * position.
+ *
+ * @param pos
+ * the position at which to start the writing.
+ * @param str
+ * the string to write.
+ * @return the number of characters written.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public int setString(long pos, String str) throws SQLException;
+
+ /**
+ * Writes {@code len} characters of a string, starting at a specified
+ * character offset, to this {@code Clob}.
+ *
+ * @param pos
+ * the position at which to start the writing.
+ * @param str
+ * the String to write.
+ * @param offset
+ * the offset within {@code str} to start writing from.
+ * @param len
+ * the number of characters to write.
+ * @return the number of characters written.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public int setString(long pos, String str, int offset, int len)
+ throws SQLException;
+
+ /**
+ * Truncates this {@code Clob} after the specified number of characters.
+ *
+ * @param len
+ * the length in characters giving the place to
+ * truncate this {@code Clob}.
+ * @throws SQLException
+ * if an error occurs accessing the {@code Clob}.
+ * @since Android 1.0
+ */
+ public void truncate(long len) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/Connection.java b/sql/src/main/java/java/sql/Connection.java
new file mode 100644
index 0000000..523071c
--- /dev/null
+++ b/sql/src/main/java/java/sql/Connection.java
@@ -0,0 +1,809 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.util.Map;
+
+/**
+ * A connection represents a link from a Java application to a database. All SQL
+ * statements and results are returned within the context of a connection.
+ * Database statements that are executed within this context form a
+ * database session which forms one or more closed transactions. Especially In distributed applications, multiple concurrent connections may exist accessing the same values of the database.
+ * which may lead to the following phenomena (referred to as transaction isolation levels):
+ *
+ *
dirty reads:
+ * reading values from table rows that are not committed.
+ *
non-repeatable reads:
+ * reading table rows more than once in a transaction but getting back different
+ * data because other transactions have altered the rows between the reads.
+ *
phantom reads:
+ * retrieving additional "phantom" rows in the course of repeated table reads
+ * because other transactions have inserted additional rows that satisfy an
+ * SQL {@code WHERE} clause
+ *
+ *
+ * @since Android 1.0
+ */
+public interface Connection {
+
+ /**
+ * A constant indicating that transactions are not supported.
+ *
+ * @since Android 1.0
+ */
+ public static final int TRANSACTION_NONE = 0;
+
+ /**
+ * No dirty reads are permitted, therefore transactions may not read
+ * a row containing uncommitted values - but does not prevent an application
+ * from non-repeatable reads and phantom reads.
+ *
+ * @since Android 1.0
+ */
+ public static final int TRANSACTION_READ_COMMITTED = 2;
+
+ /**
+ * In the case that reading uncommitted values is allowed, the following
+ * incidents may happen which may lead to an invalid results:
+ *
+ *
dirty reads
+ *
non-repeatable reads
+ *
phantom reads
+ *
+ *
+ * @since Android 1.0
+ */
+ public static final int TRANSACTION_READ_UNCOMMITTED = 1;
+
+ /**
+ * A constant indicating that dirty reads and non-repeatable
+ * reads are prevented but phantom reads can occur.
+ *
+ * @since Android 1.0
+ */
+ public static final int TRANSACTION_REPEATABLE_READ = 4;
+
+ /**
+ * The constant that indicates that the following incidents are all
+ * prevented (the opposite of {@link #TRANSACTION_READ_UNCOMMITTED}):
+ *
+ *
dirty reads
+ *
non-repeatable reads
+ *
phantom reads
+ *
+ *
+ * @since Android 1.0
+ */
+ public static final int TRANSACTION_SERIALIZABLE = 8;
+
+ /**
+ * Discards all warnings that may have arisen for this connection.
+ * Subsequent calls to {@link #getWarnings()} will return {@code null}
+ * up until a new warning condition occurs.
+ *
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public void clearWarnings() throws SQLException;
+
+ /**
+ * Causes the instant release of all database and driver connection
+ * resources associated with this object. Any subsequent invocations of this
+ * method have no effect.
+ *
+ * It is strongly recommended that all connections are closed before they
+ * are dereferenced by the application ready for garbage collection.
+ * Although the {@code finalize} method of the connection closes the
+ * connection before garbage collection takes place, it is not advisable to
+ * leave the {@code close} operation to take place in this way. Mainly
+ * because undesired side-effects may appear.
+ *
+ *
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public void close() throws SQLException;
+
+ /**
+ * Commits all of the changes made since the last {@code commit} or
+ * {@code rollback} of the associated transaction. All locks in the database
+ * held by this connection are also relinquished. Calling this operation on
+ * connection objects in {@code auto-commit} mode leads to an error.
+ *
+ * @throws SQLException
+ * if there is a problem accessing the database or if the target
+ * connection instance is in auto-commit mode.
+ */
+ public void commit() throws SQLException;
+
+ /**
+ * Returns a new instance of {@code Statement} for issuing SQL commands to
+ * the remote database.
+ *
+ * {@code ResultSets} generated by the returned statement will default to
+ * type {@code ResultSet.TYPE_FORWARD_ONLY} and concurrency level {@code
+ * ResultSet.CONCUR_READ_ONLY}.
+ *
+ * @return a {@code Statement} object with default settings.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @see ResultSet
+ */
+ public Statement createStatement() throws SQLException;
+
+ /**
+ * Returns a new instance of {@code Statement} whose associated {@code
+ * ResultSet}s have the characteristics specified in the type and
+ * concurrency arguments.
+ *
+ * @param resultSetType
+ * one of the following type specifiers:
+ *
+ *
{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ * {@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ * {@link ResultSet#TYPE_FORWARD_ONLY}
+ *
+ * @param resultSetConcurrency
+ * one of the following concurrency mode specifiers:
+ *
+ *
{@link ResultSet#CONCUR_UPDATABLE}
+ * {@link ResultSet#CONCUR_READ_ONLY}
+ *
+ * @return a new instance of {@code Statement} capable of manufacturing
+ * {@code ResultSet}s that satisfy the specified {@code
+ * resultSetType} and {@code resultSetConcurrency} values.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Statement createStatement(int resultSetType, int resultSetConcurrency)
+ throws SQLException;
+
+ /**
+ * Returns a new instance of {@code Statement} whose associated
+ * {@code ResultSet}s will have the characteristics specified in the
+ * type, concurrency and holdability arguments.
+ *
+ * @param resultSetType
+ * one of the following type specifiers:
+ *
+ *
{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ *
{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ *
{@link ResultSet#TYPE_FORWARD_ONLY}
+ *
+ * @param resultSetConcurrency
+ * one of the following concurrency mode specifiers:
+ *
+ *
{@link ResultSet#CONCUR_UPDATABLE}
+ *
{@link ResultSet#CONCUR_READ_ONLY}
+ *
+ * @param resultSetHoldability
+ * one of the following holdability mode specifiers:
+ *
+ *
{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ *
{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ *
+ * @return a new instance of {@code Statement} capable of
+ * manufacturing {@code ResultSet}s that satisfy the
+ * specified {@code resultSetType},
+ * {@code resultSetConcurrency} and
+ * {@code resultSetHoldability} values.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public Statement createStatement(int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException;
+
+ /**
+ * Returns a {@code boolean} indicating whether or not this connection is in
+ * the {@code auto-commit} operating mode.
+ *
+ * @return {@code true} if {@code auto-commit} is on, otherwise {@code
+ * false}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public boolean getAutoCommit() throws SQLException;
+
+ /**
+ * Gets this {@code Connection} object's current catalog name.
+ *
+ * @return the catalog name. {@code null} if there is no catalog
+ * name.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public String getCatalog() throws SQLException;
+
+ /**
+ * Returns the holdability property that any {@code ResultSet} produced by
+ * this instance will have.
+ *
+ * @return one of the following holdability mode specifiers:
+ *
+ *
{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ * {@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ *
+ * @throws SQLException
+ * if there is a problem accessing the a database.
+ * @since Android 1.0
+ */
+ public int getHoldability() throws SQLException;
+
+ /**
+ * Gets the metadata about the database referenced by this connection. The
+ * returned {@code DatabaseMetaData} describes the database topography,
+ * available stored procedures, SQL syntax and so on.
+ *
+ * @return a {@code DatabaseMetaData} object containing the database
+ * description.
+ * @throws SQLException
+ * if there is a problem accessing the a database.
+ * @since Android 1.0
+ */
+ public DatabaseMetaData getMetaData() throws SQLException;
+
+ /**
+ * Returns the transaction isolation level for this connection.
+ *
+ * @return the transaction isolation value.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @see #TRANSACTION_NONE
+ * @see #TRANSACTION_READ_COMMITTED
+ * @see #TRANSACTION_READ_UNCOMMITTED
+ * @see #TRANSACTION_REPEATABLE_READ
+ * @see #TRANSACTION_SERIALIZABLE
+ * @since Android 1.0
+ */
+ public int getTransactionIsolation() throws SQLException;
+
+ /**
+ * Returns the type mapping associated with this {@code Connection} object.
+ * The type mapping must be set on the application level.
+ *
+ * @return the Type Map as a {@code java.util.Map}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Map> getTypeMap() throws SQLException;
+
+ /**
+ * Gets the first instance of any {@code SQLWarning} objects that may have
+ * been created in the use of this connection. If at least one warning has
+ * occurred then this operation returns the first one reported. A {@code
+ * null} indicates that no warnings have occurred.
+ *
+ * By invoking the {@link SQLWarning#getNextWarning()} method of the
+ * returned {@code SQLWarning} object it is possible to obtain all of
+ * this connection's warning objects.
+ *
+ *
+ * @return the first warning as an SQLWarning object (may be {@code null}).
+ * @throws SQLException
+ * if there is a problem accessing the database or if the call
+ * has been made on a connection which has been previously
+ * closed.
+ * @since Android 1.0
+ */
+ public SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * Returns a {@code boolean} indicating whether or not this connection is in
+ * the {@code closed} state. The {@code closed} state may be entered into as
+ * a consequence of a successful invocation of the {@link #close()} method
+ * or else if an error has occurred that prevents the connection from
+ * functioning normally.
+ *
+ * @return {@code true} if closed, otherwise {@code false}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public boolean isClosed() throws SQLException;
+
+ /**
+ * Returns a {@code boolean} indicating whether or not this connection is
+ * currently in the {@code read-only} state.
+ *
+ * @return {@code true} if in read-only state, otherwise {@code false}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public boolean isReadOnly() throws SQLException;
+
+ /**
+ * Returns a string representation of the input SQL statement
+ * {@code sql} expressed in the underlying system's native SQL
+ * syntax.
+ *
+ * @param sql
+ * the JDBC form of an SQL statement.
+ * @return the SQL statement in native database format.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public String nativeSQL(String sql) throws SQLException;
+
+ /**
+ * Returns a new instance of {@code CallableStatement} that may be used for
+ * making stored procedure calls to the database.
+ *
+ * @param sql
+ * the SQL statement that calls the stored function
+ * @return a new instance of {@code CallableStatement} representing the SQL
+ * statement. {@code ResultSet}s emitted from this {@code
+ * CallableStatement} will default to type
+ * {@link ResultSet#TYPE_FORWARD_ONLY} and concurrency
+ * {@link ResultSet#CONCUR_READ_ONLY}.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public CallableStatement prepareCall(String sql) throws SQLException;
+
+ /**
+ * Returns a new instance of {@code CallableStatement} that may be used for
+ * making stored procedure calls to the database. {@code ResultSet}s emitted
+ * from this {@code CallableStatement} will satisfy the specified {@code
+ * resultSetType} and {@code resultSetConcurrency} values.
+ *
+ * @param sql
+ * the SQL statement
+ * @param resultSetType
+ * one of the following type specifiers:
+ *
+ *
{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ *
{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ *
{@link ResultSet#TYPE_FORWARD_ONLY}
+ *
+ * @param resultSetConcurrency
+ * one of the following concurrency mode specifiers:
+ *
+ *
{@link ResultSet#CONCUR_READ_ONLY}
+ *
{@link ResultSet#CONCUR_UPDATABLE}
+ *
+ * @return a new instance of {@code CallableStatement} representing the
+ * precompiled SQL statement. {@code ResultSet}s emitted from this
+ * {@code CallableStatement} will satisfy the specified {@code
+ * resultSetType} and {@code resultSetConcurrency} values.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ * @since Android 1.0
+ */
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException;
+
+ /**
+ * Returns a new instance of {@code CallableStatement} that may be used for
+ * making stored procedure calls to the database. {@code ResultSet}s created
+ * from this {@code CallableStatement} will have characteristics determined
+ * by the specified type, concurrency and holdability arguments.
+ *
+ * @param sql
+ * the SQL statement
+ * @param resultSetType
+ * one of the following type specifiers:
+ *
+ *
{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ *
{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ *
{@link ResultSet#TYPE_FORWARD_ONLY}
+ *
+ * @param resultSetConcurrency
+ * one of the following concurrency mode specifiers:
+ *
+ *
{@link ResultSet#CONCUR_READ_ONLY}
+ *
{@link ResultSet#CONCUR_UPDATABLE}
+ *
+ * @param resultSetHoldability
+ * one of the following holdability mode specifiers:
+ *
+ *
{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ *
{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ *
+ * @return a new instance of {@code CallableStatement} representing the
+ * precompiled SQL statement. {@code ResultSet}s emitted from this
+ * {@code CallableStatement} will satisfy the specified {@code
+ * resultSetType}, {@code resultSetConcurrency} and {@code
+ * resultSetHoldability} values.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException;
+
+ /**
+ * Returns a new instance of {@code PreparedStatement} that may be used any
+ * number of times to execute parameterized requests on the database server.
+ *
+ * Subject to JDBC driver support, this operation will attempt to send the
+ * precompiled version of the statement to the database. If
+ * the driver does not support precompiled statements, the statement will
+ * not reach the database server until it is executed. This distinction
+ * determines the moment when {@code SQLException}s get raised.
+ *
+ * By default, {@code ResultSet}s from the returned object will be
+ * {@link ResultSet#TYPE_FORWARD_ONLY} type with a
+ * {@link ResultSet#CONCUR_READ_ONLY} mode of concurrency.
+ *
+ * @param sql
+ * the SQL statement.
+ * @return the {@code PreparedStatement} containing the supplied SQL
+ * statement.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public PreparedStatement prepareStatement(String sql) throws SQLException;
+
+ /**
+ * Creates a default {@code PreparedStatement} that can retrieve
+ * automatically generated keys. Parameter {@code autoGeneratedKeys} may be
+ * used to tell the driver whether such keys should be made accessible.
+ * This is only relevant when the {@code sql} statement is an {@code insert}
+ * statement.
+ *
+ * An SQL statement which may have {@code IN} parameters can be stored and
+ * precompiled in a {@code PreparedStatement}. The {@code PreparedStatement}
+ * can then be then be used to execute the statement multiple times in an
+ * efficient way.
+ *
+ * Subject to JDBC driver support, this operation will attempt to send the
+ * precompiled version of the statement to the database. If
+ * the driver does not support precompiled statements, the statement will
+ * not reach the database server until it is executed. This distinction
+ * determines the moment when {@code SQLException}s get raised.
+ *
+ * By default, {@code ResultSet}s from the returned object will be
+ * {@link ResultSet#TYPE_FORWARD_ONLY} type with a
+ * {@link ResultSet#CONCUR_READ_ONLY} mode of concurrency.
+ *
+ *
+ * @param sql
+ * the SQL statement.
+ * @param autoGeneratedKeys
+ * one of the following generated key options:
+ *
+ *
{@link Statement#RETURN_GENERATED_KEYS}
+ *
{@link Statement#NO_GENERATED_KEYS}
+ *
+ * @return a new {@code PreparedStatement} instance representing the input
+ * SQL statement.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException;
+
+ /**
+ * Creates a default {@code PreparedStatement} that can retrieve the
+ * auto-generated keys designated by a supplied array. If {@code sql} is an
+ * SQL {@code INSERT} statement, the parameter {@code columnIndexes} is expected
+ * to hold the index values for each column in the statement's intended
+ * database table containing the autogenerated-keys of interest. Otherwise
+ * {@code columnIndexes} is ignored.
+ *
+ * Subject to JDBC driver support, this operation will attempt to send the
+ * precompiled version of the statement to the database. If
+ * the driver does not support precompiled statements, the statement will
+ * not reach the database server until it is executed. This distinction
+ * determines the moment when {@code SQLException}s get raised.
+ *
+ *
+ * By default, {@code ResultSet}s from the returned object will be
+ * {@link ResultSet#TYPE_FORWARD_ONLY} type with a
+ * {@link ResultSet#CONCUR_READ_ONLY} concurrency mode.
+ *
+ *
+ * @param sql
+ * the SQL statement.
+ * @param columnIndexes
+ * the indexes of the columns for which auto-generated keys
+ * should be made available.
+ * @return the PreparedStatement containing the supplied SQL statement.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+ throws SQLException;
+
+ /**
+ * Creates a {@code PreparedStatement} that generates {@code ResultSet}s
+ * with the specified values of {@code resultSetType} and {@code
+ * resultSetConcurrency}.
+ *
+ * @param sql
+ * the SQL statement. It can contain one or more {@code '?'}
+ * {@code IN} parameter placeholders.
+ * @param resultSetType
+ * one of the following type specifiers:
+ *
+ *
{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ *
{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ *
{@link ResultSet#TYPE_FORWARD_ONLY}
+ *
+ * @param resultSetConcurrency
+ * one of the following concurrency mode specifiers:
+ *
+ *
{@link ResultSet#CONCUR_READ_ONLY}
+ *
{@link ResultSet#CONCUR_UPDATABLE}
+ *
+ * @return a new instance of {@code PreparedStatement} containing the SQL
+ * statement {@code sql}. {@code ResultSet}s emitted from this
+ * {@code PreparedStatement} will satisfy the specified {@code
+ * resultSetType} and {@code resultSetConcurrency} values.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException;
+
+ /**
+ * Creates a {@code PreparedStatement} that generates {@code ResultSet}s
+ * with the specified type, concurrency and holdability
+ *
+ * @param sql
+ * the SQL statement. It can contain one or more {@code '?' IN}
+ * parameter placeholders.
+ * @param resultSetType
+ * one of the following type specifiers:
+ *
+ *
{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ *
{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ *
{@link ResultSet#TYPE_FORWARD_ONLY}
+ *
+ * @param resultSetConcurrency
+ * one of the following concurrency mode specifiers:
+ *
+ *
{@link ResultSet#CONCUR_READ_ONLY}
+ *
{@link ResultSet#CONCUR_UPDATABLE}
+ *
+ * @param resultSetHoldability
+ * one of the following holdability mode specifiers:
+ *
+ *
{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ *
{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ *
+ * @return a new instance of {@code PreparedStatement} containing the SQL
+ * statement {@code sql}. {@code ResultSet}s emitted from this
+ * {@code PreparedStatement} will satisfy the specified {@code
+ * resultSetType}, {@code resultSetConcurrency} and {@code
+ * resultSetHoldability} values.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException;
+
+ /**
+ * Creates a default {@code PreparedStatement} that can retrieve the
+ * auto-generated keys designated by a supplied array. If {@code sql} is an
+ * SQL {@code INSERT} statement, {@code columnNames} is expected to hold the
+ * names of each column in the statement's associated database table
+ * containing the autogenerated-keys of interest. Otherwise {@code
+ * columnNames} is ignored.
+ *
+ * Subject to JDBC driver support, this operation will attempt to send the
+ * precompiled version of the statement to the database. Alternatively, if
+ * the driver is not capable of handling precompiled statements, the
+ * statement will not reach the database server until it is executed. This
+ * will have a bearing on precisely when {@code SQLException}
+ * instances get raised.
+ *
+ *
+ * By default, ResultSets from the returned object will be
+ * {@link ResultSet#TYPE_FORWARD_ONLY} type with a
+ * {@link ResultSet#CONCUR_READ_ONLY} concurrency mode.
+ *
+ *
+ * @param sql
+ * the SQL statement.
+ * @param columnNames
+ * the names of the columns for which auto-generated keys should
+ * be made available.
+ * @return the PreparedStatement containing the supplied SQL statement.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public PreparedStatement prepareStatement(String sql, String[] columnNames)
+ throws SQLException;
+
+ /**
+ * Releases the specified {@code savepoint} from the present transaction. Once removed,
+ * the {@code Savepoint} is considered invalid and should not be referenced
+ * further.
+ *
+ * @param savepoint
+ * the object targeted for removal.
+ * @throws SQLException
+ * if there is a problem with accessing the database or if
+ * {@code savepoint} is considered not valid in this
+ * transaction.
+ * @since Android 1.0
+ */
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException;
+
+ /**
+ * Rolls back all updates made so far in this transaction and
+ * relinquishes all acquired database locks. It is an error to invoke this
+ * operation when in auto-commit mode.
+ *
+ * @throws SQLException
+ * if there is a problem with the database or if the method is
+ * called while in auto-commit mode of operation.
+ * @since Android 1.0
+ */
+ public void rollback() throws SQLException;
+
+ /**
+ * Undoes all changes made after the supplied {@code Savepoint} object was
+ * set. This method should only be used when auto-commit mode is disabled.
+ *
+ * @param savepoint
+ * the Savepoint to roll back to
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void rollback(Savepoint savepoint) throws SQLException;
+
+ /**
+ * Sets this connection's auto-commit mode {@code on} or {@code off}.
+ *
+ * Putting a Connection into auto-commit mode means that all associated SQL
+ * statements are run and committed as separate transactions.
+ * By contrast, setting auto-commit to {@code off} means that associated SQL
+ * statements get grouped into transactions that need to be completed by
+ * explicit calls to either the {@link #commit()} or {@link #rollback()}
+ * methods.
+ *
+ * Auto-commit is the default mode for new connection instances.
+ *
+ * When in this mode, commits will automatically occur upon successful SQL
+ * statement completion or upon successful completion of an execute.
+ * Statements are not considered successfully completed until all associated
+ * {@code ResultSet}s and output parameters have been obtained or closed.
+ *
+ *
+ * Calling this operation during an uncommitted transaction will result in
+ * it being committed.
+ *
+ *
+ * @param autoCommit
+ * {@code boolean} indication of whether to put the target
+ * connection into auto-commit mode ({@code true}) or not (
+ * {@code false}).
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void setAutoCommit(boolean autoCommit) throws SQLException;
+
+ /**
+ * Sets the catalog name for this connection. This is used to select a
+ * subspace of the database for future work. If the driver does not support
+ * catalog names, this method is ignored.
+ *
+ * @param catalog
+ * the catalog name to use.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void setCatalog(String catalog) throws SQLException;
+
+ /**
+ * Sets the holdability of the {@code ResultSet}s created by this Connection.
+ *
+ * @param holdability
+ * one of the following holdability mode specifiers:
+ *
+ *
{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ *
{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ *
+ *
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public void setHoldability(int holdability) throws SQLException;
+
+ /**
+ * Sets this connection to read-only mode.
+ *
+ * This serves as a hint to the driver, which can enable database
+ * optimizations.
+ *
+ *
+ * @param readOnly
+ * {@code true} to set the Connection to read only mode. {@code
+ * false} disables read-only mode.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void setReadOnly(boolean readOnly) throws SQLException;
+
+ /**
+ * Creates an unnamed {@code Savepoint} in the current transaction.
+ *
+ * @return a {@code Savepoint} object for this savepoint.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Savepoint setSavepoint() throws SQLException;
+
+ /**
+ * Creates a named {@code Savepoint} in the current transaction.
+ *
+ * @param name
+ * the name to use for the new {@code Savepoint}.
+ * @return a {@code Savepoint} object for this savepoint.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Savepoint setSavepoint(String name) throws SQLException;
+
+ /**
+ * Sets the transaction isolation level for this Connection.
+ *
+ * If this method is called during a transaction, the results are
+ * implementation defined.
+ *
+ *
+ * @param level
+ * the new transaction isolation level to use from the following
+ * list of possible values:
+ *
+ *
{@link #TRANSACTION_READ_COMMITTED}
+ *
{@link #TRANSACTION_READ_UNCOMMITTED}
+ *
{@link #TRANSACTION_REPEATABLE_READ}
+ *
{@link #TRANSACTION_SERIALIZABLE}
+ *
+ * @throws SQLException
+ * if there is a problem with the database or if the value of
+ * {@code level} is not one of the expected constant values.
+ * @since Android 1.0
+ */
+ public void setTransactionIsolation(int level) throws SQLException;
+
+ /**
+ * Sets the {@code TypeMap} for this connection. The input {@code map}
+ * should contain mappings between complex Java and SQL types.
+ *
+ * @param map
+ * the new type map.
+ * @throws SQLException
+ * if there is a problem accessing the database or if {@code
+ * map} is not an instance of {@link Map}.
+ * @since Android 1.0
+ */
+ public void setTypeMap(Map> map) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/DataTruncation.java b/sql/src/main/java/java/sql/DataTruncation.java
new file mode 100644
index 0000000..a472cc5
--- /dev/null
+++ b/sql/src/main/java/java/sql/DataTruncation.java
@@ -0,0 +1,135 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.Serializable;
+
+/**
+ * An exception which is thrown when a JDBC driver unexpectedly truncates a data
+ * value either when reading (resulting in warning), or when writing data
+ * (resulting in an error). The {@code SQLState} error code for truncated data
+ * is {@code 01004}.
+ *
+ * @since Android 1.0
+ */
+public class DataTruncation extends SQLWarning implements Serializable {
+
+ private static final long serialVersionUID = 6464298989504059473L;
+
+ private int index = 0;
+
+ private boolean parameter = false;
+
+ private boolean read = false;
+
+ private int dataSize = 0;
+
+ private int transferSize = 0;
+
+ private static final String THE_REASON = "Data truncation"; //$NON-NLS-1$
+
+ private static final String THE_SQLSTATE = "01004"; //$NON-NLS-1$
+
+ private static final int THE_ERROR_CODE = 0;
+
+ /**
+ * Creates the {@code DataTruncation} object. The reason is set to {@code
+ * "Data truncation"}, the {@code ErrorCode} is set to the {@code
+ * SQLException} default value, and the other fields are set to the values
+ * supplied as arguments.
+ *
+ * @param index
+ * the Index value of the column value or parameter that was
+ * truncated.
+ * @param parameter
+ * {@code true} if it was a parameter value that was truncated,
+ * {@code false} otherwise.
+ * @param read
+ * {@code true} if the truncation occurred on a read operation,
+ * {@code false} otherwise.
+ * @param dataSize
+ * the original size of the truncated data.
+ * @param transferSize
+ * the size of the data after truncation.
+ * @since Android 1.0
+ */
+ public DataTruncation(int index, boolean parameter, boolean read,
+ int dataSize, int transferSize) {
+ super(THE_REASON, THE_SQLSTATE, THE_ERROR_CODE);
+ this.index = index;
+ this.parameter = parameter;
+ this.read = read;
+ this.dataSize = dataSize;
+ this.transferSize = transferSize;
+ }
+
+ /**
+ * Gets the number of bytes of data that should have been read/written.
+ *
+ * @return the number of bytes that should have been read or written. The
+ * value is set to {@code -1} if the size is unknown.
+ * @since Android 1.0
+ */
+ public int getDataSize() {
+ return dataSize;
+ }
+
+ /**
+ * Gets the index of the column or of the parameter that was truncated.
+ *
+ * @return the index number of the column or of the parameter.
+ * @since Android 1.0
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Gets whether the value truncated was a parameter value or a column value.
+ *
+ * @return {@code true} if the value truncated was a parameter value,
+ * {@code false} if it was a column value.
+ * @since Android 1.0
+ */
+ public boolean getParameter() {
+ return parameter;
+ }
+
+ /**
+ * Gets whether the value was truncated on a read operation or a write
+ * operation
+ *
+ * @return {@code true} if the value was truncated on a read operation,
+ * {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean getRead() {
+ return read;
+ }
+
+ /**
+ * Gets the number of bytes of data that was actually read or written.
+ *
+ * @return the number of bytes actually read/written. The value may be set
+ * to {@code -1} if the size is unknown.
+ * @since Android 1.0
+ */
+ public int getTransferSize() {
+ return transferSize;
+ }
+}
diff --git a/sql/src/main/java/java/sql/DatabaseMetaData.java b/sql/src/main/java/java/sql/DatabaseMetaData.java
new file mode 100644
index 0000000..82219c5
--- /dev/null
+++ b/sql/src/main/java/java/sql/DatabaseMetaData.java
@@ -0,0 +1,3356 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+/**
+ * An interface which provides comprehensive information about the database
+ * management system and its supported features.
+ *
+ * This interface is implemented by JDBC driver vendors in order to provide
+ * information about the underlying database capabilities in association with
+ * the JDBC driver.
+ *
+ *
+ * Some of the methods in this interface take string parameters which are
+ * patterns. Within these string patterns, {@code '%'} and {@code '_'}
+ * characters have special meanings. {@code '%'} means
+ * "match any substring of 0 or more characters". {@code '_'} means
+ * "match any character". Only metadata entries that match the pattern are
+ * returned. If such a search pattern string is set to {@code null}, that
+ * argument's criteria are dropped from the search.
+ *
+ *
+ * @since Android 1.0
+ */
+public interface DatabaseMetaData {
+
+ /**
+ * States that it may not be permitted to store {@code NULL} values.
+ *
+ * @since Android 1.0
+ */
+ public static final short attributeNoNulls = 0;
+
+ /**
+ * States that {@code NULL} values are definitely permitted.
+ *
+ * @since Android 1.0
+ */
+ public static final short attributeNullable = 1;
+
+ /**
+ * States that whether {@code NULL} values are permitted is unknown.
+ *
+ * @since Android 1.0
+ */
+ public static final short attributeNullableUnknown = 2;
+
+ /**
+ * States the best row identifier is NOT a pseudo column.
+ *
+ * @since Android 1.0
+ */
+ public static final int bestRowNotPseudo = 1;
+
+ /**
+ * States that the best row identifier is a pseudo column.
+ *
+ * @since Android 1.0
+ */
+ public static final int bestRowPseudo = 2;
+
+ /**
+ * States that the remainder of the current session is used as the scope for
+ * the best row identifier.
+ *
+ * @since Android 1.0
+ */
+ public static final int bestRowSession = 2;
+
+ /**
+ * States that best row identifier scope lasts only while the row is being
+ * used.
+ *
+ * @since Android 1.0
+ */
+ public static final int bestRowTemporary = 0;
+
+ /**
+ * States that the remainder of the current transaction is used as the scope
+ * for the best row identifier.
+ *
+ * @since Android 1.0
+ */
+ public static final int bestRowTransaction = 1;
+
+ /**
+ * States that the best row identifier may or may not be a pseudo column.
+ *
+ * @since Android 1.0
+ */
+ public static final int bestRowUnknown = 0;
+
+ /**
+ * States that the column must not allow {@code NULL} values.
+ *
+ * @since Android 1.0
+ */
+ public static final int columnNoNulls = 0;
+
+ /**
+ * States that the column definitely allows {@code NULL} values.
+ *
+ * @since Android 1.0
+ */
+ public static final int columnNullable = 1;
+
+ /**
+ * States that it is unknown whether the columns may be nulled.
+ *
+ * @since Android 1.0
+ */
+ public static final int columnNullableUnknown = 2;
+
+ /**
+ * For the column {@code UPDATE_RULE}, states that when the primary key is
+ * updated, the foreign key (imported key) is changed accordingly.
+ *
+ * @since Android 1.0
+ */
+ public static final int importedKeyCascade = 0;
+
+ /**
+ * States that the evaluation of foreign key constraints is deferred (delayed
+ * until commit).
+ *
+ * @since Android 1.0
+ */
+ public static final int importedKeyInitiallyDeferred = 5;
+
+ /**
+ * States that the evaluation of foreign key constraint is {@code IMMEDIATE}
+ * .
+ *
+ * @since Android 1.0
+ */
+ public static final int importedKeyInitiallyImmediate = 6;
+
+ /**
+ * For the columns {@code UPDATE_RULE} and {@code DELETE_RULE}, states that
+ * if the primary key has been imported, it cannot be updated or deleted.
+ *
+ * @since Android 1.0
+ */
+ public static final int importedKeyNoAction = 3;
+
+ /**
+ * States that the evaluation of foreign key constraint must not be {@code
+ * DEFERRED}.
+ *
+ * @since Android 1.0
+ */
+ public static final int importedKeyNotDeferrable = 7;
+
+ /**
+ * States that a primary key must not be updated when imported as a foreign
+ * key by some other table. Used for the column {@code UPDATE_RULE}.
+ *
+ * @since Android 1.0
+ */
+ public static final int importedKeyRestrict = 1;
+
+ /**
+ * States that when the primary key is modified (updated or deleted) the
+ * foreign (imported) key is changed to its default value. Applies to the
+ * {@code UPDATE_RULE} and {@code DELETE_RULE} columns.
+ *
+ * @since Android 1.0
+ */
+ public static final int importedKeySetDefault = 4;
+
+ /**
+ * States that when the primary key is modified (updated or deleted) the
+ * foreign (imported) key is changed to {@code NULL}. Applies to the {@code
+ * UPDATE_RULE} and {@code DELETE_RULE} columns.
+ *
+ * @since Android 1.0
+ */
+ public static final int importedKeySetNull = 2;
+
+ /**
+ * States that the column stores {@code IN} type parameters.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureColumnIn = 1;
+
+ /**
+ * States that this column stores {@code INOUT} type parameters.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureColumnInOut = 2;
+
+ /**
+ * States that this column stores {@code OUT} type parameters.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureColumnOut = 4;
+
+ /**
+ * States that the column stores results.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureColumnResult = 3;
+
+ /**
+ * States that the column stores return values.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureColumnReturn = 5;
+
+ /**
+ * States that type of the column is unknown.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureColumnUnknown = 0;
+
+ /**
+ * States that {@code NULL} values are not permitted.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureNoNulls = 0;
+
+ /**
+ * States that the procedure does not return a result.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureNoResult = 1;
+
+ /**
+ * States that {@code NULL} values are permitted.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureNullable = 1;
+
+ /**
+ * States that it is unknown whether {@code NULL} values are permitted.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureNullableUnknown = 2;
+
+ /**
+ * States that it is unknown whether or not the procedure returns a result.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureResultUnknown = 0;
+
+ /**
+ * States that the procedure returns a result.
+ *
+ * @since Android 1.0
+ */
+ public static final int procedureReturnsResult = 2;
+
+ /**
+ * States that the value is an SQL99 {@code SQLSTATE} value.
+ *
+ * @since Android 1.0
+ */
+ public static final int sqlStateSQL99 = 2;
+
+ /**
+ * States that the value is an SQL {@code CLI SQLSTATE} value as defined by
+ * the X/Open standard.
+ *
+ * @since Android 1.0
+ */
+ public static final int sqlStateXOpen = 1;
+
+ /**
+ * States that this table index is a clustered index.
+ *
+ * @since Android 1.0
+ */
+ public static final short tableIndexClustered = 1;
+
+ /**
+ * States that this table index is a hashed index.
+ *
+ * @since Android 1.0
+ */
+ public static final short tableIndexHashed = 2;
+
+ /**
+ * States this table's index is neither a clustered index, not a hashed
+ * index, and not a table statistics index; i.e. it is something else.
+ *
+ * @since Android 1.0
+ */
+ public static final short tableIndexOther = 3;
+
+ /**
+ * States this column has the table's statistics, and that it is returned in
+ * conjunction with the table's index description.
+ *
+ * @since Android 1.0
+ */
+ public static final short tableIndexStatistic = 0;
+
+ /**
+ * States that a {@code NULL} value is NOT permitted for
+ * this data type.
+ *
+ * @since Android 1.0
+ */
+ public static final int typeNoNulls = 0;
+
+ /**
+ * States that a {@code NULL} value is permitted for this data type.
+ *
+ * @since Android 1.0
+ */
+ public static final int typeNullable = 1;
+
+ /**
+ * States that it is unknown if a {@code NULL} value is permitted for
+ * this data type.
+ *
+ * @since Android 1.0
+ */
+ public static final int typeNullableUnknown = 2;
+
+ /**
+ * States that this column shall not be used for {@code WHERE} statements
+ * with a {@code LIKE} clause.
+ *
+ * @since Android 1.0
+ */
+ public static final int typePredBasic = 2;
+
+ /**
+ * States that this column can only be used in a {@code WHERE...LIKE}
+ * statement.
+ *
+ * @since Android 1.0
+ */
+ public static final int typePredChar = 1;
+
+ /**
+ * States that this column does not support searches.
+ *
+ * @since Android 1.0
+ */
+ public static final int typePredNone = 0;
+
+ /**
+ * States that the column is searchable.
+ *
+ * @since Android 1.0
+ */
+ public static final int typeSearchable = 3;
+
+ /**
+ * States that the version column is known to be not a pseudo column.
+ */
+ public static final int versionColumnNotPseudo = 1;
+
+ /**
+ * States that this version column is known to be a pseudo column.
+ */
+ public static final int versionColumnPseudo = 2;
+
+ /**
+ * States that the version column may be a pseudo column or not.
+ */
+ public static final int versionColumnUnknown = 0;
+
+ /**
+ * Returns whether all procedures returned by {@link #getProcedures} can be
+ * called by the current user.
+ *
+ * @return {@code true} if all procedures can be called by the current user,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean allProceduresAreCallable() throws SQLException;
+
+ /**
+ * Returns whether all the tables returned by {@code getTables} can be used
+ * by the current user in a {@code SELECT} statement.
+ *
+ * @return {@code true} if all the tables can be used,{@code false}
+ * otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean allTablesAreSelectable() throws SQLException;
+
+ /**
+ * Returns whether a data definition statement in a transaction forces a {@code
+ * commit} of the transaction.
+ *
+ * @return {@code true} if the statement forces a commit, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean dataDefinitionCausesTransactionCommit() throws SQLException;
+
+ /**
+ * Returns whether the database ignores data definition statements within a
+ * transaction.
+ *
+ * @return {@code true} if the database ignores a data definition statement,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean dataDefinitionIgnoredInTransactions() throws SQLException;
+
+ /**
+ * Returns whether a visible row delete can be detected by calling
+ * {@link ResultSet#rowDeleted}.
+ *
+ * @param type
+ * the type of the {@code ResultSet} involved: {@code
+ * ResultSet.TYPE_FORWARD_ONLY}, {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @return {@code true} if the visible row delete can be detected, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean deletesAreDetected(int type) throws SQLException;
+
+ /**
+ * Returns whether the return value of {@code getMaxRowSize} includes the
+ * SQL data types {@code LONGVARCHAR} and {@code LONGVARBINARY}.
+ *
+ * @return {@code true} if the return value includes {@code LONGVARBINARY}
+ * and {@code LONGVARCHAR}, otherwise {@code false}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean doesMaxRowSizeIncludeBlobs() throws SQLException;
+
+ /**
+ * Returns a {@code ResultSet} describing a subset of the attributes of a
+ * specified SQL User Defined Type (UDT) for a specified schema and catalog.
+ * The subset is determined by restricting to those attributes whose
+ * name matches the {@code attributeNamePattern} and whose type name
+ * matches the {@code typeNamePattern}. Each row of the {@code ResultSet}
+ * describes one attribute, and the rows are ordered by the columns {@code TYPE_SCHEM},
+ * {@code TYPE_NAME} and {@code ORDINAL_POSITION}. Inherited attributes
+ * are not included.
+ *
+ * The columns of the returned {@code ResultSet} object have the following
+ * names and meanings:
+ *
+ *
{@code TYPE_CAT} - String - the type catalog name (possibly {@code
+ * null})
+ *
{@code TYPE_SCHEM} - String - the type schema name (possibly {@code
+ * null})
+ *
{@code TYPE_NAME} - String - the type name
+ *
{@code ATTR_NAME} - String - the attribute name
+ *
{@code DATA_TYPE} - int - the attribute type as defined in {@code
+ * java.sql.Types}
+ *
{@code ATTR_TYPE_NAME} - String - the attribute type name. This
+ * depends on the data source. For a {@code UDT} the name is fully
+ * qualified. For a {@code REF} it is both fully qualified and represents
+ * the target type of the reference.
+ *
{@code ATTR_SIZE} - int - the column size. When referring to char and
+ * date types this value is the maximum number of characters. When referring
+ * to numeric types is is the precision.
+ *
{@code DECIMAL_DIGITS} - int - how many fractional digits are
+ * supported
+ *
{@code NUM_PREC_RADIX} - int - numeric values radix
+ *
{@code NULLABLE} - int - whether {@code NULL} is permitted:
+ *
+ *
DatabaseMetaData.attributeNoNulls - {@code NULL} values not permitted
{@code REMARKS} - String - a comment describing the attribute
+ * (possibly {@code null})
+ *
ATTR_DEF - String - Default value for the attribute (possibly {@code
+ * null})
+ *
{@code SQL_DATA_TYPE} - int - not used
+ *
SQL_DATETIME_SUB - int - not used
+ *
CHAR_OCTET_LENGTH - int - for {@code CHAR} types, the max number of
+ * bytes in the column
+ *
ORDINAL_POSITION - int - The index of the column in the table (where
+ * the count starts from 1, not 0)
+ *
IS_NULLABLE - String - {@code "NO"} = the column does not allow {@code
+ * NULL}s, {@code "YES"} = the column allows {@code NULL}s, "" = status unknown
+ *
{@code SCOPE_CATALOG} - String - if the {@code DATA_TYPE} is {@code REF},
+ * this gives the catalog of the table corresponding to the attribute's scope.
+ * NULL if the {@code DATA_TYPE} is not REF.
+ *
{@code SCOPE_SCHEMA} - String - if the {@code DATA_TYPE} is {@code REF},
+ * this gives the schema of the table corresponding to the attribute's scope.
+ * NULL if the {@code DATA_TYPE} is not REF.
+ *
{@code SCOPE_TABLE} - String - if the {@code DATA_TYPE} is {@code REF},
+ * this gives the name of the table corresponding to the attribute's scope.
+ * NULL if the {@code DATA_TYPE} is not REF.
+ *
{@code SOURCE_DATA_TYPE} - String - The source type for a user
+ * generated REF type or for a Distinct type. ({@code NULL} if {@code
+ * DATA_TYPE} is not DISTINCT or a user generated REF)
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schemaPattern
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by a schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param typeNamePattern
+ * a type name. This pattern must match the type name stored in
+ * the database.
+ * @param attributeNamePattern
+ * an Attribute name. This pattern must match the attribute name as stored in
+ * the database.
+ * @return a {@code ResultSet}, where each row is an attribute description.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getAttributes(String catalog, String schemaPattern,
+ String typeNamePattern, String attributeNamePattern)
+ throws SQLException;
+
+ /**
+ * Returns a list of a table's optimal set of columns that uniquely
+ * identify the rows. The results are ordered by {@code SCOPE} (see below).
+ *
+ * The results are returned as a table, with one entry for each column, as
+ * follows:
+ *
+ *
{@code SCOPE} - short - the {@code SCOPE} of the result, as follows:
+ *
+ *
{@code DatabaseMetaData.bestRowTemporary} - the result is very temporary,
+ * only valid while on the current row
+ *
{@code DatabaseMetaData.bestRowTransaction} - the result is good for remainder of
+ * current transaction
+ *
{@code DatabaseMetaData.bestRowSession} - the result is good for remainder of
+ * database session
+ *
+ *
+ *
{@code COLUMN_NAME} - String - the column name
+ *
{@code DATA_TYPE} - int - the Type of the data, as defined in {@code
+ * java.sql.Types}
+ *
{@code TYPE_NAME} - String - the Name of the type - database dependent.
+ * For UDT types the name is fully qualified
+ *
{@code COLUMN_SIZE} - int - the precision of the data in the column
+ *
{@code BUFFER_LENGTH} - int - not used
+ *
{@code DECIMAL_DIGITS} - short - number of fractional digits
+ *
{@code PSEUDO_COLUMN} - short - whether this is a pseudo column (e.g.
+ * an Oracle {@code ROWID}):
+ *
+ *
{@code DatabaseMetaData.bestRowUnknown} - it is not known whether this is
+ * a pseudo column
+ *
{@code DatabaseMetaData.bestRowNotPseudo} - the column is not pseudo
+ *
{@code DatabaseMetaData.bestRowPseudo} - the column is a pseudo column
+ *
+ *
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schema
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param table
+ * the table name. This must match the name of the table as
+ * declared in the database.
+ * @param scope
+ * the {@code SCOPE} of interest, values as defined above.
+ * @param nullable
+ * {@code true} = include columns that are nullable, {@code
+ * false} = do not include nullable columns.
+ * @return a {@code ResultSet} where each row is a description of a column
+ * and the complete set of rows is the optimal set for this table.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getBestRowIdentifier(String catalog, String schema,
+ String table, int scope, boolean nullable) throws SQLException;
+
+ /**
+ * Returns the set of catalog names available in this database. The set is
+ * returned ordered by catalog name.
+ *
+ * @return a {@code ResultSet} containing the catalog names, with each row
+ * containing one catalog name (as a {@code String}) in the
+ * single column named {@code TABLE_CAT}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getCatalogs() throws SQLException;
+
+ /**
+ * Returns the separator that this database uses between a catalog name and
+ * table name.
+ *
+ * @return a String containing the separator.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getCatalogSeparator() throws SQLException;
+
+ /**
+ * Returns the term that the database vendor prefers term for "catalog".
+ *
+ * @return a String with the vendor's term for "catalog".
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getCatalogTerm() throws SQLException;
+
+ /**
+ * Returns a description of access rights for a table's columns. Only access
+ * rights matching the criteria for the column name are returned.
+ *
+ * The description is returned as a {@code ResultSet} with rows of data for
+ * each access right, with columns as follows:
+ *
+ *
{@code TABLE_CAT} - String - the catalog name (possibly {@code null})
+ *
{@code TABLE_SCHEM} - String - the schema name (possibly {@code null})
+ *
{@code TABLE_NAME} - String - the table name
+ *
{@code COLUMN_NAME} - String - the Column name
+ *
{@code GRANTOR} - String - the grantor of access (possibly {@code
+ * null})
+ *
{@code PRIVILEGE} - String - Access right - one of SELECT, INSERT,
+ * UPDATE, REFERENCES,...
+ *
{@code IS_GRANTABLE} - String - {@code "YES"} implies that the
+ * receiver can grant access to others, {@code "NO"} if the receiver cannot
+ * grant access to others, {@code null} if unknown.
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schema
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param table
+ * the table name. This must match the name of the table as
+ * declared in the database.
+ * @param columnNamePattern
+ * the column name. This must match the name of a column in the
+ * table in the database.
+ * @return a {@code ResultSet} containing the access rights, one row for
+ * each privilege description.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getColumnPrivileges(String catalog, String schema,
+ String table, String columnNamePattern) throws SQLException;
+
+ /**
+ * Returns a description of table columns available in a specified catalog.
+ * Only descriptions meeting the specified catalog, schema, table, and column
+ * names are returned.
+ *
+ * The descriptions are returned as a {@code ResultSet} conforming to the
+ * following data layout, with one row per table column:
+ *
+ *
{@code TABLE_CAT} - String - the catalog name (possibly {@code null})
+ *
{@code TABLE_SCHEM} - String - the schema name (possibly {@code null})
+ *
{@code TABLE_NAME} - String - the table name
+ *
{@code COLUMN_NAME} - String - the column name
+ *
{@code DATA_TYPE} - int - the SQL type as specified in {@code
+ * java.sql.Types}
+ *
{@code TYPE_NAME} - String - the name of the data type, (database-dependent,
+ * UDT names are fully qualified)
+ *
{@code COLUMN_SIZE} - int - the column size (the precision for numeric
+ * types, max characters for {@code char} and {@code date} types)
+ *
{@code BUFFER_LENGTH} - int - Not used
+ *
{@code DECIMAL_DIGITS} - int - maximum number of fractional digits
+ *
{@code NUM_PREC_RADIX} - int - the radix for numerical types
+ *
{@code NULLABLE} - int - whether the column allows {@code null}s:
+ *
+ *
DatabaseMetaData.columnNoNulls = may not allow {@code NULL}s
+ *
DatabaseMetaData.columnNullable = does allow {@code NULL}s
+ *
DatabaseMetaData.columnNullableUnknown = unknown {@code NULL} status
+ *
+ *
+ *
{@code REMARKS} - String - A description of the column (possibly
+ * {@code null})
+ *
{@code COLUMN_DEF} - String - Default value for the column (possibly
+ * {@code null})
+ *
{@code SQL_DATA_TYPE} - int - not used
+ *
{@code SQL_DATETIME_SUB} - int - not used
+ *
{@code CHAR_OCTET_LENGTH} - int - maximum number of bytes in the
+ * {@code char} type columns
+ *
{@code ORDINAL_POSITION} - int - the column index in the table (1 based)
+ *
{@code IS_NULLABLE} - String - {@code "NO"} = column does not allow
+ * NULLs, {@code "YES"} = column allows NULLs, "" = {@code NULL} status
+ * unknown
+ *
{@code SCOPE_CATALOG} - String - if the {@code DATA_TYPE} is {@code REF},
+ * this gives the catalog of the table corresponding to the attribute's scope.
+ * NULL if the {@code DATA_TYPE} is not REF.
+ *
{@code SCOPE_SCHEMA} - String - if the {@code DATA_TYPE} is {@code REF},
+ * this gives the schema of the table corresponding to the attribute's scope.
+ * NULL if the {@code DATA_TYPE} is not REF.
+ *
{@code SCOPE_TABLE} - String - if the {@code DATA_TYPE} is {@code REF},
+ * this gives the name of the table corresponding to the attribute's scope.
+ * NULL if the {@code DATA_TYPE} is not REF.
+ *
{@code SOURCE_DATA_TYPE} - String - The source type for a user
+ * generated REF type or for a Distinct type. ({@code NULL} if {@code
+ * DATA_TYPE} is not DISTINCT or a user generated REF)
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schemaPattern
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param tableNamePattern
+ * the table name. This must match the name of the table as
+ * declared in the database.
+ * @param columnNamePattern
+ * the column name. This must match the name of a column in the
+ * table in the database.
+ * @return the descriptions as a {@code ResultSet} with rows in the form
+ * defined above.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getColumns(String catalog, String schemaPattern,
+ String tableNamePattern, String columnNamePattern)
+ throws SQLException;
+
+ /**
+ * Returns the database connection that created this metadata.
+ *
+ * @return the connection to the database.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Returns a list of foreign key columns in a given foreign key table that
+ * reference the primary key columns of a supplied primary key table. This
+ * describes how one table imports the key of another table. It would be
+ * expected to return a single foreign key - primary key pair in most cases.
+ *
+ * The descriptions are returned as a {@code ResultSet} with one row for
+ * each foreign key, with the following layout:
+ *
+ *
{@code PKTABLE_CAT} - String - from the primary key table : Catalog
+ * (possibly {@code null})
+ *
{@code PKTABLE_SCHEM} - String - from the primary key table : Schema
+ * (possibly {@code null})
+ *
{@code PKTABLE_NAME} - String - from the primary key table : name
+ *
{@code PKCOLUMN_NAME} - String - from the primary key column : name
+ *
{@code FKTABLE_CAT} - String - from the foreign key table : the
+ * catalog name being exported (possibly {@code null})
+ *
{@code FKTABLE_SCHEM} - String - from the foreign key table : the schema name
+ * being exported (possibly {@code null})
+ *
{@code FKTABLE_NAME} - String - from the foreign key table : the name being
+ * exported
+ *
{@code FKCOLUMN_NAME} - String - from the foreign key column : the name being
+ * exported
+ *
{@code KEY_SEQ} - short - the sequence number (in the foreign key)
+ *
{@code UPDATE_RULE} - short - a value giving the rule for how to treat the corresponding foreign key when a primary
+ * key is updated:
+ *
+ *
{@code DatabaseMetaData.importedKeyNoAction} - don't allow the
+ * primary key to be updated if it is imported as a foreign key
+ *
{@code DatabaseMetaData.importedKeyCascade} - change the imported key to
+ * match the updated primary key
+ *
{@code DatabaseMetaData.importedKeySetNull} - set the imported key to
+ * {@code null}
+ *
{@code DatabaseMetaData.importedKeySetDefault} - set the imported key
+ * to its default value
+ *
{@code DatabaseMetaData.importedKeyRestrict} - same as {@code
+ * importedKeyNoAction}
+ *
+ *
+ *
{@code DELETE_RULE} - short - a value giving the rule for how to treat the foreign key when the corresponding primary
+ * key is deleted:
+ *
+ *
{@code DatabaseMetaData.importedKeyNoAction} - don't allow the
+ * primary key to be deleted if it is imported as a foreign key
+ *
{@code DatabaseMetaData.importedKeyCascade} - delete those rows that
+ * import a deleted key
+ *
{@code DatabaseMetaData.importedKeySetNull} - set the imported key to
+ * {@code null}
+ *
{@code DatabaseMetaData.importedKeySetDefault} - set the imported key
+ * to its default value
+ *
{@code DatabaseMetaData.importedKeyRestrict} - same as
+ * importedKeyNoAction
+ *
+ *
+ *
{@code FK_NAME} - String - the foreign key name (possibly {@code null})
+ *
{@code PK_NAME} - String - the primary key name (possibly {@code null})
+ *
{@code DEFERRABILITY} - short - whether foreign key constraints can be
+ * deferred until commit (see the SQL92 specification for definitions):
+ *
+ *
+ *
+ *
+ * @param primaryCatalog
+ * a catalog name for the primary key table. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param primarySchema
+ * a schema name for the primary key table. {@code null} is used to imply no narrowing of
+ * the search by schema name. Otherwise, the name must match a
+ * schema name in the database, with "" used to retrieve those
+ * without a schema name.
+ * @param primaryTable
+ * the name of the table which exports the key. It must match the
+ * name of the table in the database.
+ * @param foreignCatalog
+ * a catalog name for the foreign key table. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param foreignSchema
+ * a schema name for the foreign key table. {@code null} is used to imply no narrowing of
+ * the search by schema name. Otherwise, the name must match a
+ * schema name in the database, with "" used to retrieve those
+ * without a schema name.
+ * @param foreignTable
+ * the name of the table importing the key. It must match the
+ * name of the table in the database.
+ * @return a {@code ResultSet} containing rows with the descriptions of the
+ * foreign keys laid out according to the format defined above.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSet getCrossReference(String primaryCatalog,
+ String primarySchema, String primaryTable, String foreignCatalog,
+ String foreignSchema, String foreignTable) throws SQLException;
+
+ /**
+ * Returns the major version number of the database software.
+ *
+ * @return the major version number of the database software.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getDatabaseMajorVersion() throws SQLException;
+
+ /**
+ * Returns the minor version number of the database software.
+ *
+ * @return the minor version number of the database software.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getDatabaseMinorVersion() throws SQLException;
+
+ /**
+ * Returns the name of the database software.
+ *
+ * @return a {@code String} with the name of the database software.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getDatabaseProductName() throws SQLException;
+
+ /**
+ * Returns the version number of this database software.
+ *
+ * @return a {@code String} with the version number of the database
+ * software.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getDatabaseProductVersion() throws SQLException;
+
+ /**
+ * Returns the default transaction isolation level for this database.
+ *
+ * @return the default transaction isolation level. One of the following values:
+ *
+ *
{@code TRANSACTION_NONE}
+ *
{@code TRANSACTION_READ_COMMITTED}
+ *
{@code TRANSACTION_READ_UNCOMMITTED}
+ *
{@code TRANSACTION_REPEATABLE_READ}
+ *
{@code TRANSACTION_SERIALIZABLE}
+ *
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getDefaultTransactionIsolation() throws SQLException;
+
+ /**
+ * Returns the JDBC driver's major version number.
+ *
+ * @return the driver's major version number.
+ * @since Android 1.0
+ */
+ public int getDriverMajorVersion();
+
+ /**
+ * Returns the JDBC driver's minor version number.
+ *
+ * @return the driver's minor version number.
+ * @since Android 1.0
+ */
+ public int getDriverMinorVersion();
+
+ /**
+ * Returns the name of this JDBC driver.
+ *
+ * @return a {@code String} containing the name of the JDBC driver
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getDriverName() throws SQLException;
+
+ /**
+ * Returns the version number of this JDBC driver.
+ *
+ * @return a {@code String} containing the complete version number of the
+ * JDBC driver.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getDriverVersion() throws SQLException;
+
+ /**
+ * Returns a list of the foreign key columns that reference the primary key
+ * columns of a specified table (the foreign keys exported by a table).
+ *
+ * The list is returned as a {@code ResultSet} with a row for each of the
+ * foreign key columns, ordered by {@code FKTABLE_CAT}, {@code
+ * FKTABLE_SCHEM}, {@code FKTABLE_NAME}, and {@code KEY_SEQ}, with the
+ * format for each row being:
+ *
+ *
{@code PKTABLE_CAT} - String - from the primary key table : the catalog (possibly
+ * {@code null})
+ *
{@code PKTABLE_SCHEM} - String - from the primary key table : the schema (possibly
+ * {@code null})
+ *
{@code PKTABLE_NAME} - String - from the primary key table : the name
+ *
{@code PKCOLUMN_NAME} - String - from the primary key column : the name
+ *
{@code FKTABLE_CAT} - String - from the foreign key table : the catalog name being
+ * exported (possibly {@code null})
+ *
{@code FKTABLE_SCHEM} - String - from the foreign key table : the schema name
+ * being exported (possibly {@code null})
+ *
{@code FKTABLE_NAME} - String - from the foreign key table : the name being
+ * exported
+ *
{@code FKCOLUMN_NAME} - String - from the foreign key column : the name being
+ * exported
+ *
{@code KEY_SEQ} - short - the sequence number (in the foreign key)
+ *
{@code UPDATE_RULE} - short - a value giving the rule for how to treat the foreign key when the corresponding primary
+ * key is updated:
+ *
+ *
{@code DatabaseMetaData.importedKeyNoAction} - don't allow the
+ * primary key to be updated if it is imported as a foreign key
+ *
{@code DatabaseMetaData.importedKeyCascade} - change the imported key to
+ * match the primary key update
+ *
{@code DatabaseMetaData.importedKeySetNull} - set the imported key to
+ * {@code null}
+ *
{@code DatabaseMetaData.importedKeySetDefault} - set the imported key
+ * to its default value
+ *
{@code DatabaseMetaData.importedKeyRestrict} - same as
+ * importedKeyNoAction
+ *
+ *
+ *
{@code DELETE_RULE} - short - how to treat the foreign key when the corresponding primary
+ * key is deleted:
+ *
+ *
{@code DatabaseMetaData.importedKeyNoAction} - don't allow the
+ * primary key to be deleted if it is imported as a foreign key
+ *
{@code DatabaseMetaData.importedKeyCascade} - the deletion should
+ * also delete rows that import a deleted key
+ *
{@code DatabaseMetaData.importedKeySetNull} - the deletion sets the
+ * imported key to {@code null}
+ *
{@code DatabaseMetaData.importedKeySetDefault} - the deletion sets the
+ * imported key to its default value
+ *
{@code DatabaseMetaData.importedKeyRestrict} - same as
+ * importedKeyNoAction
+ *
+ *
+ *
{@code FK_NAME} - String - the foreign key name (possibly {@code null})
+ *
{@code PK_NAME} - String - the primary key name (possibly {@code null})
+ *
{@code DEFERRABILITY} - short - defines whether the foreign key
+ * constraints can be deferred until commit (see the SQL92 specification for
+ * definitions):
+ *
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schema
+ * a schema name. {@code null} is used to imply no narrowing of
+ * the search by schema name. Otherwise, the name must match a
+ * schema name in the database, with "" used to retrieve those
+ * without a schema name.
+ * @param table
+ * a table name, which must match the name of a table in the
+ * database
+ * @return a {@code ResultSet} containing a row for each of the foreign key
+ * columns, as defined above
+ * @throws SQLException
+ * a database error occurred
+ * @since Android 1.0
+ */
+ public ResultSet getExportedKeys(String catalog, String schema, String table)
+ throws SQLException;
+
+ /**
+ * Returns a string of characters that may be used in unquoted identifier
+ * names. The characters {@code a-z}, {@code A-Z}, {@code 0-9} and {@code _}
+ * are always permitted.
+ *
+ * @return a String containing all the additional permitted characters.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getExtraNameCharacters() throws SQLException;
+
+ /**
+ * Returns the string used to quote SQL identifiers. Returns " " (space) if
+ * identifier quoting not supported.
+ *
+ * @return the String used to quote SQL identifiers.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getIdentifierQuoteString() throws SQLException;
+
+ /**
+ * Returns a list columns in a table that are both primary keys and
+ * referenced by the table's foreign key columns (that is, the primary keys
+ * imported by a table).
+ *
+ * The list returned is a {@code ResultSet} with a row entry for each
+ * primary key column, ordered by {@code PKTABLE_CAT}, {@code PKTABLE_SCHEM},
+ * {@code PKTABLE_NAME}, and {@code KEY_SEQ}, with the following format:
+ *
+ *
{@code PKTABLE_CAT} - String - primary key catalog name being
+ * imported (possibly {@code null})
+ *
{@code PKTABLE_SCHEM} - String - primary key schema name being
+ * imported (possibly {@code null})
+ *
{@code PKTABLE_NAME} - String - primary key table name being imported
+ *
+ *
{@code PKCOLUMN_NAME} - String - primary key column name being
+ * imported
{@code DEFERRABILITY} - short - defines whether foreign key
+ * constraints can be deferred until commit (see SQL92 specification for
+ * definitions):
+ *
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schema
+ * a schema name. {@code null} is used to imply no narrowing of
+ * the search by schema name. Otherwise, the name must match a
+ * schema name in the database, with "" used to retrieve those
+ * without a schema name.
+ * @param table
+ * a table name, which must match the name of a table in the
+ * database.
+ * @return a {@code ResultSet} containing the list of primary key columns as
+ * rows in the format defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getImportedKeys(String catalog, String schema, String table)
+ throws SQLException;
+
+ /**
+ * Returns a list of indices and statistics for a specified table.
+ *
+ * The list is returned as a {@code ResultSet}, with one row for each index
+ * or statistic. The list is ordered by {@code NON_UNIQUE}, {@code TYPE},
+ * {@code INDEX_NAME}, and {@code ORDINAL_POSITION}. Each row has the
+ * following format:
+ *
{@code NON_UNIQUE} - boolean - {@code true} when index values can be
+ * non-unique. Must be {@code false} when the TYPE is tableIndexStatistic
+ *
{@code INDEX_QUALIFIER} - String : index catalog name. {@code null}
+ * when the TYPE is 'tableIndexStatistic'
+ *
{@code INDEX_NAME} - String : index name. {@code null} when TYPE is
+ * 'tableIndexStatistic'
+ *
{@code TYPE} - short - the index type. One of:
+ *
+ *
{@code DatabaseMetaData.tableIndexStatistic} - table statistics
+ * returned with Index descriptions
+ *
{@code DatabaseMetaData.tableIndexClustered} - a clustered Index
+ *
{@code DatabaseMetaData.tableIndexHashed} - a hashed Index
+ *
{@code DatabaseMetaData.tableIndexOther} - other style of Index
+ *
+ *
+ *
{@code ORDINAL_POSITION} - short - column sequence within Index. 0
+ * when TYPE is tableIndexStatistic
+ *
{@code COLUMN_NAME} - String - the column name. {@code null} when
+ * TYPE is tableIndexStatistic
+ *
{@code ASC_OR_DESC} - String - column sort sequence. {@code null} if
+ * sequencing not supported or TYPE is tableIndexStatistic; otherwise "A"
+ * means sort ascending and "D" means sort descending.
+ *
{@code CARDINALITY} - int - Number of unique values in the Index. If
+ * TYPE is tableIndexStatistic, this is number of rows in the table.
+ *
{@code PAGES} - int - Number of pages for current Index. If TYPE is
+ * tableIndexStatistic, this is number of pages used for the table.
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schema
+ * a schema name. {@code null} is used to imply no narrowing of
+ * the search by schema name. Otherwise, the name must match a
+ * schema name in the database, with "" used to retrieve those
+ * without a schema name.
+ * @param table
+ * a table name, which must match the name of a table in the
+ * database.
+ * @param unique
+ * {@code true} means only return indices for unique values,
+ * {@code false} implies that they can be returned even if not
+ * unique.
+ * @param approximate
+ * {@code true} implies that the list can contain approximate or
+ * "out of data" values, {@code false} implies that all values
+ * must be precisely accurate
+ * @return a {@code ResultSet} containing the list of indices and statistics
+ * for the table, in the format defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getIndexInfo(String catalog, String schema, String table,
+ boolean unique, boolean approximate) throws SQLException;
+
+ /**
+ * Returns this driver's major JDBC version number.
+ *
+ * @return the major JDBC version number.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getJDBCMajorVersion() throws SQLException;
+
+ /**
+ * Returns the minor JDBC version number for this driver.
+ *
+ * @return the Minor JDBC Version Number.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getJDBCMinorVersion() throws SQLException;
+
+ /**
+ * Get the maximum number of hex characters in an in-line binary literal for
+ * this database.
+ *
+ * @return the maximum number of hex characters in an in-line binary
+ * literal. If the number is unlimited then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxBinaryLiteralLength() throws SQLException;
+
+ /**
+ * Returns the maximum size of a catalog name in this database.
+ *
+ * @return the maximum size in characters for a catalog name. If the limit
+ * is unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxCatalogNameLength() throws SQLException;
+
+ /**
+ * Returns the maximum size for a character literal in this database.
+ *
+ * @return the maximum size in characters for a character literal. If the
+ * limit is unknown, or the value is unlimited, then the result is
+ * zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxCharLiteralLength() throws SQLException;
+
+ /**
+ * Returns the maximum size for a Column name for this database.
+ *
+ * @return the maximum number of characters for a Column name. If the limit
+ * is unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxColumnNameLength() throws SQLException;
+
+ /**
+ * Get the maximum number of columns in a {@code GROUP BY} clause for this
+ * database.
+ *
+ * @return the maximum number of columns in a {@code GROUP BY} clause. If
+ * the limit is unknown, or the value is unlimited, then the result
+ * is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxColumnsInGroupBy() throws SQLException;
+
+ /**
+ * Returns the maximum number of columns in an Index for this database.
+ *
+ * @return the maximum number of columns in an Index. If the limit is
+ * unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxColumnsInIndex() throws SQLException;
+
+ /**
+ * Returns the maximum number of columns in an {@code ORDER BY} clause for
+ * this database.
+ *
+ * @return the maximum number of columns in an {@code ORDER BY} clause. If
+ * the limit is unknown, or the value is unlimited, then the result
+ * is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxColumnsInOrderBy() throws SQLException;
+
+ /**
+ * Returns the maximum number of columns in a {@code SELECT} list for this
+ * database.
+ *
+ * @return the maximum number of columns in a {@code SELECT} list. If the
+ * limit is unknown, or the value is unlimited, then the result is
+ * zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxColumnsInSelect() throws SQLException;
+
+ /**
+ * Returns the maximum number of columns in a table for this database.
+ *
+ * @return the maximum number of columns in a table. If the limit is
+ * unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxColumnsInTable() throws SQLException;
+
+ /**
+ * Returns the database's maximum number of concurrent connections.
+ *
+ * @return the maximum number of connections. If the limit is unknown, or
+ * the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxConnections() throws SQLException;
+
+ /**
+ * Returns the maximum length of a cursor name for this database.
+ *
+ * @return the maximum number of characters in a cursor name. If the limit
+ * is unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxCursorNameLength() throws SQLException;
+
+ /**
+ * Returns the maximum length in bytes for an Index for this database. This
+ * covers all the parts of a composite index.
+ *
+ * @return the maximum length in bytes for an Index. If the limit is
+ * unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxIndexLength() throws SQLException;
+
+ /**
+ * Returns the maximum number of characters for a procedure name in this
+ * database.
+ *
+ * @return the maximum number of character for a procedure name. If the
+ * limit is unknown, or the value is unlimited, then the result is
+ * zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxProcedureNameLength() throws SQLException;
+
+ /**
+ * Returns the maximum number of bytes within a single row for this
+ * database.
+ *
+ * @return the maximum number of bytes for a single row. If the limit is
+ * unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxRowSize() throws SQLException;
+
+ /**
+ * Returns the maximum number of characters in a schema name for this
+ * database.
+ *
+ * @return the maximum number of characters in a schema name. If the limit
+ * is unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxSchemaNameLength() throws SQLException;
+
+ /**
+ * Returns the maximum number of characters in an SQL statement for this
+ * database.
+ *
+ * @return the maximum number of characters in an SQL statement. If the
+ * limit is unknown, or the value is unlimited, then the result is
+ * zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxStatementLength() throws SQLException;
+
+ /**
+ * Get the maximum number of simultaneously open active statements for this
+ * database.
+ *
+ * @return the maximum number of open active statements. If the limit is
+ * unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxStatements() throws SQLException;
+
+ /**
+ * Returns the maximum size for a table name in the database.
+ *
+ * @return the maximum size in characters for a table name. If the limit is
+ * unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxTableNameLength() throws SQLException;
+
+ /**
+ * Returns the maximum number of tables permitted in a {@code SELECT}
+ * statement for the database.
+ *
+ * @return the maximum number of tables permitted in a {@code SELECT}
+ * statement. If the limit is unknown, or the value is unlimited,
+ * then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxTablesInSelect() throws SQLException;
+
+ /**
+ * Returns the maximum number of characters in a user name for the database.
+ *
+ * @return the maximum number of characters in a user name. If the limit is
+ * unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getMaxUserNameLength() throws SQLException;
+
+ /**
+ * Returns a list of the math functions available with this database. These
+ * are used in the JDBC function escape clause and are the Open Group CLI
+ * math function names.
+ *
+ * @return a String which contains the list of math functions as a comma
+ * separated list.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getNumericFunctions() throws SQLException;
+
+ /**
+ * Returns a list of the primary key columns of a specified table.
+ *
+ * The list is returned as a {@code ResultSet} with one row for each primary
+ * key column, ordered by {@code COLUMN_NAME}, with each row having the
+ * structure as follows:
+ *
+ *
{@code TABLE_CAT} - String - table catalog name (possibly null)
+ *
{@code TABLE_SCHEM} - String - table schema name (possibly null)
+ *
{@code TABLE_NAME} - String - The table name
+ *
{@code COLUMN_NAME} - String - The column name
+ *
{@code KEY_SEQ} - short - the sequence number for this column in the
+ * primary key
+ *
{@code PK_NAME} - String - the primary key name (possibly null)
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with the empty string used
+ * to retrieve those without a catalog name.
+ * @param schema
+ * a schema name. {@code null} is used to imply no narrowing of
+ * the search by schema name. Otherwise, the name must match a
+ * schema name in the database, with the empty string used to
+ * retrieve those without a schema name.
+ * @param table
+ * the name of a table, which must match the name of a table in
+ * the database.
+ * @return a {@code ResultSet} containing the list of keys in the format
+ * defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getPrimaryKeys(String catalog, String schema, String table)
+ throws SQLException;
+
+ /**
+ * Returns a list of parameter and result columns for the stored procedures
+ * belonging to a specified catalog.
+ *
+ * The list is returned as a {@code ResultSet} with one row for each
+ * parameter or result column. The data is ordered by {@code
+ * PROCEDURE_SCHEM} and {@code PROCEDURE_NAME}, while for each procedure,
+ * the return value (if any) is first, followed by the parameters in the
+ * order they appear in the stored procedure call, followed by {@code
+ * ResultSet} columns in column number order. Each row has the following
+ * structure:
+ *
+ *
{@code PROCEDURE_CAT} - String - the procedure catalog name
+ *
{@code PROCEDURE_SCHEM} - String - the procedure schema name
+ * (possibly null)
+ *
{@code PROCEDURE_NAME} - String - the procedure name
+ *
{@code COLUMN_NAME} - String - the name of the column
+ *
{@code COLUMN_TYPE} - short - the kind of column or parameter, as
+ * follows:
+ *
+ *
{@code DatabaseMetaData.procedureColumnUnknown} - type unknown
+ *
{@code DatabaseMetaData.procedureColumnIn} - an {@code IN} parameter
+ *
{@code DatabaseMetaData.procedureColumnInOut} - an {@code INOUT}
+ * parameter
+ *
{@code DatabaseMetaData.procedureColumnOut} - an {@code OUT}
+ * parameter
+ *
{@code DatabaseMetaData.procedureColumnReturn} - a return value
+ *
{@code DatabaseMetaData.procedureReturnsResult} - a result column in
+ * a result set
+ *
+ *
+ *
{@code DATA_TYPE} - int - the SQL type of the data, as in {@code
+ * java.sql.Types}
+ *
{@code TYPE_NAME} - String - the SQL type name, for a UDT it is fully
+ * qualified
+ *
{@code PRECISION} - int - the precision
+ *
{@code LENGTH} - int - the length of the data in bytes
+ *
{@code SCALE} - short - the scale for numeric types
+ *
{@code RADIX} - short - the Radix for numeric data (typically 2 or
+ * 10)
+ *
{@code NULLABLE} - short - can the data contain {@code null}:
+ *
+ *
{@code DatabaseMetaData.procedureNoNulls} - {@code NULL}s not
+ * permitted
+ *
{@code DatabaseMetaData.procedureNullable} - {@code NULL}s are
+ * permitted
+ *
{@code DatabaseMetaData.procedureNullableUnknown} - {@code NULL}
+ * status unknown
+ *
+ *
+ *
{@code REMARKS} - String - an explanatory comment about the data item
+ *
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schemaPattern
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param procedureNamePattern
+ * a pattern that must match the name of the procedure stored in
+ * the database.
+ * @param columnNamePattern
+ * a column name pattern. The name must match the column name
+ * stored in the database.
+ * @return a {@code ResultSet} with the list of parameter and result columns
+ * in the format defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getProcedureColumns(String catalog, String schemaPattern,
+ String procedureNamePattern, String columnNamePattern)
+ throws SQLException;
+
+ /**
+ * Returns a list of the stored procedures available in a specified catalog.
+ *
+ * The list is returned as a {@code ResultSet} with one row for each stored
+ * procedure, ordered by PROCEDURE_SCHEM and PROCEDURE_NAME, with the data
+ * in each row as follows:
+ *
+ *
{@code PROCEDURE_CAT} - String : the procedure catalog name
+ *
{@code PROCEDURE_SCHEM} - String : the procedure schema name
+ * (possibly {@code null})
+ *
{@code PROCEDURE_NAME} - String : the procedure name
+ *
{@code Reserved}
+ *
{@code Reserved}
+ *
{@code Reserved}
+ *
{@code REMARKS} - String - information about the procedure
+ *
{@code PROCEDURE_TYPE} - short : one of:
+ *
+ *
{@code DatabaseMetaData.procedureResultUnknown} - procedure may
+ * return a result
+ *
{@code DatabaseMetaData.procedureNoResult} - procedure does not
+ * return a result
+ *
{@code DatabaseMetaData.procedureReturnsResult} - procedure
+ * definitely returns a result
+ *
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schemaPattern
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param procedureNamePattern
+ * a procedure name pattern, which must match the procedure name
+ * stored in the database.
+ * @return a {@code ResultSet} where each row is a description of a stored
+ * procedure in the format defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getProcedures(String catalog, String schemaPattern,
+ String procedureNamePattern) throws SQLException;
+
+ /**
+ * Returns the database vendor's preferred name for "procedure".
+ *
+ * @return a String with the vendor's preferred name for "procedure".
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getProcedureTerm() throws SQLException;
+
+ /**
+ * Returns the result set's default holdability.
+ *
+ * @return one of {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code
+ * ResultSet.CLOSE_CURSORS_AT_COMMIT}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getResultSetHoldability() throws SQLException;
+
+ /**
+ * Returns a list of the schema names in the database. The list is returned
+ * as a {@code ResultSet}, ordered by the schema name, with one row per
+ * schema in the following format:
+ *
+ *
{@code TABLE_SCHEM} - String - the schema name
{@code
+ * TABLE_CATALOG} - String - the catalog name (possibly {@code null})
+ *
+ *
+ * @return a {@code ResultSet} with one row for each schema in the format
+ * defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getSchemas() throws SQLException;
+
+ /**
+ * Returns the database vendor's preferred term for "schema".
+ *
+ * @return a String which is the vendor's preferred term for schema.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getSchemaTerm() throws SQLException;
+
+ /**
+ * Returns the string that is used to escape wildcard characters. This
+ * string is used to escape the {@code '_'} and {@code '%'} wildcard
+ * characters in catalog search pattern strings. {@code '_'} is used to represent any single
+ * character while {@code '%'} is used for a sequence of zero or more
+ * characters.
+ *
+ * @return a String used to escape the wildcard characters.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getSearchStringEscape() throws SQLException;
+
+ /**
+ * Returns a list of all the SQL keywords that are NOT also SQL92 keywords
+ * for the database.
+ *
+ * @return a String containing the list of SQL keywords in a comma separated
+ * format.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getSQLKeywords() throws SQLException;
+
+ /**
+ * States the type of {@code SQLState} value returned by {@code
+ * SQLException.getSQLState}. This can either be the X/Open (now known as
+ * Open Group) SQL CLI form or the SQL99 form.
+ *
+ * @return an integer, which is either {@code
+ * DatabaseMetaData.sqlStateSQL99} or {@code
+ * DatabaseMetaData.sqlStateXOpen}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public int getSQLStateType() throws SQLException;
+
+ /**
+ * Returns a list of string functions available with the database. These
+ * functions are used in JDBC function escape clause and follow the Open
+ * Group CLI string function names definition.
+ *
+ * @return a String containing the list of string functions in comma
+ * separated format.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getStringFunctions() throws SQLException;
+
+ /**
+ * Returns a listing of the hierarchies of tables in a specified schema in
+ * the database.
+ *
+ * The listing only contains entries for tables that have a super table.
+ * Super tables and corresponding subtables must be defined in the same catalog and schema. The
+ * list is returned as a {@code ResultSet}, with one row for each table that
+ * has a super table, in the following format:
+ *
SUPER{@code TABLE_NAME} - String - The super table name
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schemaPattern
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param tableNamePattern
+ * a table name, which should match the table name as stored in
+ * the database. it may be a fully qualified name. If it is fully
+ * qualified the catalog name and schema name parameters are
+ * ignored.
+ * @return a {@code ResultSet} with one row for each table which has a super
+ * table, in the format defined above. An empty {@code ResultSet} is
+ * returned if the database does not support table hierarchies.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getSuperTables(String catalog, String schemaPattern,
+ String tableNamePattern) throws SQLException;
+
+ /**
+ * Returns the User Defined Type (UDT) hierarchies for a given schema. Only
+ * the immediate parent/child relationship is described. If a UDT does not
+ * have a direct supertype, it is not listed.
+ *
+ * The listing is returned as a {@code ResultSet} where there is one row for
+ * a specific UDT which describes its supertype, with the data organized in
+ * columns as follows:
+ *
+ *
{@code TYPE_CAT} - String - the UDT catalog name (possibly {@code
+ * null})
+ *
{@code TYPE_SCHEM} - String - the UDT schema name (possibly {@code
+ * null})
+ *
{@code TYPE_NAME} - String - the UDT type name
+ *
SUPER{@code TYPE_CAT} - String - direct supertype's catalog name
+ * (possibly {@code null})
+ *
SUPER{@code TYPE_SCHEM} - String - direct supertype's schema name
+ * (possibly {@code null})
+ *
SUPER{@code TYPE_NAME} - String - direct supertype's name
+ *
+ *
+ *
+ * @param catalog
+ * the catalog name. "" means get the UDTs without a catalog.
+ * {@code null} means don't use the catalog name to restrict the
+ * search.
+ * @param schemaPattern
+ * the Schema pattern name. "" means get the UDT's without a
+ * schema.
+ * @param typeNamePattern
+ * the UDT name pattern. This may be a fully qualified name. When
+ * a fully qualified name is specified, the catalog name and
+ * schema name parameters are ignored.
+ * @return a {@code ResultSet} in which each row gives information about a
+ * particular UDT in the format defined above. An empty ResultSet is
+ * returned for a database that does not support type hierarchies.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getSuperTypes(String catalog, String schemaPattern,
+ String typeNamePattern) throws SQLException;
+
+ /**
+ * Returns a list of system functions available with the database. These are
+ * names used in the JDBC function escape clause and are Open Group CLI
+ * function names.
+ *
+ * @return a String containing the list of system functions in a comma
+ * separated format.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getSystemFunctions() throws SQLException;
+
+ /**
+ * Returns a description of access rights for each table present in a
+ * catalog. Table privileges can apply to one or more columns in the table -
+ * but are not guaranteed to apply to all columns.
+ *
+ * The privileges are returned as a {@code ResultSet}, with one row for each
+ * privilege, ordered by {@code TABLE_SCHEM}, {@code TABLE_NAME}, {@code
+ * PRIVILEGE}, and each row has data as defined in the following column
+ * definitions:
+ *
PRIVILEGE - String - the type of access granted - one of SELECT,
+ * INSERT, UPDATE, REFERENCES,...
+ *
IS_GRANTABLE - String - {@code "YES"} implies the grantee can grant
+ * access to others, {@code "NO"} implies guarantee cannot grant access to
+ * others, {@code null} means this status is unknown
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schemaPattern
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param tableNamePattern
+ * a Table Name, which should match the table name as stored in
+ * the database.
+ * @return a {@code ResultSet} containing a list with one row for each table
+ * in the format defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getTablePrivileges(String catalog, String schemaPattern,
+ String tableNamePattern) throws SQLException;
+
+ /**
+ * Returns a description of the tables in a specified catalog.
+ *
+ * The descriptions are returned as rows in a {@code ResultSet}, one row for
+ * each Table. The ResultSet is ordered by {@code TABLE_TYPE}, {@code
+ * TABLE_SCHEM} and {@code TABLE_NAME}. Each row in the ResultSet consists
+ * of a series of columns as follows:
+ *
{@code TYPE_NAME} - String - the 'Types' name (possibly {@code null})
+ *
+ *
{@code SELF_REFERENCING_COL_NAME} - String - the name of a designated
+ * identifier column in a typed table (possibly {@code null})
+ *
REF_GENERATION - String - one of the following values : "SYSTEM" |
+ * "USER" | "DERIVED" - specifies how values in the {@code
+ * SELF_REFERENCING_COL_NAME} are created (possibly {@code null})
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schemaPattern
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search by schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param tableNamePattern
+ * a table name, which should match the table name as stored in
+ * the database.
+ * @param types
+ * a list of table types to include in the list. {@code null}
+ * implies list all types.
+ * @return a {@code ResultSet} with one row per table in the format defined
+ * above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getTables(String catalog, String schemaPattern,
+ String tableNamePattern, String[] types) throws SQLException;
+
+ /**
+ * Returns a list of table types supported by the database.
+ *
+ * The list is returned as a {@code ResultSet} with one row per table type,
+ * ordered by the table type. The information in the {@code ResultSet} is
+ * structured into a single column per row, as follows:
+ *
+ *
{@code TABLE_TYPE} - String - the table type. Typical names include
+ * {@code "TABLE"}, {@code "VIEW"}, "{@code SYSTEM TABLE"}, {@code "ALIAS"},
+ * {@code "SYNONYM"}, {@code "GLOBAL TEMPORARY"}
+ *
+ *
+ *
+ * @return a {@code ResultSet} with one row per table type in the format
+ * defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getTableTypes() throws SQLException;
+
+ /**
+ * Returns a list of time and date functions available for the database.
+ *
+ * @return a string containing a comma separated list of the time and date
+ * functions.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getTimeDateFunctions() throws SQLException;
+
+ /**
+ * Get a list of the standard SQL types supported by this database. The list
+ * is returned as a {@code ResultSet}, with one row for each type, ordered
+ * by the {@code DATA_TYPE} value, where the data in each row is structured
+ * into the following columns:
+ *
+ *
{@code TYPE_NAME} - String : the type name
+ *
{@code DATA_TYPE} - int : the SQL data type value as defined in
+ * {@code java.sql.Types}
+ *
{@code PRECISION} - int - the maximum precision of the type
+ *
{@code LITERAL_PREFIX} - String : the prefix to be used when quoting
+ * a literal value (possibly {@code null})
+ *
{@code LITERAL_SUFFIX} - String : the suffix to be used when quoting
+ * a literal value (possibly {@code null})
+ *
{@code CREATE_PARAMS} - String : params used when creating the type
+ * (possibly {@code null})
+ *
{@code NULLABLE} - short : shows if the value is nullable:
+ *
+ *
{@code DatabaseMetaData.typeNoNulls} : {@code NULL}s not permitted
+ *
{@code DatabaseMetaData.typeNullable} : {@code NULL}s are permitted
+ *
{@code DatabaseMetaData.typeNullableUnknown} : {@code NULL} status
+ * unknown
+ *
+ *
+ *
{@code CASE_SENSITIVE} - boolean : true if the type is case sensitive
+ *
+ *
{@code SEARCHABLE} - short : how this type can be used with {@code WHERE}
+ * clauses:
+ *
+ *
{@code DatabaseMetaData.typePredNone} - {@code WHERE} clauses cannot be used
+ *
{@code DatabaseMetaData.typePredChar} - support for {@code
+ * WHERE...LIKE} only
+ *
{@code DatabaseMetaData.typePredBasic} - support except for {@code
+ * WHERE...LIKE}
+ *
{@code DatabaseMetaData.typeSearchable} - support for all {@code
+ * WHERE} clauses
+ *
+ *
+ *
{@code UNSIGNED_ATTRIBUTE} - boolean - the type is unsigned or not
+ *
{@code FIXED_PREC_SCALE} - boolean - fixed precision = it can be used
+ * as a money value
+ *
{@code AUTO_INCREMENT} - boolean - can be used as an auto-increment
+ * value
+ *
{@code LOCAL_TYPE_NAME} - String - a localized version of the type
+ * name (possibly {@code null})
+ *
{@code MINIMUM_SCALE} - short - the minimum scale supported
+ *
{@code MAXIMUM_SCALE} - short - the maximum scale supported
+ *
{@code SQL_DATA_TYPE} - int - not used
+ *
{@code SQL_DATETIME_SUB} - int - not used
+ *
{@code NUM_PREC_RADIX} - int - number radix (typically 2 or 10)
+ *
+ *
+ * @return a {@code ResultSet} which is structured as described above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getTypeInfo() throws SQLException;
+
+ /**
+ * Returns a description of the User Defined Types (UDTs) defined in a given
+ * schema, which includes the types {@code DISTINCT}, {@code STRUCT} and
+ * {@code JAVA_OBJECT}.
+ *
+ * The types matching the supplied the specified catalog, schema, type name
+ * and type are returned as rows in a {@code ResultSet} with columns of
+ * information as follows:
+ *
+ *
{@code TABLE_CAT} - String - catalog name (possibly {@code null})
+ *
{@code TABLE_SCHEM} - String - schema name (possibly {@code null})
+ *
{@code TABLE_NAME} - String - The table name
+ *
{@code CLASS_NAME} - String - The Java class name
+ *
{@code DATA_TYPE} - int - The SQL type as specified in {@code
+ * java.sql.Types}. One of DISTINCT, STRUCT, and JAVA_OBJECT
+ *
{@code REMARKS} - String - A comment which describes the type
+ *
{@code BASE_TYPE} - short - A type code. For a DISTINCT type, the
+ * source type. For a structured type this is the type that implements the
+ * user generated reference type of the {@code SELF_REFERENCING_COLUMN}.
+ * This is defined in {@code java.sql.Types}, and will be {@code null} if
+ * the {@code DATA_TYPE} does not match these criteria.
+ *
+ *
+ *
+ * If the driver does not support UDTs, the {@code ResultSet} is empty.
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search by catalog name. Otherwise, the name must match a
+ * catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schemaPattern
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search using schema name. Otherwise, the name
+ * must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param typeNamePattern
+ * a type name pattern, which should match a type name as stored in the
+ * database. It may be fully qualified.
+ * @param types
+ * a list of the UDT types to include in the list - one of
+ * {@code DISTINCT}, {@code STRUCT} or {@code JAVA_OBJECT}.
+ * @return a {@code ResultSet} in the format described above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getUDTs(String catalog, String schemaPattern,
+ String typeNamePattern, int[] types) throws SQLException;
+
+ /**
+ * Returns the URL for this database.
+ *
+ * @return the URL for the database. {@code null} if it cannot be generated.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getURL() throws SQLException;
+
+ /**
+ * Determine the user name as known by the database.
+ *
+ * @return the user name.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public String getUserName() throws SQLException;
+
+ /**
+ * Returns which of a table's columns are automatically updated when any
+ * value in a row is updated.
+ *
+ * The result is laid-out in the following columns:
+ *
+ *
{@code SCOPE} - short - not used
+ *
{@code COLUMN_NAME} - String - Column name
+ *
{@code DATA_TYPE} - int - The SQL data type, as defined in {@code
+ * java.sql.Types}
+ *
{@code TYPE_NAME} - String - The SQL type name, data source dependent
+ *
+ *
{@code COLUMN_SIZE} - int - Precision for numeric types
+ *
{@code BUFFER_LENGTH} - int - Length of a column value in bytes
+ *
{@code DECIMAL_DIGITS} - short - Number of digits after the decimal
+ * point
+ *
{@code PSEUDO_COLUMN} - short - If this is a pseudo-column (for
+ * example, an Oracle {@code ROWID}):
+ *
+ *
{@code DatabaseMetaData.bestRowUnknown} - don't know whether this is
+ * a pseudo column
+ *
{@code DatabaseMetaData.bestRowNotPseudo} - column is not pseudo
+ *
{@code DatabaseMetaData.bestRowPseudo} - column is a pseudo column
+ *
+ *
+ *
+ *
+ *
+ * @param catalog
+ * a catalog name. {@code null} is used to imply no narrowing of
+ * the search using catalog name. Otherwise, the name must match
+ * a catalog name held in the database, with "" used to retrieve
+ * those without a catalog name.
+ * @param schema
+ * a schema name pattern. {@code null} is used to imply no
+ * narrowing of the search using schema names. Otherwise, the
+ * name must match a schema name in the database, with "" used to
+ * retrieve those without a schema name.
+ * @param table
+ * a table name. It must match the name of a table in the
+ * database.
+ * @return a {@code ResultSet} containing the descriptions, one row for each
+ * column, in the format defined above.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public ResultSet getVersionColumns(String catalog, String schema,
+ String table) throws SQLException;
+
+ /**
+ * Determines whether a visible row insert can be detected by calling {@code
+ * ResultSet.rowInserted}.
+ *
+ * @param type
+ * the {@code ResultSet} type. This may be one of {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE} or {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE} or {@code
+ * ResultSet.TYPE_FORWARD_ONLY},
+ * @return {@code true} if {@code ResultSet.rowInserted} detects a visible
+ * row insert otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @see ResultSet#rowInserted()
+ * @since Android 1.0
+ */
+ public boolean insertsAreDetected(int type) throws SQLException;
+
+ /**
+ * Determine whether a fully qualified table name is prefixed or suffixed to
+ * a fully qualified table name.
+ *
+ * @return {@code true} if the catalog appears at the start of a fully
+ * qualified table name, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean isCatalogAtStart() throws SQLException;
+
+ /**
+ * Determines whether the database is in read-only mode.
+ *
+ * @return {@code true} if the database is in read-only mode, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean isReadOnly() throws SQLException;
+
+ /**
+ * Determines whether updates are made to a copy of, or directly on, Large Objects
+ * ({@code LOB}s).
+ *
+ * @return {@code true} if updates are made to a copy of the Large Object,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean locatorsUpdateCopy() throws SQLException;
+
+ /**
+ * Determines whether the database handles concatenations between {@code NULL} and
+ * non-{@code NULL} values by producing a {@code NULL} output.
+ *
+ * @return {@code true} if {@code NULL} to non-{@code NULL} concatenations
+ * produce a {@code NULL} result, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean nullPlusNonNullIsNull() throws SQLException;
+
+ /**
+ * Determines whether {@code NULL} values are always sorted to the end of sorted
+ * results regardless of requested sort order. This means that they will
+ * appear at the end of sorted lists whatever other non-{@code NULL} values
+ * may be present.
+ *
+ * @return {@code true} if {@code NULL} values are sorted at the end,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean nullsAreSortedAtEnd() throws SQLException;
+
+ /**
+ * Determines whether {@code NULL} values are always sorted at the start of the
+ * sorted list, irrespective of the sort order. This means that they appear
+ * at the start of sorted lists, whatever other values may be present.
+ *
+ * @return {@code true} if {@code NULL} values are sorted at the start,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean nullsAreSortedAtStart() throws SQLException;
+
+ /**
+ * Determines whether {@code NULL} values are sorted high - i.e. they are sorted
+ * as if they are higher than any other values.
+ *
+ * @return {@code true} if {@code NULL} values are sorted high, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean nullsAreSortedHigh() throws SQLException;
+
+ /**
+ * Determines whether {@code NULL} values are sorted low - i.e. they are sorted as
+ * if they are lower than any other values.
+ *
+ * @return {@code true} if {@code NULL} values are sorted low, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean nullsAreSortedLow() throws SQLException;
+
+ /**
+ * Determines whether deletes made by others are visible, for a specified {@code
+ * ResultSet} type.
+ *
+ * @param type
+ * the type of the {@code ResultSet}. It may be either {@code
+ * ResultSet.TYPE_FORWARD_ONLY} or {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE})
+ * @return {@code true} if others' deletes are visible, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean othersDeletesAreVisible(int type) throws SQLException;
+
+ /**
+ * Determines whether inserts made by others are visible, for a specified {@code
+ * ResultSet} type.
+ *
+ * @param type
+ * the type of the {@code ResultSet}. May be {@code
+ * ResultSet.TYPE_FORWARD_ONLY}, or {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @return {@code true} if others' inserts are visible, otherwise {@code
+ * false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean othersInsertsAreVisible(int type) throws SQLException;
+
+ /**
+ * Determines whether updates made by others are visible, for a specified {@code
+ * ResultSet} type.
+ *
+ * @param type
+ * the type of the {@code ResultSet}. May be {@code
+ * ResultSet.TYPE_FORWARD_ONLY}, or {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @return {@code true} if others' inserts are visible, otherwise {@code
+ * false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean othersUpdatesAreVisible(int type) throws SQLException;
+
+ /**
+ * Determines whether a {@code ResultSet} can see its own deletes, for a
+ * specified {@code ResultSet} type.
+ *
+ * @param type
+ * the type of the {@code ResultSet}: {@code
+ * ResultSet.TYPE_FORWARD_ONLY}, {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @return {@code true} if the deletes are seen by the {@code
+ * ResultSet} itself, otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean ownDeletesAreVisible(int type) throws SQLException;
+
+ /**
+ * Determines whether a {@code ResultSet} can see its own inserts, for a
+ * specified {@code ResultSet} type.
+ *
+ * @param type
+ * the type of the {@code ResultSet}: {@code
+ * ResultSet.TYPE_FORWARD_ONLY}, {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @return {@code true} if the inserts are seen by the {@code
+ * ResultSet} itself, otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean ownInsertsAreVisible(int type) throws SQLException;
+
+ /**
+ * Determines whether a {@code ResultSet} can see its own updates, for a
+ * specified {@code ResultSet} type.
+ *
+ * @param type
+ * the type of the {@code ResultSet}: {@code
+ * ResultSet.TYPE_FORWARD_ONLY}, {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @return {@code true} if the updates are seen by the {@code
+ * ResultSet} itself, otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean ownUpdatesAreVisible(int type) throws SQLException;
+
+ /**
+ * Determines whether the database treats SQL identifiers that are in mixed
+ * case (and unquoted) as case insensitive. If {@code true} then the
+ * database stores them in lower case.
+ *
+ * @return {@code true} if unquoted SQL identifiers are stored in lower
+ * case, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean storesLowerCaseIdentifiers() throws SQLException;
+
+ /**
+ * Determines whether the database considers mixed case quoted SQL
+ * identifiers as case insensitive and stores them in lower case.
+ *
+ * @return {@code true} if quoted SQL identifiers are stored in lower case,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * Determines whether the database considers mixed case unquoted SQL
+ * identifiers as case insensitive and stores them in mixed case.
+ *
+ * @return {@code true} if unquoted SQL identifiers as stored in mixed case,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean storesMixedCaseIdentifiers() throws SQLException;
+
+ /**
+ * Determines whether the database considers identifiers as case insensitive
+ * if they are mixed case quoted SQL. The database stores them in mixed
+ * case.
+ *
+ * @return {@code true} if quoted SQL identifiers are stored in mixed case,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * Determines whether the database considers mixed case unquoted SQL
+ * identifiers as case insensitive and stores them in upper case.
+ *
+ * @return {@code true} if unquoted SQL identifiers are stored in upper
+ * case, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean storesUpperCaseIdentifiers() throws SQLException;
+
+ /**
+ * Determines whether the database considers mixed case quoted SQL
+ * identifiers as case insensitive and stores them in upper case.
+ *
+ * @return {@code true} if quoted SQL identifiers are stored in upper case,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * Determines whether the database supports {@code ALTER TABLE} operation with
+ * {@code ADD COLUMN}.
+ *
+ * @return {@code true} if {@code ALTER TABLE} with {@code ADD COLUMN} is
+ * supported, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsAlterTableWithAddColumn() throws SQLException;
+
+ /**
+ * Determines whether the database supports {@code ALTER TABLE} operation with
+ * {@code DROP COLUMN}.
+ *
+ * @return {@code true} if {@code ALTER TABLE} with {@code DROP COLUMN} is
+ * supported, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsAlterTableWithDropColumn() throws SQLException;
+
+ /**
+ * Determines whether the database supports the ANSI92 entry level SQL grammar.
+ *
+ * @return {@code true} if the ANSI92 entry level SQL grammar is supported,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsANSI92EntryLevelSQL() throws SQLException;
+
+ /**
+ * Determines whether the database supports the ANSI92 full SQL grammar.
+ *
+ * @return {@code true} if the ANSI92 full SQL grammar is supported, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsANSI92FullSQL() throws SQLException;
+
+ /**
+ * Determines whether the database supports the ANSI92 intermediate SQL Grammar.
+ *
+ * @return {@code true} if the ANSI92 intermediate SQL grammar is supported,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsANSI92IntermediateSQL() throws SQLException;
+
+ /**
+ * Determines whether the database supports batch updates.
+ *
+ * @return {@code true} if batch updates are supported, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsBatchUpdates() throws SQLException;
+
+ /**
+ * Determines whether catalog names may be used in data manipulation
+ * statements.
+ *
+ * @return {@code true} if catalog names can be used in data manipulation
+ * statements, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsCatalogsInDataManipulation() throws SQLException;
+
+ /**
+ * Determines whether catalog names can be used in index definition statements.
+ *
+ * @return {@code true} if catalog names can be used in index definition
+ * statements, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsCatalogsInIndexDefinitions() throws SQLException;
+
+ /**
+ * Determines whether catalog names can be used in privilege definition
+ * statements.
+ *
+ * @return {@code true} if catalog names can be used in privilege definition
+ * statements, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException;
+
+ /**
+ * Determines whether catalog names can be used in procedure call statements.
+ *
+ * @return {@code true} if catalog names can be used in procedure call
+ * statements.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsCatalogsInProcedureCalls() throws SQLException;
+
+ /**
+ * Determines whether catalog names may be used in table definition statements.
+ *
+ * @return {@code true} if catalog names can be used in definition
+ * statements, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsCatalogsInTableDefinitions() throws SQLException;
+
+ /**
+ * Determines whether the database supports column aliasing.
+ *
+ * If aliasing is supported, then the SQL AS clause is used to provide names
+ * for computed columns and provide alias names for columns.
+ *
+ *
+ * @return {@code true} if column aliasing is supported, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ */
+ public boolean supportsColumnAliasing() throws SQLException;
+
+ /**
+ * Determines whether the database supports the {@code CONVERT} operation between
+ * SQL types.
+ *
+ * @return {@code true} if the {@code CONVERT} operation is supported,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsConvert() throws SQLException;
+
+ /**
+ * Determines whether the database supports {@code CONVERT} operation for two
+ * supplied SQL types.
+ *
+ * @param fromType
+ * the Type to convert from, as defined by {@code java.sql.Types}
+ * @param toType
+ * the Type to convert to, as defined by {@code java.sql.Types}
+ * @return {@code true} if the {@code CONVERT} operation is supported for
+ * these types, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsConvert(int fromType, int toType)
+ throws SQLException;
+
+ /**
+ * Determines whether the database supports the Core SQL Grammar for ODBC.
+ *
+ * @return {@code true} if the Core SQL Grammar is supported, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsCoreSQLGrammar() throws SQLException;
+
+ /**
+ * Determines whether the database supports correlated sub-queries.
+ *
+ * @return {@code true} if the database does support correlated sub-queries
+ * and {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsCorrelatedSubqueries() throws SQLException;
+
+ /**
+ * Determines whether the database allows both data definition and data
+ * manipulation statements inside a transaction.
+ *
+ * @return {@code true} if both types of statement are permitted, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsDataDefinitionAndDataManipulationTransactions()
+ throws SQLException;
+
+ /**
+ * Determines whether the database only allows data manipulation statements inside
+ * a transaction.
+ *
+ * @return {@code true} if data manipulation statements are permitted only within a transaction,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsDataManipulationTransactionsOnly()
+ throws SQLException;
+
+ /**
+ * Determines whether table correlation names are required to be different from
+ * the names of the tables, when they are supported.
+ *
+ * @return {@code true} if correlation names must be different from table
+ * names, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsDifferentTableCorrelationNames() throws SQLException;
+
+ /**
+ * Determines whether expressions in {@code ORDER BY} lists are supported.
+ *
+ * @return {@code true} if expressions in {@code ORDER BY} lists are
+ * supported.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsExpressionsInOrderBy() throws SQLException;
+
+ /**
+ * Determines whether the Extended SQL Grammar for ODBC is supported.
+ *
+ * @return {@code true} if the Extended SQL Grammar is supported, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsExtendedSQLGrammar() throws SQLException;
+
+ /**
+ * Determines whether the database supports full nested outer joins.
+ *
+ * @return {@code true} if full nested outer joins are supported, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsFullOuterJoins() throws SQLException;
+
+ /**
+ * Determines whether auto generated keys can be returned when a statement
+ * executes.
+ *
+ * @return {@code true} if auto generated keys can be returned, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsGetGeneratedKeys() throws SQLException;
+
+ /**
+ * Determines whether the database supports {@code GROUP BY} clauses.
+ *
+ * @return {@code true} if the {@code GROUP BY} clause is supported, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsGroupBy() throws SQLException;
+
+ /**
+ * Determines whether the database supports using a column name in a {@code GROUP
+ * BY} clause not included in the {@code SELECT} statement as long as all of
+ * the columns in the {@code SELECT} statement are used in the {@code GROUP
+ * BY} clause.
+ *
+ * @return {@code true} if {@code GROUP BY} clauses can use column names in
+ * this way, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsGroupByBeyondSelect() throws SQLException;
+
+ /**
+ * Determines whether the database supports using a column name in a {@code GROUP
+ * BY} clause that is not in the {@code SELECT} statement.
+ *
+ * @return {@code true} if {@code GROUP BY} clause can use a column name not
+ * in the {@code SELECT} statement, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsGroupByUnrelated() throws SQLException;
+
+ /**
+ * Determines whether the database supports SQL Integrity Enhancement
+ * Facility.
+ *
+ * @return {@code true} if the Integrity Enhancement Facility is supported,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsIntegrityEnhancementFacility() throws SQLException;
+
+ /**
+ * Determines whether the database supports a {@code LIKE} escape clause.
+ *
+ * @return {@code true} if LIKE escape clause is supported, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsLikeEscapeClause() throws SQLException;
+
+ /**
+ * Determines whether the database provides limited support for outer join
+ * operations.
+ *
+ * @return {@code true} if there is limited support for outer join
+ * operations, {@code false} otherwise. This will be {@code true} if
+ * {@code supportsFullOuterJoins} returns {@code true}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsLimitedOuterJoins() throws SQLException;
+
+ /**
+ * Determines whether the database supports Minimum SQL Grammar for ODBC.
+ *
+ * @return {@code true} if the Minimum SQL Grammar is supported, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsMinimumSQLGrammar() throws SQLException;
+
+ /**
+ * Determines whether the database treats mixed case unquoted SQL identifiers as
+ * case sensitive storing them in mixed case.
+ *
+ * @return {@code true} if unquoted SQL identifiers are stored in mixed
+ * case, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsMixedCaseIdentifiers() throws SQLException;
+
+ /**
+ * Determines whether the database considers mixed case quoted SQL
+ * identifiers as case sensitive, storing them in mixed case.
+ *
+ * @return {@code true} if quoted SQL identifiers are stored in mixed case,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * Determines whether it is possible for a single {@code CallableStatement} to
+ * return multiple {@code ResultSet}s simultaneously.
+ *
+ * @return {@code true} if a single {@code CallableStatement} can return
+ * multiple {@code ResultSet}s simultaneously, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsMultipleOpenResults() throws SQLException;
+
+ /**
+ * Determines whether retrieving multiple {@code ResultSet}s from a single
+ * call to the {@code execute} method is supported.
+ *
+ * @return {@code true} if multiple {@code ResultSet}s can be retrieved,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsMultipleResultSets() throws SQLException;
+
+ /**
+ * Determines whether multiple simultaneous transactions on
+ * different connections are supported.
+ *
+ * @return {@code true} if multiple open transactions are supported, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsMultipleTransactions() throws SQLException;
+
+ /**
+ * Determines whether callable statements with named parameters is supported.
+ *
+ * @return {@code true} if named parameters can be used with callable
+ * statements, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsNamedParameters() throws SQLException;
+
+ /**
+ * Determines whether columns in the database can be defined as non-nullable.
+ *
+ * @return {@code true} if columns can be defined non-nullable, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsNonNullableColumns() throws SQLException;
+
+ /**
+ * Determines whether keeping cursors open across commit operations is
+ * supported.
+ *
+ * @return {@code true} if cursors can be kept open across commit
+ * operations, {@code false} if they might get closed.
+ * @throws SQLException
+ * a database error occurred.
+ */
+ public boolean supportsOpenCursorsAcrossCommit() throws SQLException;
+
+ /**
+ * Determines whether the database can keep cursors open across rollback
+ * operations.
+ *
+ * @return {@code true} if cursors can be kept open across rollback
+ * operations, {@code false} if they might get closed.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsOpenCursorsAcrossRollback() throws SQLException;
+
+ /**
+ * Determines whether keeping statements open across commit operations is
+ * supported.
+ *
+ * @return {@code true} if statements can be kept open, {@code false} if
+ * they might not.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsOpenStatementsAcrossCommit() throws SQLException;
+
+ /**
+ * Determines whether keeping statements open across rollback operations is
+ * supported.
+ *
+ * @return {@code true} if statements can be kept open, {@code false} if
+ * they might not.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsOpenStatementsAcrossRollback() throws SQLException;
+
+ /**
+ * Determines whether using a column in an {@code ORDER BY} clause that is
+ * not in the {@code SELECT} statement is supported.
+ *
+ * @return {@code true} if it is possible to {@code ORDER} using a column
+ * not in the {@code SELECT}, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsOrderByUnrelated() throws SQLException;
+
+ /**
+ * Determines whether outer join operations are supported.
+ *
+ * @return {@code true} if outer join operations are supported, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsOuterJoins() throws SQLException;
+
+ /**
+ * Determines whether positioned {@code DELETE} statements are supported.
+ *
+ * @return {@code true} if the database supports positioned {@code DELETE}
+ * statements.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsPositionedDelete() throws SQLException;
+
+ /**
+ * Determines whether positioned {@code UPDATE} statements are supported.
+ *
+ * @return {@code true} if the database supports positioned {@code UPDATE}
+ * statements, {@code false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsPositionedUpdate() throws SQLException;
+
+ /**
+ * Determines whether there is support for a given concurrency style for the
+ * given {@code ResultSet}.
+ *
+ * @param type
+ * the {@code ResultSet} type, as defined in {@code
+ * java.sql.ResultSet}:
+ *
+ *
{@code ResultSet.TYPE_FORWARD_ONLY}
+ *
{@code ResultSet.TYPE_SCROLL_INSENSITIVE}
+ *
{@code ResultSet.TYPE_SCROLL_SENSITIVE}
+ *
+ * @param concurrency
+ * a concurrency type, which may be one of {@code
+ * ResultSet.CONCUR_READ_ONLY} or {@code
+ * ResultSet.CONCUR_UPDATABLE}.
+ * @return {@code true} if that concurrency and {@code ResultSet} type
+ * pairing is supported otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsResultSetConcurrency(int type, int concurrency)
+ throws SQLException;
+
+ /**
+ * Determines whether the supplied {@code ResultSet} holdability mode is
+ * supported.
+ *
+ * @param holdability
+ * as specified in {@code java.sql.ResultSet}: {@code
+ * ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code
+ * ResultSet.CLOSE_CURSORS_AT_COMMIT}
+ * @return {@code true} if the given ResultSet holdability is supported and
+ * if it isn't then {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsResultSetHoldability(int holdability)
+ throws SQLException;
+
+ /**
+ * Determines whether the supplied {@code ResultSet} type is supported.
+ *
+ * @param type
+ * the {@code ResultSet} type as defined in {@code
+ * java.sql.ResultSet}: {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @return {@code true} if the {@code ResultSet} type is supported, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsResultSetType(int type) throws SQLException;
+
+ /**
+ * Determines whether savepoints for transactions are supported.
+ *
+ * @return {@code true} if savepoints are supported, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSavepoints() throws SQLException;
+
+ /**
+ * Determines whether a schema name may be used in a data manipulation
+ * statement.
+ *
+ * @return {@code true} if a schema name can be used in a data manipulation,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSchemasInDataManipulation() throws SQLException;
+
+ /**
+ * Determines whether a schema name may be used in an index definition
+ * statement.
+ *
+ * @return {@code true} if a schema name can be used in an index definition,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSchemasInIndexDefinitions() throws SQLException;
+
+ /**
+ * Determines whether a database schema name can be used in a privilege
+ * definition statement.
+ *
+ * @return {@code true} if a database schema name may be used in a privilege
+ * definition, otherwise {@code false}
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException;
+
+ /**
+ * Determines whether a procedure call statement may be contain in a schema name.
+ *
+ * @return {@code true} if a schema name can be used in a procedure call,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSchemasInProcedureCalls() throws SQLException;
+
+ /**
+ * Determines whether a schema name can be used in a table definition statement.
+ *
+ * @return {@code true} if a schema name can be used in a table definition,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSchemasInTableDefinitions() throws SQLException;
+
+ /**
+ * Determines whether the {@code SELECT FOR UPDATE} statement is supported.
+ *
+ * @return {@code true} if {@code SELECT FOR UPDATE} statements are
+ * supported, otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSelectForUpdate() throws SQLException;
+
+ /**
+ * Determines whether statement pooling is supported.
+ *
+ * @return {@code true} of the database does support statement pooling,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsStatementPooling() throws SQLException;
+
+ /**
+ * Determines whether stored procedure calls using the stored procedure
+ * escape syntax is supported.
+ *
+ * @return {@code true} if stored procedure calls using the stored procedure
+ * escape syntax are supported, otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsStoredProcedures() throws SQLException;
+
+ /**
+ * Determines whether subqueries in comparison expressions are supported.
+ *
+ * @return {@code true} if subqueries are supported in comparison
+ * expressions.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSubqueriesInComparisons() throws SQLException;
+
+ /**
+ * Determines whether subqueries in {@code EXISTS} expressions are supported.
+ *
+ * @return {@code true} if subqueries are supported in {@code EXISTS}
+ * expressions, otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSubqueriesInExists() throws SQLException;
+
+ /**
+ * Determines whether subqueries in {@code IN} statements are supported.
+ *
+ * @return {@code true} if subqueries are supported in {@code IN} statements,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSubqueriesInIns() throws SQLException;
+
+ /**
+ * Determines whether subqueries in quantified expressions are supported.
+ *
+ * @return {@code true} if subqueries are supported, otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsSubqueriesInQuantifieds() throws SQLException;
+
+ /**
+ * Determines whether the database has table correlation names support.
+ *
+ * @return {@code true} if table correlation names are supported, otherwise
+ * {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsTableCorrelationNames() throws SQLException;
+
+ /**
+ * Determines whether a specified transaction isolation level is supported.
+ *
+ * @param level
+ * the transaction isolation level, as specified in {@code
+ * java.sql.Connection}: {@code TRANSACTION_NONE}, {@code
+ * TRANSACTION_READ_COMMITTED}, {@code
+ * TRANSACTION_READ_UNCOMMITTED}, {@code
+ * TRANSACTION_REPEATABLE_READ}, {@code TRANSACTION_SERIALIZABLE}
+ * @return {@code true} if the specific isolation level is supported,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsTransactionIsolationLevel(int level)
+ throws SQLException;
+
+ /**
+ * Determines whether transactions are supported.
+ *
+ * If transactions are not supported, then the {@code commit} method does
+ * nothing and the transaction isolation level is always {@code
+ * TRANSACTION_NONE}.
+ *
+ *
+ * @return {@code true} if transactions are supported, otherwise {@code
+ * false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsTransactions() throws SQLException;
+
+ /**
+ * Determines whether the {@code SQL UNION} operation is supported.
+ *
+ * @return {@code true} of the database does support {@code UNION}, otherwise
+ * {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsUnion() throws SQLException;
+
+ /**
+ * Determines whether the {@code SQL UNION ALL} operation is supported.
+ *
+ * @return {@code true} if the database does support {@code UNION ALL},
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean supportsUnionAll() throws SQLException;
+
+ /**
+ * Determines whether the method {@code ResultSet.rowUpdated} can detect a visible
+ * row update for the specified {@code ResultSet} type.
+ *
+ * @param type
+ * {@code ResultSet} type: {@code ResultSet.TYPE_FORWARD_ONLY},
+ * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or {@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ * @return {@code true} detecting changes is possible, otherwise {@code
+ * false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean updatesAreDetected(int type) throws SQLException;
+
+ /**
+ * Determines whether this database uses a file for each table.
+ *
+ * @return {@code true} if the database uses one file for each table,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean usesLocalFilePerTable() throws SQLException;
+
+ /**
+ * Determines whether this database uses a local file to store tables.
+ *
+ * @return {@code true} if the database stores tables in a local file,
+ * otherwise {@code false}.
+ * @throws SQLException
+ * a database error occurred.
+ * @since Android 1.0
+ */
+ public boolean usesLocalFiles() throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/Date.java b/sql/src/main/java/java/sql/Date.java
new file mode 100644
index 0000000..e506a43
--- /dev/null
+++ b/sql/src/main/java/java/sql/Date.java
@@ -0,0 +1,250 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.text.SimpleDateFormat;
+
+/**
+ * A class which can consume and produce dates in SQL {@code Date} format.
+ *
+ * Dates are represented in SQL as {@code yyyy-mm-dd}. Note that this date
+ * format only deals with year, month and day values. There are no values for
+ * hours, minutes, seconds.
+ *
+ * This is unlike the familiar {@code java.util.Date} object, which also includes
+ * values for hours, minutes, seconds, and milliseconds.
+ *
+ * Time points are handled as millisecond values - milliseconds since the Epoch,
+ * January 1st 1970, 00:00:00.000 GMT. Time values passed to the {@code
+ * java.sql.Date} class are "normalized" to the time 00:00:00.000 GMT on the
+ * date implied by the time value.
+ *
+ *
+ * @since Android 1.0
+ */
+public class Date extends java.util.Date {
+
+ private static final long serialVersionUID = 1511598038487230103L;
+
+ /**
+ * Constructs a {@code Date} object corresponding to the supplied year,
+ * month and day.
+ *
+ * @deprecated Please use the constructor {@link #Date(long)}.
+ * @param theYear
+ * the year, specified as the year minus 1900. Must be in the
+ * range {@code [0,8099]}.
+ * @param theMonth
+ * the month, specified as a number with 0 = January. Must be in
+ * the range {@code [0,11]}.
+ * @param theDay
+ * the day in the month. Must be in the range {@code [1,31]}.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ public Date(int theYear, int theMonth, int theDay) {
+ super(theYear, theMonth, theDay);
+ }
+
+ /**
+ * Creates a date which corresponds to the day determined by the supplied
+ * milliseconds time value {@code theDate}.
+ *
+ * @param theDate
+ * a time value in milliseconds since the epoch - January 1 1970
+ * 00:00:00 GMT. The time value (hours, minutes, seconds,
+ * milliseconds) stored in the {@code Date} object is adjusted to
+ * correspond to 00:00:00 GMT on the day determined by the supplied
+ * time value.
+ * @since Android 1.0
+ */
+ public Date(long theDate) {
+ super(normalizeTime(theDate));
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL {@code
+ * Date} values do not have an hours component.
+ * @return does not return anything.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getHours() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL {@code
+ * Date} values do not have a minutes component.
+ * @return does not return anything.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getMinutes() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL {@code
+ * Date} values do not have a seconds component.
+ * @return does not return anything.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getSeconds() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL {@code
+ * Date} values do not have an hours component.
+ * @param theHours
+ * the number of hours to set.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setHours(int theHours) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL {@code
+ * Date} values do not have a minutes component.
+ * @param theMinutes
+ * the number of minutes to set.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setMinutes(int theMinutes) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL {@code
+ * Date} values do not have a seconds component.
+ * @param theSeconds
+ * the number of seconds to set.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setSeconds(int theSeconds) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Sets this date to a date supplied as a milliseconds value. The date is
+ * set based on the supplied time value and rounded to zero GMT for that day.
+ *
+ * @param theTime
+ * the time in milliseconds since the Epoch.
+ * @since Android 1.0
+ */
+ @Override
+ public void setTime(long theTime) {
+ /*
+ * Store the Date based on the supplied time after removing any time
+ * elements finer than the day based on zero GMT
+ */
+ super.setTime(normalizeTime(theTime));
+ }
+
+ /**
+ * Produces a string representation of the date in SQL format
+ *
+ * @return a string representation of the date in SQL format - {@code
+ * "yyyy-mm-dd"}.
+ * @since Android 1.0
+ */
+ @Override
+ public String toString() {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
+ return dateFormat.format(this);
+ }
+
+ /**
+ * Creates a {@code Date} from a string representation of a date in SQL
+ * format.
+ *
+ * @param dateString
+ * the string representation of a date in SQL format - " {@code
+ * yyyy-mm-dd}".
+ * @return the {@code Date} object.
+ * @throws IllegalArgumentException
+ * if the format of the supplied string does not match the SQL
+ * format.
+ * @since Android 1.0
+ */
+ public static Date valueOf(String dateString) {
+ if (dateString == null) {
+ throw new IllegalArgumentException();
+ }
+ int firstIndex = dateString.indexOf('-');
+ int secondIndex = dateString.indexOf('-', firstIndex + 1);
+ // secondIndex == -1 means none or only one separator '-' has been
+ // found.
+ // The string is separated into three parts by two separator characters,
+ // if the first or the third part is null string, we should throw
+ // IllegalArgumentException to follow RI
+ if (secondIndex == -1 || firstIndex == 0
+ || secondIndex + 1 == dateString.length()) {
+ throw new IllegalArgumentException();
+ }
+ // parse each part of the string
+ int year = Integer.parseInt(dateString.substring(0, firstIndex));
+ int month = Integer.parseInt(dateString.substring(firstIndex + 1,
+ secondIndex));
+ int day = Integer.parseInt(dateString.substring(secondIndex + 1,
+ dateString.length()));
+ return new Date(year - 1900, month - 1, day);
+ }
+
+ /*
+ * Private method which normalizes a Time value, removing all low
+ * significance digits corresponding to milliseconds, seconds, minutes and
+ * hours, so that the returned Time value corresponds to 00:00:00 GMT on a
+ * particular day.
+ */
+ private static long normalizeTime(long theTime) {
+ return theTime;
+ }
+}
diff --git a/sql/src/main/java/java/sql/Driver.java b/sql/src/main/java/java/sql/Driver.java
new file mode 100644
index 0000000..c0499cb
--- /dev/null
+++ b/sql/src/main/java/java/sql/Driver.java
@@ -0,0 +1,136 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.util.Properties;
+
+/**
+ * An interface to a JDBC driver.
+ *
+ * The JDBC driver uses URLs to specify the location of specific data. URL
+ * format typically takes the form " {@code xxxx:yyyy:SpecificData}", where "
+ * {@code xxxx:yyyy}" is referred to as the subprotocol and is normally
+ * the same for all of a particular driver. " {@code SpecificData}" is a string
+ * which identifies the particular data source that the driver should use.
+ *
+ *
+ * A driver needs to be registered with a {@link DriverManager}. It is
+ * registered and instantiated by calling {@code Class.forName("DriverURL")}
+ * with the URL string as argument.
+ *
+ * @see DriverManager
+ *
+ * @since Android 1.0
+ */
+public interface Driver {
+
+ /**
+ * Returns whether the driver thinks that it can open a connection to the
+ * given URL.
+ *
+ * @param url
+ * the URL to connect to.
+ * @return {@code true} if the driver thinks that is can open a connection
+ * to the supplied URL, {@code false} otherwise. Typically, the
+ * driver will respond {@code true} if it thinks that it can handle
+ * the subprotocol specified by the driver.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public boolean acceptsURL(String url) throws SQLException;
+
+ /**
+ * Attempts to make a database connection to a data source specified by a
+ * supplied URL.
+ *
+ * @param url
+ * the URL to connect.
+ * @param info
+ * some properties that should be used in establishing the
+ * connection. The properties consist of name/value pairs of
+ * strings. Normally, a connection to a database requires at
+ * least two properties - for {@code "user"} and {@code
+ * "password"} in order to pass authentication to the database.
+ * @return the connection to the database.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Connection connect(String url, Properties info) throws SQLException;
+
+ /**
+ * Gets the driver's major version number.
+ *
+ * @return the major version number of the driver - typically starts at 1.
+ * @since Android 1.0
+ */
+ public int getMajorVersion();
+
+ /**
+ * Gets the driver's minor version number.
+ *
+ * @return the minor version number of the driver - typically starts at 0.
+ * @since Android 1.0
+ */
+ public int getMinorVersion();
+
+ /**
+ * Gets information about possible properties for this driver.
+ *
+ * This method is intended to provide a listing of possible properties that
+ * the client of the driver must supply in order to establish a connection
+ * to a database. Note that the returned array of properties may change
+ * depending on the supplied list of property values.
+ *
+ *
+ * @param url
+ * the URL of the database. An application may call this method
+ * iteratively as the property list is built up - for example,
+ * when displaying a dialog to an end-user as part of the
+ * database login process.
+ * @param info
+ * a set of tag/value pairs giving data that a user may be
+ * prompted to provide in order to connect to the database.
+ * @return an array of {@code DriverPropertyInfo} records which provide
+ * details on which additional properties are required (in addition
+ * to those supplied in the {@code info} parameter) in order to
+ * connect to the database.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
+ throws SQLException;
+
+ /**
+ * Reports whether this driver is a genuine JDBC CompliantTM driver. The
+ * driver may only return {@code true} if it passes all the JDBC compliance
+ * tests.
+ *
+ * A driver may not be fully compliant if the underlying database has
+ * limited functionality.
+ *
+ *
+ * @return {@code true} if the driver is fully JDBC compliant, {@code false}
+ * otherwise.
+ * @since Android 1.0
+ */
+ public boolean jdbcCompliant();
+
+}
diff --git a/sql/src/main/java/java/sql/DriverManager.java b/sql/src/main/java/java/sql/DriverManager.java
new file mode 100644
index 0000000..afcf2f5
--- /dev/null
+++ b/sql/src/main/java/java/sql/DriverManager.java
@@ -0,0 +1,463 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.util.Properties;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Set;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.util.HashSet;
+import java.util.Vector;
+import org.apache.harmony.sql.internal.nls.Messages;
+// BEGIN android-changed
+import dalvik.system.VMStack;
+// END android-changed
+
+/**
+ * Provides facilities for managing JDBC drivers.
+ *
+ * The {@code DriverManager} class loads JDBC drivers during its initialization,
+ * from the list of drivers referenced by the system property {@code
+ * "jdbc.drivers"}.
+ *
+ *
+ * @since Android 1.0
+ */
+public class DriverManager {
+
+ /*
+ * Facilities for logging. The Print Stream is deprecated but is maintained
+ * here for compatibility.
+ */
+ private static PrintStream thePrintStream;
+
+ private static PrintWriter thePrintWriter;
+
+ // Login timeout value - by default set to 0 -> "wait forever"
+ private static int loginTimeout = 0;
+
+ /*
+ * Set to hold Registered Drivers - initial capacity 10 drivers (will expand
+ * automatically if necessary.
+ */
+ private static final Set theDriverSet = new HashSet(10);
+
+ // Permission for setting log
+ private static final SQLPermission logPermission = new SQLPermission("setLog"); //$NON-NLS-1$
+
+ /*
+ * Load drivers on initialization
+ */
+ static {
+ loadInitialDrivers();
+ }
+
+ /*
+ * Loads the set of JDBC drivers defined by the Property "jdbc.drivers" if
+ * it is defined.
+ */
+ private static void loadInitialDrivers() {
+ String theDriverList = System.getProperty("jdbc.drivers", null); //$NON-NLS-1$
+ if (theDriverList == null) {
+ return;
+ }
+
+ /*
+ * Get the names of the drivers as an array of Strings from the system
+ * property by splitting the property at the separator character ':'
+ */
+ String[] theDriverNames = theDriverList.split(":"); //$NON-NLS-1$
+
+ for (String element : theDriverNames) {
+ try {
+ // Load the driver class
+ Class
+ .forName(element, true, ClassLoader
+ .getSystemClassLoader());
+ } catch (Throwable t) {
+ // Ignored
+ }
+ }
+ }
+
+ /*
+ * A private constructor to prevent allocation
+ */
+ private DriverManager() {
+ super();
+ }
+
+ /**
+ * Removes a driver from the {@code DriverManager}'s registered driver list.
+ * This will only succeed when the caller's class loader loaded the driver
+ * that is to be removed. If the driver was loaded by a different class
+ * loader, the removal of the driver fails silently.
+ *
+ * If the removal succeeds, the {@code DriverManager} will not use this
+ * driver in the future when asked to get a {@code Connection}.
+ *
+ *
+ * @param driver
+ * the JDBC driver to remove.
+ * @throws SQLException
+ * if there is a problem interfering with accessing the
+ * database.
+ * @since Android 1.0
+ */
+ public static void deregisterDriver(Driver driver) throws SQLException {
+ if (driver == null) {
+ return;
+ }
+ // BEGIN android-changed
+ ClassLoader callerClassLoader = VMStack.getCallingClassLoader();
+ // END android-changed
+
+ if (!DriverManager.isClassFromClassLoader(driver, callerClassLoader)) {
+ // sql.1=DriverManager: calling class not authorized to deregister JDBC driver
+ throw new SecurityException(Messages.getString("sql.1")); //$NON-NLS-1$
+ } // end if
+ synchronized (theDriverSet) {
+ theDriverSet.remove(driver);
+ }
+ }
+
+ /**
+ * Attempts to establish a connection to the given database URL.
+ *
+ * @param url
+ * a URL string representing the database target to connect with.
+ * @return a {@code Connection} to the database identified by the URL.
+ * {@code null} if no connection can be established.
+ * @throws SQLException
+ * if there is an error while attempting to connect to the
+ * database identified by the URL.
+ * @since Android 1.0
+ */
+ public static Connection getConnection(String url) throws SQLException {
+ return getConnection(url, new Properties());
+ }
+
+ /**
+ * Attempts to establish a connection to the given database URL.
+ *
+ * @param url
+ * a URL string representing the database target to connect with
+ * @param info
+ * a set of properties to use as arguments to set up the
+ * connection. Properties are arbitrary string/value pairs.
+ * Normally, at least the properties {@code "user"} and {@code
+ * "password"} should be passed, with appropriate settings for
+ * the user ID and its corresponding password to get access to
+ * the corresponding database.
+ * @return a {@code Connection} to the database identified by the URL.
+ * {@code null} if no connection can be established.
+ * @throws SQLException
+ * if there is an error while attempting to connect to the
+ * database identified by the URL.
+ * @since Android 1.0
+ */
+ public static Connection getConnection(String url, Properties info)
+ throws SQLException {
+ // 08 - connection exception
+ // 001 - SQL-client unable to establish SQL-connection
+ String sqlState = "08001"; //$NON-NLS-1$
+ if (url == null) {
+ // sql.5=The url cannot be null
+ throw new SQLException(Messages.getString("sql.5"), sqlState); //$NON-NLS-1$
+ }
+ synchronized (theDriverSet) {
+ /*
+ * Loop over the drivers in the DriverSet checking to see if one can
+ * open a connection to the supplied URL - return the first
+ * connection which is returned
+ */
+ for (Driver theDriver : theDriverSet) {
+ Connection theConnection = theDriver.connect(url, info);
+ if (theConnection != null) {
+ return theConnection;
+ }
+ }
+ }
+ // If we get here, none of the drivers are able to resolve the URL
+ // sql.6=No suitable driver
+ throw new SQLException(Messages.getString("sql.6"), sqlState); //$NON-NLS-1$
+ }
+
+ /**
+ * Attempts to establish a connection to the given database URL.
+ *
+ * @param url
+ * a URL string representing the database target to connect with.
+ * @param user
+ * a user ID used to login to the database.
+ * @param password
+ * a password for the user ID to login to the database.
+ * @return a {@code Connection} to the database identified by the URL.
+ * {@code null} if no connection can be established.
+ * @throws SQLException
+ * if there is an error while attempting to connect to the
+ * database identified by the URL.
+ * @since Android 1.0
+ */
+ public static Connection getConnection(String url, String user,
+ String password) throws SQLException {
+ Properties theProperties = new Properties();
+ if(null != user){
+ theProperties.setProperty("user", user); //$NON-NLS-1$
+ }
+ if(null != password){
+ theProperties.setProperty("password", password); //$NON-NLS-1$
+ }
+ return getConnection(url, theProperties);
+ }
+
+ /**
+ * Tries to find a driver that can interpret the supplied URL.
+ *
+ * @param url
+ * the URL of a database.
+ * @return a {@code Driver} that matches the provided URL. {@code null} if
+ * no {@code Driver} understands the URL
+ * @throws SQLException
+ * if there is any kind of problem accessing the database.
+ */
+ public static Driver getDriver(String url) throws SQLException {
+ // BEGIN android-changed
+ ClassLoader callerClassLoader = VMStack.getCallingClassLoader();
+ // END android-changed
+
+ synchronized (theDriverSet) {
+ /*
+ * Loop over the drivers in the DriverSet checking to see if one
+ * does understand the supplied URL - return the first driver which
+ * does understand the URL
+ */
+ Iterator theIterator = theDriverSet.iterator();
+ while (theIterator.hasNext()) {
+ Driver theDriver = theIterator.next();
+ if (theDriver.acceptsURL(url)
+ && DriverManager.isClassFromClassLoader(theDriver,
+ callerClassLoader)) {
+ return theDriver;
+ }
+ }
+ }
+ // If no drivers understand the URL, throw an SQLException
+ // sql.6=No suitable driver
+ //SQLState: 08 - connection exception
+ //001 - SQL-client unable to establish SQL-connection
+ throw new SQLException(Messages.getString("sql.6"), "08001"); //$NON-NLS-1$ //$NON-NLS-2$
+ }
+
+ /**
+ * Returns an {@code Enumeration} that contains all of the loaded JDBC
+ * drivers that the current caller can access.
+ *
+ * @return An {@code Enumeration} containing all the currently loaded JDBC
+ * {@code Drivers}.
+ * @since Android 1.0
+ */
+ public static Enumeration getDrivers() {
+ // BEGIN android-changed
+ ClassLoader callerClassLoader = VMStack.getCallingClassLoader();
+ // END android-changed
+ /*
+ * Synchronize to avoid clashes with additions and removals of drivers
+ * in the DriverSet
+ */
+ synchronized (theDriverSet) {
+ /*
+ * Create the Enumeration by building a Vector from the elements of
+ * the DriverSet
+ */
+ Vector theVector = new Vector();
+ Iterator theIterator = theDriverSet.iterator();
+ while (theIterator.hasNext()) {
+ Driver theDriver = theIterator.next();
+ if (DriverManager.isClassFromClassLoader(theDriver,
+ callerClassLoader)) {
+ theVector.add(theDriver);
+ }
+ }
+ return theVector.elements();
+ }
+ }
+
+ /**
+ * Returns the login timeout when connecting to a database in seconds.
+ *
+ * @return the login timeout in seconds.
+ * @since Android 1.0
+ */
+ public static int getLoginTimeout() {
+ return loginTimeout;
+ }
+
+ /**
+ * Gets the log {@code PrintStream} used by the {@code DriverManager} and
+ * all the JDBC Drivers.
+ *
+ * @deprecated use {@link #getLogWriter()} instead.
+ * @return the {@code PrintStream} used for logging activities.
+ * @since Android 1.0
+ */
+ @Deprecated
+ public static PrintStream getLogStream() {
+ return thePrintStream;
+ }
+
+ /**
+ * Retrieves the log writer.
+ *
+ * @return A {@code PrintWriter} object used as the log writer. {@code null}
+ * if no log writer is set.
+ * @since Android 1.0
+ */
+ public static PrintWriter getLogWriter() {
+ return thePrintWriter;
+ }
+
+ /**
+ * Prints a message to the current JDBC log stream. This is either the
+ * {@code PrintWriter} or (deprecated) the {@code PrintStream}, if set.
+ *
+ * @param message
+ * the message to print to the JDBC log stream.
+ * @since Android 1.0
+ */
+ public static void println(String message) {
+ if (thePrintWriter != null) {
+ thePrintWriter.println(message);
+ thePrintWriter.flush();
+ } else if (thePrintStream != null) {
+ thePrintStream.println(message);
+ thePrintStream.flush();
+ }
+ /*
+ * If neither the PrintWriter not the PrintStream are set, then silently
+ * do nothing the message is not recorded and no exception is generated.
+ */
+ return;
+ }
+
+ /**
+ * Registers a given JDBC driver with the {@code DriverManager}.
+ *
+ * A newly loaded JDBC driver class should register itself with the
+ * {@code DriverManager} by calling this method.
+ *
+ *
+ * @param driver
+ * the {@code Driver} to register with the {@code DriverManager}.
+ * @throws SQLException
+ * if a database access error occurs.
+ */
+ public static void registerDriver(Driver driver) throws SQLException {
+ if (driver == null) {
+ throw new NullPointerException();
+ }
+ synchronized (theDriverSet) {
+ theDriverSet.add(driver);
+ }
+ }
+
+ /**
+ * Sets the login timeout when connecting to a database in seconds.
+ *
+ * @param seconds
+ * seconds until timeout. 0 indicates wait forever.
+ * @since Android 1.0
+ */
+ public static void setLoginTimeout(int seconds) {
+ loginTimeout = seconds;
+ return;
+ }
+
+ /**
+ * Sets the print stream to use for logging data from the {@code
+ * DriverManager} and the JDBC drivers.
+ *
+ * @deprecated Use {@link #setLogWriter} instead.
+ * @param out
+ * the {@code PrintStream} to use for logging.
+ * @since Android 1.0
+ */
+ @Deprecated
+ public static void setLogStream(PrintStream out) {
+ checkLogSecurity();
+ thePrintStream = out;
+ }
+
+ /**
+ * Sets the {@code PrintWriter} that is used by all loaded drivers, and also
+ * the {@code DriverManager}.
+ *
+ * @param out
+ * the {@code PrintWriter} to be used.
+ * @since Android 1.0
+ */
+ public static void setLogWriter(PrintWriter out) {
+ checkLogSecurity();
+ thePrintWriter = out;
+ }
+
+ /*
+ * Method which checks to see if setting a logging stream is allowed by the
+ * Security manager
+ */
+ private static void checkLogSecurity() {
+ SecurityManager securityManager = System.getSecurityManager();
+ if (securityManager != null) {
+ // Throws a SecurityException if setting the log is not permitted
+ securityManager.checkPermission(logPermission);
+ }
+ }
+
+ /**
+ * Determines whether the supplied object was loaded by the given {@code ClassLoader}.
+ *
+ * @param theObject
+ * the object to check.
+ * @param theClassLoader
+ * the {@code ClassLoader}.
+ * @return {@code true} if the Object does belong to the {@code ClassLoader}
+ * , {@code false} otherwise
+ */
+ private static boolean isClassFromClassLoader(Object theObject,
+ ClassLoader theClassLoader) {
+
+ if ((theObject == null) || (theClassLoader == null)) {
+ return false;
+ }
+
+ Class> objectClass = theObject.getClass();
+
+ try {
+ Class> checkClass = Class.forName(objectClass.getName(), true,
+ theClassLoader);
+ if (checkClass == objectClass) {
+ return true;
+ }
+ } catch (Throwable t) {
+ // Empty
+ }
+ return false;
+ }
+}
diff --git a/sql/src/main/java/java/sql/DriverPropertyInfo.java b/sql/src/main/java/java/sql/DriverPropertyInfo.java
new file mode 100644
index 0000000..3875abb
--- /dev/null
+++ b/sql/src/main/java/java/sql/DriverPropertyInfo.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+/**
+ * A class holding information about driver properties of a database connection.
+ * This class is returned by the
+ * {@link Driver#getPropertyInfo(String, java.util.Properties)} method and
+ * allows for the advanced connection handling.
+ *
+ * @since Android 1.0
+ */
+public class DriverPropertyInfo {
+
+ /**
+ * If the value member can be chosen from a set of possible values, they are
+ * contained here. Otherwise choices is {@code null}.
+ *
+ * @since Android 1.0
+ */
+ public String[] choices;
+
+ /**
+ * A description of the property. May be {@code null}.
+ *
+ * @since Android 1.0
+ */
+ public String description;
+
+ /**
+ * The name of the property.
+ *
+ * @since Android 1.0
+ */
+ public String name;
+
+ /**
+ * {@code True} when the value member must be provided during {@code
+ * Driver.connect}. {@code False} otherwise.
+ *
+ * @since Android 1.0
+ */
+ public boolean required;
+
+ /**
+ * The current value associated with this property. It is depending on the
+ * data gathered by the {@code getPropertyInfo} method, the general Java
+ * environment and the driver's default values.
+ *
+ * @since Android 1.0
+ */
+ public String value;
+
+ /**
+ * Creates a {@code DriverPropertyInfo} instance with the supplied name and
+ * value. Other class members take their default values.
+ *
+ * @param name
+ * The property name.
+ * @param value
+ * The property value.
+ * @since Android 1.0
+ */
+ public DriverPropertyInfo(String name, String value) {
+ this.name = name;
+ this.value = value;
+ this.choices = null;
+ this.description = null;
+ this.required = false;
+ }
+}
diff --git a/sql/src/main/java/java/sql/ParameterMetaData.java b/sql/src/main/java/java/sql/ParameterMetaData.java
new file mode 100644
index 0000000..94901ae
--- /dev/null
+++ b/sql/src/main/java/java/sql/ParameterMetaData.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+/**
+ * An interface used to get information about the types and properties of
+ * parameters in a {@code PreparedStatement}.
+ *
+ * @since Android 1.0
+ */
+public interface ParameterMetaData {
+
+ /**
+ * Indicates that the parameter mode is {@code IN}.
+ *
+ * @since Android 1.0
+ */
+ public static final int parameterModeIn = 1;
+
+ /**
+ * Indicates that the parameter mode is {@code INOUT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int parameterModeInOut = 2;
+
+ /**
+ * Indicates that the parameter mode is {@code OUT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int parameterModeOut = 4;
+
+ /**
+ * Indicates that the parameter mode is not known.
+ *
+ * @since Android 1.0
+ */
+ public static final int parameterModeUnknown = 0;
+
+ /**
+ * Indicates that a parameter is not permitted to be {@code NULL}.
+ *
+ * @since Android 1.0
+ */
+ public static final int parameterNoNulls = 0;
+
+ /**
+ * Indicates that a parameter is permitted to be {@code NULL}.
+ *
+ * @since Android 1.0
+ */
+ public static final int parameterNullable = 1;
+
+ /**
+ * Indicates that whether a parameter is allowed to be {@code null} or not
+ * is not known.
+ *
+ * @since Android 1.0
+ */
+ public static final int parameterNullableUnknown = 2;
+
+ /**
+ * Gets the fully-qualified name of the Java class which should be passed as
+ * a parameter to the method {@code PreparedStatement.setObject}.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has index 1.
+ * @return the fully qualified Java class name of the parameter with the
+ * specified index. This class name is used for custom mapping
+ * between SQL types and Java objects.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public String getParameterClassName(int paramIndex) throws SQLException;
+
+ /**
+ * Gets the number of parameters in the {@code PreparedStatement} for which
+ * this {@code ParameterMetaData} contains information.
+ *
+ * @return the number of parameters.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getParameterCount() throws SQLException;
+
+ /**
+ * Gets the mode of the specified parameter. Can be one of:
+ *
+ *
ParameterMetaData.parameterModeIn
+ *
ParameterMetaData.parameterModeOut
+ *
ParameterMetaData.parameterModeInOut
+ *
ParameterMetaData.parameterModeUnknown
+ *
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has index 1.
+ * @return the parameter's mode.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getParameterMode(int paramIndex) throws SQLException;
+
+ /**
+ * Gets the SQL type of a specified parameter.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has index 1.
+ * @return the SQL type of the parameter as defined in {@code
+ * java.sql.Types}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getParameterType(int paramIndex) throws SQLException;
+
+ /**
+ * Gets the database-specific type name of a specified parameter.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has index 1.
+ * @return the type name for the parameter as used by the database. A
+ * fully-qualified name is returned if the parameter is a User
+ * Defined Type (UDT).
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public String getParameterTypeName(int paramIndex) throws SQLException;
+
+ /**
+ * Gets the number of decimal digits for a specified parameter.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has index 1.
+ * @return the number of decimal digits ("the precision") for the parameter.
+ * {@code 0} if the parameter is not a numeric type.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getPrecision(int paramIndex) throws SQLException;
+
+ /**
+ * Gets the number of digits after the decimal point for a specified
+ * parameter.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has index 1.
+ * @return the number of digits after the decimal point ("the scale") for
+ * the parameter. {@code 0} if the parameter is not a numeric type.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getScale(int paramIndex) throws SQLException;
+
+ /**
+ * Gets whether {@code null} values are allowed for the specified parameter.
+ * The returned value is one of:
+ *
+ *
ParameterMetaData.parameterNoNulls
+ *
ParameterMetaData.parameterNullable
+ *
ParameterMetaData.parameterNullableUnknown
+ *
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has index 1.
+ * @return the int code indicating the nullability of the parameter.
+ * @throws SQLException
+ * if a database error is encountered.
+ * @since Android 1.0
+ */
+ public int isNullable(int paramIndex) throws SQLException;
+
+ /**
+ * Gets whether values for the specified parameter can be signed numbers.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has index 1.
+ * @return {@code true} if values can be signed numbers for this parameter,
+ * {@code false} otherwise.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean isSigned(int paramIndex) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/PreparedStatement.java b/sql/src/main/java/java/sql/PreparedStatement.java
new file mode 100644
index 0000000..ab81871
--- /dev/null
+++ b/sql/src/main/java/java/sql/PreparedStatement.java
@@ -0,0 +1,742 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.util.Calendar;
+import java.net.URL;
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+
+/**
+ * An interface for a precompiled SQL Statement.
+ *
+ * An SQL Statement is put into a {@code PreparedStatement} and is precompiled
+ * so that it can be executed efficiently multiple times.
+ *
+ *
+ * Setter methods are supplied in the {@code PreparedStatement} interface for
+ * the setting of {@code IN} parameters for the statement. The setter method
+ * used for each {@code IN} parameter must match the parameter's type.
+ *
+ *
+ * @since Android 1.0
+ */
+public interface PreparedStatement extends Statement {
+
+ /**
+ * Add a set of parameters to the {@code PreparedStatement}'s command batch.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void addBatch() throws SQLException;
+
+ /**
+ * Clear the current parameter values.
+ *
+ * Typically, parameter values are retained for multiple executions of the
+ * {@code Statement}. Setting a parameter value replaces the previous value. This
+ * method clears the values for all parameters, releasing all resources used
+ * by those parameters.
+ *
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void clearParameters() throws SQLException;
+
+ /**
+ * Executes the SQL statement in this {@code PreparedStatement}.
+ *
+ * A {@code PreparedStatement} may return multiple results. The execute
+ * method executes the {@code PreparedStatement} and returns a flag
+ * indicating the kind of result produced by the action. The methods
+ * {@code getResultSet} or {@code getUpdateCount} are used to retrieve
+ * the first result, and the second and subsequent results are
+ * retrieved with {@code getMoreResults}.
+ *
+ *
+ * @return {@code true} if the result of the execution is a {@code
+ * ResultSet}, {@code false} if there is no result or if the result
+ * is an update count.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean execute() throws SQLException;
+
+ /**
+ * Executes the SQL query in the {@code PreparedStatement} and returns the
+ * {@code ResultSet} generated by the query.
+ *
+ * @return the {@code ResultSet} generated by the query, never {@code null}.
+ * @throws SQLException
+ * if a database error happens or if the SQL statement does not
+ * produce a {@code ResultSet}.
+ * @since Android 1.0
+ */
+ public ResultSet executeQuery() throws SQLException;
+
+ /**
+ * Invokes the SQL command contained within the prepared statement. This
+ * must be {@code INSERT}, {@code UPDATE}, {@code DELETE}, or a command that
+ * returns nothing.
+ *
+ * @return the number of affected rows for {@code INSERT}, {@code UPDATE} or {@code
+ * DELETE} statements, {@code 0} for statements that return nothing.
+ * @throws SQLException
+ * if a database error happens or if the SQL statement returns a
+ * {@code ResultSet}.
+ * @since Android 1.0
+ */
+ public int executeUpdate() throws SQLException;
+
+ /**
+ * Returns a {@code ResultSetMetaData} describing the {@code
+ * ResultSet} that would be produced by execution of the {@code PreparedStatement}.
+ *
+ * It is possible to know the metadata for the {@code ResultSet} without
+ * executing the {@code PreparedStatement}, because the {@code
+ * PreparedStatement} is precompiled. As a result the metadata can be
+ * queried ahead of time without actually executing the statement.
+ *
+ *
+ * @return a {@code ResultSetMetaData} object with the information about the
+ * columns of the {@code ResultSet}, if the driver can return a
+ * {@code ResultSetMetaData}. {@code null} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public ResultSetMetaData getMetaData() throws SQLException;
+
+ /**
+ * Gets information about the parameters of the {@code PreparedStatement}.
+ *
+ * @return a {@code ParameterMetaData} object which holds information about
+ * the number, type, and properties of the parameters of this {@code
+ * PreparedStatement}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public ParameterMetaData getParameterMetaData() throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the supplied {@code Array}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theArray
+ * a {@code java.sql.Array} giving the new value of the parameter at {@code
+ * parameterIndex}.
+ * @throws SQLException
+ * if a database error happens.
+ * @see Array
+ * @since Android 1.0
+ */
+ public void setArray(int parameterIndex, Array theArray)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the content of a supplied
+ * {@code InputStream}, which has a specified number of bytes.
+ *
+ * This is a good method for setting an SQL {@code LONVARCHAR} parameter
+ * where the length of the data is large. Data is read from the {@code
+ * InputStream} until end-of-file is reached or the specified number of
+ * bytes is copied.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theInputStream
+ * the ASCII {@code InputStream} carrying the data to which the
+ * parameter at {@code parameterIndex} is set.
+ * @param length
+ * the number of bytes in the {@code InputStream} to copy to the
+ * parameter.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setAsciiStream(int parameterIndex, InputStream theInputStream,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.math.BigDecimal} value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theBigDecimal
+ * the value to which the parameter at {@code parameterIndex} is
+ * set.
+ * @throws SQLException
+ * if a database error happens.
+ * @see java.math.BigDecimal
+ * @since Android 1.0
+ */
+ public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the content of a supplied
+ * binary {@code InputStream}, which has a specified number of bytes.
+ *
+ * Use this method when a large amount of data needs to be set into a
+ * {@code LONGVARBINARY} parameter.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theInputStream
+ * the binary {@code InputStream} carrying the data to update the
+ * parameter.
+ * @param length
+ * the number of bytes in the {@code InputStream} to copy to the
+ * parameter.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setBinaryStream(int parameterIndex, InputStream theInputStream,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the given {@code Blob} object.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theBlob
+ * the {@code java.sql.Blob} to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ * @see Blob
+ */
+ public void setBlob(int parameterIndex, Blob theBlob) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code boolean}
+ * value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theBoolean
+ * the boolean value to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setBoolean(int parameterIndex, boolean theBoolean)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code byte} value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theByte
+ * the byte value to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setByte(int parameterIndex, byte theByte) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied array of bytes. The
+ * array is mapped to a {@code VARBINARY} or {@code LONGVARBINARY} in the
+ * database.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theBytes
+ * the array of bytes to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setBytes(int parameterIndex, byte[] theBytes)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the character content of a
+ * {@code Reader} object, with the specified length of character data.
+ *
+ * Data is read from the {@code
+ * Reader} until end-of-file is reached or the specified number of
+ * characters are copied.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param reader
+ * the {@code java.io.Reader} containing the character data.
+ * @param length
+ * the number of characters to be read.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setCharacterStream(int parameterIndex, Reader reader, int length)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the given {@code Clob} object.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theClob
+ * a {@code java.sql.Clob} holding the data to which the
+ * parameter at {@code parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setClob(int parameterIndex, Clob theClob) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Date} value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theDate
+ * a {@code java.sql.Date} to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setDate(int parameterIndex, Date theDate) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Date} value, using a supplied {@code Calendar} to map the Date.
+ * The {@code Calendar} allows the application to control the timezone used
+ * to compute the SQL {@code DATE} in the database - without the supplied
+ * {@code Calendar}, the driver uses the default timezone of the Java
+ * virtual machine.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theDate
+ * a {@code java.sql.Date} to which the parameter at {@code
+ * parameterIndex} is set.
+ * @param cal
+ * a {@code Calendar} to use to construct the SQL {@code DATE}
+ * value.
+ * @throws SQLException
+ * if a database error happens.
+ * @see Date
+ * @see java.util.Calendar
+ * @since Android 1.0
+ */
+ public void setDate(int parameterIndex, Date theDate, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code double}
+ * value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theDouble
+ * the {@code double} value to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setDouble(int parameterIndex, double theDouble)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to to a supplied {@code float}
+ * value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theFloat
+ * the {@code float} value to update the parameter.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setFloat(int parameterIndex, float theFloat)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code int} value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theInt
+ * the {@code int} value to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setInt(int parameterIndex, int theInt) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code long} value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theLong
+ * the {@code long} value to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setLong(int parameterIndex, long theLong) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to SQL {@code NULL}. Don't use
+ * this version of {@code setNull} for User Defined Types (UDT) or
+ * for REF type parameters.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param sqlType
+ * the SQL type of the parameter, as defined in {@code
+ * java.sql.Types}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setNull(int parameterIndex, int sqlType) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to SQL {@code NULL}. This version
+ * of {@code setNull} should be used for User Defined Types (UDTs)
+ * and also REF types. UDTs can be {@code STRUCT}, {@code DISTINCT}, {@code
+ * JAVA_OBJECT} and named array types.
+ *
+ * Applications must provide the SQL type code and also a fully qualified
+ * SQL type name when supplying a {@code NULL} UDT or REF. For a UDT, the
+ * type name is the type name of the parameter itself, but for a REF
+ * parameter the type name is the type name of the referenced type.
+ *
+ *
+ * @param paramIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param sqlType
+ * the SQL type of the parameter, as defined in {@code
+ * java.sql.Types}.
+ * @param typeName
+ * the fully qualified name of a UDT or REF type - ignored if the
+ * parameter is not a UDT.
+ * @throws SQLException
+ * if a database error happens.
+ * @see Types
+ * @since Android 1.0
+ */
+ public void setNull(int paramIndex, int sqlType, String typeName)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ *
+ * There is a standard mapping from Java types to SQL types, defined in the
+ * JDBC specification. The passed object is then transformed into the
+ * appropriate SQL type, and then transferred to the database. {@code
+ * setObject} can be used to pass abstract data types unique to the
+ * database, by using a JDBC driver specific Java type. If the object's
+ * class implements the interface {@code SQLData}, the JDBC driver calls
+ * {@code SQLData.writeSQL} to write it to the SQL data stream. If the
+ * object's class implements {@code Ref}, {@code Blob}, {@code Clob},
+ * {@code Struct}, or {@code Array}, the driver passes it to the database as
+ * a value of the corresponding SQL type.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theObject
+ * the object containing the value to which the parameter at
+ * {@code parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setObject(int parameterIndex, Object theObject)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ *
+ * The object is converted to the given {@code targetSqlType} before it is
+ * sent to the database. If the object has a custom mapping (its class
+ * implements the interface {@code SQLData}), the JDBC driver will call the method
+ * {@code SQLData.writeSQL} to write it to the SQL data stream. If the
+ * object's class implements {@code Ref}, {@code Blob}, {@code Clob},
+ * {@code Struct}, or {@code Array}, the driver will pass it to the database
+ * in the form of the relevant SQL type.
+ *
+ *
+ * @param parameterIndex
+ * the parameter index, where the first parameter has index 1.
+ * @param theObject
+ * the Object containing the value to which the parameter at
+ * {@code parameterIndex} is set.
+ * @param targetSqlType
+ * the SQL type to send to the database, as defined in {@code
+ * java.sql.Types}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setObject(int parameterIndex, Object theObject,
+ int targetSqlType) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ *
+ * The object is converted to the given {@code targetSqlType} before it is
+ * sent to the database. If the object has a custom mapping (its class
+ * implements the interface {@code SQLData}), the JDBC driver will call the method
+ * {@code SQLData.writeSQL} to write it to the SQL data stream. If the
+ * object's class implements {@code Ref}, {@code Blob}, {@code Clob},
+ * {@code Struct}, or {@code Array}, the driver will pass it to the database
+ * in the form of the relevant SQL type.
+ *
+ *
+ * @param parameterIndex
+ * the parameter index, where the first parameter has index 1.
+ * @param theObject
+ * the Object containing the value to which the parameter at
+ * {@code parameterIndex} is set.
+ * @param targetSqlType
+ * the SQL type to send to the database, as defined in {@code
+ * java.sql.Types}.
+ * @param scale
+ * the number of digits after the decimal point - only applies to
+ * the types {@code java.sql.Types.DECIMAL} and {@code
+ * java.sql.Types.NUMERIC} - ignored for all other types.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setObject(int parameterIndex, Object theObject,
+ int targetSqlType, int scale) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * REF()} value. This is stored as an SQL {@code REF}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theRef
+ * a {@code java.sql.Ref} value to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @see Ref
+ * @since Android 1.0
+ */
+ public void setRef(int parameterIndex, Ref theRef) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code short}
+ * value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theShort
+ * a {@code short} value to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setShort(int parameterIndex, short theShort)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied string.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theString
+ * the value to which the parameter at {@code parameterIndex} is
+ * set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setString(int parameterIndex, String theString)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Time} value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theTime
+ * a {@code java.sql.Time} value to which the parameter at
+ * {@code parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setTime(int parameterIndex, Time theTime) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Time} value, using a supplied {@code Calendar}.
+ *
+ * The driver uses the supplied {@code Calendar} to create the SQL {@code
+ * TIME} value, which allows it to use a custom timezone - otherwise the
+ * driver uses the default timezone of the Java virtual machine.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theTime
+ * a {@code java.sql.Time} value to which the parameter at
+ * {@code parameterIndex} is set.
+ * @param cal
+ * a {@code Calendar} to use to construct the SQL {@code TIME}
+ * value.
+ * @throws SQLException
+ * if a database error happens.
+ * @see Time
+ * @see java.util.Calendar
+ * @since Android 1.0
+ */
+ public void setTime(int parameterIndex, Time theTime, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied java.sql.Timestamp
+ * value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theTimestamp
+ * the java.sql.Timestamp value to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.sql.Timestamp} value, using the supplied {@code Calendar}.
+ *
+ * The driver uses the supplied {@code Calendar} to create the SQL {@code
+ * TIMESTAMP} value, which allows it to use a custom timezone - otherwise
+ * the driver uses the default timezone of the Java virtual machine.
+ *
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theTimestamp
+ * the {@code java.sql.Timestamp} value to which the parameter at
+ * {@code parameterIndex} is set.
+ * @param cal
+ * a {@code Calendar} to use to construct the SQL {@code
+ * TIMESTAMP} value
+ * @throws SQLException
+ * if a database error happens.
+ * @see Timestamp
+ * @see java.util.Calendar
+ * @since Android 1.0
+ */
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp,
+ Calendar cal) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the characters from a supplied
+ * {@code InputStream}, with a specified number of bytes.
+ *
+ * @deprecated Use {@link #setCharacterStream(int, Reader, int)}
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theInputStream
+ * the {@code InputStream} with the character data to which the
+ * parameter at {@code parameterIndex} is set.
+ * @param length
+ * the number of bytes to read from the {@code InputStream}.
+ * @throws SQLException
+ * if a database error happens.
+ */
+ @Deprecated
+ public void setUnicodeStream(int parameterIndex,
+ InputStream theInputStream, int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied {@code
+ * java.net.URL}.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1.
+ * @param theURL
+ * the {@code URL} to which the parameter at {@code
+ * parameterIndex} is set.
+ * @throws SQLException
+ * if a database error happens.
+ * @see URL
+ * @since Android 1.0
+ */
+ public void setURL(int parameterIndex, URL theURL) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/Ref.java b/sql/src/main/java/java/sql/Ref.java
new file mode 100644
index 0000000..2ceac8b
--- /dev/null
+++ b/sql/src/main/java/java/sql/Ref.java
@@ -0,0 +1,88 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.util.Map;
+
+/**
+ * This interface represents an SQL Ref - a data object containing a cursor
+ * or pointer to a result table.
+ *
+ * The data structure identified by an instance of Ref is held in the
+ * database, so the data is not necessarily read and converted
+ * into a Java object until {@code getObject} is called. However, if
+ * the database supports the {@code Ref} type, it is not typically
+ * necessary to get the underlying object before using it in a method call -
+ * the {@code Ref} object can be used in place of the data structure.
+ *
+ * A {@code Ref} object is stored into the database using the
+ * {@link PreparedStatement#setRef(int, Ref)} method.
+ *
+ * @since Android 1.0
+ */
+public interface Ref {
+
+ /**
+ * Gets the fully-qualified SQL name of the SQL structured type that this
+ * {@code Ref} references.
+ *
+ * @return the fully qualified name of the SQL structured type.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getBaseTypeName() throws SQLException;
+
+ /**
+ * Gets the SQL structured type instance referenced by this {@code Ref}.
+ *
+ * @return a Java object whose type is defined by the mapping for the SQL
+ * structured type.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Object getObject() throws SQLException;
+
+ /**
+ * Returns the associated object and uses the relevant mapping to convert it
+ * to a Java type.
+ *
+ * @param map
+ * the mapping for type conversion.
+ * @return a Java object whose type is defined by the mapping for the SQL
+ * structured type.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Object getObject(Map> map) throws SQLException;
+
+ /**
+ * Sets the value of the structured type that this {@code Ref} references to
+ * a supplied object.
+ *
+ * @param value
+ * the {@code Object} representing the new SQL structured type
+ * that this {@code Ref} references.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public void setObject(Object value) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/ResultSet.java b/sql/src/main/java/java/sql/ResultSet.java
new file mode 100644
index 0000000..f33f9de
--- /dev/null
+++ b/sql/src/main/java/java/sql/ResultSet.java
@@ -0,0 +1,2122 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.InputStream;
+import java.math.BigDecimal;
+import java.io.Reader;
+import java.util.Calendar;
+import java.util.Map;
+import java.net.URL;
+
+/**
+ * An interface for an object which represents a database table entry, returned
+ * as the result of the query to the database.
+ *
+ * {@code ResultSet}s have a cursor which points to the current data table row.
+ * When the {@code ResultSet} is created, the cursor's location is one position
+ * ahead of the first row. To move the cursor to the first and consecutive rows,
+ * use the {@code next} method. The {@code next} method returns {@code true} as
+ * long as there are more rows in the {@code ResultSet}, otherwise it returns
+ * {@code false}.
+ *
+ *
+ * The default type of {@code ResultSet} can not be updated and its cursor can
+ * only advance forward through the rows of data. This means that it is only
+ * possible to read through it once. However, other kinds of {@code ResultSet}
+ * are implemented: an updatable type and also types where the cursor can
+ * be scrolled forward and backward through the rows of data. How such a
+ * {@code ResultSet} is created is demonstrated in the following example:
+ *
{@code // theResultSet is both scrollable and updatable}
+ *
+ * The {@code ResultSet} interface provides a series of methods for retrieving
+ * data from columns in the current row, such as {@code getDate} and {@code
+ * getFloat}. The columns are retrieved either by their index number (starting
+ * at 1) or by their name - there are separate methods for both techniques of
+ * column addressing. The column names are case insensitive. If several columns
+ * have the same name, then the getter methods use the first matching column.
+ * This means that if column names are used, it is not possible to guarantee
+ * that the name will retrieve data from the intended column - for certainty it
+ * is better to use column indexes. Ideally the columns should be read
+ * left-to-right and read once only, since not all databases are optimized to
+ * handle other techniques of reading the data.
+ *
+ *
+ * When reading data via the appropriate getter methods, the JDBC driver maps
+ * the SQL data retrieved from the database to the Java type implied by the
+ * method invoked by the application. The JDBC specification has a table for the
+ * mappings from SQL types to Java types.
+ *
+ *
+ * There are also methods for writing data into the {@code ResultSet}, such as
+ * {@code updateInt} and {@code updateString}. The update methods can be used
+ * either to modify the data of an existing row or to insert new data rows into
+ * the {@code ResultSet} . Modification of existing data involves moving the
+ * cursor to the row which needs modification and then using the update methods
+ * to modify the data, followed by calling the {@code ResultSet.updateRow}
+ * method. For insertion of new rows, the cursor is first moved to a special row
+ * called the Insert Row, data is added using the update methods,
+ * followed by calling the {@code ResultSet.insertRow} method.
+ *
+ *
+ * A {@code ResultSet} is closed if the statement which generated it closes, the
+ * statement is executed again, or the same statement's next {@code ResultSet}
+ * is retrieved (if the statement returned of multiple results).
+ *
+ *
+ * @since Android 1.0
+ */
+public interface ResultSet {
+
+ /**
+ * A constant used to indicate that a {@code ResultSet} object must be
+ * closed when the method {@code Connection.commit} is invoked.
+ *
+ * @since Android 1.0
+ */
+ public static final int CLOSE_CURSORS_AT_COMMIT = 2;
+
+ /**
+ * A constant used to indicate that a {@code ResultSet} object must not be
+ * closed when the method {@code Connection.commit} is invoked.
+ *
+ * @since Android 1.0
+ */
+ public static final int HOLD_CURSORS_OVER_COMMIT = 1;
+
+ /**
+ * A constant used to indicate the concurrency mode for a {@code ResultSet}
+ * object that cannot be updated.
+ *
+ * @since Android 1.0
+ */
+ public static final int CONCUR_READ_ONLY = 1007;
+
+ /**
+ * A constant used to indicate the concurrency mode for a {@code ResultSet}
+ * object that can be updated.
+ *
+ * @since Android 1.0
+ */
+ public static final int CONCUR_UPDATABLE = 1008;
+
+ /**
+ * A constant used to indicate processing of the rows of a {@code ResultSet}
+ * in the forward direction, first to last.
+ *
+ * @since Android 1.0
+ */
+ public static final int FETCH_FORWARD = 1000;
+
+ /**
+ * A constant used to indicate processing of the rows of a {@code ResultSet}
+ * in the reverse direction, last to first.
+ *
+ * @since Android 1.0
+ */
+ public static final int FETCH_REVERSE = 1001;
+
+ /**
+ * A constant used to indicate that the order of processing of the rows of a
+ * {@code ResultSet} is unknown.
+ *
+ * @since Android 1.0
+ */
+ public static final int FETCH_UNKNOWN = 1002;
+
+ /**
+ * A constant used to indicate a {@code ResultSet} object whose cursor can
+ * only move forward.
+ *
+ * @since Android 1.0
+ */
+ public static final int TYPE_FORWARD_ONLY = 1003;
+
+ /**
+ * A constant used to indicate a {@code ResultSet} object which is
+ * scrollable but is insensitive to changes made by others.
+ *
+ * @since Android 1.0
+ */
+ public static final int TYPE_SCROLL_INSENSITIVE = 1004;
+
+ /**
+ * A constant used to indicate a {@code ResultSet} object which is
+ * scrollable and sensitive to changes made by others.
+ *
+ * @since Android 1.0
+ */
+ public static final int TYPE_SCROLL_SENSITIVE = 1005;
+
+ /**
+ * Moves the cursor to a specified row number in the {@code ResultSet}.
+ *
+ * @param row
+ * the index of the row starting at index 1. Index {@code -1}
+ * returns the last row.
+ * @return {@code true} if the new cursor position is on the {@code
+ * ResultSet}, {@code false} otherwise.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean absolute(int row) throws SQLException;
+
+ /**
+ * Moves the cursor to the end of the {@code ResultSet}, after the last row.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void afterLast() throws SQLException;
+
+ /**
+ * Moves the cursor to the start of the {@code ResultSet}, before the first
+ * row.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void beforeFirst() throws SQLException;
+
+ /**
+ * Cancels any updates made to the current row in the {@code ResultSet}.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void cancelRowUpdates() throws SQLException;
+
+ /**
+ * Clears all warnings related to this {@code ResultSet}.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void clearWarnings() throws SQLException;
+
+ /**
+ * Releases this {@code ResultSet}'s database and JDBC resources. You are
+ * strongly advised to use this method rather than relying on the release
+ * being done when the {@code ResultSet}'s finalize method is called during
+ * garbage collection process. Note that the {@code close()} method might
+ * take some time to complete since it is dependent on the behavior of the
+ * connection to the database and the database itself.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void close() throws SQLException;
+
+ /**
+ * Deletes the current row from the {@code ResultSet} and from the
+ * underlying database.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void deleteRow() throws SQLException;
+
+ /**
+ * Gets the index number for a column in the {@code ResultSet} from the
+ * provided column name.
+ *
+ * @param columnName
+ * the column name.
+ * @return the column's index in the {@code ResultSet} identified by column
+ * name.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int findColumn(String columnName) throws SQLException;
+
+ /**
+ * Shifts the cursor position to the first row in the {@code ResultSet}.
+ *
+ * @return {@code true} if the position is in a legitimate row, {@code
+ * false} if the {@code ResultSet} contains no rows.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean first() throws SQLException;
+
+ /**
+ * Gets the content of a column specified by column index in the current row
+ * of this {@code ResultSet} as a {@code java.sql.Array}.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a {@code java.sql.Array} with the data from the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Array getArray(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a {@code
+ * java.sql.Array}.
+ *
+ * @param colName
+ * the name of the column to read.
+ * @return a {@code java.sql.Array} with the data from the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Array getArray(String colName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as an ASCII
+ * character stream.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return an {@code InputStream} with the data from the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public InputStream getAsciiStream(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as an ASCII character
+ * stream.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return an {@code InputStream} with the data from the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public InputStream getAsciiStream(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.math.BigDecimal}.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code BigDecimal} with the value of the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.math.BigDecimal}.
+ *
+ * @deprecated use {@link #getBigDecimal(int)} or
+ * {@link #getBigDecimal(String)}
+ * @param columnIndex
+ * the index of the column to read.
+ * @param scale
+ * the number of digits after the decimal point
+ * @return a {@code BigDecimal} with the value of the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ @Deprecated
+ public BigDecimal getBigDecimal(int columnIndex, int scale)
+ throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code
+ * java.math.BigDecimal}.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a BigDecimal with value of the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public BigDecimal getBigDecimal(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code
+ * java.math.BigDecimal}.
+ *
+ * @deprecated use {@link #getBigDecimal(int)} or
+ * {@link #getBigDecimal(String)}
+ * @param columnName
+ * the name of the column to read.
+ * @param scale
+ * the number of digits after the decimal point
+ * @return a BigDecimal with value of the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ @Deprecated
+ public BigDecimal getBigDecimal(String columnName, int scale)
+ throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a binary
+ * stream.
+ *
+ * This method can be used to read {@code LONGVARBINARY} values. All of the
+ * data in the {@code InputStream} should be read before getting data from
+ * any other column. A further call to a getter method will implicitly close
+ * the {@code InputStream}.
+ *
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return an {@code InputStream} with the data from the column. If the
+ * column value is SQL {@code NULL}, {@code null} is returned.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public InputStream getBinaryStream(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a binary stream.
+ *
+ * This method can be used to read {@code LONGVARBINARY} values. All of the
+ * data in the {@code InputStream} should be read before getting data from
+ * any other column. A further call to a getter method will implicitly close
+ * the {@code InputStream}.
+ *
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return an {@code InputStream} with the data from the column if the
+ * column value is SQL {@code NULL}, {@code null} is returned.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public InputStream getBinaryStream(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.sql.Blob} object.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code java.sql.Blob} with the value of the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Blob getBlob(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code
+ * java.sql.Blob} object.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a {@code java.sql.Blob} with the value of the column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Blob getBlob(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code boolean}
+ * .
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code boolean} value from the column. If the column is SQL
+ * {@code NULL}, {@code false} is returned.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean getBoolean(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code boolean}
+ * .
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a {@code boolean} value from the column. If the column is SQL
+ * {@code NULL}, {@code false} is returned.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean getBoolean(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code byte}.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code byte} equal to the value of the column. 0 if the value
+ * is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public byte getByte(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a {@code byte}.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a {@code byte} equal to the value of the column. 0 if the value
+ * is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public byte getByte(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a byte array.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a byte array containing the value of the column. {@code null} if
+ * the column contains SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public byte[] getBytes(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a byte array.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a byte array containing the value of the column. {@code null} if
+ * the column contains SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public byte[] getBytes(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.io.Reader} object.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code Reader} holding the value of the column. {@code null} if
+ * the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @see java.io.Reader
+ * @since Android 1.0
+ */
+ public Reader getCharacterStream(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a {@code
+ * java.io.Reader} object.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a {@code Reader} holding the value of the column. {@code null} if
+ * the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Reader getCharacterStream(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.sql.Clob}.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code Clob} object representing the value in the column.
+ * {@code null} if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Clob getClob(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a {@code
+ * java.sql.Clob}.
+ *
+ * @param colName
+ * the name of the column to read.
+ * @return a {@code Clob} object representing the value in the column.
+ * {@code null} if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Clob getClob(String colName) throws SQLException;
+
+ /**
+ * Gets the concurrency mode of this {@code ResultSet}.
+ *
+ * @return the concurrency mode - one of: {@code ResultSet.CONCUR_READ_ONLY}
+ * , {@code ResultSet.CONCUR_UPDATABLE}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getConcurrency() throws SQLException;
+
+ /**
+ * Gets the name of the SQL cursor of this {@code ResultSet}.
+ *
+ * @return the SQL cursor name.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public String getCursorName() throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.sql.Date}.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code java.sql.Date} matching the column value. {@code null}
+ * if the column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Date getDate(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.sql.Date}. This method uses a supplied calendar to compute the Date.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @param cal
+ * a {@code java.util.Calendar} to use in constructing the Date.
+ * @return a {@code java.sql.Date} matching the column value. {@code null}
+ * if the column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Date getDate(int columnIndex, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a {@code
+ * java.sql.Date}.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a {@code java.sql.Date} matching the column value. {@code null}
+ * if the column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Date getDate(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code
+ * java.sql.Date} object.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @param cal
+ * {@code java.util.Calendar} to use in constructing the Date.
+ * @return a {@code java.sql.Date} matching the column value. {@code null}
+ * if the column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Date getDate(String columnName, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code double}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code double} equal to the column value. {@code 0.0} if the
+ * column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public double getDouble(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a {@code double}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a {@code double} equal to the column value. {@code 0.0} if the
+ * column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public double getDouble(String columnName) throws SQLException;
+
+ /**
+ * Gets the direction in which rows are fetched for this {@code ResultSet}
+ * object.
+ *
+ * @return the fetch direction. Will be one of:
+ *
+ *
ResultSet.FETCH_FORWARD
ResultSet.FETCH_REVERSE
+ *
ResultSet.FETCH_UNKNOWN
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getFetchDirection() throws SQLException;
+
+ /**
+ * Gets the fetch size (in number of rows) for this {@code ResultSet}.
+ *
+ * @return the fetch size as an int
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getFetchSize() throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code float}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code float} equal to the column value. {@code 0.0} if the
+ * column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public float getFloat(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a {@code float}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a {@code float} equal to the column value. {@code 0.0} if the
+ * column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public float getFloat(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as an {@code int}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return an {@code int} equal to the column value. {@code 0} if the
+ * column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getInt(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as an {@code int}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return an {@code int} equal to the column value. {@code 0} if the
+ * column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getInt(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code long}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a {@code long} equal to the column value. {@code 0} if the
+ * column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public long getLong(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code long}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a {@code long} equal to the column value. {@code 0} if the
+ * column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public long getLong(String columnName) throws SQLException;
+
+ /**
+ * Gets the metadata for this {@code ResultSet}. This defines the number,
+ * types and properties of the columns in the {@code ResultSet}.
+ *
+ * @return a {@code ResultSetMetaData} object with information about this
+ * {@code ResultSet}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public ResultSetMetaData getMetaData() throws SQLException;
+
+ /**
+ * Gets the value of a specified column as a Java {@code Object}. The type
+ * of the returned object will be the default according to the column's SQL
+ * type, following the JDBC specification for built-in types.
+ *
+ * For SQL User Defined Types, if a column value is Structured or Distinct,
+ * this method behaves the same as a call to: {@code
+ * getObject(columnIndex,this.getStatement().getConnection().getTypeMap())}
+ *
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return an {@code Object} containing the value of the column. {@code
+ * null} if the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Object getObject(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a Java {@code
+ * Object}.
+ *
+ * The type of the Java object will be determined by the supplied Map to
+ * perform the mapping of SQL {@code Struct} or Distinct types into Java
+ * objects.
+ *
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @param map
+ * a {@code java.util.Map} containing a mapping from SQL Type
+ * names to Java classes.
+ * @return an {@code Object} containing the value of the column. {@code
+ * null} if the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Object getObject(int columnIndex, Map> map)
+ throws SQLException;
+
+ /**
+ * Gets the value of a specified column as a Java {@code Object}. The type
+ * of the returned object will be the default according to the column's SQL
+ * type, following the JDBC specification for built-in types.
+ *
+ * For SQL User Defined Types, if a column value is structured or distinct,
+ * this method behaves the same as a call to: {@code
+ * getObject(columnIndex,this.getStatement().getConnection().getTypeMap())}
+ *
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return an {@code Object} containing the value of the column. {@code
+ * null} if the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Object getObject(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a Java {@code
+ * Object}.
+ *
+ * The type of the Java object will be determined by the supplied Map to
+ * perform the mapping of SQL Struct or Distinct types into Java objects.
+ *
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @param map
+ * a {@code java.util.Map} containing a mapping from SQL Type names to
+ * Java classes.
+ * @return an {@code Object} containing the value of the column. {@code
+ * null} if the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Object getObject(String columnName, Map> map)
+ throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a Java {@code
+ * java.sql.Ref}.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a Ref representing the value of the SQL REF in the column
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Ref getRef(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a Java {@code
+ * java.sql.Ref}.
+ *
+ * @param colName
+ * the name of the column to read.
+ * @return a Ref representing the value of the SQL {@code REF} in the column
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Ref getRef(String colName) throws SQLException;
+
+ /**
+ * Gets the number of the current row in the {@code ResultSet}. Row numbers
+ * start at 1 for the first row.
+ *
+ * @return the index number of the current row. {@code 0} is returned if
+ * there is no current row.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public int getRow() throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a short value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a short value equal to the value of the column. {@code 0} if
+ * the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public short getShort(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a short value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a short value equal to the value of the column. {@code 0} if
+ * the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public short getShort(String columnName) throws SQLException;
+
+ /**
+ * Gets the statement that produced this {@code ResultSet}. If the {@code
+ * ResultSet} was not created by a statement (i.e. because it was returned
+ * from one of the {@link DatabaseMetaData} methods), {@code null} is
+ * returned.
+ *
+ * @return the Statement which produced this {@code ResultSet}, or {@code
+ * null} if the {@code ResultSet} was not created by a Statement.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Statement getStatement() throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a String.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return the String representing the value of the column, {@code null} if
+ * the column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public String getString(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a String.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return the String representing the value of the column, {@code null} if
+ * the column is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public String getString(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.sql.Time} value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a Time representing the column value, {@code null} if the column
+ * value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Time getTime(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.sql.Time} value. The supplied {@code Calendar} is used to
+ * map the SQL {@code Time} value to a Java Time value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @param cal
+ * a {@code Calendar} to use in creating the Java Time value.
+ * @return a Time representing the column value, {@code null} if the column
+ * value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Time getTime(int columnIndex, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code
+ * java.sql.Time} value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return the column value, {@code null} if the column value is SQL {@code
+ * NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Time getTime(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index, as a {@code
+ * java.sql.Time} value. The supplied {@code Calendar} is used to
+ * map the SQL {@code Time} value to a Java Time value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @param cal
+ * a {@code Calendar} to use in creating the Java time value.
+ * @return a Time representing the column value, {@code null} if the column
+ * value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Time getTime(String columnName, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.sql.Timestamp} value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a timestamp representing the column value, {@code null} if the
+ * column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Timestamp getTimestamp(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index, as a {@code
+ * java.sql.Timestamp} value. The supplied Calendar is used when mapping
+ * the SQL {@code Timestamp} value to a Java {@code Timestamp} value.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @param cal
+ * Calendar to use in creating the Java timestamp value.
+ * @return a timestamp representing the column value, {@code null} if the
+ * column value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Timestamp getTimestamp(int columnIndex, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code
+ * java.sql.Timestamp} value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return a timestamp representing the column value, {@code null} if the
+ * column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Timestamp getTimestamp(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name, as a {@code
+ * java.sql.Timestamp} value. The supplied Calendar is used when mapping
+ * the SQL {@code Timestamp} value to a Java {@code Timestamp} value.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @param cal
+ * Calendar to use in creating the Java {@code Timestamp} value.
+ * @return a timestamp representing the column value, {@code null} if the
+ * column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public Timestamp getTimestamp(String columnName, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Gets the type of the {@code ResultSet}.
+ *
+ * @return The {@code ResultSet} type, one of:
+ *
+ *
{@code ResultSet.TYPE_FORWARD_ONLY}
{@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE}
{@code
+ * ResultSet.TYPE_SCROLL_SENSITIVE}
+ *
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public int getType() throws SQLException;
+
+ /**
+ * Gets the value of the column as an {@code InputStream} of unicode
+ * characters.
+ *
+ * @deprecated Use {@link #getCharacterStream}.
+ * @param columnIndex
+ * the index of the column to read.
+ * @return an {@code InputStream} holding the value of the column. {@code
+ * null} if the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ @Deprecated
+ public InputStream getUnicodeStream(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of the column as an {@code InputStream} of Unicode
+ * characters.
+ *
+ * @deprecated Use {@link #getCharacterStream}
+ * @param columnName
+ * the name of the column to read.
+ * @return an {@code InputStream} holding the value of the column. {@code
+ * null} if the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ @Deprecated
+ public InputStream getUnicodeStream(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column index as a {@code
+ * java.net.URL}.
+ *
+ * @param columnIndex
+ * the index of the column to read.
+ * @return a URL. {@code null} if the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public URL getURL(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified by column name as a {@code
+ * java.net.URL} object.
+ *
+ * @param columnName
+ * the name of the column to read.
+ * @return the column vaule as a URL. {@code null} if the column value is SQL {@code NULL}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public URL getURL(String columnName) throws SQLException;
+
+ /**
+ * Gets the first warning generated by calls on this {@code ResultSet}.
+ * Subsequent warnings on this {@code ResultSet} are chained to the first
+ * one.
+ *
+ * The warnings are cleared when a new Row is read from the {@code
+ * ResultSet}. The warnings returned by this method are only the warnings
+ * generated by {@code ResultSet} method calls - warnings generated by
+ * Statement methods are held by the Statement.
+ *
+ *
+ * An {@code SQLException} is generated if this method is called on a closed
+ * {@code ResultSet}.
+ *
+ * @return an SQLWarning which is the first warning for this {@code
+ * ResultSet}. {@code null} if there are no warnings.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * Insert the insert row into the {@code ResultSet} and into the underlying
+ * database. The cursor must be set to the Insert Row before this method is
+ * invoked.
+ *
+ * @throws SQLException
+ * if a database error happens. Particular cases include the
+ * cursor not being on the Insert Row or if any columns in the
+ * row do not have a value where the column is declared as
+ * not-nullable.
+ * @since Android 1.0
+ */
+ public void insertRow() throws SQLException;
+
+ /**
+ * Gets if the cursor is after the last row of the {@code ResultSet}.
+ *
+ * @return {@code true} if the cursor is after the last row in the {@code
+ * ResultSet}, {@code false} if the cursor is at any other position
+ * in the {@code ResultSet}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean isAfterLast() throws SQLException;
+
+ /**
+ * Gets if the cursor is before the first row of the {@code ResultSet}.
+ *
+ * @return {@code true} if the cursor is before the first row in the {@code
+ * ResultSet}, {@code false} if the cursor is at any other position
+ * in the {@code ResultSet}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean isBeforeFirst() throws SQLException;
+
+ /**
+ * Gets if the cursor is on the first row of the {@code ResultSet}.
+ *
+ * @return {@code true} if the cursor is on the first row in the {@code
+ * ResultSet}, {@code false} if the cursor is at any other position
+ * in the {@code ResultSet}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean isFirst() throws SQLException;
+
+ /**
+ * Gets if the cursor is on the last row of the {@code ResultSet}
+ *
+ * @return {@code true} if the cursor is on the last row in the {@code
+ * ResultSet}, {@code false} if the cursor is at any other position
+ * in the {@code ResultSet}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean isLast() throws SQLException;
+
+ /**
+ * Shifts the cursor position to the last row of the {@code ResultSet}.
+ *
+ * @return {@code true} if the new position is in a legitimate row, {@code
+ * false} if the {@code ResultSet} contains no rows.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean last() throws SQLException;
+
+ /**
+ * Moves the cursor to the remembered position, namely the
+ * row that was the current row before a call to {@code moveToInsertRow}.
+ * This only applies if the cursor is on the Insert Row.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void moveToCurrentRow() throws SQLException;
+
+ /**
+ * Moves the cursor position to the Insert Row. The current position is
+ * remembered and the cursor is positioned at the Insert Row. The columns in
+ * the Insert Row should be filled in with the appropriate update methods,
+ * before calling {@code insertRow} to insert the new row into the database.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void moveToInsertRow() throws SQLException;
+
+ /**
+ * Shifts the cursor position down one row in this {@code ResultSet} object.
+ *
+ * Any input streams associated with the current row are closed and any
+ * warnings are cleared.
+ *
+ *
+ * @return {@code true} if the updated cursor position is pointing to a
+ * valid row, {@code false} otherwise (i.e. when the cursor is after
+ * the last row in the {@code ResultSet}).
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean next() throws SQLException;
+
+ /**
+ * Relocates the cursor position to the preceding row in this {@code
+ * ResultSet}.
+ *
+ * @return {@code true} if the new position is in a legitimate row, {@code
+ * false} if the cursor is now before the first row.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean previous() throws SQLException;
+
+ /**
+ * Refreshes the current row with its most up to date value in the database.
+ * Must not be called when the cursor is on the Insert Row.
+ *
+ * If any columns in the current row have been updated but the {@code
+ * updateRow} has not been called, then the updates are lost when this
+ * method is called.
+ *
+ *
+ * @throws SQLException
+ * if a database error happens., including if the current row is
+ * the Insert row.
+ * @since Android 1.0
+ */
+ public void refreshRow() throws SQLException;
+
+ /**
+ * Moves the cursor position up or down by a specified number of rows. If
+ * the new position is beyond the start row (or end row), the cursor position is
+ * set before the first row (or, respectively, after the last row).
+ *
+ * @param rows
+ * a number of rows to move the cursor - may be positive or
+ * negative
+ * @return {@code true} if the new cursor position is on a row, {@code
+ * false} otherwise
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean relative(int rows) throws SQLException;
+
+ /**
+ * Indicates whether a row has been deleted. This method depends on whether
+ * the JDBC driver and database can detect deletions.
+ *
+ * @return {@code true} if a row has been deleted and if deletions are
+ * detected, {@code false} otherwise.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean rowDeleted() throws SQLException;
+
+ /**
+ * Indicates whether the current row has had an insertion operation. This
+ * method depends on whether the JDBC driver and database can detect
+ * insertions.
+ *
+ * @return {@code true} if a row has been inserted and if insertions are
+ * detected, {@code false} otherwise.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean rowInserted() throws SQLException;
+
+ /**
+ * Indicates whether the current row has been updated. This method depends
+ * on whether the JDBC driver and database can detect updates.
+ *
+ * @return {@code true} if the current row has been updated and if updates
+ * can be detected, {@code false} otherwise.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean rowUpdated() throws SQLException;
+
+ /**
+ * Indicates which direction (forward/reverse) will be used to process the
+ * rows of this {@code ResultSet} object. This is treated as a hint by the
+ * JDBC driver.
+ *
+ * @param direction
+ * can be {@code ResultSet.FETCH_FORWARD}, {@code
+ * ResultSet.FETCH_REVERSE}, or {@code ResultSet.FETCH_UNKNOWN}
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public void setFetchDirection(int direction) throws SQLException;
+
+ /**
+ * Indicates the number of rows to fetch from the database when extra rows
+ * are required for this {@code ResultSet}. This used as a hint to the JDBC
+ * driver.
+ *
+ * @param rows
+ * the number of rows to fetch. {@code 0} implies that the JDBC
+ * driver can make its own decision about the fetch size. The
+ * number should not be greater than the maximum number of rows
+ * established by the statement that generated the {@code
+ * ResultSet}.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void setFetchSize(int rows) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code
+ * java.sql.Array} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateArray(int columnIndex, Array x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code java.sql.Array}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateArray(String columnName, Array x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with an ASCII stream value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @param length
+ * the length of the data to write from the stream
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateAsciiStream(int columnIndex, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with an Ascii stream value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @param length
+ * the length of the data to write from the stream
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateAsciiStream(String columnName, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code
+ * java.sql.BigDecimal} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBigDecimal(int columnIndex, BigDecimal x)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code
+ * java.sql.BigDecimal} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBigDecimal(String columnName, BigDecimal x)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a binary stream value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @param length
+ * the number of bytes to be read from the the stream.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBinaryStream(int columnIndex, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a binary stream value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @param length
+ * he number of bytes to be read from the the stream.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBinaryStream(String columnName, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code java.sql.Blob}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBlob(int columnIndex, Blob x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code java.sql.Blob}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBlob(String columnName, Blob x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code boolean}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBoolean(int columnIndex, boolean x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code boolean} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBoolean(String columnName, boolean x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code byte} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateByte(int columnIndex, byte x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code byte} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateByte(String columnName, byte x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code byte} array
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBytes(int columnIndex, byte[] x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a byte array value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateBytes(String columnName, byte[] x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a character stream
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @param length
+ * the length of data to write from the stream
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateCharacterStream(int columnIndex, Reader x, int length)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a character stream
+ * value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param reader
+ * the new value for the specified column.
+ * @param length
+ * the length of data to write from the Reader
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateCharacterStream(String columnName, Reader reader,
+ int length) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code java.sql.Clob}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateClob(int columnIndex, Clob x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code java.sql.Clob}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateClob(String columnName, Clob x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code java.sql.Date}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateDate(int columnIndex, Date x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code java.sql.Date}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateDate(String columnName, Date x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code double} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateDouble(int columnIndex, double x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code double} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateDouble(String columnName, double x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code float} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateFloat(int columnIndex, float x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code float} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateFloat(String columnName, float x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with an {@code int} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateInt(int columnIndex, int x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with an {@code int} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateInt(String columnName, int x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code long} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column..
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateLong(int columnIndex, long x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code long} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateLong(String columnName, long x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code null} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateNull(int columnIndex) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code null} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateNull(String columnName) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with an {@code Object}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateObject(int columnIndex, Object x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with an {@code Object}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @param scale
+ * for the types {@code java.sql.Types.DECIMAL} or {@code
+ * java.sql.Types.NUMERIC}, this specifies the number of digits
+ * after the decimal point.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateObject(int columnIndex, Object x, int scale)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with an {@code Object} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateObject(String columnName, Object x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with an {@code Object} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @param scale
+ * for the types {@code java.sql.Types.DECIMAL} or {@code
+ * java.sql.Types.NUMERIC}, this specifies the number of digits
+ * after the decimal point.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateObject(String columnName, Object x, int scale)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code java.sql.Ref}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateRef(int columnIndex, Ref x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code java.sql.Ref}
+ * value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateRef(String columnName, Ref x) throws SQLException;
+
+ /**
+ * Updates the database with the new contents of the current row of this
+ * {@code ResultSet} object.
+ *
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateRow() throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code short} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateShort(int columnIndex, short x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code short} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateShort(String columnName, short x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code String} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateString(int columnIndex, String x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code String} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateString(String columnName, String x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code Time} value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateTime(int columnIndex, Time x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a {@code Time} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateTime(String columnName, Time x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a {@code Timestamp}
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to update.
+ * @param x
+ * the new timestamp value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateTimestamp(int columnIndex, Timestamp x)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by column name with a {@code Timestamp} value.
+ *
+ * @param columnName
+ * the name of the column to update.
+ * @param x
+ * the new timestamp value for the specified column.
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public void updateTimestamp(String columnName, Timestamp x)
+ throws SQLException;
+
+ /**
+ * Determines whether the last column read from this {@code ResultSet}
+ * contained SQL {@code NULL}.
+ *
+ * @return {@code {@code true} if the last column contained SQL {@code
+ * NULL}, {@code false} otherwise
+ * @throws SQLException
+ * if a database error happens.
+ * @since Android 1.0
+ */
+ public boolean wasNull() throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/ResultSetMetaData.java b/sql/src/main/java/java/sql/ResultSetMetaData.java
new file mode 100644
index 0000000..95c515d
--- /dev/null
+++ b/sql/src/main/java/java/sql/ResultSetMetaData.java
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+/**
+ * Provides information about the columns returned in a {@code ResultSet}.
+ *
+ * @since Android 1.0
+ */
+public interface ResultSetMetaData {
+
+ /**
+ * Indicates that a column cannot contain {@code NULL} values.
+ *
+ * @since Android 1.0
+ */
+ public static final int columnNoNulls = 0;
+
+ /**
+ * Indicates that a column can contain {@code NULL} values.
+ *
+ * @since Android 1.0
+ */
+ public static final int columnNullable = 1;
+
+ /**
+ * Indicates that it is unknown whether a column can contain {@code NULL}s or not.
+ *
+ * @since Android 1.0
+ */
+ public static final int columnNullableUnknown = 2;
+
+ /**
+ * Returns the title of an indexed column's catalog.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the catalog title.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getCatalogName(int column) throws SQLException;
+
+ /**
+ * Returns the fully-qualified type of the class that is produced when
+ * invoking {@code ResultSet.getObject} to recover this column's value.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the fully-qualified class name.
+ * @throws SQLException
+ * if there is a database error.
+ * @see ResultSet#getObject
+ * @since Android 1.0
+ */
+ public String getColumnClassName(int column) throws SQLException;
+
+ /**
+ * Returns number of columns contained in the associated result set.
+ *
+ * @return the column count.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public int getColumnCount() throws SQLException;
+
+ /**
+ * Returns the indexed column's standard maximum width, expressed in number
+ * of characters.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the column's max width.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public int getColumnDisplaySize(int column) throws SQLException;
+
+ /**
+ * Returns a recommended title for the indexed column, to be used when the
+ * title needs to be displayed.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the column's title.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getColumnLabel(int column) throws SQLException;
+
+ /**
+ * Returns the title of the indexed column.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the column title.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getColumnName(int column) throws SQLException;
+
+ /**
+ * Returns the type of the indexed column as SQL type code.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the column type code.
+ * @throws SQLException
+ * if there is a database error.
+ * @see Types
+ * @since Android 1.0
+ */
+ public int getColumnType(int column) throws SQLException;
+
+ /**
+ * Returns the type name of the indexed column.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the type name.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getColumnTypeName(int column) throws SQLException;
+
+ /**
+ * Returns the decimal precision of the indexed column.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the precision.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public int getPrecision(int column) throws SQLException;
+
+ /**
+ * Returns the number of digits to the right of the decimal point of the
+ * indexed column.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return number of decimal places.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public int getScale(int column) throws SQLException;
+
+ /**
+ * Returns the name of the indexed columns schema.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the name of the columns schema.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getSchemaName(int column) throws SQLException;
+
+ /**
+ * Returns the title of the indexed columns table.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return the table title.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String getTableName(int column) throws SQLException;
+
+ /**
+ * Returns an indication of whether the indexed column is automatically
+ * incremented and is therefore read-only.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if it is automatically numbered, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean isAutoIncrement(int column) throws SQLException;
+
+ /**
+ * Returns an indication of whether the case of the indexed column is
+ * important.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if case matters, {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean isCaseSensitive(int column) throws SQLException;
+
+ /**
+ * Returns whether the indexed column contains a monetary amount.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if it is a monetary value, {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean isCurrency(int column) throws SQLException;
+
+ /**
+ * Returns an indication of whether writing to the indexed column is
+ * guaranteed to be successful.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if the write is guaranteed, {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean isDefinitelyWritable(int column) throws SQLException;
+
+ /**
+ * Returns whether the indexed column is nullable.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if it is nullable, {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public int isNullable(int column) throws SQLException;
+
+ /**
+ * Returns an indication of whether writing to the indexed column is
+ * guaranteed to be unsuccessful.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if the column is read-only, {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean isReadOnly(int column) throws SQLException;
+
+ /**
+ * Returns an indication of whether the indexed column is searchable.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if the indexed column is searchable, {@code false}
+ * otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean isSearchable(int column) throws SQLException;
+
+ /**
+ * Returns an indication of whether the values contained in the indexed
+ * column are signed.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if they are signed, {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean isSigned(int column) throws SQLException;
+
+ /**
+ * Returns an indication of whether writing to the indexed column is
+ * possible.
+ *
+ * @param column
+ * the column index, starting at 1.
+ * @return {@code true} if it is possible to write, {@code false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean isWritable(int column) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/SQLData.java b/sql/src/main/java/java/sql/SQLData.java
new file mode 100644
index 0000000..cae9d15
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLData.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+/**
+ * An interface for the custom mapping of an SQL User Defined Type (UDT)
+ * to a Java class. The Java class object is added to the connection's type map
+ * paired with the SQL name of the corresponding UDT.
+ *
+ * Usually within an implementation of {@code SQLData}, there is a corresponding
+ * field for every attribute of an SQL type, but only one field, if the type is
+ * SQL {@code DISTINCT}. When the UDT is returned within a {@code ResultSet}, it
+ * is accessed with the {@link ResultSet#getObject} method and is returned as an
+ * object which is an instance of the class defined by the {@code SQLData}
+ * mapping. The application can use this object just like any other Java object
+ * and can store changes back into the database using the
+ * {@link PreparedStatement#setObject} method which performs the reverse mapping
+ * into the SQL {@code UDT}.
+ *
+ * Normally the implementation of a custom mapping is generated by
+ * a tool requiring the name of the SQL {@code UDT}, the name
+ * of the class which it is going to be mapped to, and the field names to which
+ * the UDT attributes are mapped. The tool can then implement the {@code
+ * SQLData}, {@code readSQL}, and {@code writeSQL} methods. {@code readSQL} reads
+ * attributes from an {@code SQLInput} object, and {@code writeSQL} writes them.
+ * This is done via {@code SQLInput} and {@code SQLOutput} method calls
+ * respectively.
+ *
+ * Ordinarily an application would not call {@code SQLData} methods directly.
+ * Similarly {@code SQLInput} and {@code SQLOutput} methods are not usually
+ * called directly.
+ *
+ *
+ * @since Android 1.0
+ */
+public interface SQLData {
+
+ /**
+ * Gets the SQL name of the User Defined Type (UDT) that this object
+ * represents. This method, usually invoked by the JDBC driver, retrieves
+ * the name of the UDT instance associated with this {@code SQLData} object.
+ *
+ * @return a string with UDT type name for this object mapping, passed to
+ * {@code readSQL} when the object was created.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public String getSQLTypeName() throws SQLException;
+
+ /**
+ * Reads data from the database into this object. This method follows these
+ * steps:
+ *
+ *
+ *
Utilize the passed input stream to read the attributes or entries of
+ * the SQL type
+ *
This is carried out by reading each entry from the input stream,
+ * ordered as they are in the SQL definition.
+ *
Assign the data to the appropriate fields or elements. This is done
+ * by calling the relevant reader method for the type involved (e.g. {@code
+ * SQLInput.readString}, {@code SQLInputreadBigDecimal}). If the type is
+ * distinct, then read its only data entry. For structured types, read every
+ * entry.
+ *
+ *
+ *
+ * The supplied input stream is typically initialized by the calling JDBC
+ * driver with the type map before {@code readSQL} is called.
+ *
+ *
+ * @param stream
+ * the {@code SQLInput} stream from which the type map data is
+ * read for the custom mapping.
+ * @param typeName
+ * the SQL type name for the type which is being mapped.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see SQLInput
+ * @since Android 1.0
+ */
+ public void readSQL(SQLInput stream, String typeName) throws SQLException;
+
+ /**
+ * Writes the object to a supplied {@code SQLOutput} data stream, writing it
+ * out as an SQL value to the data source.
+ *
+ * This method follows the following steps:
+ *
+ *
Write each attribute of the SQL type to the output stream.
+ *
Write each item by calling a method on the output stream, in the
+ * order they appear in the SQL definition of the type. Use the appropriate
+ * {@code SQLOutput} methods (e.g. {@code writeInt}, {@code writeString}).
+ * Write a single data element for a distinct type. For a structured type,
+ * write a value for each attribute of the the SQL type.
+ *
+ *
+ *
+ * @param stream
+ * the {@code SQLOutput} stream to use to write out the data for
+ * the custom mapping.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see SQLOutput
+ * @since Android 1.0
+ */
+ public void writeSQL(SQLOutput stream) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/SQLException.java b/sql/src/main/java/java/sql/SQLException.java
new file mode 100644
index 0000000..2cea139
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLException.java
@@ -0,0 +1,168 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.Serializable;
+
+/**
+ * An {@code Exception} class that is used in conjunction with JDBC operations.
+ * It provides information about problems encountered with database access and
+ * other problems related to JDBC
+ *
+ * The {@code SQLException} class provides the following information:
+ *
+ *
A standard Java exception message, as a {@code String}
+ *
An {@code SQLState} string. This is an error description string which
+ * follows either the SQL 99 conventions or the X/OPEN {@code SQLstate}
+ * conventions. The potential values of the {@code SQLState} string are
+ * described in each of the specifications. Which of the conventions is being
+ * used by the {@code SQLState} string can be discovered by using the {@code
+ * getSQLStateType} method of the {@code DatabaseMetaData} interface.
+ *
An error code, an an integer. The error code is specific to each database
+ * vendor and is typically the error code returned by the database itself.
+ *
A chain to a next {@code Exception}, if relevant, which can give access
+ * to additional error information.
+ *
+ *
+ *
+ * @see DatabaseMetaData
+ *
+ * @since Android 1.0
+ */
+public class SQLException extends Exception implements Serializable {
+
+ private static final long serialVersionUID = 2135244094396331484L;
+
+ private String SQLState = null;
+
+ private int vendorCode = 0;
+
+ private SQLException next = null;
+
+ /**
+ * Creates an {@code SQLException} object. The reason string is set to
+ * {@code null}, the {@code SQLState} string is set to {@code null} and the
+ * error code is set to 0.
+ */
+ public SQLException() {
+ super();
+ }
+
+ /**
+ * Creates an {@code SQLException} object. The reason string is set to the given
+ * reason string, the {@code SQLState} string is set to {@code null} and the error code is
+ * set to 0.
+ *
+ * @param theReason
+ * the string to use as the Reason string
+ */
+ public SQLException(String theReason) {
+ this(theReason, null, 0);
+ }
+
+ /**
+ * Creates an {@code SQLException} object. The reason string is set to the
+ * given reason string, the {@code SQLState} string is set to the given
+ * {@code SQLState} string and the error code is set to 0.
+ *
+ * @param theReason
+ * the string to use as the reason string.
+ * @param theSQLState
+ * the string to use as the {@code SQLState} string.
+ * @since Android 1.0
+ */
+ public SQLException(String theReason, String theSQLState) {
+ this(theReason, theSQLState, 0);
+ }
+
+ /**
+ * Creates an {@code SQLException} object. The reason string is set to the
+ * given reason string, the {@code SQLState} string is set to the given
+ * {@code SQLState} string and the error code is set to the given error code
+ * value.
+ *
+ * @param theReason
+ * the string to use as the reason string.
+ * @param theSQLState
+ * the string to use as the {@code SQLState} string.
+ * @param theErrorCode
+ * the integer value for the error code.
+ * @since Android 1.0
+ */
+ public SQLException(String theReason, String theSQLState, int theErrorCode) {
+ super(theReason);
+ SQLState = theSQLState;
+ vendorCode = theErrorCode;
+ }
+
+ /**
+ * Returns the integer error code for this {@code SQLException}.
+ *
+ * @return The integer error code for this {@code SQLException}. The meaning
+ * of the code is specific to the vendor of the database.
+ * @since Android 1.0
+ */
+ public int getErrorCode() {
+ return vendorCode;
+ }
+
+ /**
+ * Retrieves the {@code SQLException} chained to this {@code SQLException},
+ * if any.
+ *
+ * @return The {@code SQLException} chained to this {@code SQLException}.
+ * {@code null} if there is no {@code SQLException} chained to this
+ * {@code SQLException}.
+ */
+ public SQLException getNextException() {
+ return next;
+ }
+
+ /**
+ * Retrieves the {@code SQLState} description string for this {@code
+ * SQLException} object.
+ *
+ * @return The {@code SQLState} string for this {@code SQLException} object.
+ * This is an error description string which follows either the SQL
+ * 99 conventions or the X/OPEN {@code SQLstate} conventions. The
+ * potential values of the {@code SQLState} string are described in
+ * each of the specifications. Which of the conventions is being
+ * used by the {@code SQLState} string can be discovered by using
+ * the {@code getSQLStateType} method of the {@code
+ * DatabaseMetaData} interface.
+ */
+ public String getSQLState() {
+ return SQLState;
+ }
+
+ /**
+ * Adds the SQLException to the end of this {@code SQLException} chain.
+ *
+ * @param ex
+ * the new {@code SQLException} to be added to the end of the
+ * chain.
+ * @since Android 1.0
+ */
+ public void setNextException(SQLException ex) {
+ if (next != null) {
+ next.setNextException(ex);
+ } else {
+ next = ex;
+ }
+ }
+}
diff --git a/sql/src/main/java/java/sql/SQLInput.java b/sql/src/main/java/java/sql/SQLInput.java
new file mode 100644
index 0000000..b72c839
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLInput.java
@@ -0,0 +1,341 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.math.BigDecimal;
+import java.io.Reader;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * The {@code SQLInput} interface defines operations which apply to a type of
+ * input stream which carries a series of values representing an instance of
+ * an SQL structured type or SQL distinct type.
+ *
+ * This interface is used to define custom mappings of SQL User Defined
+ * Types (UDTs) to Java classes. It is used by JDBC drivers, therefore
+ * application programmers do not normally use the {@code SQLInput} methods
+ * directly. Reader methods such as {@code readLong} and {@code readBytes}
+ * provide means to read values from an {@code SQLInput} stream.
+ *
+ * When the {@code getObject} method is called with an object which implements
+ * the {@code SQLData} interface, the JDBC driver determines the SQL type of the
+ * UDT being mapped by calling the {@code SQLData.getSQLType} method. The driver
+ * creates an instance of an {@code SQLInput} stream, filling the stream with
+ * the attributes of the UDT. The {@code SQLInput} stream is passed to the
+ * {@code SQLData.readSQL} method which then calls the {@code SQLInput} reader
+ * methods to read the attributes.
+ *
+ *
+ * @see SQLData
+ *
+ * @since Android 1.0
+ */
+public interface SQLInput {
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code String}.
+ *
+ * @return the next attribute. {@code null} if the value is SQL {@code NULL}.
+ *
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public String readString() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code boolean}
+ * .
+ *
+ * @return the next attribute as a {@code boolean}. {@code false} if the
+ * value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean readBoolean() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code byte}.
+ *
+ * @return the next attribute as a {@code byte}. 0 if the value is SQL
+ * {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public byte readByte() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code short}.
+ *
+ * @return the next attribute as a {@code short}. 0 if the value is SQL
+ * {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public short readShort() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of an {@code int}.
+ *
+ * @return the next attribute as an {@code int}. 0 if the value is SQL
+ * {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public int readInt() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code long}.
+ *
+ * @return the next attribute as a {@code long}. 0 if the value is SQL
+ * {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public long readLong() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code float}.
+ *
+ * @return the next attribute as a {@code float}. 0 if the value is SQL
+ * {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public float readFloat() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code double}.
+ *
+ * @return the next attribute as a {@code double}. 0 if the value is SQL
+ * {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public double readDouble() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.math.BigDecimal}.
+ *
+ * @return the attribute as a {@code java.math.BigDecimal}. {@code null} if
+ * the read returns SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see java.math.BigDecimal
+ * @since Android 1.0
+ */
+ public BigDecimal readBigDecimal() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a byte array.
+ *
+ * @return the attribute as a byte array. {@code null} if the read returns
+ * SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public byte[] readBytes() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.sql.Date}.
+ *
+ * @return the next attribute as a {@code java.sql.Date}. {@code null} if
+ * the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see Date
+ * @since Android 1.0
+ */
+ public Date readDate() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.sql.Time}.
+ *
+ * @return the attribute as a {@code java.sql.Time}. {@code null} if the
+ * read returns SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see Time
+ * @since Android 1.0
+ */
+ public Time readTime() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.sql.Timestamp}.
+ *
+ * @return the attribute as a {@code java.sql.Timestamp}. {@code null} if
+ * the read returns SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see Timestamp
+ * @since Android 1.0
+ */
+ public Timestamp readTimestamp() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a Unicode
+ * character stream embodied as a {@code java.io.Reader}.
+ *
+ * @return the next attribute as a {@code java.io.Reader}. {@code null} if
+ * the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see java.io.Reader
+ * @since Android 1.0
+ */
+ public Reader readCharacterStream() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of an ASCII
+ * character stream embodied as a {@code java.io.InputStream}.
+ *
+ * @return the next attribute as a {@code java.io.InputStream}. {@code null}
+ * if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see java.io.InputStream
+ * @since Android 1.0
+ */
+ public InputStream readAsciiStream() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a stream of bytes
+ * embodied as a {@code java.io.InputStream}.
+ *
+ * @return the next attribute as a {@code java.io.InputStream}. {@code null}
+ * if the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see java.io.InputStream
+ * @since Android 1.0
+ */
+ public InputStream readBinaryStream() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.lang.Object}.
+ *
+ * The type of the {@code Object} returned is determined by the type mapping
+ * for this JDBC driver, including any customized mappings, if present. A
+ * type map is given to the {@code SQLInput} by the JDBC driver before the
+ * {@code SQLInput} is given to the application.
+ *
+ *
+ * If the attribute is an SQL structured or distinct type, its SQL type is
+ * determined. If the stream's type map contains an element for that SQL
+ * type, the driver creates an object for the relevant type and invokes the
+ * method {@code SQLData.readSQL} on it, which reads supplementary data from
+ * the stream using whichever protocol is defined for that method.
+ *
+ *
+ * @return the next attribute as an Object. {@code null} if the value is SQL
+ * {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Object readObject() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.sql.Ref}.
+ *
+ * @return the next attribute as a {@code java.sql.Ref}. {@code null} if the
+ * value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see Ref
+ * @since Android 1.0
+ */
+ public Ref readRef() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.sql.Blob}.
+ *
+ * @return the next attribute as a {@code java.sql.Blob}. {@code null} if
+ * the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public Blob readBlob() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.sql.Clob}.
+ *
+ * @return the next attribute as a {@code java.sql.Clob}. {@code null} if
+ * the value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see Clob
+ * @since Android 1.0
+ */
+ public Clob readClob() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a {@code
+ * java.sql.Array}.
+ *
+ * @return the next attribute as an {@code Array}. {@code null} if the value
+ * is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see Array
+ * @since Android 1.0
+ */
+ public Array readArray() throws SQLException;
+
+ /**
+ * Reports whether the last value read was SQL {@code NULL}.
+ *
+ * @return {@code true} if the last value read was SQL {@code NULL}, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * if there is a database error.
+ * @since Android 1.0
+ */
+ public boolean wasNull() throws SQLException;
+
+ /**
+ * Reads the next attribute in the stream (SQL DATALINK value) and returns
+ * it as a {@code java.net.URL} object.
+ *
+ * @return the next attribute as a {@code java.net.URL}. {@code null} if the
+ * value is SQL {@code NULL}.
+ * @throws SQLException
+ * if there is a database error.
+ * @see java.net.URL
+ * @since Android 1.0
+ */
+ public URL readURL() throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/SQLOutput.java b/sql/src/main/java/java/sql/SQLOutput.java
new file mode 100644
index 0000000..9fded5e
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLOutput.java
@@ -0,0 +1,321 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+
+/**
+ * The interface for an output stream used to write attributes of an SQL User
+ * Defined Type (UDT) to the database. This interface is used for custom
+ * mapping of types and is called by the JDBC driver. It is not intended to be
+ * used by applications.
+ *
+ * When an object which implements the {@code SQLData} interface is used as an
+ * argument to an SQL statement, the JDBC driver calls the method {@code
+ * SQLData.getSQLType} to establish the type of the SQL UDT that is being
+ * passed. The driver then creates an {@code SQLOutput} stream and passes it to
+ * the {@code SQLData.writeSQL} method, which in turn uses the appropriate
+ * {@code SQLOutput} writer methods to write the data from the {@code SQLData}
+ * object into the stream according to the defined mapping.
+ *
+ *
+ * @see SQLData
+ *
+ * @since Android 1.0
+ */
+public interface SQLOutput {
+
+ /**
+ * Write a {@code String} value into the output stream.
+ *
+ * @param theString
+ * the {@code String} to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeString(String theString) throws SQLException;
+
+ /**
+ * Write a {@code boolean} value into the output stream.
+ *
+ * @param theFlag
+ * the {@code boolean} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeBoolean(boolean theFlag) throws SQLException;
+
+ /**
+ * Write a {@code byte} value into the output stream.
+ *
+ * @param theByte
+ * the {@code byte} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeByte(byte theByte) throws SQLException;
+
+ /**
+ * Write a {@code short} value into the output stream.
+ *
+ * @param theShort
+ * the {@code short} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeShort(short theShort) throws SQLException;
+
+ /**
+ * Write an {@code int} value into the output stream.
+ *
+ * @param theInt
+ * the {@code int} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeInt(int theInt) throws SQLException;
+
+ /**
+ * Write a {@code long} value into the output stream.
+ *
+ * @param theLong
+ * the {@code long} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeLong(long theLong) throws SQLException;
+
+ /**
+ * Write a {@code float} value into the output stream.
+ *
+ * @param theFloat
+ * the {@code float} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeFloat(float theFloat) throws SQLException;
+
+ /**
+ * Write a {@code double} value into the output stream.
+ *
+ * @param theDouble
+ * the {@code double} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeDouble(double theDouble) throws SQLException;
+
+ /**
+ * Write a {@code java.math.BigDecimal} value into the output stream.
+ *
+ * @param theBigDecimal
+ * the {@code BigDecimal} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeBigDecimal(BigDecimal theBigDecimal) throws SQLException;
+
+ /**
+ * Write an array of bytes into the output stream.
+ *
+ * @param theBytes
+ * the array of bytes to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeBytes(byte[] theBytes) throws SQLException;
+
+ /**
+ * Write a {@code java.sql.Date} value into the output stream.
+ *
+ * @param theDate
+ * the {@code Date} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Date
+ * @since Android 1.0
+ */
+ public void writeDate(Date theDate) throws SQLException;
+
+ /**
+ * Write a {@code java.sql.Time} value into the output stream.
+ *
+ * @param theTime
+ * the {@code Time} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Time
+ * @since Android 1.0
+ */
+ public void writeTime(Time theTime) throws SQLException;
+
+ /**
+ * Write a {@code java.sql.Timestamp} value into the output stream.
+ *
+ * @param theTimestamp
+ * the {@code Timestamp} value to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Timestamp
+ * @since Android 1.0
+ */
+ public void writeTimestamp(Timestamp theTimestamp) throws SQLException;
+
+ /**
+ * Write a stream of unicode characters into the output stream.
+ *
+ * @param theStream
+ * the stream of unicode characters to write, as a {@code
+ * java.io.Reader} object.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeCharacterStream(Reader theStream) throws SQLException;
+
+ /**
+ * Write a stream of ASCII characters into the output stream.
+ *
+ * @param theStream
+ * the stream of ASCII characters to write, as a {@code
+ * java.io.InputStream} object
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeAsciiStream(InputStream theStream) throws SQLException;
+
+ /**
+ * Write a stream of uninterpreted bytes into the output stream.
+ *
+ * @param theStream
+ * the stream of bytes to write, as a {@code java.io.InputStream}
+ * object
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public void writeBinaryStream(InputStream theStream) throws SQLException;
+
+ /**
+ * Write an {@code SQLData} object into the output stream.
+ *
+ * If the {@code SQLData} object is null, writes {@code NULL} to the stream.
+ *
+ *
+ * Otherwise, calls the {@code SQLData.writeSQL} method of the object, which
+ * writes the object's attributes to the stream by calling the appropriate
+ * SQLOutput writer methods for each attribute, in order. The order of the
+ * attributes is the order they are listed in the SQL definition of the User
+ * Defined Type.
+ *
+ *
+ * @param theObject
+ * the {@code SQLData} object to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see SQLData
+ * @since Android 1.0
+ */
+ public void writeObject(SQLData theObject) throws SQLException;
+
+ /**
+ * Write an SQL {@code Ref} value into the output stream.
+ *
+ * @param theRef
+ * the {@code java.sql.Ref} object to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Ref
+ * @since Android 1.0
+ */
+ public void writeRef(Ref theRef) throws SQLException;
+
+ /**
+ * Write an SQL {@code Blob} value into the output stream.
+ *
+ * @param theBlob
+ * the {@code java.sql.Blob} object to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Blob
+ * @since Android 1.0
+ */
+ public void writeBlob(Blob theBlob) throws SQLException;
+
+ /**
+ * Write an SQL {@code Clob} value into the output stream.
+ *
+ * @param theClob
+ * the {@code java.sql.Clob} object to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Clob
+ * @since Android 1.0
+ */
+ public void writeClob(Clob theClob) throws SQLException;
+
+ /**
+ * Write an SQL {@code Struct} value into the output stream.
+ *
+ * @param theStruct
+ * the {@code java.sql.Struct} object to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Struct
+ * @since Android 1.0
+ */
+ public void writeStruct(Struct theStruct) throws SQLException;
+
+ /**
+ * Write an SQL {@code Array} value into the output stream.
+ *
+ * @param theArray
+ * the {@code java.sql.Array} object to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see Array
+ * @since Android 1.0
+ */
+ public void writeArray(Array theArray) throws SQLException;
+
+ /**
+ * Write an SQL {@code DATALINK} value into the output stream.
+ *
+ * @param theURL
+ * the datalink value as a {@code java.net.URL} to write.
+ * @throws SQLException
+ * if a database error occurs.
+ * @see java.net.URL
+ * @since Android 1.0
+ */
+ public void writeURL(URL theURL) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/SQLPermission.java b/sql/src/main/java/java/sql/SQLPermission.java
new file mode 100644
index 0000000..a9f82d1
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLPermission.java
@@ -0,0 +1,67 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.Serializable;
+import java.security.BasicPermission;
+import java.security.Guard;
+
+/**
+ * A Permission relating to security access control in the {@code java.sql}
+ * package.
+ *
+ * Currently, the only permission supported has the name " {@code setLog}". The
+ * {@code setLog} permission controls whether a Java application or applet can
+ * open a logging stream using the {@code DriverManager.setLogWriter} method or
+ * the {@code DriverManager.setLogStream} method. This is a potentially
+ * dangerous operation since the logging stream can contain sensitive
+ * information such as usernames and passwords.
+ *
+ *
+ * @see DriverManager
+ *
+ * @since Android 1.0
+ */
+public final class SQLPermission extends BasicPermission implements Guard,
+ Serializable {
+
+ private static final long serialVersionUID = -1439323187199563495L;
+
+ /**
+ * Creates a new {@code SQLPermission} object with the specified name.
+ *
+ * @param name
+ * the name to use for this {@code SQLPermission}.
+ */
+ public SQLPermission(String name) {
+ super(name);
+ }
+
+ /**
+ * Creates a new {@code SQLPermission} object with the specified name.
+ *
+ * @param name
+ * is the name of the {@code SQLPermission}. Currently only
+ * {@code "setLog"} is allowed.
+ * @param actions
+ * is currently unused and should be set to {@code null}.
+ */
+ public SQLPermission(String name, String actions) {
+ super(name, null);
+ }
+}
diff --git a/sql/src/main/java/java/sql/SQLWarning.java b/sql/src/main/java/java/sql/SQLWarning.java
new file mode 100644
index 0000000..de94da5
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLWarning.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.io.Serializable;
+
+import org.apache.harmony.sql.internal.nls.Messages;
+
+/**
+ * An exception class that holds information about Database access warnings.
+ *
+ * @since Android 1.0
+ */
+public class SQLWarning extends SQLException implements Serializable {
+
+ private static final long serialVersionUID = 3917336774604784856L;
+
+ /**
+ * Creates an {@code SQLWarning} object. The reason string is set to {@code
+ * null}, the {@code SQLState} string is set to {@code null} and the error
+ * code is set to 0.
+ *
+ * @since Android 1.0
+ */
+ public SQLWarning() {
+ super();
+ }
+
+ /**
+ * Creates an {@code SQLWarning} object. The reason string is set to the
+ * given reason string, the {@code SQLState} string is set to {@code null}
+ * and the error code is set to 0.
+ *
+ * @param theReason
+ * the reason why this warning is issued.
+ * @since Android 1.0
+ */
+ public SQLWarning(String theReason) {
+ super(theReason);
+ }
+
+ /**
+ * Creates an {@code SQLWarning} object. The reason string is set to the
+ * given reason string, the {@code SQLState} string is set to the given
+ * {@code SQLState} string and the error code is set to 0.
+ *
+ * @param theReason
+ * the reason why this warning is issued.
+ * @param theSQLState
+ * the string to use as the {@code SQLState} string.
+ */
+ public SQLWarning(String theReason, String theSQLState) {
+ super(theReason, theSQLState);
+ }
+
+ /**
+ * Creates an {@code SQLWarning} object. The reason string is set to the
+ * given reason string, the {@code SQLState} string is set to the given
+ * {@code SQLState} string and the error code is set to the given error code
+ * value.
+ *
+ * @param theReason
+ * the reason why this warning is issued.
+ * @param theSQLState
+ * the X/Open standard specifc error code.
+ * @param theErrorCode
+ * a vendor specific error code.
+ * @since Android 1.0
+ */
+ public SQLWarning(String theReason, String theSQLState, int theErrorCode) {
+ super(theReason, theSQLState, theErrorCode);
+ }
+
+ /**
+ * Gets the next {@code SQLWarning} chained to this {@code SQLWarning} object.
+ *
+ * @return the {@code SQLWarning} chained to this {@code SQLWarning}.
+ * {@code null} if no {@code SQLWarning} is chained to this {@code
+ * SQLWarning}.
+ * @since Android 1.0
+ */
+ public SQLWarning getNextWarning() {
+ SQLException next = super.getNextException();
+ if (next == null) {
+ return null;
+ }
+ if (next instanceof SQLWarning) {
+ return (SQLWarning) next;
+ }
+ throw new Error(Messages.getString("sql.8")); //$NON-NLS-1$
+ }
+
+ /**
+ * Chains a supplied {@code SQLWarning} to this {@code SQLWarning}.
+ *
+ * @param w
+ * the {@code SQLWarning} linked to this {@code SQLWarning}.
+ * @since Android 1.0
+ */
+ public void setNextWarning(SQLWarning w) {
+ super.setNextException(w);
+ }
+}
diff --git a/sql/src/main/java/java/sql/Savepoint.java b/sql/src/main/java/java/sql/Savepoint.java
new file mode 100644
index 0000000..42b4a17
--- /dev/null
+++ b/sql/src/main/java/java/sql/Savepoint.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+/**
+ * A savepoint is an instant during the current transaction that can be utilized
+ * by a rollback via the {@link Connection#rollback} command. Rolling back to a
+ * particular savepoint means that all changes that occurred after that
+ * savepoint are undone.
+ *
+ * @since Android 1.0
+ */
+public interface Savepoint {
+
+ /**
+ * Returns the constructed ID for this savepoint.
+ *
+ * @return the ID for this savepoint.
+ * @throws SQLException
+ * if an error occurrs accessing the database.
+ * @since Android 1.0
+ */
+ public int getSavepointId() throws SQLException;
+
+ /**
+ * Returns the name for this savepoint.
+ *
+ * @return the name of this savepoint.
+ * @throws SQLException
+ * if an error occurrs accessing the database.
+ * @since Android 1.0
+ */
+ public String getSavepointName() throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/Statement.java b/sql/src/main/java/java/sql/Statement.java
new file mode 100644
index 0000000..4985a9e
--- /dev/null
+++ b/sql/src/main/java/java/sql/Statement.java
@@ -0,0 +1,716 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+/**
+ * Interface used for executing static SQL statements to retrieve query results.
+ * The resulting table rows are returned as {@code ResultSet}s. For any given
+ * {@code Statement} object, only one {@code ResultSet} can be opened at one
+ * time. A call to any of the execution methods of {@code Statement} will cause
+ * any previously created {@code ResultSet} object for that {@code Statement} to
+ * be closed implicitly.
+ *
+ * To have multiple {@code ResultSet} objects opened concurrently, multiple
+ * {@code Statement} objects must be created and then executed.
+ *
+ *
+ * To obtain such an executable statement one needs to invoke {@code
+ * Connection#createStatement}.
+ *
+ *
+ * @see ResultSet
+ * @see Connection#createStatement
+ *
+ * @since Android 1.0
+ */
+public interface Statement {
+
+ /**
+ * Passing this constant to {@link #getMoreResults} implies that all {@code
+ * ResultSet} objects previously kept open should be closed.
+ *
+ * @since Android 1.0
+ */
+ public static final int CLOSE_ALL_RESULTS = 3;
+
+ /**
+ * Passing this constant to {@link #getMoreResults} implies that the current
+ * {@code ResultSet} object should be closed.
+ *
+ * @since Android 1.0
+ */
+ public static final int CLOSE_CURRENT_RESULT = 1;
+
+ /**
+ * Indicates that an error was encountered during execution of a batch
+ * statement.
+ *
+ * @since Android 1.0
+ */
+ public static final int EXECUTE_FAILED = -3;
+
+ /**
+ * Passing this constant to getMoreResults implies that the current
+ * {@code ResultSet} object should not be closed.
+ *
+ * @since Android 1.0
+ */
+ public static final int KEEP_CURRENT_RESULT = 2;
+
+ /**
+ * Indicates that generated keys should not be accessible for retrieval.
+ *
+ * @since Android 1.0
+ */
+ public static final int NO_GENERATED_KEYS = 2;
+
+ /**
+ * Indicates that generated keys should be accessible for retrieval.
+ *
+ * @since Android 1.0
+ */
+ public static final int RETURN_GENERATED_KEYS = 1;
+
+ /**
+ * Indicates that a batch statement was executed with a successful result,
+ * but a count of the number of rows it affected is unavailable.
+ *
+ * @since Android 1.0
+ */
+ public static final int SUCCESS_NO_INFO = -2;
+
+ /**
+ * Adds a specified SQL command to the list of commands for this {@code
+ * Statement}.
+ *
+ * The list of commands is executed by invoking the {@code executeBatch}
+ * method.
+ *
+ *
+ * @param sql
+ * the SQL command as a String. Typically an {@code INSERT} or
+ * {@code UPDATE} statement.
+ * @throws SQLException
+ * if an error occurs accessing the database or the database
+ * does not support batch updates.
+ * @since Android 1.0
+ */
+ public void addBatch(String sql) throws SQLException;
+
+ /**
+ * Cancels this statement's execution if both the database and the JDBC
+ * driver support aborting an SQL statement in flight. This method can be
+ * used by one thread to stop a statement that is executed on another
+ * thread.
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void cancel() throws SQLException;
+
+ /**
+ * Clears the current list of SQL commands for this statement.
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database or the database
+ * does not support batch updates.
+ * @since Android 1.0
+ */
+ public void clearBatch() throws SQLException;
+
+ /**
+ * Clears all {@code SQLWarnings} from this statement.
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void clearWarnings() throws SQLException;
+
+ /**
+ * Releases this statement's database and JDBC driver resources.
+ *
+ * Using this method to release these resources as soon as possible is
+ * strongly recommended.
+ *
+ *
+ * One should not rely on the resources being automatically released when
+ * finalized during garbage collection. Doing so can result in unpredictable
+ * behavior for the application.
+ *
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void close() throws SQLException;
+
+ /**
+ * Executes a supplied SQL statement. This may return multiple {@code
+ * ResultSet}s.
+ *
+ * Use the {@code getResultSet} or {@code getUpdateCount} methods to get the
+ * first result and {@code getMoreResults} to get any subsequent results.
+ *
+ *
+ * @param sql
+ * the SQL statement to execute
+ * @return {@code true} if the first result is a {@code ResultSet}, {@code
+ * false} if the first result is an update count or if there is no
+ * result.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public boolean execute(String sql) throws SQLException;
+
+ /**
+ * Executes a supplied SQL statement. This may return multiple {@code
+ * ResultSet}s. This method allows control of whether auto-generated Keys
+ * should be made available for retrieval, if the SQL statement is an
+ * {@code INSERT} statement.
+ *
+ * Use the {@code getResultSet} or {@code getUpdateCount} methods to get the
+ * first result and {@code getMoreResults} to get any subsequent results.
+ *
+ *
+ * @param sql
+ * the SQL statement to execute.
+ * @param autoGeneratedKeys
+ * a flag indicating whether to make auto generated keys
+ * available for retrieval. This parameter must be one of {@code
+ * Statement.NO_GENERATED_KEYS} or {@code
+ * Statement.RETURN_GENERATED_KEYS}.
+ * @return {@code true} if results exists and the first result is a {@code
+ * ResultSet}, {@code false} if the first result is an update count
+ * or if there is no result.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public boolean execute(String sql, int autoGeneratedKeys)
+ throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. This may return multiple {@code
+ * ResultSet}s. This method allows retrieval of auto generated keys
+ * specified by the supplied array of column indexes, if the SQL statement
+ * is an {@code INSERT} statement.
+ *
+ * Use the {@code getResultSet} or {@code getUpdateCount} methods to get the
+ * first result and {@code getMoreResults} to get any subsequent results.
+ *
+ *
+ * @param sql
+ * the SQL statement to execute.
+ * @param columnIndexes
+ * an array of indexes of the columns in the inserted row which
+ * should be made available for retrieval via the {@code
+ * getGeneratedKeys} method.
+ * @return {@code true} if the first result is a {@code ResultSet}, {@code
+ * false} if the first result is an update count or if there is no
+ * result.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public boolean execute(String sql, int[] columnIndexes) throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. This may return multiple {@code
+ * ResultSet}s. This method allows retrieval of auto generated keys
+ * specified by the supplied array of column indexes, if the SQL statement
+ * is an {@code INSERT} statement.
+ *
+ * Use the {@code getResultSet} or {@code getUpdateCount} methods to get the
+ * first result and {@code getMoreResults} to get any subsequent results.
+ *
+ *
+ * @param sql
+ * the SQL statement to execute.
+ * @param columnNames
+ * an array of column names in the inserted row which should be
+ * made available for retrieval via the {@code getGeneratedKeys}
+ * method.
+ * @return {@code true} if the first result is a {@code ResultSet}, {@code
+ * false} if the first result is an update count or if there is no
+ * result
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public boolean execute(String sql, String[] columnNames)
+ throws SQLException;
+
+ /**
+ * Submits a batch of SQL commands to the database. Returns an array of
+ * update counts, if all the commands execute successfully.
+ *
+ * If one of the commands in the batch fails, this method can throw a
+ * {@link BatchUpdateException} and the JDBC driver may or may not process
+ * the remaining commands. The JDBC driver must behave consistently with the
+ * underlying database, following the "all or nothing" principle. If the
+ * driver continues processing, the array of results returned contains the
+ * same number of elements as there are commands in the batch, with a
+ * minimum of one of the elements having the {@code EXECUTE_FAILED} value.
+ *
+ * @return an array of update counts, with one entry for each command in the
+ * batch. The elements are ordered according to the order in which
+ * the commands were added to the batch.
+ *
+ *
+ *
If the value of an element is ≥ 0, the corresponding
+ * command completed successfully and the value is the update
+ * count (the number of rows in the database affected by the
+ * command) for that command.
+ *
If the value is {@code SUCCESS_NO_INFO}, the command
+ * completed successfully but the number of rows affected is
+ * unknown.
+ *
+ *
If the value is {@code EXECUTE_FAILED}, the command failed.
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public int[] executeBatch() throws SQLException;
+
+ /**
+ * Executes a supplied SQL statement. Returns a single {@code ResultSet}.
+ *
+ * @param sql
+ * an SQL statement to execute. Typically a {@code SELECT}
+ * statement
+ * @return a {@code ResultSet} containing the data produced by the SQL
+ * statement. Never null.
+ * @throws SQLException
+ * if an error occurs accessing the database or if the statement
+ * produces anything other than a single {@code ResultSet}.
+ * @since Android 1.0
+ */
+ public ResultSet executeQuery(String sql) throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. The statement may be an {@code
+ * INSERT}, {@code UPDATE} or {@code DELETE} statement or a statement which
+ * returns nothing.
+ *
+ * @param sql
+ * an SQL statement to execute - an SQL {@code INSERT}, {@code
+ * UPDATE}, {@code DELETE} or a statement which returns nothing
+ * @return the count of updated rows, or 0 for a statement that returns
+ * nothing.
+ * @throws SQLException
+ * if an error occurs accessing the database or if the statement
+ * produces a {@code ResultSet}.
+ * @since Android 1.0
+ */
+ public int executeUpdate(String sql) throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. This method allows control of
+ * whether auto-generated Keys should be made available for retrieval.
+ *
+ * @param sql
+ * an SQL statement to execute - an SQL {@code INSERT}, {@code
+ * UPDATE}, {@code DELETE} or a statement which does not return
+ * anything.
+ * @param autoGeneratedKeys
+ * a flag that indicates whether to allow retrieval of auto
+ * generated keys. Parameter must be one of {@code
+ * Statement.RETURN_GENERATED_KEYS} or {@code
+ * Statement.NO_GENERATED_KEYS}
+ * @return the number of updated rows, or 0 if the statement returns
+ * nothing.
+ * @throws SQLException
+ * if an error occurs accessing the database or if the statement
+ * produces a {@code ResultSet}.
+ * @since Android 1.0
+ */
+ public int executeUpdate(String sql, int autoGeneratedKeys)
+ throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. This method allows retrieval of auto
+ * generated keys specified by the supplied array of column indexes.
+ *
+ * @param sql
+ * an SQL statement to execute - an SQL {@code INSERT}, {@code
+ * UPDATE}, {@code DELETE} or a statement which returns nothing
+ * @param columnIndexes
+ * an array of indexes of the columns in the inserted row which
+ * should be made available for retrieval via the {@code
+ * getGeneratedKeys} method.
+ * @return the count of updated rows, or 0 for a statement that returns
+ * nothing.
+ * @throws SQLException
+ * if an error occurs accessing the database or if the statement
+ * produces a {@code ResultSet}.
+ * @since Android 1.0
+ */
+ public int executeUpdate(String sql, int[] columnIndexes)
+ throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. This method allows retrieval of auto
+ * generated keys specified by the supplied array of column names.
+ *
+ * @param sql
+ * an SQL statement to execute - an SQL {@code INSERT}, {@code
+ * UPDATE}, {@code DELETE} or a statement which returns nothing
+ * @param columnNames
+ * an array of column names in the inserted row which should be
+ * made available for retrieval via the {@code getGeneratedKeys}
+ * method.
+ * @return the count of updated rows, or 0 for a statement that returns
+ * nothing.
+ * @throws SQLException
+ * if an error occurs accessing the database or if the statement
+ * produces a {@code ResultSet}.
+ * @since Android 1.0
+ */
+ public int executeUpdate(String sql, String[] columnNames)
+ throws SQLException;
+
+ /**
+ * Gets the {@code Connection} object which created this statement.
+ *
+ * @return the {@code Connection} through which this statement is
+ * transmitted to the database.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Gets the default direction for fetching rows for {@code ResultSet}s
+ * generated from this statement.
+ *
+ * @return the default fetch direction, one of:
+ *
+ *
ResultSet.FETCH_FORWARD
ResultSet.FETCH_REVERSE
+ *
ResultSet.FETCH_UNKNOWN
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getFetchDirection() throws SQLException;
+
+ /**
+ * Gets the default number of rows for a fetch for the {@code ResultSet}
+ * objects returned from this statement.
+ *
+ * @return the default fetch size for {@code ResultSet}s produced by this
+ * statement.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getFetchSize() throws SQLException;
+
+ /**
+ * Returns auto generated keys created by executing this statement.
+ *
+ * @return a {@code ResultSet} containing the auto generated keys - empty if
+ * no keys are generated by this statement.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public ResultSet getGeneratedKeys() throws SQLException;
+
+ /**
+ * Gets the maximum number of bytes which can be returned as values from
+ * character and binary type columns in a {@code ResultSet} derived from this
+ * statement. This limit applies to {@code BINARY}, {@code VARBINARY},
+ * {@code LONGVARBINARY}, {@code CHAR}, {@code VARCHAR}, and {@code
+ * LONGVARCHAR} types. Any data exceeding the maximum size is abandoned
+ * without announcement.
+ *
+ * @return the current size limit, where {@code 0} means that there is no
+ * limit.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getMaxFieldSize() throws SQLException;
+
+ /**
+ * Gets the maximum number of rows that a {@code ResultSet} can contain when
+ * produced from this statement. If the limit is exceeded, the excess rows
+ * are discarded silently.
+ *
+ * @return the current row limit, where {@code 0} means that there is no
+ * limit.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getMaxRows() throws SQLException;
+
+ /**
+ * Moves to this statement's next result. Returns {@code true} if it is a
+ * {@code ResultSet}. Any current {@code ResultSet} objects previously
+ * obtained with {@code getResultSet()} are closed implicitly.
+ *
+ * @return {@code true} if the next result is a {@code ResultSet}, {@code
+ * false} if the next result is not a {@code ResultSet} or if there
+ * are no more results. Note that if there is no more data, this
+ * method will return {@code false} and {@code getUpdateCount} will
+ * return -1.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public boolean getMoreResults() throws SQLException;
+
+ /**
+ * Moves to this statement's next result. Returns {@code true} if the next
+ * result is a {@code ResultSet}. Any current {@code ResultSet} objects
+ * previously obtained with {@code getResultSet()} are handled as indicated
+ * by a supplied Flag parameter.
+ *
+ * @param current
+ * a flag indicating what to do with existing {@code ResultSet}s.
+ * This parameter must be one of {@code
+ * Statement.CLOSE_ALL_RESULTS}, {@code
+ * Statement.CLOSE_CURRENT_RESULT} or {@code
+ * Statement.KEEP_CURRENT_RESULT}.
+ * @return {@code true} if the next result exists and is a {@code ResultSet}
+ * , {@code false} if the next result is not a {@code ResultSet} or
+ * if there are no more results. Note that if there is no more data,
+ * this method will return {@code false} and {@code getUpdateCount}
+ * will return -1.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public boolean getMoreResults(int current) throws SQLException;
+
+ /**
+ * Gets the timeout value for the statement's execution time. The JDBC
+ * driver will wait up to this value for the execution to complete - after
+ * the limit is exceeded an SQL {@code Exception} is thrown.
+ *
+ * @return the current query timeout value, where {@code 0} indicates that
+ * there is no current timeout.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getQueryTimeout() throws SQLException;
+
+ /**
+ * Gets the current result. Should only be called once per result.
+ *
+ * @return the {@code ResultSet} for the current result. {@code null} if the
+ * result is an update count or if there are no more results.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public ResultSet getResultSet() throws SQLException;
+
+ /**
+ * Gets the concurrency setting for {@code ResultSet} objects generated by
+ * this statement.
+ *
+ * @return {@code ResultSet.CONCUR_READ_ONLY} or {@code
+ * ResultSet.CONCUR_UPDATABLE}.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getResultSetConcurrency() throws SQLException;
+
+ /**
+ * Gets the cursor hold setting for {@code ResultSet} objects generated by
+ * this statement.
+ *
+ * @return {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or {@code
+ * ResultSet.CLOSE_CURSORS_AT_COMMIT}
+ * @throws SQLException
+ * if there is an error while accessing the database.
+ * @since Android 1.0
+ */
+ public int getResultSetHoldability() throws SQLException;
+
+ /**
+ * Gets the {@code ResultSet} type setting for {@code ResultSet}s derived
+ * from this statement.
+ *
+ * @return {@code ResultSet.TYPE_FORWARD_ONLY} for a {@code ResultSet} where
+ * the cursor can only move forwards, {@code
+ * ResultSet.TYPE_SCROLL_INSENSITIVE} for a {@code ResultSet} which
+ * is scrollable but is not sensitive to changes made by others,
+ * {@code ResultSet.TYPE_SCROLL_SENSITIVE} for a {@code ResultSet}
+ * which is scrollable but is sensitive to changes made by others.
+ * @throws SQLException
+ * if there is an error accessing the database.
+ * @since Android 1.0
+ */
+ public int getResultSetType() throws SQLException;
+
+ /**
+ * Gets an update count for the current result if it is not a {@code
+ * ResultSet}.
+ *
+ * @return the current result as an update count. {@code -1} if the current
+ * result is a {@code ResultSet} or if there are no more results.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getUpdateCount() throws SQLException;
+
+ /**
+ * Retrieves the first {@code SQLWarning} reported by calls on this
+ * statement. If there are multiple warnings, subsequent warnings are
+ * chained to the first one. The chain of warnings is cleared each time the
+ * statement is executed.
+ *
+ * Warnings associated with reads from the {@code ResultSet} returned from
+ * executing the statement will be attached to the {@code ResultSet}, not the
+ * statement object.
+ *
+ *
+ * @return an SQLWarning, null if there are no warnings
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * Sets the SQL cursor name. This name is used by subsequent statement
+ * execute methods.
+ *
+ * Cursor names must be unique within one Connection.
+ *
+ *
+ * With the cursor name set, it can then be used in SQL positioned
+ * update or delete statements to determine the current row in a {@code
+ * ResultSet} generated from this statement. The positioned update or delete
+ * must be done with a different statement than this one.
+ *
+ *
+ * @param name
+ * the Cursor name as a string,
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setCursorName(String name) throws SQLException;
+
+ /**
+ * Sets Escape Processing mode.
+ *
+ * If Escape Processing is on, the JDBC driver will do escape substitution
+ * on an SQL statement before sending it for execution. This does not apply
+ * to {@link PreparedStatement}s since they are processed when created,
+ * before this method can be called.
+ *
+ *
+ * @param enable
+ * {@code true} to set escape processing mode on, {@code
+ * false} to turn it off.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setEscapeProcessing(boolean enable) throws SQLException;
+
+ /**
+ * Sets the fetch direction - a hint to the JDBC driver about the direction
+ * of processing of rows in {@code ResultSet}s created by this statement.
+ * The default fetch direction is {@code FETCH_FORWARD}.
+ *
+ * @param direction
+ * which fetch direction to use. This parameter should be one of
+ *
+ *
{@code ResultSet.FETCH_UNKNOWN}
+ *
{@code ResultSet.FETCH_FORWARD}
+ *
{@code ResultSet.FETCH_REVERSE}
+ *
+ * @throws SQLException
+ * if there is an error while accessing the database or if the
+ * fetch direction is unrecognized.
+ */
+ public void setFetchDirection(int direction) throws SQLException;
+
+ /**
+ * Sets the fetch size. This is a hint to the JDBC driver about how many
+ * rows should be fetched from the database when more are required by
+ * application processing.
+ *
+ * @param rows
+ * the number of rows that should be fetched. {@code 0} tells the driver
+ * to ignore the hint. Should be less than {@code getMaxRows} for
+ * this statement. Should not be negative.
+ * @throws SQLException
+ * if an error occurs accessing the database, or if the rows
+ * parameter is out of range.
+ * @since Android 1.0
+ */
+ public void setFetchSize(int rows) throws SQLException;
+
+ /**
+ * Sets the maximum number of bytes for {@code ResultSet} columns that
+ * contain character or binary values. This applies to {@code BINARY},
+ * {@code VARBINARY}, {@code LONGVARBINARY}, {@code CHAR}, {@code VARCHAR},
+ * and {@code LONGVARCHAR} fields. Any data exceeding the maximum size is
+ * abandoned without announcement.
+ *
+ * @param max
+ * the maximum field size in bytes. {@code 0} means "no limit".
+ * @throws SQLException
+ * if an error occurs accessing the database or the {@code max}
+ * value is < {@code 0}.
+ * @since Android 1.0
+ */
+ public void setMaxFieldSize(int max) throws SQLException;
+
+ /**
+ * Sets the maximum number of rows that any {@code ResultSet} can contain.
+ * If the number of rows exceeds this value, the additional rows are
+ * silently discarded.
+ *
+ * @param max
+ * the maximum number of rows. {@code 0} means "no limit".
+ * @throws SQLException
+ * if an error occurs accessing the database or if max < {@code
+ * 0}.
+ * @since Android 1.0
+ */
+ public void setMaxRows(int max) throws SQLException;
+
+ /**
+ * Sets the timeout, in seconds, for queries - how long the driver will
+ * allow for completion of a statement execution. If the timeout is
+ * exceeded, the query will throw an {@code SQLException}.
+ *
+ * @param seconds
+ * timeout in seconds. 0 means no timeout ("wait forever")
+ * @throws SQLException
+ * if an error occurs accessing the database or if seconds <
+ * {@code 0}.
+ * @since Android 1.0
+ */
+ public void setQueryTimeout(int seconds) throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/Struct.java b/sql/src/main/java/java/sql/Struct.java
new file mode 100644
index 0000000..1167cdf
--- /dev/null
+++ b/sql/src/main/java/java/sql/Struct.java
@@ -0,0 +1,73 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.util.Map;
+
+/**
+ * An interface which provides facilities for manipulating an SQL structured type
+ * as a Java object. The {@code Struct} object has a value for each attribute of the SQL structured
+ * type.
+ *
+ * @since Android 1.0
+ */
+public interface Struct {
+
+ /**
+ * Gets the SQL Type name of the SQL structured type that this {@code
+ * Struct} represents.
+ *
+ * @return the fully qualified name of SQL structured type.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public String getSQLTypeName() throws SQLException;
+
+ /**
+ * Gets the values of the attributes of this SQL structured type. This
+ * method uses the type map associated with the {@link Connection} for
+ * customized type mappings. Where there is no entry in the type mapping
+ * which matches this structured type, the JDBC driver uses the standard
+ * mapping.
+ *
+ * @return an {@code Object} array containing the ordered attributes.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Object[] getAttributes() throws SQLException;
+
+ /**
+ * Gets the values of the attributes of this SQL structured type. This
+ * method uses the supplied type mapping to determine how to map SQL types
+ * to their corresponding Java objects. In the
+ * case where there is no entry in the type mapping which matches this
+ * structured type, the JDBC driver uses the default mapping. The {@code
+ * Connection} type map is never utilized by this method.
+ *
+ * @param theMap
+ * a Map describing how SQL Type names are mapped to classes.
+ * @return an Object array containing the ordered attributes,.
+ * @throws SQLException
+ * if a database error occurs.
+ * @since Android 1.0
+ */
+ public Object[] getAttributes(Map> theMap)
+ throws SQLException;
+}
diff --git a/sql/src/main/java/java/sql/Time.java b/sql/src/main/java/java/sql/Time.java
new file mode 100644
index 0000000..7fb28e1
--- /dev/null
+++ b/sql/src/main/java/java/sql/Time.java
@@ -0,0 +1,240 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+/**
+ * Java representation of an SQL {@code TIME} value. Provides utilities to
+ * format and parse the time's representation as a String in JDBC escape format.
+ *
+ * @since Android 1.0
+ */
+public class Time extends Date {
+
+ private static final long serialVersionUID = 8397324403548013681L;
+
+ /**
+ * Constructs a {@code Time} object using the supplied values for Hour,
+ * Minute and Second. The Year, Month and
+ * Day elements of the {@code Time} object are set to the date
+ * of the Epoch (January 1, 1970).
+ *
+ * Any attempt to access the Year, Month or Day
+ * elements of a {@code Time} object will result in an {@code
+ * IllegalArgumentException}.
+ *
+ * The result is undefined if any argument is out of bounds.
+ *
+ *
+ * @deprecated Please use the constructor {@link #Time(long)}.
+ * @param theHour
+ * a value in the range {@code [0,23]}.
+ * @param theMinute
+ * a value in the range {@code [0,59]}.
+ * @param theSecond
+ * a value in the range {@code [0,59]}.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ public Time(int theHour, int theMinute, int theSecond) {
+ super(70, 0, 1, theHour, theMinute, theSecond);
+ }
+
+ /**
+ * Constructs a {@code Time} object using a supplied time specified in
+ * milliseconds.
+ *
+ * @param theTime
+ * a {@code Time} specified in milliseconds since the
+ * Epoch (January 1st 1970, 00:00:00.000).
+ * @since Android 1.0
+ */
+ public Time(long theTime) {
+ super(theTime);
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL
+ * {@code Time} object does not have a {@code Date} component.
+ * @return does not return anything.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getDate() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL
+ * {@code Time} object does not have a Day component.
+ * @return does not return anything.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getDay() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL
+ * {@code Time} object does not have a Month component.
+ * @return does not return anything.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getMonth() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL
+ * {@code Time} object does not have a Year component.
+ * @return does not return anything.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getYear() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL
+ * {@code Time} object does not have a {@code Date} component.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setDate(int i) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL
+ * {@code Time} object does not have a Month component.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setMonth(int i) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL
+ * {@code Time} object does not have a Year component.
+ * @throws IllegalArgumentException
+ * if this method is called.
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setYear(int i) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * Sets the time for this {@code Time} object to the supplied milliseconds
+ * value.
+ *
+ * @param time
+ * A time value expressed as milliseconds since the Epoch.
+ * Negative values are milliseconds before the Epoch. The Epoch
+ * is January 1 1970, 00:00:00.000.
+ * @since Android 1.0
+ */
+ @Override
+ public void setTime(long time) {
+ super.setTime(time);
+ }
+
+ /**
+ * Formats the {@code Time} as a String in JDBC escape format: {@code
+ * hh:mm:ss}.
+ *
+ * @return A String representing the {@code Time} value in JDBC escape
+ * format: {@code HH:mm:ss}
+ * @since Android 1.0
+ */
+ @Override
+ public String toString() {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
+ return dateFormat.format(this);
+ }
+
+ /**
+ * Creates a {@code Time} object from a string holding a time represented in
+ * JDBC escape format: {@code hh:mm:ss}.
+ *
+ * An exception occurs if the input string does not comply with this format.
+ *
+ *
+ * @param timeString
+ * A String representing the time value in JDBC escape format:
+ * {@code hh:mm:ss}.
+ * @return The {@code Time} object set to a time corresponding to the given
+ * time.
+ * @throws IllegalArgumentException
+ * if the supplied time string is not in JDBC escape format.
+ * @since Android 1.0
+ */
+ public static Time valueOf(String timeString) {
+ if (timeString == null) {
+ throw new IllegalArgumentException();
+ }
+ int firstIndex = timeString.indexOf(':');
+ int secondIndex = timeString.indexOf(':', firstIndex + 1);
+ // secondIndex == -1 means none or only one separator '-' has been found.
+ // The string is separated into three parts by two separator characters,
+ // if the first or the third part is null string, we should throw
+ // IllegalArgumentException to follow RI
+ if (secondIndex == -1|| firstIndex == 0 || secondIndex + 1 == timeString.length()) {
+ throw new IllegalArgumentException();
+ }
+ // parse each part of the string
+ int hour = Integer.parseInt(timeString.substring(0, firstIndex));
+ int minute = Integer.parseInt(timeString.substring(firstIndex + 1, secondIndex));
+ int second = Integer.parseInt(timeString.substring(secondIndex + 1, timeString
+ .length()));
+ return new Time(hour, minute, second);
+ }
+}
diff --git a/sql/src/main/java/java/sql/Timestamp.java b/sql/src/main/java/java/sql/Timestamp.java
new file mode 100644
index 0000000..b526fb3
--- /dev/null
+++ b/sql/src/main/java/java/sql/Timestamp.java
@@ -0,0 +1,530 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+import java.text.DecimalFormat;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+
+import org.apache.harmony.sql.internal.nls.Messages;
+
+/**
+ * A Java representation of the SQL {@code TIMESTAMP} type. It provides the
+ * capability of representing the SQL {@code TIMESTAMP} nanosecond value, in
+ * addition to the regular date/time value which has millisecond resolution.
+ *
+ * The {@code Timestamp} class consists of a regular date/time value, where only
+ * the integral seconds value is stored, plus a nanoseconds value where the
+ * fractional seconds are stored.
+ *
+ * The addition of the nanosecond value field to the {@code Timestamp} object
+ * makes it significantly different from the {@code java.util.Date} object which
+ * it extends. Users should be aware that {@code Timestamp} objects are not
+ * interchangable with {@code java.util.Date} objects when used outside the
+ * confines of the {@code java.sql} package.
+ *
+ *
+ * @see Date
+ * @see Time
+ * @see java.util.Date
+ * @since Android 1.0
+ */
+public class Timestamp extends Date {
+
+ private static final long serialVersionUID = 2745179027874758501L;
+
+ // The nanoseconds time value of the Timestamp
+ private int nanos;
+
+ /**
+ * Returns a {@code Timestamp} corresponding to the time specified by the
+ * supplied values for Year, Month, Date, Hour,
+ * Minutes, Seconds and Nanoseconds.
+ *
+ * @deprecated Please use the constructor {@link #Timestamp(long)}.
+ * @param theYear
+ * specified as the year minus 1900.
+ * @param theMonth
+ * specified as an integer in the range [0,11].
+ * @param theDate
+ * specified as an integer in the range [1,31].
+ * @param theHour
+ * specified as an integer in the range [0,23].
+ * @param theMinute
+ * specified as an integer in the range [0,59].
+ * @param theSecond
+ * specified as an integer in the range [0,59].
+ * @param theNano
+ * which defines the nanosecond value of the timestamp specified
+ * as an integer in the range [0,999'999'999]
+ * @throws IllegalArgumentException
+ * if any of the parameters is out of range.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ public Timestamp(int theYear, int theMonth, int theDate, int theHour,
+ int theMinute, int theSecond, int theNano)
+ throws IllegalArgumentException {
+ super(theYear, theMonth, theDate, theHour, theMinute, theSecond);
+ if (theNano < 0 || theNano > 999999999) {
+ throw new IllegalArgumentException();
+ }
+ nanos = theNano;
+ }
+
+ /**
+ * Returns a {@code Timestamp} object corresponding to the time represented
+ * by a supplied time value.
+ *
+ * @param theTime
+ * a time value in the format of milliseconds since the Epoch
+ * (January 1 1970 00:00:00.000 GMT).
+ * @since Android 1.0
+ */
+ public Timestamp(long theTime) {
+ super(theTime);
+ /*
+ * Now set the time for this Timestamp object - which deals with the
+ * nanosecond value as well as the base time
+ */
+ this.setTime(theTime);
+ }
+
+ /**
+ * Returns {@code true} if this timestamp object is later than the supplied
+ * timestamp, otherwise returns {@code false}.
+ *
+ * @param theTimestamp
+ * the timestamp to compare with this timestamp object.
+ * @return {@code true} if this {@code Timestamp} object is later than the
+ * supplied timestamp, {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean after(Timestamp theTimestamp) {
+ long thisTime = this.getTime();
+ long compareTime = theTimestamp.getTime();
+
+ // If the time value is later, the timestamp is later
+ if (thisTime > compareTime) {
+ return true;
+ }
+ // If the time value is earlier, the timestamp is not later
+ else if (thisTime < compareTime) {
+ return false;
+ }
+ /*
+ * Otherwise the time values are equal in which case the nanoseconds
+ * value determines whether this timestamp is later...
+ */
+ else if (this.getNanos() > theTimestamp.getNanos()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Returns {@code true} if this {@code Timestamp} object is earlier than the
+ * supplied timestamp, otherwise returns {@code false}.
+ *
+ * @param theTimestamp
+ * the timestamp to compare with this {@code Timestamp} object.
+ * @return {@code true} if this {@code Timestamp} object is earlier than the
+ * supplied timestamp, {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean before(Timestamp theTimestamp) {
+ long thisTime = this.getTime();
+ long compareTime = theTimestamp.getTime();
+
+ // If the time value is later, the timestamp is later
+ if (thisTime < compareTime) {
+ return true;
+ }
+ // If the time value is earlier, the timestamp is not later
+ else if (thisTime > compareTime) {
+ return false;
+ }
+ /*
+ * Otherwise the time values are equal in which case the nanoseconds
+ * value determines whether this timestamp is later...
+ */
+ else if (this.getNanos() < theTimestamp.getNanos()) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ /**
+ * Compares this {@code Timestamp} object with a supplied {@code Timestamp}
+ * object.
+ *
+ * @param theObject
+ * the timestamp to compare with this {@code Timestamp} object,
+ * passed as an {@code Object}.
+ * @return
+ *
+ * {@code 0} if the two {@code Timestamp} objects are equal in time
+ *
+ *
+ * a value {@code < 0} if this {@code Timestamp} object is before
+ * the supplied {@code Timestamp} and a value
+ *
+ *
+ * {@code > 0} if this {@code Timestamp} object is after the
+ * supplied {@code Timestamp}
+ *
+ *
+ * @throws ClassCastException
+ * if the supplied object is not a {@code Timestamp} object.
+ * @since Android 1.0
+ */
+ @Override
+ public int compareTo(Date theObject) throws ClassCastException {
+ return this.compareTo((Timestamp) theObject);
+ }
+
+ /**
+ * Compares this {@code Timestamp} object with a supplied {@code Timestamp}
+ * object.
+ *
+ * @param theTimestamp
+ * the timestamp to compare with this {@code Timestamp} object,
+ * passed in as a {@code Timestamp}.
+ * @return one of the following:
+ *
+ *
{@code 0}, if the two {@code Timestamp} objects are
+ * equal in time
+ *
{@code < 0}, if this {@code Timestamp} object is before the
+ * supplied {@code Timestamp}
+ *
{@code > 0}, if this {@code Timestamp} object is after the
+ * supplied {@code Timestamp}
+ *
+ * @since Android 1.0
+ */
+ public int compareTo(Timestamp theTimestamp) {
+ int result = super.compareTo(theTimestamp);
+ if (result == 0) {
+ int thisNano = this.getNanos();
+ int thatNano = theTimestamp.getNanos();
+ if (thisNano > thatNano) {
+ return 1;
+ } else if (thisNano == thatNano) {
+ return 0;
+ } else {
+ return -1;
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Tests to see if this timestamp is equal to a supplied object.
+ *
+ * @param theObject
+ * the object to which this timestamp is compared.
+ * @return {@code true} if this {@code Timestamp} object is equal to the
+ * supplied {@code Timestamp} object {@code false} if the object
+ * is not a {@code Timestamp} object or if the object is a {@code
+ * Timestamp} but represents a different instant in time.
+ * @since Android 1.0
+ */
+ @Override
+ public boolean equals(Object theObject) {
+ if (theObject instanceof Timestamp) {
+ return equals((Timestamp) theObject);
+ }
+ return false;
+ }
+
+ /**
+ * Tests to see if this timestamp is equal to a supplied timestamp.
+ *
+ * @param theTimestamp
+ * the timestamp to compare with this {@code Timestamp} object,
+ * passed as an {@code Object}.
+ * @return {@code true} if this {@code Timestamp} object is equal to the
+ * supplied {@code Timestamp} object, {@code false} otherwise.
+ * @since Android 1.0
+ */
+ public boolean equals(Timestamp theTimestamp) {
+ if (theTimestamp == null) {
+ return false;
+ }
+ return (this.getTime() == theTimestamp.getTime())
+ && (this.getNanos() == theTimestamp.getNanos());
+ }
+
+ /**
+ * Gets this {@code Timestamp}'s nanosecond value
+ *
+ * @return The timestamp's nanosecond value, an integer between 0 and
+ * 999,999,999.
+ * @since Android 1.0
+ */
+ public int getNanos() {
+ return nanos;
+ }
+
+ /**
+ * Returns the time represented by this {@code Timestamp} object, as a long
+ * value containing the number of milliseconds since the Epoch (January 1
+ * 1970, 00:00:00.000 GMT).
+ *
+ * @return the number of milliseconds that have passed since January 1 1970,
+ * 00:00:00.000 GMT.
+ * @since Android 1.0
+ */
+ @Override
+ public long getTime() {
+ long theTime = super.getTime();
+ theTime = theTime + (nanos / 1000000);
+ return theTime;
+ }
+
+ /**
+ * Sets the nanosecond value for this {@code Timestamp}.
+ *
+ * @param n
+ * number of nanoseconds.
+ * @throws IllegalArgumentException
+ * if number of nanoseconds smaller than 0 or greater than
+ * 999,999,999.
+ * @since Android 1.0
+ */
+ public void setNanos(int n) throws IllegalArgumentException {
+ if ((n < 0) || (n > 999999999)) {
+ // sql.0=Value out of range
+ throw new IllegalArgumentException(Messages.getString("sql.0")); //$NON-NLS-1$
+ }
+ nanos = n;
+ }
+
+ /**
+ * Sets the time represented by this {@code Timestamp} object to the
+ * supplied time, defined as the number of milliseconds since the Epoch
+ * (January 1 1970, 00:00:00.000 GMT).
+ *
+ * @param theTime
+ * number of milliseconds since the Epoch (January 1 1970,
+ * 00:00:00.000 GMT).
+ * @since Android 1.0
+ */
+ @Override
+ public void setTime(long theTime) {
+ /*
+ * Deal with the nanoseconds value. The supplied time is in milliseconds -
+ * so we must extract the milliseconds value and multiply by 1000000 to
+ * get nanoseconds. Things are more complex if theTime value is
+ * negative, since then the time value is the time before the Epoch but
+ * the nanoseconds value of the Timestamp must be positive - so we must
+ * take the "raw" milliseconds value and subtract it from 1000 to get to
+ * the true nanoseconds value Simultaneously, recalculate the time value
+ * to the exact nearest second and reset the Date time value
+ */
+ int milliseconds = (int) (theTime % 1000);
+ theTime = theTime - milliseconds;
+ if (milliseconds < 0) {
+ theTime = theTime - 1000;
+ milliseconds = 1000 + milliseconds;
+ }
+ super.setTime(theTime);
+ setNanos(milliseconds * 1000000);
+ }
+
+ /**
+ * Returns the timestamp formatted as a String in the JDBC Timestamp Escape
+ * format, which is {@code "yyyy-mm-dd hh:mm:ss.nnnnnnnnn"}.
+ *
+ * @return A string representing the instant defined by the {@code
+ * Timestamp}, in JDBC Timestamp escape format.
+ * @since Android 1.0
+ */
+ @SuppressWarnings("deprecation")
+ @Override
+ public String toString() {
+ /*
+ * Use a DecimalFormat to lay out the nanosecond value as a simple
+ * string of 9 integers, with leading Zeros
+ */
+ DecimalFormat decimalFormat = new DecimalFormat("0"); //$NON-NLS-1$
+ decimalFormat.setMinimumIntegerDigits(9);
+ decimalFormat.setMaximumIntegerDigits(9);
+ String theNanos = decimalFormat.format(nanos);
+ theNanos = stripTrailingZeros(theNanos);
+
+ String year = format((getYear() + 1900), 4);
+ String month = format((getMonth() + 1), 2);
+ String date = format(getDate(), 2);
+ String hours = format(getHours(), 2);
+ String minutes = format(getMinutes(), 2);
+ String seconds = format(getSeconds(), 2);
+
+ return year + '-' + month + '-' + date + ' ' + hours + ':' + minutes
+ + ':' + seconds + '.' + theNanos;
+ }
+
+ /*
+ * Private method to format the time
+ */
+ private String format(int date, int digits) {
+ StringBuilder dateStringBuffer = new StringBuilder(String.valueOf(date));
+ while (dateStringBuffer.length() < digits) {
+ dateStringBuffer = dateStringBuffer.insert(0,'0');
+ }
+ return dateStringBuffer.toString();
+ }
+
+ /*
+ * Private method to strip trailing '0' characters from a string. @param
+ * inputString the starting string @return a string with the trailing zeros
+ * stripped - will leave a single 0 at the beginning of the string
+ */
+ private String stripTrailingZeros(String inputString) {
+ String finalString;
+
+ int i;
+ for (i = inputString.length(); i > 0; i--) {
+ if (inputString.charAt(i - 1) != '0') {
+ break;
+ }
+ /*
+ * If the string has a 0 as its first character, return a string
+ * with a single '0'
+ */
+ if (i == 1) {
+ return "0"; //$NON-NLS-1$
+ }
+ }
+
+ finalString = inputString.substring(0, i);
+ return finalString;
+ }
+
+ /**
+ * Creates a {@code Timestamp} object with a time value equal to the time
+ * specified by a supplied String holding the time in JDBC timestamp escape
+ * format, which is {@code "yyyy-mm-dd hh:mm:ss.nnnnnnnnn}"
+ *
+ * @param s
+ * the {@code String} containing a time in JDBC timestamp escape
+ * format.
+ * @return A {@code Timestamp} object with time value as defined by the
+ * supplied {@code String}.
+ * @throws IllegalArgumentException
+ * if the provided string is {@code null}.
+ * @since Android 1.0
+ */
+ public static Timestamp valueOf(String s) throws IllegalArgumentException {
+ if (s == null) {
+ // sql.3=Argument cannot be null
+ throw new IllegalArgumentException(Messages.getString("sql.3")); //$NON-NLS-1$
+ }
+
+ SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //$NON-NLS-1$
+ ParsePosition pp = new ParsePosition(0);
+
+ /*
+ * First parse out the yyyy-MM-dd HH:mm:ss component of the String into
+ * a Date object using the SimpleDateFormat. This should stop after the
+ * seconds value, according to the definition of SimpleDateFormat.parse,
+ * with the ParsePosition indicating the index of the "." which should
+ * precede the nanoseconds value
+ */
+ Date theDate;
+ try {
+ theDate = df.parse(s, pp);
+ } catch (Exception e) {
+ throw new IllegalArgumentException(Messages.getString("sql.2")); //$NON-NLS-1$
+ }
+
+ if (theDate == null) {
+ throw new IllegalArgumentException(Messages.getString("sql.2")); //$NON-NLS-1$
+ }
+
+ /*
+ * If we get here, the Date part of the string was OK - now for the
+ * nanoseconds value. Strictly, this requires the remaining part of the
+ * String to look like ".nnnnnnnnn". However, we accept anything with a
+ * '.' followed by 1 to 9 digits - we also accept nothing (no fractions
+ * of a second). Anything else is interpreted as incorrect format which
+ * will generate an IllegalArgumentException
+ */
+ int position = pp.getIndex();
+ int remaining = s.length() - position;
+ int theNanos;
+
+ if (remaining == 0) {
+ // First, allow for the case where no fraction of a second is given:
+ theNanos = 0;
+ } else {
+ /*
+ * Case where fraction of a second is specified: Require 1 character
+ * plus the "." in the remaining part of the string...
+ */
+ if ((s.length() - position) < ".n".length()) { //$NON-NLS-1$
+ throw new IllegalArgumentException(Messages.getString("sql.2")); //$NON-NLS-1$
+ }
+
+ /*
+ * If we're strict, we should not allow any EXTRA characters after
+ * the 9 digits
+ */
+ if ((s.length() - position) > ".nnnnnnnnn".length()) { //$NON-NLS-1$
+ throw new IllegalArgumentException(Messages.getString("sql.2")); //$NON-NLS-1$
+ }
+
+ // Require the next character to be a "."
+ if (s.charAt(position) != '.') {
+ // sql.4=Bad input string format: expected '.' not {0}
+ throw new NumberFormatException(Messages.getString("sql.4", s.charAt(position))); //$NON-NLS-1$
+ }
+ // Get the length of the number string - need to account for the '.'
+ int nanoLength = s.length() - position - 1;
+
+ // Get the 9 characters following the "." as an integer
+ String theNanoString = s.substring(position + 1, position + 1
+ + nanoLength);
+ /*
+ * We must adjust for the cases where the nanos String was not 9
+ * characters long by padding out with zeros
+ */
+ theNanoString = theNanoString + "000000000"; //$NON-NLS-1$
+ theNanoString = theNanoString.substring(0, 9);
+
+ try {
+ theNanos = Integer.parseInt(theNanoString);
+ } catch (Exception e) {
+ // If we get here, the string was not a number
+ throw new IllegalArgumentException(Messages.getString("sql.2")); //$NON-NLS-1$
+ }
+ }
+
+ if (theNanos < 0 || theNanos > 999999999) {
+ throw new IllegalArgumentException(Messages.getString("sql.2")); //$NON-NLS-1$
+ }
+
+ Timestamp theTimestamp = new Timestamp(theDate.getTime());
+ theTimestamp.setNanos(theNanos);
+
+ return theTimestamp;
+ }
+}
diff --git a/sql/src/main/java/java/sql/Types.java b/sql/src/main/java/java/sql/Types.java
new file mode 100644
index 0000000..8ce0421
--- /dev/null
+++ b/sql/src/main/java/java/sql/Types.java
@@ -0,0 +1,247 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package java.sql;
+
+/**
+ * A class which defines constants used to identify generic SQL types, also
+ * called JDBC types. The type constant values are equivalent to those defined
+ * by X/OPEN.
+ *
+ * @since Android 1.0
+ */
+public class Types {
+
+ /*
+ * Private constructor to prevent instantiation.
+ */
+ private Types() {
+ super();
+ }
+
+ /**
+ * The type code that identifies the SQL type {@code ARRAY}.
+ *
+ * @since Android 1.0
+ */
+ public static final int ARRAY = 2003;
+
+ /**
+ * The type code that identifies the SQL type {@code BIGINT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int BIGINT = -5;
+
+ /**
+ * The type code that identifies the SQL type {@code BINARY}.
+ *
+ * @since Android 1.0
+ */
+ public static final int BINARY = -2;
+
+ /**
+ * The type code that identifies the SQL type {@code BIT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int BIT = -7;
+
+ /**
+ * The type code that identifies the SQL type {@code BLOB}.
+ *
+ * @since Android 1.0
+ */
+ public static final int BLOB = 2004;
+
+ /**
+ * The type code that identifies the SQL type {@code BOOLEAN}.
+ *
+ * @since Android 1.0
+ */
+ public static final int BOOLEAN = 16;
+
+ /**
+ * The type code that identifies the SQL type {@code CHAR}.
+ *
+ * @since Android 1.0
+ */
+ public static final int CHAR = 1;
+
+ /**
+ * The type code that identifies the SQL type {@code CLOB}.
+ *
+ * @since Android 1.0
+ */
+ public static final int CLOB = 2005;
+
+ /**
+ * The type code that identifies the SQL type {@code DATALINK}.
+ *
+ * @since Android 1.0
+ */
+ public static final int DATALINK = 70;
+
+ /**
+ * The type code that identifies the SQL type {@code DATE}.
+ *
+ * @since Android 1.0
+ */
+ public static final int DATE = 91;
+
+ /**
+ * The type code that identifies the SQL type {@code DECIMAL}.
+ *
+ * @since Android 1.0
+ */
+ public static final int DECIMAL = 3;
+
+ /**
+ * The type code that identifies the SQL type {@code DISTINCT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int DISTINCT = 2001;
+
+ /**
+ * The type code that identifies the SQL type {@code DOUBLE}.
+ *
+ * @since Android 1.0
+ */
+ public static final int DOUBLE = 8;
+
+ /**
+ * The type code that identifies the SQL type {@code FLOAT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int FLOAT = 6;
+
+ /**
+ * The type code that identifies the SQL type {@code INTEGER}.
+ *
+ * @since Android 1.0
+ */
+ public static final int INTEGER = 4;
+
+ /**
+ * The type code that identifies the SQL type {@code JAVA_OBJECT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int JAVA_OBJECT = 2000;
+
+ /**
+ * The type code that identifies the SQL type {@code LONGVARBINARY}.
+ *
+ * @since Android 1.0
+ */
+ public static final int LONGVARBINARY = -4;
+
+ /**
+ * The type code that identifies the SQL type {@code LONGVARCHAR}.
+ *
+ * @since Android 1.0
+ */
+ public static final int LONGVARCHAR = -1;
+
+ /**
+ * The type code that identifies the SQL type {@code NULL}.
+ *
+ * @since Android 1.0
+ */
+ public static final int NULL = 0;
+
+ /**
+ * The type code that identifies the SQL type {@code NUMERIC}.
+ *
+ * @since Android 1.0
+ */
+ public static final int NUMERIC = 2;
+
+ /**
+ * The type code that identifies that the SQL type is database specific and
+ * is mapped to a Java object, accessed via the methods
+ * {@code getObject} and {@code setObject}.
+ *
+ * @since Android 1.0
+ */
+ public static final int OTHER = 1111;
+
+ /**
+ * The type code that identifies the SQL type {@code REAL}.
+ *
+ * @since Android 1.0
+ */
+ public static final int REAL = 7;
+
+ /**
+ * The type code that identifies the SQL type {@code REF}.
+ *
+ * @since Android 1.0
+ */
+ public static final int REF = 2006;
+
+ /**
+ * The type code that identifies the SQL type {@code SMALLINT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int SMALLINT = 5;
+
+ /**
+ * The type code that identifies the SQL type {@code STRUCT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int STRUCT = 2002;
+
+ /**
+ * The type code that identifies the SQL type {@code TIME}.
+ *
+ * @since Android 1.0
+ */
+ public static final int TIME = 92;
+
+ /**
+ * The type code that identifies the SQL type {@code TIMESTAMP}.
+ *
+ * @since Android 1.0
+ */
+ public static final int TIMESTAMP = 93;
+
+ /**
+ * The type code that identifies the SQL type {@code TINYINT}.
+ *
+ * @since Android 1.0
+ */
+ public static final int TINYINT = -6;
+
+ /**
+ * The type code that identifies the SQL type {@code VARBINARY}.
+ *
+ * @since Android 1.0
+ */
+ public static final int VARBINARY = -3;
+
+ /**
+ * The type code that identifies the SQL type {@code VARCHAR}.
+ *
+ * @since Android 1.0
+ */
+ public static final int VARCHAR = 12;
+}
diff --git a/sql/src/main/java/java/sql/package.html b/sql/src/main/java/java/sql/package.html
new file mode 100644
index 0000000..9ae2488
--- /dev/null
+++ b/sql/src/main/java/java/sql/package.html
@@ -0,0 +1,8 @@
+
+
+
+ Provides a standard interface for accessing SQL-based databases.
+
+ @since Android 1.0
+
+
\ No newline at end of file
diff --git a/sql/src/main/java/javax/sql/ConnectionEvent.java b/sql/src/main/java/javax/sql/ConnectionEvent.java
new file mode 100644
index 0000000..e07e7c1
--- /dev/null
+++ b/sql/src/main/java/javax/sql/ConnectionEvent.java
@@ -0,0 +1,79 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.util.EventObject;
+import java.sql.SQLException;
+import java.io.Serializable;
+
+/**
+ * Sent when specific events happen on a {@link PooledConnection} object. These
+ * events are a facility to report when an application closes the pooled
+ * connection or when an error occurs in the pooled connection.
+ *
+ * @since Android 1.0
+ */
+public class ConnectionEvent extends EventObject implements Serializable {
+
+ private static final long serialVersionUID = -4843217645290030002L;
+
+ private SQLException theSQLException;
+
+ /**
+ * Creates a connection event initialized with the supplied {@code
+ * PooledConnection} reporting that the application has closed the
+ * connection.
+ *
+ * @param theConnection
+ * the connection for which this event is created.
+ * @since Android 1.0
+ */
+ public ConnectionEvent(PooledConnection theConnection) {
+ super(theConnection);
+ }
+
+ /**
+ * Creates a {@code ConnectionEvent} initialized with the supplied {@code
+ * PooledConnection} and with the supplied {@code SQLException} indicating
+ * that an error has occurred within the {@code PooledConnection}.
+ *
+ * @param theConnection
+ * the connection for which this event is created.
+ * @param theException
+ * information about the state of error that has occurred on the
+ * application side.
+ * @since Android 1.0
+ */
+ public ConnectionEvent(PooledConnection theConnection,
+ SQLException theException) {
+ super(theConnection);
+ theSQLException = theException;
+ }
+
+ /**
+ * Gets the {@code SQLException} which holds information about the error
+ * which occurred in the {@code PooledConnection}.
+ *
+ * @return a {@code SQLException} containing information about the error.
+ * May be {@code null} if no error has occurred.
+ * @since Android 1.0
+ */
+ public SQLException getSQLException() {
+ return theSQLException;
+ }
+}
diff --git a/sql/src/main/java/javax/sql/ConnectionEventListener.java b/sql/src/main/java/javax/sql/ConnectionEventListener.java
new file mode 100644
index 0000000..1333814
--- /dev/null
+++ b/sql/src/main/java/javax/sql/ConnectionEventListener.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.util.EventListener;
+
+/**
+ * An interface used to receive events generated by a {@link PooledConnection}.
+ *
+ * This interface would typically be implemented by a component which manages a
+ * connection pool (a connection pool manager). A connection triggers an event
+ * to a {@code ConnectionEventListener} either when the application closes a
+ * connection it has been using or when a significant error occurs while the
+ * connection is being used.
+ *
+ *
+ * The connection pool manager can return closed connections to the pool for
+ * later reuse. Connections experiencing an error should be discarded.
+ *
+ *
+ * @since Android 1.0
+ */
+public interface ConnectionEventListener extends EventListener {
+
+ /**
+ * Notifies the {@code ConnectionEventListener} that an application has
+ * called the {@code close} method on a pooled connection.
+ *
+ * @param theEvent
+ * a {@code ConnectionEvent} containing details about the source
+ * of the event.
+ * @since Android 1.0
+ */
+ public void connectionClosed(ConnectionEvent theEvent);
+
+ /**
+ * Notifies the {@code ConnectionEventListener} that an error has occurred
+ * on a {@code PooledConnection}. This notification is triggered before the
+ * {@code SQLException}, which is available through the event argument, is
+ * thrown.
+ *
+ * @param theEvent
+ * a {@code ConnectionEvent} containing details about the source
+ * of the event and the {@code SQLException} that has occurred.
+ * @since Android 1.0
+ */
+ public void connectionErrorOccurred(ConnectionEvent theEvent);
+}
diff --git a/sql/src/main/java/javax/sql/ConnectionPoolDataSource.java b/sql/src/main/java/javax/sql/ConnectionPoolDataSource.java
new file mode 100644
index 0000000..d73128b
--- /dev/null
+++ b/sql/src/main/java/javax/sql/ConnectionPoolDataSource.java
@@ -0,0 +1,137 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.sql.SQLException;
+import java.io.PrintWriter;
+
+/**
+ * An interface for the creation of {@code ConnectionPoolDataSource} objects.
+ * Used internally within the package.
+ *
+ * A class which implements the {@code ConnectionPoolDataSource} interface is
+ * typically registered with a JNDI naming service directory and is retrieved
+ * from there by name.
+ *
+ *
+ * @since Android 1.0
+ */
+public interface ConnectionPoolDataSource {
+
+ /**
+ * Gets the login timeout value for this {@code ConnectionPoolDataSource}.
+ * The login timeout is the maximum time in seconds that the {@code
+ * ConnectionPoolDataSource} will wait when opening a connection to a
+ * database. A timeout value of 0 implies either the system default timeout
+ * value (if there is one) or that there is no timeout. The default value
+ * for the login timeout is {@code 0}.
+ *
+ * @return the login timeout value in seconds.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public int getLoginTimeout() throws SQLException;
+
+ /**
+ * Gets the log writer for this {@code ConnectionPoolDataSource}.
+ *
+ * The log writer is a stream to which all log and trace messages are sent
+ * from this {@code ConnectionPoolDataSource}. The log writer can be {@code
+ * null}, in which case the log and trace capture is disabled. The default
+ * value for the log writer when an {@code ConnectionPoolDataSource} is
+ * created is {@code null}. Note that the log writer for an {@code
+ * ConnectionPoolDataSource} is not the same as the log writer used by a
+ * {@code DriverManager}.
+ *
+ *
+ * @return a {@code PrintWriter} which is the log writer for this {@code
+ * ConnectionPoolDataSource}. Can be {@code null}, in which case log
+ * writing is disabled for this {@code ConnectionPoolDataSource}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public PrintWriter getLogWriter() throws SQLException;
+
+ /**
+ * Creates a connection to a database which can then be used as a pooled
+ * connection.
+ *
+ * @return a {@code PooledConnection} which represents the connection to the
+ * database.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public PooledConnection getPooledConnection() throws SQLException;
+
+ /**
+ * Creates a connection to a database, using the supplied user name and
+ * password, which can then be used as a pooled connection.
+ *
+ * @param theUser
+ * the a user name for the database login.
+ * @param thePassword
+ * the password associated with the user identified by {@code
+ * theUser}.
+ * @return a {@code PooledConnection} object which represents the connection
+ * to the database.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public PooledConnection getPooledConnection(String theUser,
+ String thePassword) throws SQLException;
+
+ /**
+ * Sets the login timeout value for this {@code ConnectionPoolDataSource}.
+ * The login timeout is the maximum time in seconds that the {@code
+ * ConnectionPoolDataSource} will wait when opening a connection to a
+ * database. A timeout value of 0 implies either the system default timeout
+ * value (if there is one) or that there is no timeout. The default value
+ * for the login timeout is 0.
+ *
+ * @param theTimeout
+ * the new login timeout value in seconds.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void setLoginTimeout(int theTimeout) throws SQLException;
+
+ /**
+ * Sets the log writer for this {@code ConnectionPoolDataSource}.
+ *
+ * The log writer is a stream to which all log and trace messages are sent
+ * from this {@code ConnectionPoolDataSource}. The log writer can be {@code
+ * null}, in which case log and trace capture is disabled. The default value
+ * for the log writer, when a {@code ConnectionPoolDataSource} is created,
+ * is {@code null}. Note that the log writer for a {@code
+ * ConnectionPoolDataSource} is not the same as the log writer used by a
+ * {@code DriverManager}.
+ *
+ *
+ * @param theWriter
+ * is the log writer for this {@code ConnectionPoolDataSource}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void setLogWriter(PrintWriter theWriter) throws SQLException;
+}
diff --git a/sql/src/main/java/javax/sql/DataSource.java b/sql/src/main/java/javax/sql/DataSource.java
new file mode 100644
index 0000000..98be761
--- /dev/null
+++ b/sql/src/main/java/javax/sql/DataSource.java
@@ -0,0 +1,158 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.io.PrintWriter;
+
+/**
+ * An interface for the creation of {@code Connection} objects which represent a
+ * connection to a database. This interface is an alternative to the {@code
+ * java.sql.DriverManager}.
+ *
+ * A class which implements the {@code DataSource} interface is typically
+ * registered with a JNDI naming service directory and is retrieved from there
+ * by name.
+ *
+ *
+ * The {@code DataSource} interface is typically implemented by the writer of a
+ * JDBC driver. There are three variants of the {@code DataSource} interface,
+ * which produce connections with different characteristics:
+ *
+ *
+ *
Standard {@code DataSource}: produces standard {@code Connection}
+ * objects with no special features.
+ *
Connection Pool {@code DataSource}: produces {@code
+ * PooledConnection} objects which require a connection pool manager as an
+ * intermediary component.
+ *
Distributed transaction {@code DataSource} ("XADataSource"):
+ * produces {@code XAConnection} objects which can be used to handle distributed
+ * transactions which typically require an intermediary transaction manager
+ * component. {@code XAConnection} objects also provide connection pooling
+ * capabilities as well as distributed transaction capabilities.
+ *
+ *
+ * Note that a JDBC driver which is accessed via the {@code DataSource}
+ * interface is loaded via a JNDI lookup process. A driver loaded in this way
+ * does not register itself with the {@code DriverManager}.
+ *
+ *
+ * @since Android 1.0
+ */
+public interface DataSource {
+
+ /**
+ * Creates a connection to the database represented by this {@code
+ * DataSource}.
+ *
+ * @return a {@code Connection} object which is a connection to the
+ * database.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Creates a connection to the database represented by this {@code
+ * DataSource}, using the supplied user name and password.
+ *
+ * @param theUsername
+ * the a user name for the database login.
+ * @param thePassword
+ * the password associated with the user identified by {@code
+ * theUsername}.
+ * @return the {@code Connection} object which is the connection to the
+ * database.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Connection getConnection(String theUsername, String thePassword)
+ throws SQLException;
+
+ /**
+ * Gets the login timeout value for this {@code DataSource}. The login
+ * timeout is the maximum time in seconds that the {@code DataSource} will
+ * wait when opening a connection to a database. A timeout value of 0
+ * implies either the system default timeout value (if there is one) or that
+ * there is no timeout. The default value for the login timeout is 0.
+ *
+ * @return the login timeout value in seconds.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public int getLoginTimeout() throws SQLException;
+
+ /**
+ * Gets the log writer for this {@code DataSource}.
+ *
+ * The log writer is a stream to which all log and trace messages are sent
+ * from this {@code DataSource}. The log writer can be {@code null}, in
+ * which case, log and trace capture is disabled. The default value for the
+ * log writer when an {@code DataSource} is created is {@code null}. Note
+ * that the log writer for a {@code DataSource} is not the same as the log
+ * writer used by a {@code DriverManager}.
+ *
+ *
+ * @return a {@code PrintWriter} which is the log writer for this {@code
+ * DataSource}. Can be {@code null}, in which case log writing is
+ * disabled for this {@code DataSource}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public PrintWriter getLogWriter() throws SQLException;
+
+ /**
+ * Sets the login timeout value for this {@code DataSource}. The login
+ * timeout is the maximum time in seconds that the {@code DataSource} will
+ * wait when opening a connection to a database. A timeout value of 0
+ * implies either the system default timeout value (if there is one) or that
+ * there is no timeout. The default value for the login timeout is 0.
+ *
+ * @param theTimeout
+ * the new login timeout value in seconds.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void setLoginTimeout(int theTimeout) throws SQLException;
+
+ /**
+ * Sets the log writer for this {@code DataSource}.
+ *
+ * The log writer is a stream to which all log and trace messages are sent
+ * from this {@code DataSource}. The log writer can be {@code null}, in
+ * which case, log and trace capture is disabled. The default value for the
+ * log writer when a {@code DataSource} is created is {@code null}. Note
+ * that the log writer for a {@code DataSource} is not the same as the log
+ * writer used by a {@code DriverManager}.
+ *
+ *
+ * @param theWriter
+ * a {@code PrintWriter} to use as the log writer for this
+ * {@code DataSource}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void setLogWriter(PrintWriter theWriter) throws SQLException;
+}
diff --git a/sql/src/main/java/javax/sql/PooledConnection.java b/sql/src/main/java/javax/sql/PooledConnection.java
new file mode 100644
index 0000000..b4c5616
--- /dev/null
+++ b/sql/src/main/java/javax/sql/PooledConnection.java
@@ -0,0 +1,123 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.sql.SQLException;
+import java.sql.Connection;
+
+/**
+ * An interface which provides facilities for handling connections to a database
+ * which are pooled.
+ *
+ * Typically, a {@code PooledConnection} is recycled when it is no longer
+ * required by an application, rather than being closed and discarded. The
+ * reason for treating connections in this way is that it can be an expensive
+ * process both to establish a connection to a database and to destroy the
+ * connection. Reusing connections through a pool is a way of improving system
+ * performance and reducing overhead.
+ *
+ *
+ * It is not intended that an application uses the {@code PooledConnection}
+ * interface directly. The {@code PooledConnection} interface is intended for
+ * use by a component called a connection pool manager, typically part of the
+ * infrastructure that supports use of the database by applications.
+ *
+ *
+ * Applications obtain connections to the database by calling the
+ * {@link DataSource#getConnection} method. Behind the scenes, the connection
+ * pool manager will get a {@code PooledConnection} object from its connection
+ * pool and passes back a connection object that wraps or references the {@code
+ * PooledConnection} object. A new {@code PooledConnection} object will only be
+ * created if the pool is empty.
+ *
+ *
+ * When the application is finished using a {@code PooledConnection}, the
+ * application calls the {@link Connection#close} method. The connection pool
+ * manager is notified via a {@link ConnectionEvent} from the connection that
+ * this has happened (the pool manager registers itself with the connection
+ * before the connection is given to the application). The pool manager removes
+ * the underlying {@code PooledConnection} object from the connection and
+ * returns it to the pool for reuse - the {@code PooledConnection} is thus
+ * recycled rather than being destroyed.
+ *
+ *
+ * The connection to the database represented by the {@code PooledConnection} is
+ * kept open until the {@code PooledConnection} object itself is deactivated by
+ * the connection pool manager, which calls {@code PooledConnection.close()}.
+ * This is typically done if there are too many inactive connections in the
+ * pool, if the {@code PooledConnection} encounters a problem that makes it
+ * unusable or if the whole system is being shut down.
+ *
+ *
+ * @since Android 1.0
+ */
+public interface PooledConnection {
+
+ /**
+ * Registers the supplied {@code ConnectionEventListener} with this {@code
+ * PooledConnection}. Once registered, the {@code ConnectionEventListener}
+ * will receive {@link ConnectionEvent} events when they occur in the
+ * {@code PooledConnection}.
+ *
+ * @param theListener
+ * an object which implements the {@code ConnectionEventListener}
+ * interface.
+ * @since Android 1.0
+ */
+ public void addConnectionEventListener(ConnectionEventListener theListener);
+
+ /**
+ * Closes the connection to the database held by this {@code
+ * PooledConnection}. This method should not be called directly by
+ * application code - it is intended only for the connection pool manager
+ * component.
+ *
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void close() throws SQLException;
+
+ /**
+ * Creates a connection to the database. This method is typically called by
+ * the connection pool manager when an application invokes the method
+ * {@code DataSource.getConnection()} and there are no {@code
+ * PooledConnection} objects available in the connection pool.
+ *
+ * @return a {@code Connection} object.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Unregisters the supplied {@code ConnectionEventListener} from this {@code
+ * PooledConnection}. Once unregistered, the {@code ConnectionEventListener}
+ * will no longer receive events occurring in the {@code PooledConnection}.
+ *
+ * @param theListener
+ * an object which implements the {@code ConnectionEventListener}
+ * interface. This object should have previously been registered
+ * with the {@code PooledConnection} using the {@code
+ * addConnectionEventListener} method.
+ * @since Android 1.0
+ */
+ public void removeConnectionEventListener(
+ ConnectionEventListener theListener);
+}
diff --git a/sql/src/main/java/javax/sql/RowSet.java b/sql/src/main/java/javax/sql/RowSet.java
new file mode 100644
index 0000000..4edc3d3
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSet.java
@@ -0,0 +1,985 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.Ref;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Map;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.Calendar;
+import java.math.BigDecimal;
+
+/**
+ * An interface which provides means to access data which
+ * persists on a database. It extends the functionality of
+ * {@link java.sql.ResultSet ResultSet} into a form that it can be used as a
+ * JavaBean component, suited for a visual programming environment.
+ *
+ * {@code RowSet} provides getters and setters for properties relating to the
+ * general database environment together with the getters and setters for
+ * distinct data values which constitute the row set. The {@code RowSet} class
+ * supports JavaBean events so that other components in an application can be
+ * informed when changes happen such as changes in data values.
+ *
+ *
+ * {@code RowSet} is a facility implemented on top of the remainder of the JDBC
+ * API. It may be connected, maintaining a connection to the database
+ * throughout its lifecycle. The changes made on a disconnected {@code
+ * RowSet} on the other hand can be persisted only establishing a new connection
+ * with the database each time.
+ *
+ *
+ * Disconnected {@code RowSets} make use of {@code RowSetReaders} to populate
+ * the {@code RowSet} with data, possibly from a non-relational database source.
+ * They may also use {@code RowSetWriters} to send data back to the underlying
+ * data store. There is considerable freedom in the way that {@code
+ * RowSetReaders} and {@code RowSetWriters} may be implemented to retrieve and
+ * store data.
+ *
+ *
+ * @see RowSetReader
+ * @see RowSetWriter
+ * @since Android 1.0
+ */
+public interface RowSet extends ResultSet {
+
+ /**
+ * Registers the supplied {@link RowSetListener} with this {@code RowSet}.
+ * Once registered, the {@link RowSetListener} is notified of events
+ * generated by the {@code RowSet}.
+ *
+ * @param theListener
+ * an object which implements the {@code rowSetListener}
+ * interface.
+ * @since Android 1.0
+ */
+ public void addRowSetListener(RowSetListener theListener);
+
+ /**
+ * Clears the parameters previously set for this {@code RowSet}.
+ *
+ * The {@code RowSet} object retains its value until either a new value for
+ * a parameter is set or its value is actively reset. {@code
+ * clearParameters} provides a facility to clear the values for all
+ * parameters with one method call.
+ *
+ *
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void clearParameters() throws SQLException;
+
+ /**
+ * Fetches data for this {@code RowSet} from the database. If successful,
+ * any existing data for the {@code RowSet} is discarded and its metadata is
+ * overwritten.
+ *
+ * Data is retrieved connecting to the database and executing an
+ * according SQL statement. This requires some or all of the following
+ * properties to be set: URL, database name, user name, password,
+ * transaction isolation, type map; plus some or all of the properties:
+ * command, read only, maximum field size, maximum rows, escape processing,
+ * and query timeout.
+ *
+ *
+ * The {@code RowSet} may use a {@code RowSetReader} to access the database
+ * it will then invoke the {@link RowSetReader#readData} method on the
+ * reader to fetch the data. When the new data is fetched all the listeners
+ * are notified to take appropriate measures.
+ *
+ *
+ * @throws SQLException
+ * if a problem occurs accessing the database or if the
+ * properties needed to access the database have not been set.
+ * @see RowSetMetaData
+ * @see RowSetReader
+ * @since Android 1.0
+ */
+ public void execute() throws SQLException;
+
+ /**
+ * Gets the {@code RowSet}'s command property.
+ *
+ * @return a string containing the {@code RowSet}'s command property. A
+ * command is a SQL statement which is executed to fetch required
+ * data into the {@code RowSet}.
+ * @since Android 1.0
+ */
+ public String getCommand();
+
+ /**
+ * Gets the ODBC Data Source Name property associated with this {@code
+ * RowSet}. The database name can be used to find a {@link DataSource}
+ * which has been registered with a naming service - the {@link DataSource}
+ * can then be used to create a connection to the database.
+ *
+ * @return the name of the database.
+ * @since Android 1.0
+ */
+ public String getDataSourceName();
+
+ /**
+ * Reports if escape processing is enabled for this {@code RowSet}. If
+ * escape processing is on, the driver performs a substitution of the escape
+ * syntax with the applicable code before sending an SQL command to the
+ * database. The default value for escape processing is {@code true}.
+ *
+ * @return {@code true} if escape processing is enabled, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public boolean getEscapeProcessing() throws SQLException;
+
+ /**
+ * Gets the maximum number of bytes that can be returned for column values
+ * which are of type {@code BINARY}, {@code VARBINARY}, {@code
+ * LONGVARBINARYBINARY}, {@code CHAR}, {@code VARCHAR}, or {@code
+ * LONGVARCHAR}. Excess data is silently discarded if the number is
+ * exceeded.
+ *
+ * @return the current maximum size in bytes. 0 implies no size limit.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getMaxFieldSize() throws SQLException;
+
+ /**
+ * Gets the maximum number of rows for this {@code RowSet}. Excess rows are
+ * discarded silently if the limit is exceeded.
+ *
+ * @return the previous maximum number of rows. 0 implies no row limit.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getMaxRows() throws SQLException;
+
+ /**
+ * Gets the value of the password property for this {@code RowSet}. This
+ * property is used when a connection to the database is established.
+ * Therefore it should be set prior to invoking the {@link #execute} method.
+ *
+ * @return the value of the password property.
+ * @since Android 1.0
+ */
+ public String getPassword();
+
+ /**
+ * Gets the timeout for the driver when a query operation is executed. If a
+ * query takes longer than the timeout then a {@code SQLException} is
+ * thrown.
+ *
+ * @return the timeout value in seconds.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public int getQueryTimeout() throws SQLException;
+
+ /**
+ * Gets the transaction isolation level property set for this
+ * {@code RowSet}. The transaction isolation level defines the
+ * policy implemented on the database for maintaining the data
+ * values consistent.
+ *
+ * @return the current transaction isolation level. Must be one of:
+ *
+ *
{@code Connection.TRANSACTION_READ_UNCOMMITTED}
+ *
{@code Connection.TRANSACTION_READ_COMMITTED}
+ *
{@code Connection.TRANSACTION_REPEATABLE_READ}
+ *
{@code Connection.TRANSACTION_SERIALIZABLE}
+ *
+ * @see java.sql.Connection
+ * @since Android 1.0
+ */
+ public int getTransactionIsolation();
+
+ /**
+ * Gets the custom mapping of SQL User-Defined Types (UDTs) and Java classes
+ * for this {@code RowSet}, if applicable.
+ *
+ * @return the custom mappings of SQL types to Java classes.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public Map> getTypeMap() throws SQLException;
+
+ /**
+ * Gets the URL property value for this {@code RowSet}. If there is no
+ * {@code DataSource} object specified, the {@code RowSet} uses the URL to
+ * establish a connection to the database. The default value for the URL is
+ * {@code null}.
+ *
+ * @return a String holding the value of the URL property.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public String getUrl() throws SQLException;
+
+ /**
+ * Gets the value of the {@code username} property for this {@code RowSet}.
+ * The {@code username} is used when establishing a connection to the
+ * database and should be set before the {@code execute} method is invoked.
+ *
+ * @return a {@code String} holding the value of the {@code username}
+ * property.
+ * @since Android 1.0
+ */
+ public String getUsername();
+
+ /**
+ * Indicates if this {@code RowSet} is read-only.
+ *
+ * @return {@code true} if this {@code RowSet} is read-only, {@code false}
+ * if it is updatable.
+ * @since Android 1.0
+ */
+ public boolean isReadOnly();
+
+ /**
+ * Removes a specified {@link RowSetListener} object from the set of
+ * listeners which will be notified of events by this {@code RowSet}.
+ *
+ * @param theListener
+ * the {@link RowSetListener} to remove from the set of listeners
+ * for this {@code RowSet}.
+ * @since Android 1.0
+ */
+ public void removeRowSetListener(RowSetListener theListener);
+
+ /**
+ * Sets the specified {@code ARRAY} parameter in the {@code RowSet} command
+ * with the supplied {@code java.sql.Array} value.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theArray
+ * the {@code Array} data value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setArray(int parameterIndex, Array theArray)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * with the ASCII data in the supplied {@code java.io.InputStream} value.
+ * Data is read from the {@code InputStream} until end-of-file is reached.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theInputStream
+ * the ASCII data value to which the parameter is set.
+ * @param length
+ * the length of the data in bytes.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setAsciiStream(int parameterIndex, InputStream theInputStream,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of the specified SQL {@code NUMERIC} parameter in the
+ * {@code RowSet} command with the data in the supplied {@code
+ * java.math.BigDecimal} value.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theBigDecimal
+ * the big decimal value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to the binary data in the supplied input stream. Data is read from the
+ * input stream until end-of-file is reached.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theInputStream
+ * the binary data stream to which the parameter is set.
+ * @param length
+ * the length of the data in bytes.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setBinaryStream(int parameterIndex, InputStream theInputStream,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to the supplied {@code Blob} value.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theBlob
+ * the {@code Blob} value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setBlob(int parameterIndex, Blob theBlob) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to the supplied boolean.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theBoolean
+ * the {@code boolean} value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setBoolean(int parameterIndex, boolean theBoolean)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to the supplied byte value.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theByte
+ * the {@code byte} value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setByte(int parameterIndex, byte theByte) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to the supplied byte array value.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theByteArray
+ * the {@code Array} of {@code bytes} to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setBytes(int parameterIndex, byte[] theByteArray)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to the sequence of Unicode characters carried by the supplied {@code
+ * java.io.Reader}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theReader
+ * the {@code Reader} which contains the Unicode data to set the
+ * parameter.
+ * @param length
+ * the length of the data in the {@code Reader} in characters.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setCharacterStream(int parameterIndex, Reader theReader,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * with the value of a supplied {@code java.sql.Clob}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theClob
+ * the {@code Clob} value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setClob(int parameterIndex, Clob theClob) throws SQLException;
+
+ /**
+ * Sets the Command property for this {@code RowSet} - the command is an SQL
+ * query which runs when the {@code execute} method is invoked. This
+ * property is optional for databases that do not support commands.
+ *
+ * @param cmd
+ * the SQL query. Can be {@code null}.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setCommand(String cmd) throws SQLException;
+
+ /**
+ * Sets the concurrency property of this {@code RowSet}. The default value
+ * is {@code ResultSet.CONCUR_READ_ONLY}.
+ *
+ * @param concurrency
+ * the concurrency value. One of:
+ *
+ *
{@code ResultSet.CONCUR_READ_ONLY}
+ *
{@code ResultSet.CONCUR_UPDATABLE}
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @see java.sql.ResultSet
+ * @since Android 1.0
+ */
+ public void setConcurrency(int concurrency) throws SQLException;
+
+ /**
+ * Sets the database name property for the {@code RowSet}.
+ *
+ * The database name can be used to find a {@link DataSource} which has been
+ * registered with a naming service - the {@link DataSource} can then be
+ * used to create a connection to the database.
+ *
+ *
+ * @param name
+ * the database name.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setDataSourceName(String name) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * with the value of a supplied {@code java.sql.Date}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theDate
+ * the date value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setDate(int parameterIndex, Date theDate) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * with the value of a supplied {@code java.sql.Date}, where the conversion
+ * of the date to an SQL {@code DATE} value is calculated using a supplied
+ * {@code Calendar}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theDate
+ * the date to which the parameter is set.
+ * @param theCalendar
+ * the {@code Calendar} to use in converting the Date to an SQL
+ * {@code DATE} value.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setDate(int parameterIndex, Date theDate, Calendar theCalendar)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * with the supplied {@code double}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theDouble
+ * the {@code double} value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setDouble(int parameterIndex, double theDouble)
+ throws SQLException;
+
+ /**
+ * Sets the escape processing status for this {@code RowSet}. If escape
+ * processing is on, the driver performs a substitution of the escape syntax
+ * with the applicable code before sending an SQL command to the database.
+ * The default value for escape processing is {@code true}.
+ *
+ * @param enable
+ * {@code true} to enable escape processing, {@code false} to
+ * turn it off.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setEscapeProcessing(boolean enable) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * with the supplied {@code float}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theFloat
+ * the {@code float} value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setFloat(int parameterIndex, float theFloat)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * with the supplied {@code integer}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theInteger
+ * the {@code integer} value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setInt(int parameterIndex, int theInteger) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * with the supplied {@code long}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theLong
+ * the {@code long} value value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setLong(int parameterIndex, long theLong) throws SQLException;
+
+ /**
+ * Sets the maximum number of bytes which can be returned for a column value
+ * where the column type is one of {@code BINARY}, {@code VARBINARY},
+ * {@code LONGVARBINARYBINARY}, {@code CHAR}, {@code VARCHAR}, or {@code
+ * LONGVARCHAR}. Data which exceeds this limit is silently discarded. For
+ * portability, a value greater than 256 is recommended.
+ *
+ * @param max
+ * the maximum size of the returned column value in bytes. 0
+ * implies no size limit.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setMaxFieldSize(int max) throws SQLException;
+
+ /**
+ * Sets the maximum number of rows which can be held by the {@code RowSet}.
+ * Any additional rows are silently discarded.
+ *
+ * @param max
+ * the maximum number of rows which can be held in the {@code
+ * RowSet}. 0 means no limit.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setMaxRows(int max) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to SQL {@code NULL}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param sqlType
+ * the type of the parameter, as defined by {@code
+ * java.sql.Types}.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setNull(int parameterIndex, int sqlType) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to SQL {@code NULL}. This form of the {@code setNull} method should be
+ * used for User Defined Types and {@code REF} parameters.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param sqlType
+ * the type of the parameter, as defined by {@code
+ * java.sql.Types}.
+ * @param typeName
+ * the fully qualified name of an SQL user defined type or the
+ * name of the SQL structured type referenced by a {@code REF}
+ * type. Ignored if the sqlType is not a UDT or REF type.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setNull(int parameterIndex, int sqlType, String typeName)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied Java object.
+ *
+ * The JDBC specification provides a standard mapping for Java objects to
+ * SQL data types. Database specific types can be mapped by JDBC driver
+ * specific Java types.
+ *
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theObject
+ * the Java object containing the data value to which the
+ * parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setObject(int parameterIndex, Object theObject)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied Java object.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theObject
+ * the Java object containing the data value.
+ * @param targetSqlType
+ * the SQL type to send to the database, as defined in {@code
+ * java.sql.Types}.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setObject(int parameterIndex, Object theObject,
+ int targetSqlType) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied Java object.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theObject
+ * the Java object containing the data value.
+ * @param targetSqlType
+ * the SQL type to send to the database, as defined in {@code
+ * java.sql.Types}.
+ * @param scale
+ * the number of digits after the decimal point, for {@code
+ * java.sql.Types.DECIMAL} and {@code java.sql.Types.NUMERIC}
+ * types. Ignored for all other types.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setObject(int parameterIndex, Object theObject,
+ int targetSqlType, int scale) throws SQLException;
+
+ /**
+ * Sets the database Password for this {@code RowSet}. This property is used
+ * when a connection to the database is established. Therefore it should be
+ * set prior to invoking the {@link #execute} method.
+ *
+ * @param password
+ * a {@code String} holding the password.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setPassword(String password) throws SQLException;
+
+ /**
+ * Gets the timeout for the driver when a query operation is executed. If a
+ * query takes longer than the timeout, a {@code SQLException} is thrown.
+ *
+ * @param seconds
+ * the number of seconds for the timeout.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setQueryTimeout(int seconds) throws SQLException;
+
+ /**
+ * Sets whether the {@code RowSet} is read-only or updatable.
+ *
+ * @param readOnly
+ * {@code true} to set the {@code RowSet} to read-only state,
+ * {@code false} to allow updates.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setReadOnly(boolean readOnly) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied {@code java.sql.Ref}. This is sent to the database as an
+ * SQL {@code REF} value.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theRef
+ * the value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @see java.sql.Ref
+ * @since Android 1.0
+ */
+ public void setRef(int parameterIndex, Ref theRef) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied {@code short integer}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theShort
+ * the value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setShort(int parameterIndex, short theShort)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied {@code String}. The string is placed into the database as a
+ * {@code VARCHAR} or {@code LONGVARCHAR} SQL value, depending on the
+ * database limits for the length of {@code VARCHAR} values.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theString
+ * the value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setString(int parameterIndex, String theString)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied {@code java.sql.Time}, converting it to an SQL {@code TIME}
+ * value using the system default {@code Calendar}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theTime
+ * the value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @see java.util.Calendar
+ * @see java.sql.Time
+ * @since Android 1.0
+ */
+ public void setTime(int parameterIndex, Time theTime) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied {@code java.sql.Time}, converting it to an SQL {@code TIME}
+ * value using a supplied {@code Calendar}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theTime
+ * the value to which the parameter is set.
+ * @param theCalendar
+ * the {@code Calendar} to use in the conversion operation.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @see java.util.Calendar
+ * @see java.sql.Time
+ * @since Android 1.0
+ */
+ public void setTime(int parameterIndex, Time theTime, Calendar theCalendar)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied {@code java.sql.Timestamp}, converting it to an SQL {@code
+ * TIMESTAMP} value using the system default {@code Calendar}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theTimestamp
+ * the value to which the parameter is set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @see java.util.Calendar
+ * @see java.sql.Timestamp
+ * @since Android 1.0
+ */
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the {@code RowSet} command
+ * to a supplied {@code java.sql.Timestamp}, converting it to an SQL {@code
+ * TIMESTAMP} value using a supplied {@code Calendar}.
+ *
+ * @param parameterIndex
+ * the index of the parameter to set; the first parameter's index
+ * is 1.
+ * @param theTimestamp
+ * the value to which the parameter is set.
+ * @param theCalendar
+ * the {@code Calendar} to use in the conversion operation
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @see java.util.Calendar
+ * @see java.sql.Timestamp
+ * @since Android 1.0
+ */
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp,
+ Calendar theCalendar) throws SQLException;
+
+ /**
+ * Sets the target instance's transaction isolation level to one of a
+ * discrete set of possible values. The transaction isolation level defines
+ * the policy implemented on the database for maintaining the data values
+ * consistent.
+ *
+ * Keep in mind that setting a transaction isolation level has no effect
+ * unless your driver and DBMS support it.
+ *
+ *
+ * @param level
+ * the transaction isolation level. One of:
+ *
+ *
{@code Connection.TRANSACTION_READ_UNCOMMITTED}
+ *
{@code Connection.TRANSACTION_READ_COMMITTED}
+ *
{@code Connection.TRANSACTION_REPEATABLE_READ}
+ *
{@code Connection.TRANSACTION_SERIALIZABLE}
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @see java.sql.Connection
+ * @since Android 1.0
+ */
+ public void setTransactionIsolation(int level) throws SQLException;
+
+ /**
+ * Sets the type of this {@code RowSet}. By default, the type is
+ * non-scrollable.
+ *
+ * @param type
+ * the type for the {@code RowSet}. One of:
+ *
+ *
{@code ResultSet.TYPE_FORWARD_ONLY}
+ *
{@code ResultSet.TYPE_SCROLL_INSENSITIVE}
+ *
{@code ResultSet.TYPE_SCROLL_SENSITIVE}
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setType(int type) throws SQLException;
+
+ /**
+ * Sets the mapping of SQL User Defined Types (UDTs) to Java classes. The
+ * Java classes must all implement the {@link java.sql.SQLData SQLData}
+ * interface.
+ *
+ * @param theTypeMap
+ * the names of SQL UDTs and the Java classes to which they are
+ * mapped.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setTypeMap(Map> theTypeMap)
+ throws SQLException;
+
+ /**
+ * Sets the URL used by this {@code RowSet} to access the database via a
+ * {@code DriverManager}. The URL is optional - an alternative is to use a
+ * database name to create a connection.
+ *
+ * @param theURL
+ * the URL for the database. Can be {@code null}.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setUrl(String theURL) throws SQLException;
+
+ /**
+ * Sets the {@code Username} property for the {@code RowSet}, used to
+ * authenticate a connection to the database.
+ *
+ * @param theUsername
+ * the new user name for this row set.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setUsername(String theUsername) throws SQLException;
+}
diff --git a/sql/src/main/java/javax/sql/RowSetEvent.java b/sql/src/main/java/javax/sql/RowSetEvent.java
new file mode 100644
index 0000000..9d4c98c
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetEvent.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.util.EventObject;
+import java.io.Serializable;
+
+/**
+ * An event which is sent when specific events happen to a {@link RowSet}
+ * object. The events are sent to inform registered listeners that changes have
+ * occurred to the {@code RowSet}. The events covered are:
+ *
+ *
A single row in the {@code RowSet} changes.
+ *
The whole set of data in the {@code RowSet} changes.
+ *
The {@code RowSet} cursor position changes.
+ *
+ *
+ * The event contains a reference to the {@code RowSet} object which generated
+ * the message so that the listeners can extract whatever information they need
+ * from that reference.
+ *
+ *
+ * @since Android 1.0
+ */
+public class RowSetEvent extends EventObject implements Serializable {
+
+ private static final long serialVersionUID = -1875450876546332005L;
+
+ /**
+ * Creates a {@code RowSetEvent} object containing a reference to the
+ * {@link RowSet} object that generated the event. Information about the
+ * changes that have occurred to the {@code RowSet} can be extracted from
+ * the {@code RowSet} using one or more of the query methods available on
+ * the {@code RowSet}.
+ *
+ * @param theSource
+ * the {@code RowSet} which generated the event.
+ * @since Android 1.0
+ */
+ public RowSetEvent(RowSet theSource) {
+ super(theSource);
+ }
+}
diff --git a/sql/src/main/java/javax/sql/RowSetInternal.java b/sql/src/main/java/javax/sql/RowSetInternal.java
new file mode 100644
index 0000000..baa261d
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetInternal.java
@@ -0,0 +1,93 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+
+/**
+ * An interface provided by a {@code RowSet} object to let either a {@code RowSetReader} or a
+ * {@code RowSetWriter} access its internal state, thereby providing facilities to read and update the state of
+ * the {@code RowSet}.
+ */
+public interface RowSetInternal {
+
+ /**
+ * Gets the connection associated with this {@code RowSet} object.
+ *
+ * @return the connection or {@code null}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Gets the {@code ResultSet} that was the original (unmodified) content of
+ * the {@code RowSet}.
+ *
+ * The {@code ResultSet}'s cursor is positioned before the first row of
+ * data.
+ *
+ *
+ * @return the {@code ResultSet} that contained the original data value of
+ * the {@code RowSet}.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public ResultSet getOriginal() throws SQLException;
+
+ /**
+ * Gets the original value of the current row only. If the current row did
+ * not have an original value, then an empty value is returned.
+ *
+ * @return a {@code ResultSet} containing the value of the current row only.
+ * @throws SQLException
+ * if there is a problem accessing the database, or if the
+ * cursor is not on a valid row (before the first row, after the
+ * last one or pointing to the insert row).
+ * @since Android 1.0
+ */
+ public ResultSet getOriginalRow() throws SQLException;
+
+ /**
+ * Gets the parameter values that have been set for this {@code RowSet}'s
+ * command.
+ *
+ * @return the values of parameters that have been set.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public Object[] getParams() throws SQLException;
+
+ /**
+ * Sets {@code RowSetMetaData} for this {@code RowSet}. The {@code
+ * RowSetMetaData} is used by a {@code RowSetReader} to set values giving
+ * information about the {@code RowSet}'s columns.
+ *
+ * @param theMetaData
+ * holds the metadata about the {@code RowSet}'s columns.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ * @since Android 1.0
+ */
+ public void setMetaData(RowSetMetaData theMetaData) throws SQLException;
+}
diff --git a/sql/src/main/java/javax/sql/RowSetListener.java b/sql/src/main/java/javax/sql/RowSetListener.java
new file mode 100644
index 0000000..06a7253
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetListener.java
@@ -0,0 +1,72 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.util.EventListener;
+
+/**
+ * An interface used to send notification of events occurring in the context of
+ * a {@link RowSet}. To receive the notification events, an object must
+ * implement the {@code RowSetListener} interface and then register itself with
+ * the {@code RowSet} of interest using the
+ * {@link RowSet#addRowSetListener(RowSetListener)} method.
+ *
+ * @since Android 1.0
+ */
+public interface RowSetListener extends EventListener {
+
+ /**
+ * Notifies the listener that the {@code RowSet}'s cursor in {@code
+ * theEvent.getSource} has moved.
+ *
+ * @param theEvent
+ * a {@code RowSetEvent} that contains information about the
+ * {@code RowSet} involved. This information can be used to
+ * retrieve information about the change, such as the updated
+ * data values.
+ * @since Android 1.0
+ */
+ public void cursorMoved(RowSetEvent theEvent);
+
+ /**
+ * Notifies the listener that one of the {@code RowSet}'s rows in {@code
+ * theEvent.getSource} has changed.
+ *
+ * @param theEvent
+ * a {@code RowSetEvent} that contains information about the
+ * {@code RowSet} involved. This information can be used to
+ * retrieve information about the change, such as the new cursor
+ * position.
+ * @since Android 1.0
+ */
+ public void rowChanged(RowSetEvent theEvent);
+
+ /**
+ * Notifies the listener that the {@code RowSet}'s entire contents in
+ * {@code theEvent.getSource} have been updated (an example is the execution
+ * of a command which retrieves new data from the database).
+ *
+ * @param theEvent
+ * a {@code RowSetEvent} that contains information about the
+ * {@code RowSet} involved. This information can be used to
+ * retrieve information about the change, such as the updated
+ * rows of data.
+ * @since Android 1.0
+ */
+ public void rowSetChanged(RowSetEvent theEvent);
+}
diff --git a/sql/src/main/java/javax/sql/RowSetMetaData.java b/sql/src/main/java/javax/sql/RowSetMetaData.java
new file mode 100644
index 0000000..3051876
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetMetaData.java
@@ -0,0 +1,314 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+
+/**
+ * An interface which provides facilities for getting information about the
+ * columns in a {@code RowSet}.
+ *
+ * {@code RowSetMetaData} extends {@link java.sql.ResultSetMetaData}, adding new
+ * operations for carrying out value sets.
+ *
+ *
+ * Application code would not normally call this interface directly. It would be
+ * called internally when {@code RowSet.execute} is called.
+ *
+ *
+ * @see RowSetInternal#setMetaData(RowSetMetaData)
+ * @since Android 1.0
+ */
+public interface RowSetMetaData extends ResultSetMetaData {
+
+ /**
+ * Sets automatic numbering for a specified column in the {@code RowSet}. If
+ * automatic numbering is on, the column is read-only. The default value for
+ * the auto increment parameter is {@code false}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param autoIncrement
+ * {@code true} to set automatic numbering on, {@code false} to
+ * turn it off (default).
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setAutoIncrement(int columnIndex, boolean autoIncrement)
+ throws SQLException;
+
+ /**
+ * Sets the case sensitive property for a specified column in the {@code
+ * RowSet}. The default is that the column is not case sensitive.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param caseSensitive
+ * {@code true} to make the column case sensitive, {@code false}
+ * to make it case insensitive (default).
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setCaseSensitive(int columnIndex, boolean caseSensitive)
+ throws SQLException;
+
+ /**
+ * Sets the catalog name for a specified column in the {@code RowSet}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param catalogName
+ * the new catalog's name.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setCatalogName(int columnIndex, String catalogName)
+ throws SQLException;
+
+ /**
+ * Sets the number of columns contained in the row set.
+ *
+ * @param columnCount
+ * the number of columns contained in the {@code RowSet}.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setColumnCount(int columnCount) throws SQLException;
+
+ /**
+ * Sets the normal maximum width in characters for a specified column in the
+ * {@code RowSet}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param displaySize
+ * the normal maximum column width in characters.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setColumnDisplaySize(int columnIndex, int displaySize)
+ throws SQLException;
+
+ /**
+ * Sets the suggested name as label for the column contained in the {@code
+ * RowSet}. The label is an alias for printing and displaying purposes.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param theLabel
+ * the alias name for the column.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setColumnLabel(int columnIndex, String theLabel)
+ throws SQLException;
+
+ /**
+ * Sets the column name for a specified column in the {@code RowSet}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param theColumnName
+ * the column's label.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setColumnName(int columnIndex, String theColumnName)
+ throws SQLException;
+
+ /**
+ * Sets the SQL type for a specified column in the {@code RowSet}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param theSQLType
+ * the SQL Type, as defined by {@code java.sql.Types}.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setColumnType(int columnIndex, int theSQLType)
+ throws SQLException;
+
+ /**
+ * Sets the type name for a specified column in the {@code RowSet}, where
+ * the data type is specific to the data source.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param theTypeName
+ * the SQL type name for the column.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setColumnTypeName(int columnIndex, String theTypeName)
+ throws SQLException;
+
+ /**
+ * Sets whether a specified column is a currency value. The default value is
+ * {@code false}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param isCurrency
+ * {@code true} if the column should be treated as a currency
+ * value, {@code false} if it should not be treated as a currency
+ * value (default).
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setCurrency(int columnIndex, boolean isCurrency)
+ throws SQLException;
+
+ /**
+ * Sets whether a specified column can contain SQL {@code NULL} values.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param nullability
+ * an integer which is one of the following values:
+ *
+ *
{@code ResultSetMetaData.columnNoNulls}
+ *
{@code ResultSetMetaData.columnNullable}
+ *
{@code ResultSetMetaData.columnNullableUnknown}
+ *
+ *
+ * The default value is {@code
+ * ResultSetMetaData.columnNullableUnknown}.
+ *
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setNullable(int columnIndex, int nullability)
+ throws SQLException;
+
+ /**
+ * Sets the number of decimal digits for a specified column in the {@code
+ * RowSet}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param thePrecision
+ * the number of decimal digits.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setPrecision(int columnIndex, int thePrecision)
+ throws SQLException;
+
+ /**
+ * Declares how many decimal digits there should be after a decimal point
+ * for the column specified by {@code columnIndex}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param theScale
+ * the number of digits after the decimal point.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setScale(int columnIndex, int theScale) throws SQLException;
+
+ /**
+ * Sets the schema name for a specified column in the {@code RowSet}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param theSchemaName
+ * a {@code String} containing the schema name.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setSchemaName(int columnIndex, String theSchemaName)
+ throws SQLException;
+
+ /**
+ * Sets whether a specified column can be used in a search involving a
+ * {@code WHERE} clause. The default value is {@code false}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param isSearchable
+ * {@code true} of the column can be used in a {@code WHERE}
+ * clause search, {@code false} otherwise.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setSearchable(int columnIndex, boolean isSearchable)
+ throws SQLException;
+
+ /**
+ * Sets if a specified column can contain signed numbers.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param isSigned
+ * {@code true} if the column can contain signed numbers, {@code
+ * false} otherwise.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setSigned(int columnIndex, boolean isSigned)
+ throws SQLException;
+
+ /**
+ * Sets the table name for a specified column in the {@code RowSet}.
+ *
+ * @param columnIndex
+ * the index number for the column; the first column's index is
+ * 1.
+ * @param theTableName
+ * the table name for the column.
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public void setTableName(int columnIndex, String theTableName)
+ throws SQLException;
+}
diff --git a/sql/src/main/java/javax/sql/RowSetReader.java b/sql/src/main/java/javax/sql/RowSetReader.java
new file mode 100644
index 0000000..d4a902f
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetReader.java
@@ -0,0 +1,59 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.sql.SQLException;
+
+/**
+ * An interface which provides functionality for a disconnected {@code RowSet}
+ * to get data from a database into its rows. The {@code RowSet} calls the
+ * {@code RowSetReader} interface when the {@code RowSet}'s execute method is
+ * invoked - a {@code RowSetReader} must first be registered with the {@code
+ * RowSet} for this to work.
+ *
+ * @see RowSet
+ * @since Android 1.0
+ */
+public interface RowSetReader {
+
+ /**
+ * Reads new data into the {@code RowSet}. The calling {@code RowSet} object
+ * must itself implement the {@code RowSetInternal} interface and the
+ * {@code RowSetReader} must be registered as a reader on the
+ * {@code RowSet}.
+ *
+ * This method adds rows into the calling {@code RowSet}. The reader may
+ * invoke any of the {@code RowSet}'s methods except for the {@code execute}
+ * method (calling {@code execute} will cause an {@code SQLException} to be
+ * thrown). However, when the reader calls the {@code RowSet}'s methods, no
+ * events are sent to listeners - any listeners are informed by the calling
+ * {@code RowSet}'s {@code execute} method once the reader returns from the
+ * {@code readData} method.
+ *
+ *
+ * @param theCaller
+ * must be the calling {@code RowSet} object, which must have
+ * implemented the {@code RowSetInternal} interface.
+ * @throws SQLException
+ * if a problem occurs accessing the database or if the reader
+ * calls the {@link RowSet#execute()} method.
+ * @see RowSetInternal
+ * @since Android 1.0
+ */
+ public void readData(RowSetInternal theCaller) throws SQLException;
+}
diff --git a/sql/src/main/java/javax/sql/RowSetWriter.java b/sql/src/main/java/javax/sql/RowSetWriter.java
new file mode 100644
index 0000000..34473b2
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetWriter.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package javax.sql;
+
+import java.sql.SQLException;
+
+/**
+ * An interface which provides functionality for a disconnected {@code RowSet}
+ * to put data updates back to the data source from which the {@code RowSet} was
+ * originally populated. An object implementing this interface is called a
+ * writer.
+ *
+ * The writer must establish a connection to the {@code RowSet}'s database
+ * before writing the data. The {@code RowSet} calling this interface must
+ * implement the {@code RowSetInternal} interface.
+ *
+ *
+ * The writer may encounter a situation where the updated data needs to be
+ * written back to the database, but has already been updated there in the mean
+ * time. How a conflict of this kind is handled is determined by the
+ * implementation of this writer.
+ *
+ *
+ * @see RowSetInternal
+ * @since Android 1.0
+ */
+public interface RowSetWriter {
+
+ /**
+ * Writes changes made in the {@code RowSet}, which is associated with this
+ * {@code RowSetWriter}, back to the database.
+ *
+ * @param theRowSet
+ * a row set that fulfills the following criteria:
+ *
+ *
it must implement the {@code RowSetInternal} interface,
+ *
have this {@code RowSetWriter} registered with it,
+ *
must call this method internally.
+ *
+ * @return {@code true} if the modified data was written, {@code false}
+ * otherwise (which typically implies some form of conflict).
+ * @throws SQLException
+ * if a problem occurs accessing the database.
+ * @since Android 1.0
+ */
+ public boolean writeData(RowSetInternal theRowSet) throws SQLException;
+}
diff --git a/sql/src/main/java/javax/sql/package.html b/sql/src/main/java/javax/sql/package.html
new file mode 100644
index 0000000..6c9500f
--- /dev/null
+++ b/sql/src/main/java/javax/sql/package.html
@@ -0,0 +1,9 @@
+
+
+
+ Provides extensions to the standard interface for accessing SQL-based
+ databases.
+
+ @since Android 1.0
+
+
\ No newline at end of file
diff --git a/sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java b/sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java
new file mode 100644
index 0000000..b3dbd32
--- /dev/null
+++ b/sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java
@@ -0,0 +1,147 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+/*
+ * THE FILE HAS BEEN AUTOGENERATED BY MSGTOOL TOOL.
+ * All changes made to this file manually will be overwritten
+ * if this tool runs again. Better make changes in the template file.
+ */
+
+// BEGIN android-note
+// Redundant code has been removed and is now called from MsgHelp.
+// END android-note
+
+package org.apache.harmony.sql.internal.nls;
+
+
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+// BEGIN android-changed
+import org.apache.harmony.luni.util.MsgHelp;
+// END android-changed
+
+/**
+ * This class retrieves strings from a resource bundle and returns them,
+ * formatting them with MessageFormat when required.
+ *
+ * It is used by the system classes to provide national language support, by
+ * looking up messages in the
+ * org.apache.harmony.sql.internal.nls.messages
+ *
+ * resource bundle. Note that if this file is not available, or an invalid key
+ * is looked up, or resource bundle support is not available, the key itself
+ * will be returned as the associated message. This means that the KEY
+ * should a reasonable human-readable (english) string.
+ *
+ */
+public class Messages {
+
+ // BEGIN android-changed
+ private static final String sResource =
+ "org.apache.harmony.sql.internal.nls.messages"; //$NON-NLS-1$
+ // END android-changed
+
+ /**
+ * Retrieves a message which has no arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg) {
+ // BEGIN android-changed
+ return MsgHelp.getString(sResource, msg);
+ // END android-changed
+ }
+
+ /**
+ * Retrieves a message which takes 1 argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * Object the object to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object arg) {
+ return getString(msg, new Object[] { arg });
+ }
+
+ /**
+ * Retrieves a message which takes 1 integer argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * int the integer to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, int arg) {
+ return getString(msg, new Object[] { Integer.toString(arg) });
+ }
+
+ /**
+ * Retrieves a message which takes 1 character argument.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg
+ * char the character to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, char arg) {
+ return getString(msg, new Object[] { String.valueOf(arg) });
+ }
+
+ /**
+ * Retrieves a message which takes 2 arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param arg1
+ * Object an object to insert in the formatted output.
+ * @param arg2
+ * Object another object to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object arg1, Object arg2) {
+ return getString(msg, new Object[] { arg1, arg2 });
+ }
+
+ /**
+ * Retrieves a message which takes several arguments.
+ *
+ * @param msg
+ * String the key to look up.
+ * @param args
+ * Object[] the objects to insert in the formatted output.
+ * @return String the message for that key in the system message bundle.
+ */
+ static public String getString(String msg, Object[] args) {
+ // BEGIN android-changed
+ return MsgHelp.getString(sResource, msg, args);
+ // END android-changed
+ }
+
+ // BEGIN android-note
+ // Duplicate code was dropped in favor of using MsgHelp.
+ // END android-note
+}
diff --git a/sql/src/main/java/org/apache/harmony/sql/internal/nls/messages.properties b/sql/src/main/java/org/apache/harmony/sql/internal/nls/messages.properties
new file mode 100644
index 0000000..3e6ff1d
--- /dev/null
+++ b/sql/src/main/java/org/apache/harmony/sql/internal/nls/messages.properties
@@ -0,0 +1,42 @@
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements. See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You 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.
+#
+
+# messages for EN locale
+sql.0=Value out of range
+sql.1=DriverManager: calling class not authorized to deregister JDBC driver
+sql.2=Timestamp format must be yyyy-mm-dd hh:mm:ss.fffffffff
+sql.3=Argument cannot be null
+sql.4=Bad input string format: expected '.' not {0}
+sql.5=The url cannot be null
+sql.6=No suitable driver
+sql.8=SQLWarning chain holds value that is not a SQLWarning
+sql.9=Cannot instantiate a SerialRef object with a null Ref object
+sql.10=Cannot instantiate a SerialRef object that returns a null base type name
+sql.11=SQLException: {0}
+sql.12=Cannot serialize empty URL instance
+sql.13=Cannot instantiate a SerialBlob object with a null Blob object
+sql.14=Invalid starting position or length
+sql.15=Invalid position in BLOB object set
+sql.16=Invalid offset in byte array set
+sql.17=javax.sql.rowset.serial.SerialException: Length more than what can be truncated
+sql.18=Unsupported operation. SerialBlob cannot return a writable binary stream, unless instantiated with a Blob object that provides a setBinaryStream() implementation
+sql.19=Cannot instantiate a SerialClob object with a null Clob object
+sql.20=Invalid Clob object. Calls to getCharacterStream or getAsciiStream return null which cannot be serialized.
+sql.21=Invalid position in CLOB object set
+sql.22=Invalid position and substring length
+sql.23=Buffer is not sufficient to hold the value
+sql.24=Invalid length for truncate
+sql.25=Unsupported operation. SerialClob is not instantiated with a fully implemented Clob object.
diff --git a/sql/src/main/native/sqlite_jni.c b/sql/src/main/native/sqlite_jni.c
new file mode 100644
index 0000000..c8a76e4
--- /dev/null
+++ b/sql/src/main/native/sqlite_jni.c
@@ -0,0 +1,4398 @@
+#include
+#include
+#include
+
+#include "sqlite_jni_defs.h"
+
+#if HAVE_SQLITE2
+#include "sqlite.h"
+#endif
+
+#if HAVE_SQLITE3
+#include "sqlite3.h"
+#undef HAVE_SQLITE_COMPILE
+#define HAVE_SQLITE_COMPILE 1
+#undef HAVE_SQLITE_PROGRESS_HANDLER
+#define HAVE_SQLITE_PROGRESS_HANDLER 1
+#undef HAVE_SQLITE_TRACE
+#define HAVE_SQLITE_TRACE 1
+#if !HAVE_SQLITE3_MALLOC
+#define sqlite3_malloc malloc
+#define sqlite3_free free
+#endif
+#if !HAVE_SQLITE3_BIND_PARAMETER_COUNT
+#define sqlite3_bind_parameter_count(dummy) (1000)
+#endif
+#endif
+
+#if HAVE_SQLITE2 && HAVE_SQLITE3
+#define HAVE_BOTH_SQLITE 1
+#endif
+
+#include "sqlite_jni.h"
+
+#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+#define MAX_PARAMS 256
+#else
+#define MAX_PARAMS 32
+#endif
+
+/* free memory proc */
+
+typedef void (freemem)(void *);
+
+/* internal handle for SQLite database */
+
+typedef struct {
+ void *sqlite; /* SQLite handle */
+#if HAVE_BOTH_SQLITE
+ int is3; /* True for SQLITE3 handle */
+#endif
+ int ver; /* version code */
+ jobject bh; /* BusyHandler object */
+ jobject cb; /* Callback object */
+ jobject ai; /* Authorizer object */
+ jobject tr; /* Trace object */
+ jobject ph; /* ProgressHandler object */
+ JNIEnv *env; /* Java environment for callbacks */
+ int row1; /* true while processing first row */
+ int haveutf; /* true for SQLite UTF-8 support */
+ jstring enc; /* encoding or 0 */
+ struct hfunc *funcs; /* SQLite user defined function handles */
+#if HAVE_SQLITE_COMPILE
+ struct hvm *vms; /* Compiled SQLite VMs */
+#endif
+#if HAVE_SQLITE3
+ sqlite3_stmt *stmt; /* For callback() */
+#endif
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ struct hbl *blobs; /* SQLite3 blob handles */
+#endif
+} handle;
+
+/* internal handle for SQLite user defined function */
+
+typedef struct hfunc {
+ struct hfunc *next; /* next function */
+#if HAVE_BOTH_SQLITE
+ int is3; /* True for SQLITE3 handle */
+#endif
+ jobject fc; /* FunctionContext object */
+ jobject fi; /* Function object */
+ jobject db; /* Database object */
+ handle *h; /* SQLite database handle */
+ void *sf; /* SQLite function handle */
+ JNIEnv *env; /* Java environment for callbacks */
+} hfunc;
+
+#if HAVE_SQLITE_COMPILE
+/* internal handle for SQLite VM (sqlite_compile()) */
+
+typedef struct hvm {
+ struct hvm *next; /* next vm handle */
+#if HAVE_BOTH_SQLITE
+ int is3; /* True for SQLITE3 handle */
+#endif
+ void *vm; /* SQLite 2/3 VM/statement */
+ char *tail; /* tail SQL string */
+ int tail_len; /* only for SQLite3/prepare */
+ handle *h; /* SQLite database handle */
+ handle hh; /* fake SQLite database handle */
+} hvm;
+#endif
+
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+/* internal handle for sqlite3_blob */
+
+typedef struct hbl {
+ struct hbl *next; /* next blob handle */
+ sqlite3_blob *blob; /* SQLite3 blob */
+ handle *h; /* SQLite database handle */
+} hbl;
+#endif
+
+/* ISO to/from UTF-8 translation */
+
+typedef struct {
+ char *result; /* translated C string result */
+ char *tofree; /* memory to be free'd, or 0 */
+ jstring jstr; /* resulting Java string or 0 */
+} transstr;
+
+/* static cached weak class refs, field and method ids */
+
+static jclass C_java_lang_String = 0;
+
+static jfieldID F_SQLite_Database_handle = 0;
+static jfieldID F_SQLite_Database_error_code = 0;
+static jfieldID F_SQLite_FunctionContext_handle = 0;
+static jfieldID F_SQLite_Vm_handle = 0;
+static jfieldID F_SQLite_Vm_error_code = 0;
+static jfieldID F_SQLite_Stmt_handle = 0;
+static jfieldID F_SQLite_Stmt_error_code = 0;
+static jfieldID F_SQLite_Blob_handle = 0;
+static jfieldID F_SQLite_Blob_size = 0;
+
+static jmethodID M_java_lang_String_getBytes = 0;
+static jmethodID M_java_lang_String_getBytes2 = 0;
+static jmethodID M_java_lang_String_initBytes = 0;
+static jmethodID M_java_lang_String_initBytes2 = 0;
+
+static const char xdigits[] = "0123456789ABCDEF";
+
+static void
+seterr(JNIEnv *env, jobject obj, int err)
+{
+ jvalue v;
+
+ v.j = 0;
+ v.i = (jint) err;
+ (*env)->SetIntField(env, obj, F_SQLite_Database_error_code, v.i);
+}
+
+#if HAVE_SQLITE_COMPILE
+static void
+setvmerr(JNIEnv *env, jobject obj, int err)
+{
+ jvalue v;
+
+ v.j = 0;
+ v.i = (jint) err;
+ (*env)->SetIntField(env, obj, F_SQLite_Vm_error_code, v.i);
+}
+
+#if HAVE_SQLITE3
+static void
+setstmterr(JNIEnv *env, jobject obj, int err)
+{
+ jvalue v;
+
+ v.j = 0;
+ v.i = (jint) err;
+ (*env)->SetIntField(env, obj, F_SQLite_Stmt_error_code, v.i);
+}
+
+static int
+jstrlen(const jchar *jstr)
+{
+ int len = 0;
+
+ if (jstr) {
+ while (*jstr++) {
+ len++;
+ }
+ }
+ return len;
+}
+#endif
+#endif
+
+static void *
+gethandle(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Database_handle);
+ return (void *) v.l;
+}
+
+#if HAVE_SQLITE_COMPILE
+static void *
+gethvm(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Vm_handle);
+ return (void *) v.l;
+}
+
+#if HAVE_SQLITE3
+static void *
+gethstmt(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Stmt_handle);
+ return (void *) v.l;
+}
+#endif
+#endif
+
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+static void *
+gethbl(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_Blob_handle);
+ return (void *) v.l;
+}
+#endif
+
+static void
+delglobrefp(JNIEnv *env, jobject *obj)
+{
+ if (*obj) {
+ (*env)->DeleteGlobalRef(env, *obj);
+ *obj = 0;
+ }
+}
+
+static jobject
+globrefpop(JNIEnv *env, jobject *obj)
+{
+ jobject ret = 0;
+
+ if (*obj) {
+ ret = *obj;
+ *obj = 0;
+ }
+ return ret;
+}
+
+static void
+globrefset(JNIEnv *env, jobject obj, jobject *ref)
+{
+ if (ref) {
+ if (obj) {
+ *ref = (*env)->NewGlobalRef(env, obj);
+ } else {
+ *ref = 0;
+ }
+ }
+}
+
+static void
+freep(char **strp)
+{
+ if (strp && *strp) {
+ free(*strp);
+ *strp = 0;
+ }
+}
+
+static void
+throwex(JNIEnv *env, const char *msg)
+{
+ jclass except = (*env)->FindClass(env, "SQLite/Exception");
+
+ (*env)->ExceptionClear(env);
+ if (except) {
+ (*env)->ThrowNew(env, except, msg);
+ }
+}
+
+static void
+throwoom(JNIEnv *env, const char *msg)
+{
+ jclass except = (*env)->FindClass(env, "java/lang/OutOfMemoryError");
+
+ (*env)->ExceptionClear(env);
+ if (except) {
+ (*env)->ThrowNew(env, except, msg);
+ }
+}
+
+static void
+throwclosed(JNIEnv *env)
+{
+ throwex(env, "database already closed");
+}
+
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+static void
+throwioex(JNIEnv *env, const char *msg)
+{
+ jclass except = (*env)->FindClass(env, "java/io/IOException");
+
+ (*env)->ExceptionClear(env);
+ if (except) {
+ (*env)->ThrowNew(env, except, msg);
+ }
+}
+#endif
+
+static void
+transfree(transstr *dest)
+{
+ dest->result = 0;
+ freep(&dest->tofree);
+}
+
+static char *
+trans2iso(JNIEnv *env, int haveutf, jstring enc, jstring src,
+ transstr *dest)
+{
+ jbyteArray bytes = 0;
+ jthrowable exc;
+
+ dest->result = 0;
+ dest->tofree = 0;
+ if (haveutf) {
+ const char *utf = (*env)->GetStringUTFChars(env, src, 0);
+
+ if (!utf) {
+ return dest->result;
+ }
+ dest->tofree = malloc(strlen(utf) + 1);
+ dest->result = dest->tofree;
+ strcpy(dest->result, utf);
+ (*env)->ReleaseStringUTFChars(env, src, utf);
+ return dest->result;
+ }
+ if (enc) {
+ bytes = (*env)->CallObjectMethod(env, src,
+ M_java_lang_String_getBytes2, enc);
+ } else {
+ bytes = (*env)->CallObjectMethod(env, src,
+ M_java_lang_String_getBytes);
+ }
+ exc = (*env)->ExceptionOccurred(env);
+ if (!exc) {
+ jint len = (*env)->GetArrayLength(env, bytes);
+ dest->tofree = malloc(len + 1);
+ if (!dest->tofree) {
+ throwoom(env, "string translation failed");
+ return dest->result;
+ }
+ dest->result = dest->tofree;
+ (*env)->GetByteArrayRegion(env, bytes, 0, len, (jbyte *) dest->result);
+ dest->result[len] = '\0';
+ } else {
+ (*env)->DeleteLocalRef(env, exc);
+ }
+ return dest->result;
+}
+
+static jstring
+trans2utf(JNIEnv *env, int haveutf, jstring enc, const char *src,
+ transstr *dest)
+{
+ jbyteArray bytes = 0;
+ int len;
+
+ dest->result = 0;
+ dest->tofree = 0;
+ dest->jstr = 0;
+ if (!src) {
+ return dest->jstr;
+ }
+ if (haveutf) {
+ dest->jstr = (*env)->NewStringUTF(env, src);
+ return dest->jstr;
+ }
+ len = strlen(src);
+ bytes = (*env)->NewByteArray(env, len);
+ if (bytes) {
+ (*env)->SetByteArrayRegion(env, bytes, 0, len, (jbyte *) src);
+ if (enc) {
+ dest->jstr =
+ (*env)->NewObject(env, C_java_lang_String,
+ M_java_lang_String_initBytes2, bytes, enc);
+ } else {
+ dest->jstr =
+ (*env)->NewObject(env, C_java_lang_String,
+ M_java_lang_String_initBytes, bytes);
+ }
+ (*env)->DeleteLocalRef(env, bytes);
+ return dest->jstr;
+ }
+ throwoom(env, "string translation failed");
+ return dest->jstr;
+}
+
+#if HAVE_SQLITE2
+static int
+busyhandler(void *udata, const char *table, int count)
+{
+ handle *h = (handle *) udata;
+ JNIEnv *env = h->env;
+ int ret = 0;
+
+ if (env && h->bh) {
+ transstr tabstr;
+ jclass cls = (*env)->GetObjectClass(env, h->bh);
+ jmethodID mid = (*env)->GetMethodID(env, cls, "busy",
+ "(Ljava/lang/String;I)Z");
+
+ if (mid == 0) {
+ return ret;
+ }
+ trans2utf(env, h->haveutf, h->enc, table, &tabstr);
+ ret = (*env)->CallBooleanMethod(env, h->bh, mid, tabstr.jstr,
+ (jint) count)
+ != JNI_FALSE;
+ (*env)->DeleteLocalRef(env, tabstr.jstr);
+ }
+ return ret;
+}
+#endif
+
+#if HAVE_SQLITE3
+static int
+busyhandler3(void *udata, int count)
+{
+ handle *h = (handle *) udata;
+ JNIEnv *env = h->env;
+ int ret = 0;
+
+ if (env && h->bh) {
+ jclass cls = (*env)->GetObjectClass(env, h->bh);
+ jmethodID mid = (*env)->GetMethodID(env, cls, "busy",
+ "(Ljava/lang/String;I)Z");
+
+ if (mid == 0) {
+ return ret;
+ }
+ ret = (*env)->CallBooleanMethod(env, h->bh, mid, 0, (jint) count)
+ != JNI_FALSE;
+ }
+ return ret;
+}
+#endif
+
+static int
+progresshandler(void *udata)
+{
+ handle *h = (handle *) udata;
+ JNIEnv *env = h->env;
+ int ret = 0;
+
+ if (env && h->ph) {
+ jclass cls = (*env)->GetObjectClass(env, h->ph);
+ jmethodID mid = (*env)->GetMethodID(env, cls, "progress", "()Z");
+
+ if (mid == 0) {
+ return ret;
+ }
+ ret = (*env)->CallBooleanMethod(env, h->ph, mid) != JNI_TRUE;
+ }
+ return ret;
+}
+
+static int
+callback(void *udata, int ncol, char **data, char **cols)
+{
+ handle *h = (handle *) udata;
+ JNIEnv *env = h->env;
+
+ if (env && h->cb) {
+ jthrowable exc;
+ jclass cls = (*env)->GetObjectClass(env, h->cb);
+ jmethodID mid;
+ jobjectArray arr = 0;
+ jint i;
+
+ if (h->row1) {
+ mid = (*env)->GetMethodID(env, cls, "columns",
+ "([Ljava/lang/String;)V");
+
+ if (mid) {
+ arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0);
+ for (i = 0; i < ncol; i++) {
+ if (cols[i]) {
+ transstr col;
+
+ trans2utf(env, h->haveutf, h->enc, cols[i], &col);
+ (*env)->SetObjectArrayElement(env, arr, i, col.jstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, col.jstr);
+ }
+ }
+ h->row1 = 0;
+ (*env)->CallVoidMethod(env, h->cb, mid, arr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, arr);
+ }
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ mid = (*env)->GetMethodID(env, cls, "types",
+ "([Ljava/lang/String;)V");
+
+ if (mid && h->stmt) {
+ arr = (*env)->NewObjectArray(env, ncol,
+ C_java_lang_String, 0);
+ for (i = 0; i < ncol; i++) {
+ const char *ctype =
+ sqlite3_column_decltype(h->stmt, i);
+
+ if (!ctype) {
+ switch (sqlite3_column_type(h->stmt, i)) {
+ case SQLITE_INTEGER: ctype = "integer"; break;
+ case SQLITE_FLOAT: ctype = "double"; break;
+ default:
+#if defined(SQLITE_TEXT) && defined(SQLITE3_TEXT) && (SQLITE_TEXT != SQLITE3_TEXT)
+ case SQLITE_TEXT:
+#else
+#ifdef SQLITE3_TEXT
+ case SQLITE3_TEXT:
+#endif
+#endif
+ ctype = "text"; break;
+ case SQLITE_BLOB: ctype = "blob"; break;
+ case SQLITE_NULL: ctype = "null"; break;
+ }
+ }
+ if (ctype) {
+ transstr ty;
+
+ trans2utf(env, 1, 0, ctype, &ty);
+ (*env)->SetObjectArrayElement(env, arr, i,
+ ty.jstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, ty.jstr);
+ }
+ }
+ (*env)->CallVoidMethod(env, h->cb, mid, arr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, arr);
+ }
+ } else {
+ if (h->ver >= 0x020506 && cols[ncol]) {
+ mid = (*env)->GetMethodID(env, cls, "types",
+ "([Ljava/lang/String;)V");
+
+ if (mid) {
+ arr = (*env)->NewObjectArray(env, ncol,
+ C_java_lang_String, 0);
+ for (i = 0; i < ncol; i++) {
+ if (cols[i + ncol]) {
+ transstr ty;
+
+ trans2utf(env, h->haveutf, h->enc,
+ cols[i + ncol], &ty);
+ (*env)->SetObjectArrayElement(env, arr, i,
+ ty.jstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, ty.jstr);
+ }
+ }
+ (*env)->CallVoidMethod(env, h->cb, mid, arr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, arr);
+ }
+ }
+ }
+#else
+#if HAVE_SQLITE2
+ if (h->ver >= 0x020506 && cols[ncol]) {
+ mid = (*env)->GetMethodID(env, cls, "types",
+ "([Ljava/lang/String;)V");
+
+ if (mid) {
+ arr = (*env)->NewObjectArray(env, ncol,
+ C_java_lang_String, 0);
+ for (i = 0; i < ncol; i++) {
+ if (cols[i + ncol]) {
+ transstr ty;
+
+ trans2utf(env, h->haveutf, h->enc,
+ cols[i + ncol], &ty);
+ (*env)->SetObjectArrayElement(env, arr, i,
+ ty.jstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, ty.jstr);
+ }
+ }
+ (*env)->CallVoidMethod(env, h->cb, mid, arr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, arr);
+ }
+ }
+#endif
+#if HAVE_SQLITE3
+ mid = (*env)->GetMethodID(env, cls, "types",
+ "([Ljava/lang/String;)V");
+
+ if (mid && h->stmt) {
+ arr = (*env)->NewObjectArray(env, ncol,
+ C_java_lang_String, 0);
+ for (i = 0; i < ncol; i++) {
+ const char *ctype = sqlite3_column_decltype(h->stmt, i);
+
+ if (!ctype) {
+ switch (sqlite3_column_type(h->stmt, i)) {
+ case SQLITE_INTEGER: ctype = "integer"; break;
+ case SQLITE_FLOAT: ctype = "double"; break;
+ default:
+#if defined(SQLITE_TEXT) && defined(SQLITE3_TEXT) && (SQLITE_TEXT != SQLITE3_TEXT)
+ case SQLITE_TEXT:
+#else
+#ifdef SQLITE3_TEXT
+ case SQLITE3_TEXT:
+#endif
+#endif
+ ctype = "text"; break;
+ case SQLITE_BLOB: ctype = "blob"; break;
+ case SQLITE_NULL: ctype = "null"; break;
+ }
+ }
+ if (ctype) {
+ transstr ty;
+
+ trans2utf(env, 1, 0, ctype, &ty);
+ (*env)->SetObjectArrayElement(env, arr, i, ty.jstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, ty.jstr);
+ }
+ }
+ (*env)->CallVoidMethod(env, h->cb, mid, arr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, arr);
+ }
+#endif
+#endif
+ }
+ mid = (*env)->GetMethodID(env, cls, "newrow",
+ "([Ljava/lang/String;)Z");
+ if (mid) {
+ jboolean rc;
+
+ if (data) {
+ arr = (*env)->NewObjectArray(env, ncol, C_java_lang_String, 0);
+ } else {
+ arr = 0;
+ }
+ for (i = 0; arr && i < ncol; i++) {
+ if (data[i]) {
+ transstr dats;
+
+ trans2utf(env, h->haveutf, h->enc, data[i], &dats);
+ (*env)->SetObjectArrayElement(env, arr, i, dats.jstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ (*env)->DeleteLocalRef(env, dats.jstr);
+ }
+ }
+ rc = (*env)->CallBooleanMethod(env, h->cb, mid, arr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return 1;
+ }
+ if (arr) {
+ (*env)->DeleteLocalRef(env, arr);
+ }
+ (*env)->DeleteLocalRef(env, cls);
+ return rc != JNI_FALSE;
+ }
+ }
+ return 0;
+}
+
+static void
+doclose(JNIEnv *env, jobject obj, int final)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h) {
+ hfunc *f;
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ hbl *bl;
+#endif
+#if HAVE_SQLITE_COMPILE
+ hvm *v;
+
+ while ((v = h->vms)) {
+ h->vms = v->next;
+ v->next = 0;
+ v->h = 0;
+ if (v->vm) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+ } else {
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+#endif
+#endif
+ v->vm = 0;
+ }
+ }
+#endif
+ if (h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_close((sqlite3 *) h->sqlite);
+ } else {
+ sqlite_close((sqlite *) h->sqlite);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_close((sqlite *) h->sqlite);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_close((sqlite3 *) h->sqlite);
+#endif
+#endif
+ h->sqlite = 0;
+ }
+ while ((f = h->funcs)) {
+ h->funcs = f->next;
+ f->h = 0;
+ f->sf = 0;
+ f->env = 0;
+ if (f->fc) {
+ (*env)->SetLongField(env, f->fc,
+ F_SQLite_FunctionContext_handle, 0);
+ }
+ delglobrefp(env, &f->db);
+ delglobrefp(env, &f->fi);
+ delglobrefp(env, &f->fc);
+ free(f);
+ }
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ while ((bl = h->blobs)) {
+ h->blobs = bl->next;
+ bl->next = 0;
+ bl->h = 0;
+ if (bl->blob) {
+ sqlite3_blob_close(bl->blob);
+ }
+ bl->blob = 0;
+ }
+#endif
+ delglobrefp(env, &h->bh);
+ delglobrefp(env, &h->cb);
+ delglobrefp(env, &h->ai);
+ delglobrefp(env, &h->tr);
+ delglobrefp(env, &h->ph);
+ delglobrefp(env, &h->enc);
+ free(h);
+ (*env)->SetLongField(env, obj, F_SQLite_Database_handle, 0);
+ return;
+ }
+ if (!final) {
+ throwclosed(env);
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1close(JNIEnv *env, jobject obj)
+{
+ doclose(env, obj, 0);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1finalize(JNIEnv *env, jobject obj)
+{
+ doclose(env, obj, 1);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1busy_1timeout(JNIEnv *env, jobject obj, jint ms)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_busy_timeout((sqlite3 * ) h->sqlite, ms);
+ } else {
+ sqlite_busy_timeout((sqlite *) h->sqlite, ms);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_busy_timeout((sqlite *) h->sqlite, ms);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_busy_timeout((sqlite3 * ) h->sqlite, ms);
+#endif
+#endif
+ return;
+ }
+ throwclosed(env);
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Database_version(JNIEnv *env, jclass cls)
+{
+ /* CHECK THIS */
+#if HAVE_BOTH_SQLITE
+ return (*env)->NewStringUTF(env, sqlite_libversion());
+#else
+#if HAVE_SQLITE2
+ return (*env)->NewStringUTF(env, sqlite_libversion());
+#else
+ return (*env)->NewStringUTF(env, sqlite3_libversion());
+#endif
+#endif
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Database_dbversion(JNIEnv *env, jobject obj)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ return (*env)->NewStringUTF(env, sqlite3_libversion());
+ } else {
+ return (*env)->NewStringUTF(env, sqlite_libversion());
+ }
+#else
+#if HAVE_SQLITE2
+ return (*env)->NewStringUTF(env, sqlite_libversion());
+#else
+ return (*env)->NewStringUTF(env, sqlite3_libversion());
+#endif
+#endif
+ }
+ return (*env)->NewStringUTF(env, "unknown");
+}
+
+JNIEXPORT jlong JNICALL
+Java_SQLite_Database__1last_1insert_1rowid(JNIEnv *env, jobject obj)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ return (jlong) sqlite3_last_insert_rowid((sqlite3 *) h->sqlite);
+ } else {
+ return (jlong) sqlite_last_insert_rowid((sqlite *) h->sqlite);
+ }
+#else
+#if HAVE_SQLITE2
+ return (jlong) sqlite_last_insert_rowid((sqlite *) h->sqlite);
+#endif
+#if HAVE_SQLITE3
+ return (jlong) sqlite3_last_insert_rowid((sqlite3 *) h->sqlite);
+#endif
+#endif
+ }
+ throwclosed(env);
+ return (jlong) 0;
+}
+
+JNIEXPORT jlong JNICALL
+Java_SQLite_Database__1changes(JNIEnv *env, jobject obj)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ return (jlong) sqlite3_changes((sqlite3 *) h->sqlite);
+ } else {
+ return (jlong) sqlite_changes((sqlite *) h->sqlite);
+ }
+#else
+#if HAVE_SQLITE2
+ return (jlong) sqlite_changes((sqlite *) h->sqlite);
+#endif
+#if HAVE_SQLITE3
+ return (jlong) sqlite3_changes((sqlite3 *) h->sqlite);
+#endif
+#endif
+ }
+ throwclosed(env);
+ return (jlong) 0;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_SQLite_Database__1complete(JNIEnv *env, jclass cls, jstring sql)
+{
+ transstr sqlstr;
+ jboolean result;
+
+ if (!sql) {
+ return JNI_FALSE;
+ }
+#if HAVE_BOTH_SQLITE || HAVE_SQLITE3
+ /* CHECK THIS */
+ trans2iso(env, 1, 0, sql, &sqlstr);
+ result = sqlite3_complete(sqlstr.result) ? JNI_TRUE : JNI_FALSE;
+#else
+ trans2iso(env, strcmp(sqlite_libencoding(), "UTF-8") == 0, 0,
+ sql, &sqlstr);
+ result = sqlite_complete(sqlstr.result) ? JNI_TRUE : JNI_FALSE;
+#endif
+ transfree(&sqlstr);
+ return result;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1interrupt(JNIEnv *env, jobject obj)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_interrupt((sqlite3 *) h->sqlite);
+ } else {
+ sqlite_interrupt((sqlite *) h->sqlite);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_interrupt((sqlite *) h->sqlite);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_interrupt((sqlite3 *) h->sqlite);
+#endif
+#endif
+ return;
+ }
+ throwclosed(env);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1open(JNIEnv *env, jobject obj, jstring file, jint mode)
+{
+ handle *h = gethandle(env, obj);
+ jthrowable exc;
+ char *err = 0;
+ transstr filename;
+ int maj, min, lev;
+
+ if (h) {
+ if (h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_close((sqlite3 *) h->sqlite);
+ } else {
+ sqlite_close((sqlite *) h->sqlite);
+ }
+ h->is3 = 0;
+#else
+#if HAVE_SQLITE2
+ sqlite_close((sqlite *) h->sqlite);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_close((sqlite3 *) h->sqlite);
+#endif
+#endif
+ h->sqlite = 0;
+ }
+ } else {
+ h = malloc(sizeof (handle));
+ if (!h) {
+ throwoom(env, "unable to get SQLite handle");
+ return;
+ }
+ h->sqlite = 0;
+ h->bh = h->cb = h->ai = h->tr = h->ph = 0;
+ /* CHECK THIS */
+#if HAVE_BOTH_SQLITE
+ h->is3 = 0;
+ h->stmt = 0;
+ h->haveutf = 1;
+#else
+#if HAVE_SQLITE2
+ h->haveutf = strcmp(sqlite_libencoding(), "UTF-8") == 0;
+#endif
+#if HAVE_SQLITE3
+ h->stmt = 0;
+ h->haveutf = 1;
+#endif
+#endif
+ h->enc = 0;
+ h->funcs = 0;
+ h->ver = 0;
+#if HAVE_SQLITE_COMPILE
+ h->vms = 0;
+#endif
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ h->blobs = 0;
+#endif
+ }
+ h->env = 0;
+ if (!file) {
+ throwex(env, err ? err : "invalid file name");
+ return;
+ }
+ trans2iso(env, h->haveutf, h->enc, file, &filename);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+#if HAVE_BOTH_SQLITE
+ {
+ FILE *f = fopen(filename.result, "rb");
+ int c_0 = EOF;
+
+ if (f) {
+ c_0 = fgetc(f);
+ fclose(f);
+ }
+ if (c_0 != '*') {
+ int rc = sqlite3_open(filename.result, (sqlite3 **) &h->sqlite);
+
+ if (rc == SQLITE_OK) {
+ h->is3 = 1;
+ } else if (h->sqlite) {
+ sqlite3_close((sqlite3 *) h->sqlite);
+ h->sqlite = 0;
+ }
+ } else {
+ h->sqlite = (void *) sqlite_open(filename.result,
+ (int) mode, &err);
+ }
+ }
+#else
+#if HAVE_SQLITE2
+ h->sqlite = (void *) sqlite_open(filename.result, (int) mode, &err);
+#endif
+#if HAVE_SQLITE3
+ if (sqlite3_open(filename.result, (sqlite3 **) &h->sqlite) != SQLITE_OK) {
+ if (h->sqlite) {
+ sqlite3_close((sqlite3 *) h->sqlite);
+ h->sqlite = 0;
+ }
+ }
+#endif
+#endif
+ transfree(&filename);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+#if HAVE_SQLITE2
+ if (err) {
+ sqlite_freemem(err);
+ }
+#endif
+ if (h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_close((sqlite3 *) h->sqlite);
+ h->is3 = 0;
+ } else {
+ sqlite_close((sqlite *) h->sqlite);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_close((sqlite *) h->sqlite);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_close((sqlite3 *) h->sqlite);
+#endif
+#endif
+ }
+ h->sqlite = 0;
+ return;
+ }
+ if (h->sqlite) {
+ jvalue v;
+
+ v.j = 0;
+ v.l = (jobject) h;
+ (*env)->SetLongField(env, obj, F_SQLite_Database_handle, v.j);
+#if HAVE_SQLITE2
+ if (err) {
+ sqlite_freemem(err);
+ }
+#endif
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev);
+ } else {
+ sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev);
+ }
+#else
+#if HAVE_SQLITE2
+ sscanf(sqlite_libversion(), "%d.%d.%d", &maj, &min, &lev);
+#endif
+#if HAVE_SQLITE3
+ sscanf(sqlite3_libversion(), "%d.%d.%d", &maj, &min, &lev);
+#endif
+#endif
+ h->ver = ((maj & 0xFF) << 16) | ((min & 0xFF) << 8) | (lev & 0xFF);
+ return;
+ }
+ throwex(env, err ? err : "unknown error in open");
+#if HAVE_SQLITE2
+ if (err) {
+ sqlite_freemem(err);
+ }
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1open_1aux_1file(JNIEnv *env, jobject obj, jstring file)
+{
+ handle *h = gethandle(env, obj);
+#if HAVE_SQLITE_OPEN_AUX_FILE
+ jboolean b;
+ jthrowable exc;
+ char *err = 0;
+ transstr filename;
+ int ret;
+#endif
+
+ if (h && h->sqlite) {
+#if HAVE_SQLITE_OPEN_AUX_FILE
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ throwex(env, "unsupported");
+ }
+#endif
+ trans2iso(env, h->haveutf, h->enc, file, &filename);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ ret = sqlite_open_aux_file((sqlite *) h->sqlite,
+ filename.result, &err);
+ transfree(&filename);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ if (err) {
+ sqlite_freemem(err);
+ }
+ return;
+ }
+ if (ret != SQLITE_OK) {
+ throwex(env, err ? err : sqlite_error_string(ret));
+ }
+ if (err) {
+ sqlite_freemem(err);
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+ return;
+ }
+ throwclosed(env);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1busy_1handler(JNIEnv *env, jobject obj, jobject bh)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+ delglobrefp(env, &h->bh);
+ globrefset(env, bh, &h->bh);
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_busy_handler((sqlite3 *) h->sqlite, busyhandler3, h);
+ } else {
+ sqlite_busy_handler((sqlite *) h->sqlite, busyhandler, h);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_busy_handler((sqlite *) h->sqlite, busyhandler, h);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_busy_handler((sqlite3 *) h->sqlite, busyhandler3, h);
+#endif
+#endif
+ return;
+ }
+ throwclosed(env);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2
+ (JNIEnv *env, jobject obj, jstring sql, jobject cb)
+{
+ handle *h = gethandle(env, obj);
+ freemem *freeproc;
+
+ if (!sql) {
+ throwex(env, "invalid SQL statement");
+ return;
+ }
+ if (h) {
+ if (h->sqlite) {
+ jthrowable exc;
+ int rc;
+ char *err = 0;
+ transstr sqlstr;
+ jobject oldcb = globrefpop(env, &h->cb);
+
+ globrefset(env, cb, &h->cb);
+ h->env = env;
+ h->row1 = 1;
+ trans2iso(env, h->haveutf, h->enc, sql, &sqlstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ rc = sqlite3_exec((sqlite3 *) h->sqlite, sqlstr.result,
+ callback, h, &err);
+ freeproc = (freemem *) sqlite3_free;
+ } else {
+ rc = sqlite_exec((sqlite *) h->sqlite, sqlstr.result,
+ callback, h, &err);
+ freeproc = (freemem *) sqlite_freemem;
+ }
+#else
+#if HAVE_SQLITE2
+ rc = sqlite_exec((sqlite *) h->sqlite, sqlstr.result,
+ callback, h, &err);
+ freeproc = (freemem *) sqlite_freemem;
+#endif
+#if HAVE_SQLITE3
+ rc = sqlite3_exec((sqlite3 *) h->sqlite, sqlstr.result,
+ callback, h, &err);
+ freeproc = (freemem *) sqlite3_free;
+#endif
+#endif
+ transfree(&sqlstr);
+ exc = (*env)->ExceptionOccurred(env);
+ delglobrefp(env, &h->cb);
+ h->cb = oldcb;
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ if (err) {
+ freeproc(err);
+ }
+ return;
+ }
+ if (rc != SQLITE_OK) {
+ char msg[128];
+
+ seterr(env, obj, rc);
+ if (!err) {
+ sprintf(msg, "error %d in sqlite*_exec", rc);
+ }
+ throwex(env, err ? err : msg);
+ }
+ if (err) {
+ freeproc(err);
+ }
+ return;
+ }
+ }
+ throwclosed(env);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2
+ (JNIEnv *env, jobject obj, jstring sql, jobject cb, jobjectArray args)
+{
+ handle *h = gethandle(env, obj);
+ freemem *freeproc = 0;
+
+ if (!sql) {
+ throwex(env, "invalid SQL statement");
+ return;
+ }
+ if (h) {
+ if (h->sqlite) {
+ jboolean b;
+ jthrowable exc;
+ int rc = SQLITE_ERROR, nargs, i;
+ char *err = 0, *p;
+ const char *str = (*env)->GetStringUTFChars(env, sql, &b);
+ transstr sqlstr;
+ struct args {
+ char *arg;
+ jobject obj;
+ transstr trans;
+ } *argv = 0;
+ char **cargv = 0;
+ jobject oldcb = globrefpop(env, &h->cb);
+
+ globrefset(env, cb, &h->cb);
+ p = (char *) str;
+ nargs = 0;
+ while (*p) {
+ if (*p == '%') {
+ ++p;
+ if (*p == 'q' || *p == 's') {
+ nargs++;
+ if (nargs > MAX_PARAMS) {
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ delglobrefp(env, &h->cb);
+ h->cb = oldcb;
+ throwex(env, "too much SQL parameters");
+ return;
+ }
+ } else if (h->ver >= 0x020500 && *p == 'Q') {
+ nargs++;
+ if (nargs > MAX_PARAMS) {
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ delglobrefp(env, &h->cb);
+ h->cb = oldcb;
+ throwex(env, "too much SQL parameters");
+ return;
+ }
+ } else if (*p != '%') {
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ delglobrefp(env, &h->cb);
+ h->cb = oldcb;
+ throwex(env, "bad % specification in query");
+ return;
+ }
+ }
+ ++p;
+ }
+ cargv = malloc((sizeof (*argv) + sizeof (char *))
+ * MAX_PARAMS);
+ if (!cargv) {
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ delglobrefp(env, &h->cb);
+ h->cb = oldcb;
+ throwoom(env, "unable to allocate arg vector");
+ return;
+ }
+ argv = (struct args *) (cargv + MAX_PARAMS);
+ for (i = 0; i < MAX_PARAMS; i++) {
+ cargv[i] = 0;
+ argv[i].arg = 0;
+ argv[i].obj = 0;
+ argv[i].trans.result = argv[i].trans.tofree = 0;
+ }
+ exc = 0;
+ for (i = 0; i < nargs; i++) {
+ jobject so = (*env)->GetObjectArrayElement(env, args, i);
+
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ break;
+ }
+ if (so) {
+ argv[i].obj = so;
+ argv[i].arg = cargv[i] =
+ trans2iso(env, h->haveutf, h->enc, argv[i].obj,
+ &argv[i].trans);
+ }
+ }
+ if (exc) {
+ for (i = 0; i < nargs; i++) {
+ if (argv[i].obj) {
+ transfree(&argv[i].trans);
+ }
+ }
+ freep((char **) &cargv);
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ delglobrefp(env, &h->cb);
+ h->cb = oldcb;
+ return;
+ }
+ h->env = env;
+ h->row1 = 1;
+ trans2iso(env, h->haveutf, h->enc, sql, &sqlstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (!exc) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+ char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
+#else
+ char *s = sqlite3_mprintf(sqlstr.result,
+ cargv[0], cargv[1],
+ cargv[2], cargv[3],
+ cargv[4], cargv[5],
+ cargv[6], cargv[7],
+ cargv[8], cargv[9],
+ cargv[10], cargv[11],
+ cargv[12], cargv[13],
+ cargv[14], cargv[15],
+ cargv[16], cargv[17],
+ cargv[18], cargv[19],
+ cargv[20], cargv[21],
+ cargv[22], cargv[23],
+ cargv[24], cargv[25],
+ cargv[26], cargv[27],
+ cargv[28], cargv[29],
+ cargv[30], cargv[31]);
+#endif
+
+ if (s) {
+ rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback,
+ h, &err);
+ sqlite3_free(s);
+ } else {
+ rc = SQLITE_NOMEM;
+ }
+ freeproc = (freemem *) sqlite3_free;
+ } else {
+#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+ rc = sqlite_exec_vprintf((sqlite *) h->sqlite,
+ sqlstr.result, callback, h, &err,
+ (char *) cargv);
+#else
+ rc = sqlite_exec_printf((sqlite *) h->sqlite,
+ sqlstr.result, callback,
+ h, &err,
+ cargv[0], cargv[1],
+ cargv[2], cargv[3],
+ cargv[4], cargv[5],
+ cargv[6], cargv[7],
+ cargv[8], cargv[9],
+ cargv[10], cargv[11],
+ cargv[12], cargv[13],
+ cargv[14], cargv[15],
+ cargv[16], cargv[17],
+ cargv[18], cargv[19],
+ cargv[20], cargv[21],
+ cargv[22], cargv[23],
+ cargv[24], cargv[25],
+ cargv[26], cargv[27],
+ cargv[28], cargv[29],
+ cargv[30], cargv[31]);
+#endif
+ freeproc = (freemem *) sqlite_freemem;
+ }
+#else
+#if HAVE_SQLITE2
+#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+ rc = sqlite_exec_vprintf((sqlite *) h->sqlite, sqlstr.result,
+ callback, h, &err, (char *) cargv);
+#else
+ rc = sqlite_exec_printf((sqlite *) h->sqlite, sqlstr.result,
+ callback, h, &err,
+ cargv[0], cargv[1],
+ cargv[2], cargv[3],
+ cargv[4], cargv[5],
+ cargv[6], cargv[7],
+ cargv[8], cargv[9],
+ cargv[10], cargv[11],
+ cargv[12], cargv[13],
+ cargv[14], cargv[15],
+ cargv[16], cargv[17],
+ cargv[18], cargv[19],
+ cargv[20], cargv[21],
+ cargv[22], cargv[23],
+ cargv[24], cargv[25],
+ cargv[26], cargv[27],
+ cargv[28], cargv[29],
+ cargv[30], cargv[31]);
+#endif
+ freeproc = (freemem *) sqlite_freemem;
+#endif
+#if HAVE_SQLITE3
+#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+ char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
+#else
+ char *s = sqlite3_mprintf(sqlstr.result,
+ cargv[0], cargv[1],
+ cargv[2], cargv[3],
+ cargv[4], cargv[5],
+ cargv[6], cargv[7],
+ cargv[8], cargv[9],
+ cargv[10], cargv[11],
+ cargv[12], cargv[13],
+ cargv[14], cargv[15],
+ cargv[16], cargv[17],
+ cargv[18], cargv[19],
+ cargv[20], cargv[21],
+ cargv[22], cargv[23],
+ cargv[24], cargv[25],
+ cargv[26], cargv[27],
+ cargv[28], cargv[29],
+ cargv[30], cargv[31]);
+#endif
+
+ if (s) {
+ rc = sqlite3_exec((sqlite3 *) h->sqlite, s, callback,
+ h, &err);
+ sqlite3_free(s);
+ } else {
+ rc = SQLITE_NOMEM;
+ }
+ freeproc = (freemem *) sqlite3_free;
+#endif
+#endif
+ exc = (*env)->ExceptionOccurred(env);
+ }
+ for (i = 0; i < nargs; i++) {
+ if (argv[i].obj) {
+ transfree(&argv[i].trans);
+ }
+ }
+ transfree(&sqlstr);
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ freep((char **) &cargv);
+ delglobrefp(env, &h->cb);
+ h->cb = oldcb;
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ if (err && freeproc) {
+ freeproc(err);
+ }
+ return;
+ }
+ if (rc != SQLITE_OK) {
+ char msg[128];
+
+ seterr(env, obj, rc);
+ if (!err) {
+ sprintf(msg, "error %d in sqlite*_exec", rc);
+ }
+ throwex(env, err ? err : msg);
+ }
+ if (err && freeproc) {
+ freeproc(err);
+ }
+ return;
+ }
+ }
+ throwclosed(env);
+}
+
+static hfunc *
+getfunc(JNIEnv *env, jobject obj)
+{
+ jvalue v;
+
+ v.j = (*env)->GetLongField(env, obj, F_SQLite_FunctionContext_handle);
+ return (hfunc *) v.l;
+}
+
+#if HAVE_SQLITE2
+static void
+call_common(sqlite_func *sf, int isstep, int nargs, const char **args)
+{
+ hfunc *f = (hfunc *) sqlite_user_data(sf);
+
+ if (f && f->env && f->fi) {
+ JNIEnv *env = f->env;
+ jclass cls = (*env)->GetObjectClass(env, f->fi);
+ jmethodID mid =
+ (*env)->GetMethodID(env, cls,
+ isstep ? "step" : "function",
+ "(LSQLite/FunctionContext;[Ljava/lang/String;)V");
+ jobjectArray arr;
+ int i;
+
+ if (mid == 0) {
+ return;
+ }
+ arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
+ for (i = 0; i < nargs; i++) {
+ if (args[i]) {
+ transstr arg;
+ jthrowable exc;
+
+ trans2utf(env, f->h->haveutf, f->h->enc, args[i], &arg);
+ (*env)->SetObjectArrayElement(env, arr, i, arg.jstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ (*env)->DeleteLocalRef(env, arg.jstr);
+ }
+ }
+ f->sf = sf;
+ (*env)->CallVoidMethod(env, f->fi, mid, f->fc, arr);
+ (*env)->DeleteLocalRef(env, arr);
+ (*env)->DeleteLocalRef(env, cls);
+ }
+}
+
+static void
+call_func(sqlite_func *sf, int nargs, const char **args)
+{
+ call_common(sf, 0, nargs, args);
+}
+
+static void
+call_step(sqlite_func *sf, int nargs, const char **args)
+{
+ call_common(sf, 1, nargs, args);
+}
+
+static void
+call_final(sqlite_func *sf)
+{
+ hfunc *f = (hfunc *) sqlite_user_data(sf);
+
+ if (f && f->env && f->fi) {
+ JNIEnv *env = f->env;
+ jclass cls = (*env)->GetObjectClass(env, f->fi);
+ jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
+ "(LSQLite/FunctionContext;)V");
+ if (mid == 0) {
+ return;
+ }
+ f->sf = sf;
+ (*env)->CallVoidMethod(env, f->fi, mid, f->fc);
+ (*env)->DeleteLocalRef(env, cls);
+ }
+}
+#endif
+
+#if HAVE_SQLITE3
+static void
+call3_common(sqlite3_context *sf, int isstep, int nargs, sqlite3_value **args)
+{
+ hfunc *f = (hfunc *) sqlite3_user_data(sf);
+
+ if (f && f->env && f->fi) {
+ JNIEnv *env = f->env;
+ jclass cls = (*env)->GetObjectClass(env, f->fi);
+ jmethodID mid =
+ (*env)->GetMethodID(env, cls,
+ isstep ? "step" : "function",
+ "(LSQLite/FunctionContext;[Ljava/lang/String;)V");
+ jobjectArray arr;
+ int i;
+
+ if (mid == 0) {
+ return;
+ }
+ arr = (*env)->NewObjectArray(env, nargs, C_java_lang_String, 0);
+ for (i = 0; i < nargs; i++) {
+ if (args[i]) {
+ transstr arg;
+ jthrowable exc;
+
+ trans2utf(env, 1, 0, (char *) sqlite3_value_text(args[i]),
+ &arg);
+ (*env)->SetObjectArrayElement(env, arr, i, arg.jstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ (*env)->DeleteLocalRef(env, arg.jstr);
+ }
+ }
+ f->sf = sf;
+ (*env)->CallVoidMethod(env, f->fi, mid, f->fc, arr);
+ (*env)->DeleteLocalRef(env, arr);
+ (*env)->DeleteLocalRef(env, cls);
+ }
+}
+
+static void
+call3_func(sqlite3_context *sf, int nargs, sqlite3_value **args)
+{
+ call3_common(sf, 0, nargs, args);
+}
+
+static void
+call3_step(sqlite3_context *sf, int nargs, sqlite3_value **args)
+{
+ call3_common(sf, 1, nargs, args);
+}
+
+static void
+call3_final(sqlite3_context *sf)
+{
+ hfunc *f = (hfunc *) sqlite3_user_data(sf);
+
+ if (f && f->env && f->fi) {
+ JNIEnv *env = f->env;
+ jclass cls = (*env)->GetObjectClass(env, f->fi);
+ jmethodID mid = (*env)->GetMethodID(env, cls, "last_step",
+ "(LSQLite/FunctionContext;)V");
+ if (mid == 0) {
+ return;
+ }
+ f->sf = sf;
+ (*env)->CallVoidMethod(env, f->fi, mid, f->fc);
+ (*env)->DeleteLocalRef(env, cls);
+ }
+}
+#endif
+
+static void
+mkfunc_common(JNIEnv *env, int isagg, jobject obj, jstring name,
+ jint nargs, jobject fi)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+ jclass cls = (*env)->FindClass(env, "SQLite/FunctionContext");
+ jobject fc;
+ hfunc *f;
+ int ret;
+ transstr namestr;
+ jvalue v;
+ jthrowable exc;
+
+ fc = (*env)->AllocObject(env, cls);
+ if (!fi) {
+ throwex(env, "null SQLite.Function not allowed");
+ return;
+ }
+ f = malloc(sizeof (hfunc));
+ if (!f) {
+ throwoom(env, "unable to get SQLite.FunctionContext handle");
+ return;
+ }
+ globrefset(env, fc, &f->fc);
+ globrefset(env, fi, &f->fi);
+ globrefset(env, obj, &f->db);
+ f->h = h;
+ f->next = h->funcs;
+ h->funcs = f;
+ f->sf = 0;
+ f->env = env;
+ v.j = 0;
+ v.l = (jobject) f;
+ (*env)->SetLongField(env, f->fc, F_SQLite_FunctionContext_handle, v.j);
+ trans2iso(env, h->haveutf, h->enc, name, &namestr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+#if HAVE_BOTH_SQLITE
+ f->is3 = h->is3;
+ if (h->is3) {
+ ret = sqlite3_create_function((sqlite3 *) h->sqlite,
+ namestr.result,
+ (int) nargs,
+ SQLITE_UTF8, f,
+ isagg ? NULL : call3_func,
+ isagg ? call3_step : NULL,
+ isagg ? call3_final : NULL);
+
+ } else {
+ if (isagg) {
+ ret = sqlite_create_aggregate((sqlite *) h->sqlite,
+ namestr.result,
+ (int) nargs,
+ call_step, call_final, f);
+ } else {
+ ret = sqlite_create_function((sqlite *) h->sqlite,
+ namestr.result,
+ (int) nargs,
+ call_func, f);
+ }
+ }
+#else
+#if HAVE_SQLITE2
+ if (isagg) {
+ ret = sqlite_create_aggregate((sqlite *) h->sqlite, namestr.result,
+ (int) nargs,
+ call_step, call_final, f);
+ } else {
+ ret = sqlite_create_function((sqlite *) h->sqlite, namestr.result,
+ (int) nargs,
+ call_func, f);
+ }
+#endif
+#if HAVE_SQLITE3
+ ret = sqlite3_create_function((sqlite3 *) h->sqlite,
+ namestr.result,
+ (int) nargs,
+ SQLITE_UTF8, f,
+ isagg ? NULL : call3_func,
+ isagg ? call3_step : NULL,
+ isagg ? call3_final : NULL);
+#endif
+#endif
+ transfree(&namestr);
+ if (ret != SQLITE_OK) {
+ throwex(env, "error creating function/aggregate");
+ }
+ return;
+ }
+ throwclosed(env);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1create_1aggregate(JNIEnv *env, jobject obj,
+ jstring name, jint nargs, jobject fi)
+{
+ mkfunc_common(env, 1, obj, name, nargs, fi);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1create_1function(JNIEnv *env, jobject obj,
+ jstring name, jint nargs, jobject fi)
+{
+ mkfunc_common(env, 0, obj, name, nargs, fi);
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1function_1type(JNIEnv *env, jobject obj,
+ jstring name, jint type)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ return;
+ }
+#endif
+#if HAVE_SQLITE2
+#if HAVE_SQLITE_FUNCTION_TYPE
+ {
+ int ret;
+ transstr namestr;
+ jthrowable exc;
+
+ trans2iso(env, h->haveutf, h->enc, name, &namestr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ ret = sqlite_function_type(h->sqlite, namestr.result, (int) type);
+ transfree(&namestr);
+ if (ret != SQLITE_OK) {
+ throwex(env, sqlite_error_string(ret));
+ }
+ }
+#endif
+#endif
+ return;
+ }
+ throwclosed(env);
+}
+
+JNIEXPORT jint JNICALL
+Java_SQLite_FunctionContext_count(JNIEnv *env, jobject obj)
+{
+ hfunc *f = getfunc(env, obj);
+ jint r = 0;
+
+ if (f && f->sf) {
+#if HAVE_SQLITE_BOTH
+ if (f->is3) {
+ r = (jint) sqlite3_aggregate_count((sqlite3_context *) f->sf);
+ } else {
+ r = (jint) sqlite_aggregate_count((sqlite_func *) f->sf);
+ }
+#else
+#if HAVE_SQLITE2
+ r = (jint) sqlite_aggregate_count((sqlite_func *) f->sf);
+#endif
+#if HAVE_SQLITE3
+ r = (jint) sqlite3_aggregate_count((sqlite3_context *) f->sf);
+#endif
+#endif
+ }
+ return r;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_FunctionContext_set_1error(JNIEnv *env, jobject obj, jstring err)
+{
+ hfunc *f = getfunc(env, obj);
+
+ if (f && f->sf) {
+#if HAVE_BOTH_SQLITE
+ if (!f->is3) {
+ transstr errstr;
+ jthrowable exc;
+
+ trans2iso(env, f->h->haveutf, f->h->enc, err, &errstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ sqlite_set_result_error((sqlite_func *) f->sf,
+ errstr.result, -1);
+ transfree(&errstr);
+ } else if (err) {
+ jsize len = (*env)->GetStringLength(env, err) * sizeof (jchar);
+ const jchar *str = (*env)->GetStringChars(env, err, 0);
+
+ sqlite3_result_error16((sqlite3_context *) f->sf, str, len);
+ (*env)->ReleaseStringChars(env, err, str);
+ } else {
+ sqlite3_result_error((sqlite3_context *) f->sf,
+ "null error text", -1);
+ }
+#else
+#if HAVE_SQLITE2
+ transstr errstr;
+ jthrowable exc;
+
+ trans2iso(env, f->h->haveutf, f->h->enc, err, &errstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ sqlite_set_result_error((sqlite_func *) f->sf, errstr.result, -1);
+ transfree(&errstr);
+#endif
+#if HAVE_SQLITE3
+ if (err) {
+ jsize len = (*env)->GetStringLength(env, err) * sizeof (jchar);
+ const jchar *str = (*env)->GetStringChars(env, err, 0);
+
+ sqlite3_result_error16((sqlite3_context *) f->sf, str, len);
+ (*env)->ReleaseStringChars(env, err, str);
+ } else {
+ sqlite3_result_error((sqlite3_context *) f->sf,
+ "null error text", -1);
+ }
+#endif
+#endif
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_FunctionContext_set_1result__D(JNIEnv *env, jobject obj, jdouble d)
+{
+ hfunc *f = getfunc(env, obj);
+
+ if (f && f->sf) {
+#if HAVE_BOTH_SQLITE
+ if (f->is3) {
+ sqlite3_result_double((sqlite3_context *) f->sf, (double) d);
+ } else {
+ sqlite_set_result_double((sqlite_func *) f->sf, (double) d);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_set_result_double((sqlite_func *) f->sf, (double) d);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_result_double((sqlite3_context *) f->sf, (double) d);
+#endif
+#endif
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_FunctionContext_set_1result__I(JNIEnv *env, jobject obj, jint i)
+{
+ hfunc *f = getfunc(env, obj);
+
+ if (f && f->sf) {
+#if HAVE_BOTH_SQLITE
+ if (f->is3) {
+ sqlite3_result_int((sqlite3_context *) f->sf, (int) i);
+ } else {
+ sqlite_set_result_int((sqlite_func *) f->sf, (int) i);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_set_result_int((sqlite_func *) f->sf, (int) i);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_result_int((sqlite3_context *) f->sf, (int) i);
+#endif
+#endif
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_FunctionContext_set_1result__Ljava_lang_String_2(JNIEnv *env,
+ jobject obj,
+ jstring ret)
+{
+ hfunc *f = getfunc(env, obj);
+
+ if (f && f->sf) {
+#if HAVE_BOTH_SQLITE
+ if (!f->is3) {
+ transstr retstr;
+ jthrowable exc;
+
+ trans2iso(env, f->h->haveutf, f->h->enc, ret, &retstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ sqlite_set_result_string((sqlite_func *) f->sf,
+ retstr.result, -1);
+ transfree(&retstr);
+ } else if (ret) {
+ jsize len = (*env)->GetStringLength(env, ret) * sizeof (jchar);
+ const jchar *str = (*env)->GetStringChars(env, ret, 0);
+
+ sqlite3_result_text16((sqlite3_context *) f->sf, str, len,
+ SQLITE_TRANSIENT);
+ (*env)->ReleaseStringChars(env, ret, str);
+ } else {
+ sqlite3_result_null((sqlite3_context *) f->sf);
+ }
+#else
+#if HAVE_SQLITE2
+ transstr retstr;
+ jthrowable exc;
+
+ trans2iso(env, f->h->haveutf, f->h->enc, ret, &retstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ sqlite_set_result_string((sqlite_func *) f->sf, retstr.result, -1);
+ transfree(&retstr);
+#endif
+#if HAVE_SQLITE3
+ if (ret) {
+ jsize len = (*env)->GetStringLength(env, ret) * sizeof (jchar);
+ const jchar *str = (*env)->GetStringChars(env, ret, 0);
+
+ sqlite3_result_text16((sqlite3_context *) f->sf, str, len,
+ SQLITE_TRANSIENT);
+ (*env)->ReleaseStringChars(env, ret, str);
+ } else {
+ sqlite3_result_null((sqlite3_context *) f->sf);
+ }
+#endif
+#endif
+ }
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_FunctionContext_set_1result___3B(JNIEnv *env, jobject obj,
+ jbyteArray b)
+{
+#if HAVE_SQLITE3
+ hfunc *f = getfunc(env, obj);
+
+ if (f && f->sf) {
+#if HAVE_BOTH_SQLITE
+ if (!f->is3) {
+ /* silently ignored */
+ return;
+ }
+#endif
+ if (b) {
+ jsize len;
+ jbyte *data;
+
+ len = (*env)->GetArrayLength(env, b);
+ data = (*env)->GetByteArrayElements(env, b, 0);
+ sqlite3_result_blob((sqlite3_context *) f->sf,
+ data, len, SQLITE_TRANSIENT);
+ (*env)->ReleaseByteArrayElements(env, b, data, 0);
+ } else {
+ sqlite3_result_null((sqlite3_context *) f->sf);
+ }
+ }
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_FunctionContext_set_1result_1zeroblob(JNIEnv *env, jobject obj,
+ jint n)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_RESULT_ZEROBLOB
+ hfunc *f = getfunc(env, obj);
+
+ if (f && f->sf) {
+#if HAVE_BOTH_SQLITE
+ if (!f->is3) {
+ /* silently ignored */
+ return;
+ }
+#endif
+ sqlite3_result_zeroblob((sqlite3_context *) f->sf, n);
+ }
+#endif
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Database_error_1string(JNIEnv *env, jclass c, jint err)
+{
+#if HAVE_SQLITE2
+ return (*env)->NewStringUTF(env, sqlite_error_string((int) err));
+#else
+ return (*env)->NewStringUTF(env, "unkown error");
+#endif
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Database__1errmsg(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+#if HAVE_BOTH_SQLITE
+ if (!h->is3) {
+ return 0;
+ }
+#endif
+ return (*env)->NewStringUTF(env,
+ sqlite3_errmsg((sqlite3 *) h->sqlite));
+ }
+#endif
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1set_1encoding(JNIEnv *env, jobject obj, jstring enc)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && !h->haveutf) {
+#if HAVE_BOTH_SQLITE
+ if (!h->is3) {
+ delglobrefp(env, &h->enc);
+ h->enc = enc;
+ globrefset(env, enc, &h->enc);
+ }
+#else
+#if HAVE_SQLITE2
+ delglobrefp(env, &h->enc);
+ h->enc = enc;
+ globrefset(env, enc, &h->enc);
+#endif
+#endif
+ }
+}
+
+#if HAVE_SQLITE_SET_AUTHORIZER
+static int
+doauth(void *arg, int what, const char *arg1, const char *arg2,
+ const char *arg3, const char *arg4)
+{
+ handle *h = (handle *) arg;
+ JNIEnv *env = h->env;
+
+ if (env && h->ai) {
+ jthrowable exc;
+ jclass cls = (*env)->GetObjectClass(env, h->ai);
+ jmethodID mid;
+ jint i = what;
+
+ mid = (*env)->GetMethodID(env, cls, "authorize",
+ "(ILjava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)I");
+ if (mid) {
+ jstring s1 = 0, s2 = 0, s3 = 0, s4 = 0;
+ transstr tr;
+
+ if (arg1) {
+ trans2utf(env, h->haveutf, h->enc, arg1, &tr);
+ s1 = tr.jstr;
+ }
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return SQLITE_DENY;
+ }
+ if (arg2) {
+ trans2utf(env, h->haveutf, h->enc, arg2, &tr);
+ s2 = tr.jstr;
+ }
+ if (arg3) {
+ trans2utf(env, h->haveutf, h->enc, arg3, &tr);
+ s3 = tr.jstr;
+ }
+ if (arg4) {
+ trans2utf(env, h->haveutf, h->enc, arg4, &tr);
+ s4 = tr.jstr;
+ }
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return SQLITE_DENY;
+ }
+ i = (*env)->CallIntMethod(env, h->ai, mid, i, s1, s2, s3, s4);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return SQLITE_DENY;
+ }
+ (*env)->DeleteLocalRef(env, s4);
+ (*env)->DeleteLocalRef(env, s3);
+ (*env)->DeleteLocalRef(env, s2);
+ (*env)->DeleteLocalRef(env, s1);
+ if (i != SQLITE_OK && i != SQLITE_IGNORE) {
+ i = SQLITE_DENY;
+ }
+ return (int) i;
+ }
+ }
+ return SQLITE_DENY;
+}
+#endif
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1set_1authorizer(JNIEnv *env, jobject obj, jobject auth)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+ delglobrefp(env, &h->ai);
+ globrefset(env, auth, &h->ai);
+#if HAVE_SQLITE_SET_AUTHORIZER
+ h->env = env;
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_set_authorizer((sqlite3 *) h->sqlite,
+ h->ai ? doauth : 0, h);
+ } else {
+ sqlite_set_authorizer((sqlite *) h->sqlite,
+ h->ai ? doauth : 0, h);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_set_authorizer((sqlite *) h->sqlite, h->ai ? doauth : 0, h);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_set_authorizer((sqlite3 *) h->sqlite, h->ai ? doauth : 0, h);
+#endif
+#endif
+#endif
+ return;
+ }
+ throwclosed(env);
+}
+
+#if HAVE_SQLITE_TRACE
+static void
+dotrace(void *arg, const char *msg)
+{
+ handle *h = (handle *) arg;
+ JNIEnv *env = h->env;
+
+ if (env && h->tr && msg) {
+ jthrowable exc;
+ jclass cls = (*env)->GetObjectClass(env, h->tr);
+ jmethodID mid;
+
+ mid = (*env)->GetMethodID(env, cls, "trace", "(Ljava/lang/String;)V");
+ if (mid) {
+ transstr tr;
+
+ trans2utf(env, h->haveutf, h->enc, msg, &tr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ (*env)->ExceptionClear(env);
+ return;
+ }
+ (*env)->CallVoidMethod(env, h->tr, mid, tr.jstr);
+ (*env)->ExceptionClear(env);
+ (*env)->DeleteLocalRef(env, tr.jstr);
+ return;
+ }
+ }
+ return;
+}
+#endif
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1trace(JNIEnv *env, jobject obj, jobject tr)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+ delglobrefp(env, &h->tr);
+ globrefset(env, tr, &h->tr);
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_trace((sqlite3 *) h->sqlite, h->tr ? dotrace : 0, h);
+ } else {
+#if HAVE_SQLITE_TRACE
+ sqlite_trace((sqlite *) h->sqlite, h->tr ? dotrace : 0, h);
+#endif
+ }
+#else
+#if HAVE_SQLITE2
+#if HAVE_SQLITE_TRACE
+ sqlite_trace((sqlite *) h->sqlite, h->tr ? dotrace : 0, h);
+#endif
+#endif
+#if HAVE_SQLITE3
+ sqlite3_trace((sqlite3 *) h->sqlite, h->tr ? dotrace : 0, h);
+#endif
+#endif
+ return;
+ }
+ throwclosed(env);
+}
+
+#if HAVE_SQLITE_COMPILE
+static void
+dovmfinal(JNIEnv *env, jobject obj, int final)
+{
+ hvm *v = gethvm(env, obj);
+
+ if (v) {
+ if (v->h) {
+ handle *h = v->h;
+ hvm *vv, **vvp;
+
+ vvp = &h->vms;
+ vv = *vvp;
+ while (vv) {
+ if (vv == v) {
+ *vvp = vv->next;
+ break;
+ }
+ vvp = &vv->next;
+ vv = *vvp;
+ }
+ }
+ if (v->vm) {
+#if HAVE_BOTH_SQLITE
+ if (v->is3) {
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+ } else {
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+#endif
+#endif
+ v->vm = 0;
+ }
+ free(v);
+ (*env)->SetLongField(env, obj, F_SQLite_Vm_handle, 0);
+ return;
+ }
+ if (!final) {
+ throwex(env, "vm already closed");
+ }
+}
+#endif
+
+#if HAVE_SQLITE3
+static void
+dostmtfinal(JNIEnv *env, jobject obj)
+{
+ hvm *v = gethstmt(env, obj);
+
+ if (v) {
+ if (v->h) {
+ handle *h = v->h;
+ hvm *vv, **vvp;
+
+ vvp = &h->vms;
+ vv = *vvp;
+ while (vv) {
+ if (vv == v) {
+ *vvp = vv->next;
+ break;
+ }
+ vvp = &vv->next;
+ vv = *vvp;
+ }
+ }
+ if (v->vm) {
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+ }
+ v->vm = 0;
+ free(v);
+ (*env)->SetLongField(env, obj, F_SQLite_Stmt_handle, 0);
+ }
+}
+#endif
+
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+static void
+doblobfinal(JNIEnv *env, jobject obj)
+{
+ hbl *bl = gethbl(env, obj);
+
+ if (bl) {
+ if (bl->h) {
+ handle *h = bl->h;
+ hbl *blc, **blp;
+
+ blp = &h->blobs;
+ blc = *blp;
+ while (blc) {
+ if (blc == bl) {
+ *blp = blc->next;
+ break;
+ }
+ blp = &blc->next;
+ blc = *blp;
+ }
+ }
+ if (bl->blob) {
+ sqlite3_blob_close(bl->blob);
+ }
+ bl->blob = 0;
+ free(bl);
+ (*env)->SetLongField(env, obj, F_SQLite_Blob_handle, 0);
+ (*env)->SetIntField(env, obj, F_SQLite_Blob_size, 0);
+ }
+}
+#endif
+
+JNIEXPORT void JNICALL
+Java_SQLite_Vm_stop(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE_COMPILE
+ dovmfinal(env, obj, 0);
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Vm_finalize(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE_COMPILE
+ dovmfinal(env, obj, 1);
+#endif
+}
+
+#if HAVE_SQLITE_COMPILE
+#if HAVE_SQLITE3
+static void
+free_tab(void *mem)
+{
+ char **p = (char **) mem;
+ int i, n;
+
+ if (!p) {
+ return;
+ }
+ p -= 1;
+ mem = (void *) p;
+ n = ((int *) p)[0];
+ p += n * 2 + 2 + 1;
+ for (i = 0; i < n; i++) {
+ if (p[i]) {
+ free(p[i]);
+ }
+ }
+ free(mem);
+}
+#endif
+#endif
+
+JNIEXPORT jboolean JNICALL
+Java_SQLite_Vm_step(JNIEnv *env, jobject obj, jobject cb)
+{
+#if HAVE_SQLITE_COMPILE
+ hvm *v = gethvm(env, obj);
+
+ if (v && v->vm && v->h) {
+ jthrowable exc;
+ int ret, ncol = 0;
+#if HAVE_SQLITE3
+ freemem *freeproc = 0;
+ const char **blob = 0;
+#endif
+ const char **data = 0, **cols = 0;
+
+ v->h->env = env;
+#if HAVE_BOTH_SQLITE
+ if (v->is3) {
+ ret = sqlite3_step((sqlite3_stmt *) v->vm);
+ if (ret == SQLITE_ROW) {
+ ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
+ if (ncol > 0) {
+ data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
+ if (data) {
+ data[0] = (const char *) ncol;
+ ++data;
+ cols = data + ncol + 1;
+ blob = cols + ncol + 1;
+ freeproc = free_tab;
+ } else {
+ ret = SQLITE_NOMEM;
+ }
+ }
+ if (ret != SQLITE_NOMEM) {
+ int i;
+
+ for (i = 0; i < ncol; i++) {
+ cols[i] =
+ sqlite3_column_name((sqlite3_stmt *) v->vm, i);
+ if (sqlite3_column_type((sqlite3_stmt *) v->vm, i)
+ == SQLITE_BLOB) {
+ unsigned char *src = (unsigned char *)
+ sqlite3_column_blob((sqlite3_stmt *) v->vm, i);
+ int n =
+ sqlite3_column_bytes((sqlite3_stmt *) v->vm,
+ i);
+
+ if (src) {
+ data[i] = malloc(n * 2 + 4);
+ if (data[i]) {
+ int k;
+ char *p = (char *) data[i];
+
+ blob[i] = data[i];
+ *p++ = 'X';
+ *p++ = '\'';
+ for (k = 0; k < n; k++) {
+ *p++ = xdigits[src[k] >> 4];
+ *p++ = xdigits[src[k] & 0x0F];
+ }
+ *p++ = '\'';
+ *p++ = '\0';
+ }
+ }
+ } else {
+ data[i] = (const char *)
+ sqlite3_column_text((sqlite3_stmt *) v->vm, i);
+ }
+ }
+ }
+ }
+ } else {
+ ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols);
+ }
+#else
+#if HAVE_SQLITE2
+ ret = sqlite_step((sqlite_vm *) v->vm, &ncol, &data, &cols);
+#endif
+#if HAVE_SQLITE3
+ ret = sqlite3_step((sqlite3_stmt *) v->vm);
+ if (ret == SQLITE_ROW) {
+ ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
+ if (ncol > 0) {
+ data = calloc(ncol * 3 + 3 + 1, sizeof (char *));
+ if (data) {
+ data[0] = (const char *) ncol;
+ ++data;
+ cols = data + ncol + 1;
+ blob = cols + ncol + 1;
+ freeproc = free_tab;
+ } else {
+ ret = SQLITE_NOMEM;
+ }
+ }
+ if (ret != SQLITE_NOMEM) {
+ int i;
+
+ for (i = 0; i < ncol; i++) {
+ cols[i] = sqlite3_column_name((sqlite3_stmt *) v->vm, i);
+ if (sqlite3_column_type((sqlite3_stmt *) v->vm, i)
+ == SQLITE_BLOB) {
+ unsigned char *src = (unsigned char *)
+ sqlite3_column_blob((sqlite3_stmt *) v->vm, i);
+ int n =
+ sqlite3_column_bytes((sqlite3_stmt *) v->vm, i);
+
+ if (src) {
+ data[i] = malloc(n * 2 + 4);
+ if (data[i]) {
+ int k;
+ char *p = (char *) data[i];
+
+ blob[i] = data[i];
+ *p++ = 'X';
+ *p++ = '\'';
+ for (k = 0; k < n; k++) {
+ *p++ = xdigits[src[k] >> 4];
+ *p++ = xdigits[src[k] & 0x0F];
+ }
+ *p++ = '\'';
+ *p++ = '\0';
+ }
+ }
+ } else {
+ data[i] = (char *)
+ sqlite3_column_text((sqlite3_stmt *) v->vm, i);
+ }
+ }
+ }
+ }
+#endif
+#endif
+ if (ret == SQLITE_ROW) {
+ v->hh.cb = cb;
+ v->hh.env = env;
+#if HAVE_BOTH_SQLITE
+ if (v->is3) {
+ v->hh.stmt = (sqlite3_stmt *) v->vm;
+ }
+#else
+#if HAVE_SQLITE3
+ v->hh.stmt = (sqlite3_stmt *) v->vm;
+#endif
+#endif
+ callback((void *) &v->hh, ncol, (char **) data, (char **) cols);
+#if HAVE_SQLITE3
+ if (data && freeproc) {
+ freeproc((void *) data);
+ }
+#endif
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ goto dofin;
+ }
+ return JNI_TRUE;
+ } else if (ret == SQLITE_DONE) {
+dofin:
+#if HAVE_BOTH_SQLITE
+ if (v->is3) {
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+ } else {
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+#endif
+#endif
+ v->vm = 0;
+ return JNI_FALSE;
+ }
+#if HAVE_BOTH_SQLITE
+ if (v->is3) {
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+ } else {
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+#endif
+#endif
+ setvmerr(env, obj, ret);
+ v->vm = 0;
+ throwex(env, "error in step");
+ return JNI_FALSE;
+ }
+ throwex(env, "vm already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return JNI_FALSE;
+}
+
+JNIEXPORT jboolean JNICALL
+Java_SQLite_Vm_compile(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE_COMPILE
+ hvm *v = gethvm(env, obj);
+ void *svm = 0;
+ char *err = 0;
+ const char *tail;
+ int ret;
+
+ if (v && v->vm) {
+#if HAVE_BOTH_SQLITE
+ if (v->is3) {
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+ } else {
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_finalize((sqlite_vm *) v->vm, 0);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+#endif
+#endif
+ v->vm = 0;
+ }
+ if (v && v->h && v->h->sqlite) {
+ if (!v->tail) {
+ return JNI_FALSE;
+ }
+ v->h->env = env;
+#if HAVE_BOTH_SQLITE
+ if (v->is3) {
+#if HAVE_SQLITE3_PREPARE_V2
+ ret = sqlite3_prepare_v2((sqlite3 *) v->h->sqlite, v->tail, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#else
+ ret = sqlite3_prepare((sqlite3 *) v->h->sqlite, v->tail, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#endif
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ svm = 0;
+ }
+ }
+ } else {
+ ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail,
+ &tail, (sqlite_vm **) &svm, &err);
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite_finalize((sqlite_vm *) svm, 0);
+ svm = 0;
+ }
+ }
+ }
+#else
+#if HAVE_SQLITE2
+ ret = sqlite_compile((sqlite *) v->h->sqlite, v->tail,
+ &tail, (sqlite_vm **) &svm, &err);
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite_finalize((sqlite_vm *) svm, 0);
+ svm = 0;
+ }
+ }
+#endif
+#if HAVE_SQLITE3
+#if HAVE_SQLITE3_PREPARE_V2
+ ret = sqlite3_prepare_v2((sqlite3 *) v->h->sqlite,
+ v->tail, -1, (sqlite3_stmt **) &svm, &tail);
+#else
+ ret = sqlite3_prepare((sqlite3 *) v->h->sqlite,
+ v->tail, -1, (sqlite3_stmt **) &svm, &tail);
+#endif
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ svm = 0;
+ }
+ }
+#endif
+#endif
+ if (ret != SQLITE_OK) {
+ setvmerr(env, obj, ret);
+ v->tail = 0;
+ throwex(env, err ? err : "error in compile/prepare");
+#if HAVE_SQLITE2
+ if (err) {
+ sqlite_freemem(err);
+ }
+#endif
+ return JNI_FALSE;
+ }
+#if HAVE_SQLITE2
+ if (err) {
+ sqlite_freemem(err);
+ }
+#endif
+ if (!svm) {
+ v->tail = 0;
+ return JNI_FALSE;
+ }
+ v->vm = svm;
+ v->tail = (char *) tail;
+ v->hh.row1 = 1;
+ return JNI_TRUE;
+ }
+ throwex(env, "vm already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return JNI_FALSE;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database_vm_1compile(JNIEnv *env, jobject obj, jstring sql,
+ jobject vm)
+{
+#if HAVE_SQLITE_COMPILE
+ handle *h = gethandle(env, obj);
+ void *svm = 0;
+ hvm *v;
+ char *err = 0;
+ const char *tail;
+ transstr tr;
+ jvalue vv;
+ int ret;
+ jthrowable exc;
+
+ if (!h) {
+ throwclosed(env);
+ return;
+ }
+ if (!vm) {
+ throwex(env, "null vm");
+ return;
+ }
+ if (!sql) {
+ throwex(env, "null sql");
+ return;
+ }
+ trans2iso(env, h->haveutf, h->enc, sql, &tr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ h->env = env;
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+#if HAVE_SQLITE3_PREPARE_V2
+ ret = sqlite3_prepare_v2((sqlite3 *) h->sqlite, tr.result, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#else
+ ret = sqlite3_prepare((sqlite3 *) h->sqlite, tr.result, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#endif
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ svm = 0;
+ }
+ }
+ } else {
+ ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail,
+ (sqlite_vm **) &svm, &err);
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite_finalize((sqlite_vm *) svm, 0);
+ }
+ }
+ }
+#else
+#if HAVE_SQLITE2
+ ret = sqlite_compile((sqlite *) h->sqlite, tr.result, &tail,
+ (sqlite_vm **) &svm, &err);
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite_finalize((sqlite_vm *) svm, 0);
+ svm = 0;
+ }
+ }
+#endif
+#if HAVE_SQLITE3
+#if HAVE_SQLITE3_PREPARE_V2
+ ret = sqlite3_prepare_v2((sqlite3 *) h->sqlite, tr.result, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#else
+ ret = sqlite3_prepare((sqlite3 *) h->sqlite, tr.result, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#endif
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ svm = 0;
+ }
+ }
+#endif
+#endif
+ if (ret != SQLITE_OK) {
+ transfree(&tr);
+ setvmerr(env, vm, ret);
+ throwex(env, err ? err : "error in prepare/compile");
+#if HAVE_SQLITE2
+ if (err) {
+ sqlite_freemem(err);
+ }
+#endif
+ return;
+ }
+#if HAVE_SQLITE2
+ if (err) {
+ sqlite_freemem(err);
+ }
+#endif
+ if (!svm) {
+ transfree(&tr);
+ return;
+ }
+ v = malloc(sizeof (hvm) + strlen(tail) + 1);
+ if (!v) {
+ transfree(&tr);
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ } else {
+ sqlite_finalize((sqlite_vm *) svm, 0);
+ }
+#else
+#if HAVE_SQLITE2
+ sqlite_finalize((sqlite_vm *) svm, 0);
+#endif
+#if HAVE_SQLITE3
+ sqlite3_finalize((sqlite3_stmt *) svm);
+#endif
+#endif
+ throwoom(env, "unable to get SQLite handle");
+ return;
+ }
+ v->next = h->vms;
+ h->vms = v;
+ v->vm = svm;
+ v->h = h;
+ v->tail = (char *) (v + 1);
+#if HAVE_BOTH_SQLITE
+ v->is3 = v->hh.is3 = h->is3;
+#endif
+ strcpy(v->tail, tail);
+ v->hh.sqlite = 0;
+ v->hh.haveutf = h->haveutf;
+ v->hh.ver = h->ver;
+ v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
+ v->hh.row1 = 1;
+ v->hh.enc = h->enc;
+ v->hh.funcs = 0;
+ v->hh.vms = 0;
+ v->hh.env = 0;
+ vv.j = 0;
+ vv.l = (jobject) v;
+ (*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j);
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database_vm_1compile_1args(JNIEnv *env,
+ jobject obj, jstring sql,
+ jobject vm, jobjectArray args)
+{
+#if HAVE_SQLITE_COMPILE
+#if HAVE_SQLITE3
+ handle *h = gethandle(env, obj);
+#endif
+
+#if HAVE_BOTH_SQLITE
+ if (h && !h->is3) {
+ throwex(env, "unsupported");
+ return;
+ }
+#else
+#if HAVE_SQLITE2
+ throwex(env, "unsupported");
+#endif
+#endif
+#if HAVE_SQLITE3
+ if (!h || !h->sqlite) {
+ throwclosed(env);
+ return;
+ }
+ if (!vm) {
+ throwex(env, "null vm");
+ return;
+ }
+ if (!sql) {
+ throwex(env, "null sql");
+ return;
+ } else {
+ void *svm = 0;
+ hvm *v;
+ jvalue vv;
+ jthrowable exc;
+ jboolean b;
+ int rc = SQLITE_ERROR, nargs, i;
+ char *p;
+ const char *str = (*env)->GetStringUTFChars(env, sql, &b);
+ const char *tail;
+ transstr sqlstr;
+ struct args {
+ char *arg;
+ jobject obj;
+ transstr trans;
+ } *argv = 0;
+ char **cargv = 0;
+
+ p = (char *) str;
+ nargs = 0;
+ while (*p) {
+ if (*p == '%') {
+ ++p;
+ if (*p == 'q' || *p == 'Q' || *p == 's') {
+ nargs++;
+ if (nargs > MAX_PARAMS) {
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ throwex(env, "too much SQL parameters");
+ return;
+ }
+ } else if (*p != '%') {
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ throwex(env, "bad % specification in query");
+ return;
+ }
+ }
+ ++p;
+ }
+ cargv = malloc((sizeof (*argv) + sizeof (char *)) * MAX_PARAMS);
+ if (!cargv) {
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ throwoom(env, "unable to allocate arg vector");
+ return;
+ }
+ argv = (struct args *) (cargv + MAX_PARAMS);
+ for (i = 0; i < MAX_PARAMS; i++) {
+ cargv[i] = 0;
+ argv[i].arg = 0;
+ argv[i].obj = 0;
+ argv[i].trans.result = argv[i].trans.tofree = 0;
+ }
+ exc = 0;
+ for (i = 0; i < nargs; i++) {
+ jobject so = (*env)->GetObjectArrayElement(env, args, i);
+
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ break;
+ }
+ if (so) {
+ argv[i].obj = so;
+ argv[i].arg = cargv[i] =
+ trans2iso(env, 1, 0, argv[i].obj, &argv[i].trans);
+ }
+ }
+ if (exc) {
+ for (i = 0; i < nargs; i++) {
+ if (argv[i].obj) {
+ transfree(&argv[i].trans);
+ }
+ }
+ freep((char **) &cargv);
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ return;
+ }
+ h->row1 = 1;
+ trans2iso(env, 1, 0, sql, &sqlstr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (!exc) {
+#if defined(_WIN32) || !defined(CANT_PASS_VALIST_AS_CHARPTR)
+ char *s = sqlite3_vmprintf(sqlstr.result, (char *) cargv);
+#else
+ char *s = sqlite3_mprintf(sqlstr.result,
+ cargv[0], cargv[1],
+ cargv[2], cargv[3],
+ cargv[4], cargv[5],
+ cargv[6], cargv[7],
+ cargv[8], cargv[9],
+ cargv[10], cargv[11],
+ cargv[12], cargv[13],
+ cargv[14], cargv[15],
+ cargv[16], cargv[17],
+ cargv[18], cargv[19],
+ cargv[20], cargv[21],
+ cargv[22], cargv[23],
+ cargv[24], cargv[25],
+ cargv[26], cargv[27],
+ cargv[28], cargv[29],
+ cargv[30], cargv[31]);
+#endif
+ if (!s) {
+ rc = SQLITE_NOMEM;
+ } else {
+#if HAVE_SQLITE3_PREPARE_V2
+ rc = sqlite3_prepare_v2((sqlite3 *) h->sqlite, s, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#else
+ rc = sqlite3_prepare((sqlite3 *) h->sqlite, s, -1,
+ (sqlite3_stmt **) &svm, &tail);
+#endif
+ if (rc != SQLITE_OK) {
+ if (svm) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ svm = 0;
+ }
+ }
+ }
+ if (rc != SQLITE_OK) {
+ sqlite3_free(s);
+ for (i = 0; i < nargs; i++) {
+ if (argv[i].obj) {
+ transfree(&argv[i].trans);
+ }
+ }
+ freep((char **) &cargv);
+ transfree(&sqlstr);
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ setvmerr(env, vm, rc);
+ throwex(env, "error in prepare");
+ return;
+ }
+ v = malloc(sizeof (hvm) + strlen(tail) + 1);
+ if (!v) {
+ sqlite3_free(s);
+ for (i = 0; i < nargs; i++) {
+ if (argv[i].obj) {
+ transfree(&argv[i].trans);
+ }
+ }
+ freep((char **) &cargv);
+ transfree(&sqlstr);
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ setvmerr(env, vm, SQLITE_NOMEM);
+ throwoom(env, "unable to get SQLite handle");
+ return;
+ }
+ v->next = h->vms;
+ h->vms = v;
+ v->vm = svm;
+ v->h = h;
+ v->tail = (char *) (v + 1);
+#if HAVE_BOTH_SQLITE
+ v->is3 = v->hh.is3 = h->is3;
+#endif
+ strcpy(v->tail, tail);
+ sqlite3_free(s);
+ v->hh.sqlite = 0;
+ v->hh.haveutf = h->haveutf;
+ v->hh.ver = h->ver;
+ v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
+ v->hh.row1 = 1;
+ v->hh.enc = h->enc;
+ v->hh.funcs = 0;
+ v->hh.vms = 0;
+ v->hh.env = 0;
+ vv.j = 0;
+ vv.l = (jobject) v;
+ (*env)->SetLongField(env, vm, F_SQLite_Vm_handle, vv.j);
+ }
+ for (i = 0; i < nargs; i++) {
+ if (argv[i].obj) {
+ transfree(&argv[i].trans);
+ }
+ }
+ freep((char **) &cargv);
+ transfree(&sqlstr);
+ (*env)->ReleaseStringUTFChars(env, sql, str);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ }
+ }
+#endif
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_FunctionContext_internal_1init(JNIEnv *env, jclass cls)
+{
+ F_SQLite_FunctionContext_handle =
+ (*env)->GetFieldID(env, cls, "handle", "J");
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1progress_1handler(JNIEnv *env, jobject obj, jint n,
+ jobject ph)
+{
+ handle *h = gethandle(env, obj);
+
+ if (h && h->sqlite) {
+ /* CHECK THIS */
+#if HAVE_SQLITE_PROGRESS_HANDLER
+ delglobrefp(env, &h->ph);
+#if HAVE_BOTH_SQLITE
+ if (h->is3) {
+ if (ph) {
+ globrefset(env, ph, &h->ph);
+ sqlite3_progress_handler((sqlite3 *) h->sqlite,
+ n, progresshandler, h);
+ } else {
+ sqlite3_progress_handler((sqlite3 *) h->sqlite,
+ 0, 0, 0);
+ }
+ } else {
+ if (ph) {
+ globrefset(env, ph, &h->ph);
+ sqlite_progress_handler((sqlite *) h->sqlite,
+ n, progresshandler, h);
+ } else {
+ sqlite_progress_handler((sqlite *) h->sqlite,
+ 0, 0, 0);
+ }
+ }
+#else
+#if HAVE_SQLITE2
+ if (ph) {
+ globrefset(env, ph, &h->ph);
+ sqlite_progress_handler((sqlite *) h->sqlite,
+ n, progresshandler, h);
+ } else {
+ sqlite_progress_handler((sqlite *) h->sqlite,
+ 0, 0, 0);
+ }
+#endif
+#if HAVE_SQLITE3
+ if (ph) {
+ globrefset(env, ph, &h->ph);
+ sqlite3_progress_handler((sqlite3 *) h->sqlite,
+ n, progresshandler, h);
+ } else {
+ sqlite3_progress_handler((sqlite3 *) h->sqlite,
+ 0, 0, 0);
+ }
+#endif
+#endif
+ return;
+#else
+ throwex(env, "unsupported");
+ return;
+#endif
+ }
+ throwclosed(env);
+}
+
+JNIEXPORT jboolean JNICALL
+Java_SQLite_Database_is3(JNIEnv *env, jobject obj)
+{
+#if HAVE_BOTH_SQLITE
+ handle *h = gethandle(env, obj);
+
+ if (h) {
+ return h->is3 ? JNI_TRUE : JNI_FALSE;
+ }
+ return JNI_FALSE;
+#else
+#if HAVE_SQLITE2
+ return JNI_FALSE;
+#endif
+#if HAVE_SQLITE3
+ return JNI_TRUE;
+#endif
+#endif
+}
+
+JNIEXPORT jboolean JNICALL
+Java_SQLite_Stmt_prepare(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3
+ hvm *v = gethstmt(env, obj);
+ void *svm = 0;
+ char *tail;
+ int ret;
+
+ if (v && v->vm) {
+ sqlite3_finalize((sqlite3_stmt *) v->vm);
+ v->vm = 0;
+ }
+ if (v && v->h && v->h->sqlite) {
+ if (!v->tail) {
+ return JNI_FALSE;
+ }
+ v->h->env = env;
+#if HAVE_SQLITE3_PREPARE16_V2
+ ret = sqlite3_prepare16_v2((sqlite3 *) v->h->sqlite,
+ v->tail, -1, (sqlite3_stmt **) &svm,
+ (const void **) &tail);
+#else
+ ret = sqlite3_prepare16((sqlite3 *) v->h->sqlite,
+ v->tail, -1, (sqlite3_stmt **) &svm,
+ (const void **) &tail);
+#endif
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ svm = 0;
+ }
+ }
+ if (ret != SQLITE_OK) {
+ const char *err = sqlite3_errmsg(v->h->sqlite);
+
+ setstmterr(env, obj, ret);
+ v->tail = 0;
+ throwex(env, err ? err : "error in compile/prepare");
+ return JNI_FALSE;
+ }
+ if (!svm) {
+ v->tail = 0;
+ return JNI_FALSE;
+ }
+ v->vm = svm;
+ v->tail = (char *) tail;
+ v->hh.row1 = 1;
+ return JNI_TRUE;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return JNI_FALSE;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database_stmt_1prepare(JNIEnv *env, jobject obj, jstring sql,
+ jobject stmt)
+{
+#if HAVE_SQLITE3
+ handle *h = gethandle(env, obj);
+ void *svm = 0;
+ hvm *v;
+ jvalue vv;
+ jsize len16;
+ const jchar *sql16, *tail = 0;
+ int ret;
+
+ if (!h) {
+ throwclosed(env);
+ return;
+ }
+ if (!stmt) {
+ throwex(env, "null stmt");
+ return;
+ }
+ if (!sql) {
+ throwex(env, "null sql");
+ return;
+ }
+#ifdef HAVE_BOTH_SQLITE
+ if (!h->is3) {
+ throwex(env, "only on SQLite3 database");
+ return;
+ }
+#endif
+ len16 = (*env)->GetStringLength(env, sql) * sizeof (jchar);
+ if (len16 < 1) {
+ return;
+ }
+ h->env = env;
+ sql16 = (*env)->GetStringChars(env, sql, 0);
+#if HAVE_SQLITE3_PREPARE16_V2
+ ret = sqlite3_prepare16_v2((sqlite3 *) h->sqlite, sql16, len16,
+ (sqlite3_stmt **) &svm, (const void **) &tail);
+#else
+ ret = sqlite3_prepare16((sqlite3 *) h->sqlite, sql16, len16,
+ (sqlite3_stmt **) &svm, (const void **) &tail);
+#endif
+ if (ret != SQLITE_OK) {
+ if (svm) {
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ svm = 0;
+ }
+ }
+ if (ret != SQLITE_OK) {
+ const char *err = sqlite3_errmsg(h->sqlite);
+
+ (*env)->ReleaseStringChars(env, sql, sql16);
+ setstmterr(env, stmt, ret);
+ throwex(env, err ? err : "error in prepare");
+ return;
+ }
+ if (!svm) {
+ (*env)->ReleaseStringChars(env, sql, sql16);
+ return;
+ }
+ len16 = len16 + sizeof (jchar) - ((char *) tail - (char *) sql16);
+ if (len16 < sizeof (jchar)) {
+ len16 = sizeof (jchar);
+ }
+ v = malloc(sizeof (hvm) + len16);
+ if (!v) {
+ (*env)->ReleaseStringChars(env, sql, sql16);
+ sqlite3_finalize((sqlite3_stmt *) svm);
+ throwoom(env, "unable to get SQLite handle");
+ return;
+ }
+ v->next = h->vms;
+ h->vms = v;
+ v->vm = svm;
+ v->h = h;
+ v->tail = (char *) (v + 1);
+#if HAVE_BOTH_SQLITE
+ v->is3 = v->hh.is3 = 1;
+#endif
+ memcpy(v->tail, tail, len16);
+ len16 /= sizeof (jchar);
+ ((jchar *) v->tail)[len16 - 1] = 0;
+ (*env)->ReleaseStringChars(env, sql, sql16);
+ v->hh.sqlite = 0;
+ v->hh.haveutf = h->haveutf;
+ v->hh.ver = h->ver;
+ v->hh.bh = v->hh.cb = v->hh.ai = v->hh.tr = v->hh.ph = 0;
+ v->hh.row1 = 1;
+ v->hh.enc = h->enc;
+ v->hh.funcs = 0;
+ v->hh.vms = 0;
+ v->hh.env = 0;
+ vv.j = 0;
+ vv.l = (jobject) v;
+ (*env)->SetLongField(env, stmt, F_SQLite_Stmt_handle, vv.j);
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT jboolean JNICALL
+Java_SQLite_Stmt_step(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ret;
+
+ ret = sqlite3_step((sqlite3_stmt *) v->vm);
+ if (ret == SQLITE_ROW) {
+ return JNI_TRUE;
+ }
+ if (ret != SQLITE_DONE) {
+ const char *err = sqlite3_errmsg(v->h->sqlite);
+
+ setstmterr(env, obj, ret);
+ throwex(env, err ? err : "error in step");
+ }
+ return JNI_FALSE;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return JNI_FALSE;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_close(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ret;
+
+ ret = sqlite3_finalize((sqlite3_stmt *) v->vm);
+ v->vm = 0;
+ if (ret != SQLITE_OK) {
+ const char *err = sqlite3_errmsg(v->h->sqlite);
+
+ setstmterr(env, obj, ret);
+ throwex(env, err ? err : "error in close");
+ }
+ return;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_reset(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ sqlite3_reset((sqlite3_stmt *) v->vm);
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_clear_1bindings(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_CLEAR_BINDINGS
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ sqlite3_clear_bindings((sqlite3_stmt *) v->vm);
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_bind__II(JNIEnv *env, jobject obj, jint pos, jint val)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ int ret;
+
+ if (pos < 1 || pos > npar) {
+ throwex(env, "parameter position out of bounds");
+ return;
+ }
+ ret = sqlite3_bind_int((sqlite3_stmt *) v->vm, pos, val);
+ if (ret != SQLITE_OK) {
+ setstmterr(env, obj, ret);
+ throwex(env, "bind failed");
+ }
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_bind__IJ(JNIEnv *env, jobject obj, jint pos, jlong val)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ int ret;
+
+ if (pos < 1 || pos > npar) {
+ throwex(env, "parameter position out of bounds");
+ return;
+ }
+ ret = sqlite3_bind_int64((sqlite3_stmt *) v->vm, pos, val);
+ if (ret != SQLITE_OK) {
+ setstmterr(env, obj, ret);
+ throwex(env, "bind failed");
+ }
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_bind__ID(JNIEnv *env, jobject obj, jint pos, jdouble val)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ int ret;
+
+ if (pos < 1 || pos > npar) {
+ throwex(env, "parameter position out of bounds");
+ return;
+ }
+ ret = sqlite3_bind_double((sqlite3_stmt *) v->vm, pos, val);
+ if (ret != SQLITE_OK) {
+ setstmterr(env, obj, ret);
+ throwex(env, "bind failed");
+ }
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_bind__I_3B(JNIEnv *env, jobject obj, jint pos, jbyteArray val)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ int ret;
+ jint len;
+ char *data = 0;
+
+ if (pos < 1 || pos > npar) {
+ throwex(env, "parameter position out of bounds");
+ return;
+ }
+ if (val) {
+ len = (*env)->GetArrayLength(env, val);
+ if (len > 0) {
+ data = sqlite3_malloc(len);
+ if (!data) {
+ throwoom(env, "unable to get blob parameter");
+ return;
+ }
+ (*env)->GetByteArrayRegion(env, val, 0, len, (jbyte *) data);
+ ret = sqlite3_bind_blob((sqlite3_stmt *) v->vm,
+ pos, data, len, sqlite3_free);
+ } else {
+ ret = sqlite3_bind_blob((sqlite3_stmt *) v->vm,
+ pos, "", 0, SQLITE_STATIC);
+ }
+ } else {
+ ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
+ }
+ if (ret != SQLITE_OK) {
+ if (data) {
+ sqlite3_free(data);
+ }
+ setstmterr(env, obj, ret);
+ throwex(env, "bind failed");
+ }
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_bind__ILjava_lang_String_2(JNIEnv *env, jobject obj,
+ jint pos, jstring val)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ int ret;
+ jsize len;
+ char *data = 0;
+
+ if (pos < 1 || pos > npar) {
+ throwex(env, "parameter position out of bounds");
+ return;
+ }
+ if (val) {
+ len = (*env)->GetStringLength(env, val);
+ if (len > 0) {
+ const jchar *ch;
+
+ len *= sizeof (jchar);
+ data = sqlite3_malloc(len);
+ if (!data) {
+ throwoom(env, "unable to get blob parameter");
+ return;
+ }
+ ch = (*env)->GetStringChars(env, val, 0);
+ memcpy(data, ch, len);
+ (*env)->ReleaseStringChars(env, val, ch);
+ ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm,
+ pos, data, len, sqlite3_free);
+ } else {
+ ret = sqlite3_bind_text16((sqlite3_stmt *) v->vm, pos, "", 0,
+ SQLITE_STATIC);
+ }
+ } else {
+ ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
+ }
+ if (ret != SQLITE_OK) {
+ if (data) {
+ sqlite3_free(data);
+ }
+ setstmterr(env, obj, ret);
+ throwex(env, "bind failed");
+ }
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_bind__I(JNIEnv *env, jobject obj, jint pos)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ int ret;
+
+ if (pos < 1 || pos > npar) {
+ throwex(env, "parameter position out of bounds");
+ return;
+ }
+ ret = sqlite3_bind_null((sqlite3_stmt *) v->vm, pos);
+ if (ret != SQLITE_OK) {
+ setstmterr(env, obj, ret);
+ throwex(env, "bind failed");
+ }
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_bind_1zeroblob(JNIEnv *env, jobject obj, jint pos, jint len)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_ZEROBLOB
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ int ret;
+
+ if (pos < 1 || pos > npar) {
+ throwex(env, "parameter position out of bounds");
+ return;
+ }
+ ret = sqlite3_bind_zeroblob((sqlite3_stmt *) v->vm, pos, len);
+ if (ret != SQLITE_OK) {
+ setstmterr(env, obj, ret);
+ throwex(env, "bind failed");
+ }
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT jint JNICALL
+Java_SQLite_Stmt_bind_1parameter_1count(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ return sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Stmt_bind_1parameter_1name(JNIEnv *env, jobject obj, jint pos)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_PARAMETER_NAME
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int npar = sqlite3_bind_parameter_count((sqlite3_stmt *) v->vm);
+ const char *name;
+
+ if (pos < 1 || pos > npar) {
+ throwex(env, "parameter position out of bounds");
+ return 0;
+ }
+ name = sqlite3_bind_parameter_name((sqlite3_stmt *) v->vm, pos);
+ if (name) {
+ return (*env)->NewStringUTF(env, name);
+ }
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jint JNICALL
+Java_SQLite_Stmt_bind_1parameter_1index(JNIEnv *env, jobject obj,
+ jstring name)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_BIND_PARAMETER_INDEX
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int pos;
+ const char *n;
+ transstr namestr;
+ jthrowable exc;
+
+ n = trans2iso(env, 1, 0, name, &namestr);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return -1;
+ }
+ pos = sqlite3_bind_parameter_index((sqlite3_stmt *) v->vm, n);
+ transfree(&namestr);
+ return pos;
+ } else {
+ throwex(env, "stmt already closed");
+ }
+#else
+ throwex(env, "unsupported");
+#endif
+ return -1;
+}
+
+JNIEXPORT jint JNICALL
+Java_SQLite_Stmt_column_1int(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ return sqlite3_column_int((sqlite3_stmt *) v->vm, col);
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jlong JNICALL
+Java_SQLite_Stmt_column_1long(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ return sqlite3_column_int64((sqlite3_stmt *) v->vm, col);
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jdouble JNICALL
+Java_SQLite_Stmt_column_1double(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ return sqlite3_column_double((sqlite3_stmt *) v->vm, col);
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jbyteArray JNICALL
+Java_SQLite_Stmt_column_1bytes(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
+ int nbytes;
+ const jbyte *data;
+ jbyteArray b = 0;
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ data = sqlite3_column_blob((sqlite3_stmt *) v->vm, col);
+ if (data) {
+ nbytes = sqlite3_column_bytes((sqlite3_stmt *) v->vm, col);
+ } else {
+ return 0;
+ }
+ b = (*env)->NewByteArray(env, nbytes);
+ if (!b) {
+ throwoom(env, "unable to get blob column data");
+ return 0;
+ }
+ (*env)->SetByteArrayRegion(env, b, 0, nbytes, data);
+ return b;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Stmt_column_1string(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
+ int nbytes;
+ const jchar *data;
+ jstring b = 0;
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ data = sqlite3_column_text16((sqlite3_stmt *) v->vm, col);
+ if (data) {
+ nbytes = sqlite3_column_bytes16((sqlite3_stmt *) v->vm, col);
+ } else {
+ return 0;
+ }
+ nbytes /= sizeof (jchar);
+ b = (*env)->NewString(env, data, nbytes);
+ if (!b) {
+ throwoom(env, "unable to get string column data");
+ return 0;
+ }
+ return b;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jint JNICALL
+Java_SQLite_Stmt_column_1type(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_data_count((sqlite3_stmt *) v->vm);
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ return sqlite3_column_type((sqlite3_stmt *) v->vm, col);
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jint JNICALL
+Java_SQLite_Stmt_column_1count(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ return sqlite3_column_count((sqlite3_stmt *) v->vm);
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Stmt_column_1table_1name(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_TABLE_NAME16
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
+ const jchar *str;
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ str = sqlite3_column_table_name16((sqlite3_stmt *) v->vm, col);
+ if (str) {
+ return (*env)->NewString(env, str, jstrlen(str));
+ }
+ return 0;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Stmt_column_1database_1name(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_DATABASE_NAME16
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
+ const jchar *str;
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ str = sqlite3_column_database_name16((sqlite3_stmt *) v->vm, col);
+ if (str) {
+ return (*env)->NewString(env, str, jstrlen(str));
+ }
+ return 0;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Stmt_column_1decltype(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
+ const jchar *str;
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ str = sqlite3_column_decltype16((sqlite3_stmt *) v->vm, col);
+ if (str) {
+ return (*env)->NewString(env, str, jstrlen(str));
+ }
+ return 0;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jstring JNICALL
+Java_SQLite_Stmt_column_1origin_1name(JNIEnv *env, jobject obj, jint col)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_COLUMN_ORIGIN_NAME16
+ hvm *v = gethstmt(env, obj);
+
+ if (v && v->vm && v->h) {
+ int ncol = sqlite3_column_count((sqlite3_stmt *) v->vm);
+ const jchar *str;
+
+ if (col < 0 || col >= ncol) {
+ throwex(env, "column out of bounds");
+ return 0;
+ }
+ str = sqlite3_column_origin_name16((sqlite3_stmt *) v->vm, col);
+ if (str) {
+ return (*env)->NewString(env, str, jstrlen(str));
+ }
+ return 0;
+ }
+ throwex(env, "stmt already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_finalize(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE_COMPILE
+ dostmtfinal(env, obj);
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database__1open_1blob(JNIEnv *env, jobject obj,
+ jstring dbname, jstring table,
+ jstring column, jlong row,
+ jboolean rw, jobject blobj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ handle *h = gethandle(env, obj);
+ hbl *bl;
+ jthrowable exc;
+ transstr dbn, tbl, col;
+ sqlite3_blob *blob;
+ jvalue vv;
+ int ret;
+
+ if (!blobj) {
+ throwex(env, "null blob");
+ return;
+ }
+ if (h && h->sqlite) {
+ trans2iso(env, h->haveutf, h->enc, dbname, &dbn);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ trans2iso(env, h->haveutf, h->enc, table, &tbl);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ transfree(&dbn);
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ trans2iso(env, h->haveutf, h->enc, column, &col);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ transfree(&tbl);
+ transfree(&dbn);
+ (*env)->DeleteLocalRef(env, exc);
+ return;
+ }
+ ret = sqlite3_blob_open(h->sqlite,
+ dbn.result, tbl.result, col.result,
+ row, rw, &blob);
+ transfree(&col);
+ transfree(&tbl);
+ transfree(&dbn);
+ if (ret != SQLITE_OK) {
+ const char *err = sqlite3_errmsg(h->sqlite);
+
+ seterr(env, obj, ret);
+ throwex(env, err ? err : "error in blob open");
+ return;
+ }
+ bl = malloc(sizeof (hbl));
+ if (!bl) {
+ sqlite3_blob_close(blob);
+ throwoom(env, "unable to get SQLite blob handle");
+ return;
+ }
+ bl->next = h->blobs;
+ h->blobs = bl;
+ bl->blob = blob;
+ bl->h = h;
+ vv.j = 0;
+ vv.l = (jobject) bl;
+ (*env)->SetLongField(env, blobj, F_SQLite_Blob_handle, vv.j);
+ (*env)->SetIntField(env, blobj, F_SQLite_Blob_size,
+ sqlite3_blob_bytes(blob));
+ return;
+ }
+ throwex(env, "not an open database");
+#else
+ throwex(env, "unsupported");
+#endif
+}
+
+JNIEXPORT jint JNICALL
+Java_SQLite_Blob_write(JNIEnv *env , jobject obj, jbyteArray b, jint off,
+ jint pos, jint len)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ hbl *bl = gethbl(env, obj);
+
+ if (bl && bl->h && bl->blob) {
+ jbyte *buf;
+ jthrowable exc;
+ int ret;
+
+ if (len <= 0) {
+ return 0;
+ }
+ buf = malloc(len);
+ if (!buf) {
+ throwoom(env, "out of buffer space for blob");
+ return 0;
+ }
+ (*env)->GetByteArrayRegion(env, b, off, len, buf);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ free(buf);
+ return 0;
+ }
+ ret = sqlite3_blob_write(bl->blob, buf, len, pos);
+ free(buf);
+ if (ret != SQLITE_OK) {
+ throwioex(env, "blob write error");
+ return 0;
+ }
+ return len;
+ }
+ throwex(env, "blob already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT jint JNICALL
+Java_SQLite_Blob_read(JNIEnv *env , jobject obj, jbyteArray b, jint off,
+ jint pos, jint len)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ hbl *bl = gethbl(env, obj);
+
+ if (bl && bl->h && bl->blob) {
+ jbyte *buf;
+ jthrowable exc;
+ int ret;
+
+ if (len <= 0) {
+ return 0;
+ }
+ buf = malloc(len);
+ if (!buf) {
+ throwoom(env, "out of buffer space for blob");
+ return 0;
+ }
+ ret = sqlite3_blob_read(bl->blob, buf, len, pos);
+ if (ret != SQLITE_OK) {
+ free(buf);
+ throwioex(env, "blob read error");
+ return 0;
+ }
+ (*env)->SetByteArrayRegion(env, b, off, len, buf);
+ free(buf);
+ exc = (*env)->ExceptionOccurred(env);
+ if (exc) {
+ return 0;
+ }
+ return len;
+ }
+ throwex(env, "blob already closed");
+#else
+ throwex(env, "unsupported");
+#endif
+ return 0;
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Blob_close(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ doblobfinal(env, obj);
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Blob_finalize(JNIEnv *env, jobject obj)
+{
+#if HAVE_SQLITE3 && HAVE_SQLITE3_INCRBLOBIO
+ doblobfinal(env, obj);
+#endif
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Stmt_internal_1init(JNIEnv *env, jclass cls)
+{
+ F_SQLite_Stmt_handle =
+ (*env)->GetFieldID(env, cls, "handle", "J");
+ F_SQLite_Stmt_error_code =
+ (*env)->GetFieldID(env, cls, "error_code", "I");
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Vm_internal_1init(JNIEnv *env, jclass cls)
+{
+ F_SQLite_Vm_handle =
+ (*env)->GetFieldID(env, cls, "handle", "J");
+ F_SQLite_Vm_error_code =
+ (*env)->GetFieldID(env, cls, "error_code", "I");
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Blob_internal_1init(JNIEnv *env, jclass cls)
+{
+ F_SQLite_Blob_handle =
+ (*env)->GetFieldID(env, cls, "handle", "J");
+ F_SQLite_Blob_size =
+ (*env)->GetFieldID(env, cls, "size", "I");
+}
+
+JNIEXPORT void JNICALL
+Java_SQLite_Database_internal_1init(JNIEnv *env, jclass cls)
+{
+//#ifndef JNI_VERSION_1_2
+ jclass jls = (*env)->FindClass(env, "java/lang/String");
+
+ C_java_lang_String = (*env)->NewGlobalRef(env, jls);
+//#endif
+ F_SQLite_Database_handle =
+ (*env)->GetFieldID(env, cls, "handle", "J");
+ F_SQLite_Database_error_code =
+ (*env)->GetFieldID(env, cls, "error_code", "I");
+ M_java_lang_String_getBytes =
+ (*env)->GetMethodID(env, C_java_lang_String, "getBytes", "()[B");
+ M_java_lang_String_getBytes2 =
+ (*env)->GetMethodID(env, C_java_lang_String, "getBytes",
+ "(Ljava/lang/String;)[B");
+ M_java_lang_String_initBytes =
+ (*env)->GetMethodID(env, C_java_lang_String, "", "([B)V");
+ M_java_lang_String_initBytes2 =
+ (*env)->GetMethodID(env, C_java_lang_String, "",
+ "([BLjava/lang/String;)V");
+}
+
+#ifdef JNI_VERSION_1_2
+JNIEXPORT jint JNICALL
+JNI_OnLoad(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+ jclass cls;
+
+#ifndef _WIN32
+#if HAVE_SQLITE2
+ if (strcmp(sqlite_libencoding(), "UTF-8") != 0) {
+ fprintf(stderr, "WARNING: using non-UTF SQLite2 engine\n");
+ }
+#endif
+#endif
+ if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) {
+ return JNI_ERR;
+ }
+ cls = (*env)->FindClass(env, "java/lang/String");
+ if (!cls) {
+ return JNI_ERR;
+ }
+ C_java_lang_String = (*env)->NewWeakGlobalRef(env, cls);
+ return JNI_VERSION_1_2;
+}
+
+JNIEXPORT void JNICALL
+JNI_OnUnload(JavaVM *vm, void *reserved)
+{
+ JNIEnv *env;
+
+ if ((*vm)->GetEnv(vm, (void **) &env, JNI_VERSION_1_2)) {
+ return;
+ }
+ if (C_java_lang_String) {
+ (*env)->DeleteWeakGlobalRef(env, C_java_lang_String);
+ C_java_lang_String = 0;
+ }
+}
+#endif
diff --git a/sql/src/main/native/sqlite_jni.h b/sql/src/main/native/sqlite_jni.h
new file mode 100644
index 0000000..cdb7692
--- /dev/null
+++ b/sql/src/main/native/sqlite_jni.h
@@ -0,0 +1,657 @@
+/* DO NOT EDIT THIS FILE - it is machine generated */
+#include
+/* Header for class SQLite_Database */
+
+#ifndef _Included_SQLite_Database
+#define _Included_SQLite_Database
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: SQLite_Database
+ * Method: _open
+ * Signature: (Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1open
+ (JNIEnv *, jobject, jstring, jint);
+
+/*
+ * Class: SQLite_Database
+ * Method: _open_aux_file
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1open_1aux_1file
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: SQLite_Database
+ * Method: _finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1finalize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1close
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _exec
+ * Signature: (Ljava/lang/String;LSQLite/Callback;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2
+ (JNIEnv *, jobject, jstring, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _exec
+ * Signature: (Ljava/lang/String;LSQLite/Callback;[Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2
+ (JNIEnv *, jobject, jstring, jobject, jobjectArray);
+
+/*
+ * Class: SQLite_Database
+ * Method: _last_insert_rowid
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_SQLite_Database__1last_1insert_1rowid
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _interrupt
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1interrupt
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _changes
+ * Signature: ()J
+ */
+JNIEXPORT jlong JNICALL Java_SQLite_Database__1changes
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _busy_handler
+ * Signature: (LSQLite/BusyHandler;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1busy_1handler
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _busy_timeout
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1busy_1timeout
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Database
+ * Method: _complete
+ * Signature: (Ljava/lang/String;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_SQLite_Database__1complete
+ (JNIEnv *, jclass, jstring);
+
+/*
+ * Class: SQLite_Database
+ * Method: version
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Database_version
+ (JNIEnv *, jclass);
+
+/*
+ * Class: SQLite_Database
+ * Method: dbversion
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Database_dbversion
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _create_function
+ * Signature: (Ljava/lang/String;ILSQLite/Function;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1create_1function
+ (JNIEnv *, jobject, jstring, jint, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _create_aggregate
+ * Signature: (Ljava/lang/String;ILSQLite/Function;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1create_1aggregate
+ (JNIEnv *, jobject, jstring, jint, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _function_type
+ * Signature: (Ljava/lang/String;I)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1function_1type
+ (JNIEnv *, jobject, jstring, jint);
+
+/*
+ * Class: SQLite_Database
+ * Method: _errmsg
+ * Signature: ()Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Database__1errmsg
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: error_string
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Database_error_1string
+ (JNIEnv *, jclass, jint);
+
+/*
+ * Class: SQLite_Database
+ * Method: _set_encoding
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1set_1encoding
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: SQLite_Database
+ * Method: _set_authorizer
+ * Signature: (LSQLite/Authorizer;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1set_1authorizer
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _trace
+ * Signature: (LSQLite/Trace;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1trace
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: is3
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_SQLite_Database_is3
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: vm_compile
+ * Signature: (Ljava/lang/String;LSQLite/Vm;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database_vm_1compile
+ (JNIEnv *, jobject, jstring, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: vm_compile_args
+ * Signature: (Ljava/lang/String;LSQLite/Vm;[Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database_vm_1compile_1args
+ (JNIEnv *, jobject, jstring, jobject, jobjectArray);
+
+/*
+ * Class: SQLite_Database
+ * Method: stmt_prepare
+ * Signature: (Ljava/lang/String;LSQLite/Stmt;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database_stmt_1prepare
+ (JNIEnv *, jobject, jstring, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _open_blob
+ * Signature: (Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZLSQLite/Blob;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1open_1blob
+ (JNIEnv *, jobject, jstring, jstring, jstring, jlong, jboolean, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: _progress_handler
+ * Signature: (ILSQLite/ProgressHandler;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database__1progress_1handler
+ (JNIEnv *, jobject, jint, jobject);
+
+/*
+ * Class: SQLite_Database
+ * Method: internal_init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Database_internal_1init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class SQLite_Vm */
+
+#ifndef _Included_SQLite_Vm
+#define _Included_SQLite_Vm
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: SQLite_Vm
+ * Method: step
+ * Signature: (LSQLite/Callback;)Z
+ */
+JNIEXPORT jboolean JNICALL Java_SQLite_Vm_step
+ (JNIEnv *, jobject, jobject);
+
+/*
+ * Class: SQLite_Vm
+ * Method: compile
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_SQLite_Vm_compile
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Vm
+ * Method: stop
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Vm_stop
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Vm
+ * Method: finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Vm_finalize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Vm
+ * Method: internal_init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Vm_internal_1init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class SQLite_FunctionContext */
+
+#ifndef _Included_SQLite_FunctionContext
+#define _Included_SQLite_FunctionContext
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: SQLite_FunctionContext
+ * Method: set_result
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__Ljava_lang_String_2
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: SQLite_FunctionContext
+ * Method: set_result
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_FunctionContext
+ * Method: set_result
+ * Signature: (D)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__D
+ (JNIEnv *, jobject, jdouble);
+
+/*
+ * Class: SQLite_FunctionContext
+ * Method: set_error
+ * Signature: (Ljava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1error
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: SQLite_FunctionContext
+ * Method: set_result
+ * Signature: ([B)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result___3B
+ (JNIEnv *, jobject, jbyteArray);
+
+/*
+ * Class: SQLite_FunctionContext
+ * Method: set_result_zeroblob
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result_1zeroblob
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_FunctionContext
+ * Method: count
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_SQLite_FunctionContext_count
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_FunctionContext
+ * Method: internal_init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_FunctionContext_internal_1init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class SQLite_Stmt */
+
+#ifndef _Included_SQLite_Stmt
+#define _Included_SQLite_Stmt
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: SQLite_Stmt
+ * Method: prepare
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_SQLite_Stmt_prepare
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: step
+ * Signature: ()Z
+ */
+JNIEXPORT jboolean JNICALL Java_SQLite_Stmt_step
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_close
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: reset
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_reset
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: clear_bindings
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_clear_1bindings
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__II
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind
+ * Signature: (IJ)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__IJ
+ (JNIEnv *, jobject, jint, jlong);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind
+ * Signature: (ID)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__ID
+ (JNIEnv *, jobject, jint, jdouble);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind
+ * Signature: (I[B)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__I_3B
+ (JNIEnv *, jobject, jint, jbyteArray);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind
+ * Signature: (ILjava/lang/String;)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__ILjava_lang_String_2
+ (JNIEnv *, jobject, jint, jstring);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind
+ * Signature: (I)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__I
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind_zeroblob
+ * Signature: (II)V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_bind_1zeroblob
+ (JNIEnv *, jobject, jint, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind_parameter_count
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_SQLite_Stmt_bind_1parameter_1count
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind_parameter_name
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Stmt_bind_1parameter_1name
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: bind_parameter_index
+ * Signature: (Ljava/lang/String;)I
+ */
+JNIEXPORT jint JNICALL Java_SQLite_Stmt_bind_1parameter_1index
+ (JNIEnv *, jobject, jstring);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_int
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1int
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_long
+ * Signature: (I)J
+ */
+JNIEXPORT jlong JNICALL Java_SQLite_Stmt_column_1long
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_double
+ * Signature: (I)D
+ */
+JNIEXPORT jdouble JNICALL Java_SQLite_Stmt_column_1double
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_bytes
+ * Signature: (I)[B
+ */
+JNIEXPORT jbyteArray JNICALL Java_SQLite_Stmt_column_1bytes
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_string
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1string
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_type
+ * Signature: (I)I
+ */
+JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1type
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_count
+ * Signature: ()I
+ */
+JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1count
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_table_name
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1table_1name
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_database_name
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1database_1name
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_decltype
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1decltype
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: column_origin_name
+ * Signature: (I)Ljava/lang/String;
+ */
+JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1origin_1name
+ (JNIEnv *, jobject, jint);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_finalize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Stmt
+ * Method: internal_init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Stmt_internal_1init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
+/* Header for class SQLite_Blob */
+
+#ifndef _Included_SQLite_Blob
+#define _Included_SQLite_Blob
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+ * Class: SQLite_Blob
+ * Method: close
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Blob_close
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Blob
+ * Method: write
+ * Signature: ([BIII)I
+ */
+JNIEXPORT jint JNICALL Java_SQLite_Blob_write
+ (JNIEnv *, jobject, jbyteArray, jint, jint, jint);
+
+/*
+ * Class: SQLite_Blob
+ * Method: read
+ * Signature: ([BIII)I
+ */
+JNIEXPORT jint JNICALL Java_SQLite_Blob_read
+ (JNIEnv *, jobject, jbyteArray, jint, jint, jint);
+
+/*
+ * Class: SQLite_Blob
+ * Method: finalize
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Blob_finalize
+ (JNIEnv *, jobject);
+
+/*
+ * Class: SQLite_Blob
+ * Method: internal_init
+ * Signature: ()V
+ */
+JNIEXPORT void JNICALL Java_SQLite_Blob_internal_1init
+ (JNIEnv *, jclass);
+
+#ifdef __cplusplus
+}
+#endif
+#endif
diff --git a/sql/src/main/native/sqlite_jni_defs.h b/sql/src/main/native/sqlite_jni_defs.h
new file mode 100644
index 0000000..91b2378
--- /dev/null
+++ b/sql/src/main/native/sqlite_jni_defs.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define HAVE_SQLITE2 0
+#define HAVE_SQLITE3 1
+#define HAVE_SQLITE_FUNCTION_TYPE 0
+#define HAVE_SQLITE_OPEN_AUX_FILE 0
+#define HAVE_SQLITE_SET_AUTHORIZER 0
+#define HAVE_SQLITE_TRACE 0
+#define HAVE_SQLITE_COMPILE 0
+#define HAVE_SQLITE_PROGRESS_HANDLER 0
+#define HAVE_SQLITE3_MALLOC 1
+#define HAVE_SQLITE3_PREPARE_V2 0
+#define HAVE_SQLITE3_PREPARE16_V2 0
+#define HAVE_SQLITE3_BIND_ZEROBLOB 0
+#define HAVE_SQLITE3_CLEAR_BINDINGS 0
+#define HAVE_SQLITE3_COLUMN_TABLE_NAME16 0
+#define HAVE_SQLITE3_COLUMN_DATABASE_NAME16 0
+#define HAVE_SQLITE3_COLUMN_ORIGIN_NAME16 0
+#define HAVE_SQLITE3_BIND_PARAMETER_COUNT 1
+#define HAVE_SQLITE3_BIND_PARAMETER_NAME 1
+#define HAVE_SQLITE3_BIND_PARAMETER_INDEX 1
+#define HAVE_SQLITE3_RESULT_ZEROBLOB 0
+#define HAVE_SQLITE3_INCRBLOBIO 0
+
+
diff --git a/sql/src/main/native/sqlite_jni_registration.c b/sql/src/main/native/sqlite_jni_registration.c
new file mode 100644
index 0000000..1ef5192
--- /dev/null
+++ b/sql/src/main/native/sqlite_jni_registration.c
@@ -0,0 +1,308 @@
+/*
+ * Copyright 2007, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "JNIHelp.h"
+#include "sqlite_jni.h"
+
+/* Methods for class SQLite_Database */
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1open
+ (JNIEnv *, jobject, jstring, jint);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1open_1aux_1file
+ (JNIEnv *, jobject, jstring);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1finalize
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1close
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2
+ (JNIEnv *, jobject, jstring, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2
+ (JNIEnv *, jobject, jstring, jobject, jobjectArray);
+extern JNIEXPORT jlong JNICALL Java_SQLite_Database__1last_1insert_1rowid
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1interrupt
+ (JNIEnv *, jobject);
+extern JNIEXPORT jlong JNICALL Java_SQLite_Database__1changes
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1busy_1handler
+ (JNIEnv *, jobject, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1busy_1timeout
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jboolean JNICALL Java_SQLite_Database__1complete
+ (JNIEnv *, jclass, jstring);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Database_version
+ (JNIEnv *, jclass);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Database_dbversion
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1create_1function
+ (JNIEnv *, jobject, jstring, jint, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1create_1aggregate
+ (JNIEnv *, jobject, jstring, jint, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1function_1type
+ (JNIEnv *, jobject, jstring, jint);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Database__1errmsg
+ (JNIEnv *, jobject);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Database_error_1string
+ (JNIEnv *, jclass, jint);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1set_1encoding
+ (JNIEnv *, jobject, jstring);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1set_1authorizer
+ (JNIEnv *, jobject, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1trace
+ (JNIEnv *, jobject, jobject);
+extern JNIEXPORT jboolean JNICALL Java_SQLite_Database_is3
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database_vm_1compile
+ (JNIEnv *, jobject, jstring, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database_vm_1compile_1args
+ (JNIEnv *, jobject, jstring, jobject, jobjectArray);
+extern JNIEXPORT void JNICALL Java_SQLite_Database_stmt_1prepare
+ (JNIEnv *, jobject, jstring, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1open_1blob
+ (JNIEnv *, jobject, jstring, jstring, jstring, jlong, jboolean, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database__1progress_1handler
+ (JNIEnv *, jobject, jint, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Database_internal_1init
+ (JNIEnv *, jclass);
+
+
+/* Methods for class SQLite_Vm */
+
+extern JNIEXPORT jboolean JNICALL Java_SQLite_Vm_step
+ (JNIEnv *, jobject, jobject);
+extern JNIEXPORT jboolean JNICALL Java_SQLite_Vm_compile
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Vm_stop
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Vm_finalize
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Vm_internal_1init
+ (JNIEnv *, jclass);
+
+/* Methods for class SQLite_FunctionContext */
+
+extern JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__Ljava_lang_String_2
+ (JNIEnv *, jobject, jstring);
+extern JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__I
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result__D
+ (JNIEnv *, jobject, jdouble);
+extern JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1error
+ (JNIEnv *, jobject, jstring);
+extern JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result___3B
+ (JNIEnv *, jobject, jbyteArray);
+extern JNIEXPORT void JNICALL Java_SQLite_FunctionContext_set_1result_1zeroblob
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jint JNICALL Java_SQLite_FunctionContext_count
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_FunctionContext_internal_1init
+ (JNIEnv *, jclass);
+
+/* Methods for class SQLite_Stmt */
+
+extern JNIEXPORT jboolean JNICALL Java_SQLite_Stmt_prepare
+ (JNIEnv *, jobject);
+extern JNIEXPORT jboolean JNICALL Java_SQLite_Stmt_step
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_close
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_reset
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_clear_1bindings
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__II
+ (JNIEnv *, jobject, jint, jint);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__IJ
+ (JNIEnv *, jobject, jint, jlong);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__ID
+ (JNIEnv *, jobject, jint, jdouble);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__I_3B
+ (JNIEnv *, jobject, jint, jbyteArray);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__ILjava_lang_String_2
+ (JNIEnv *, jobject, jint, jstring);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_bind__I
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_bind_1zeroblob
+ (JNIEnv *, jobject, jint, jint);
+extern JNIEXPORT jint JNICALL Java_SQLite_Stmt_bind_1parameter_1count
+ (JNIEnv *, jobject);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Stmt_bind_1parameter_1name
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jint JNICALL Java_SQLite_Stmt_bind_1parameter_1index
+ (JNIEnv *, jobject, jstring);
+extern JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1int
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jlong JNICALL Java_SQLite_Stmt_column_1long
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jdouble JNICALL Java_SQLite_Stmt_column_1double
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jbyteArray JNICALL Java_SQLite_Stmt_column_1bytes
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1string
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1type
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jint JNICALL Java_SQLite_Stmt_column_1count
+ (JNIEnv *, jobject);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1table_1name
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1database_1name
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1decltype
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT jstring JNICALL Java_SQLite_Stmt_column_1origin_1name
+ (JNIEnv *, jobject, jint);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_finalize
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Stmt_internal_1init
+ (JNIEnv *, jclass);
+
+/* Methods for class SQLite_Blob */
+
+extern JNIEXPORT void JNICALL Java_SQLite_Blob_close
+ (JNIEnv *, jobject);
+extern JNIEXPORT jint JNICALL Java_SQLite_Blob_write
+ (JNIEnv *, jobject, jbyteArray, jint, jint, jint);
+extern JNIEXPORT jint JNICALL Java_SQLite_Blob_read
+ (JNIEnv *, jobject, jbyteArray, jint, jint, jint);
+extern JNIEXPORT void JNICALL Java_SQLite_Blob_finalize
+ (JNIEnv *, jobject);
+extern JNIEXPORT void JNICALL Java_SQLite_Blob_internal_1init
+ (JNIEnv *, jclass);
+
+/*
+ * JNI registration
+ */
+static JNINativeMethod sqliteDatabaseMethods[] = {
+ /* name, signature, funcPtr */
+/* Header for class SQLite_Database */
+{ "_open", "(Ljava/lang/String;I)V", Java_SQLite_Database__1open},
+{ "_open_aux_file", "(Ljava/lang/String;)V", Java_SQLite_Database__1open_1aux_1file},
+{ "_finalize", "()V", Java_SQLite_Database__1finalize},
+{ "_close", "()V", Java_SQLite_Database__1close},
+{ "_exec", "(Ljava/lang/String;LSQLite/Callback;)V", Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2},
+{ "_exec", "(Ljava/lang/String;LSQLite/Callback;[Ljava/lang/String;)V", Java_SQLite_Database__1exec__Ljava_lang_String_2LSQLite_Callback_2_3Ljava_lang_String_2},
+{ "_last_insert_rowid", "()J", Java_SQLite_Database__1last_1insert_1rowid},
+{ "_interrupt", "()V", Java_SQLite_Database__1interrupt},
+{ "_changes", "()J", Java_SQLite_Database__1changes},
+{ "_busy_handler", "(LSQLite/BusyHandler;)V", Java_SQLite_Database__1busy_1handler},
+{ "_busy_timeout", "(I)V", Java_SQLite_Database__1busy_1timeout},
+{ "_complete", "(Ljava/lang/String;)Z", Java_SQLite_Database__1complete},
+{ "version", "()Ljava/lang/String;", Java_SQLite_Database_version},
+{ "dbversion", "()Ljava/lang/String;", Java_SQLite_Database_dbversion},
+{ "_create_function", "(Ljava/lang/String;ILSQLite/Function;)V", Java_SQLite_Database__1create_1function},
+{ "_create_aggregate", "(Ljava/lang/String;ILSQLite/Function;)V", Java_SQLite_Database__1create_1aggregate},
+{ "_function_type", "(Ljava/lang/String;I)V", Java_SQLite_Database__1function_1type},
+{ "_errmsg", "()Ljava/lang/String;", Java_SQLite_Database__1errmsg},
+{ "error_string", "(I)Ljava/lang/String;", Java_SQLite_Database_error_1string},
+{ "_set_encoding", "(Ljava/lang/String;)V", Java_SQLite_Database__1set_1encoding},
+{ "_set_authorizer", "(LSQLite/Authorizer;)V", Java_SQLite_Database__1set_1authorizer},
+{ "_trace", "(LSQLite/Trace;)V", Java_SQLite_Database__1trace},
+{ "is3", "()Z", Java_SQLite_Database_is3},
+{ "vm_compile", "(Ljava/lang/String;LSQLite/Vm;)V", Java_SQLite_Database_vm_1compile},
+{ "vm_compile_args", "(Ljava/lang/String;LSQLite/Vm;[Ljava/lang/String;)V", Java_SQLite_Database_vm_1compile_1args},
+{ "stmt_prepare", "(Ljava/lang/String;LSQLite/Stmt;)V", Java_SQLite_Database_stmt_1prepare},
+{ "_open_blob", "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;JZLSQLite/Blob;)V", Java_SQLite_Database__1open_1blob},
+{ "_progress_handler", "(ILSQLite/ProgressHandler;)V", Java_SQLite_Database__1progress_1handler},
+{ "internal_init", "()V", Java_SQLite_Database_internal_1init}
+};
+
+static JNINativeMethod sqliteVmMethods[] = {
+/* Header for class SQLite_Vm */
+{ "step", "(LSQLite/Callback;)Z", Java_SQLite_Vm_step},
+{ "compile", "()Z", Java_SQLite_Vm_compile},
+{ "stop", "()V", Java_SQLite_Vm_stop},
+{ "finalize", "()V", Java_SQLite_Vm_finalize},
+{ "internal_init", "()V", Java_SQLite_Vm_internal_1init}
+};
+
+static JNINativeMethod sqliteFunctionContextMethods[] = {
+/* Header for class SQLite_FunctionContext */
+{ "set_result", "(Ljava/lang/String;)V", Java_SQLite_FunctionContext_set_1result__Ljava_lang_String_2},
+{ "set_result", "(I)V", Java_SQLite_FunctionContext_set_1result__I},
+{ "set_result", "(D)V", Java_SQLite_FunctionContext_set_1result__D},
+{ "set_error", "(Ljava/lang/String;)V", Java_SQLite_FunctionContext_set_1error},
+{ "set_result", "([B)V", Java_SQLite_FunctionContext_set_1result___3B},
+{ "set_result_zeroblob", "(I)V", Java_SQLite_FunctionContext_set_1result_1zeroblob},
+{ "count", "()I", Java_SQLite_FunctionContext_count},
+{ "internal_init", "()V", Java_SQLite_FunctionContext_internal_1init}
+};
+
+static JNINativeMethod sqliteStmtMethods[] = {
+/* Header for class SQLite_Stmt */
+{ "prepare", "()Z", Java_SQLite_Stmt_prepare},
+{ "step", "()Z", JNICALL Java_SQLite_Stmt_step},
+{ "close", "()V", Java_SQLite_Stmt_close},
+{ "reset", "()V", Java_SQLite_Stmt_reset},
+{ "clear_bindings", "()V", Java_SQLite_Stmt_clear_1bindings},
+{ "bind", "(II)V", Java_SQLite_Stmt_bind__II},
+{ "bind", "(IJ)V", Java_SQLite_Stmt_bind__IJ},
+{ "bind", "(ID)V", Java_SQLite_Stmt_bind__ID},
+{ "bind", "(I[B)V", Java_SQLite_Stmt_bind__I_3B},
+{ "bind", "(ILjava/lang/String;)V", Java_SQLite_Stmt_bind__ILjava_lang_String_2},
+{ "bind", "(I)V", Java_SQLite_Stmt_bind__I},
+{ "bind_zeroblob", "(II)V", Java_SQLite_Stmt_bind_1zeroblob},
+{ "bind_parameter_count", "()I", Java_SQLite_Stmt_bind_1parameter_1count},
+{ "bind_parameter_name", "(I)Ljava/lang/String;", Java_SQLite_Stmt_bind_1parameter_1name},
+{ "bind_parameter_index", "(Ljava/lang/String;)I", Java_SQLite_Stmt_bind_1parameter_1index},
+{ "column_int", "(I)I", Java_SQLite_Stmt_column_1int},
+{ "column_long", "(I)J", Java_SQLite_Stmt_column_1long},
+{ "column_double", "(I)D", Java_SQLite_Stmt_column_1double},
+{ "column_bytes", "(I)[B", Java_SQLite_Stmt_column_1bytes},
+{ "column_string", "(I)Ljava/lang/String;", Java_SQLite_Stmt_column_1string},
+{ "column_type", "(I)I", Java_SQLite_Stmt_column_1type},
+{ "column_count", "()I", Java_SQLite_Stmt_column_1count},
+{ "column_table_name", "(I)Ljava/lang/String;", Java_SQLite_Stmt_column_1table_1name},
+{ "column_database_name", "(I)Ljava/lang/String;", Java_SQLite_Stmt_column_1database_1name},
+{ "column_decltype", "(I)Ljava/lang/String;", Java_SQLite_Stmt_column_1decltype},
+{ "column_origin_name", "(I)Ljava/lang/String;", Java_SQLite_Stmt_column_1origin_1name},
+{ "finalize", "()V", Java_SQLite_Stmt_finalize},
+{ "internal_init", "()V", Java_SQLite_Stmt_internal_1init}
+};
+
+static JNINativeMethod sqliteBlobMethods[] = {
+/* Header for class SQLite_Blob */
+
+{ "close", "()V", Java_SQLite_Blob_close},
+{ "write", "([BIII)I", Java_SQLite_Blob_write},
+{ "read", "([BIII)I", Java_SQLite_Blob_read},
+{ "finalize", "()V", Java_SQLite_Blob_finalize},
+{ "internal_init", "()V", Java_SQLite_Blob_internal_1init}
+};
+
+int register_SQLite_Database(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "SQLite/Database",
+ sqliteDatabaseMethods, NELEM(sqliteDatabaseMethods));
+}
+
+int register_SQLite_Vm(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "SQLite/Vm",
+ sqliteVmMethods, NELEM(sqliteVmMethods));
+}
+
+int register_SQLite_FunctionContext(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "SQLite/FunctionContext",
+ sqliteFunctionContextMethods, NELEM(sqliteFunctionContextMethods));
+}
+
+int register_SQLite_Stmt(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "SQLite/Stmt",
+ sqliteStmtMethods, NELEM(sqliteStmtMethods));
+}
+
+int register_SQLite_Blob(JNIEnv* env) {
+ return jniRegisterNativeMethods(env, "SQLite/Blob",
+ sqliteBlobMethods, NELEM(sqliteBlobMethods));
+}
diff --git a/sql/src/main/native/sub.mk b/sql/src/main/native/sub.mk
new file mode 100644
index 0000000..d84e0b6
--- /dev/null
+++ b/sql/src/main/native/sub.mk
@@ -0,0 +1,19 @@
+# This file is included by the top-level libcore Android.mk.
+# It's not a normal makefile, so we don't include CLEAR_VARS
+# or BUILD_*_LIBRARY.
+
+LOCAL_SRC_FILES := \
+ sqlite_jni.c \
+ sqlite_jni_registration.c
+
+LOCAL_C_INCLUDES += \
+ external/sqlite/dist
+
+# Any shared/static libs that are listed here must also
+# be listed in libs/nativehelper/Android.mk.
+# TODO: fix this requirement
+
+LOCAL_SHARED_LIBRARIES += \
+ libsqlite
+
+LOCAL_STATIC_LIBRARIES +=
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/AllTests.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/AllTests.java
new file mode 100644
index 0000000..58c670a
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/AllTests.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * This is autogenerated source file. Includes tests for package org.apache.harmony.sql.tests.java.sql;
+ */
+
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AllTests.suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite("All tests for package org.apache.harmony.sql.tests.java.sql;");
+ // $JUnit-BEGIN$
+
+ suite.addTestSuite(BatchUpdateExceptionTest.class);
+ suite.addTestSuite(ConnectionTest.class);
+ suite.addTestSuite(DataTruncationTest.class);
+ suite.addTestSuite(DatabaseMetaDataTest.class);
+ suite.addTestSuite(DateTest.class);
+ suite.addTestSuite(DriverManagerTest.class);
+ suite.addTestSuite(DriverPropertyInfoTest.class);
+ suite.addTestSuite(ParameterMetaDataTest.class);
+ suite.addTestSuite(ResultSetMetaDataTest.class);
+ suite.addTestSuite(ResultSetTest.class);
+ suite.addTestSuite(SQLExceptionTest.class);
+ suite.addTestSuite(SQLPermissionTest.class);
+ suite.addTestSuite(SQLWarningTest.class);
+ suite.addTestSuite(StatementTest.class);
+ suite.addTestSuite(TimeTest.class);
+ suite.addTestSuite(TimestampTest.class);
+ suite.addTestSuite(TypesTest.class);
+
+ // $JUnit-END$
+ return suite;
+ }
+}
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.java
new file mode 100644
index 0000000..87e737e
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.java
@@ -0,0 +1,438 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.io.Serializable;
+import java.sql.BatchUpdateException;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+@TestTargetClass(BatchUpdateException.class)
+public class BatchUpdateExceptionTest extends TestCase {
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "BatchUpdateException",
+ args = {}
+ )
+ public void testBatchUpdateException() {
+
+ int[] theFinalStates1 = { 0 }; // Error Code state
+ int[][] theFinalStates2 = { null }; // Update Counts array state
+ String[] theFinalStates3 = { null }; // SQL State state value
+ String[] theFinalStates4 = { null }; // Message state
+
+ Exception[] theExceptions = { null };
+
+ BatchUpdateException aBatchUpdateException;
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aBatchUpdateException = new BatchUpdateException();
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getErrorCode(),
+ theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getUpdateCounts(),
+ theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getSQLState(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getMessage(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testBatchUpdateException
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "BatchUpdateException",
+ args = {int[].class}
+ )
+ public void testBatchUpdateExceptionintArray() {
+
+ int[][] init1 = { { 1, 2, 3 }, null };
+
+ int[] theFinalStates1 = { 0, 0 }; // Error Code state
+ int[][] theFinalStates2 = init1; // Update Counts array state
+ String[] theFinalStates3 = { null, null }; // SQL State state value
+ String[] theFinalStates4 = { null, null }; // Message state
+
+ Exception[] theExceptions = { null, null };
+
+ BatchUpdateException aBatchUpdateException;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aBatchUpdateException = new BatchUpdateException(init1[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getErrorCode(),
+ theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getUpdateCounts(),
+ theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getSQLState(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getMessage(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testBatchUpdateExceptionintArray
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "BatchUpdateException",
+ args = {java.lang.String.class, int[].class}
+ )
+ public void testBatchUpdateExceptionStringintArray() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", null, "",
+ ".", "a" };
+ int[][] init2 = { { 1, 2, 3 }, {}, { 3 }, null, { 5, 5 }, { 6 },
+ { 121, 2, 1 }, { 1 }, { 1, 2 } };
+
+ int[] theFinalStates1 = { 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Error Code
+ // state
+ // Update Counts array state
+ int[][] theFinalStates2 = init2;
+ // SQL State state value
+ String[] theFinalStates3 = { null, null, null, null, null, null, null,
+ null, null };
+ String[] theFinalStates4 = init1; // Message state
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null, null };
+
+ BatchUpdateException aBatchUpdateException;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aBatchUpdateException = new BatchUpdateException(init1[i],
+ init2[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getErrorCode(),
+ theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getUpdateCounts(),
+ theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getSQLState(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getMessage(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testBatchUpdateExceptionStringintArray
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "BatchUpdateException",
+ args = {java.lang.String.class, java.lang.String.class, int[].class}
+ )
+ public void testBatchUpdateExceptionStringStringintArray() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", null, "",
+ ".", "a", "a" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", "a", null,
+ "", ".", "a" };
+ int[][] init3 = { { 1, 2, 3 }, {}, { 3 }, { 5, 5 }, { 6 },
+ { 121, 2, 1 }, { 1 }, { 1, 2 }, { 1 }, { 2 }, null };
+
+ int[] theFinalStates1 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; // Error
+ // Code
+ // state
+ // Update Counts array state
+ int[][] theFinalStates2 = init3;
+ // SQL State state value
+ String[] theFinalStates3 = init2;
+ String[] theFinalStates4 = init1; // Message state
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null, null, null, null };
+
+ BatchUpdateException aBatchUpdateException;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aBatchUpdateException = new BatchUpdateException(init1[i],
+ init2[i], init3[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getErrorCode(),
+ theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getUpdateCounts(),
+ theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getSQLState(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getMessage(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testBatchUpdateExceptionStringStringintArray
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "BatchUpdateException",
+ args = {java.lang.String.class, java.lang.String.class, int.class, int[].class}
+ )
+ public void testBatchUpdateExceptionStringStringintintArray() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", null, "",
+ ".", "a", "a" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", "a", null,
+ "", ".", "a" };
+ int[] init3 = { -2147483648, 2147483647, 0, -492417162, -156220255,
+ -173012890, -631026360, -2147483648, -2147483648, -2147483648,
+ -2147483648 };
+ int[][] init4 = { { 1, 2, 3 }, {}, { 3 }, { 5, 5 }, { 6 },
+ { 121, 2, 1 }, { 1 }, { 1, 2 }, { 1 }, { 2 }, null };
+
+ int[] theFinalStates1 = init3; // Error Code state
+ // Update Counts array state
+ int[][] theFinalStates2 = init4;
+ // SQL State state value
+ String[] theFinalStates3 = init2;
+ String[] theFinalStates4 = init1; // Message state
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null, null, null, null };
+
+ BatchUpdateException aBatchUpdateException;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aBatchUpdateException = new BatchUpdateException(init1[i],
+ init2[i], init3[i], init4[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getErrorCode(),
+ theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getUpdateCounts(),
+ theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getSQLState(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getMessage(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testBatchUpdateExceptionStringStringintintArray
+
+ /*
+ * Method test for getUpdateCounts
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getUpdateCounts",
+ args = {}
+ )
+ public void testGetUpdateCounts() {
+
+ BatchUpdateException aBatchUpdateException;
+ int[][] init1 = { { 1, 2, 3 }, {}, null };
+
+ int[] theReturn;
+ int[][] theReturns = init1;
+
+ int[] theFinalStates1 = { 0, 0, 0 }; // Error Code state
+ int[][] theFinalStates2 = init1; // Update Counts array state
+ String[] theFinalStates3 = { null, null, null }; // SQL State state
+ // value
+ String[] theFinalStates4 = { null, null, null }; // Message state
+
+ Exception[] theExceptions = { null, null, null };
+
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aBatchUpdateException = new BatchUpdateException(init1[i]);
+ theReturn = aBatchUpdateException.getUpdateCounts();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getErrorCode(),
+ theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getUpdateCounts(),
+ theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getSQLState(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch: ",
+ aBatchUpdateException.getMessage(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetUpdateCounts
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Serialization test",
+ method = "!SerializationSelf",
+ args = {}
+ )
+ public void testSerializationSelf() throws Exception {
+ BatchUpdateException object = new BatchUpdateException();
+ SerializationTest.verifySelf(object, BATCHUPDATEEXCEPTION_COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Serialization test",
+ method = "!SerializationGolden",
+ args = {}
+ )
+ public void testSerializationCompatibility() throws Exception {
+ int vendorCode = 10;
+ int[] updateCounts = { 1, 2, 3, 4 };
+ BatchUpdateException object = new BatchUpdateException("reason",
+ "SQLState", vendorCode, updateCounts);
+ SerializationTest.verifyGolden(this, object,
+ BATCHUPDATEEXCEPTION_COMPARATOR);
+ }
+
+ // comparator for BatchUpdateException field updateCounts
+ private static final SerializableAssert BATCHUPDATEEXCEPTION_COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ deserialized);
+
+ BatchUpdateException initThr = (BatchUpdateException) initial;
+ BatchUpdateException dserThr = (BatchUpdateException) deserialized;
+
+ // verify updateCounts
+ int[] initUpdateCounts = initThr.getUpdateCounts();
+ int[] dserUpdateCounts = dserThr.getUpdateCounts();
+ assertTrue(Arrays.equals(initUpdateCounts, dserUpdateCounts));
+ }
+ };
+
+} // end class BatchUpdateExceptionTest
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ConnectionTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ConnectionTest.java
new file mode 100644
index 0000000..823c8a5
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ConnectionTest.java
@@ -0,0 +1,101 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(java.sql.Connection.class)
+public class ConnectionTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testPublicStatics() {
+
+ HashMap thePublicStatics = new HashMap();
+ thePublicStatics.put("TRANSACTION_SERIALIZABLE", new Integer(8));
+ thePublicStatics.put("TRANSACTION_REPEATABLE_READ", new Integer(4));
+ thePublicStatics.put("TRANSACTION_READ_COMMITTED", new Integer(2));
+ thePublicStatics.put("TRANSACTION_READ_UNCOMMITTED", new Integer(1));
+ thePublicStatics.put("TRANSACTION_NONE", new Integer(0));
+
+ /*
+ * System.out.println( "TRANSACTION_SERIALIZABLE: " +
+ * Connection.TRANSACTION_SERIALIZABLE ); System.out.println(
+ * "TRANSACTION_REPEATABLE_READ: " +
+ * Connection.TRANSACTION_REPEATABLE_READ ); System.out.println(
+ * "TRANSACTION_READ_COMMITTED: " +
+ * Connection.TRANSACTION_READ_COMMITTED ); System.out.println(
+ * "TRANSACTION_READ_UNCOMMITTED: " +
+ * Connection.TRANSACTION_READ_UNCOMMITTED ); System.out.println(
+ * "TRANSACTION_NONE: " + Connection.TRANSACTION_NONE );
+ */
+
+ Class> connectionClass;
+ try {
+ connectionClass = Class.forName("java.sql.Connection");
+ } catch (ClassNotFoundException e) {
+ fail("java.sql.Connection class not found!");
+ return;
+ } // end try
+
+ Field[] theFields = connectionClass.getDeclaredFields();
+ int requiredModifier = Modifier.PUBLIC + Modifier.STATIC
+ + Modifier.FINAL;
+
+ int countPublicStatics = 0;
+ for (Field element : theFields) {
+ String fieldName = element.getName();
+ int theMods = element.getModifiers();
+ if (Modifier.isPublic(theMods) && Modifier.isStatic(theMods)) {
+ try {
+ Object fieldValue = element.get(null);
+ Object expectedValue = thePublicStatics.get(fieldName);
+ if (expectedValue == null) {
+ fail("Field " + fieldName + " missing!");
+ } // end
+ assertEquals("Field " + fieldName + " value mismatch: ",
+ expectedValue, fieldValue);
+ assertEquals("Field " + fieldName + " modifier mismatch: ",
+ requiredModifier, theMods);
+ countPublicStatics++;
+ } catch (IllegalAccessException e) {
+ fail("Illegal access to Field " + fieldName);
+ } // end try
+ } // end if
+ } // end for
+
+ } // end method testPublicStatics
+
+} // end class ConnectionTest
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.java
new file mode 100644
index 0000000..bafd679
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.java
@@ -0,0 +1,555 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.io.Serializable;
+import java.sql.DataTruncation;
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(DataTruncation.class)
+public class DataTruncationTest extends TestCase {
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "DataTruncation",
+ args = {int.class, boolean.class, boolean.class, int.class, int.class}
+ )
+ public void testDataTruncationintbooleanbooleanintint() {
+
+ int[] init1 = { -2147483648, 2147483647, 0, 329751502, 318587557,
+ -1217247045, 329474146 };
+ boolean[] init2 = { false, true, false, false, false, true, false };
+ boolean[] init3 = { false, true, false, false, false, false, true };
+ int[] init4 = { -2147483648, 2147483647, 0, 1761409290, -1331044048,
+ -576231606, 661635011 };
+ int[] init5 = { -2147483648, 2147483647, 0, 540816689, -1890783845,
+ -105552912, -85923935 };
+
+ String[] theFinalStates1 = { "01004", "01004", "01004", "01004",
+ "01004", "01004", "01004" };
+ String state2 = "Data truncation";
+ String[] theFinalStates2 = { state2, state2, state2, state2, state2,
+ state2, state2 };
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0, 0, 0 };
+ int[] theFinalStates4 = init1;
+ int[] theFinalStates5 = init4;
+ int[] theFinalStates6 = init5;
+ boolean[] theFinalStates7 = init2;
+ boolean[] theFinalStates8 = init3;
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ DataTruncation aDataTruncation;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aDataTruncation = new DataTruncation(init1[i], init2[i],
+ init3[i], init4[i], init5[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getSQLState(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getMessage(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getIndex(), theFinalStates4[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getDataSize(), theFinalStates5[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getTransferSize(), theFinalStates6[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getParameter(), theFinalStates7[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getRead(), theFinalStates8[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testDataTruncationintbooleanbooleanintint
+
+ /*
+ * Method test for getIndex
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getIndex",
+ args = {}
+ )
+ public void testGetIndex() {
+
+ DataTruncation aDataTruncation;
+ int[] init1 = { -2147483648, 2147483647, 0, -2045829673, 1977156911,
+ 478985827, 1687271915 };
+ boolean[] init2 = { false, true, false, false, true, true, true };
+ boolean[] init3 = { false, true, false, false, true, true, true };
+ int[] init4 = { -2147483648, 2147483647, 0, -631377748, 21025030,
+ 1215194589, 1064137121 };
+ int[] init5 = { -2147483648, 2147483647, 0, -897998505, 997578180,
+ 735015866, 264619424 };
+
+ int theReturn;
+ int[] theReturns = init1;
+ String[] theFinalStates1 = { "01004", "01004", "01004", "01004",
+ "01004", "01004", "01004" };
+ String state2 = "Data truncation";
+ String[] theFinalStates2 = { state2, state2, state2, state2, state2,
+ state2, state2 };
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0, 0, 0 };
+ int[] theFinalStates4 = init1;
+ int[] theFinalStates5 = init4;
+ int[] theFinalStates6 = init5;
+ boolean[] theFinalStates7 = init2;
+ boolean[] theFinalStates8 = init3;
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aDataTruncation = new DataTruncation(init1[i], init2[i],
+ init3[i], init4[i], init5[i]);
+ theReturn = aDataTruncation.getIndex();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getSQLState(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getMessage(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getIndex(), theFinalStates4[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getDataSize(), theFinalStates5[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getTransferSize(), theFinalStates6[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getParameter(), theFinalStates7[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getRead(), theFinalStates8[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetIndex
+
+ /*
+ * Method test for getParameter
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getParameter",
+ args = {}
+ )
+ public void testGetParameter() {
+
+ DataTruncation aDataTruncation;
+ int[] init1 = { -2147483648, 2147483647, 0, -492314242, 1637665948,
+ -305785075, 258819883 };
+ boolean[] init2 = { false, true, false, true, true, false, true };
+ boolean[] init3 = { false, true, false, false, false, true, true };
+ int[] init4 = { -2147483648, 2147483647, 0, 1134512579, 533874007,
+ 1709608139, 990656593 };
+ int[] init5 = { -2147483648, 2147483647, 0, -1566784226, -744009101,
+ -444614454, 356465980 };
+
+ boolean theReturn;
+ boolean[] theReturns = init2;
+ String[] theFinalStates1 = { "01004", "01004", "01004", "01004",
+ "01004", "01004", "01004" };
+ String state2 = "Data truncation";
+ String[] theFinalStates2 = { state2, state2, state2, state2, state2,
+ state2, state2 };
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0, 0, 0 };
+ int[] theFinalStates4 = init1;
+ int[] theFinalStates5 = init4;
+ int[] theFinalStates6 = init5;
+ boolean[] theFinalStates7 = init2;
+ boolean[] theFinalStates8 = init3;
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aDataTruncation = new DataTruncation(init1[i], init2[i],
+ init3[i], init4[i], init5[i]);
+ theReturn = aDataTruncation.getParameter();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getSQLState(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getMessage(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getIndex(), theFinalStates4[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getDataSize(), theFinalStates5[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getTransferSize(), theFinalStates6[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getParameter(), theFinalStates7[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getRead(), theFinalStates8[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetParameter
+
+ /*
+ * Method test for getRead
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getRead",
+ args = {}
+ )
+ public void testGetRead() {
+
+ DataTruncation aDataTruncation;
+ int[] init1 = { -2147483648, 2147483647, 0, 2092420209, -1695764964,
+ 1832837995, -80199594 };
+ boolean[] init2 = { false, true, false, false, false, true, true };
+ boolean[] init3 = { false, true, false, false, true, true, false };
+ int[] init4 = { -2147483648, 2147483647, 0, 1762375167, -604897453,
+ 1362491587, 1007466498 };
+ int[] init5 = { -2147483648, 2147483647, 0, 1494407222, -1696982311,
+ -940493360, -1777579868 };
+
+ boolean theReturn;
+ boolean[] theReturns = init3;
+ String[] theFinalStates1 = { "01004", "01004", "01004", "01004",
+ "01004", "01004", "01004" };
+ String state2 = "Data truncation";
+ String[] theFinalStates2 = { state2, state2, state2, state2, state2,
+ state2, state2 };
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0, 0, 0 };
+ int[] theFinalStates4 = init1;
+ int[] theFinalStates5 = init4;
+ int[] theFinalStates6 = init5;
+ boolean[] theFinalStates7 = init2;
+ boolean[] theFinalStates8 = init3;
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aDataTruncation = new DataTruncation(init1[i], init2[i],
+ init3[i], init4[i], init5[i]);
+ theReturn = aDataTruncation.getRead();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getSQLState(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getMessage(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getIndex(), theFinalStates4[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getDataSize(), theFinalStates5[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getTransferSize(), theFinalStates6[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getParameter(), theFinalStates7[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getRead(), theFinalStates8[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetRead
+
+ /*
+ * Method test for getDataSize
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDataSize",
+ args = {}
+ )
+ public void testGetDataSize() {
+
+ DataTruncation aDataTruncation;
+ int[] init1 = { -2147483648, 2147483647, 0, 1146707040, -2020665632,
+ 1268632617, -1595624039 };
+ boolean[] init2 = { false, true, false, true, false, true, true };
+ boolean[] init3 = { false, true, false, true, true, false, false };
+ int[] init4 = { -2147483648, 2147483647, 0, -367493363, 328996907,
+ -1581326731, 835022052 };
+ int[] init5 = { -2147483648, 2147483647, 0, -886134194, 908213800,
+ 1123419516, -429606389 };
+
+ int theReturn;
+ int[] theReturns = init4;
+ String[] theFinalStates1 = { "01004", "01004", "01004", "01004",
+ "01004", "01004", "01004" };
+ String state2 = "Data truncation";
+ String[] theFinalStates2 = { state2, state2, state2, state2, state2,
+ state2, state2 };
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0, 0, 0 };
+ int[] theFinalStates4 = init1;
+ int[] theFinalStates5 = init4;
+ int[] theFinalStates6 = init5;
+ boolean[] theFinalStates7 = init2;
+ boolean[] theFinalStates8 = init3;
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aDataTruncation = new DataTruncation(init1[i], init2[i],
+ init3[i], init4[i], init5[i]);
+ theReturn = aDataTruncation.getDataSize();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getSQLState(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getMessage(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getIndex(), theFinalStates4[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getDataSize(), theFinalStates5[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getTransferSize(), theFinalStates6[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getParameter(), theFinalStates7[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getRead(), theFinalStates8[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetDataSize
+
+ /*
+ * Method test for getTransferSize
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getTransferSize",
+ args = {}
+ )
+ public void testGetTransferSize() {
+
+ DataTruncation aDataTruncation;
+ int[] init1 = { -2147483648, 2147483647, 0, 78096124, 1719192600,
+ -1661234694, -1205825753 };
+ boolean[] init2 = { false, true, false, false, true, false, true };
+ boolean[] init3 = { false, true, false, false, false, false, false };
+ int[] init4 = { -2147483648, 2147483647, 0, -493779295, -2042560243,
+ -217347438, 1357818664 };
+ int[] init5 = { -2147483648, 2147483647, 0, -1647009002, -717544563,
+ -1368171905, -918209633 };
+
+ int theReturn;
+ int[] theReturns = init5;
+ String[] theFinalStates1 = { "01004", "01004", "01004", "01004",
+ "01004", "01004", "01004" };
+ String state2 = "Data truncation";
+ String[] theFinalStates2 = { state2, state2, state2, state2, state2,
+ state2, state2 };
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0, 0, 0 };
+ int[] theFinalStates4 = init1;
+ int[] theFinalStates5 = init4;
+ int[] theFinalStates6 = init5;
+ boolean[] theFinalStates7 = init2;
+ boolean[] theFinalStates8 = init3;
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aDataTruncation = new DataTruncation(init1[i], init2[i],
+ init3[i], init4[i], init5[i]);
+ theReturn = aDataTruncation.getTransferSize();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getSQLState(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getMessage(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getIndex(), theFinalStates4[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getDataSize(), theFinalStates5[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getTransferSize(), theFinalStates6[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getParameter(), theFinalStates7[i]);
+ assertEquals(i + " Final state mismatch", aDataTruncation
+ .getRead(), theFinalStates8[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetTransferSize
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Serialization test",
+ method = "!SerializationSelf",
+ args = {}
+ )
+ public void testSerializationSelf() throws Exception {
+ DataTruncation object = new DataTruncation(10, true, true, 10, 10);
+ SerializationTest.verifySelf(object, DATATRUNCATION_COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Serialization test",
+ method = "!SerializationGolden",
+ args = {}
+ )
+ public void testSerializationCompatibility() throws Exception {
+ DataTruncation object = new DataTruncation(10, true, true, 10, 10);
+ SerializationTest.verifyGolden(this, object, DATATRUNCATION_COMPARATOR);
+ }
+
+ // comparator for DataTruncation objects
+ private static final SerializableAssert DATATRUNCATION_COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ deserialized);
+
+ DataTruncation initThr = (DataTruncation) initial;
+ DataTruncation dserThr = (DataTruncation) deserialized;
+
+ // verify index
+ assertEquals(initThr.getIndex(), dserThr.getIndex());
+
+ // verify parameter
+ assertEquals(initThr.getParameter(), dserThr.getParameter());
+
+ // verify read
+ assertEquals(initThr.getRead(), dserThr.getRead());
+
+ // verify dataSize
+ assertEquals(initThr.getDataSize(), dserThr.getDataSize());
+
+ // verify transferSize
+ assertEquals(initThr.getTransferSize(), dserThr.getTransferSize());
+ }
+ };
+
+} // end class DataTruncationTest
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.java
new file mode 100644
index 0000000..5c63c5a
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.java
@@ -0,0 +1,131 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(java.sql.DatabaseMetaData.class)
+public class DatabaseMetaDataTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testPublicStatics() {
+
+ HashMap thePublicStatics = new HashMap();
+ thePublicStatics.put("sqlStateSQL99", new Integer(2));
+ thePublicStatics.put("sqlStateXOpen", new Integer(1));
+ thePublicStatics.put("attributeNullableUnknown", new Short((short) 2));
+ thePublicStatics.put("attributeNullable", new Short((short) 1));
+ thePublicStatics.put("attributeNoNulls", new Short((short) 0));
+ thePublicStatics.put("tableIndexOther", new Short((short) 3));
+ thePublicStatics.put("tableIndexHashed", new Short((short) 2));
+ thePublicStatics.put("tableIndexClustered", new Short((short) 1));
+ thePublicStatics.put("tableIndexStatistic", new Short((short) 0));
+ thePublicStatics.put("typeSearchable", new Integer(3));
+ thePublicStatics.put("typePredBasic", new Integer(2));
+ thePublicStatics.put("typePredChar", new Integer(1));
+ thePublicStatics.put("typePredNone", new Integer(0));
+ thePublicStatics.put("typeNullableUnknown", new Integer(2));
+ thePublicStatics.put("typeNullable", new Integer(1));
+ thePublicStatics.put("typeNoNulls", new Integer(0));
+ thePublicStatics.put("importedKeyNotDeferrable", new Integer(7));
+ thePublicStatics.put("importedKeyInitiallyImmediate", new Integer(6));
+ thePublicStatics.put("importedKeyInitiallyDeferred", new Integer(5));
+ thePublicStatics.put("importedKeySetDefault", new Integer(4));
+ thePublicStatics.put("importedKeyNoAction", new Integer(3));
+ thePublicStatics.put("importedKeySetNull", new Integer(2));
+ thePublicStatics.put("importedKeyRestrict", new Integer(1));
+ thePublicStatics.put("importedKeyCascade", new Integer(0));
+ thePublicStatics.put("versionColumnPseudo", new Integer(2));
+ thePublicStatics.put("versionColumnNotPseudo", new Integer(1));
+ thePublicStatics.put("versionColumnUnknown", new Integer(0));
+ thePublicStatics.put("bestRowPseudo", new Integer(2));
+ thePublicStatics.put("bestRowNotPseudo", new Integer(1));
+ thePublicStatics.put("bestRowUnknown", new Integer(0));
+ thePublicStatics.put("bestRowSession", new Integer(2));
+ thePublicStatics.put("bestRowTransaction", new Integer(1));
+ thePublicStatics.put("bestRowTemporary", new Integer(0));
+ thePublicStatics.put("columnNullableUnknown", new Integer(2));
+ thePublicStatics.put("columnNullable", new Integer(1));
+ thePublicStatics.put("columnNoNulls", new Integer(0));
+ thePublicStatics.put("procedureNullableUnknown", new Integer(2));
+ thePublicStatics.put("procedureNullable", new Integer(1));
+ thePublicStatics.put("procedureNoNulls", new Integer(0));
+ thePublicStatics.put("procedureColumnResult", new Integer(3));
+ thePublicStatics.put("procedureColumnReturn", new Integer(5));
+ thePublicStatics.put("procedureColumnOut", new Integer(4));
+ thePublicStatics.put("procedureColumnInOut", new Integer(2));
+ thePublicStatics.put("procedureColumnIn", new Integer(1));
+ thePublicStatics.put("procedureColumnUnknown", new Integer(0));
+ thePublicStatics.put("procedureReturnsResult", new Integer(2));
+ thePublicStatics.put("procedureNoResult", new Integer(1));
+ thePublicStatics.put("procedureResultUnknown", new Integer(0));
+
+ Class> databaseMetaDataClass;
+ try {
+ databaseMetaDataClass = Class.forName("java.sql.DatabaseMetaData");
+ } catch (ClassNotFoundException e) {
+ fail("java.sql.DatabaseMetaData class not found!");
+ return;
+ } // end try
+
+ Field[] theFields = databaseMetaDataClass.getDeclaredFields();
+ int requiredModifier = Modifier.PUBLIC + Modifier.STATIC
+ + Modifier.FINAL;
+
+ int countPublicStatics = 0;
+ for (Field element : theFields) {
+ String fieldName = element.getName();
+ int theMods = element.getModifiers();
+ if (Modifier.isPublic(theMods) && Modifier.isStatic(theMods)) {
+ try {
+ Object fieldValue = element.get(null);
+ Object expectedValue = thePublicStatics.get(fieldName);
+ if (expectedValue == null) {
+ fail("Field " + fieldName + " missing!");
+ } // end
+ assertEquals("Field " + fieldName + " value mismatch: ",
+ expectedValue, fieldValue);
+ assertEquals("Field " + fieldName + " modifier mismatch: ",
+ requiredModifier, theMods);
+ countPublicStatics++;
+ } catch (IllegalAccessException e) {
+ fail("Illegal access to Field " + fieldName);
+ } // end try
+ } // end if
+ } // end for
+
+ } // end method testPublicStatics
+
+} // end class DatabaseMetaDataTest
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java
new file mode 100644
index 0000000..3b833c4
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java
@@ -0,0 +1,457 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Date;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import junit.framework.TestCase;
+@TestTargetClass(Date.class)
+/**
+ * JUnit Testcase for the java.sql.Date class
+ *
+ */
+public class DateTest extends TestCase {
+
+ // A calendar object created in the GMT time zone
+ static Calendar aCal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
+
+ // Some interesting millisecond time values
+ // These millisecond times are all in GMT, effectively
+ static long TIME_AN_HOUR = 3600000; // 1000 * 60 * 60 ms
+
+ static long TIME_EPOCH = 0;
+
+ static long TIME_NOW = System.currentTimeMillis();
+
+ static long TIME_NEGATIVE = -3600001;
+
+ static long TIME_TESTDATE1 = getTime(1999, Calendar.DECEMBER, 31, 23, 59,
+ 59);
+
+ static long TIME_TESTDATE2 = getTime(2010, Calendar.JUNE, 10, 20, 3, 16);
+
+ static long TIME_TESTDATE3 = getTime(1931, Calendar.APRIL, 21, 1, 25, 1);
+
+ static long TIME_LOWERLIMIT = Long.MIN_VALUE;
+
+ static long TIME_UPPERLIMIT = Long.MAX_VALUE;
+
+ // Date strings
+ static String SQL_DATESTRING1 = "1999-12-31";
+
+ static String SQL_DATESTRING2 = "2010-06-10";
+
+ static String SQL_DATESTRING3 = "1931-04-21";
+
+ static String SQL_EPOCHSTRING = "1970-01-01";
+
+ static String SQL_DATEDAY1 = "1970-01-02";
+
+ static String SQL_NEGATIVE = "1969-12-31";
+
+ static long[] TIME_ARRAY = new long[] { TIME_TESTDATE1, TIME_TESTDATE2,
+ TIME_TESTDATE3, TIME_NEGATIVE, TIME_EPOCH };
+
+ // Date string array for London (GMT)
+ static String[] SQL_DATEARRAY = new String[] { SQL_DATESTRING1,
+ SQL_DATESTRING2, SQL_DATESTRING3, SQL_NEGATIVE, SQL_EPOCHSTRING };
+
+ // Date string array for New York - sometimes a day earlier than London
+ static String[] SQL_NYARRAY = new String[] { "1999-12-31", "2010-06-10",
+ "1931-04-20", "1969-12-31", "1969-12-31" };
+
+ // Date string for Tokyo
+ static String[] SQL_JAPANARRAY = new String[] { "2000-01-01", "2010-06-11",
+ "1931-04-21", "1970-01-01", "1970-01-01" };
+
+ static String[][] SQL_TZ_DATEARRAYS = new String[][] { SQL_DATEARRAY,
+ SQL_NYARRAY, SQL_JAPANARRAY };
+
+ // Timezones
+ static String TZ_LONDON = "Europe/London"; // Note: != GMT
+
+ static String TZ_PACIFIC = "America/Los_Angeles"; // GNT - 8
+
+ static String TZ_JAPAN = "Asia/Tokyo"; // GMT + 9
+
+ static String[] TIMEZONES = { TZ_LONDON, TZ_PACIFIC, TZ_JAPAN };
+
+ /*
+ * Helper method to create a long milliseconds time from a supplied date and
+ * time
+ */
+ static private long getTime(int year, int month, int date, int hour,
+ int minute, int second) {
+ aCal.set(year, month, date, hour, minute, second);
+ return aCal.getTimeInMillis();
+ } // end method getTime( int, int, int, int, int, int )
+
+ /*
+ * Test of the Date(int, int, int) constructor - now deprecated but still
+ * functioning
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "Date",
+ args = {int.class, int.class, int.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testDateintintint() {
+
+ int init1[] = { 99, 8099, 9000, 99999, 99, 99, -1, -100 };
+ int init2[] = { 11, 0, 0, 0, 999, 0, 0, -111 };
+ int init3[] = { 31, 0, 0, 0, 0, 999, 0, -999 };
+
+ for (int i = 0; i < init1.length; i++) {
+ Date theDate = new Date(init1[i], init2[i], init3[i]);
+ assertNotNull(theDate);
+ } // end for
+
+ } // end method testDateintintint
+
+ /*
+ * Test of the Date( long ) constructor
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "Date",
+ args = {long.class}
+ )
+ public void testDatelong() {
+
+ long init1[] = { TIME_TESTDATE1, TIME_TESTDATE2, TIME_TESTDATE3,
+ TIME_NEGATIVE, TIME_LOWERLIMIT, TIME_UPPERLIMIT, TIME_EPOCH,
+ TIME_NOW };
+
+ for (long element : init1) {
+ Date theDate = new Date(element);
+ assertNotNull(theDate);
+ } // end for
+
+ } // end method testDatelong
+
+ /*
+ * Test of the (deprecated) int Date.getHours() method - which always throws
+ * an IllegalArgumentException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getHours",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetHours() {
+ Date theDate = new Date(TIME_TESTDATE1);
+ try {
+ theDate.getHours();
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ie) {
+ //expected
+ } // end try
+ } // end method testGetHours()
+
+ /*
+ * Test of the (deprecated) int Date.getMinutes() method - which always
+ * throws an IllegalArgumentException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMinutes",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetMinutes() {
+ Date theDate = new Date(TIME_TESTDATE1);
+ try {
+ theDate.getMinutes();
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ie) {
+ //expected
+ } // end try
+ } // end method testGetMinutes()
+
+ /*
+ * Test of the (deprecated) int Date.getSeconds() method - which always
+ * throws an IllegalArgumentException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getSeconds",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetSeconds() {
+ Date theDate = new Date(TIME_TESTDATE1);
+ try {
+ theDate.getSeconds();
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ie) {
+ //expected
+ } // end try
+ } // end method testGetSeconds()
+
+ /*
+ * Test of the (deprecated) Date.setHours( int ) method - which always
+ * throws an IllegalArgumentException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setHours",
+ args = {int.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testSetHours() {
+ Date theDate = new Date(TIME_TESTDATE1);
+ try {
+ theDate.setHours(22);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ie) {
+ //expected
+ } // end try
+ } // end method testSetHours( int )
+
+ /*
+ * Test of the (deprecated) Date.setMinutes( int ) method - which always
+ * throws an IllegalArgumentException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setMinutes",
+ args = {int.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testSetMinutes() {
+ Date theDate = new Date(TIME_TESTDATE1);
+ try {
+ theDate.setMinutes(54);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ie) {
+ //expected
+ } // end try
+
+ } // end method testSetMinutes( int )
+
+ /*
+ * Test of the (deprecated) Date.setSeconds( int ) method - which always
+ * throws an IllegalArgumentException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setSeconds",
+ args = {int.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testSetSeconds() {
+ Date theDate = new Date(TIME_TESTDATE1);
+ try {
+ theDate.setSeconds(36);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException ie) {
+ //expected
+ } // end try
+ } // end method testSetSeconds( int )
+
+ /*
+ * Test of the String Date.toString() method This method is sensitive to the
+ * time zone setting and this test sets the time zone before calling the
+ * toString() method.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "toString",
+ args = {}
+ )
+ public void testToString() {
+ // This test is set up for GMT time zone, so need to set the time zone
+ // to GMT first
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Date theDate = new Date(TIME_ARRAY[i]);
+ assertEquals(SQL_DATEARRAY[i], theDate.toString());
+ } // end for
+
+ } // end method testToString()
+
+ /*
+ * Test of the void setTime(int) method This does depend on the Time Zone
+ * settings and sets up the time zone to one of a group of specific time
+ * zones and tests the method using each of these time zones in turn.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setTime",
+ args = {long.class}
+ )
+ public void testSetTimelong() {
+
+ // Loop over the array of test timezones
+ for (int i = 0; i < TIMEZONES.length; i++) {
+ testSetTimelong(TIMEZONES[i], SQL_TZ_DATEARRAYS[i]);
+ } // end for
+
+ } // end method testSetTimelong()
+
+ /*
+ * Internal method for testing Date.setTime with a specific time zone
+ */
+ private void testSetTimelong(String timeZoneName, String[] dateArray) {
+
+ if (timeZoneName != null) {
+ TimeZone.setDefault(TimeZone.getTimeZone(timeZoneName));
+ } // end if
+
+ Date theDate = new Date(TIME_TESTDATE1);
+
+ // Loop over the array of test times & dates
+ for (int i = 0; i < dateArray.length; i++) {
+ theDate.setTime(TIME_ARRAY[i]);
+ assertEquals(dateArray[i], theDate.toString());
+ } // end for
+
+ } // end method testSetTimelong()
+
+ /*
+ * Test of the Date.valueOf( String ) method This test is not dependent on
+ * the default Time Zone setting
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "valueOf",
+ args = {java.lang.String.class}
+ )
+ public void testValueOf() {
+ String SQL_NOTVALID1 = "ABCDEF"; // Invalid date string
+ String SQL_NOTVALID2 = "12321.43.56"; // Invalid date string
+ String SQL_NOTVALID3 = null; // Invalid date string
+ String[] SQL_INVALIDARRAY = { SQL_NOTVALID1, SQL_NOTVALID2,
+ SQL_NOTVALID3 };
+
+ Date theDate;
+
+ for (String element : SQL_DATEARRAY) {
+ theDate = Date.valueOf(element);
+ assertEquals(element, theDate.toString());
+ } // end for
+
+ for (String element : SQL_INVALIDARRAY) {
+ try {
+ theDate = Date.valueOf(element);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+ } // end for
+
+ } // end method testValueOf()
+
+ /**
+ * @tests java.sql.Date#valueOf(String )
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "valueOf",
+ args = {java.lang.String.class}
+ )
+ public void test_valueOf_IllegalArgumentException() {
+ try{
+ Date.valueOf("1996-10-07-01");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ //expected
+ }
+
+ try{
+ Date.valueOf("-10-07-01");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Date.valueOf("--01");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Date.valueOf("1991--");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Date.valueOf("-01-");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Date.valueOf("-10-w2-01");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Date.valueOf("07-w2-");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Date.valueOf("1997-w2-w2");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ //expected
+ }
+
+ try{
+ Date.valueOf("1996--01");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ //expected
+ }
+ }
+
+} // end class DateTest
+
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
new file mode 100644
index 0000000..a4b12ab
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
@@ -0,0 +1,682 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.BrokenTest;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.io.ByteArrayOutputStream;
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.lang.reflect.Method;
+import java.security.Permission;
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.SQLPermission;
+import java.util.Enumeration;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+@TestTargetClass(DriverManager.class)
+/**
+ * JUnit Testcase for the java.sql.DriverManager class
+ *
+ */
+public class DriverManagerTest extends TestCase {
+
+ // Set of driver names to use
+ static final String DRIVER1 = "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver1";
+
+ static final String DRIVER2 = "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver2";
+
+ static final String DRIVER3 = "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver3";
+
+ static final String DRIVER4 = "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver4";
+
+ static final String DRIVER5 = "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver5";
+
+ static final String INVALIDDRIVER1 = "abc.klm.Foo";
+
+ static String[] driverNames = { DRIVER1, DRIVER2 };
+
+ static int numberLoaded;
+
+ static String baseURL1 = "jdbc:mikes1";
+
+ static String baseURL4 = "jdbc:mikes4";
+
+ static final String JDBC_PROPERTY = "jdbc.drivers";
+
+ static TestHelper_ClassLoader testClassLoader = new TestHelper_ClassLoader();
+
+ // Static initializer to load the drivers so that they are available to all
+ // the
+ // test methods as needed.
+ @Override
+ public void setUp() {
+ numberLoaded = loadDrivers();
+ } // end setUp()
+
+ /**
+ * Test for the method DriverManager.deregisterDriver
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "SQLException checking missed: not feasible.",
+ method = "deregisterDriver",
+ args = {java.sql.Driver.class}
+ )
+ public void testDeregisterDriver() throws Exception {
+ // First get one of the drivers loaded by the test
+ Driver aDriver;
+ aDriver = DriverManager.getDriver(baseURL4);
+
+ // Deregister this driver
+ DriverManager.deregisterDriver(aDriver);
+
+ assertFalse("testDeregisterDriver: Driver was not deregistered.",
+ isDriverLoaded(aDriver));
+
+ // Re-register this driver (so subsequent tests have it available)
+ DriverManager.registerDriver(aDriver);
+ assertTrue("testDeregisterDriver: Driver did not reload.",
+ isDriverLoaded(aDriver));
+
+ // Test deregistering a null driver
+ DriverManager.deregisterDriver(null);
+
+ // Test deregistering a driver which was not loaded by this test's
+ // classloader
+ // TODO - need to load a driver with a different classloader!!
+ aDriver = DriverManager.getDriver(baseURL1);
+
+ try {
+ Class> driverClass = Class
+ .forName(
+ "org.apache.harmony.sql.tests.java.sql.TestHelper_DriverManager",
+ true, testClassLoader);
+
+ // Give the Helper class one of our drivers....
+ Class>[] methodClasses = {Class.forName("java.sql.Driver")};
+ Method theMethod = driverClass.getDeclaredMethod("setDriver",
+ methodClasses);
+ Object[] args = {aDriver};
+ assertNotNull(args);
+ theMethod.invoke(null, args);
+ } catch (Exception e) {
+ fail("testDeregisterDriver: Got exception allocating TestHelper: "
+ + e.getMessage());
+ e.printStackTrace();
+ return;
+ } // end try
+
+ // Check that the driver was not deregistered
+ assertTrue(
+ "testDeregisterDriver: Driver was incorrectly deregistered.",
+ DriverManagerTest.isDriverLoaded(aDriver));
+
+ } // end method testDeregisterDriver()
+
+ static void printClassLoader(Object theObject) {
+ Class extends Object> theClass = theObject.getClass();
+ ClassLoader theClassLoader = theClass.getClassLoader();
+ System.out.println("ClassLoader is: " + theClassLoader.toString()
+ + " for object: " + theObject.toString());
+ } // end method printClassLoader( Object )
+
+ static boolean isDriverLoaded(Driver theDriver) {
+ Enumeration> driverList = DriverManager.getDrivers();
+ while (driverList.hasMoreElements()) {
+ if ((Driver) driverList.nextElement() == theDriver) {
+ return true;
+ }
+ } // end while
+ return false;
+ } // end method isDriverLoaded( Driver )
+
+ /*
+ * Class under test for Connection getConnection(String)
+ */
+ // valid connection - data1 does not require a user and password...
+ static String validConnectionURL = "jdbc:mikes1:data1";
+
+ // invalid connection - data2 requires a user & password
+ static String invalidConnectionURL1 = "jdbc:mikes1:data2";
+
+ // invalid connection - URL is gibberish
+ static String invalidConnectionURL2 = "xyz1:abc3:456q";
+
+ // invalid connection - URL is null
+ static String invalidConnectionURL3 = null;
+
+ static String[] invalidConnectionURLs = { invalidConnectionURL2,
+ invalidConnectionURL3 };
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getConnection",
+ args = {java.lang.String.class}
+ )
+ public void testGetConnectionString() throws SQLException {
+ Connection theConnection = null;
+ // validConnection - no user & password required
+ theConnection = DriverManager.getConnection(validConnectionURL);
+ assertNotNull(theConnection);
+ assertNotNull(DriverManager.getConnection(invalidConnectionURL1));
+
+ for (String element : invalidConnectionURLs) {
+ try {
+ theConnection = DriverManager
+ .getConnection(element);
+ fail("Should throw SQLException");
+ } catch (SQLException e) {
+ //expected
+ } // end try
+ } // end for
+ } // end method testGetConnectionString()
+
+ /**
+ * @tests java.sql.DriverManager#getConnection(String, Properties)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getConnection",
+ args = {java.lang.String.class, java.util.Properties.class}
+ )
+ public void test_getConnection_LStringLProperties() {
+ try {
+ DriverManager.getConnection("fff", //$NON-NLS-1$
+ new Properties());
+ fail("Should throw SQLException.");
+ } catch (SQLException e) {
+ assertEquals("08001", e.getSQLState()); //$NON-NLS-1$
+ }
+
+ try {
+ DriverManager.getConnection(null,
+ new Properties());
+ fail("Should throw SQLException.");
+ } catch (SQLException e) {
+ assertEquals("08001", e.getSQLState()); //$NON-NLS-1$
+ }
+ }
+
+ /*
+ * Class under test for Connection getConnection(String, Properties)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getConnection",
+ args = {java.lang.String.class, java.util.Properties.class}
+ )
+ public void testGetConnectionStringProperties() throws SQLException {
+ String validURL1 = "jdbc:mikes1:data2";
+ String validuser1 = "theuser";
+ String validpassword1 = "thepassword";
+ String invalidURL1 = "xyz:abc1:foo";
+ String invalidURL2 = "jdbc:mikes1:crazyone";
+ String invalidURL3 = "";
+ String invaliduser1 = "jonny nouser";
+ String invalidpassword1 = "whizz";
+ Properties nullProps = null;
+ Properties validProps = new Properties();
+ validProps.setProperty("user", validuser1);
+ validProps.setProperty("password", validpassword1);
+ Properties invalidProps1 = new Properties();
+ invalidProps1.setProperty("user", invaliduser1);
+ invalidProps1.setProperty("password", invalidpassword1);
+ String[] invalidURLs = { null, invalidURL1,
+ invalidURL2, invalidURL3 };
+ Properties[] invalidProps = { nullProps, invalidProps1};
+
+
+
+ Connection theConnection = null;
+ // validConnection - user & password required
+ theConnection = DriverManager.getConnection(validURL1, validProps);
+ assertNotNull(theConnection);
+
+ // invalid Connections
+ for (int i = 0; i < invalidURLs.length; i++) {
+ theConnection = null;
+ try {
+ theConnection = DriverManager.getConnection(invalidURLs[i],
+ validProps);
+ fail("Should throw SQLException");
+ } catch (SQLException e) {
+ //expected
+ } // end try
+ } // end for
+ for (Properties invalidProp : invalidProps) {
+ assertNotNull(DriverManager.getConnection(validURL1, invalidProp));
+ }
+ } // end method testGetConnectionStringProperties()
+
+ /*
+ * Class under test for Connection getConnection(String, String, String)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getConnection",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void testGetConnectionStringStringString() throws SQLException {
+ String validURL1 = "jdbc:mikes1:data2";
+ String validuser1 = "theuser";
+ String validpassword1 = "thepassword";
+ String invalidURL1 = "xyz:abc1:foo";
+ String invaliduser1 = "jonny nouser";
+ String invalidpassword1 = "whizz";
+ String[] invalid1 = { null, validuser1, validpassword1 };
+ String[] invalid2 = { validURL1, null, validpassword1 };
+ String[] invalid3 = { validURL1, validuser1, null };
+ String[] invalid4 = { invalidURL1, validuser1, validpassword1 };
+ String[] invalid5 = { validURL1, invaliduser1, invalidpassword1 };
+ String[] invalid6 = { validURL1, validuser1, invalidpassword1 };
+ String[][] invalids1 = { invalid1, invalid4};
+ String[][] invalids2 = {invalid2, invalid3, invalid5, invalid6 };
+
+ Connection theConnection = null;
+ // validConnection - user & password required
+ theConnection = DriverManager.getConnection(validURL1, validuser1,
+ validpassword1);
+ assertNotNull(theConnection);
+ for (String[] theData : invalids1) {
+ theConnection = null;
+ try {
+ theConnection = DriverManager.getConnection(theData[0],
+ theData[1], theData[2]);
+ fail("Should throw SQLException.");
+ } catch (SQLException e) {
+ //expected
+ } // end try
+ } // end for
+ for (String[] theData : invalids2) {
+ assertNotNull(DriverManager.getConnection(theData[0], theData[1],
+ theData[2]));
+ }
+ } // end method testGetConnectionStringStringString()
+
+ static String validURL1 = "jdbc:mikes1";
+
+ static String validURL2 = "jdbc:mikes2";
+
+ static String invalidURL1 = "xyz:acb";
+
+ static String invalidURL2 = null;
+
+ static String[] validURLs = { validURL1, validURL2 };
+
+ static String[] invalidURLs = { invalidURL1, invalidURL2 };
+
+ static String exceptionMsg1 = "No suitable driver";
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDriver",
+ args = {java.lang.String.class}
+ )
+ public void testGetDriver() throws SQLException {
+ for (String element : validURLs) {
+ Driver validDriver = DriverManager.getDriver(element);
+ assertNotNull(validDriver);
+ } // end for
+
+ for (String element : invalidURLs) {
+ try {
+ DriverManager.getDriver(element);
+ fail("Should throw SQLException");
+ } catch (SQLException e) {
+ assertEquals("08001", e.getSQLState());
+ assertEquals(exceptionMsg1, e.getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetDriver()
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDrivers",
+ args = {}
+ )
+ public void testGetDrivers() {
+ // Load a driver manager
+ Enumeration driverList = DriverManager.getDrivers();
+ int i = 0;
+ while (driverList.hasMoreElements()) {
+ Driver theDriver = driverList.nextElement();
+ assertNotNull(theDriver);
+ i++;
+ } // end while
+
+ // Check that all the drivers are in the list...
+ assertEquals("testGetDrivers: Don't see all the loaded drivers - ", i,
+ numberLoaded);
+ } // end method testGetDrivers()
+
+ static int timeout1 = 25;
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getLoginTimeout",
+ args = {}
+ )
+ public void testGetLoginTimeout() {
+ DriverManager.setLoginTimeout(timeout1);
+ assertEquals(timeout1, DriverManager.getLoginTimeout());
+ } // end method testGetLoginTimeout()
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getLogStream",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetLogStream() {
+ assertNull(DriverManager.getLogStream());
+
+ DriverManager.setLogStream(testPrintStream);
+ assertTrue(DriverManager.getLogStream() == testPrintStream);
+
+ DriverManager.setLogStream(null);
+ } // end method testGetLogStream()
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getLogWriter",
+ args = {}
+ )
+ public void testGetLogWriter() {
+ assertNull(DriverManager.getLogWriter());
+
+ DriverManager.setLogWriter(testPrintWriter);
+
+ assertTrue(DriverManager.getLogWriter() == testPrintWriter);
+
+ DriverManager.setLogWriter(null);
+ } // end method testGetLogWriter()
+
+ static String testMessage = "DriverManagerTest: test message for print stream";
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "println",
+ args = {java.lang.String.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testPrintln() {
+ // System.out.println("testPrintln");
+ DriverManager.println(testMessage);
+
+ DriverManager.setLogWriter(testPrintWriter);
+ DriverManager.println(testMessage);
+
+ String theOutput = outputStream.toString();
+ // System.out.println("testPrintln: output= " + theOutput );
+ assertTrue(theOutput.startsWith(testMessage));
+
+ DriverManager.setLogWriter(null);
+
+ DriverManager.setLogStream(testPrintStream);
+ DriverManager.println(testMessage);
+
+ theOutput = outputStream2.toString();
+ // System.out.println("testPrintln: output= " + theOutput );
+ assertTrue(theOutput.startsWith(testMessage));
+
+ DriverManager.setLogStream(null);
+ } // end method testPrintln()
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking missed: not feasible",
+ method = "registerDriver",
+ args = {java.sql.Driver.class}
+ )
+ public void testRegisterDriver() throws ClassNotFoundException,
+ SQLException, IllegalAccessException, InstantiationException {
+ String EXTRA_DRIVER_NAME = "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver3";
+
+ try {
+ DriverManager.registerDriver(null);
+ fail("Should throw NullPointerException.");
+ } catch (NullPointerException e) {
+ // expected
+ } // end try
+
+ Driver theDriver = null;
+ // Load another Driver that isn't in the basic set
+ Class> driverClass = Class.forName(EXTRA_DRIVER_NAME);
+ theDriver = (Driver) driverClass.newInstance();
+ DriverManager.registerDriver(theDriver);
+
+ assertTrue("testRegisterDriver: driver not in loaded set",
+ isDriverLoaded(theDriver));
+
+
+
+ } // end testRegisterDriver()
+
+ static int validTimeout1 = 15;
+
+ static int validTimeout2 = 0;
+
+ static int[] validTimeouts = { validTimeout1, validTimeout2 };
+
+ static int invalidTimeout1 = -10;
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setLoginTimeout",
+ args = {int.class}
+ )
+ public void testSetLoginTimeout() {
+ for (int element : validTimeouts) {
+ DriverManager.setLoginTimeout(element);
+
+ assertEquals(element, DriverManager.getLoginTimeout());
+ } // end for
+ // Invalid timeouts
+ DriverManager.setLoginTimeout(invalidTimeout1);
+ assertEquals(invalidTimeout1, DriverManager.getLoginTimeout());
+ } // end testSetLoginTimeout()
+
+ static ByteArrayOutputStream outputStream2 = new ByteArrayOutputStream();
+
+ static PrintStream testPrintStream = new PrintStream(outputStream2);
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setLogStream",
+ args = {java.io.PrintStream.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testSetLogStream() {
+ // System.out.println("testSetLogStream");
+ DriverManager.setLogStream(testPrintStream);
+
+ assertSame(testPrintStream, DriverManager.getLogStream());
+
+ DriverManager.setLogStream(null);
+
+ assertNull(DriverManager.getLogStream());
+
+ // Now let's deal with the case where there is a SecurityManager in
+ // place
+ TestSecurityManager theSecManager = new TestSecurityManager();
+ System.setSecurityManager(theSecManager);
+
+ theSecManager.setLogAccess(false);
+
+ try {
+ DriverManager.setLogStream(testPrintStream);
+ fail("Should throw SecurityException.");
+ } catch (SecurityException s) {
+ //expected
+ }
+
+ theSecManager.setLogAccess(true);
+
+ DriverManager.setLogStream(testPrintStream);
+
+ System.setSecurityManager(null);
+ } // end method testSetLogStream()
+
+ static ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ static PrintWriter testPrintWriter = new PrintWriter(outputStream);
+
+ /**
+ * Test for the setLogWriter method
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setLogWriter",
+ args = {java.io.PrintWriter.class}
+ )
+ public void testSetLogWriter() {
+ // System.out.println("testSetLogWriter");
+ DriverManager.setLogWriter(testPrintWriter);
+
+ assertSame(testPrintWriter, DriverManager.getLogWriter());
+
+ DriverManager.setLogWriter(null);
+
+ assertNull("testDriverManager: Log writer not null:", DriverManager
+ .getLogWriter());
+
+ // Now let's deal with the case where there is a SecurityManager in
+ // place
+ TestSecurityManager theSecManager = new TestSecurityManager();
+ System.setSecurityManager(theSecManager);
+
+ theSecManager.setLogAccess(false);
+
+ try {
+ DriverManager.setLogWriter(testPrintWriter);
+ fail("Should throw SecurityException.");
+ } catch (SecurityException s) {
+ //expected
+ }
+
+ theSecManager.setLogAccess(true);
+ DriverManager.setLogWriter(testPrintWriter);
+
+ System.setSecurityManager(null);
+ } // end method testSetLogWriter()
+
+ /*
+ * Method which loads a set of JDBC drivers ready for use by the various
+ * tests @return the number of drivers loaded
+ */
+ static boolean driversLoaded = false;
+
+ private static int loadDrivers() {
+ if (driversLoaded) {
+ return numberLoaded;
+ }
+ /*
+ * First define a value for the System property "jdbc.drivers" - before
+ * the DriverManager class is loaded - this property defines a set of
+ * drivers which the DriverManager will load during its initialization
+ * and which will be loaded on the System ClassLoader - unlike the ones
+ * loaded later by this method which are loaded on the Application
+ * ClassLoader.
+ */
+ int numberLoaded = 0;
+ String theSystemDrivers = DRIVER4 + ":" + DRIVER5 + ":"
+ + INVALIDDRIVER1;
+ System.setProperty(JDBC_PROPERTY, theSystemDrivers);
+ numberLoaded += 2;
+
+ for (String element : driverNames) {
+ try {
+ Class> driverClass = Class.forName(element);
+ assertNotNull(driverClass);
+ // System.out.println("Loaded driver - classloader = " +
+ // driverClass.getClassLoader());
+ numberLoaded++;
+ } catch (ClassNotFoundException e) {
+ System.out.println("DriverManagerTest: failed to load Driver: "
+ + element);
+ } // end try
+ } // end for
+ /*
+ * System.out.println("DriverManagerTest: number of drivers loaded: " +
+ * numberLoaded);
+ */
+ driversLoaded = true;
+ return numberLoaded;
+ } // end method loadDrivers()
+
+ class TestSecurityManager extends SecurityManager {
+
+ boolean logAccess = true;
+
+ SQLPermission sqlPermission = new SQLPermission("setLog");
+
+ RuntimePermission setManagerPermission = new RuntimePermission(
+ "setSecurityManager");
+
+ TestSecurityManager() {
+ super();
+ } // end method TestSecurityManager()
+
+ void setLogAccess(boolean allow) {
+ logAccess = allow;
+ } // end method setLogAccess( boolean )
+
+ @Override
+ public void checkPermission(Permission thePermission) {
+ if (thePermission.equals(sqlPermission)) {
+ if (!logAccess) {
+ throw new SecurityException("Cannot set the sql Log Writer");
+ } // end if
+ return;
+ } // end if
+
+ if (thePermission.equals(setManagerPermission)) {
+ return;
+ } // end if
+ // super.checkPermission( thePermission );
+ } // end method checkPermission( Permission )
+
+ } // end class TestSecurityManager
+
+} // end class DriverManagerTest
+
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverPropertyInfoTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverPropertyInfoTest.java
new file mode 100644
index 0000000..e442987
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverPropertyInfoTest.java
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import SQLite.JDBCDriver;
+import dalvik.annotation.BrokenTest;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.util.Arrays;
+import java.util.Properties;
+
+import junit.framework.TestCase;
+@TestTargetClass(DriverPropertyInfo.class)
+/**
+ * JUnit Testcase for the java.sql.DriverPropertyInfo class
+ *
+ */
+
+public class DriverPropertyInfoTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ @TestTargetNew(
+ level = TestLevel.ADDITIONAL,
+ notes = "Empty test",
+ method = "!",
+ args = {}
+ )
+ @BrokenTest("empty")
+ public void testPublicStatics() {
+
+ } // end method testPublicStatics
+
+ /*
+ * Constructor test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Verification with invalid parameters missed: no feasible behaviour not specified (black box approach).",
+ method = "DriverPropertyInfo",
+ args = {java.lang.String.class, java.lang.String.class}
+ )
+ public void testDriverPropertyInfoStringString() {
+
+ DriverPropertyInfo aDriverPropertyInfo = new DriverPropertyInfo(
+ validName, validValue);
+
+ assertNotNull(aDriverPropertyInfo);
+
+ assertEquals(aDriverPropertyInfo.name,validName);
+ assertEquals(aDriverPropertyInfo.value,validValue);
+
+ aDriverPropertyInfo = new DriverPropertyInfo(null, null);
+
+ assertNotNull(aDriverPropertyInfo);
+ assertNull(aDriverPropertyInfo.name);
+ assertNull(aDriverPropertyInfo.value);
+
+ } // end method testDriverPropertyInfoStringString
+
+ /*
+ * Public fields test
+ */
+ static String validName = "testname";
+
+ static String validValue = "testvalue";
+
+ static String[] updateChoices = { "Choice1", "Choice2", "Choice3" };
+
+ static String updateValue = "updateValue";
+
+ static boolean updateRequired = true;
+
+ static String updateDescription = "update description";
+
+ static String updateName = "updateName";
+
+ String connectionURL = "jdbc:sqlite:/" + "Test.db";
+
+ String classname = "SQLite.JDBCDriver";
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testPublicFields() {
+
+ // Constructor here...
+ DriverPropertyInfo aDriverPropertyInfo = new DriverPropertyInfo(
+ validName, validValue);
+
+ assertTrue(Arrays.equals(testChoices, aDriverPropertyInfo.choices));
+ assertEquals(testValue, aDriverPropertyInfo.value);
+ assertEquals(testRequired, aDriverPropertyInfo.required);
+ assertEquals(testDescription, aDriverPropertyInfo.description);
+ assertEquals(testName, aDriverPropertyInfo.name);
+
+ aDriverPropertyInfo.choices = updateChoices;
+ aDriverPropertyInfo.value = updateValue;
+ aDriverPropertyInfo.required = updateRequired;
+ aDriverPropertyInfo.description = updateDescription;
+ aDriverPropertyInfo.name = updateName;
+
+ assertTrue(Arrays.equals(updateChoices, aDriverPropertyInfo.choices));
+ assertEquals(updateValue, aDriverPropertyInfo.value);
+ assertEquals(updateRequired, aDriverPropertyInfo.required);
+ assertEquals(updateDescription, aDriverPropertyInfo.description);
+ assertEquals(updateName, aDriverPropertyInfo.name);
+
+ //functional test
+ try {
+ Class.forName(classname).newInstance();
+ Properties props = new Properties();
+ Driver d = DriverManager.getDriver(connectionURL);
+ DriverPropertyInfo[] info = d.getPropertyInfo(connectionURL,
+ props);
+ // get the property metadata
+ String name = info[0].name;
+ assertNotNull(name);
+ assertEquals(name, "encoding");
+ String[] choices = info[0].choices;
+ assertNull(choices);
+ boolean required = info[0].required;
+ assertFalse(required);
+ String description = info[0].description;
+ assertNull(description);
+
+ } catch (SQLException e) {
+ System.out.println("Error in test setup: " + e.getMessage());
+ e.printStackTrace();
+ } catch (Exception ex) {
+ System.err.println("Unexpected exception " + ex.toString());
+ }
+
+
+ } // end method testPublicFields
+
+ // Default values...
+ static String[] testChoices = null;
+
+ static java.lang.String testValue = validValue;
+
+ static boolean testRequired = false;
+
+ static java.lang.String testDescription = null;
+
+ static java.lang.String testName = validName;
+
+} // end class DriverPropertyInfoTest
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ParameterMetaDataTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ParameterMetaDataTest.java
new file mode 100644
index 0000000..b488880
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ParameterMetaDataTest.java
@@ -0,0 +1,106 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(java.sql.ParameterMetaData.class)
+public class ParameterMetaDataTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testPublicStatics() {
+
+ HashMap thePublicStatics = new HashMap();
+ thePublicStatics.put("parameterModeOut", new Integer(4));
+ thePublicStatics.put("parameterModeInOut", new Integer(2));
+ thePublicStatics.put("parameterModeIn", new Integer(1));
+ thePublicStatics.put("parameterModeUnknown", new Integer(0));
+ thePublicStatics.put("parameterNullableUnknown", new Integer(2));
+ thePublicStatics.put("parameterNullable", new Integer(1));
+ thePublicStatics.put("parameterNoNulls", new Integer(0));
+
+ /*
+ * System.out.println( "parameterModeOut: " +
+ * ParameterMetaData.parameterModeOut ); System.out.println(
+ * "parameterModeInOut: " + ParameterMetaData.parameterModeInOut );
+ * System.out.println( "parameterModeIn: " +
+ * ParameterMetaData.parameterModeIn ); System.out.println(
+ * "parameterModeUnknown: " + ParameterMetaData.parameterModeUnknown );
+ * System.out.println( "parameterNullableUnknown: " +
+ * ParameterMetaData.parameterNullableUnknown ); System.out.println(
+ * "parameterNullable: " + ParameterMetaData.parameterNullable );
+ * System.out.println( "parameterNoNulls: " +
+ * ParameterMetaData.parameterNoNulls );
+ */
+
+ Class> parameterMetaDataClass;
+ try {
+ parameterMetaDataClass = Class
+ .forName("java.sql.ParameterMetaData");
+ } catch (ClassNotFoundException e) {
+ fail("java.sql.ParameterMetaData class not found!");
+ return;
+ } // end try
+
+ Field[] theFields = parameterMetaDataClass.getDeclaredFields();
+ int requiredModifier = Modifier.PUBLIC + Modifier.STATIC
+ + Modifier.FINAL;
+
+ int countPublicStatics = 0;
+ for (Field element : theFields) {
+ String fieldName = element.getName();
+ int theMods = element.getModifiers();
+ if (Modifier.isPublic(theMods) && Modifier.isStatic(theMods)) {
+ try {
+ Object fieldValue = element.get(null);
+ Object expectedValue = thePublicStatics.get(fieldName);
+ if (expectedValue == null) {
+ fail("Field " + fieldName + " missing!");
+ } // end
+ assertEquals("Field " + fieldName + " value mismatch: ",
+ expectedValue, fieldValue);
+ assertEquals("Field " + fieldName + " modifier mismatch: ",
+ requiredModifier, theMods);
+ countPublicStatics++;
+ } catch (IllegalAccessException e) {
+ fail("Illegal access to Field " + fieldName);
+ } // end try
+ } // end if
+ } // end for
+
+ } // end method testPublicStatics
+
+} // end class ParameterMetaDataTest
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetMetaDataTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetMetaDataTest.java
new file mode 100644
index 0000000..dc28c4c
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetMetaDataTest.java
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(java.sql.ResultSetMetaData.class)
+public class ResultSetMetaDataTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testPublicStatics() {
+
+ HashMap thePublicStatics = new HashMap();
+ thePublicStatics.put("columnNullableUnknown", new Integer(2));
+ thePublicStatics.put("columnNullable", new Integer(1));
+ thePublicStatics.put("columnNoNulls", new Integer(0));
+
+ /*
+ * System.out.println( "columnNullableUnknown: " +
+ * ResultSetMetaData.columnNullableUnknown ); System.out.println(
+ * "columnNullable: " + ResultSetMetaData.columnNullable );
+ * System.out.println( "columnNoNulls: " +
+ * ResultSetMetaData.columnNoNulls );
+ */
+
+ Class> resultSetMetaDataClass;
+ try {
+ resultSetMetaDataClass = Class
+ .forName("java.sql.ResultSetMetaData");
+ } catch (ClassNotFoundException e) {
+ fail("java.sql.ResultSetMetaData class not found!");
+ return;
+ } // end try
+
+ Field[] theFields = resultSetMetaDataClass.getDeclaredFields();
+ int requiredModifier = Modifier.PUBLIC + Modifier.STATIC
+ + Modifier.FINAL;
+
+ int countPublicStatics = 0;
+ for (Field element : theFields) {
+ String fieldName = element.getName();
+ int theMods = element.getModifiers();
+ if (Modifier.isPublic(theMods) && Modifier.isStatic(theMods)) {
+ try {
+ Object fieldValue = element.get(null);
+ Object expectedValue = thePublicStatics.get(fieldName);
+ if (expectedValue == null) {
+ fail("Field " + fieldName + " missing!");
+ } // end
+ assertEquals("Field " + fieldName + " value mismatch: ",
+ expectedValue, fieldValue);
+ assertEquals("Field " + fieldName + " modifier mismatch: ",
+ requiredModifier, theMods);
+ countPublicStatics++;
+ } catch (IllegalAccessException e) {
+ fail("Illegal access to Field " + fieldName);
+ } // end try
+ } // end if
+ } // end for
+
+ } // end method testPublicStatics
+
+} // end class ResultSetMetaDataTest
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetTest.java
new file mode 100644
index 0000000..bd9b18f
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(java.sql.ResultSet.class)
+public class ResultSetTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testPublicStatics() {
+
+ HashMap thePublicStatics = new HashMap();
+ thePublicStatics.put("CLOSE_CURSORS_AT_COMMIT",
+ new java.lang.Integer(2));
+ thePublicStatics.put("HOLD_CURSORS_OVER_COMMIT", new java.lang.Integer(
+ 1));
+ thePublicStatics.put("CONCUR_UPDATABLE", new java.lang.Integer(1008));
+ thePublicStatics.put("CONCUR_READ_ONLY", new java.lang.Integer(1007));
+ thePublicStatics.put("TYPE_SCROLL_SENSITIVE", new java.lang.Integer(
+ 1005));
+ thePublicStatics.put("TYPE_SCROLL_INSENSITIVE", new java.lang.Integer(
+ 1004));
+ thePublicStatics.put("TYPE_FORWARD_ONLY", new java.lang.Integer(1003));
+ thePublicStatics.put("FETCH_UNKNOWN", new java.lang.Integer(1002));
+ thePublicStatics.put("FETCH_REVERSE", new java.lang.Integer(1001));
+ thePublicStatics.put("FETCH_FORWARD", new java.lang.Integer(1000));
+
+ /*
+ * System.out.println( "CLOSE_CURSORS_AT_COMMIT: " +
+ * ResultSet.CLOSE_CURSORS_AT_COMMIT ); System.out.println(
+ * "HOLD_CURSORS_OVER_COMMIT: " + ResultSet.HOLD_CURSORS_OVER_COMMIT );
+ * System.out.println( "CONCUR_UPDATABLE: " + ResultSet.CONCUR_UPDATABLE );
+ * System.out.println( "CONCUR_READ_ONLY: " + ResultSet.CONCUR_READ_ONLY );
+ * System.out.println( "TYPE_SCROLL_SENSITIVE: " +
+ * ResultSet.TYPE_SCROLL_SENSITIVE ); System.out.println(
+ * "TYPE_SCROLL_INSENSITIVE: " + ResultSet.TYPE_SCROLL_INSENSITIVE );
+ * System.out.println( "TYPE_FORWARD_ONLY: " +
+ * ResultSet.TYPE_FORWARD_ONLY ); System.out.println( "FETCH_UNKNOWN: " +
+ * ResultSet.FETCH_UNKNOWN ); System.out.println( "FETCH_REVERSE: " +
+ * ResultSet.FETCH_REVERSE ); System.out.println( "FETCH_FORWARD: " +
+ * ResultSet.FETCH_FORWARD );
+ */
+
+ Class> resultSetClass;
+ try {
+ resultSetClass = Class.forName("java.sql.ResultSet");
+ } catch (ClassNotFoundException e) {
+ fail("java.sql.ResultSet class not found!");
+ return;
+ } // end try
+
+ Field[] theFields = resultSetClass.getDeclaredFields();
+ int requiredModifier = Modifier.PUBLIC + Modifier.STATIC
+ + Modifier.FINAL;
+
+ int countPublicStatics = 0;
+ for (Field element : theFields) {
+ String fieldName = element.getName();
+ int theMods = element.getModifiers();
+ if (Modifier.isPublic(theMods) && Modifier.isStatic(theMods)) {
+ try {
+ Object fieldValue = element.get(null);
+ Object expectedValue = thePublicStatics.get(fieldName);
+ if (expectedValue == null) {
+ fail("Field " + fieldName + " missing!");
+ } // end
+ assertEquals("Field " + fieldName + " value mismatch: ",
+ expectedValue, fieldValue);
+ assertEquals("Field " + fieldName + " modifier mismatch: ",
+ requiredModifier, theMods);
+ countPublicStatics++;
+ } catch (IllegalAccessException e) {
+ fail("Illegal access to Field " + fieldName);
+ } // end try
+ } // end if
+ } // end for
+
+ } // end method testPublicStatics
+
+} // end class ResultSetTest
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.java
new file mode 100644
index 0000000..53a8a71
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.java
@@ -0,0 +1,619 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.sql.SQLException;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+import junit.framework.Assert;
+import junit.framework.TestCase;
+
+@TestTargetClass(SQLException.class)
+public class SQLExceptionTest extends TestCase {
+
+ static long theFixedSUID = 2135244094396331484L;
+
+ /*
+ * SUID test
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testSUID() {
+
+ try {
+ Class> theClass = Class.forName("java.sql.SQLException");
+ Field theField = theClass.getDeclaredField("serialVersionUID");
+ theField.setAccessible(true);
+ long theSUID = theField.getLong(null);
+ assertEquals("SUID mismatch: ", theFixedSUID, theSUID);
+ } catch (Exception e) {
+ System.out.println("SUID check got exception: " + e.getMessage());
+ // assertTrue("Exception while testing SUID ", false );
+ } // end catch
+
+ } // end method testSUID
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "SQLException",
+ args = {java.lang.String.class, java.lang.String.class, int.class}
+ )
+ public void testSQLExceptionStringStringint() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", "1", "a",
+ null, "", "\u0000", "a", "a", "a" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", "a",
+ "&valid*", "a", "a", "a", null, "", "\u0000" };
+ int[] init3 = { -2147483648, 2147483647, 0, 48429456, 1770127344,
+ 1047282235, -545472907, -2147483648, -2147483648, -2147483648,
+ -2147483648, -2147483648, -2147483648 };
+
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = init2;
+ int[] theFinalStates3 = init3;
+ SQLException[] theFinalStates4 = { null, null, null, null, null, null,
+ null, null, null, null, null, null, null };
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null, null, null, null, null, null };
+
+ SQLException aSQLException;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLException = new SQLException(init1[i], init2[i], init3[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getNextException(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSQLExceptionStringStringint
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "SQLException",
+ args = {java.lang.String.class, java.lang.String.class}
+ )
+ public void testSQLExceptionStringString() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", null, "",
+ "\u0000", "a", "a", "a" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", "a", "a",
+ "a", null, "", "\u0000" };
+
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = init2;
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0 };
+ SQLException[] theFinalStates4 = { null, null, null, null, null, null,
+ null, null, null, null, null };
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null, null, null, null };
+
+ SQLException aSQLException;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLException = new SQLException(init1[i], init2[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getNextException(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSQLExceptionStringString
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "SQLException",
+ args = {java.lang.String.class}
+ )
+ public void testSQLExceptionString() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", null,
+ "", "\u0000" };
+
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = { null, null, null, null, null, null, null,
+ null };
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0,
+ 0, 0, 0 };
+ SQLException[] theFinalStates4 = { null, null, null, null, null, null,
+ null, null };
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null };
+
+ SQLException aSQLException;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLException = new SQLException(init1[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getNextException(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSQLExceptionString
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "SQLException",
+ args = {}
+ )
+ public void testSQLException() {
+
+ String[] theFinalStates1 = { null };
+ String[] theFinalStates2 = { null };
+ int[] theFinalStates3 = { 0 };
+ SQLException[] theFinalStates4 = { null };
+
+ Exception[] theExceptions = { null };
+
+ SQLException aSQLException;
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLException = new SQLException();
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getNextException(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSQLException
+
+ /*
+ * Method test for getErrorCode
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getErrorCode",
+ args = {}
+ )
+ public void testGetErrorCode() {
+
+ SQLException aSQLException;
+ String[] init1 = { "a", "1", "valid1", "----", null, "&valid*", "1" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", null, "a" };
+ int[] init3 = { -2147483648, 2147483647, 0, 48429456, 1770127344,
+ 1047282235, -545472907 };
+
+ int theReturn;
+ int[] theReturns = init3;
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = init2;
+ int[] theFinalStates3 = init3;
+ SQLException[] theFinalStates4 = { null, null, null, null, null, null,
+ null };
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLException = new SQLException(init1[i], init2[i], init3[i]);
+ theReturn = aSQLException.getErrorCode();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getNextException(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetErrorCode
+
+ /*
+ * Method test for getNextException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getNextException",
+ args = {}
+ )
+ public void testGetNextException() {
+
+ SQLException aSQLException;
+ String[] init1 = { "a", "1", "valid1", "----", null, "&valid*", "1" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", null, "a" };
+ int[] init3 = { -2147483648, 2147483647, 0, 48429456, 1770127344,
+ 1047282235, -545472907 };
+ SQLException[] init4 = { new SQLException(), null, new SQLException(),
+ new SQLException(), new SQLException(), null,
+ new SQLException() };
+
+ SQLException theReturn;
+ SQLException[] theReturns = init4;
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = init2;
+ int[] theFinalStates3 = init3;
+ SQLException[] theFinalStates4 = init4;
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLException = new SQLException(init1[i], init2[i], init3[i]);
+ aSQLException.setNextException(init4[i]);
+ theReturn = aSQLException.getNextException();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getNextException(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetNextException
+
+ /*
+ * Method test for getSQLState
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getSQLState",
+ args = {}
+ )
+ public void testGetSQLState() {
+
+ SQLException aSQLException;
+ String[] init1 = { "a", "1", "valid1", "----", null, "&valid*", "1" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", null, "a" };
+ int[] init3 = { -2147483648, 2147483647, 0, 48429456, 1770127344,
+ 1047282235, -545472907 };
+
+ String theReturn;
+ String[] theReturns = init2;
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = init2;
+ int[] theFinalStates3 = init3;
+ SQLException[] theFinalStates4 = { null, null, null, null, null, null,
+ null };
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null };
+
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLException = new SQLException(init1[i], init2[i], init3[i]);
+ theReturn = aSQLException.getSQLState();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getNextException(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetSQLState
+
+ /*
+ * Method test for setNextException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "setNextException",
+ args = {java.sql.SQLException.class}
+ )
+ public void testSetNextExceptionSQLException() {
+
+ SQLException[] parm1 = { new SQLException(), null, new SQLException(),
+ new SQLException(), new SQLException(), null,
+ new SQLException() };
+
+ SQLException aSQLException;
+
+ String[] init1 = { "a", "1", "valid1", "----", null, "&valid*", "1" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", null, "a" };
+ int[] init3 = { -2147483648, 2147483647, 0, 48429456, 1770127344,
+ 1047282235, -545472907 };
+
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = init2;
+ int[] theFinalStates3 = init3;
+ SQLException[] theFinalStates4 = parm1;
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null, null, null, null };
+
+ int loopCount = parm1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLException = new SQLException(init1[i], init2[i], init3[i]);
+ aSQLException.setNextException(parm1[i]);
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLException
+ .getNextException(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSetNextExceptionSQLException
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Serialization test",
+ method = "!SerializationSelf",
+ args = {}
+ )
+ public void testSerializationSelf() throws Exception {
+ SQLException object = new SQLException();
+ SerializationTest.verifySelf(object, SQLEXCEPTION_COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Serialization test",
+ method = "!SerializationGolden",
+ args = {}
+ )
+ public void testSerializationCompatibility() throws Exception {
+
+ SQLException nextSQLException = new SQLException("nextReason",
+ "nextSQLState", 33);
+
+ int vendorCode = 10;
+ SQLException object = new SQLException("reason", "SQLState", vendorCode);
+
+ object.setNextException(nextSQLException);
+
+ SerializationTest.verifyGolden(this, object, SQLEXCEPTION_COMPARATOR);
+ }
+
+ // comparator for SQLException objects
+ private static final SerializableAssert SQLEXCEPTION_COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ deserialized);
+
+ SQLException initThr = (SQLException) initial;
+ SQLException dserThr = (SQLException) deserialized;
+
+ // verify SQLState
+ Assert.assertEquals("SQLState", initThr.getSQLState(), dserThr
+ .getSQLState());
+
+ // verify vendorCode
+ Assert.assertEquals("vendorCode", initThr.getErrorCode(), dserThr
+ .getErrorCode());
+
+ // verify next
+ if (initThr.getNextException() == null) {
+ assertNull(dserThr.getNextException());
+ } else {
+ // use the same comparator
+ SQLEXCEPTION_COMPARATOR.assertDeserialized(initThr
+ .getNextException(), dserThr.getNextException());
+ }
+ }
+ };
+
+ /**
+ * @tests java.sql.SQLException#setNextException(java.sql.SQLException)
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "setNextException",
+ args = {java.sql.SQLException.class}
+ )
+ public void test_setNextException_LSQLException() {
+ SQLException se1 = new SQLException("reason" , "SQLState" , 1);
+ SQLException se2 = new SQLException("reason" , "SQLState" , 2);
+ SQLException se3 = new SQLException("reason" , "SQLState" , 3);
+ SQLException se4 = new SQLException("reason" , "SQLState" , 4);
+
+ se1.setNextException(se2);
+ assertSame(se2, se1.getNextException());
+
+ se1.setNextException(se3);
+ assertSame(se2, se1.getNextException());
+ assertSame(se3, se2.getNextException());
+ assertNull(se3.getNextException());
+
+ se3.setNextException(null);
+ assertNull(se3.getNextException());
+
+ se3.setNextException(se4);
+ assertSame(se4, se3.getNextException());
+ }
+
+} // end class SQLExceptionTest
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLPermissionTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLPermissionTest.java
new file mode 100644
index 0000000..5122478
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLPermissionTest.java
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.SQLPermission;
+
+import junit.framework.TestCase;
+@TestTargetClass(SQLPermission.class)
+/**
+ * JUnit Testcase for the java.sql.SQLPermission class
+ *
+ * Note that the SQLPermission class only defines 2 constructors and all other
+ * methods are inherited. This testcase explicitly tets the constructors but also
+ * implicitly tests some of the inherited query methods.
+ *
+ */
+
+public class SQLPermissionTest extends TestCase {
+
+ /*
+ * Constructor test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "invalid parameters checking missed. not fully supported",
+ method = "SQLPermission",
+ args = {java.lang.String.class, java.lang.String.class}
+ )
+ public void testSQLPermissionStringString() {
+ String validName = "setLog";
+ String validActions = "theActions";
+
+ SQLPermission thePermission = new SQLPermission(validName, validActions);
+
+ assertNotNull(thePermission);
+ assertEquals(validName, thePermission.getName());
+ // System.out.println("The actions: " + thePermission.getActions() + "."
+ // );
+ assertEquals("", thePermission.getActions());
+ } // end method testSQLPermissionStringString
+
+ /*
+ * Constructor test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not fully supported",
+ method = "SQLPermission",
+ args = {java.lang.String.class}
+ )
+ public void testSQLPermissionString() {
+ String validName = "setLog";
+
+ SQLPermission thePermission = new SQLPermission(validName);
+
+ assertNotNull(thePermission);
+ assertEquals(validName, thePermission.getName());
+
+ // Set an invalid name ...
+ String invalidName = "foo";
+
+ thePermission = new SQLPermission(invalidName);
+
+ assertNotNull(thePermission);
+ assertEquals(invalidName, thePermission.getName());
+ assertEquals("", thePermission.getActions());
+ } // end method testSQLPermissionString
+
+} // end class SQLPermissionTest
+
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.java
new file mode 100644
index 0000000..2307f8e
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.java
@@ -0,0 +1,474 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.io.Serializable;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(SQLWarning.class)
+public class SQLWarningTest extends TestCase {
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "SQLWarning",
+ args = {}
+ )
+ public void testSQLWarning() {
+
+ String[] theFinalStates1 = { null };
+ String[] theFinalStates2 = { null };
+ int[] theFinalStates3 = { 0 };
+ SQLWarning[] theFinalStates4 = { null };
+
+ Exception[] theExceptions = { null };
+
+ SQLWarning aSQLWarning;
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLWarning = new SQLWarning();
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getNextWarning(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSQLWarning
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "SQLWarning",
+ args = {java.lang.String.class}
+ )
+ public void testSQLWarningString() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", null,
+ "", "\u0000" };
+
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = { null, null, null, null, null, null, null,
+ null };
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0, 0, 0, 0 };
+ SQLWarning[] theFinalStates4 = { null, null, null, null, null, null,
+ null, null };
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null };
+
+ SQLWarning aSQLWarning;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLWarning = new SQLWarning(init1[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getNextWarning(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSQLWarningString
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "SQLWarning",
+ args = {java.lang.String.class, java.lang.String.class}
+ )
+ public void testSQLWarningStringString() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", null, "",
+ "\u0000", "a", "a", "a" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", "a", "a",
+ "a", null, "", "\u0000" };
+
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = init2;
+ int[] theFinalStates3 = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
+ SQLWarning[] theFinalStates4 = { null, null, null, null, null, null,
+ null, null, null, null, null };
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null, null, null, null };
+
+ SQLWarning aSQLWarning;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLWarning = new SQLWarning(init1[i], init2[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getNextWarning(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSQLWarningStringString
+
+ /*
+ * ConstructorTest
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "SQLWarning",
+ args = {java.lang.String.class, java.lang.String.class, int.class}
+ )
+ public void testSQLWarningStringStringint() {
+
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*", "----",
+ "----", null, "", "\u0000", "a", "a", "a" };
+ String[] init2 = { "a", "1", "valid1", "----", "&valid*", "valid1",
+ "----", "a", "a", "a", null, "", "\u0000" };
+ int[] init3 = { -2147483648, 2147483647, 0, 1412862821, -733923487,
+ 488067774, -1529953616, -2147483648, -2147483648, -2147483648,
+ -2147483648, -2147483648, -2147483648 };
+
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = init2;
+ int[] theFinalStates3 = init3;
+ SQLWarning[] theFinalStates4 = { null, null, null, null, null, null,
+ null, null, null, null, null, null, null };
+
+ Exception[] theExceptions = { null, null, null, null, null, null, null,
+ null, null, null, null, null, null };
+
+ SQLWarning aSQLWarning;
+ int loopCount = init1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLWarning = new SQLWarning(init1[i], init2[i], init3[i]);
+ if (theExceptions[i] != null) {
+ fail();
+ }
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getNextWarning(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSQLWarningStringStringint
+
+ /*
+ * Method test for getNextWarning
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "getNextWarning",
+ args = {}
+ )
+ public void testGetNextWarning() {
+
+ SQLWarning aSQLWarning;
+ String[] init1 = { "a", "1", "valid1", "----", "&valid*" };
+
+ SQLWarning theReturn;
+ SQLWarning[] theReturns = { null };
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = { null };
+ int[] theFinalStates3 = { 0 };
+ SQLWarning[] theFinalStates4 = { null };
+
+ Exception[] theExceptions = { null };
+
+ int loopCount = 1;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLWarning = new SQLWarning(init1[i]);
+ theReturn = aSQLWarning.getNextWarning();
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + "Return value mismatch", theReturn,
+ theReturns[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getNextWarning(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testGetNextWarning
+
+ /*
+ * Method test for setNextWarning
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "setNextWarning",
+ args = {java.sql.SQLWarning.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "getNextWarning",
+ args = {}
+ )
+ })
+ public void testSetNextWarningSQLWarning() {
+
+ SQLWarning[] parm1 = { new SQLWarning(), null };
+
+ SQLWarning aSQLWarning;
+ String[] init1 = { "a", "1" };
+
+ String[] theFinalStates1 = init1;
+ String[] theFinalStates2 = { null, null };
+ int[] theFinalStates3 = { 0, 0 };
+ SQLWarning[] theFinalStates4 = parm1;
+
+ Exception[] theExceptions = { null, null };
+
+ int loopCount = parm1.length;
+ for (int i = 0; i < loopCount; i++) {
+ try {
+ aSQLWarning = new SQLWarning(init1[i]);
+ aSQLWarning.setNextWarning(parm1[i]);
+ if (theExceptions[i] != null) {
+ fail(i + "Exception missed");
+ }
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getMessage(), theFinalStates1[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getSQLState(), theFinalStates2[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getErrorCode(), theFinalStates3[i]);
+ assertEquals(i + " Final state mismatch", aSQLWarning
+ .getNextWarning(), theFinalStates4[i]);
+
+ } catch (Exception e) {
+ if (theExceptions[i] == null) {
+ fail(i + "Unexpected exception");
+ }
+ assertEquals(i + "Exception mismatch", e.getClass(),
+ theExceptions[i].getClass());
+ assertEquals(i + "Exception mismatch", e.getMessage(),
+ theExceptions[i].getMessage());
+ } // end try
+ } // end for
+
+ } // end method testSetNextWarningSQLWarning
+
+ /**
+ * @tests java.sql.SQLWarning#setNextWarning(java.sql.SQLWarning)
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "setNextWarning",
+ args = {java.sql.SQLWarning.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "getNextWarning",
+ args = {}
+ )
+ })
+ public void test_setNextWarning_SQLWarning() {
+ SQLWarning sw = new SQLWarning("reason", "SQLState", 0);
+ SQLWarning sw1 = new SQLWarning("reason", "SQLState", 1);
+ SQLWarning sw2 = new SQLWarning("reason", "SQLState", 2);
+ SQLWarning sw3 = new SQLWarning("reason", "SQLState", 3);
+
+ SQLException se = new SQLException("reason", "SQLState", 4);
+
+ sw.setNextWarning(sw1);
+ assertSame(sw1, sw.getNextException());
+ assertSame(sw1, sw.getNextWarning());
+
+
+ sw.setNextWarning(sw2);
+ assertSame(sw2, sw1.getNextException());
+ assertSame(sw2, sw1.getNextWarning());
+
+ sw.setNextException(sw3);
+ assertSame(sw3, sw2.getNextException());
+ assertSame(sw3, sw2.getNextWarning());
+
+ sw.setNextException(se);
+ assertSame(se, sw3.getNextException());
+ try {
+ sw3.getNextWarning();
+ fail("should throw Error");
+ } catch (Error e) {
+ //expected
+ }
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Serialization test",
+ method = "SQLWarning",
+ args = {}
+ )
+ public void testSerializationSelf() throws Exception {
+ SQLWarning object = new SQLWarning();
+ SerializationTest.verifySelf(object, SQLWARNING_COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Serialization test",
+ method = "SQLWarning",
+ args = {java.lang.String.class, java.lang.String.class, int.class}
+ )
+ public void testSerializationCompatibility() throws Exception {
+ SQLWarning object = new SQLWarning();
+
+ SQLWarning nextSQLWarning = new SQLWarning("nextReason",
+ "nextSQLState", 10);
+
+ object.setNextWarning(nextSQLWarning);
+
+ SerializationTest.verifyGolden(this, object, SQLWARNING_COMPARATOR);
+ }
+
+ // comparator for SQLWarning objects
+ private static final SerializableAssert SQLWARNING_COMPARATOR = new SerializableAssert() {
+ public void assertDeserialized(Serializable initial,
+ Serializable deserialized) {
+
+ // do common checks for all throwable objects
+ SerializationTest.THROWABLE_COMPARATOR.assertDeserialized(initial,
+ deserialized);
+
+ SQLWarning initThr = (SQLWarning) initial;
+ SQLWarning dserThr = (SQLWarning) deserialized;
+
+ // verify getNextWarning() method
+ if (initThr.getNextWarning() == null) {
+ assertNull(dserThr.getNextWarning());
+ } else {
+ // use the same comparator
+ SQLWARNING_COMPARATOR.assertDeserialized(initThr
+ .getNextWarning(), dserThr.getNextWarning());
+ }
+ }
+ };
+
+} // end class SQLWarningTest
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/StatementTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/StatementTest.java
new file mode 100644
index 0000000..fb3e550
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/StatementTest.java
@@ -0,0 +1,104 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(java.sql.Statement.class)
+public class StatementTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testPublicStatics() {
+
+ HashMap thePublicStatics = new HashMap();
+ thePublicStatics.put("NO_GENERATED_KEYS", new Integer(2));
+ thePublicStatics.put("RETURN_GENERATED_KEYS", new Integer(1));
+ thePublicStatics.put("EXECUTE_FAILED", new Integer(-3));
+ thePublicStatics.put("SUCCESS_NO_INFO", new Integer(-2));
+ thePublicStatics.put("CLOSE_ALL_RESULTS", new Integer(3));
+ thePublicStatics.put("KEEP_CURRENT_RESULT", new Integer(2));
+ thePublicStatics.put("CLOSE_CURRENT_RESULT", new Integer(1));
+
+ /*
+ * System.out.println( "NO_GENERATED_KEYS: " +
+ * Statement.NO_GENERATED_KEYS ); System.out.println(
+ * "RETURN_GENERATED_KEYS: " + Statement.RETURN_GENERATED_KEYS );
+ * System.out.println( "EXECUTE_FAILED: " + Statement.EXECUTE_FAILED );
+ * System.out.println( "SUCCESS_NO_INFO: " + Statement.SUCCESS_NO_INFO );
+ * System.out.println( "CLOSE_ALL_RESULTS: " +
+ * Statement.CLOSE_ALL_RESULTS ); System.out.println(
+ * "KEEP_CURRENT_RESULT: " + Statement.KEEP_CURRENT_RESULT );
+ * System.out.println( "CLOSE_CURRENT_RESULT: " +
+ * Statement.CLOSE_CURRENT_RESULT );
+ */
+
+ Class> statementClass;
+ try {
+ statementClass = Class.forName("java.sql.Statement");
+ } catch (ClassNotFoundException e) {
+ fail("java.sql.Statement class not found!");
+ return;
+ } // end try
+
+ Field[] theFields = statementClass.getDeclaredFields();
+ int requiredModifier = Modifier.PUBLIC + Modifier.STATIC
+ + Modifier.FINAL;
+
+ int countPublicStatics = 0;
+ for (Field element : theFields) {
+ String fieldName = element.getName();
+ int theMods = element.getModifiers();
+ if (Modifier.isPublic(theMods) && Modifier.isStatic(theMods)) {
+ try {
+ Object fieldValue = element.get(null);
+ Object expectedValue = thePublicStatics.get(fieldName);
+ if (expectedValue == null) {
+ fail("Field " + fieldName + " missing!");
+ } // end
+ assertEquals("Field " + fieldName + " value mismatch: ",
+ expectedValue, fieldValue);
+ assertEquals("Field " + fieldName + " modifier mismatch: ",
+ requiredModifier, theMods);
+ countPublicStatics++;
+ } catch (IllegalAccessException e) {
+ fail("Illegal access to Field " + fieldName);
+ } // end try
+ } // end if
+ } // end for
+
+ } // end method testPublicStatics
+
+} // end class StatementTest
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_ClassLoader.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_ClassLoader.java
new file mode 100644
index 0000000..940a3aa
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_ClassLoader.java
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+public class TestHelper_ClassLoader extends ClassLoader {
+
+ public TestHelper_ClassLoader() {
+ super(null);
+ }
+
+ /**
+ * Loads a class specified by its name
+ *
+ * This classloader makes the assumption that any class it is asked to load
+ * is in the current directory....
+ */
+ @Override
+ public Class> findClass(String className) throws ClassNotFoundException {
+ Class> theClass = null;
+
+ if (!className.equals("org.apache.harmony.sql.tests.java.sql.TestHelper_DriverManager")) {
+ return null;
+ }
+
+ String classNameAsFile = className.replace('.', '/') + ".class";
+ // System.out.println("findClass - class filename = " + classNameAsFile
+ // );
+
+ String classPath = System.getProperty("java.class.path");
+ // System.out.println("Test class loader - classpath = " + classPath );
+
+ String theSeparator = String.valueOf(File.pathSeparatorChar);
+ String[] theClassPaths = classPath.split(theSeparator);
+ for (int i = 0; (i < theClassPaths.length) && (theClass == null); i++) {
+ // Ignore jar files...
+ if (theClassPaths[i].endsWith(".jar")) {
+ theClass = loadClassFromJar(theClassPaths[i], className,
+ classNameAsFile);
+ } else {
+ theClass = loadClassFromFile(theClassPaths[i], className,
+ classNameAsFile);
+ } // end if
+ } // end for
+
+ return theClass;
+ } // end method findClass( String )
+
+ @Override
+ public Class> loadClass(String className) throws ClassNotFoundException {
+ // Allowed classes:
+ String[] disallowedClasses = { "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver1",
+ "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver2",
+ "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver4",
+ "org.apache.harmony.sql.tests.java.sql.TestHelper_Driver5" };
+
+ Class> theClass;
+
+ theClass = findLoadedClass(className);
+ if (theClass != null) {
+ return theClass;
+ }
+
+ theClass = this.findClass(className);
+
+ if (theClass == null) {
+ for (String element : disallowedClasses) {
+ if (element.equals(className)) {
+ return null;
+ } // end if
+ } // end for
+ theClass = Class.forName(className);
+ } // end if
+
+ return theClass;
+ } // end method loadClass( String )
+
+ private Class> loadClassFromFile(String pathName, String className,
+ String classNameAsFile) {
+ Class> theClass = null;
+ FileInputStream theInput = null;
+ File theFile = null;
+ try {
+ theFile = new File(pathName, classNameAsFile);
+ if (theFile.exists()) {
+ int length = (int) theFile.length();
+ theInput = new FileInputStream(theFile);
+ byte[] theBytes = new byte[length + 100];
+ int dataRead = 0;
+ while (dataRead < length) {
+ int count = theInput.read(theBytes, dataRead,
+ theBytes.length - dataRead);
+ if (count == -1) {
+ break;
+ }
+ dataRead += count;
+ }
+
+ if (dataRead > 0) {
+ // Create the class from the bytes read in...
+ theClass = this.defineClass(className, theBytes, 0, dataRead);
+ ClassLoader testClassLoader = theClass.getClassLoader();
+ if (testClassLoader != this) {
+ System.out.println("findClass - wrong classloader!!");
+ }
+ }
+ }
+ } catch (Exception e) {
+ System.out.println("findClass - exception reading class file.");
+ e.printStackTrace();
+ } finally {
+ try {
+ if (theInput != null) {
+ theInput.close();
+ }
+ } catch (Exception e) {
+ }
+ }
+ return theClass;
+ }
+
+ /*
+ * Loads a named class from a specified JAR file
+ */
+ private Class> loadClassFromJar(String jarfileName, String className,
+ String classNameAsFile) {
+ Class> theClass = null;
+
+ // First, try to open the Jar file
+ JarFile theJar = null;
+ try {
+ theJar = new JarFile(jarfileName);
+ JarEntry theEntry = theJar.getJarEntry(classNameAsFile);
+
+ if (theEntry == null) {
+ // System.out.println("TestHelper_Classloader - did not find
+ // class file in Jar " + jarfileName );
+ return theClass;
+ } // end if
+
+ theEntry.getMethod();
+ InputStream theStream = theJar.getInputStream(theEntry);
+
+ long size = theEntry.getSize();
+ if (size < 0) {
+ size = 100000;
+ }
+ byte[] theBytes = new byte[(int) size + 100];
+
+ int dataRead = 0;
+ while (dataRead < size) {
+ int count = theStream.read(theBytes, dataRead, theBytes.length
+ - dataRead);
+ if (count == -1) {
+ break;
+ }
+ dataRead += count;
+ } // end while
+
+ // System.out.println("loadClassFromJar: read " + dataRead + " bytes
+ // from class file");
+ if (dataRead > 0) {
+ // Create the class from the bytes read in...
+ theClass = this.defineClass(className, theBytes, 0, dataRead);
+ /* System.out.println("findClass: created Class object."); */
+ ClassLoader testClassLoader = theClass.getClassLoader();
+ if (testClassLoader != this) {
+ System.out.println("findClass - wrong classloader!!");
+ } else {
+ System.out
+ .println("Testclassloader loaded class from jar: "
+ + className);
+ } // end if
+ } // end if
+ } catch (IOException ie) {
+ System.out
+ .println("TestHelper_ClassLoader: IOException opening Jar "
+ + jarfileName);
+ } catch (Exception e) {
+ System.out
+ .println("TestHelper_ClassLoader: Exception loading class from Jar ");
+ } catch (ClassFormatError ce) {
+ System.out
+ .println("TestHelper_ClassLoader: ClassFormatException loading class from Jar ");
+ } finally {
+ try {
+ if (theJar != null) {
+ theJar.close();
+ }
+ } catch (Exception e) {
+ } // end try
+ } // end try
+
+ return theClass;
+ } // end method loadClassFromJar(
+
+} // end class TestHelper_ClassLoader
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Connection1.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Connection1.java
new file mode 100644
index 0000000..8b1fd60
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Connection1.java
@@ -0,0 +1,176 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.util.Map;
+
+/**
+ * Helper class for the java.sql tests - a skeleton class which implements the
+ * java.sql.Connection interface
+ *
+ */
+public class TestHelper_Connection1 implements Connection {
+ public void clearWarnings() throws SQLException {
+ }
+
+ public void close() throws SQLException {
+ }
+
+ public void commit() throws SQLException {
+ }
+
+ public Statement createStatement() throws SQLException {
+ return null;
+ }
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency,
+ int resultSetHoldability) throws SQLException {
+ return null;
+ }
+
+ public Statement createStatement(int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ return null;
+ }
+
+ public boolean getAutoCommit() throws SQLException {
+ return false;
+ }
+
+ public String getCatalog() throws SQLException {
+ return null;
+ }
+
+ public int getHoldability() throws SQLException {
+ return 0;
+ }
+
+ public DatabaseMetaData getMetaData() throws SQLException {
+ return null;
+ }
+
+ public int getTransactionIsolation() throws SQLException {
+ return 0;
+ }
+
+ public Map> getTypeMap() throws SQLException {
+ return null;
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return null;
+ }
+
+ public boolean isClosed() throws SQLException {
+ return false;
+ }
+
+ public boolean isReadOnly() throws SQLException {
+ return false;
+ }
+
+ public String nativeSQL(String sql) throws SQLException {
+ return null;
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ return null;
+ }
+
+ public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency)
+ throws SQLException {
+ return null;
+ }
+
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ return null;
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability) throws SQLException {
+ return null;
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException {
+ return null;
+ }
+
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException {
+ return null;
+ }
+
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+ throws SQLException {
+ return null;
+ }
+
+ public PreparedStatement prepareStatement(String sql, String[] columnNames)
+ throws SQLException {
+ return null;
+ }
+
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ return null;
+ }
+
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException {
+ }
+
+ public void rollback() throws SQLException {
+ }
+
+ public void rollback(Savepoint savepoint) throws SQLException {
+ }
+
+ public void setAutoCommit(boolean autoCommit) throws SQLException {
+ }
+
+ public void setCatalog(String catalog) throws SQLException {
+ }
+
+ public void setHoldability(int holdability) throws SQLException {
+ }
+
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ }
+
+ public Savepoint setSavepoint() throws SQLException {
+ return null;
+ }
+
+ public Savepoint setSavepoint(String name) throws SQLException {
+ return null;
+ }
+
+ public void setTransactionIsolation(int level) throws SQLException {
+ }
+
+ public void setTypeMap(Map> map) throws SQLException {
+ }
+}
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver1.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver1.java
new file mode 100644
index 0000000..ae09f94
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver1.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.util.Properties;
+
+/**
+ * A simple implementation of a class implementing a JDBC Driver, for use in the
+ * testing of the java.sql.DriverManager class
+ *
+ */
+public class TestHelper_Driver1 implements Driver {
+ int majorVersion = 1;
+
+ int minorVersion = 0;
+
+ String baseURL = "jdbc:mikes1";
+
+ String[] dataSources = { "data1", "data2", "data3" };
+
+ static Driver theDriver;
+ static {
+ theDriver = new TestHelper_Driver1();
+ try {
+ DriverManager.registerDriver(theDriver);
+ } catch (SQLException e) {
+ System.out.println("Failed to register driver!");
+ }
+ } // end static block initializer
+
+ protected TestHelper_Driver1() {
+ super();
+ } // end constructor TestHelper_Driver1()
+
+ public boolean acceptsURL(String url) throws SQLException {
+ // Check on the supplied String...
+ if (url == null) {
+ return false;
+ }
+ // Everything's fine if the quoted url starts with the base url for this
+ // driver
+ if (url.startsWith(baseURL)) {
+ return true;
+ }
+ return false;
+ } // end method acceptsURL
+
+ static String validuser = "theuser";
+
+ static String validpassword = "thepassword";
+
+ static String userProperty = "user";
+
+ static String passwordProperty = "password";
+
+ public Connection connect(String url, Properties info) throws SQLException {
+ // Does the URL have the right form?
+ if (this.acceptsURL(url)) {
+ // The datasource name is the remainder of the url after the ":"
+ String datasource = url.substring(baseURL.length() + 1);
+ for (String element : dataSources) {
+ if (datasource.equals(element)) {
+ /*
+ * Check for user and password, except for datasource =
+ * data1 which is set up not to require a user/password
+ * combination
+ */
+ // It all checks out - so return a connection
+ Connection connection = new TestHelper_Connection1();
+ return connection;
+ } // end if
+ } // end for
+ } // end if
+ return null;
+ } // end method connect(String, Properties)
+
+ public int getMajorVersion() {
+ return majorVersion;
+ } // end method getMajorVersion()
+
+ public int getMinorVersion() {
+ return minorVersion;
+ } // end method getMinorVersion()
+
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
+ throws SQLException {
+ DriverPropertyInfo[] theInfos = { new DriverPropertyInfo(userProperty, "*"),
+ new DriverPropertyInfo(passwordProperty, "*"), };
+ return theInfos;
+ }
+
+ public boolean jdbcCompliant() {
+ // Basic version here returns false
+ return false;
+ }
+}
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver2.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver2.java
new file mode 100644
index 0000000..6d495d6
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver2.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Basic JDBC driver implementation to help with tests
+ *
+ */
+public class TestHelper_Driver2 extends TestHelper_Driver1 {
+
+ static {
+ Driver theDriver = new TestHelper_Driver2();
+ /*
+ * System.out.println("Driver2 classloader: " +
+ * theDriver.getClass().getClassLoader() ); System.out.println("Driver2
+ * object is: " + theDriver );
+ */
+ try {
+ DriverManager.registerDriver(theDriver);
+ } catch (SQLException e) {
+ System.out.println("Failed to register driver!");
+ }
+ } // end static block initializer
+
+ protected TestHelper_Driver2() {
+ super();
+ baseURL = "jdbc:mikes2";
+ } // end constructor TestHelper_Driver1()
+
+} // end class TestHelper_Driver2
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver3.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver3.java
new file mode 100644
index 0000000..f02bdc3
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver3.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+
+/**
+ * TODO Type description
+ *
+ */
+public class TestHelper_Driver3 extends TestHelper_Driver1 {
+
+ /*
+ * This driver does NOT automatically register itself...
+ */
+
+ public TestHelper_Driver3() {
+ super();
+ baseURL = "jdbc:mikes3";
+ } // end constructor TestHelper_Driver1()
+
+} // end class TestHelper_Driver3
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver4.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver4.java
new file mode 100644
index 0000000..655436d
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver4.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+import java.util.Properties;
+
+/**
+ * Basic JDBC driver implementation to help with tests
+ *
+ */
+public class TestHelper_Driver4 implements Driver {
+ int majorVersion = 1;
+
+ int minorVersion = 0;
+
+ String baseURL;
+
+ String[] dataSources = { "data1", "data2", "data3" };
+ static {
+ Driver theDriver = new TestHelper_Driver4();
+ try {
+ DriverManager.registerDriver(theDriver);
+ } catch (SQLException e) {
+ System.out.println("Failed to register driver!");
+ }
+ } // end static block initializer
+
+ protected TestHelper_Driver4() {
+ super();
+ baseURL = "jdbc:mikes4";
+ } // end constructor TestHelper_Driver4()
+
+ public boolean acceptsURL(String url) throws SQLException {
+ // Check on the supplied String...
+ if (url == null) {
+ return false;
+ }
+ // Everything's fine if the quoted url starts with the base url for this
+ // driver
+ if (url.startsWith(baseURL)) {
+ return true;
+ }
+ return false;
+ } // end method acceptsURL
+
+ static String validuser = "theuser";
+
+ static String validpassword = "thepassword";
+
+ static String userProperty = "user";
+
+ static String passwordProperty = "password";
+
+ public Connection connect(String url, Properties info) throws SQLException {
+ // Does the URL have the right form?
+ if (this.acceptsURL(url)) {
+ // The datasource name is the remainder of the url after the ":"
+ String datasource = url.substring(baseURL.length() + 1);
+ for (String element : dataSources) {
+ if (datasource.equals(element)) {
+ /*
+ * Check for user and password, except for datasource =
+ * data1 which is set up not to require a user/password
+ * combination
+ */
+ if (datasource.equals("data1")) {
+ // do nothing...
+ } else {
+ if (info == null) {
+ throw new SQLException("Properties bundle is null");
+ }
+ String user = (String) info.get(userProperty);
+ String password = (String) info.get(passwordProperty);
+ if (user == null || password == null) {
+ throw new SQLException("Userid and/or password not supplied");
+ }
+ if (!user.equals(validuser) || !password.equals(validpassword)) {
+ throw new SQLException("Userid and/or password not valid");
+ } // end if
+ } // end if
+ // It all checks out - so return a connection
+ Connection connection = new TestHelper_Connection1();
+ return connection;
+ } // end if
+ } // end for
+ } // end if
+ return null;
+ } // end method connect(String, Properties)
+
+ public int getMajorVersion() {
+ return majorVersion;
+ } // end method getMajorVersion()
+
+ public int getMinorVersion() {
+ return minorVersion;
+ } // end method getMinorVersion()
+
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
+ throws SQLException {
+ DriverPropertyInfo[] theInfos = { new DriverPropertyInfo(userProperty, "*"),
+ new DriverPropertyInfo(passwordProperty, "*"), };
+ return theInfos;
+ }
+
+ public boolean jdbcCompliant() {
+ // Basic version here returns false
+ return false;
+ }
+}
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver5.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver5.java
new file mode 100644
index 0000000..b228466
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver5.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+/**
+ * Basic JDBC driver implementation to help with tests
+ *
+ */
+public class TestHelper_Driver5 extends TestHelper_Driver4 {
+
+ static {
+ Driver theDriver = new TestHelper_Driver5();
+ try {
+ DriverManager.registerDriver(theDriver);
+ } catch (SQLException e) {
+ System.out.println("Failed to register driver!");
+ }
+ } // end static block initializer
+
+ protected TestHelper_Driver5() {
+ super();
+ baseURL = "jdbc:mikes5";
+ } // end constructor TestHelper_Driver5()
+
+} // end class TestHelper_Driver5
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_DriverManager.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_DriverManager.java
new file mode 100644
index 0000000..773684e
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_DriverManager.java
@@ -0,0 +1,112 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.logging.Logger;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(DriverManager.class)
+/**
+ * Helper class for the Driver manager tes - it allows the test code to be
+ * loaded under a different classloader, necessary for testing the
+ * DeregisterDriver function of DriverManager
+ *
+ */
+public class TestHelper_DriverManager extends TestCase {
+
+ static Driver testDriver = null;
+
+ static TestHelper_DriverManager theHelper;
+
+ static {
+ theHelper = new TestHelper_DriverManager();
+ // theHelper.testDeregister();
+ } // end static
+
+ public TestHelper_DriverManager() {
+ super();
+ } // end constructor TestHelper_DriverManager()
+
+ public static void setDriver(Driver theDriver) {
+ testDriver = theDriver;
+ // Logger.global.info("TestHelper_DriverManager: Test Driver set!");
+
+ theHelper.checkDeregister();
+ } // end method setDriver( Driver )
+
+ public void checkDeregister() {
+
+ String baseURL = "jdbc:mikes1";
+
+ // Logger.global.info("Calling checkDeregister in TestHelper_DriverManager....");
+
+ Driver aDriver;
+
+ // Logger.global.info("checkDeregister classloader: this.getClass().getClassLoader()");
+
+ // Try to get a driver from the general pool... this should fail
+ try {
+ aDriver = DriverManager.getDriver(baseURL);
+ fail("testDeregisterDriver: Didn't get exception when getting valid driver from other classloader.");
+ } catch (SQLException e) {
+ // e.printStackTrace();
+ assertTrue(
+ "testDeregisterDriver: Got exception when getting valid driver from other classloader.",
+ true);
+ // return;
+ } // end try
+
+ // OK, now THIS driver was loaded by someone else....
+ aDriver = testDriver;
+
+ // printClassLoader( aDriver );
+
+ // Deregister this driver
+ try {
+ DriverManager.deregisterDriver(aDriver);
+ // We shouldn't get here - but if we do, we need to re-register the
+ // driver to
+ // prevent subsequent tests from failing due to inability to get to
+ // this driver...
+ DriverManager.registerDriver(aDriver);
+ fail("checkDeregisterDriver: Didn't get Security Exception deregistering invalid driver.");
+ } catch (SecurityException s) {
+ // This is the exception we should get...
+ // System.out.println("checkDeregisterDriver: got expected Security
+ // Exception");
+ } catch (Exception e) {
+ fail("checkDeregisterDriver: Got wrong exception type when deregistering invalid driver.");
+ } // end try
+
+ } // end method testDeRegister
+
+ static void printClassLoader(Object theObject) {
+ Class extends Object> theClass = theObject.getClass();
+ ClassLoader theClassLoader = theClass.getClassLoader();
+ System.out.println("ClassLoader is: " + theClassLoader.toString()
+ + " for object: " + theObject.toString());
+ } // end method printClassLoader( Object )
+
+} // end class TestHelper_DriverManager
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimeTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimeTest.java
new file mode 100644
index 0000000..d8451de
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimeTest.java
@@ -0,0 +1,389 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Time;
+import java.util.TimeZone;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(Time.class)
+/**
+ * JUnit Testcase for the java.sql.Time class
+ *
+ */
+public class TimeTest extends TestCase {
+
+ static long TIME_TEST1 = 38720000; // 10:45:20 GMT
+
+ static long TIME_TEST2 = 80279000; // 22:17:59 GMT
+
+ static long TIME_TEST3 = -38720000; // 13:14:40 GMT
+
+ static String STRING_TEST1 = "10:45:20";
+
+ static String STRING_TEST2 = "22:17:59";
+
+ static String STRING_TEST3 = "13:14:40";
+
+ static String STRING_INVALID1 = "ABCDEFGHI";
+
+ static String STRING_INVALID2 = "233104";
+
+ static String STRING_INVALID3 = "21-43-48";
+
+ static String STRING_OUTRANGE = "35:99:66";
+
+ static long[] TIME_ARRAY = { TIME_TEST1, TIME_TEST2, TIME_TEST3 };
+
+ static String[] STRING_GMT_ARRAY = { STRING_TEST1, STRING_TEST2,
+ STRING_TEST3 };
+
+ static String[] STRING_LA_ARRAY = { "02:45:20", "14:17:59", "05:14:40" };
+
+ static String[] STRING_JP_ARRAY = { "19:45:20", "07:17:59", "22:14:40" };
+
+ static String[] INVALID_STRINGS = { STRING_INVALID1, STRING_INVALID2,
+ STRING_INVALID3 };
+
+ // Timezones
+ static String TZ_LONDON = "GMT"; // GMT (!) PS London != GMT (?!?)
+
+ static String TZ_PACIFIC = "America/Los_Angeles"; // GMT - 8
+
+ static String TZ_JAPAN = "Asia/Tokyo"; // GMT + 9
+
+ static String[] TIMEZONES = { TZ_LONDON, TZ_PACIFIC, TZ_JAPAN };
+
+ static String[][] STRING_ARRAYS = { STRING_GMT_ARRAY, STRING_LA_ARRAY,
+ STRING_JP_ARRAY };
+
+ @SuppressWarnings("deprecation")
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Deprecated method",
+ method = "Time",
+ args = {int.class, int.class, int.class}
+ )
+ public void testTimeintintint() {
+ Time theTime = new Time(10, 45, 20);
+
+ // The date should have been created
+ assertNotNull(theTime);
+ } // end method testTimeintintint()
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Incorrect parameter checking missed",
+ method = "Time",
+ args = {long.class}
+ )
+ public void testTime() {
+ Time theTime = new Time(TIME_TEST1);
+
+ // The date should have been created
+ assertNotNull(theTime);
+ assertTrue(theTime.toString().contains("10:45:20"));
+ } // end method testTime()
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "toString",
+ args = {}
+ )
+ public void testToString() {
+ // Loop through the timezones testing the String conversion for each
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ testToString(TIMEZONES[i], TIME_ARRAY, STRING_ARRAYS[i]);
+ } // end for
+
+ } // end method test
+
+ private void testToString(String timeZone, long[] theTimes,
+ String[] theTimeStrings) {
+ // Set the timezone
+ TimeZone.setDefault(TimeZone.getTimeZone(timeZone));
+
+ for (int i = 0; i < theTimes.length; i++) {
+ // Create the Time object
+ Time theTime = new Time(theTimes[i]);
+ // Convert to a time string ... and compare
+ String JDBCString = theTime.toString();
+ assertEquals(theTimeStrings[i], JDBCString);
+ } // end for
+
+ } // end testToString( String, long[], String[] )
+
+ /*
+ * Method test for valueOf
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "valueOf",
+ args = {java.lang.String.class}
+ )
+ public void testValueOfString() {
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
+
+ Time[] theReturns = { new Time(38720000), new Time(80279000),
+ new Time(47680000)};
+ String[] validTime = { "10:45:20", "22:17:59", "13:14:40", };
+ String[] invalidTime = { null, "ABCDEFGHI", "233104", "21-43-48" };
+
+ for (int i = 0; i < validTime.length; i++) {
+ Time theReturn = Time.valueOf(validTime[i]);
+ assertEquals(theReturns[i], theReturn);
+ } // end for
+
+ for (String element : invalidTime) {
+ try {
+ Time.valueOf(element);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+ }
+
+ } // end method testValueOfString
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setTime",
+ args = {long.class}
+ )
+ public void testSetTime() {
+ // Ensure that the timezone is set to GMT
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
+ Time theTime = new Time(TIME_TEST1);
+ assertEquals(STRING_TEST1, theTime.toString());
+
+ theTime.setTime(TIME_TEST2);
+ assertEquals(STRING_TEST2, theTime.toString());
+ } // end method testSetTime()
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setDate",
+ args = {int.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testSetDate() {
+ Time theTime = new Time(TIME_TEST1);
+
+ try {
+ theTime.setDate(10);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+ } // end method testSetDate()
+
+ @SuppressWarnings("deprecation")
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setMonth",
+ args = {int.class}
+ )
+ public void testSetMonth() {
+ Time theTime = new Time(TIME_TEST1);
+
+ try {
+ theTime.setMonth(2);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+ } // end method testSetMonth()
+
+ @SuppressWarnings("deprecation")
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setYear",
+ args = {int.class}
+ )
+ public void testSetYear() {
+ Time theTime = new Time(TIME_TEST1);
+
+ try {
+ theTime.setYear(99);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+ } // end method testSetYear()
+
+ @SuppressWarnings("deprecation")
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDate",
+ args = {}
+ )
+ public void testGetDate() {
+ Time theTime = new Time(TIME_TEST1);
+
+ try {
+ theTime.getDate();
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+ } // end method test
+
+ @SuppressWarnings("deprecation")
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDay",
+ args = {}
+ )
+ public void testGetDay() {
+ Time theTime = new Time(TIME_TEST1);
+
+ try {
+ theTime.getDay();
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+ } // end method test
+
+ @SuppressWarnings("deprecation")
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMonth",
+ args = {}
+ )
+ public void testGetMonth() {
+ Time theTime = new Time(TIME_TEST1);
+
+ try {
+ theTime.getMonth();
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+ } // end method test
+
+ @SuppressWarnings("deprecation")
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getYear",
+ args = {}
+ )
+ public void testGetYear() {
+ Time theTime = new Time(TIME_TEST1);
+
+ try {
+ theTime.getYear();
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+ } // end method test
+
+ /**
+ * @tests java.sql.Time#valueOf(String )
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "valueOf",
+ args = {java.lang.String.class}
+ )
+ public void test_valueOf_IllegalArgumentException() {
+ try{
+ Time.valueOf("15:43:12:34");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ //expected
+ }
+
+ try{
+ Time.valueOf(":10:07:01");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Time.valueOf("::01");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Time.valueOf("11::");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Time.valueOf(":01:");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Time.valueOf(":10:w2:01");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Time.valueOf("07:w2:");
+ fail("should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+
+ try{
+ Time.valueOf("17:w2:w2");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ //expected
+ }
+
+ try{
+ Time.valueOf("16::01");
+ fail("should throw NumberFormatException");
+ } catch (NumberFormatException e) {
+ //expected
+ }
+ }
+} // end class TimeTest
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java
new file mode 100644
index 0000000..cdbc63c
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java
@@ -0,0 +1,774 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Timestamp;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import junit.framework.TestCase;
+
+@TestTargetClass(Timestamp.class)
+/**
+ * JUnit Testcase for the java.sql.Timestamp class
+ *
+ */
+
+public class TimestampTest extends TestCase {
+
+ static long TIME_TEST1 = 38720231; // 10:45:20.231 GMT
+
+ static long TIME_TEST2 = 80279000; // 22:17:59.000 GMT
+
+ static long TIME_TEST3 = -38720691; // 13:14:39.309 GMT
+
+ static long TIME_COMPARE = 123498845;
+
+ static long TIME_EARLY = -2347889122L;// A time well before the Epoch
+
+ static long TIME_LATE = 2347889122L; // A time well after the Epoch
+
+ static String STRING_TEST1 = "1970-01-01 10:45:20.231"; // "1970-01-01
+ // 10:45:20.231000000";
+
+ static String STRING_TEST2 = "1970-01-01 22:17:59.0"; // "1970-01-01
+ // 22:17:59.000000000";
+
+ static String STRING_TEST3 = "1969-12-31 13:14:39.309"; // "1969-12-31
+ // 13:14:39.309000000";
+
+ static String STRING_INVALID1 = "ABCDEFGHI";
+
+ static String STRING_INVALID2 = "233104";
+
+ static String STRING_INVALID3 = "21-43-48";
+
+ // A timepoint in the correct format but with numeric values out of range
+ // ...this is accepted despite being a crazy date specification
+ // ...it is treated as the correct format date 3000-06-08 12:40:06.875 !!
+ static String STRING_OUTRANGE = "2999-15-99 35:99:66.875";
+
+ static long[] TIME_ARRAY = { TIME_TEST1, TIME_TEST2, TIME_TEST3 };
+
+ static int[] YEAR_ARRAY = { 70, 70, 69 };
+
+ static int[] MONTH_ARRAY = { 0, 0, 11 };
+
+ static int[] DATE_ARRAY = { 1, 1, 31 };
+
+ static int[] HOURS_ARRAY = { 10, 22, 13 };
+
+ static int[] MINUTES_ARRAY = { 45, 17, 14 };
+
+ static int[] SECONDS_ARRAY = { 20, 59, 39 };
+
+ static int[] NANOS_ARRAY = { 231000000, 000000000, 309000000 };
+
+ static int[] NANOS_ARRAY2 = { 137891990, 635665198, 109985421 };
+
+ static String[] STRING_NANOS_ARRAY = { "1970-01-01 10:45:20.13789199",
+ "1970-01-01 22:17:59.635665198", "1969-12-31 13:14:39.109985421" };
+
+ static String[] STRING_GMT_ARRAY = { STRING_TEST1, STRING_TEST2,
+ STRING_TEST3 };
+
+ static String[] STRING_LA_ARRAY = { "02:45:20", "14:17:59", "05:14:40" };
+
+ static String[] STRING_JP_ARRAY = { "19:45:20", "07:17:59", "22:14:40" };
+
+ static String[] INVALID_STRINGS = { STRING_INVALID1, STRING_INVALID2,
+ STRING_INVALID3 };
+
+ // Timezones
+ static String TZ_LONDON = "GMT"; // GMT (!) PS London != GMT (?!?)
+
+ static String TZ_PACIFIC = "America/Los_Angeles"; // GMT - 8
+
+ static String TZ_JAPAN = "Asia/Tokyo"; // GMT + 9
+
+ static String[] TIMEZONES = { TZ_LONDON, TZ_PACIFIC, TZ_JAPAN };
+
+ static String[][] STRING_ARRAYS = { STRING_GMT_ARRAY, STRING_LA_ARRAY,
+ STRING_JP_ARRAY };
+
+ /*
+ * Constructor test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Incorrect parameter checking missed",
+ method = "Timestamp",
+ args = {long.class}
+ )
+ public void testTimestamplong() {
+ Timestamp theTimestamp = new Timestamp(TIME_TEST1);
+
+ // The Timestamp should have been created
+ assertNotNull(theTimestamp);
+ } // end method testTimestamplong
+
+ /*
+ * Constructor test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "Timestamp",
+ args = {int.class, int.class, int.class, int.class, int.class, int.class, int.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testTimestampintintintintintintint() {
+ int[][] valid = { { 99, 2, 14, 17, 52, 3, 213577212 }, // 0 valid
+ { 0, 0, 1, 0, 0, 0, 0 }, // 1 valid
+ { 106, 11, 31, 23, 59, 59, 999999999 }, // 2 valid
+ { 106, 11, 31, 23, 59, 61, 999999999 }, // 5 Seconds out of
+ // range
+ { 106, 11, 31, 23, 59, -1, 999999999 }, // 6 Seconds out of
+ // range
+ { 106, 11, 31, 23, 61, 59, 999999999 }, // 7 Minutes out of
+ // range
+ { 106, 11, 31, 23, -1, 59, 999999999 }, // 8 Minutes out of
+ // range
+ { 106, 11, 31, 25, 59, 59, 999999999 }, // 9 Hours out of range
+ { 106, 11, 31, -1, 59, 59, 999999999 }, // 10 Hours out of range
+ { 106, 11, 35, 23, 59, 59, 999999999 }, // 11 Days out of range
+ { 106, 11, -1, 23, 59, 59, 999999999 }, // 12 Days out of range
+ { 106, 15, 31, 23, 59, 59, 999999999 }, // 13 Months out of
+ // range
+ { 106, -1, 31, 23, 59, 59, 999999999 }, // 14 Months out of
+ // range
+ { -10, 11, 31, 23, 59, 59, 999999999 }, // 15 valid - Years
+ // negative
+ };
+
+ for (int[] element : valid) {
+ Timestamp theTimestamp = new Timestamp(element[0],
+ element[1], element[2], element[3],
+ element[4], element[5], element[6]);
+ assertNotNull("Timestamp not generated: ", theTimestamp);
+ } // end for
+
+ int[][] invalid = {
+ { 106, 11, 31, 23, 59, 59, 1999999999 },
+ { 106, 11, 31, 23, 59, 59, -999999999 },
+ };
+ for (int[] element : invalid) {
+ try {
+ new Timestamp(element[0],
+ element[1], element[2], element[3],
+ element[4], element[5], element[6]);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ // expected
+ }
+ }
+
+ } // end method testTimestampintintintintintintint
+
+ /*
+ * Method test for setTime
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setTime",
+ args = {long.class}
+ )
+ public void testSetTimelong() {
+ // First set the timezone to GMT
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
+ Timestamp theTimestamp = new Timestamp(TIME_TEST1);
+
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ theTimestamp.setTime(TIME_ARRAY[i]);
+
+ assertEquals(TIME_ARRAY[i], theTimestamp.getTime());
+ assertEquals(NANOS_ARRAY[i], theTimestamp.getNanos());
+ } // end for
+
+ } // end method testsetTimelong
+
+ /*
+ * Method test for getTime
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getTime",
+ args = {}
+ )
+ public void testGetTime() {
+ // First set the timezone to GMT
+ TimeZone.setDefault(TimeZone.getTimeZone("GMT"));
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+ assertEquals(element, theTimestamp.getTime());
+ } // end for
+
+ } // end method testgetTime
+
+ /*
+ * Method test for getYear
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Deprecation",
+ method = "getYear",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetYear() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ assertEquals(YEAR_ARRAY[i], theTimestamp.getYear());
+ } // end for
+
+ } // end method testgetYear
+
+ /*
+ * Method test for getMonth
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Deprecation",
+ method = "getMonth",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetMonth() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ assertEquals(MONTH_ARRAY[i], theTimestamp.getMonth());
+ } // end for
+
+ } // end method testgetMonth
+
+ /*
+ * Method test for getDate
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Deprecation",
+ method = "getDate",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetDate() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ assertEquals(DATE_ARRAY[i], theTimestamp.getDate());
+ } // end for
+
+ } // end method testgetDate
+
+ /*
+ * Method test for getHours
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Deprecation",
+ method = "getHours",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetHours() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ assertEquals(HOURS_ARRAY[i], theTimestamp.getHours());
+ } // end for
+
+ } // end method testgetHours
+
+ /*
+ * Method test for getMinutes
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Deprecation",
+ method = "getMinutes",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetMinutes() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ assertEquals(MINUTES_ARRAY[i], theTimestamp.getMinutes());
+ } // end for
+
+ } // end method testgetMinutes
+
+ /*
+ * Method test for getSeconds
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Deprecation",
+ method = "getSeconds",
+ args = {}
+ )
+ @SuppressWarnings("deprecation")
+ public void testGetSeconds() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ assertEquals(SECONDS_ARRAY[i], theTimestamp.getSeconds());
+ } // end for
+
+ } // end method testgetSeconds
+
+ /*
+ * Method test for valueOf
+ */
+ static String theExceptionMessage = "Timestamp format must be yyyy-mm-dd hh:mm:ss.fffffffff";
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "valueOf",
+ args = {java.lang.String.class}
+ )
+ public void testValueOfString() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ Timestamp theTimestamp2 = Timestamp.valueOf(STRING_GMT_ARRAY[i]);
+ assertEquals(theTimestamp, theTimestamp2);
+ } // end for
+
+ // Test for a string in correct format but with number values out of
+ // range
+ Timestamp theTimestamp = Timestamp.valueOf(STRING_OUTRANGE);
+ assertNotNull(theTimestamp);
+ /*
+ * System.out.println("testValueOfString: outrange timestamp: " +
+ * theTimestamp.toString() );
+ */
+
+ for (String element : INVALID_STRINGS) {
+ try {
+ Timestamp.valueOf(element);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+
+ } // end for
+
+ } // end method testvalueOfString
+
+ /*
+ * Method test for valueOf
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "valueOf",
+ args = {java.lang.String.class}
+ )
+ public void testValueOfString1() {
+
+ Timestamp theReturn;
+ long[] theReturnTime = { 38720231, 38720231, 80279000, -38720691,
+ 38720000};
+ int[] theReturnNanos = { 231000000, 231987654, 0, 309000000, 0,};
+
+ String[] valid = {
+ "1970-01-01 10:45:20.231",
+ "1970-01-01 10:45:20.231987654",
+ "1970-01-01 22:17:59.0",
+ "1969-12-31 13:14:39.309",
+ "1970-01-01 10:45:20",
+ };
+ String[] invalid = {
+ null,
+ "ABCDEFGHI",
+ "233104", "1970-01-01 22:17:59.",
+ "1970-01-01 10:45:20.231987654690645322",
+ "1970-01-01 10:45:20&231987654",
+ "1970-01-01 10:45:20.-31987654",
+ "1970-01-01 10:45:20.ABCD87654",
+ "21-43-48",
+ };
+
+ for (int i = 0; i < valid.length; i++) {
+ theReturn = Timestamp.valueOf(valid[i]);
+ assertEquals(theReturnTime[i], theReturn.getTime());
+ assertEquals(theReturnNanos[i], theReturn.getNanos());
+ } // end for
+
+ for (String element : invalid) {
+ try {
+ theReturn = Timestamp.valueOf(element);
+ fail("Should throw IllegalArgumentException.");
+ } catch (IllegalArgumentException e) {
+ //expected
+ }
+ }
+
+ } // end method testValueOfString
+
+ /*
+ * Method test for toString
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "toString",
+ args = {}
+ )
+ public void testToString() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ assertEquals(STRING_GMT_ARRAY[i], theTimestamp.toString());
+ } // end for
+
+ } // end method testtoString
+
+ /*
+ * Method test for getNanos
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getNanos",
+ args = {}
+ )
+ public void testGetNanos() {
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ assertEquals(NANOS_ARRAY[i], theTimestamp.getNanos());
+ } // end for
+
+ } // end method testgetNanos
+
+ /*
+ * Method test for setNanos
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setNanos",
+ args = {int.class}
+ )
+ public void testSetNanosint() {
+ int[] NANOS_INVALID = { -137891990, 1635665198, -1 };
+ for (int i = 0; i < TIME_ARRAY.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+
+ theTimestamp.setNanos(NANOS_ARRAY2[i]);
+
+ assertEquals(NANOS_ARRAY2[i], theTimestamp.getNanos());
+ // Also check that these Timestamps with detailed nanos values
+ // convert to
+ // strings correctly
+ assertEquals(STRING_NANOS_ARRAY[i], theTimestamp.toString());
+ } // end for
+
+ for (int i = 0; i < NANOS_INVALID.length; i++) {
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[i]);
+ int originalNanos = theTimestamp.getNanos();
+ try {
+ theTimestamp.setNanos(NANOS_INVALID[i]);
+ fail("Should throw IllegalArgumentException");
+ } catch (IllegalArgumentException e) {
+ //expected
+ } // end try
+
+ assertEquals(originalNanos, theTimestamp.getNanos());
+ } // end for
+
+ } // end method testsetNanosint
+
+ /*
+ * Method test for equals
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "equals",
+ args = {java.sql.Timestamp.class}
+ )
+ public void testEqualsTimestamp() {
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+ Timestamp theTimestamp2 = new Timestamp(element);
+
+ assertTrue(theTimestamp.equals(theTimestamp2));
+ } // end for
+
+ Timestamp theTest = new Timestamp(TIME_COMPARE);
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+ assertFalse(theTimestamp.equals(theTest));
+ } // end for
+
+ // Regression for HARMONY-526
+ assertFalse(new Timestamp(0).equals((Timestamp) null));
+ } // end method testequalsTimestamp
+
+ /*
+ * Method test for equals
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "equals",
+ args = {java.lang.Object.class}
+ )
+ public void testEqualsObject() {
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+
+ Object theTimestamp2 = new Timestamp(element);
+
+ assertTrue(theTimestamp.equals(theTimestamp2));
+ } // end for
+
+ Object theTest = new Timestamp(TIME_COMPARE);
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+
+ assertFalse(theTimestamp.equals(theTest));
+ } // end for
+
+ Object nastyTest = new String("Test ");
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[1]);
+ assertFalse(theTimestamp.equals(nastyTest));
+
+ // Regression for HARMONY-526
+ assertFalse(new Timestamp(0).equals((Object) null));
+ } // end method testequalsObject
+
+ /*
+ * Method test for before
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "before",
+ args = {java.sql.Timestamp.class}
+ )
+ public void testBeforeTimestamp() {
+ Timestamp theTest = new Timestamp(TIME_LATE);
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+
+ assertTrue(theTimestamp.before(theTest));
+ } // end for
+
+ theTest = new Timestamp(TIME_EARLY);
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+
+ assertFalse(theTimestamp.before(theTest));
+ } // end for
+
+ for (long element : TIME_ARRAY) {
+ theTest = new Timestamp(element);
+ Timestamp theTimestamp = new Timestamp(element);
+
+ assertFalse(theTimestamp.before(theTest));
+ theTest.setNanos(theTest.getNanos() + 1);
+ assertTrue(theTimestamp.before(theTest));
+ } // end for
+
+ } // end method testbeforeTimestamp
+
+ /*
+ * Method test for after
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "after",
+ args = {java.sql.Timestamp.class}
+ )
+ public void testAfterTimestamp() {
+ Timestamp theTest = new Timestamp(TIME_LATE);
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+
+ assertFalse(theTimestamp.after(theTest));
+ } // end for
+
+ theTest = new Timestamp(TIME_EARLY);
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+
+ assertTrue(theTimestamp.after(theTest));
+ } // end for
+
+ for (long element : TIME_ARRAY) {
+ theTest = new Timestamp(element);
+ Timestamp theTimestamp = new Timestamp(element);
+
+ assertFalse(theTimestamp.after(theTest));
+ theTimestamp.setNanos(theTimestamp.getNanos() + 1);
+ assertTrue(theTimestamp.after(theTest));
+ } // end for
+
+ } // end method testafterTimestamp
+
+ /*
+ * Method test for compareTo
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "compareTo",
+ args = {java.sql.Timestamp.class}
+ )
+ @SuppressWarnings("deprecation")
+ public void testCompareToTimestamp() {
+ Timestamp theTest = new Timestamp(TIME_EARLY);
+ Timestamp theTest2 = new Timestamp(TIME_LATE);
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+ Timestamp theTimestamp2 = new Timestamp(element);
+
+ assertTrue(theTimestamp.compareTo(theTest) > 0);
+ assertTrue(theTimestamp.compareTo(theTest2) < 0);
+ assertEquals(0, theTimestamp.compareTo(theTimestamp2));
+ } // end for
+
+ Timestamp t1 = new Timestamp(-1L);
+ Timestamp t2 = new Timestamp(-1L);
+
+ t1.setTime(Long.MIN_VALUE);
+ t2.setDate(Integer.MIN_VALUE);
+ assertEquals(1, t1.compareTo(t2));
+ assertEquals(-1, t2.compareTo(t1));
+
+ t1.setTime(Long.MAX_VALUE);
+ t2.setTime(Long.MAX_VALUE - 1);
+ assertEquals(1, t1.compareTo(t2));
+ assertEquals(-1, t2.compareTo(t1));
+
+ t1.setTime(Integer.MAX_VALUE);
+ t2.setTime(Integer.MAX_VALUE);
+ assertEquals(0, t1.compareTo(t2));
+ assertEquals(0, t2.compareTo(t1));
+
+ } // end method testcompareToTimestamp
+
+ /**
+ * @tests java.sql.Timestamp#compareTo(java.util.Date)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "compareTo",
+ args = {java.util.Date.class}
+ )
+ public void testCompareToDate() {
+ Date theTest = new Timestamp(TIME_EARLY);
+ Date theTest2 = new Timestamp(TIME_LATE);
+
+ for (long element : TIME_ARRAY) {
+ Timestamp theTimestamp = new Timestamp(element);
+ Date theTimestamp2 = new Timestamp(element);
+
+ assertTrue(theTimestamp.compareTo(theTest) > 0);
+ assertTrue(theTimestamp.compareTo(theTest2) < 0);
+ assertEquals(0, theTimestamp.compareTo(theTimestamp2));
+ } // end for
+
+ Date nastyTest = new Date();
+ Timestamp theTimestamp = new Timestamp(TIME_ARRAY[1]);
+ try {
+ theTimestamp.compareTo(nastyTest);
+ // It throws ClassCastException in JDK 1.5.0_06 but in 1.5.0_07 it
+ // does not throw the expected exception.
+ fail("testCompareToObject: Did not get expected ClassCastException");
+ } catch (ClassCastException e) {
+ // Should get here
+ /*
+ * System.out.println("testCompareToObject: ClassCastException as
+ * expected"); System.out.println("Exception message: " +
+ * e.getMessage());
+ */
+ } // end try
+
+ } // end method testcompareToObject
+
+ /**
+ * @tests serialization/deserialization compatibility.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Serialization test",
+ method = "!SerializationSelf",
+ args = {}
+ )
+ public void testSerializationSelf() throws Exception {
+ Timestamp object = new Timestamp(100L);
+ SerializationTest.verifySelf(object);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Serialization test",
+ method = "!SerializationGolden",
+ args = {}
+ )
+ public void testSerializationCompatibility() throws Exception {
+ Timestamp object = new Timestamp(100L);
+ SerializationTest.verifyGolden(this, object);
+ }
+
+ /**
+ * @tests java.sql.Timestamp#toString()
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ method = "toString",
+ args = {}
+ )
+ public void test_toString() {
+
+ Timestamp t1 = new Timestamp(Long.MIN_VALUE);
+ assertEquals("292278994-08-17 07:12:55.192", t1.toString()); //$NON-NLS-1$
+
+ Timestamp t2 = new Timestamp(Long.MIN_VALUE + 1);
+ assertEquals("292278994-08-17 07:12:55.193", t2.toString()); //$NON-NLS-1$
+
+ Timestamp t3 = new Timestamp(Long.MIN_VALUE + 807);
+ assertEquals("292278994-08-17 07:12:55.999", t3.toString()); //$NON-NLS-1$
+
+ Timestamp t4 = new Timestamp(Long.MIN_VALUE + 808);
+ assertEquals("292269055-12-02 16:47:05.0", t4.toString()); //$NON-NLS-1$
+ }
+
+} // end class TimestampTest
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TypesTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TypesTest.java
new file mode 100644
index 0000000..948d95f
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TypesTest.java
@@ -0,0 +1,113 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(java.sql.Types.class)
+public class TypesTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Field testing",
+ method = "!Constants",
+ args = {}
+ )
+ public void testPublicStatics() {
+
+ HashMap thePublicStatics = new HashMap();
+ thePublicStatics.put("BOOLEAN", new Integer(16));
+ thePublicStatics.put("DATALINK", new Integer(70));
+ thePublicStatics.put("REF", new Integer(2006));
+ thePublicStatics.put("CLOB", new Integer(2005));
+ thePublicStatics.put("BLOB", new Integer(2004));
+ thePublicStatics.put("ARRAY", new Integer(2003));
+ thePublicStatics.put("STRUCT", new Integer(2002));
+ thePublicStatics.put("DISTINCT", new Integer(2001));
+ thePublicStatics.put("JAVA_OBJECT", new Integer(2000));
+ thePublicStatics.put("OTHER", new Integer(1111));
+ thePublicStatics.put("NULL", new Integer(0));
+ thePublicStatics.put("LONGVARBINARY", new Integer(-4));
+ thePublicStatics.put("VARBINARY", new Integer(-3));
+ thePublicStatics.put("BINARY", new Integer(-2));
+ thePublicStatics.put("TIMESTAMP", new Integer(93));
+ thePublicStatics.put("TIME", new Integer(92));
+ thePublicStatics.put("DATE", new Integer(91));
+ thePublicStatics.put("LONGVARCHAR", new Integer(-1));
+ thePublicStatics.put("VARCHAR", new Integer(12));
+ thePublicStatics.put("CHAR", new Integer(1));
+ thePublicStatics.put("DECIMAL", new Integer(3));
+ thePublicStatics.put("NUMERIC", new Integer(2));
+ thePublicStatics.put("DOUBLE", new Integer(8));
+ thePublicStatics.put("REAL", new Integer(7));
+ thePublicStatics.put("FLOAT", new Integer(6));
+ thePublicStatics.put("BIGINT", new Integer(-5));
+ thePublicStatics.put("INTEGER", new Integer(4));
+ thePublicStatics.put("SMALLINT", new Integer(5));
+ thePublicStatics.put("TINYINT", new Integer(-6));
+ thePublicStatics.put("BIT", new Integer(-7));
+
+ Class> typesClass;
+ try {
+ typesClass = Class.forName("java.sql.Types");
+ } catch (ClassNotFoundException e) {
+ fail("java.sql.Types class not found!");
+ return;
+ } // end try
+
+ Field[] theFields = typesClass.getDeclaredFields();
+ int requiredModifier = Modifier.PUBLIC + Modifier.STATIC
+ + Modifier.FINAL;
+
+ int countPublicStatics = 0;
+ for (Field element : theFields) {
+ String fieldName = element.getName();
+ int theMods = element.getModifiers();
+ if (Modifier.isPublic(theMods) && Modifier.isStatic(theMods)) {
+ try {
+ Object fieldValue = element.get(null);
+ Object expectedValue = thePublicStatics.get(fieldName);
+ if (expectedValue == null) {
+ fail("Field " + fieldName + " missing!");
+ } // end
+ assertEquals("Field " + fieldName + " value mismatch: ",
+ expectedValue, fieldValue);
+ assertEquals("Field " + fieldName + " modifier mismatch: ",
+ requiredModifier, theMods);
+ countPublicStatics++;
+ } catch (IllegalAccessException e) {
+ fail("Illegal access to Field " + fieldName);
+ } // end try
+ } // end if
+ } // end for
+
+ } // end method testPublicStatics
+
+} // end class TypesTest
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/AllTests.java b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/AllTests.java
new file mode 100644
index 0000000..abbb8b0
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/AllTests.java
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.harmony.sql.tests.javax.sql;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * This is autogenerated source file. Includes tests for package org.apache.harmony.sql.tests.javax.sql;
+ */
+
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AllTests.suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite("All tests for package org.apache.harmony.sql.tests.javax.sql;");
+ // $JUnit-BEGIN$
+
+ suite.addTestSuite(ConnectionEventTest.class);
+ suite.addTestSuite(RowSetEventTest.class);
+
+ // $JUnit-END$
+ return suite;
+ }
+}
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java
new file mode 100644
index 0000000..376b173
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import java.sql.SQLException;
+
+import javax.sql.ConnectionEvent;
+import javax.sql.PooledConnection;
+
+@TestTargetClass(ConnectionEvent.class)
+public class ConnectionEventTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.ConnectionEvent#ConnectionEvent(PooledConnection)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "functional test missing but not feasible: no implementation available.",
+ method = "ConnectionEvent",
+ args = {javax.sql.PooledConnection.class}
+ )
+ public void testConstructorConnection() {
+ try {
+ new ConnectionEvent(null);
+ fail("illegal argument exception expected");
+ } catch (IllegalArgumentException e) {
+ }
+
+ Impl_PooledConnection ipc = new Impl_PooledConnection();
+ ConnectionEvent ce = new ConnectionEvent(ipc);
+ assertSame(ipc, ce.getSource());
+ assertNull(ce.getSQLException());
+
+ //cross test
+ ConnectionEvent ce2 = new ConnectionEvent(ipc,null);
+ assertSame(ce2.getSource(),ce.getSource());
+ }
+
+
+
+ /**
+ * @tests {@link javax.sql.ConnectionEvent#ConnectionEvent(PooledConnection, SQLException)}
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "functional test missing but not feasible: no implementation available.",
+ method = "ConnectionEvent",
+ args = {javax.sql.PooledConnection.class, java.sql.SQLException.class}
+ )
+ public void testConstructorConnectionSQLException() {
+ try {
+ new ConnectionEvent(null, null);
+ fail("illegal argument exception expected");
+ } catch (IllegalArgumentException e) {
+ }
+
+ Impl_PooledConnection ipc = new Impl_PooledConnection();
+ ConnectionEvent ce = new ConnectionEvent(ipc, null);
+ assertSame(ipc, ce.getSource());
+ assertNull(ce.getSQLException());
+
+ SQLException e = new SQLException();
+ ce = new ConnectionEvent(ipc, e);
+ assertSame(ipc, ce.getSource());
+ assertSame(e, ce.getSQLException());
+ }
+
+ /**
+ * @tests {@link javax.sql.ConnectionEvent#getSQLException()}
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "functional test missing but not feasible: no implementation available.",
+ method = "getSQLException",
+ args = {}
+ )
+ public void testGetSQLException() {
+
+ Impl_PooledConnection ipc = new Impl_PooledConnection();
+ ConnectionEvent ce = new ConnectionEvent(ipc);
+
+ ConnectionEvent ce2 = new ConnectionEvent(ipc, null);
+ assertNull(ce.getSQLException());
+ assertEquals(ce2.getSQLException(), ce.getSQLException());
+
+ SQLException e = new SQLException();
+ ConnectionEvent ce3 = new ConnectionEvent(ipc, e);
+ assertNotNull(ce3.getSQLException());
+ assertNotSame(ce3.getSQLException(), ce2.getSQLException());
+
+ }
+}
+
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_PooledConnection.java b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_PooledConnection.java
new file mode 100644
index 0000000..d135ced
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_PooledConnection.java
@@ -0,0 +1,38 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.javax.sql;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+import javax.sql.ConnectionEventListener;
+import javax.sql.PooledConnection;
+
+class Impl_PooledConnection implements PooledConnection {
+ public void addConnectionEventListener(ConnectionEventListener theListener) {
+ }
+
+ public void close() throws SQLException {
+ }
+
+ public Connection getConnection() throws SQLException {
+ return null;
+ }
+
+ public void removeConnectionEventListener(ConnectionEventListener theListener) {
+ }
+}
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_RowSet.java b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_RowSet.java
new file mode 100644
index 0000000..ace6b9a
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_RowSet.java
@@ -0,0 +1,738 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.javax.sql;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.Ref;
+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.util.Calendar;
+import java.util.Map;
+import javax.sql.RowSet;
+import javax.sql.RowSetListener;
+
+@SuppressWarnings("deprecation")
+class Impl_RowSet implements RowSet {
+ public void addRowSetListener(RowSetListener theListener) {
+ }
+
+ public void clearParameters() throws SQLException {
+ }
+
+ public void execute() throws SQLException {
+ }
+
+ public String getCommand() {
+ return null;
+ }
+
+ public String getDataSourceName() {
+ return null;
+ }
+
+ public boolean getEscapeProcessing() throws SQLException {
+ return false;
+ }
+
+ public int getMaxFieldSize() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxRows() throws SQLException {
+ return 0;
+ }
+
+ public String getPassword() {
+ return null;
+ }
+
+ public int getQueryTimeout() throws SQLException {
+ return 0;
+ }
+
+ public int getTransactionIsolation() {
+ return 0;
+ }
+
+ public Map> getTypeMap() throws SQLException {
+ return null;
+ }
+
+ public String getUrl() throws SQLException {
+ return null;
+ }
+
+ public String getUsername() {
+ return null;
+ }
+
+ public boolean isReadOnly() {
+ return false;
+ }
+
+ public void removeRowSetListener(RowSetListener theListener) {
+ }
+
+ public void setArray(int parameterIndex, Array theArray) throws SQLException {
+ }
+
+ public void setAsciiStream(int parameterIndex, InputStream theInputStream, int length)
+ throws SQLException {
+ }
+
+ public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal) throws SQLException {
+ }
+
+ public void setBinaryStream(int parameterIndex, InputStream theInputStream, int length)
+ throws SQLException {
+ }
+
+ public void setBlob(int parameterIndex, Blob theBlob) throws SQLException {
+ }
+
+ public void setBoolean(int parameterIndex, boolean theBoolean) throws SQLException {
+ }
+
+ public void setByte(int parameterIndex, byte theByte) throws SQLException {
+ }
+
+ public void setBytes(int parameterIndex, byte[] theByteArray) throws SQLException {
+ }
+
+ public void setCharacterStream(int parameterIndex, Reader theReader, int length)
+ throws SQLException {
+ }
+
+ public void setClob(int parameterIndex, Clob theClob) throws SQLException {
+ }
+
+ public void setCommand(String cmd) throws SQLException {
+ }
+
+ public void setConcurrency(int concurrency) throws SQLException {
+ }
+
+ public void setDataSourceName(String name) throws SQLException {
+ }
+
+ public void setDate(int parameterIndex, Date theDate, Calendar theCalendar)
+ throws SQLException {
+ }
+
+ public void setDate(int parameterIndex, Date theDate) throws SQLException {
+ }
+
+ public void setDouble(int parameterIndex, double theDouble) throws SQLException {
+ }
+
+ public void setEscapeProcessing(boolean enable) throws SQLException {
+ }
+
+ public void setFloat(int parameterIndex, float theFloat) throws SQLException {
+ }
+
+ public void setInt(int parameterIndex, int theInteger) throws SQLException {
+ }
+
+ public void setLong(int parameterIndex, long theLong) throws SQLException {
+ }
+
+ public void setMaxFieldSize(int max) throws SQLException {
+ }
+
+ public void setMaxRows(int max) throws SQLException {
+ }
+
+ public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException {
+ }
+
+ public void setNull(int parameterIndex, int sqlType) throws SQLException {
+ }
+
+ public void setObject(int parameterIndex, Object theObject, int targetSqlType, int scale)
+ throws SQLException {
+ }
+
+ public void setObject(int parameterIndex, Object theObject, int targetSqlType)
+ throws SQLException {
+ }
+
+ public void setObject(int parameterIndex, Object theObject) throws SQLException {
+ }
+
+ public void setPassword(String password) throws SQLException {
+ }
+
+ public void setQueryTimeout(int seconds) throws SQLException {
+ }
+
+ public void setReadOnly(boolean readOnly) throws SQLException {
+ }
+
+ public void setRef(int parameterIndex, Ref theRef) throws SQLException {
+ }
+
+ public void setShort(int parameterIndex, short theShort) throws SQLException {
+ }
+
+ public void setString(int parameterIndex, String theString) throws SQLException {
+ }
+
+ public void setTime(int parameterIndex, Time theTime, Calendar theCalendar)
+ throws SQLException {
+ }
+
+ public void setTime(int parameterIndex, Time theTime) throws SQLException {
+ }
+
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp, Calendar theCalendar)
+ throws SQLException {
+ }
+
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp) throws SQLException {
+ }
+
+ public void setTransactionIsolation(int level) throws SQLException {
+ }
+
+ public void setType(int type) throws SQLException {
+ }
+
+ public void setTypeMap(Map> theTypeMap) throws SQLException {
+ }
+
+ public void setUrl(String theURL) throws SQLException {
+ }
+
+ public void setUsername(String theUsername) throws SQLException {
+ }
+
+ public boolean absolute(int row) throws SQLException {
+ return false;
+ }
+
+ public void afterLast() throws SQLException {
+ }
+
+ public void beforeFirst() throws SQLException {
+ }
+
+ public void cancelRowUpdates() throws SQLException {
+ }
+
+ public void clearWarnings() throws SQLException {
+ }
+
+ public void close() throws SQLException {
+ }
+
+ public void deleteRow() throws SQLException {
+ }
+
+ public int findColumn(String columnName) throws SQLException {
+ return 0;
+ }
+
+ public boolean first() throws SQLException {
+ return false;
+ }
+
+ public Array getArray(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Array getArray(String colName) throws SQLException {
+ return null;
+ }
+
+ public InputStream getAsciiStream(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public InputStream getAsciiStream(String columnName) throws SQLException {
+ return null;
+ }
+
+ public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException {
+ return null;
+ }
+
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public BigDecimal getBigDecimal(String columnName, int scale) throws SQLException {
+ return null;
+ }
+
+ public BigDecimal getBigDecimal(String columnName) throws SQLException {
+ return null;
+ }
+
+ public InputStream getBinaryStream(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public InputStream getBinaryStream(String columnName) throws SQLException {
+ return null;
+ }
+
+ public Blob getBlob(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Blob getBlob(String columnName) throws SQLException {
+ return null;
+ }
+
+ public boolean getBoolean(int columnIndex) throws SQLException {
+ return false;
+ }
+
+ public boolean getBoolean(String columnName) throws SQLException {
+ return false;
+ }
+
+ public byte getByte(int columnIndex) throws SQLException {
+ return 0;
+ }
+
+ public byte getByte(String columnName) throws SQLException {
+ return 0;
+ }
+
+ public byte[] getBytes(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public byte[] getBytes(String columnName) throws SQLException {
+ return null;
+ }
+
+ public Reader getCharacterStream(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Reader getCharacterStream(String columnName) throws SQLException {
+ return null;
+ }
+
+ public Clob getClob(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Clob getClob(String colName) throws SQLException {
+ return null;
+ }
+
+ public int getConcurrency() throws SQLException {
+ return 0;
+ }
+
+ public String getCursorName() throws SQLException {
+ return null;
+ }
+
+ public Date getDate(int columnIndex, Calendar cal) throws SQLException {
+ return null;
+ }
+
+ public Date getDate(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Date getDate(String columnName, Calendar cal) throws SQLException {
+ return null;
+ }
+
+ public Date getDate(String columnName) throws SQLException {
+ return null;
+ }
+
+ public double getDouble(int columnIndex) throws SQLException {
+ return 0;
+ }
+
+ public double getDouble(String columnName) throws SQLException {
+ return 0;
+ }
+
+ public int getFetchDirection() throws SQLException {
+ return 0;
+ }
+
+ public int getFetchSize() throws SQLException {
+ return 0;
+ }
+
+ public float getFloat(int columnIndex) throws SQLException {
+ return 0;
+ }
+
+ public float getFloat(String columnName) throws SQLException {
+ return 0;
+ }
+
+ public int getInt(int columnIndex) throws SQLException {
+ return 0;
+ }
+
+ public int getInt(String columnName) throws SQLException {
+ return 0;
+ }
+
+ public long getLong(int columnIndex) throws SQLException {
+ return 0;
+ }
+
+ public long getLong(String columnName) throws SQLException {
+ return 0;
+ }
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ return null;
+ }
+
+ public Object getObject(int columnIndex, Map> map) throws SQLException {
+ return null;
+ }
+
+ public Object getObject(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Object getObject(String columnName, Map> map) throws SQLException {
+ return null;
+ }
+
+ public Object getObject(String columnName) throws SQLException {
+ return null;
+ }
+
+ public Ref getRef(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Ref getRef(String colName) throws SQLException {
+ return null;
+ }
+
+ public int getRow() throws SQLException {
+ return 0;
+ }
+
+ public short getShort(int columnIndex) throws SQLException {
+ return 0;
+ }
+
+ public short getShort(String columnName) throws SQLException {
+ return 0;
+ }
+
+ public Statement getStatement() throws SQLException {
+ return null;
+ }
+
+ public String getString(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public String getString(String columnName) throws SQLException {
+ return null;
+ }
+
+ public Time getTime(int columnIndex, Calendar cal) throws SQLException {
+ return null;
+ }
+
+ public Time getTime(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Time getTime(String columnName, Calendar cal) throws SQLException {
+ return null;
+ }
+
+ public Time getTime(String columnName) throws SQLException {
+ return null;
+ }
+
+ public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException {
+ return null;
+ }
+
+ public Timestamp getTimestamp(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Timestamp getTimestamp(String columnName, Calendar cal) throws SQLException {
+ return null;
+ }
+
+ public Timestamp getTimestamp(String columnName) throws SQLException {
+ return null;
+ }
+
+ public int getType() throws SQLException {
+ return 0;
+ }
+
+ public InputStream getUnicodeStream(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public InputStream getUnicodeStream(String columnName) throws SQLException {
+ return null;
+ }
+
+ public URL getURL(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public URL getURL(String columnName) throws SQLException {
+ return null;
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return null;
+ }
+
+ public void insertRow() throws SQLException {
+ }
+
+ public boolean isAfterLast() throws SQLException {
+ return false;
+ }
+
+ public boolean isBeforeFirst() throws SQLException {
+ return false;
+ }
+
+ public boolean isFirst() throws SQLException {
+ return false;
+ }
+
+ public boolean isLast() throws SQLException {
+ return false;
+ }
+
+ public boolean last() throws SQLException {
+ return false;
+ }
+
+ public void moveToCurrentRow() throws SQLException {
+ }
+
+ public void moveToInsertRow() throws SQLException {
+ }
+
+ public boolean next() throws SQLException {
+ return false;
+ }
+
+ public boolean previous() throws SQLException {
+ return false;
+ }
+
+ public void refreshRow() throws SQLException {
+ }
+
+ public boolean relative(int rows) throws SQLException {
+ return false;
+ }
+
+ public boolean rowDeleted() throws SQLException {
+ return false;
+ }
+
+ public boolean rowInserted() throws SQLException {
+ return false;
+ }
+
+ public boolean rowUpdated() throws SQLException {
+ return false;
+ }
+
+ public void setFetchDirection(int direction) throws SQLException {
+ }
+
+ public void setFetchSize(int rows) throws SQLException {
+ }
+
+ public void updateArray(int columnIndex, Array x) throws SQLException {
+ }
+
+ public void updateArray(String columnName, Array x) throws SQLException {
+ }
+
+ public void updateAsciiStream(int columnIndex, InputStream x, int length)
+ throws SQLException {
+ }
+
+ public void updateAsciiStream(String columnName, InputStream x, int length)
+ throws SQLException {
+ }
+
+ public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException {
+ }
+
+ public void updateBigDecimal(String columnName, BigDecimal x) throws SQLException {
+ }
+
+ public void updateBinaryStream(int columnIndex, InputStream x, int length)
+ throws SQLException {
+ }
+
+ public void updateBinaryStream(String columnName, InputStream x, int length)
+ throws SQLException {
+ }
+
+ public void updateBlob(int columnIndex, Blob x) throws SQLException {
+ }
+
+ public void updateBlob(String columnName, Blob x) throws SQLException {
+ }
+
+ public void updateBoolean(int columnIndex, boolean x) throws SQLException {
+ }
+
+ public void updateBoolean(String columnName, boolean x) throws SQLException {
+ }
+
+ public void updateByte(int columnIndex, byte x) throws SQLException {
+ }
+
+ public void updateByte(String columnName, byte x) throws SQLException {
+ }
+
+ public void updateBytes(int columnIndex, byte[] x) throws SQLException {
+ }
+
+ public void updateBytes(String columnName, byte[] x) throws SQLException {
+ }
+
+ public void updateCharacterStream(int columnIndex, Reader x, int length)
+ throws SQLException {
+ }
+
+ public void updateCharacterStream(String columnName, Reader reader, int length)
+ throws SQLException {
+ }
+
+ public void updateClob(int columnIndex, Clob x) throws SQLException {
+ }
+
+ public void updateClob(String columnName, Clob x) throws SQLException {
+ }
+
+ public void updateDate(int columnIndex, Date x) throws SQLException {
+ }
+
+ public void updateDate(String columnName, Date x) throws SQLException {
+ }
+
+ public void updateDouble(int columnIndex, double x) throws SQLException {
+ }
+
+ public void updateDouble(String columnName, double x) throws SQLException {
+ }
+
+ public void updateFloat(int columnIndex, float x) throws SQLException {
+ }
+
+ public void updateFloat(String columnName, float x) throws SQLException {
+ }
+
+ public void updateInt(int columnIndex, int x) throws SQLException {
+ }
+
+ public void updateInt(String columnName, int x) throws SQLException {
+ }
+
+ public void updateLong(int columnIndex, long x) throws SQLException {
+ }
+
+ public void updateLong(String columnName, long x) throws SQLException {
+ }
+
+ public void updateNull(int columnIndex) throws SQLException {
+ }
+
+ public void updateNull(String columnName) throws SQLException {
+ }
+
+ public void updateObject(int columnIndex, Object x, int scale) throws SQLException {
+ }
+
+ public void updateObject(int columnIndex, Object x) throws SQLException {
+ }
+
+ public void updateObject(String columnName, Object x, int scale) throws SQLException {
+ }
+
+ public void updateObject(String columnName, Object x) throws SQLException {
+ }
+
+ public void updateRef(int columnIndex, Ref x) throws SQLException {
+ }
+
+ public void updateRef(String columnName, Ref x) throws SQLException {
+ }
+
+ public void updateRow() throws SQLException {
+ }
+
+ public void updateShort(int columnIndex, short x) throws SQLException {
+ }
+
+ public void updateShort(String columnName, short x) throws SQLException {
+ }
+
+ public void updateString(int columnIndex, String x) throws SQLException {
+ }
+
+ public void updateString(String columnName, String x) throws SQLException {
+ }
+
+ public void updateTime(int columnIndex, Time x) throws SQLException {
+ }
+
+ public void updateTime(String columnName, Time x) throws SQLException {
+ }
+
+ public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException {
+ }
+
+ public void updateTimestamp(String columnName, Timestamp x) throws SQLException {
+ }
+
+ public boolean wasNull() throws SQLException {
+ return false;
+ }
+}
diff --git a/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.java b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.java
new file mode 100644
index 0000000..bf30fbc
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.java
@@ -0,0 +1,55 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package org.apache.harmony.sql.tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import javax.sql.ConnectionEvent;
+import javax.sql.RowSet;
+import javax.sql.RowSetEvent;
+import junit.framework.TestCase;
+
+@TestTargetClass(RowSetEvent.class)
+public class RowSetEventTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.RowSetEvent#RowSetEvent(javax.sql.RowSet)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "functional test missing but not feasible: no implementation available.",
+ method = "RowSetEvent",
+ args = {javax.sql.RowSet.class}
+ )
+ public void testConstructor() {
+ try {
+ new RowSetEvent(null);
+ fail("illegal argument exception expected");
+ } catch (IllegalArgumentException e) {
+ }
+
+ Impl_RowSet irs = new Impl_RowSet();
+ RowSetEvent rse = new RowSetEvent(irs);
+ assertSame(irs, rse.getSource());
+ }
+
+
+}
diff --git a/sql/src/test/java/tests/SQLite/AbstractSqlTest.java b/sql/src/test/java/tests/SQLite/AbstractSqlTest.java
new file mode 100644
index 0000000..0c7fa61
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/AbstractSqlTest.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package tests.SQLite;
+
+import SQLite.Callback;
+import SQLite.Database;
+import SQLite.Exception;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+
+/**
+ * This class provides SQL unit test, which can be used by subclasses eg. to
+ * test JDBC drivers.
+ */
+@TestTargetClass(Database.class)
+abstract class AbstractSqlTest extends TestCase {
+
+ /**
+ * The first connection.
+ */
+ private Connection firstConnection;
+
+ /**
+ * The second connection.
+ */
+ private Connection secondConnection;
+
+ /**
+ * The statement from the first connection.
+ */
+ private Statement firstStmt;
+
+ /**
+ * The statement from the second connection.
+ */
+ private Statement secondStmt;
+
+ /**
+ * The values of the first column "one".
+ */
+ private final String[] ones = {"hello!", "goodbye"};
+
+ /**
+ * The values of the second column "two".
+ */
+ private final short[] twos = {10, 20};
+
+ /**
+ * The updated values of the first column "one".
+ */
+ private final String[] ones_updated;
+
+ /** Creates a new instance of this class */
+ public AbstractSqlTest() {
+ super();
+ ones_updated = new String[ones.length];
+ for (int i = 0; i < ones.length; i++) {
+ ones_updated[i] = ones[i] + twos[i];
+ }
+ }
+
+ /**
+ * Sets up a unit test, by creating two statements from two connections and
+ * creating a test table.
+ *
+ * @exception SQLException if there is a problem accessing the database
+ * @throws Exception
+ * @exception Exception may be thrown by subclasses
+ */
+ @Override
+ protected void setUp() throws InstantiationException,
+ IllegalAccessException, ClassNotFoundException, SQLException, Exception {
+ Class.forName(getDriverClassName()).newInstance();
+ firstConnection = DriverManager.getConnection(getConnectionURL());
+ firstConnection.setTransactionIsolation(getTransactionIsolation());
+ secondConnection = DriverManager.getConnection(getConnectionURL());
+ secondConnection.setTransactionIsolation(getTransactionIsolation());
+ firstStmt = firstConnection.createStatement();
+ firstStmt.execute("create table tbl1(one varchar(10), two smallint)");
+ secondStmt = secondConnection.createStatement();
+ }
+
+ /**
+ * Tears down a unit test, by setting the auto commit property of the first
+ * connection back to true, dropping the test table and closing the two
+ * connections.
+ */
+ @Override
+ protected void tearDown() throws SQLException {
+ firstStmt.close();
+ secondStmt.close();
+ firstConnection.setAutoCommit(true);
+ firstStmt = firstConnection.createStatement();
+ firstStmt.execute("drop table tbl1");
+ firstStmt.close();
+ firstConnection.close();
+ secondConnection.close();
+ }
+
+ /**
+ * Adds some rows to the test table and asserts that the rows can be
+ * retrieved again.
+ *
+ * @throws SQLException if there is a problem accessing the database
+ */
+ private void autoCommitInsertSelect() throws SQLException {
+ firstStmt.getConnection().setAutoCommit(true);
+ for (int i = 0; i < ones.length; i++) {
+ firstStmt.execute("insert into tbl1 values('" + ones[i] + "',"
+ + twos[i] + ")");
+ }
+ assertAllFromTbl1(firstStmt, ones, twos);
+ }
+
+ /**
+ * Asserts that the expected values can be selected from the test table.
+ *
+ * @param stmt the statement to be used for the selection of the data
+ * @param ones the expected values of the column 'one'
+ * @param twos the expected values of the column 'two'
+ * @throws SQLException if there is a problem accessing the database
+ */
+ private void assertAllFromTbl1(Statement stmt, String[] ones, short[] twos)
+ throws SQLException {
+ ResultSet rs = stmt.executeQuery("select * from tbl1");
+ int i = 0;
+ for (; rs.next(); i++) {
+ assertTrue(i < ones.length);
+ assertEquals(ones[i], rs.getString("one"));
+ assertEquals(twos[i], rs.getShort("two"));
+ }
+ assertTrue(i == ones.length);
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ clazz = Database.class,
+ method = "exec",
+ args = {String.class, Callback.class}
+ )
+ public void testAutoCommitInsertSelect() throws SQLException{
+ autoCommitInsertSelect();
+ }
+
+ /**
+ * Tests the following sequence after successful insertion of some test
+ * data:
+ * - update data from connection one
+ * - select data from connection two (-> should have the old values)
+ * - commit data from connection one
+ * - select data from connection two (-> should have the new values)
+ *
+ * @throws SQLException if there is a problem accessing the database
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ clazz = Database.class,
+ method = "exec",
+ args = {String.class, Callback.class}
+ )
+ public void testUpdateSelectCommitSelect() throws SQLException {
+ autoCommitInsertSelect();
+ firstStmt.getConnection().setAutoCommit(false);
+ updateOnes(firstStmt, ones_updated, twos);
+ assertAllFromTbl1(secondStmt, ones, twos);
+ firstStmt.getConnection().commit();
+ assertAllFromTbl1(secondStmt, ones_updated, twos);
+ }
+
+ /**
+ * Tests the following sequence after successful insertion of some test
+ * data:
+ * - update data from connection one
+ * - select data from connection two (-> should have the old values)
+ * - rollback data from connection one
+ * - select data from connection two (-> should still have the old values)
+ *
+ * @throws SQLException if there is a problem accessing the database
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "",
+ clazz = Database.class,
+ method = "exec",
+ args = {String.class, Callback.class}
+ )
+ public void testUpdateSelectRollbackSelect() throws SQLException {
+ autoCommitInsertSelect();
+ firstStmt.getConnection().setAutoCommit(false);
+ updateOnes(firstStmt, ones_updated, twos);
+ assertAllFromTbl1(secondStmt, ones, twos);
+ firstStmt.getConnection().rollback();
+ assertAllFromTbl1(secondStmt, ones, twos);
+ }
+
+ /**
+ * Updates the values in column 'one'
+ * @param stmt the statement to be used to update the data
+ * @param ones_updated the updated valus of column 'one'
+ * @param twos the reference values of column 'two'
+ * @throws SQLException if there is a problem accessing the database
+ */
+ private void updateOnes(Statement stmt, String[] ones_updated, short[] twos)
+ throws SQLException {
+ for (int i = 0; i < ones_updated.length; i++) {
+ stmt.execute("UPDATE tbl1 SET one = '" + ones_updated[i]
+ + "' WHERE two = " + twos[i]);
+ }
+ }
+
+ protected abstract String getConnectionURL();
+
+ protected abstract String getDriverClassName();
+
+ protected abstract int getTransactionIsolation();
+
+}
diff --git a/sql/src/test/java/tests/SQLite/AllTests.java b/sql/src/test/java/tests/SQLite/AllTests.java
new file mode 100644
index 0000000..2cf0f61
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/AllTests.java
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+public class AllTests {
+
+ //All tests executed with sqlite3 only
+ public static Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite("Tests for SQLite");
+ //$JUnit-BEGIN$
+ suite.addTestSuite(DatabaseTest.class);
+ suite.addTestSuite(JDBCDriverFunctionalTest.class);
+ suite.addTestSuite(JDBCDriverTest.class);
+ suite.addTestSuite(ConstantsTest.class);
+ suite.addTestSuite(BlobTest.class);
+ suite.addTestSuite(StmtTest.class);
+ suite.addTestSuite(ExceptionTest.class);
+ suite.addTestSuite(FunctionContextTest.class);
+ //$JUnit-END$
+ return suite;
+ }
+
+}
diff --git a/sql/src/test/java/tests/SQLite/BlobTest.java b/sql/src/test/java/tests/SQLite/BlobTest.java
new file mode 100644
index 0000000..71f2005
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/BlobTest.java
@@ -0,0 +1,235 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import SQLite.Blob;
+import SQLite.Database;
+import SQLite.Exception;
+import SQLite.Stmt;
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import junit.framework.TestCase;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+
+@TestTargetClass(Blob.class)
+public class BlobTest extends SQLiteTest {
+
+ private static Blob testBlob = null;
+
+ private byte[] blobInput= null;
+
+ private static InputStream file = null;
+
+ private static Database db = null;
+
+ private static Stmt st = null;
+
+ public class MockBlob extends Blob {
+ public void finalize() {
+ try {
+ super.finalize();
+ } catch (Throwable exception) {
+ fail("Test activity faild!");
+ }
+ }
+ }
+
+ public void setUp() throws java.lang.Exception {
+ super.setUp();
+ testBlob = new Blob();
+
+ super.setUp();
+ Support_SQL.loadDriver();
+ db = new Database();
+ db.open(dbFile.getPath(), 0);
+
+ db.exec("create table B(id integer primary key, val blob)",null);
+ db.exec("insert into B values(1, zeroblob(128))", null);
+ db.exec("insert into B values(2, zeroblob(128))", null);
+ db.exec("insert into B values(3, zeroblob(128))", null);
+
+ // can not fill Blob with data at this point...
+ /*
+ File resources = Support_Resources.createTempFolder();
+ BufferedReader r = null;
+ try {
+ Class c = Class.forName(this.getClass().getName());
+ assertNotNull(c);
+ file = Class.forName(this.getClass().getName())
+ .getResourceAsStream("/blob.c");
+ r = new BufferedReader(new InputStreamReader(file));
+ } catch (NullPointerException e) {
+ fail("Should not throw NullPointerException reading file"
+ + e.getMessage());
+ }
+ OutputStream out = testBlob.getOutputStream();
+ String s = null;
+ while ((s = r.readLine()) != null) {
+ out.write(r.readLine().getBytes());
+ }
+ out.flush();
+ out.close();
+ testBlob.close();
+ */
+ }
+
+ public void tearDown() {
+
+ testBlob.close();
+ super.tearDown();
+ }
+
+ /**
+ * @throws Exception
+ * @throws IOException
+ * @tests Blob#Blob()
+ */
+ @TestTargets ( {
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "db.open_blob is not supported also for Stmt, therefore cannot test Blobs",
+ method = "Blob",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "functional test",
+ method = "getOutputStream",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "functional test",
+ method = "getInputStream",
+ args = {}
+ )
+ })
+ @KnownFailure("db.open_blob is not supported.")
+ public void testBlob() throws Exception, IOException {
+ byte[] b = new byte[4];
+ byte[] b128 = new byte[128];
+ for (int i = 0; i < b128.length; i++) {
+ b128[i] = (byte) i;
+ }
+ Blob blob = db.open_blob(dbFile.getPath(), "B", "val", 1, true);
+ try {
+
+ OutputStream os = blob.getOutputStream();
+ os.write(b128);
+ os.close();
+
+ InputStream is = blob.getInputStream();
+ is.skip(96);
+ assertEquals(4,is.read(b));
+ is.close();
+ } finally {
+ blob.close();
+ }
+ }
+
+ /**
+ * @tests Blob#finalize()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "Can not be checked. Should be tested in DX test package.",
+ method = "finalize",
+ args = {}
+ )
+ public void testFinalize() {
+
+ }
+
+ /**
+ * @tests Blob.getInputStream()
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Exception test",
+ method = "getInputStream",
+ args = {}
+ )
+ public void testGetInputStream() {
+ InputStream in = testBlob.getInputStream();
+
+ try {
+ in.read();
+ fail("Exception not thrown for invalid Blob.");
+ } catch (Throwable e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests Blob#getOutputStream()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Exception test",
+ method = "getOutputStream",
+ args = {}
+ )
+ public void testGetOutputStream() {
+ OutputStream out = testBlob.getOutputStream();
+
+ try {
+ out.write(null);
+ fail("Write operation unsupported");
+ } catch (Throwable e) {
+ assertEquals("Write operation unsupported", e.getMessage());
+ }
+ }
+
+ /**
+ * @tests Blob#close()
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "not clear from spec what should happen when Blob is closed.",
+ method = "close",
+ args = {}
+ )
+ @KnownFailure("Blob does not clean up inputStream.")
+ public void testClose() {
+ assertNotNull(testBlob);
+
+ testBlob.close();
+ // inputStream eithter null or some error occurs
+ try {
+ assertNull(testBlob.getInputStream());
+ } catch (Throwable e) {
+ //ok
+ }
+
+ try {
+ assertNull(testBlob.getOutputStream());
+ } catch (Throwable e) {
+ //ok
+ }
+
+ }
+}
diff --git a/sql/src/test/java/tests/SQLite/ConstantsTest.java b/sql/src/test/java/tests/SQLite/ConstantsTest.java
new file mode 100644
index 0000000..2a4961f
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/ConstantsTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import SQLite.Constants;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(Constants.class)
+public class ConstantsTest extends TestCase {
+
+ /**
+ * @tests Constants#Constants()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "constructor test",
+ method = "Constants",
+ args = {}
+ )
+ public void testConstants() {
+ Constants c = new Constants();
+
+ assertNotNull(c);
+ assertEquals(c.SQLITE_OK, 0);
+ assertEquals(c.SQLITE_ERROR, 1);
+ assertEquals(c.SQLITE_INTERNAL, 2);
+ assertEquals(c.SQLITE_PERM, 3);
+ assertEquals(c.SQLITE_ABORT, 4);
+ assertEquals(c.SQLITE_BUSY, 5);
+ assertEquals(c.SQLITE_LOCKED, 6);
+ assertEquals(c.SQLITE_NOMEM, 7);
+ assertEquals(c.SQLITE_READONLY, 8);
+ assertEquals(c.SQLITE_INTERRUPT, 9);
+ assertEquals(c.SQLITE_IOERR, 10);
+ assertEquals(c.SQLITE_CORRUPT, 11);
+ assertEquals(c.SQLITE_NOTFOUND, 12);
+ assertEquals(c.SQLITE_FULL, 13);
+ assertEquals(c.SQLITE_CANTOPEN, 14);
+ assertEquals(c.SQLITE_PROTOCOL, 15);
+ assertEquals(c.SQLITE_EMPTY, 16);
+ assertEquals(c.SQLITE_SCHEMA, 17);
+ assertEquals(c.SQLITE_TOOBIG, 18);
+ assertEquals(c.SQLITE_CONSTRAINT, 19);
+ assertEquals(c.SQLITE_MISMATCH, 20);
+ assertEquals(c.SQLITE_MISUSE, 21);
+ assertEquals(c.SQLITE_NOLFS, 22);
+ assertEquals(c.SQLITE_AUTH, 23);
+ assertEquals(c.SQLITE_FORMAT, 24);
+ assertEquals(c.SQLITE_RANGE, 25);
+ assertEquals(c.SQLITE_NOTADB, 26);
+ assertEquals(c.SQLITE_ROW, 100);
+ assertEquals(c.SQLITE_DONE, 101);
+ assertEquals(c.SQLITE_INTEGER, 1);
+ assertEquals(c.SQLITE_FLOAT, 2);
+ assertEquals(c.SQLITE_BLOB, 4);
+ assertEquals(c.SQLITE_NULL, 5);
+ assertEquals(c.SQLITE3_TEXT, 3);
+ assertEquals(c.SQLITE_NUMERIC, -1);
+ assertEquals(c.SQLITE_TEXT, 3);
+ assertEquals(c.SQLITE2_TEXT, -2);
+ assertEquals(c.SQLITE_ARGS, -3);
+ assertEquals(c.SQLITE_COPY, 0);
+ assertEquals(c.SQLITE_CREATE_INDEX, 1);
+ assertEquals(c.SQLITE_CREATE_TABLE, 2);
+ assertEquals(c.SQLITE_CREATE_TEMP_INDEX, 3);
+ assertEquals(c.SQLITE_CREATE_TEMP_TABLE, 4);
+ assertEquals(c.SQLITE_CREATE_TEMP_TRIGGER, 5);
+ assertEquals(c.SQLITE_CREATE_TEMP_VIEW, 6);
+ assertEquals(c.SQLITE_CREATE_TRIGGER, 7);
+ assertEquals(c.SQLITE_CREATE_VIEW, 8);
+ assertEquals(c.SQLITE_DELETE, 9);
+ assertEquals(c.SQLITE_DROP_INDEX, 10);
+ assertEquals(c.SQLITE_DROP_TABLE, 11);
+ assertEquals(c.SQLITE_DROP_TEMP_INDEX, 12);
+ assertEquals(c.SQLITE_DROP_TEMP_TABLE, 13);
+ assertEquals(c.SQLITE_DROP_TEMP_TRIGGER, 14);
+ assertEquals(c.SQLITE_DROP_TEMP_VIEW, 15);
+ assertEquals(c.SQLITE_DROP_TRIGGER, 16);
+ assertEquals(c.SQLITE_DROP_VIEW, 17);
+ assertEquals(c.SQLITE_INSERT, 18);
+ assertEquals(c.SQLITE_PRAGMA, 19);
+ assertEquals(c.SQLITE_READ, 20);
+ assertEquals(c.SQLITE_SELECT, 21);
+ assertEquals(c.SQLITE_TRANSACTION, 22);
+ assertEquals(c.SQLITE_UPDATE, 23);
+ assertEquals(c.SQLITE_ATTACH, 24);
+ assertEquals(c.SQLITE_DETACH, 25);
+ assertEquals(c.SQLITE_DENY, 1);
+ assertEquals(c.SQLITE_IGNORE, 2);
+ }
+}
diff --git a/sql/src/test/java/tests/SQLite/DatabaseTest.java b/sql/src/test/java/tests/SQLite/DatabaseTest.java
new file mode 100644
index 0000000..50eb6cc
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/DatabaseTest.java
@@ -0,0 +1,2037 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+import tests.support.DatabaseCreator;
+import tests.support.MockFunction;
+import tests.support.ThreadPool;
+import tests.support.resource.Support_Resources;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import SQLite.Authorizer;
+import SQLite.Blob;
+import SQLite.BusyHandler;
+import SQLite.Callback;
+import SQLite.Constants;
+import SQLite.Database;
+import SQLite.Exception;
+import SQLite.Function;
+import SQLite.FunctionContext;
+import SQLite.ProgressHandler;
+import SQLite.Stmt;
+import SQLite.TableResult;
+import SQLite.Trace;
+import SQLite.Vm;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.logging.Logger;
+
+@TestTargetClass(Database.class)
+public class DatabaseTest extends SQLiteTest {
+
+ /**
+ * The SQLite db file.
+ */
+// protected final File dbFile = new File("sqliteTest.db");
+//
+// private final String connectionURL = "jdbc:sqlite:/" + dbFile.getPath();
+//
+// private final String classname = "SQLite.JDBCDriver";
+//
+// private static Connection conn = null;
+
+ private static ErrorTracker tracker = null;
+
+ private Statement statement;
+
+ private Database db = null;
+
+ private static final int numThreads = 10;
+
+ private static final int numOfRecords = 30;
+
+ public void setUp() throws java.lang.Exception {
+ try {
+ super.setUp();
+ assertNotNull("Could not establish DB connection",conn);
+ tracker = new ErrorTracker();
+
+ statement = conn.createStatement();
+
+ //Cleanup tables if necessary
+
+ DatabaseMetaData meta = conn.getMetaData();
+ assertNotNull(meta);
+ if (meta != null) {
+ ResultSet userTab = meta.getTables(null, null, null, null);
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ this.statement.execute("drop table "+tableName);
+ }
+ }
+
+ // Create default test table
+// statement = conn.createStatement();
+ statement.execute(DatabaseCreator.CREATE_TABLE_SIMPLE1);
+ statement.close();
+
+ try {
+ db = new Database();
+ db.open(dbFile.getPath(), 0);
+ db.busy_handler(null);
+ } catch (Exception e) {
+ System.out.println("2: Error opening File: Dir "+dbFile.getPath()+" Name: "+dbFile.getPath());
+ } catch (java.lang.Exception e) {
+ System.err.println("Non SQLException "+e.getMessage());
+ }
+ } catch (Exception e) {
+ System.out.println("Database setup fails: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ public void tearDown() {
+
+ try {
+ db.close();
+ }catch (Exception e) {
+ if (! (e.getMessage().equals("database already closed"))) {
+ System.err.println("Error closing DB "+dbFile.getPath());
+ }
+ }
+// conn.close();
+// dbFile.delete();
+ tracker.reset();
+ super.tearDown();
+ }
+
+ /**
+ * @tests Database#Database()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "constructor test",
+ method = "Database",
+ args = {}
+ )
+ public void testDatabase() {
+ // db closed
+ Database db2 = new Database();
+ try {
+ db.close();
+ db2 = new Database();
+ db2.open(dbFile.getPath(), 0);
+ db2.close();
+ db.open(dbFile.getPath(), 0);
+ } catch (Exception e) {
+ fail("Database object could not be created "+e.getMessage());
+ e.printStackTrace();
+ }
+ //db is open
+ try {
+ db2.open(dbFile.getPath(), 0);
+ db2.close();
+ } catch (Exception e) {
+ fail("Second Database object could not be created "+e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @tests Database#finalize()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "method test",
+ method = "finalize",
+ args = {}
+ )
+ public void testFinalize() {
+ }
+
+ /**
+ * @tests {@link Database#open(String, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test. Test fails.",
+ method = "open",
+ args = {java.lang.String.class, int.class}
+ )
+ public void testOpen() {
+ try {
+ db.close();
+ db.open(dbFile.getPath(), 0);
+ } catch (Exception e) {
+ fail("Database object could not be opened: " + e.getMessage());
+ e.printStackTrace();
+ }
+ // open second db while db1 still open
+ Database db2 = new Database();
+ try {
+ db2.open(dbFile.getPath(), 0);
+ db2.open(dbFile.getPath(), 0);
+ db2.close();
+ } catch (Exception e) {
+ fail("Database object could not be opened: " + e.getMessage());
+ e.printStackTrace();
+ }
+ // open non db file
+ File tempDir = Support_Resources.createTempFolder();
+ final String resourceName = "blob.c";
+ try {
+ URL file = Class.forName(this.getClass().getName())
+ .getResource("/blob.c");
+ db2.open(file.getPath(), 0);
+ fail("Should not be able to open non db file");
+ } catch (Exception e) {
+ assertEquals("unknown error in open", e.getMessage());
+ } catch (java.lang.Exception e) {
+ fail("Error in setup " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * @tests Database#open_aux_file(String)
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "not supported",
+ method = "open_aux_file",
+ args = {java.lang.String.class}
+ )
+ public void testOpen_aux_file() {
+ File temp = null;
+ try {
+ db.open_aux_file("");
+ fail("open should fail");
+ } catch (Exception e) {
+ assertEquals("unsupported", e.getMessage());
+ }
+
+ /*
+ try {
+ temp = File.createTempFile("openAuxMethod", ".db");
+ db.open_aux_file("");
+ db.exec("create table AUX_TABLE", null);
+ db.close();
+ } catch (Exception e) {
+ temp.delete();
+ fail("Error handling temporary file "+e.getMessage());
+ e.printStackTrace();
+ } catch (IOException e) {
+ temp.delete();
+ fail("Could not create temporary File");
+ e.printStackTrace();
+ }
+ try {
+ db.open(dbFile.getPath(),0);
+ db.exec("select * from AUX_TABLE", null);
+ fail("Statement should fail");
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ temp.delete();
+ */
+ }
+
+ /**
+ * @tests Database#close()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "close",
+ args = {}
+ )
+ public void testClose() {
+ try {
+ db.close();
+ db.get_table("test");
+ } catch (Exception e) {
+ assertTrue(e.getMessage().equals("database already closed"));
+ try {
+ db.open(dbFile.getPath(), 0);
+ } catch (Exception e1) {
+ fail("Database object could not be reopened after 'close': "
+ + e.getMessage());
+ e1.printStackTrace();
+ }
+ }
+
+ try {
+ db.close();
+ db.close();
+ } catch (Exception e) {
+ assertTrue(e.getMessage().equals("database already closed"));
+ try {
+ db.open(dbFile.getPath(), 0);
+ } catch (Exception e1) {
+ fail("Database object could not be reopened after 'close': "
+ + e.getMessage());
+ e1.printStackTrace();
+ }
+ }
+ }
+
+ /**
+ * @tests Database#exec(String, Callback)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "exec",
+ args = {java.lang.String.class, Callback.class}
+ )
+ public void testExecStringCallback() {
+ TableResult res = new TableResult();
+ try {
+ db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " VALUES(1, 10, 20)", null);
+ db.exec("select * from " + DatabaseCreator.SIMPLE_TABLE1, res);
+ db
+ .exec("delete from " + DatabaseCreator.SIMPLE_TABLE1
+ + " where 1", null);
+ } catch (Exception e) {
+ fail("Database error");
+ e.printStackTrace();
+ }
+ String row[] = (String[]) res.rows.elementAt(0);
+ assertEquals(Integer.parseInt(row[0]), 1);
+ assertEquals(Integer.parseInt(row[1]), 10);
+ assertEquals(Integer.parseInt(row[2]), 20);
+ }
+
+ /**
+ * @tests Database#exec(String, Callback, String[])
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "exec",
+ args = {java.lang.String.class, Callback.class, java.lang.String[].class}
+ )
+ public void testExecStringCallbackStringArray() {
+ TableResult res = new TableResult();
+ String args[] = new String[1];
+ args[0] = "table";
+ try {
+ db.exec("select name from sqlite_master where type = '%q';", res,
+ args);
+ String[] s = (String[]) res.rows.elementAt(0);
+ assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
+ } catch (Exception e) {
+ fail("DB Error occurred");
+ e.printStackTrace();
+ }
+
+ try {
+ db.exec("select name from sqlite_master where type = ", res, args);
+ fail("Testmethod should fail");
+ } catch (Exception e) {
+ // Ok
+ }
+ }
+
+ /**
+ * @tests {@link Database#last_insert_rowid()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "last_insert_rowid",
+ args = {}
+ )
+ public void testLast_insert_rowid() {
+ assertEquals(0, db.last_insert_rowid());
+ try {
+ db
+ .exec(
+ "create table TEST5(id integer, firstname text, lastname text);",
+ null);
+ db.exec("insert into TEST5 values (1,'James','Bond');", null);
+ db.exec("insert into TEST5 values (2,'Fiona','Apple');", null);
+ } catch (Exception e) {
+ fail("Error in test setup: " + e.getMessage());
+ e.printStackTrace();
+ }
+ assertEquals(2, db.last_insert_rowid());
+ assertEquals(db.last_insert_rowid(), db.last_insert_rowid());
+
+ try {
+ db.exec("drop table TEST5;", null);
+ } catch (Exception e) {
+ fail("Error in test setup: " + e.getMessage());
+ e.printStackTrace();
+ }
+ assertEquals(2, db.last_insert_rowid());
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Database#interrupt()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "interrupt",
+ args = {}
+ )
+ @KnownFailure("Reason for failure unknown: Database should be locked. " +
+ "Specification of interrupt is scarce.")
+ public void testInterrupt() throws Exception {
+ ThreadPool threadPool = new ThreadPool(numThreads);
+
+ // initialization
+ ResultSet userTabs;
+ try {
+ userTabs = conn.getMetaData().getTables(null, null, null, null);
+ while (userTabs.next()) {
+ String tableName = userTabs.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ }
+ }
+ db.exec(DatabaseCreator.CREATE_TABLE3, null);
+ db.exec(DatabaseCreator.CREATE_TABLE1, null);
+ } catch (SQLException e1) {
+ fail("Error initializing test " + e1.toString());
+ e1.printStackTrace();
+ } catch (Exception e) {
+ fail("Error initializing test " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ int id1 = numOfRecords - 3;
+ threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
+ // should not be able to do any other insertions since task 1 holds lock
+ int id2 = numOfRecords + 3;
+ threadPool
+ .runTask(createTask2Interrupt(id2, dbFile.getPath(), tracker));
+
+ threadPool.join();
+
+ List errors = tracker.getErrors();
+ System.out.println("Last error: " + db.error_message());
+ if (errors.size() > 0) {
+ assertEquals(errors.get(0), db
+ .error_string(Constants.SQLITE_LOCKED));
+ for (String s : errors) {
+ Logger.global.info("INTERRUPT Error: " + s);
+ }
+
+ } else {
+ fail("Should have one exception: database should be locked.");
+ }
+
+ // reset
+
+ db
+ .exec(
+ "delete from " + DatabaseCreator.TEST_TABLE1
+ + " where 1", null);
+ db
+ .exec(
+ "delete from " + DatabaseCreator.TEST_TABLE3
+ + " where 1", null);
+
+ }
+
+ /**
+ * @tests {@link Database#changes()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "test fails",
+ method = "changes",
+ args = {}
+ )
+ @KnownFailure("Returns wrong number for updates: returns value > 1 for select.")
+ public void testChanges() {
+ TableResult res = new TableResult();
+ try {
+ assertTrue(db.changes() == 0);
+ db.exec("INSERT INTO " + DatabaseCreator.SIMPLE_TABLE1
+ + " VALUES(2, 5, 7);", null);
+ int rows = (int) db.changes();
+ assertEquals(1,db.changes());
+ db.exec("update " + DatabaseCreator.SIMPLE_TABLE1
+ + " set speed = 7, size= 5 where id = 2;", null);
+ assertEquals(1,db.changes());
+ db.exec("select * from " + DatabaseCreator.SIMPLE_TABLE1, res);
+ assertEquals(0,db.changes());
+ db.exec("INSERT INTO " + DatabaseCreator.SIMPLE_TABLE1
+ + " VALUES(8, 5, 7);", null);
+ db.exec("Update "+DatabaseCreator.SIMPLE_TABLE1+" set speed = 10;",null);
+ assertTrue(db.changes() > 2);
+ } catch (Exception e) {
+ fail("Could not get changes: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @throws Exception
+ * @tests {@link Database#busy_handler(BusyHandler)}
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "method test fails once in a while. Cannot be sure that exception is thrown every time.",
+ method = "busy_handler",
+ args = {BusyHandler.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "method test fails once in a while. Cannot be sure that exception is thrown every time.",
+ method = "busy",
+ clazz = BusyHandler.class,
+ args = {java.lang.String.class, int.class}
+ )
+ })
+ @KnownFailure("method test fails once in a while. "+
+ "Cannot be sure that exception is thrown in every test execution.")
+ public void testBusy_handler() throws SQLException, Exception {
+ TestBusyHandler bh = new TestBusyHandler();
+ db.busy_handler(bh);
+ int counter = 0;
+ ThreadPool threadPool = new ThreadPool(numThreads);
+
+ // initialization
+ ResultSet userTabs;
+ try {
+ userTabs = conn.getMetaData().getTables(null, null, null, null);
+ while (userTabs.next()) {
+ String tableName = userTabs.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ }
+ }
+ db.exec(DatabaseCreator.CREATE_TABLE3, null);
+ db.exec(DatabaseCreator.CREATE_TABLE1, null);
+ } catch (SQLException e1) {
+ fail("Error initializing test " + e1.toString());
+ e1.printStackTrace();
+ } catch (Exception e) {
+ fail("Error initializing test " + e.getMessage());
+ e.printStackTrace();
+ }
+
+
+// try {
+// DatabaseCreator.fillTestTable1(conn, numOfRecords);
+ // set to fail immediately if table is locked.
+// db.busy_handler(bh);
+// db.busy_timeout(0);
+ try {
+ conn.setAutoCommit(false);
+ int id1 = numOfRecords - 3;
+ threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
+ int id2 = numOfRecords + 3;
+ threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
+ int oldID = 5;
+ int newID = 100;
+ threadPool.runTask(createTask3(oldID, dbFile.getPath(), newID,
+ tracker));
+
+ threadPool.join();
+
+ List errors = tracker.getErrors();
+ if (errors.size() > 0) {
+// assertEquals(errors.get(0),
+// db.error_string(Constants.SQLITE_LOCKED));
+ for (String s: errors) {
+ System.out.println("Round 2 Error: "+s);
+ }
+ } else {
+ fail("No error happened");
+ }
+
+ // reset
+
+
+ db.exec("delete from " + DatabaseCreator.TEST_TABLE1 + " where 1",
+ null);
+ db.exec("delete from " + DatabaseCreator.TEST_TABLE3 + " where 1",
+ null);
+//
+// // increase timeout for retry
+// db.busy_timeout(1000);
+// db.busy_handler(bh);
+// tracker.reset();
+
+// threadPool = new ThreadPool(numThreads);
+//
+// threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
+// threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
+//
+// threadPool.join();
+//
+// errors = tracker.getErrors();
+// if (errors.size() > 0) {
+// // assertEquals(errors.get(0),
+// // db.error_string(Constants.SQLITE_LOCKED));
+// for (String s: errors) {
+// System.out.println("Round 2 Error"+s);
+// }
+// } else {
+// // ok
+// System.out.println("BUSY: No Error!");
+// }
+//
+//
+ } catch (Exception e) {
+ fail("Error in test setup " + e.getMessage());
+ try {
+ db.get_table("select * from " + DatabaseCreator.TEST_TABLE1,
+ null).toString();
+ } catch (Exception e1) {
+
+ e1.printStackTrace();
+ }
+ e.printStackTrace();
+// } catch (SQLException e2) {
+// System.out.println("Error in test setup "+e2.toString());
+// try {
+// db.get_table("select * from "+DatabaseCreator.TEST_TABLE1,null).
+// toString();
+// } catch (Exception e1) {
+// e2.printStackTrace();
+// }
+ } finally {
+ conn.setAutoCommit(true);
+ db.exec(DatabaseCreator.DROP_TABLE1, null);
+ db.exec(DatabaseCreator.DROP_TABLE3, null);
+ }
+ }
+
+ /**
+ * @throws Exception
+ * @throws SQLException
+ * @tests {@link Database#busy_timeout(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "test fails. Cannot be sure that exception is thrown every time.",
+ method = "busy_timeout",
+ args = {int.class}
+ )
+ @KnownFailure("Database does not lock values")
+ public void testBusy_timeout() throws Exception, SQLException {
+ int counter = 0;
+ ThreadPool threadPool = new ThreadPool(numThreads);
+
+ // initialization
+ ResultSet userTabs;
+ try {
+ userTabs = conn.getMetaData().getTables(null, null, null, null);
+ while (userTabs.next()) {
+ String tableName = userTabs.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ }
+ }
+ db.exec(DatabaseCreator.CREATE_TABLE3, null);
+ db.exec(DatabaseCreator.CREATE_TABLE1, null);
+ } catch (SQLException e1) {
+ fail("Error initializing test " + e1.toString());
+ e1.printStackTrace();
+ } catch (Exception e) {
+ fail("Error initializing test " + e.getMessage());
+ e.printStackTrace();
+ }
+
+
+ // test run
+ try {
+ conn.setAutoCommit(false);
+
+// DatabaseCreator.fillTestTable1(conn, numOfRecords);
+ // set to fail immediately if table is locked.
+ db.busy_handler(null);
+ db.busy_timeout(0);
+ int id1 = numOfRecords - 3;
+
+ threadPool.runTask(createTask2(id1, dbFile.getPath(), tracker));
+ int id2 = numOfRecords + 3;
+ threadPool.runTask(createTask1(id2, dbFile.getPath(), tracker));
+ int oldID = 5;
+ int newID = 100;
+ threadPool.runTask(createTask3(oldID, dbFile.getPath(), newID,
+ tracker));
+
+ threadPool.join();
+
+ List errors = tracker.getErrors();
+ assertTrue("No error occurred on DB but should have",errors.size() > 0);
+
+ assertEquals(errors.get(0),
+ db.error_string(Constants.SQLITE_LOCKED));
+ assertEquals(errors.get(0), "database is locked");
+
+ // reset
+
+ db.exec("delete from " + DatabaseCreator.TEST_TABLE1 + " where 1",
+ null);
+ db.exec("delete from " + DatabaseCreator.TEST_TABLE3 + " where 1",
+ null);
+
+ // increase timeout for retry
+ db.busy_timeout(10000);
+ db.busy_handler(null);
+ tracker.reset();
+ threadPool = new ThreadPool(numThreads);
+
+ threadPool.runTask(createTask1(id1, dbFile.getPath(), tracker));
+ threadPool.runTask(createTask2(id2, dbFile.getPath(), tracker));
+
+ threadPool.join();
+
+ errors = tracker.getErrors();
+ if (errors.size() > 0) {
+ fail("busy timeout should prevent from lock exception!");
+ for (String s: errors) {
+ System.out.println("Round 2 Error"+s);
+ }
+ } else {
+ // ok
+ }
+
+
+ } catch (Exception e) {
+ fail("Error in test setup " + e.getMessage());
+ try {
+ db.get_table("select * from " + DatabaseCreator.TEST_TABLE1,
+ null).toString();
+ } catch (Exception e1) {
+
+ e1.printStackTrace();
+ }
+ e.printStackTrace();
+ } finally {
+ conn.setAutoCommit(true);
+ // cleanup
+ db.exec(DatabaseCreator.DROP_TABLE1, null);
+ db.exec(DatabaseCreator.DROP_TABLE3, null);
+ }
+ }
+
+ /**
+ * @tests {@link Database#get_table(String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "get_table",
+ args = {java.lang.String.class}
+ )
+ public void testGet_tableString() {
+ TableResult emptyTable = new TableResult();
+ try {
+ //select from empty table
+ TableResult res = db.get_table("select * from "
+ + DatabaseCreator.SIMPLE_TABLE1);
+ assertEquals(res.toString(), emptyTable.toString());
+ //fill table-> t
+// DatabaseCreator.fillSimpleTable1(conn);
+// res = db.get_table("select * from "
+// + DatabaseCreator.SIMPLE_TABLE1);
+// assertFalse(emptyTable.toString().equals(res.toString()));
+
+ try {
+ db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " VALUES(1, 10, 20)", null);
+ res = db.get_table("select * from " + DatabaseCreator.SIMPLE_TABLE1);
+ db
+ .exec("delete from " + DatabaseCreator.SIMPLE_TABLE1
+ + " where 1", null);
+ } catch (Exception e) {
+ fail("Database error");
+ e.printStackTrace();
+ }
+ String row[] = (String[]) res.rows.elementAt(0);
+ assertEquals(Integer.parseInt(row[0]), 1);
+ assertEquals(Integer.parseInt(row[1]), 10);
+ assertEquals(Integer.parseInt(row[2]), 20);
+ } catch (Exception e) {
+ fail("Error getting table " + e.getMessage());
+ e.printStackTrace();
+// } catch (SQLException e) {
+// fail("Error initialising table " + e.getMessage());
+// e.printStackTrace();
+ }
+ }
+
+ /**
+ * @tests {@link Database#get_table(String, String[])}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "get_table",
+ args = {java.lang.String.class, java.lang.String[].class}
+ )
+ public void testGet_tableStringStringArray() {
+ String args[] = new String[1];
+ args[0] = "table";
+ String argsFail[] = new String[1];
+ try {
+ TableResult res = db.get_table(
+ "select name from sqlite_master where type = ", argsFail);
+ fail("Testmethod should fail");
+ } catch (Exception e) {
+ try {
+ TableResult res = db.get_table(
+ "select name from sqlite_master where type = '%q'",
+ args);
+ String[] s = (String[]) res.rows.elementAt(0);
+ assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
+ } catch (Exception e2) {
+ fail("Testmethod failed: " + e2.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ }
+
+ /**
+ * @tests {@link Database#get_table(String, String[], TableResult)}
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "get_table",
+ args = {java.lang.String.class, java.lang.String[].class, TableResult.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "toString",
+ clazz = TableResult.class,
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "types",
+ clazz = TableResult.class,
+ args = {String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "TableResult",
+ clazz = TableResult.class,
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_NECESSARY,
+ notes = "method test",
+ method = "columns",
+ clazz = TableResult.class,
+ args = {String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_NECESSARY,
+ notes = "method test",
+ method = "newrow",
+ clazz = TableResult.class,
+ args = {String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_NECESSARY,
+ notes = "method test",
+ method = "clear",
+ clazz = TableResult.class,
+ args = {}
+ )
+
+ })
+ public void testGet_tableStringStringArrayTableResult() {
+ String args[] = new String[1];
+ String argsFail[] = new String[1];
+ TableResult res = new TableResult();
+ TableResult defaultTableRes = new TableResult();
+ args[0] = "table";
+
+ try {
+ db.get_table("select name from sqlite_master where type = '%q'",
+ argsFail, res);
+ assertEquals(defaultTableRes.toString(), res.toString());
+ } catch (Exception e) {
+ try {
+ db.get_table(
+ "select name from sqlite_master where type = '%q'",
+ args, res);
+ String[] s = (String[]) res.rows.elementAt(0);
+ assertEquals(s[0], DatabaseCreator.SIMPLE_TABLE1);
+ String[] types = res.types;
+ System.out
+ .println("DatabaseTest.testGet_tableStringStringArrayTableResult() "+types.toString());
+ } catch (Exception e2) {
+ fail("Testmethod failed: " + e2.getMessage());
+ e.printStackTrace();
+ }
+ }
+ }
+
+
+ /**
+ * @tests {@link Database#complete(String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "complete",
+ args = {java.lang.String.class}
+ )
+ public void testComplete() {
+ assertFalse(db.complete("create"));
+ assertTrue(db.complete("create table TEST (res double);"));
+ }
+
+ /**
+ * @tests {@link Database#version()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "version",
+ args = {}
+ )
+ public void testVersion() {
+ String version = db.version();
+ if (version != null) {
+ assertTrue(Integer.parseInt(db.version().substring(0,1)) > 0);
+ assertEquals(db.version(), db.version());
+ } else {
+ fail("DB version info missing");
+ }
+
+ }
+
+ /**
+ * @tests {@link Database#dbversion()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "dbversion",
+ args = {}
+ )
+ public void testDbversion() {
+ String verNo = "";
+ try {
+ verNo = db.dbversion();
+ db.close();
+ assertEquals(db.dbversion(),"unknown");
+ db.open(dbFile.getPath(), 0);
+ assertEquals(verNo,db.dbversion());
+ } catch (Exception e) {
+ try {
+ db.open(dbFile.getPath(), 0);
+ } catch (Exception e1) {
+ fail("error in db setup "+e.getMessage());
+ e.printStackTrace();
+ }
+ fail("error in db setup "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ assertTrue(Integer.parseInt(verNo.substring(0, 1))>= 3 );
+
+ }
+
+ /**
+ * @tests {@link Database#create_function(String, int, Function)}
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "create_function",
+ args = {java.lang.String.class, int.class, Function.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "create_function",
+ args = {java.lang.String.class, int.class, Function.class}
+ )
+ })
+ public void testCreate_function() {
+ try {
+ double input = 1.0;
+ db.exec("create table TEST (res double)", null);
+ db.exec("insert into TEST values (" + Double.toString(input) + ")",
+ null);
+ TableResult res = new TableResult();
+ Function sinFunc = (Function) new SinFunc();
+ db.create_function("sin", 1, sinFunc);
+ db.exec("select sin(res) from TEST WHERE res = "
+ + Double.toString(input), res);
+ String row[] = (String[]) res.rows.elementAt(0);
+ String val = row[0];
+ double sinusVal = Double.parseDouble(val);
+ double funcVal = Math.sin(input);
+
+ assertTrue(Math.round(funcVal) == Math.round(sinusVal));
+ } catch (Exception e) {
+ fail("Error happened creating function:" + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @tests {@link Database#create_aggregate(String, int, Function)}
+ */
+ @TestTargets({
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "create_aggregate",
+ args = {java.lang.String.class, int.class, Function.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "step",
+ clazz = Function.class,
+ args = {FunctionContext.class, String[].class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "last_step",
+ clazz = Function.class,
+ args = {FunctionContext.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "function",
+ clazz = Function.class,
+ args = {FunctionContext.class, String[].class}
+ )
+ })
+ public void testCreate_aggregate() {
+ TestTrace t = new TestTrace();
+
+ MockFunction aggFunction = new MockFunction();
+
+ try {
+ db
+ .exec(
+ "create table TEST(id integer, firstname text, lastname text)",
+ null);
+ db.exec("insert into TEST values(3, 'James', 'Bond'); ", null);
+ db.exec("insert into TEST values(4, 'Fiona', 'Apple'); ", null);
+ db.trace((Trace) t);
+ db.create_aggregate("myaggfunc", 1, aggFunction);
+ db.function_type("myaggfunc", Constants.SQLITE_TEXT);
+ db.exec("PRAGMA show_datatypes = on", null);
+
+ assertFalse(aggFunction.functionCalled);
+ assertFalse(aggFunction.stepCalled);
+ assertFalse(aggFunction.lastStepCalled);
+ db.exec("select myaggfunc(TEST.firstname) from TEST", t);
+ assertTrue(aggFunction.stepCalled);
+ assertTrue(aggFunction.lastStepCalled);
+ assertTrue(aggFunction.functionCalled);
+
+ assertEquals("James Fiona ",aggFunction.getAggValue());
+ db.exec("drop table TEST", null);
+ } catch (Exception e) {
+ System.out.println(t.getTrace());
+ fail("Error in test setup: " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ db.create_aggregate("myaggfunc", 0, null);
+ } catch (Throwable e) {
+ assertEquals("null SQLite.Function not allowed",e.getMessage());
+ }
+
+ try {
+ db.create_aggregate("myaggfunc", 0, aggFunction);
+ } catch (Throwable e) {
+ assertEquals("wrong number of arguments to function myaggfunc()",e.getMessage());
+ }
+
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Database#function_type(String, int)}
+ * This method does not make sense
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Method does not make sense: for functions, return type is already set.",
+ method = "function_type",
+ args = {java.lang.String.class, int.class}
+ )
+ public void testFunction_type() throws Exception {
+
+ double input = 1.0;
+ TableResult res = new TableResult();
+ Function sinFunc = (Function) new SinFunc();
+
+ db.exec("PRAGMA show_datatypes = on", null);
+ db.exec("create table TEST (res double)", null);
+ db.exec("insert into TEST values (" + Double.toString(input) + ")",
+ null);
+
+ db.create_function("sin", 1, sinFunc);
+ db.function_type("sin", Constants.SQLITE_NUMERIC);
+ res = db.get_table("select sin(res) from TEST WHERE res = "
+ + Double.toString(input));
+
+ String row[] = (String[]) res.rows.elementAt(0);
+ String val = row[0];
+ assertTrue("double".equalsIgnoreCase(res.types[0]));
+ assertSame(Math.round(Math.sin(input)), Math.round(Double.parseDouble(val)));
+
+ // function determines return type: test that Double type is returned.
+ db.function_type("sin", Constants.SQLITE_BLOB);
+ Stmt s = db.prepare("select sin(res) from TEST WHERE res = ?");
+ s.bind(1,input);
+ s.step();
+
+ res = db.get_table("select sin(res) from TEST WHERE res = "
+ + Double.toString(input));
+ assertTrue("double".equalsIgnoreCase(res.types[0]));
+ row = (String[]) res.rows.elementAt(0);
+ val = row[0];
+ assertSame(Math.round(Math.sin(input)), Math.round(Double.parseDouble(val)));
+
+
+
+
+ }
+
+ /**
+ * @tests {@link Database#last_error()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "last_error",
+ args = {}
+ )
+ public void testLast_error() {
+ assertEquals(db.last_error(), Constants.SQLITE_OK);
+ try {
+ db.exec("create table TEST (res double)",null);
+ db.exec("create table TEST (res double)",null);
+ fail("Error should have happened");
+ } catch (Exception e) {
+ assertEquals(db.last_error(),db.last_error());
+ assertEquals(db.last_error(),Constants.SQLITE_ERROR);
+ }
+
+ }
+
+ /**
+ * @tests {@link Database#set_last_error(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "don't now which other errors may occur from black-box approach.",
+ method = "set_last_error",
+ args = {int.class}
+ )
+ public void testSet_last_error() {
+ assertEquals(db.last_error(), Constants.SQLITE_OK);
+
+ try {
+ db.exec("sel from test;", null);
+ } catch (Exception e) {
+ assertEquals(Constants.SQLITE_ERROR,db.last_error());
+ }
+ }
+
+ /**
+ * @tests {@link Database#error_message()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "error_message",
+ args = {}
+ )
+ public void testError_message() {
+ String statement = "create table TEST (res double)";
+ try {
+ db.exec(statement,null);
+ db.exec(statement,null);
+ fail("DB Error expected");
+ } catch (Exception e) {
+ String dbError = db.error_message();
+ assertTrue(e.getMessage().equals(dbError));
+
+ }
+ }
+
+ /**
+ * @tests {@link Database#error_string(int)}
+ */
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "error_string",
+ args = {int.class}
+ )
+ public void testError_string() {
+ TestTrace t = new TestTrace();
+ assertEquals(db.last_error(), Constants.SQLITE_OK);
+ String errorString = db.error_string(Constants.SQLITE_ERROR);
+ try {
+ db.trace((Trace) t);
+ db.exec("create table TEST (res double)", t);
+ db.exec("create table TEST (res double)", t);
+ } catch (Exception e) {
+ assertEquals(db.last_error(), Constants.SQLITE_ERROR);
+ if (db.is3()) {
+ assertEquals("Unsupported Method (sqlite 3): error_string", db
+ .error_string(db.last_error()), errorString);
+ }
+ }
+ }
+
+ /**
+ * @throws UnsupportedEncodingException
+ * @tests {@link Database#set_encoding(String)}
+ * Method unsupported? -> tests fail
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test fails.",
+ method = "set_encoding",
+ args = {java.lang.String.class}
+ )
+ @KnownFailure("ASCII encoding does not work: a UTF encoded val is returned. Spec is not sufficient. "
+ + "Might be that test impl is wrong or String constructor for the ASCII encoding.")
+ public void testSet_encoding() throws UnsupportedEncodingException {
+ String input = "\u00bfMa\u00f1ana\u003f"; // ?Manana?
+ TableResult res = new TableResult();
+ String refOutput = null;
+ Stmt stat = null;
+
+ // DB setup
+ try {
+ db.exec("create table encodingTest (encoded text DEFAULT NULL);",
+ null);
+ stat = db
+ .prepare("insert into encodingTest(encoded) values(:one);");
+ stat.bind(1, input);
+ stat.step();
+ // stat.close();
+ db.exec("select * from encodingTest;", res);
+ String[] encInput = (String[]) res.rows.elementAt(0);
+ String output = encInput[0];
+ assertEquals(input, output);
+ // db.exec("delete from encodingTest where 1", null);
+ } catch (Exception e1) {
+ fail("Error in test setup: " + e1.getMessage());
+ e1.printStackTrace();
+ }
+
+ // tests for different encoding schemes
+ String[] charsetNames = {"UTF-8", "UTF-16", "UTF-16BE", "UTF-16LE"};
+ for (int i = 0; i < charsetNames.length; i++) {
+ try {
+ byte[] encInput = input.getBytes(charsetNames[i]);
+ db.set_encoding(charsetNames[i]);
+ db.exec("select * from encodingTest;", res);
+ String[] encOutput = (String[]) res.rows.elementAt(0);
+ String inputAsString = new String(encInput,charsetNames[i]);
+ assertEquals(inputAsString, encOutput[0]);
+ } catch (Exception e4) {
+ fail("Error setting the encoding." + e4.getMessage());
+ e4.printStackTrace();
+ } catch (UnsupportedEncodingException e2) {
+ fail(e2.getMessage());
+ e2.printStackTrace();
+ }
+ }
+
+ // Default tests
+ try {
+ db.set_encoding("UTF-16");
+ db.exec("select * from encodingTest;", res);
+ String[] encOutput1 = (String[]) res.rows.elementAt(0);
+ assertEquals("Got "+encOutput1[0]+" as UTF-16",input,encOutput1[0]);
+
+ db.set_encoding("US-ASCII");
+ db.exec("select * from encodingTest;", res);
+ String[] encOutput2 = (String[]) res.rows.elementAt(0);
+ assertEquals(new String(input.getBytes(),"US-ASCII"),encOutput2[0]);
+ } catch (Exception e) {
+ fail("Error setting the encoding." + e.getMessage());
+ e.printStackTrace();
+ }
+
+
+ // DB teardown
+ try {
+ stat.close();
+ db.exec("delete from encodingTest", null);
+ // reset encoding
+ } catch (Exception e3) {
+ fail("Error in teardown of encoding environment");
+ e3.printStackTrace();
+ }
+
+ // Default tests
+ try {
+ db.set_encoding("");
+ fail("invalid input should fail");
+ } catch (Exception e) {
+ //ok
+ }
+
+ }
+
+ /**
+ * Test fails -> implemented correctly?
+ * @tests {@link Database#set_authorizer(Authorizer)}
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test fails.",
+ method = "set_authorizer",
+ args = {Authorizer.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test fails.",
+ method = "authorize",
+ clazz = Authorizer.class,
+ args = {int.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ })
+ @KnownFailure("Callback never made for authorization. "+
+ "Results of private table are returned withouth furhter checks.")
+ public void testSet_authorizer() {
+
+ TableResult resPriv = null;
+ TableResult resPub = null;
+ TableResult emptyTable = new TableResult();
+ String insertPublic = "insert into public_table values(1,2)";
+ String insertPrivate = "insert into private_table values(1,2)";
+ try {
+ // prepare, authorizer is not activated yet
+ db.exec("create table public_table(c1 integer, c2 integer);", null);
+ db.exec("create table private_table(c1 integer, c2 integer);", null);
+ // inserts
+ db.exec(insertPublic, null);
+ db.exec(insertPrivate, null);
+ // selects
+ resPriv = db.get_table("select * from private_table");
+ resPub = db.get_table("select * from public_table");
+
+// db.exec("delete from public_table where 1", null);
+// TableResult emptyPubTable = db.exec("select * from public");
+
+ // set Authorizer (positive case): denies private table
+ AuthorizerCallback cb = new AuthorizerCallback();
+ db.set_authorizer(cb);
+ //select
+
+ db.exec("select * from private_table", cb);
+ assertTrue(cb.wasCalled());
+
+ /*
+ TableResult res = db.get_table("select * from private_table");
+ assertEquals(emptyTable.toString(),res.toString());
+ assertFalse(emptyTable.equals(resPriv));
+
+ res = db.get_table("select * from public_table");
+ assertEquals(resPub,res);
+ */
+ } catch (Exception e) {
+ fail("Error testing authorization: "+e.getMessage());
+ }
+
+ // Try insert
+ try {
+ db.exec(insertPublic, null);
+ fail("authorization failed");
+ } catch (Exception e) {
+ try {
+ db.exec(insertPrivate, null);
+ fail("authorization failed");
+ } catch (Exception e1) {
+ // ok
+ }
+ }
+
+ }
+
+ /**
+ * @tests {@link Database#trace(Trace)}
+ */
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "trace",
+ args = {Trace.class}
+ )
+ public void testTrace() {
+ String stmt = "create table TEST (res double);";
+ TestTrace t = new TestTrace();
+ assertFalse(t.traceCalled);
+ assertEquals(db.last_error(),Constants.SQLITE_OK);
+ try {
+ db.trace((Trace) t);
+ db.exec(stmt,t);
+ assertTrue(t.traceCalled);
+ assertEquals(t.getTrace(),stmt);
+ } catch (Exception e) {
+ fail("Error testing traces: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ db.close();
+ db.exec(stmt,t);
+ fail("Exception Expected");
+ } catch (Exception e) {
+ //ok
+ }
+
+
+ }
+
+ /**
+ * @tests {@link Database#compile(String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "compile",
+ args = {java.lang.String.class}
+ )
+ public void testCompileString() {
+ try {
+ db.compile("select name from sqlite_master;");
+ } catch (Exception e) {
+ fail("Error compiling sql statement " + e.getMessage());
+ e.printStackTrace();
+ }
+ try {
+ db.compile("test");
+ fail("Compiling of inaccurate statement does not fail.");
+ } catch (Exception e) {
+
+ }
+ }
+
+ /**
+ * @tests {@link Database#compile(String, String[])}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "compile",
+ args = {java.lang.String.class, java.lang.String[].class}
+ )
+ public void testCompileStringStringArray() {
+ String args[] = new String[1];
+ args[0] = "table";
+ try {
+ db.compile("select name from sqlite_master where type = '%q';",args);
+ } catch (Exception e) {
+ fail("Error compiling sql statement " + e.getMessage());
+ e.printStackTrace();
+ }
+ try {
+ db.compile("test",null);
+ fail("Compiling of inaccurate statement does not fail.");
+ } catch (Exception e) {
+
+ }
+ }
+
+ /**
+ * @tests {@link Database#prepare(String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "prepare",
+ args = {java.lang.String.class}
+ )
+ public void testPrepare() {
+ Stmt st = null;
+ Stmt st2 = null;
+ // test empty statement
+ try {
+ st = db.prepare("");
+ assertEquals(0, st.bind_parameter_count());
+ st.step();
+ fail("stmt should not be prepared");
+ } catch (Exception e) {
+ assertEquals("stmt already closed", e.getMessage());
+ }
+
+ // test statement with unbound arguments
+ try {
+ st2 = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ assertEquals(3, st2.bind_parameter_count());
+ assertEquals(3, st2.bind_parameter_index(":three"));
+ assertEquals(":two", st2.bind_parameter_name(2));
+ } catch (Exception e) {
+ fail("error in prepare method: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ try {
+ st2.close();
+ } catch (Exception e) {
+ fail("error in prepare method cleanup: " + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ try {
+ db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values(:one,:two,:three,:four);");
+ } catch (Exception e) {
+ assertEquals("table " + DatabaseCreator.SIMPLE_TABLE1
+ + " has 3 columns but 4 values were supplied", e
+ .getMessage());
+ }
+
+ try {
+ db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values(5, '10, 20);");
+ } catch (Exception e) {
+ assertEquals("unrecognized token: \"'10, 20);\"", e.getMessage());
+ }
+
+ try {
+ db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values(5, 10 20);");
+ } catch (Exception e) {
+ assertEquals("near \"20\": syntax error", e.getMessage());
+ }
+
+ }
+
+ /**
+ * @throws Exception
+ * @throws java.lang.Exception
+ * @tests {@link Database#open_blob(String, String, String, long, boolean)}
+ * unsupported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "open_blob",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, long.class, boolean.class}
+ )
+ @KnownFailure("not supported")
+ public void testOpen_blob() throws Exception, java.lang.Exception {
+ Stmt statement2;
+ Blob blobInput = new Blob();
+
+
+ // Create test input Blob
+ InputStream inStream = null;
+ byte[] in = {(byte) 1, (byte) 2, (byte) 3, (byte) 4};
+
+ // setup test input
+ db.exec("create table TEST (res blob)",null);
+ inStream = Class.forName(this.getClass().getName()).getResourceAsStream("/blob.c");
+ assertNotNull(inStream);
+
+
+ // insert byte array in db
+ try {
+ statement2 = db.prepare("insert into TEST(res) values (?)");
+ statement2.bind(1, in);
+ statement2.step();
+ statement2.close();
+ } catch (Exception e) {
+ fail("Error happened inserting blob" + e.getMessage());
+ e.printStackTrace();
+ }
+
+ // read from db
+ byte[] output = null;
+ Blob blob;
+
+ blob = db.open_blob(dbFile.getPath(), "TEST", "res", 1, true);
+ if (blob == null) {
+ fail("Blob could not be retrieved");
+ }
+ //read from blob and compare values (positive case)
+ InputStream is = blob.getInputStream();
+
+ int i = 0;
+ int outByte = 0;
+ byte[] out = new byte[4];
+ while ((outByte = is.read()) > -1) {
+ out[i] = (byte) outByte;
+ i++;
+ }
+ is.close();
+
+ blob.close();
+
+ assertTrue(Arrays.equals(in, out));
+
+ //read from blob and compare values (default blob)
+ db.exec("insert into TEST values(zeroblob(128))", null);
+ Blob blob2 = db.open_blob(dbFile.getPath(), "TEST", "res", 2, true);
+ is = blob2.getInputStream();
+ for (i = 0; i < 128; i++) {
+ assertEquals(0, is.read());
+ }
+ is.close();
+ }
+
+ /**
+ * @tests {@link Database#is3()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "is3",
+ args = {}
+ )
+ public void testIs3() {
+ int ver = Integer.parseInt(db.version().substring(0,1));
+ if (db.is3()) {
+ assertTrue( ver == 3);
+ } else {
+ assertTrue(ver != 3);
+ }
+ }
+
+ /**
+ * @tests {@link Database#progress_handler(int, ProgressHandler)}
+ */
+ @TestTargets ({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "progress_handler",
+ args = {int.class, ProgressHandler.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "progress",
+ clazz = ProgressHandler.class,
+ args = {}
+ )
+ })
+ public void testProgress_handler() {
+ int inputVal = 3;
+ TestProgressHandler prog = new TestProgressHandler();
+ try {
+ db.exec("create table TEST5(id integer, firstname text, lastname text)",null);
+ Vm vm = db.compile("select * from TEST5; "
+ + "insert into TEST5 values(3, 'James', 'Bond'); "
+ + "delete from TEST5 where id = 3; "
+ + "select * from TEST5");
+ int stmt = 0;
+ do {
+ ++stmt;
+ if (stmt > inputVal) {
+ db.progress_handler(inputVal, prog);
+ } else {
+ assertEquals(0, prog.getCounts());
+ }
+ while (vm.step(prog)) {
+ }
+ } while (vm.compile());
+ assertEquals(inputVal,prog.getCounts());
+ } catch (Exception e) {
+ fail("Error in test setup: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ // Boundary value test
+ inputVal = 0;
+ TestProgressHandler progBoundary = new TestProgressHandler();
+ db.progress_handler(inputVal, progBoundary);
+ try {
+ Vm vm2 = db.compile("select * from TEST5; "
+ + "insert into TEST5 values(3, 'James', 'Bond'); "
+ + "delete from TEST5 where id = 3; "
+ + "select * from TEST5");
+ do {
+ vm2.step(progBoundary);
+ } while (vm2.compile());
+ assertEquals(inputVal, progBoundary.getCounts());
+ }catch (Exception e) {
+ fail("Error in test setup: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ db.exec("drop table TEST5",null);
+ } catch (Exception e) {
+ System.out.println(e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+
+
+ class SinFunc implements Function {
+
+
+ public void function(FunctionContext fc, String args[]) {
+ Double d = new Double(args[0]);
+ fc.set_result(Math.sin(d.doubleValue()));
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ @TestTargetClass(Trace.class)
+ class TestTrace implements Trace,Callback {
+
+ private StringBuffer buf = new StringBuffer();
+
+ public boolean traceCalled = false;
+
+ public String getTrace() {
+ return buf.toString();
+ }
+
+ public void trace(String stmt) {
+ traceCalled = true;
+ buf.append(stmt);
+ }
+
+ public void columns(String[] coldata) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean newrow(String[] rowdata) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void types(String[] types) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ @TestTargetClass(Authorizer.class)
+ class AuthorizerCallback implements Authorizer,Callback {
+ private boolean isAuthorizing = false;
+
+ public boolean wasCalled() {
+ return isAuthorizing;
+ }
+
+ public int authorize(int action, String arg1, String arg2, String arg3,
+ String arg4) {
+ Logger.global.info("DB authorization callback "+action+" "+arg1+" "+arg2+" "+arg3+" "+arg4+" ");
+ this.isAuthorizing = true;
+ if (action != Constants.SQLITE_SELECT || arg1.contains("private_table")) {
+ return Constants.SQLITE_DENY;
+ } else {
+ return Constants.SQLITE_OK;
+ }
+ }
+
+ public void columns(String[] coldata) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean newrow(String[] rowdata) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void types(String[] types) {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+ class TestBusyHandler implements BusyHandler, Callback {
+
+ public boolean busy(String table, int count) {
+ System.out.println("BUSY!");
+ return true;
+ }
+
+ public void columns(String[] coldata) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean newrow(String[] rowdata) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void types(String[] types) {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+ class TestProgressHandler implements ProgressHandler,Callback {
+
+ private boolean progressed = false;
+
+ private int counter = 0;
+
+ public boolean isProgressed() {
+ return progressed;
+ }
+
+ public int getCounts() {
+ return counter;
+ }
+
+ public boolean progress() {
+ this.progressed = true;
+ counter++;
+ return true;
+ }
+
+ public void columns(String[] coldata) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public boolean newrow(String[] rowdata) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ public void types(String[] types) {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+// class dbBusyThread implements Runnable {
+//
+// String dbName = "sqliteTest.db";
+//
+// Thread runner;
+// public dbBusyThread() {
+// }
+// public dbBusyThread(String threadName) {
+// runner = new Thread(this, threadName); // (1) Create a new thread.
+// System.out.println(runner.getName());
+// runner.start(); // (2) Start the thread.
+// }
+// public void run() {
+// insert(3000);
+// }
+//
+// public void runNoDelay() {
+// insert(0);
+// }
+//
+// synchronized private void insert(long delay) {
+// Database db2 = new Database();
+// try {
+// db2.open(dbName, 0);
+// db2.exec("insert into TEST5 values (4,'Anglina','Jolie');",
+// null);
+// wait(delay);
+// } catch (Exception e) {
+// System.out.println("Error in Thread " + e.getMessage());
+// e.printStackTrace();
+// } catch (InterruptedException e2) {
+// System.out.println("Error in Thread " + e2.getMessage());
+// e2.printStackTrace();
+// } finally {
+// try {
+// db2.close();
+// } catch (Exception e) {
+// // We do not handle this case
+// }
+// }
+// }
+// }
+
+ /**
+ * This method creates a Runnable that executes insert operation for the
+ * first table
+ */
+ private static Runnable createTask2Interrupt(final int id,
+ final String dbName, final ErrorTracker errorTracker) {
+ return new Runnable() {
+ public void run() {
+ Database db = new Database();
+ try {
+ String value = DatabaseCreator.defaultString + id;
+
+ db.open(dbName, 0);
+ String insertQuery = "INSERT INTO "
+ + DatabaseCreator.TEST_TABLE1
+ + " (id, field1, field2, field3) VALUES(" + id
+ + ", '" + value + "', " + id + ", " + id + ")";
+ db.exec(insertQuery, null);
+ } catch (Exception e) {
+ errorTracker.registerException(this, e);
+ try {
+ db.interrupt();
+ db.exec("DELETE FROM " + DatabaseCreator.SIMPLE_TABLE1
+ + " WHERE id=" + id, null);
+ } catch (Exception e1) {
+ errorTracker.registerException(this, e1);
+ }
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that executes delete operation for the
+ * first table
+ */
+ private static Runnable createTask1(final int id,final String dbName, final ErrorTracker errorTracker) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Database db = new Database();
+ db.open(dbName, 0);
+ db.exec("DELETE FROM "
+ + DatabaseCreator.SIMPLE_TABLE1 + " WHERE id=" + id,null);
+ } catch (Exception e) {
+ errorTracker.registerException(this, e);
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that executes insert operation for the
+ * first table
+ */
+ private static Runnable createTask2(final int id, final String dbName, final ErrorTracker errorTracker ) {
+ return new Runnable() {
+ public void run() {
+ try {
+ String value = DatabaseCreator.defaultString + id;
+ Database db = new Database();
+ db.open(dbName, 0);
+ String insertQuery = "INSERT INTO "
+ + DatabaseCreator.TEST_TABLE1
+ + " (id, field1, field2, field3) VALUES(" + id
+ + ", '" + value + "', " + id + ", " + id + ")";
+ db.exec(insertQuery,null);
+ } catch (Exception e) {
+ errorTracker.registerException(this, e);
+
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that executes update operation for the one
+ * record of the first table
+ */
+ private static Runnable createTask3(final int oldID, final String dbName,
+ final int newID, final ErrorTracker errorTracker) {
+ return new Runnable() {
+ public void run() {
+ Database db = new Database();
+ try {
+ db.open(dbName, 0);
+ String value = DatabaseCreator.defaultString + newID;
+ String updateQuery = "UPDATE "
+ + DatabaseCreator.TEST_TABLE1 + " SET id=" + newID
+ + ", field1='" + value + "', field2=" + newID
+ + ", field3=" + newID + " WHERE id=" + oldID;
+ db.exec(updateQuery, null);
+ } catch (Exception e) {
+ errorTracker.registerException(this, e);
+ }
+ }
+ };
+ }
+
+ private class ErrorTracker {
+ private List errors = new ArrayList();
+
+ public void registerException(Runnable runnable, Exception e) {
+ System.out.println("Registered: "+e.getMessage());
+ errors.add(e.getMessage());
+ }
+
+ public List getErrors() {
+ return errors;
+ }
+
+ public void reset() {
+ errors.clear();
+ }
+ }
+
+}
+
diff --git a/sql/src/test/java/tests/SQLite/ExceptionTest.java b/sql/src/test/java/tests/SQLite/ExceptionTest.java
new file mode 100644
index 0000000..fe86e8f
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/ExceptionTest.java
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import SQLite.Database;
+import SQLite.Exception;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+@TestTargetClass(SQLite.Exception.class)
+public class ExceptionTest extends SQLiteTest {
+
+ private Database db = null;
+
+ public void setUp() throws java.lang.Exception {
+ super.setUp();
+ db = new Database();
+ }
+
+ public void tearDown() {
+ super.tearDown();
+ }
+
+ /**
+ * @tests {@link Exception#Exception(String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "constructor test",
+ method = "Exception",
+ args = {java.lang.String.class}
+ )
+ public void testException() {
+ try {
+ db.open(dbFile.getName(), 0);
+ } catch (Exception e) {
+ assertNotNull(e);
+ assertNotNull(e.getMessage());
+ }
+ }
+
+}
diff --git a/sql/src/test/java/tests/SQLite/FunctionContextTest.java b/sql/src/test/java/tests/SQLite/FunctionContextTest.java
new file mode 100644
index 0000000..1bb5cf5
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/FunctionContextTest.java
@@ -0,0 +1,452 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import SQLite.Database;
+import SQLite.Exception;
+import SQLite.Function;
+import SQLite.FunctionContext;
+import SQLite.Stmt;
+import SQLite.TableResult;
+import dalvik.annotation.AndroidOnly;
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import java.io.UnsupportedEncodingException;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import tests.support.DatabaseCreator;
+
+@TestTargetClass(FunctionContext.class)
+public class FunctionContextTest extends SQLiteTest {
+
+ private Database db = null;
+
+ public void setUp() throws java.lang.Exception {
+ Statement st = null;
+ super.setUp();
+ db = new Database();
+ db.open(dbFile.getPath(), 0);
+ st = conn.createStatement();
+ st.execute(DatabaseCreator.CREATE_TABLE2);
+ st.execute(DatabaseCreator.CREATE_TABLE_SIMPLE1);
+ st.close();
+ }
+
+ /* (non-Javadoc)
+ * @see junit.framework.TestCase#tearDown()
+ */
+ public void tearDown() {
+ super.tearDown();
+ }
+
+ /**
+ * Test method for {@link SQLite.FunctionContext#set_result(java.lang.String)}.
+ * @throws Exception
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "indirectly tested invoking function",
+ method = "set_result",
+ args = {java.lang.String.class}
+ )
+ public void testSet_resultString() throws Exception {
+ TestFCString testString = new TestFCString();
+ db.exec("insert into " + DatabaseCreator.TEST_TABLE2
+ + " (ftext) values ('TestInput')", null);
+ db.create_function("test", 1, testString);
+ TableResult res = db.get_table("select test(ftext) from "
+ + DatabaseCreator.TEST_TABLE2);
+ String row[] = (String[]) res.rows.elementAt(0);
+ String val = row[0];
+
+ assertEquals("TestInput", val);
+ }
+
+ /**
+ * Test method for {@link SQLite.FunctionContext#set_result(int)}.
+ * @throws Exception
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "method test",
+ method = "set_result",
+ args = {int.class}
+ )
+ public void testSet_resultInt() throws Exception {
+ TestFCInt testInt = new TestFCInt();
+ db.exec("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (1,'" + testInt.intVal + "',3)", null);
+ db.create_function("testInt", 1, testInt);
+ TableResult res = db.get_table("select testInt(speed) from "
+ + DatabaseCreator.SIMPLE_TABLE1);
+ String row[] = (String[]) res.rows.elementAt(0);
+ String val = row[0];
+
+ assertEquals(testInt.intVal, Integer.parseInt(val));
+ }
+
+ /**
+ * Test method for {@link SQLite.FunctionContext#set_result(double)}.
+ * @throws Exception
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "indirectly tested",
+ method = "set_result",
+ args = {double.class}
+ )
+ public void testSet_resultDouble() throws Exception {
+ SinFunc testD = new SinFunc();
+ db.exec("insert into " + DatabaseCreator.TEST_TABLE2
+ + " (fdouble) values (" + testD.testDouble + ")", null);
+ db.create_function("testDouble", 1, testD);
+ TableResult res = db.get_table("select testDouble(fdouble) from "
+ + DatabaseCreator.TEST_TABLE2);
+ String row[] = (String[]) res.rows.elementAt(0);
+ String val = row[0];
+
+ assertEquals(testD.testDouble, Double.parseDouble(val));
+
+ assertTrue(testD.functionCalled);
+ }
+
+ /**
+ * Test method for {@link SQLite.FunctionContext#set_error(java.lang.String)}.
+ * @throws Exception
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "set_error",
+ args = {java.lang.String.class}
+ )
+ public void testSet_error() throws Exception {
+ TestFCError testError = new TestFCError();
+ SinFunc testD = new SinFunc();
+ db.exec("insert into " + DatabaseCreator.TEST_TABLE2
+ + " (fdouble) values (" + testD.testDouble + ")", null);
+ db.create_function("testError", 1, testError);
+
+ try {
+ TableResult res = db.get_table("select testError(fdouble) from "
+ + DatabaseCreator.TEST_TABLE2);
+ fail("Should get Exception");
+ } catch (Exception e) {
+ assertEquals("error in step", e.getMessage());
+ }
+
+ assertFalse(testD.functionCalled);
+ }
+
+ /**
+ * Test method for {@link SQLite.FunctionContext#set_result(byte[])}.
+ * @throws Exception
+ * @throws UnsupportedEncodingException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "set_result",
+ args = {byte[].class}
+ )
+ public void testSet_resultByteArray() throws Exception, UnsupportedEncodingException {
+ Stmt st = null;
+ TestFCByteArray testBinArrayFnc = new TestFCByteArray();
+ String expected = "";
+ expected = "X'" + getHexString(testBinArrayFnc.byteVal) + "'";
+
+ // setup
+ db.exec("create table testBinaryData (binVal BINARY) ;", null);
+
+ try {
+ st = db.prepare("insert into testBinaryData values (?)");
+ st.bind(1, testBinArrayFnc.byteVal);
+ st.step();
+
+
+ db.create_function("testBinArray", 1, testBinArrayFnc);
+ TableResult res = db
+ .get_table("select testBinArray(binVal) from testBinaryData");
+
+ String row[] = (String[]) res.rows.elementAt(0);
+ String val = row[0];
+
+ assertTrue(expected.equalsIgnoreCase(val));
+
+ assertTrue(testBinArrayFnc.functionCalled);
+
+ } finally {
+ //teardown
+ db.exec("drop table testBinaryData;", null);
+ }
+ }
+
+ /**
+ * Test method for {@link SQLite.FunctionContext#set_result_zeroblob(int)}.
+ * @throws Exception
+ * @throws UnsupportedEncodingException
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "set_result_zeroblob",
+ args = {int.class}
+ )
+ public void testSet_result_zeroblob() throws Exception,
+ UnsupportedEncodingException {
+ Stmt st = null;
+ TestFCZeroBlob testZeroBlobFnc = new TestFCZeroBlob();
+ byte[] byteVal = {(byte) 1, (byte) 2, (byte) 3};
+
+
+ // setup
+ db.exec("create table testBinaryData (binVal BINARY) ;", null);
+
+ try {
+ st = db.prepare("insert into testBinaryData values (?)");
+ st.bind(1, byteVal);
+ st.step();
+
+
+ db.create_function("testZeroBlob", 0, testZeroBlobFnc);
+ TableResult res = db
+ .get_table("select testZeroBlob() from testBinaryData");
+ TableResult res2 = db.get_table("select zeroblob("
+ + testZeroBlobFnc.numBytes + ") from testBinaryData");
+
+ String row[] = (String[]) res.rows.elementAt(0);
+ String val = row[0];
+
+ assertNotNull(val);
+
+ assertEquals(((String[]) res2.rows.elementAt(0))[0], val);
+ assertTrue(testZeroBlobFnc.functionCalled);
+
+ } finally {
+ // teardown
+ db.exec("drop table if exists testBinaryData;", null);
+ }
+ }
+
+ /**
+ * Test method for {@link SQLite.FunctionContext#count()}.
+ * @throws SQLException
+ * @throws Exception
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "count",
+ args = {}
+ )
+ @AndroidOnly("Test Method results in a segmentation fault.")
+ public void testCount() throws SQLException, Exception {
+ TestFCCount countTest = new TestFCCount();
+ int inputCount = 10;
+
+ assertFalse(countTest.functionCalled);
+
+ DatabaseCreator.fillTestTable2(conn, inputCount);
+ db.create_function("testCount", 0, countTest);
+ // the invokation of testCount leads to a Segmentation fault
+ /*
+ TableResult res = db
+ .get_table("select testCount() from "+DatabaseCreator.TEST_TABLE2);
+
+ String row[] = (String[]) res.rows.elementAt(0);
+ String val = row[0];
+
+ assertTrue(countTest.functionCalled);
+ assertEquals(inputCount,Integer.parseInt(val));
+ */
+
+ }
+
+ class TestFCError implements Function {
+ public boolean functionCalled = false;
+ public String errorMsg = "FunctionError";
+
+ public void function(FunctionContext fc, String args[]) {
+ functionCalled = true;
+ fc.set_error(errorMsg);
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ class TestFCCount implements Function {
+ public boolean functionCalled = false;
+ public int noOfRows = 0;
+
+ public void function(FunctionContext fc, String args[]) {
+ functionCalled = true;
+ noOfRows = fc.count();
+ fc.set_result(noOfRows);
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ class TestFCZeroBlob implements Function {
+ public int numBytes = 16;
+ public boolean functionCalled = false;
+
+ public void function(FunctionContext fc, String args[]) {
+ functionCalled = true;
+ fc.set_result_zeroblob(numBytes);
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ class TestFCString implements Function {
+ public String testString = "TestString";
+ public boolean functionCalled;
+
+ public void function(FunctionContext fc, String args[]) {
+ assertNotNull(args);
+ functionCalled = true;
+ fc.set_result(args[0]);
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ class TestFCInt implements Function {
+ public int intVal = Integer.MAX_VALUE;
+ public boolean functionCalled;
+
+ public void function(FunctionContext fc, String args[]) {
+ assertNotNull(args);
+ functionCalled = true;
+ fc.set_result(Integer.parseInt(args[0]));
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ class TestFCByteArray implements Function {
+ public byte[] byteVal = {(byte) 1, (byte) 2, (byte) 3};
+ public boolean functionCalled;
+
+ public void function(FunctionContext fc, String args[]) {
+ assertNotNull(args);
+ functionCalled = true;
+ fc.set_result(args[0].getBytes());
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ class SinFunc implements Function {
+
+ public Double testDouble = 3.0;
+ public boolean functionCalled = false;
+
+ public void function(FunctionContext fc, String args[]) {
+ Double d = new Double(args[0]);
+ functionCalled = true;
+ fc.set_result(d.doubleValue());
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+ }
+
+ static final byte[] HEX_CHAR_TABLE = {
+ (byte)'0', (byte)'1', (byte)'2', (byte)'3',
+ (byte)'4', (byte)'5', (byte)'6', (byte)'7',
+ (byte)'8', (byte)'9', (byte)'a', (byte)'b',
+ (byte)'c', (byte)'d', (byte)'e', (byte)'f'
+ };
+
+ public static String getHexString(byte[] raw)
+ throws UnsupportedEncodingException {
+ byte[] hex = new byte[2 * raw.length];
+ int index = 0;
+
+ for (byte b : raw) {
+ int v = b & 0xFF;
+ hex[index++] = HEX_CHAR_TABLE[v >>> 4];
+ hex[index++] = HEX_CHAR_TABLE[v & 0xF];
+ }
+ return new String(hex, "ASCII");
+ }
+
+}
diff --git a/sql/src/test/java/tests/SQLite/JDBCDriverFunctionalTest.java b/sql/src/test/java/tests/SQLite/JDBCDriverFunctionalTest.java
new file mode 100644
index 0000000..ed2c0b3
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/JDBCDriverFunctionalTest.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import SQLite.Exception;
+import SQLite.JDBCDriver;
+import dalvik.annotation.TestTargetClass;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+
+/**
+ * Tests the SQLite.JDBCDriver.
+ */
+@TestTargetClass(JDBCDriver.class)
+public class JDBCDriverFunctionalTest extends AbstractSqlTest {
+
+
+
+ /**
+ * The SQLite db file.
+ */
+ private File dbFile = null;
+
+ private String connectionURL = "empty";
+
+ /**
+ * Sets up an unit test by loading the SQLite.JDBCDriver, getting two
+ * connections and calling the setUp method of the super class.
+ * @throws Exception
+ * @throws IllegalAccessException
+ * @throws InstantiationException
+ * @throws Exception
+ * @throws Exception
+ * @throws Exception
+ * @throws Exception
+ * @throws Exception
+ */
+ @Override
+ public void setUp() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException, Exception { // the Exception class needs to be fully
+ // qualified since there is an Exception
+ // class in the SQLite package.
+
+ super.setUp();
+ }
+
+ /**
+ * Tears down an unit test by calling the tearDown method of the super class
+ * and deleting the SQLite test db file.
+ */
+ @Override
+ protected void tearDown() throws SQLException {
+ super.tearDown();
+ dbFile.delete();
+ }
+
+
+ @Override
+ protected String getConnectionURL() {
+ if (connectionURL.equals("empty")) {
+ String tmp = System.getProperty("java.io.tmpdir");
+ File tmpDir = new File(tmp);
+ if (tmpDir.isDirectory()) {
+ try {
+ dbFile = File.createTempFile("JDBCDriverFunctionalTest",
+ ".db", tmpDir);
+ } catch (IOException e) {
+ System.err.println("error creating temporary DB file.");
+ }
+ dbFile.deleteOnExit();
+ } else {
+ System.err.println("java.io.tmpdir does not exist");
+ }
+
+ connectionURL = "jdbc:sqlite:/" + dbFile.getPath();
+
+ }
+
+ return connectionURL;
+ }
+
+ @Override
+ protected String getDriverClassName() {
+ return "SQLite.JDBCDriver";
+ }
+
+ @Override
+ protected int getTransactionIsolation() {
+ return Connection.TRANSACTION_SERIALIZABLE;
+ }
+
+
+}
diff --git a/sql/src/test/java/tests/SQLite/JDBCDriverTest.java b/sql/src/test/java/tests/SQLite/JDBCDriverTest.java
new file mode 100644
index 0000000..c6fd677
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/JDBCDriverTest.java
@@ -0,0 +1,272 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import SQLite.Exception;
+import SQLite.JDBCDriver;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargets;
+
+import java.sql.Connection;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.DriverPropertyInfo;
+import java.sql.SQLException;
+
+
+@TestTargetClass(JDBCDriver.class)
+public class JDBCDriverTest extends JDBCDriverFunctionalTest {
+
+ /**
+ * The SQLite db file.
+ */
+ private JDBCDriver jDriver;
+
+ private Driver returnedDriver;
+
+ public void setUp() throws ClassNotFoundException, SQLException, InstantiationException, IllegalAccessException, Exception {
+
+ try {
+ super.setUp();
+ returnedDriver = DriverManager.getDriver(getConnectionURL());
+ if (returnedDriver instanceof JDBCDriver) {
+ this.jDriver = (JDBCDriver) returnedDriver;
+ }
+ } catch (SQLException e) {
+ System.out.println("Cannot get driver");
+ e.printStackTrace();
+ } catch (Exception e) {
+ System.out.println("DB Setup failed");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @tests JDBCDriver#JDBCDriver()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "constructor test",
+ method = "JDBCDriver",
+ args = {}
+ )
+ public void testJDBCDriver() {
+ assertTrue(returnedDriver instanceof JDBCDriver);
+ }
+
+ /**
+ * @tests JDBCDriver#acceptsURL(String)
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "constructor test",
+ method = "acceptsURL",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "constructor test",
+ // we have to list the Driver target explicitly, since SQLite
+ // is not part of the target packages
+ clazz = Driver.class,
+ method = "acceptsURL",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testAcceptsURL() {
+ try {
+ if (this.jDriver != null) {
+ assertTrue(jDriver.acceptsURL(getConnectionURL()));
+ } else {
+ fail("no Driver available");
+ }
+ } catch (SQLException e) {
+ fail("Driver does not accept URL");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @tests JDBCDriver#connect(String, java.util.Properties)
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "connect",
+ args = {java.lang.String.class, java.util.Properties.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ // we have to list the Driver target explicitly, since SQLite
+ // is not part of the target packages
+ clazz = Driver.class,
+ notes = "method test",
+ method = "connect",
+ args = {java.lang.String.class, java.util.Properties.class}
+ )
+ })
+ public void testConnect() {
+ try {
+ if (this.jDriver != null) {
+ Connection c = jDriver.connect(getConnectionURL(), null);
+ assertFalse(c.isClosed());
+ DriverManager.getConnection(getConnectionURL());
+ } else {
+ fail("no Driver available");
+ }
+ } catch (SQLException e) {
+ fail("Driver does not connect");
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @tests JDBCDriver#getMajorVersion()
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "getMajorVersion",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ // we have to list the Driver target explicitly, since SQLite
+ // is not part of the target packages
+ clazz = Driver.class,
+ notes = "method test",
+ method = "getMajorVersion",
+ args = {}
+ )
+ })
+ public void testGetMajorVersion() {
+ if (this.jDriver != null) {
+ assertTrue(jDriver.getMajorVersion() > 0);
+ } else {
+ fail("no Driver available");
+ }
+ }
+
+ /**
+ * @tests JDBCDriver#getMinorVersion()
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "getMinorVersion",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ // we have to list the Driver target explicitly, since SQLite
+ // is not part of the target packages
+ clazz = Driver.class,
+ method = "getMinorVersion",
+ args = {}
+ )
+ })
+ public void testGetMinorVersion() {
+ if (this.jDriver != null) {
+ assertTrue(jDriver.getMinorVersion() > 0);
+ } else {
+ fail("no version information available");
+ }
+ }
+
+ /**
+ * @tests JDBCDriver#getPropertyInfo(String, java.util.Properties)
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "getPropertyInfo",
+ args = {java.lang.String.class, java.util.Properties.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ // we have to list the Driver target explicitly, since SQLite
+ // is not part of the target packages
+ clazz = Driver.class,
+ method = "getPropertyInfo",
+ args = {java.lang.String.class, java.util.Properties.class}
+ )
+ })
+ public void testGetPropertyInfo() {
+ DriverPropertyInfo[] info = null;
+ try {
+ if (this.jDriver != null) {
+ info = jDriver.getPropertyInfo(getConnectionURL(), null);
+ assertNotNull(info);
+ assertTrue(info.length > 0);
+ } else {
+ fail("no Driver available");
+ }
+ } catch (SQLException e) {
+ fail("Driver property details not available");
+ e.printStackTrace();
+ }
+
+ assertNotNull(info);
+
+ }
+
+ /**
+ * @tests JDBCDriver#jdbcCompliant()
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "jdbcCompliant",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ // we have to list the Driver target explicitly, since SQLite
+ // is not part of the target packages
+ clazz = Driver.class,
+ notes = "method test",
+ method = "jdbcCompliant",
+ args = {}
+ )
+ })
+ public void testJdbcCompliant() {
+ if (this.jDriver != null) {
+ assertFalse(jDriver.jdbcCompliant());
+ } else {
+ fail("no version information available");
+ }
+ }
+ /**
+ * Tears down an unit test by calling the tearDown method of the super class
+ * and deleting the SQLite test db file.
+ */
+ @Override
+ protected void tearDown() throws SQLException {
+ super.tearDown();
+ }
+
+}
diff --git a/sql/src/test/java/tests/SQLite/SQLiteTest.java b/sql/src/test/java/tests/SQLite/SQLiteTest.java
new file mode 100644
index 0000000..0463dcb
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/SQLiteTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import junit.framework.TestCase;
+
+import java.io.File;
+import java.io.IOException;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.logging.Logger;
+
+public class SQLiteTest extends TestCase {
+ public static Connection conn;
+ public static File dbFile = null;
+
+ public void setUp() throws Exception {
+ String tmp = System.getProperty("java.io.tmpdir");
+ File tmpDir = new File(tmp);
+ try {
+ if (tmpDir.isDirectory()) {
+ dbFile = File.createTempFile("sqliteTest", ".db", tmpDir);
+ dbFile.deleteOnExit();
+ } else {
+ System.out.println("ctsdir does not exist");
+ }
+
+ Class.forName("SQLite.JDBCDriver").newInstance();
+
+ if (!dbFile.exists()) {
+ Logger.global.severe("DB file could not be created. Tests can not be executed.");
+ } else {
+ conn = DriverManager.getConnection("jdbc:sqlite:/"
+ + dbFile.getPath());
+ }
+ assertNotNull("Error creating connection",conn);
+ } catch (IOException e) {
+ System.out.println("Problem creating test file in " + tmp);
+ } catch (SQLException e) {
+ // TODO Auto-generated catch block
+ fail("Exception: " + e.toString());
+ } catch (java.lang.Exception e) {
+ fail("Exception: " + e.toString());
+ }
+
+ }
+
+ public void tearDown() {
+ try {
+ if (!conn.isClosed()) {
+ conn.close();
+ }
+ } catch (SQLException e) {
+ fail("Couldn't close Connection: " + e.getMessage());
+ }
+
+ }
+
+}
diff --git a/sql/src/test/java/tests/SQLite/ShellTest.java b/sql/src/test/java/tests/SQLite/ShellTest.java
new file mode 100644
index 0000000..208341c
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/ShellTest.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import SQLite.Shell;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+@TestTargetClass(Shell.class)
+public class ShellTest extends TestCase {
+
+ /**
+ * Test method for {@link SQLite.Shell#Shell(java.io.PrintWriter, java.io.PrintWriter)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "Shell",
+ args = {PrintWriter.class, PrintWriter.class}
+ )
+ public void testShellPrintWriterPrintWriter() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link SQLite.Shell#Shell(java.io.PrintStream, java.io.PrintStream)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "Shell",
+ args = {PrintStream.class, PrintStream.class}
+ )
+ public void testShellPrintStreamPrintStream() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link SQLite.Shell#clone()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "clone",
+ args = {}
+ )
+ public void testClone() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link SQLite.Shell#sql_quote_dbl(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "sql_quote_dbl",
+ args = {String.class}
+ )
+ public void testSql_quote_dbl() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link SQLite.Shell#sql_quote(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "sql_quote",
+ args = {String.class}
+ )
+ public void testSql_quote() {
+ fail("Not yet implemented");
+ }
+
+
+ /**
+ * Test method for {@link SQLite.Shell#columns(java.lang.String[])}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "columns",
+ args = {String[].class}
+ )
+ public void testColumns() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link SQLite.Shell#types(java.lang.String[])}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "types",
+ args = {String[].class}
+ )
+ public void testTypes() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link SQLite.Shell#newrow(java.lang.String[])}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "newrow",
+ args = {String[].class}
+ )
+ public void testNewrow() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "main",
+ args = {String[].class}
+ )
+ public void testMain() {
+
+ }
+
+}
diff --git a/sql/src/test/java/tests/SQLite/StmtTest.java b/sql/src/test/java/tests/SQLite/StmtTest.java
new file mode 100644
index 0000000..20f8221
--- /dev/null
+++ b/sql/src/test/java/tests/SQLite/StmtTest.java
@@ -0,0 +1,1271 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.SQLite;
+
+import SQLite.Constants;
+import SQLite.Database;
+import SQLite.Exception;
+import SQLite.Stmt;
+import SQLite.TableResult;
+import dalvik.annotation.AndroidOnly;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+@TestTargetClass(Stmt.class)
+public class StmtTest extends SQLiteTest {
+
+ private static Database db = null;
+
+ private static Stmt st = null;
+
+ private static final String createAllTypes =
+ "create table type (" +
+
+ " BoolVal BOOLEAN," + " IntVal INT," + " LongVal LONG,"
+ + " Bint BIGINT," + " Tint TINYINT," + " Sint SMALLINT,"
+ + " Mint MEDIUMINT, " +
+
+ " IntegerVal INTEGER, " + " RealVal REAL, "
+ + " DoubleVal DOUBLE, " + " FloatVal FLOAT, "
+ + " DecVal DECIMAL, " +
+
+ " NumVal NUMERIC, " + " charStr CHAR(20), "
+ + " dateVal DATE, " + " timeVal TIME, " + " TS TIMESTAMP, "
+ +
+
+ " DT DATETIME, " + " TBlob TINYBLOB, " + " BlobVal BLOB, "
+ + " MBlob MEDIUMBLOB, " + " LBlob LONGBLOB, " +
+
+ " TText TINYTEXT, " + " TextVal TEXT, "
+ + " MText MEDIUMTEXT, " + " LText LONGTEXT, " +
+
+ " MaxLongVal BIGINT, MinLongVal BIGINT, "+
+
+ " validURL URL, invalidURL URL "+
+
+ ");";
+
+ static final String insertAllTypes =
+ "insert into type (BoolVal, IntVal, LongVal, Bint, Tint, Sint, Mint,"
+ + "IntegerVal, RealVal, DoubleVal, FloatVal, DecVal,"
+ + "NumVal, charStr, dateVal, timeVal, TS,"
+ + "DT, TBlob, BlobVal, MBlob, LBlob,"
+ + "TText, TextVal, MText, LText, MaxLongVal, MinLongVal,"
+ + " validURL, invalidURL"
+ + ") "
+ + "values (1, -1, 22, 2, 33,"
+ + "3, 1, 2, 3.9, 23.2, 33.3, 44,"
+ + "5, 'test string', '1799-05-26', '12:35:45', '2007-10-09 14:28:02.0',"
+ + "'1221-09-22 10:11:55', 1, 2, 3, 4,"
+ + "'Test text message tiny', 'Test text',"
+ + " 'Test text message medium', 'Test text message long', "
+ + Long.MAX_VALUE+", "+Long.MIN_VALUE+", "
+ + "null, null "+
+ ");";
+
+ static final String allTypesTable = "type";
+
+ public void setUp() throws java.lang.Exception {
+ super.setUp();
+ Support_SQL.loadDriver();
+ db = new Database();
+ db.open(dbFile.getPath(), 0);
+ db.exec(DatabaseCreator.CREATE_TABLE_SIMPLE1, null);
+ DatabaseCreator.fillSimpleTable1(conn);
+
+ }
+
+ public void tearDown() {
+ if (st != null) {
+ try {
+ st.close();
+ } catch (Exception e) {
+
+ }
+ }
+ try {
+ db.close();
+ Connection con = Support_SQL.getConnection();
+ con.close();
+// dbFile.delete();
+ } catch (Exception e) {
+ fail("Exception in tearDown: "+e.getMessage());
+ } catch (SQLException e) {
+ fail("SQLException in tearDown: "+e.getMessage());
+ }
+ super.tearDown();
+ }
+
+ /**
+ * @tests {@link Stmt#Stmt()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "constructor test",
+ method = "Stmt",
+ args = {}
+ )
+ public void testStmt() {
+ Stmt st = new Stmt();
+ assertNotNull(st);
+ try {
+ Stmt actual = db.prepare("");
+ assertNotNull(st);
+ // no black box test assertEquals(actual.error_code,st.error_code);
+ } catch (Exception e) {
+ fail("Statement setup fails: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st.step();
+ fail("Cannot execute non prepared Stmt");
+ } catch (Exception e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#finalize()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "method test",
+ method = "finalize",
+ args = {}
+ )
+ public void testFinalize() {
+
+ }
+
+ /**
+ * @tests {@link Stmt#prepare()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "prepare",
+ args = {}
+ )
+ public void testPrepare() {
+ try {
+ st = db.prepare("");
+ st.prepare();
+ fail("statement is closed");
+ } catch (Exception e) {
+ assertEquals("stmt already closed", e.getMessage());
+ }
+
+ try {
+ st = new Stmt();
+ st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1);
+ assertFalse(st.prepare());
+ st = new Stmt();
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ assertFalse(st.prepare());
+ st = new Stmt();
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ st.bind(1, 1);
+ st.bind(2, 10);
+ st.bind(3, 30);
+ assertFalse(st.prepare());
+ st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1
+ + "; " + "delete from " + DatabaseCreator.SIMPLE_TABLE1
+ + " where id = 5; " + "insert into "
+ + DatabaseCreator.SIMPLE_TABLE1 + " values(5, 10, 20); "
+ + "select * from " + DatabaseCreator.SIMPLE_TABLE1 + ";");
+ assertTrue(st.prepare());
+ assertTrue(st.prepare());
+ assertTrue(st.prepare());
+ assertFalse(st.prepare());
+ } catch (Exception e) {
+ fail("statement should be ready for execution: "
+ + e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#step()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "step",
+ args = {}
+ )
+ public void testStep() {
+ try {
+ st.step();
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertEquals("stmt already closed", e.getMessage());
+ }
+
+ try {
+ st = new Stmt();
+ st = db.prepare("select name from sqlite_master where type = 'table'");
+ st.step();
+ } catch (Exception e) {
+ fail("test fails");
+ }
+
+ }
+
+ /**
+ * @tests {@link Stmt#close()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "close",
+ args = {}
+ )
+ public void testClose() {
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ st.close();
+ } catch (Exception e) {
+ fail("Test fails");
+ e.printStackTrace();
+ }
+
+ try {
+ st.step();
+ fail("Test fails");
+ } catch (Exception e) {
+ assertEquals("stmt already closed", e.getMessage());
+ }
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#reset()}
+ */
+ @TestTargetNew(
+ level = TestLevel.TODO,
+ notes = "method test",
+ method = "reset",
+ args = {}
+ )
+ @AndroidOnly("Tableresult is not cleared when resetting statement: "+
+ "Either complete spec or change implementation accordingly.")
+ public void testReset() throws Exception {
+ db.exec("create table TEST (res integer not null)", null);
+
+ st = db.prepare("insert into TEST values (:one);");
+ st.bind(1, 1);
+ st.step();
+
+ // verify that parameter is still bound
+ st.reset();
+ assertEquals(1,st.bind_parameter_count());
+ st.step();
+
+ TableResult count = db.get_table("select count(*) from TEST where res=1", null);
+
+ String[] row0 = (String[]) count.rows.elementAt(0);
+ assertEquals(2, Integer.parseInt(row0[0]));
+
+ //Verify that rest (tableResult) is cleared
+ st = db.prepare("select * from TEST;");
+ st.step();
+ assertEquals(1, st.column_count());
+ st.reset();
+ assertEquals(0,st.column_count());
+ }
+
+ /**
+ * @tests {@link Stmt#clear_bindings()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "clear_bindings",
+ args = {}
+ )
+ public void testClear_bindings() {
+ try {
+ st.clear_bindings();
+ } catch (Exception e) {
+ assertEquals("unsupported", e.getMessage());
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#bind(int, int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "bind",
+ args = {int.class, int.class}
+ )
+ public void testBindIntInt() {
+ try {
+ int input = 0;
+ int maxVal = Integer.MAX_VALUE;
+ int minVal = Integer.MIN_VALUE;
+
+ db.exec("create table TEST (res integer)", null);
+ st = db.prepare("insert into TEST values (:one);");
+ st.bind(1, input);
+ st.step();
+
+ st.reset();
+ st.bind(1,maxVal);
+ st.step();
+
+ st.reset();
+ st.bind(1,minVal);
+ st.step();
+
+ TableResult r = db.get_table("select * from TEST");
+
+ String[] row0 = (String[]) r.rows.elementAt(0);
+ assertEquals(input,Integer.parseInt(row0[0]));
+
+ String[] row1 = (String[]) r.rows.elementAt(1);
+ assertEquals(maxVal,Integer.parseInt(row1[0]));
+
+ String[] row2 = (String[]) r.rows.elementAt(2);
+ assertEquals(minVal,Integer.parseInt(row2[0]));
+
+ } catch (Exception e) {
+ fail("Error in test setup: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st.close();
+ st.bind(1,Integer.MIN_VALUE);
+ fail("Exception expected");
+ } catch (Exception e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#bind(int, long)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "bind",
+ args = {int.class, long.class}
+ )
+ public void testBindIntLong() {
+ try {
+ long input = 0;
+ long maxVal = Long.MAX_VALUE;
+ long minVal = Long.MIN_VALUE;
+
+ db.exec("create table TEST (res long)", null);
+ st = db.prepare("insert into TEST values (:one);");
+ st.bind(1, input);
+ st.step();
+
+ st.reset();
+ st.bind(1,maxVal);
+ st.step();
+
+ st.reset();
+ st.bind(1,minVal);
+ st.step();
+
+ TableResult r = db.get_table("select * from TEST");
+
+ String[] row0 = (String[]) r.rows.elementAt(0);
+ assertEquals(input,Long.parseLong(row0[0]));
+
+ String[] row1 = (String[]) r.rows.elementAt(1);
+ assertEquals(maxVal,Long.parseLong(row1[0]));
+
+ String[] row2 = (String[]) r.rows.elementAt(2);
+ assertEquals(minVal,Long.parseLong(row2[0]));
+
+ } catch (Exception e) {
+ fail("Error in test setup: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st.close();
+ st.bind(1,Long.MIN_VALUE);
+ fail("Exception expected");
+ } catch (Exception e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#bind(int, double)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "bind",
+ args = {int.class, double.class}
+ )
+ public void testBindIntDouble() {
+ try {
+ double input = 0.0;
+ double maxVal = Double.MAX_VALUE;
+ double minVal = Double.MIN_VALUE;
+ double negInf = Double.NEGATIVE_INFINITY;
+ double posInf = Double.POSITIVE_INFINITY;
+ double nan = Double.NaN;
+
+ db.exec("create table TEST (res double)", null);
+ st = db.prepare("insert into TEST values (:one);");
+ st.bind(1, input);
+ st.step();
+
+ st.reset();
+ st.bind(1, maxVal);
+ st.step();
+
+ st.reset();
+ st.bind(1, minVal);
+ st.step();
+
+ st.reset();
+ st.bind(1, negInf);
+ st.step();
+
+ st.reset();
+ st.bind(1, posInf);
+ st.step();
+
+ st.reset();
+ st.bind(1, nan);
+ st.step();
+
+
+ TableResult r = db.get_table("select * from TEST");
+
+ String[] row0 = (String[]) r.rows.elementAt(0);
+ assertTrue(Double.compare(input, Double.parseDouble(row0[0])) == 0);
+
+ String[] row1 = (String[]) r.rows.elementAt(1);
+ assertFalse(Double.compare(maxVal, Double.parseDouble(row1[0])) == 0);
+ assertTrue(Double.compare(maxVal, Double.parseDouble(row1[0])) < 0);
+ assertTrue(Double.isInfinite(Double.parseDouble(row1[0])));
+
+ String[] row2 = (String[]) r.rows.elementAt(2);
+ assertTrue(Double.compare(minVal, Double.parseDouble(row2[0])) == 0);
+
+ String[] row3 = (String[]) r.rows.elementAt(3);
+ assertEquals("Double.NEGATIVE_INFINITY SQLite representation",
+ "-Inf", row3[0]);
+
+ String[] row4 = (String[]) r.rows.elementAt(4);
+ assertEquals("Double.POSITIVE_INFINITY SQLite representation",
+ "Inf", row4[0]);
+
+ String[] row5 = (String[]) r.rows.elementAt(4);
+ assertEquals("Double.Nan SQLite representation", "Inf", row5[0]);
+
+ } catch (Exception e) {
+ fail("Error in test setup: " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st.close();
+ st.bind(1,0.0);
+ fail("Exception expected");
+ } catch (Exception e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#bind(int, byte[])}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "bind",
+ args = {int.class, byte[].class}
+ )
+ public void testBindIntByteArray() {
+
+ String name = "Hello World";
+
+ try {
+ byte[] b = new byte[name.getBytes().length];
+ b = name.getBytes();
+ String stringInHex = "";
+
+ db.exec(DatabaseCreator.CREATE_TABLE_PARENT, null);
+ st = db.prepare("insert into " + DatabaseCreator.PARENT_TABLE
+ + " values (:one, :two);");
+ st.bind(1, 2);
+ st.bind(2, b);
+ st.step();
+
+ //compare what was stored with input based on Hex representation
+ // since type of column is CHAR
+ TableResult r = db.get_table("select * from "
+ + DatabaseCreator.PARENT_TABLE);
+ String[] row = (String[]) r.rows.elementAt(0);
+
+ for (byte aByte : b) {
+ stringInHex += Integer.toHexString(aByte);
+ }
+ stringInHex = "X'" + stringInHex + "'";
+ assertTrue(stringInHex.equalsIgnoreCase(row[1]));
+
+ } catch (Exception e) {
+ fail("Error in test setup: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st.close();
+ st.bind(1,name.getBytes());
+ fail("Exception expected");
+ } catch (Exception e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#bind(int, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "bind",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testBindIntString() {
+ String name = "Hello World";
+
+ try {
+
+ db.exec(DatabaseCreator.CREATE_TABLE_PARENT, null);
+ st = db.prepare("insert into " + DatabaseCreator.PARENT_TABLE
+ + " values (:one, :two);");
+ st.bind(1, 2);
+ st.bind(2, name);
+ st.step();
+
+ TableResult r = db.get_table("select * from "
+ + DatabaseCreator.PARENT_TABLE);
+ String[] row = (String[]) r.rows.elementAt(0);
+ assertEquals(name,row[1]);
+
+ } catch (Exception e) {
+ fail("Error in test setup: "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st.close();
+ st.bind(1,name);
+ fail("Exception expected");
+ } catch (Exception e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#bind(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "bind",
+ args = {int.class}
+ )
+ public void testBindInt() {
+
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ st.bind(4);
+ st.bind(1, 4);
+ st.bind(2, 10);
+ st.bind(3, 30);
+ st.step();
+ fail("Test failes");
+ } catch (Exception e) {
+ // What happens if null is bound to non existing variable position
+ assertEquals("parameter position out of bounds" , e.getMessage());
+ }
+
+ // functional tests
+
+ try {
+ st.reset();
+ st.bind(1);
+ st.bind(2, 10);
+ st.bind(3, 30);
+ st.step();
+ fail("Test failes");
+ } catch (Exception e) {
+ // What happens if null is bound to NON NULL field
+ assertEquals("SQL logic error or missing database", e.getMessage());
+ }
+
+ try {
+ st.reset();
+ st.bind(1, 3);
+ st.bind(2);
+ st.bind(3, 30);
+ st.step();
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ }
+
+ }
+
+ /**
+ * @tests {@link Stmt#bind_zeroblob(int, int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "bind_zeroblob",
+ args = {int.class, int.class}
+ )
+ public void testBind_zeroblob() {
+ try {
+ st.bind_zeroblob(1, 128);
+ } catch (Exception e) {
+ assertEquals("unsupported", e.getMessage());
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#bind_parameter_count()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "bind_parameter_count",
+ args = {}
+ )
+ public void testBind_parameter_count() {
+ try {
+ st.bind_parameter_count();
+ } catch (Exception e) {
+ assertEquals("stmt already closed", e.getMessage());
+ }
+
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ assertEquals(3, st.bind_parameter_count());
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (?, ?, ?)");
+ assertEquals(3, st.bind_parameter_count());
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1);
+ assertEquals(0, st.bind_parameter_count());
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st.close();
+ st.bind_parameter_count();
+ fail("Exception expected");
+ } catch (Exception e) {
+ //ok
+ }
+
+ }
+
+ /**
+ * @tests {@link Stmt#bind_parameter_name(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "bind_parameter_name",
+ args = {int.class}
+ )
+ public void testBind_parameter_name() {
+ try {
+ st.bind_parameter_name(1);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertEquals("stmt already closed", e.getMessage());
+ }
+
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ assertEquals(":one", st.bind_parameter_name(1));
+ assertEquals(":two", st.bind_parameter_name(2));
+ assertEquals(":three", st.bind_parameter_name(3));
+ String name = st.bind_parameter_name(4);
+ } catch (Exception e) {
+ assertEquals("parameter position out of bounds",e.getMessage());
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#bind_parameter_index(String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "bind_parameter_index",
+ args = {java.lang.String.class}
+ )
+ public void testBind_parameter_index() {
+
+ try {
+ st.bind_parameter_index("");
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertEquals("stmt already closed", e.getMessage());
+ }
+
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ assertEquals(3, st.bind_parameter_index(":three"));
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ assertEquals(0, st.bind_parameter_index(":t"));
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (?, ?, ?)");
+ assertEquals(0, st.bind_parameter_index("?"));
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#column_int(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "column_int",
+ args = {int.class}
+ )
+ public void testColumn_int() throws Exception {
+ db.exec(createAllTypes, null);
+ db.exec(insertAllTypes, null);
+
+ int columnObjectCastFromLong;
+ Object columnObject = null;
+ int intColumn = 0;
+ String selectStmt = "select * from "+DatabaseCreator.SIMPLE_TABLE1;
+
+ st = db.prepare(selectStmt);
+ st.step();
+ // select 'speed' value
+ columnObject = st.column(1);
+ intColumn = st.column_int(1);
+ assertNotNull(intColumn);
+
+ assertTrue("Integer".equalsIgnoreCase(st.column_decltype(1)));
+ int stSpeed = Integer.parseInt(columnObject.toString());
+ assertNotNull(stSpeed);
+ assertEquals( intColumn, stSpeed);
+ assertEquals(10,stSpeed);
+
+ selectStmt = "select TextVal from "+allTypesTable;
+
+ st = db.prepare(selectStmt);
+ st.step();
+ // select double value
+ try {
+ st.column_int(0);
+ } catch (Exception e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#column_long(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "column_long",
+ args = {int.class}
+ )
+ public void testColumn_long() {
+ Object columnObject = null;
+ int columnObjectCastFromLong;
+ long longColumn = 0;
+ try {
+ String selectStmt = "select * from "+DatabaseCreator.SIMPLE_TABLE1;
+ st = db.prepare(selectStmt);
+ st.step();
+ columnObject = st.column(1);
+ longColumn = st.column_long(1);
+ assertNotNull(longColumn);
+ // column declared as integer
+ assertTrue("Integer".equalsIgnoreCase(st.column_decltype(1)));
+ int stSpeed = Integer.parseInt(columnObject.toString());
+ assertNotNull(stSpeed);
+ assertEquals( longColumn, stSpeed);
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ st.column_long(4);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertEquals( "column out of bounds" , e.getMessage());
+ }
+
+ try {
+ st.column_long(-1);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertEquals( "column out of bounds" , e.getMessage());
+ }
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#column_double(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "column_double",
+ args = {int.class}
+ )
+ public void testColumn_double() throws Exception {
+ db.exec(createAllTypes, null);
+ db.exec(insertAllTypes, null);
+
+ Object columnObject = null;
+ double doubleColumn = 0;
+ double actualVal = 23.2;
+ String selectStmt = "select DoubleVal from "+allTypesTable;
+
+ st = db.prepare(selectStmt);
+ st.step();
+ // select double value
+ doubleColumn = st.column_double(0);
+ assertNotNull(doubleColumn);
+
+ assertTrue("DOUBLE".equalsIgnoreCase(st.column_decltype(0)));
+ assertNotNull(doubleColumn);
+ assertEquals( actualVal, doubleColumn);
+
+ // Exception test
+ selectStmt = "select dateVal from "+allTypesTable;
+
+ st = db.prepare(selectStmt);
+ st.step();
+ // select double value
+ try {
+ st.column_double(0);
+ } catch (Exception e) {
+ //ok
+ }
+
+
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#column_bytes(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "column_bytes",
+ args = {int.class}
+ )
+ public void testColumn_bytes() throws Exception {
+
+ db.exec("create table B(id integer primary key, val blob)",null);
+ db.exec("insert into B values(1, zeroblob(128))", null);
+ st = db.prepare("select val from B where id = 1");
+ assertTrue(st.step());
+ try {
+ st.column_bytes(0);
+ } catch (Exception e) {
+ assertEquals("unsupported", e.getMessage());
+ }
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#column_string(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "column_string",
+ args = {int.class}
+ )
+ public void testColumn_string() throws Exception {
+ db.exec(createAllTypes, null);
+ db.exec(insertAllTypes, null);
+
+ Object columnObject = null;
+ String stringColumn = "";
+ String actualVal = "test string";
+ String selectStmt = "select charStr from "+allTypesTable;
+
+ st = db.prepare(selectStmt);
+ st.step();
+ // select string value
+ stringColumn = st.column_string(0);
+ assertNotNull(stringColumn);
+
+ assertTrue("CHAR(20)".equalsIgnoreCase(st.column_decltype(0)));
+ assertNotNull(stringColumn);
+ assertEquals( actualVal, stringColumn);
+
+ // Exception test
+ selectStmt = "select DoubleVal from "+allTypesTable;
+
+ st = db.prepare(selectStmt);
+ st.step();
+ // select double value
+ try {
+ st.column_string(0);
+ } catch (Exception e) {
+ //ok
+ }
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#column_type(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "method test",
+ method = "column_type",
+ args = {int.class}
+ )
+ @AndroidOnly("For numeric, float and blob wrong type is returned")
+ public void testColumn_type() throws Exception {
+ db.exec(createAllTypes, null);
+ db.exec(insertAllTypes, null);
+ st = db.prepare("select * from " + allTypesTable);
+ st.step();
+
+ // Exception test
+ try {
+ st.column_type(100);
+ } catch (Exception e) {
+ // ok
+ }
+
+ /*
+ Dictionary
+
+ public static final int SQLITE_INTEGER = 1;
+ public static final int SQLITE_FLOAT = 2;
+ public static final int SQLITE_BLOB = 4;
+ public static final int SQLITE_NULL = 5;
+ public static final int SQLITE3_TEXT = 3;
+ public static final int SQLITE_NUMERIC = -1;
+ */
+
+ assertEquals(Constants.SQLITE3_TEXT, st.column_type(23)); // ok TEXT
+ assertEquals(Constants.SQLITE3_TEXT, st.column_type(13)); // CHAR(20)
+
+ assertEquals(Constants.SQLITE_FLOAT, st.column_type(8));
+ assertEquals(Constants.SQLITE_FLOAT, st.column_type(9));
+ assertEquals(Constants.SQLITE_FLOAT, st.column_type(10)); // FLOAT
+
+ for (int i = 0; i < 8; i++) {
+ assertEquals("Expected Integer at position " + i,
+ Constants.SQLITE_INTEGER, st.column_type(i));
+ }
+
+ assertEquals(Constants.SQLITE_NULL, st.column_type(28));
+ assertEquals(Constants.SQLITE_NULL, st.column_type(29));
+
+ // Failing tests
+ assertTrue("NUMERIC".equalsIgnoreCase(st.column_decltype(12)));
+ assertEquals(Constants.SQLITE_NUMERIC, st.column_type(12)); // NUMERIC
+ // -> got
+ // INTEGER
+
+ assertTrue("FLOAT".equalsIgnoreCase(st.column_decltype(11)));
+ assertEquals(Constants.SQLITE_FLOAT, st.column_type(11)); // FLOAT ->
+ // got INTEGER
+ assertTrue("BLOB".equalsIgnoreCase(st.column_decltype(19)));
+ assertEquals(Constants.SQLITE_BLOB, st.column_type(19)); // Blob got
+ // INTEGER
+
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#column_count() )}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "column_count",
+ args = {}
+ )
+ @AndroidOnly("Wrong value is returned in case of a prepared statment to "+
+ "which a '*' bound ")
+ public void testColumn_count() throws Exception {
+
+ String selectStmt = "select * from "+DatabaseCreator.SIMPLE_TABLE1;
+ st = db.prepare(selectStmt);
+
+ assertEquals(3, st.column_count());
+
+ st.step();
+ int columnCount = st.column_count();
+ assertNotNull(columnCount);
+ assertEquals( 3, columnCount);
+
+ // actual prepared statement
+ selectStmt = "select ? from "+DatabaseCreator.SIMPLE_TABLE1;
+ st = db.prepare(selectStmt);
+
+ assertEquals(3, st.column_count());
+
+ st.bind(1, "*");
+ st.step();
+ columnCount = st.column_count();
+ assertNotNull(columnCount);
+ assertEquals( 3, columnCount);
+
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#column(int) )}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "method test",
+ method = "column",
+ args = {int.class}
+ )
+ public void testColumn() throws Exception {
+ Object columnObject = null;
+ int columnObjectCastFromLong;
+ int intColumn = 0;
+ try {
+ String selectStmt = "select * from "+DatabaseCreator.SIMPLE_TABLE1;
+ TableResult res = db.get_table(selectStmt);
+ st = db.prepare(selectStmt);
+ st.step();
+ columnObject = st.column(1);
+ intColumn = st.column_int(1);
+ assertNotNull(intColumn);
+ assertTrue("Integer".equalsIgnoreCase(st.column_decltype(1)));
+ int stSpeed = Integer.parseInt(columnObject.toString());
+ assertNotNull(stSpeed);
+ assertEquals( intColumn, stSpeed);
+ } catch (Exception e) {
+ fail("Error in test setup : " + e.getMessage());
+ e.printStackTrace();
+ }
+
+ try {
+ assertNotNull(columnObject);
+ int dummy = ((Integer) columnObject).intValue();
+ fail("Cast to Integer should fail");
+ } catch (ClassCastException e) {
+ assertEquals("java.lang.Long", e.getMessage());
+ }
+
+ try {
+ st.column(4);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertEquals( "column out of bounds" , e.getMessage());
+ }
+
+ try {
+ st.column(-1);
+ fail("Exception expected");
+ } catch (Exception e) {
+ assertEquals( "column out of bounds" , e.getMessage());
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#column_table_name(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "column_table_name",
+ args = {int.class}
+ )
+ public void testColumn_table_name() {
+ try {
+ st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1);
+ String name = st.column_table_name(1);
+ fail("Function is now supported.");
+ } catch (Exception e) {
+ assertEquals("unsupported", e.getMessage());
+ }
+ }
+
+ /**
+ * @tests {@link Stmt#column_database_name(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "column_database_name",
+ args = {int.class}
+ )
+ public void testColumn_database_name() {
+ try {
+ st = db.prepare("insert into " + DatabaseCreator.SIMPLE_TABLE1
+ + " values (:one,:two,:three)");
+ String name = st.column_database_name(1);
+ fail("Function is now supported.");
+ } catch (Exception e) {
+ assertEquals("unsupported", e.getMessage());
+ }
+
+ }
+
+ /**
+ * @throws Exception
+ * @tests {@link Stmt#column_decltype(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "method test",
+ method = "column_decltype",
+ args = {int.class}
+ )
+ public void testColumn_decltype() throws Exception {
+ db.exec(createAllTypes, null);
+ db.exec(insertAllTypes, null);
+ st = db.prepare("select * from " + allTypesTable);
+ st.step();
+
+ // Exception test
+ try {
+ st.column_decltype(100);
+ } catch (Exception e) {
+ // ok
+ }
+
+ assertTrue(st.column_decltype(0), "BOOLEAN".equalsIgnoreCase(st
+ .column_decltype(0)));
+ assertTrue(st.column_decltype(1), "INT".equalsIgnoreCase(st
+ .column_decltype(1)));
+ assertTrue(st.column_decltype(2), "LONG".equalsIgnoreCase(st
+ .column_decltype(2)));
+ assertTrue(st.column_decltype(3), "BIGINT".equalsIgnoreCase(st
+ .column_decltype(3)));
+ assertTrue(st.column_decltype(4), "TINYINT".equalsIgnoreCase(st
+ .column_decltype(4)));
+ assertTrue(st.column_decltype(5), "SMALLINT".equalsIgnoreCase(st
+ .column_decltype(5)));
+ assertTrue(st.column_decltype(6), "MEDIUMINT".equalsIgnoreCase(st
+ .column_decltype(6)));
+ assertTrue(st.column_decltype(7), "INTEGER".equalsIgnoreCase(st
+ .column_decltype(7)));
+ assertTrue(st.column_decltype(8), "REAL".equalsIgnoreCase(st
+ .column_decltype(8)));
+ assertTrue(st.column_decltype(9), "DOUBLE".equalsIgnoreCase(st
+ .column_decltype(9)));
+ assertTrue(st.column_decltype(10), "FLOAT".equalsIgnoreCase(st
+ .column_decltype(10)));
+ assertTrue(st.column_decltype(11), "DECIMAL".equalsIgnoreCase(st
+ .column_decltype(11)));
+ assertTrue(st.column_decltype(12), "NUMERIC".equalsIgnoreCase(st
+ .column_decltype(12)));
+ assertTrue(st.column_decltype(13), "CHAR(20)".equalsIgnoreCase(st
+ .column_decltype(13)));
+
+ assertTrue(st.column_decltype(19), "BLOB".equalsIgnoreCase(st
+ .column_decltype(19)));
+
+ assertTrue(st.column_decltype(23), "TEXT".equalsIgnoreCase(st
+ .column_decltype(23)));
+ assertTrue(st.column_decltype(28), "URL".equalsIgnoreCase(st
+ .column_decltype(28)));
+ assertTrue(st.column_decltype(29), "URL".equalsIgnoreCase(st
+ .column_decltype(29)));
+ }
+
+ /**
+ * @tests {@link Stmt#column_origin_name(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "column_origin_name",
+ args = {int.class}
+ )
+ public void testColumn_origin_name() {
+ try {
+ st = db.prepare("select * from " + DatabaseCreator.SIMPLE_TABLE1);
+ String name = st.column_origin_name(1);
+ fail("Function is now supported.");
+ } catch (Exception e) {
+ assertEquals("unsupported", e.getMessage());
+ }
+ }
+}
diff --git a/sql/src/test/java/tests/java/sql/AllTests.java b/sql/src/test/java/tests/java/sql/AllTests.java
new file mode 100644
index 0000000..8c1e51a
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/AllTests.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.java.sql;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * This is autogenerated source file. Includes tests for package tests.java.sql;
+ */
+
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AllTests.suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite("All tests for package tests.java.sql;");
+ // $JUnit-BEGIN$
+
+ suite.addTest(DatabaseMetaDataTest.suite());
+ suite.addTest(MultiThreadAccessTest.suite());
+ suite.addTest(StressTest.suite());
+ suite.addTest(UpdateFunctionalityTest.suite());
+ suite.addTest(SelectFunctionalityTest.suite());
+ suite.addTest(UpdateFunctionalityTest2.suite());
+ suite.addTest(DeleteFunctionalityTest.suite());
+ suite.addTest(DatabaseMetaDataTest.suite());
+ suite.addTest(DatabaseMetaDataNotSupportedTest.suite());
+ suite.addTest(InsertFunctionalityTest.suite());
+
+ // $JUnit-END$
+ return suite;
+ }
+}
diff --git a/sql/src/test/java/tests/java/sql/DatabaseMetaDataNotSupportedTest.java b/sql/src/test/java/tests/java/sql/DatabaseMetaDataNotSupportedTest.java
new file mode 100644
index 0000000..9f262d9
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/DatabaseMetaDataNotSupportedTest.java
@@ -0,0 +1,2066 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.java.sql;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashSet;
+
+@TestTargetClass(DatabaseMetaData.class)
+public class DatabaseMetaDataNotSupportedTest extends TestCase {
+
+ private static String VIEW_NAME = "myView";
+
+ private static String CREATE_VIEW_QUERY = "CREATE VIEW " + VIEW_NAME
+ + " AS SELECT * FROM " + DatabaseCreator.TEST_TABLE1;
+
+ private static String DROP_VIEW_QUERY = "DROP VIEW " + VIEW_NAME;
+
+ protected static Connection conn;
+
+ protected static DatabaseMetaData meta;
+
+ protected static Statement statement;
+
+ protected static Statement statementForward;
+
+ private static int id = 1;
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ DatabaseMetaDataTest.class)) {
+ protected void setUp() {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ meta = conn.getMetaData();
+ statement = conn.createStatement();
+ createTestTables();
+ } catch (SQLException e) {
+ System.out.println("Error in test setup: "+e.getMessage());
+ }
+ }
+
+ protected void tearDown() {
+ try {
+ conn = Support_SQL.getConnection();
+ meta = conn.getMetaData();
+ statement = conn.createStatement();
+ deleteTestTables();
+ } catch (SQLException e) {
+ System.out.println("Error in teardown: "+e.getMessage());
+ } finally {
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ }
+ }
+ }
+
+ private void createTestTables() {
+ try {
+ ResultSet userTab = meta.getTables(null, null, null, null);
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE3)) {
+ statement.execute(DatabaseCreator.DROP_TABLE3);
+ } else if (tableName.equals(VIEW_NAME)) {
+ statement.execute(DROP_VIEW_QUERY);
+ }
+ }
+ userTab.close();
+ statement.execute(DatabaseCreator.CREATE_TABLE3);
+ statement.execute(DatabaseCreator.CREATE_TABLE1);
+ statement.execute(CREATE_VIEW_QUERY);
+ meta = conn.getMetaData();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ private void deleteTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ statement.execute(DatabaseCreator.DROP_TABLE3);
+ statement.execute(DROP_VIEW_QUERY);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ } finally {
+ try {
+ if (! conn.isClosed()) {
+ conn.close();
+ }
+ } catch (SQLException e) {
+
+ }
+ }
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#allProceduresAreCallable()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "Granting not supported.",
+ method = "allProceduresAreCallable",
+ args = {}
+ )
+ public void test_allProceduresAreCallable() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests {@link java.sql.DatabaseMetaData#allTablesAreSelectable()}
+ *
+ * // NOT_FEASIBLE GRANT and REVOKE are not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "test fails. GRANT and REVOKE not supported",
+ method = "allTablesAreSelectable",
+ args = {}
+ )
+ @KnownFailure("Not supported ops applied")
+ public void test_allTablesAreSelectable() throws SQLException {
+ // grant SELECT privileges
+
+ String query = "GRANT CREATE, SELECT ON " + DatabaseCreator.TEST_TABLE1
+ + " TO " + Support_SQL.sqlUser;
+ statement.execute(query);
+ Connection userConn = Support_SQL.getConnection(Support_SQL.sqlUrl,
+ Support_SQL.sqlUser, Support_SQL.sqlUser);
+ DatabaseMetaData userMeta = userConn.getMetaData();
+ ResultSet userTab = userMeta.getTables(null, null, null, null);
+
+ assertTrue("Tables are not obtained", userTab.next());
+ assertEquals("Incorrect name of obtained table",
+ DatabaseCreator.TEST_TABLE1.toLowerCase(), userTab.getString(
+ "TABLE_NAME").toLowerCase());
+ assertTrue("Not all of obtained tables are selectable", userMeta
+ .allTablesAreSelectable());
+
+ userTab.close();
+ // revoke SELECT privileges
+ query = "REVOKE SELECT ON " + DatabaseCreator.TEST_TABLE1 + " FROM "
+ + Support_SQL.sqlUser;
+ statement.execute(query);
+
+ userTab = userMeta.getTables(null, null, null, null);
+
+ assertTrue("Tables are not obtained", userTab.next());
+ assertEquals("Incorrect name of obtained table",
+ DatabaseCreator.TEST_TABLE1.toLowerCase(), userTab.getString(
+ "TABLE_NAME").toLowerCase());
+ assertFalse("No SELECT privileges", userMeta.allTablesAreSelectable());
+
+ userTab.close();
+ // revoke CREATE privileges
+ query = "REVOKE CREATE ON " + DatabaseCreator.TEST_TABLE1 + " FROM "
+ + Support_SQL.sqlUser;
+ statement.execute(query);
+ userConn.close();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#dataDefinitionCausesTransactionCommit()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "dataDefinitionCausesTransactionCommit",
+ args = {}
+ )
+ public void test_dataDefinitionCausesTransactionCommit()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#dataDefinitionIgnoredInTransactions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "dataDefinitionIgnoredInTransactions",
+ args = {}
+ )
+ public void test_dataDefinitionIgnoredInTransactions() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#deletesAreDetected(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "deletesAreDetected",
+ args = {int.class}
+ )
+ public void test_deletesAreDetectedI() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#doesMaxRowSizeIncludeBlobs()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "doesMaxRowSizeIncludeBlobs",
+ args = {}
+ )
+ public void test_doesMaxRowSizeIncludeBlobs() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getAttributes(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "getAttributes",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void test_getAttributesLjava_lang_StringLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getCatalogs()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported. not supported. Received result wasn't checked.",
+ method = "getCatalogs",
+ args = {}
+ )
+ public void test_getCatalogs() throws SQLException {
+ ResultSet rs = meta.getCatalogs();
+ // NOT_FEASIBLE getCatalog is not supported
+// while (rs.next()) {
+ //if (rs.getString("TABLE_CAT").equalsIgnoreCase(conn.getCatalog())) {
+ // rs.close();
+ // return;
+ //}
+// }
+ rs.close();
+// fail("Incorrect a set of catalogs");
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getCatalogSeparator()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getCatalogSeparator",
+ args = {}
+ )
+ public void test_getCatalogSeparator() throws SQLException {
+ assertTrue("Incorrect catalog separator", "".equals(meta
+ .getCatalogSeparator().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getCatalogTerm()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getCatalogTerm",
+ args = {}
+ )
+ public void test_getCatalogTerm() throws SQLException {
+ assertTrue("Incorrect catalog term", "".equals(meta
+ .getCatalogSeparator().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getExtraNameCharacters()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getExtraNameCharacters",
+ args = {}
+ )
+ public void test_getExtraNameCharacters() throws SQLException {
+ assertNotNull("Incorrect extra name characters", meta
+ .getExtraNameCharacters());
+
+ }
+
+ /**
+ * @tests {@link java.sql.DatabaseMetaData #getIndexInfo(java.lang.String,
+ * java.lang.String, java.lang.String, boolean, boolean)}
+ *
+ * NOT_FEASIBLE getCatalog is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported. not supported. Received result wasn't checked.",
+ method = "getIndexInfo",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, boolean.class, boolean.class}
+ )
+ public void test_getIndexInfoLjava_lang_StringLjava_lang_StringLjava_lang_StringZZ()
+ throws SQLException {
+ boolean unique = false;
+ ResultSet rs = meta.getIndexInfo(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1, unique, true);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ assertTrue("Rows do not obtained", rs.next());
+ int col = rsmd.getColumnCount();
+ assertEquals("Incorrect number of columns", 13, col);
+ String[] columnNames = { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "NON_UNIQUE", "INDEX_QUALIFIER", "INDEX_NAME", "TYPE",
+ "ORDINAL_POSITION", "COLUMN_NAME", "ASC_OR_DESC",
+ "CARDINALITY", "PAGES", "FILTER_CONDITION" };
+ for (int c = 1; c <= col; ++c) {
+ assertEquals("Incorrect column name", columnNames[c - 1], rsmd
+ .getColumnName(c));
+ }
+
+ assertEquals("Incorrect table catalog", conn.getCatalog(), rs
+ .getString("TABLE_CAT"));
+ assertEquals("Incorrect table schema", null, rs
+ .getString("TABLE_SCHEM"));
+ assertEquals("Incorrect table name", DatabaseCreator.TEST_TABLE1, rs
+ .getString("TABLE_NAME"));
+ assertEquals("Incorrect state of uniquess", unique, rs
+ .getBoolean("NON_UNIQUE"));
+ assertEquals("Incorrect index catalog", "", rs
+ .getString("INDEX_QUALIFIER"));
+ assertEquals("Incorrect index name", "primary", rs.getString(
+ "INDEX_NAME").toLowerCase());
+ assertEquals("Incorrect index type", DatabaseMetaData.tableIndexOther,
+ rs.getShort("TYPE"));
+ assertEquals("Incorrect column sequence number within index", 1, rs
+ .getShort("ORDINAL_POSITION"));
+ assertEquals("Incorrect column name", "id", rs.getString("COLUMN_NAME"));
+ assertEquals("Incorrect column sort sequence", "a", rs.getString(
+ "ASC_OR_DESC").toLowerCase());
+ assertEquals("Incorrect cardinality", 1, rs.getInt("CARDINALITY"));
+ assertEquals("Incorrect value of pages", 0, rs.getInt("PAGES"));
+ assertEquals("Incorrect filter condition", null, rs
+ .getString("FILTER_CONDITION"));
+ rs.close();
+ }
+
+ /**
+ * @tests {@link java.sql.DatabaseMetaData #getColumnPrivileges(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)}
+ *
+ * NOT_FEASIBLE GRANT is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported. not supported. Received result wasn't checked.",
+ method = "getColumnPrivileges",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void test_getColumnPrivilegesLjava_lang_StringLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ ResultSet rs = meta.getColumnPrivileges(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1, "id");
+ ResultSetMetaData rsmd = rs.getMetaData();
+ assertFalse("Rows are obtained", rs.next());
+ rs.close();
+
+ String query = "GRANT REFERENCES(id) ON " + DatabaseCreator.TEST_TABLE1
+ + " TO " + Support_SQL.sqlLogin;
+ statement.execute(query);
+
+ rs = meta.getColumnPrivileges(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1, "id");
+ rsmd = rs.getMetaData();
+ assertTrue("Rows do not obtained", rs.next());
+ int col = rsmd.getColumnCount();
+ assertEquals("Incorrect number of columns", 8, col);
+ String[] columnNames = { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "GRANTOR", "GRANTEE", "PRIVILEGE",
+ "IS_GRANTABLE" };
+ for (int c = 1; c <= col; ++c) {
+ assertEquals("Incorrect column name", columnNames[c - 1], rsmd
+ .getColumnName(c));
+ }
+ assertEquals("Incorrect table catalogue", conn.getCatalog(), rs
+ .getString("TABLE_CAT").toLowerCase());
+ assertEquals("Incorrect table schema", null, rs
+ .getString("TABLE_SCHEM"));
+ assertEquals("Incorrect table name", DatabaseCreator.TEST_TABLE1, rs
+ .getString("TABLE_NAME").toLowerCase());
+ assertEquals("Incorrect column name", "id", rs.getString("COLUMN_NAME")
+ .toLowerCase());
+ assertEquals("Incorrect grantor", Support_SQL.sqlLogin + "@"
+ + Support_SQL.sqlHost, rs.getString("GRANTOR").toLowerCase());
+ assertTrue("Incorrect grantee",
+ rs.getString("GRANTEE").indexOf("root") != -1);
+ assertEquals("Incorrect privilege", "references", rs.getString(
+ "PRIVILEGE").toLowerCase());
+
+ query = "REVOKE REFERENCES(id) ON " + DatabaseCreator.TEST_TABLE1
+ + " FROM " + Support_SQL.sqlLogin;
+ statement.execute(query);
+ rs.close();
+ }
+
+
+ /**
+ * @tests {@link java.sql.DatabaseMetaData #getExportedKeys(java.lang.String,
+ * java.lang.String, java.lang.String)}
+ *
+ * NOT_FEASIBLE foreign keys are not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported. not supported. Received result wasn't checked.",
+ method = "getExportedKeys",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void test_getExportedKeysLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ ResultSet rs = meta.getExportedKeys(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE3);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ assertTrue("Rows do not obtained", rs.next());
+ int col = rsmd.getColumnCount();
+ assertEquals("Incorrect number of columns", 14, col);
+ String[] columnNames = { "PKTABLE_CAT", "PKTABLE_SCHEM",
+ "PKTABLE_NAME", "PKCOLUMN_NAME", "FKTABLE_CAT",
+ "FKTABLE_SCHEM", "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
+ "UPDATE_RULE", "DELETE_RULE", "FK_NAME", "PK_NAME",
+ "DEFERRABILITY" };
+ for (int c = 1; c <= col; ++c) {
+ assertEquals("Incorrect column name", columnNames[c - 1], rsmd
+ .getColumnName(c));
+ }
+
+ assertEquals("Incorrect primary key table catalog", conn.getCatalog(),
+ rs.getString("PKTABLE_CAT"));
+ assertEquals("Incorrect primary key table schema", null, rs
+ .getString("PKTABLE_SCHEM"));
+ assertEquals("Incorrect primary key table name",
+ DatabaseCreator.TEST_TABLE3, rs.getString("PKTABLE_NAME"));
+ assertEquals("Incorrect primary key column name", "fk", rs
+ .getString("PKCOLUMN_NAME"));
+ assertEquals("Incorrect foreign key table catalog", conn.getCatalog(),
+ rs.getString("FKTABLE_CAT"));
+ assertEquals("Incorrect foreign key table schema", null, rs
+ .getString("FKTABLE_SCHEM"));
+ assertEquals("Incorrect foreign key table name",
+ DatabaseCreator.TEST_TABLE1, rs.getString("FKTABLE_NAME"));
+ assertEquals("Incorrect foreign key column name", "fkey", rs
+ .getString("FKCOLUMN_NAME"));
+ assertEquals("Incorrect sequence number within foreign key", 1, rs
+ .getShort("KEY_SEQ"));
+ assertEquals("Incorrect update rule value",
+ DatabaseMetaData.importedKeyNoAction, rs
+ .getShort("UPDATE_RULE"));
+ assertEquals("Incorrect delete rule value",
+ DatabaseMetaData.importedKeyNoAction, rs
+ .getShort("DELETE_RULE"));
+ assertNotNull("Incorrect foreign key name", rs.getString("FK_NAME"));
+ assertEquals("Incorrect primary key name", null, rs
+ .getString("PK_NAME"));
+ assertEquals("Incorrect deferrability",
+ DatabaseMetaData.importedKeyNotDeferrable, rs
+ .getShort("DEFERRABILITY"));
+ rs.close();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getProcedureColumns(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "getProcedureColumns",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void test_getProcedureColumnsLjava_lang_StringLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getProcedures(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "getProcedures",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void test_getProceduresLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getProcedureTerm()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getProcedureTerm",
+ args = {}
+ )
+ public void test_getProcedureTerm() throws SQLException {
+ assertTrue("Incorrect procedure term", "".equals(meta
+ .getProcedureTerm().trim()));
+
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getProcedureTerm();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSchemaTerm()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getSchemaTerm",
+ args = {}
+ )
+ public void test_getSchemaTerm() throws SQLException {
+ String term = meta.getSchemaTerm();
+ assertNotNull("Incorrect schema term", term );
+
+ assertTrue("".equals(term));
+
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getSchemaTerm();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getSuperTables(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "getSuperTables",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void test_getSuperTablesLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getSuperTypes(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "getSuperTypes",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void test_getSuperTypesLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getTablePrivileges(java.lang.String,
+ * java.lang.String, java.lang.String)
+ *
+ * NOT_FEASIBLE GRANT is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported. not supported. Received result wasn't checked.",
+ method = "getTablePrivileges",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ public void test_getTablePrivilegesLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // case 1. Get privileges when no privilegies exist for one table
+ ResultSet privileges = meta.getTablePrivileges(conn.getCatalog(), "%",
+ DatabaseCreator.TEST_TABLE3);
+ assertFalse("Some privilegies exist", privileges.next());
+ privileges.close();
+
+ // case 2. Get privileges when no privilegies exist for all tables
+ privileges = meta.getTablePrivileges(null, null, null);
+ assertFalse("Some privilegies exist", privileges.next());
+ privileges.close();
+
+ // case 3. grant CREATE and SELECT privileges ang get them
+ HashSet expectedPrivs = new HashSet();
+ expectedPrivs.add("CREATE");
+ expectedPrivs.add("SELECT");
+
+ String query = "GRANT CREATE, SELECT ON " + DatabaseCreator.TEST_TABLE3
+ + " TO " + Support_SQL.sqlUser;
+ statement.execute(query);
+
+ privileges = meta.getTablePrivileges(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE3);
+
+ while (privileges.next()) {
+ assertEquals("Wrong catalog name", Support_SQL.sqlCatalog,
+ privileges.getString("TABLE_CAT"));
+ assertNull("Wrong schema", privileges.getString("TABLE_SCHEM"));
+ assertEquals("Wrong table name", DatabaseCreator.TEST_TABLE3,
+ privileges.getString("TABLE_NAME"));
+ assertTrue("Wrong privilege " + privileges.getString("PRIVILEGE"),
+ expectedPrivs.remove(privileges.getString("PRIVILEGE")));
+ assertEquals("Wrong grantor", Support_SQL.sqlLogin + "@"
+ + Support_SQL.sqlHost, privileges.getString("GRANTOR"));
+ assertEquals("Wrong grantee", Support_SQL.sqlUser + "@%",
+ privileges.getString("GRANTEE"));
+ assertNull("Wrong value of IS_GRANTABLE", privileges
+ .getString("IS_GRANTABLE"));
+ }
+ privileges.close();
+ assertTrue("Wrong privileges were returned", expectedPrivs.isEmpty());
+
+ query = "REVOKE CREATE, SELECT ON " + DatabaseCreator.TEST_TABLE3
+ + " FROM " + Support_SQL.sqlUser;
+ statement.execute(query);
+
+ // case 4. grant all privileges ang get them
+ String[] privs = new String[] { "ALTER", "CREATE", "CREATE VIEW",
+ "DELETE", "DROP", "INDEX", "INSERT", "REFERENCES", "SELECT",
+ "SHOW VIEW", "UPDATE" };
+ expectedPrivs = new HashSet();
+ for (int i = 0; i < privs.length; i++) {
+ expectedPrivs.add(privs[i]);
+ }
+ query = "GRANT ALL ON " + DatabaseCreator.TEST_TABLE3 + " TO "
+ + Support_SQL.sqlUser;
+ statement.execute(query);
+
+ privileges = meta.getTablePrivileges(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE3);
+
+ while (privileges.next()) {
+ assertEquals("Wrong catalog name", Support_SQL.sqlCatalog,
+ privileges.getString("TABLE_CAT"));
+ assertNull("Wrong schema", privileges.getString("TABLE_SCHEM"));
+ assertEquals("Wrong table name", DatabaseCreator.TEST_TABLE3,
+ privileges.getString("TABLE_NAME"));
+ assertTrue("Wrong privilege " + privileges.getString("PRIVILEGE"),
+ expectedPrivs.remove(privileges.getString("PRIVILEGE")));
+ assertEquals("Wrong grantor", Support_SQL.sqlLogin + "@"
+ + Support_SQL.sqlHost, privileges.getString("GRANTOR"));
+ assertEquals("Wrong grantee", Support_SQL.sqlUser + "@%",
+ privileges.getString("GRANTEE"));
+ assertNull("Wrong value of IS_GRANTABLE", privileges
+ .getString("IS_GRANTABLE"));
+ }
+ privileges.close();
+ assertTrue("Wrong privileges were returned", expectedPrivs.isEmpty());
+
+ query = "REVOKE ALL ON " + DatabaseCreator.TEST_TABLE3 + " FROM "
+ + Support_SQL.sqlUser;
+ statement.execute(query);
+
+ // case 5. check no privelegies after revoke
+ privileges = meta.getTablePrivileges(conn.getCatalog(), "%",
+ DatabaseCreator.TEST_TABLE3);
+ assertFalse("Some privilegies exist", privileges.next());
+ privileges.close();
+
+ privileges = meta.getTablePrivileges(null, null, null);
+ assertFalse("Some privilegies exist", privileges.next());
+ privileges.close();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getUDTs(java.lang.String,
+ * java.lang.String, java.lang.String, int[])
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "getUDTs",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, int[].class}
+ )
+ public void test_getUDTsLjava_lang_StringLjava_lang_StringLjava_lang_String$I()
+ throws SQLException {
+ // NOT_FEASIBLE: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getVersionColumns(java.lang.String,
+ * java.lang.String, java.lang.String)
+ *
+ * NOT_FEASIBLE trigger is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported. Received result wasn't checked.Triggers not supported",
+ method = "getVersionColumns",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ @KnownFailure("Not supported ops applied")
+ public void test_getVersionColumnsLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ DatabaseMetaDataTest.insertNewRecord();
+
+ String triggerName = "updateTrigger";
+ String triggerQuery = "CREATE TRIGGER " + triggerName
+ + " AFTER UPDATE ON " + DatabaseCreator.TEST_TABLE1
+ + " FOR EACH ROW BEGIN INSERT INTO "
+ + DatabaseCreator.TEST_TABLE3 + " SET fk = 10; END;";
+ statementForward.execute(triggerQuery);
+
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field1='fffff' WHERE id=1";
+ statementForward.execute(updateQuery);
+
+ ResultSet rs = meta.getVersionColumns(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1);
+ assertTrue("Result set is empty", rs.next());
+ rs.close();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#isCatalogAtStart()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "isCatalogAtStart",
+ args = {}
+ )
+ public void test_isCatalogAtStart() throws SQLException {
+ assertFalse(
+ "catalog doesn't appear at the start of a fully qualified table name",
+ meta.isCatalogAtStart());
+
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.isCatalogAtStart();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#locatorsUpdateCopy()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "locatorsUpdateCopy",
+ args = {}
+ )
+ public void test_locatorsUpdateCopy() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullPlusNonNullIsNull()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "nullPlusNonNullIsNull",
+ args = {}
+ )
+ public void test_nullPlusNonNullIsNull() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullsAreSortedAtEnd()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "nullsAreSortedAtEnd",
+ args = {}
+ )
+ public void test_nullsAreSortedAtEnd() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullsAreSortedAtStart()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "nullsAreSortedAtStart",
+ args = {}
+ )
+ public void test_nullsAreSortedAtStart() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullsAreSortedHigh()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "nullsAreSortedHigh",
+ args = {}
+ )
+ public void test_nullsAreSortedHigh() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullsAreSortedLow()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "nullsAreSortedLow",
+ args = {}
+ )
+ public void test_nullsAreSortedLow() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#ownDeletesAreVisible(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Not Fully Supported.",
+ method = "ownDeletesAreVisible",
+ args = {int.class}
+ )
+ public void test_ownDeletesAreVisibleI() throws SQLException {
+ // NOT_FEASIBLE not supported
+// assertFalse(
+// "result set's own deletes are visible for TYPE_FORWARD_ONLY type",
+// meta.ownDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+// assertFalse(
+// "result set's own deletes are visible for TYPE_SCROLL_INSENSITIVE type",
+// meta.ownDeletesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+// assertFalse(
+// "result set's own deletes are visible for TYPE_SCROLL_SENSITIVE type",
+// meta.ownDeletesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+ assertFalse("result set's own deletes are visible for unknown type",
+ meta.ownDeletesAreVisible(100));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#ownInsertsAreVisible(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "not supported.",
+ method = "ownInsertsAreVisible",
+ args = {int.class}
+ )
+ public void test_ownInsertsAreVisibleI() throws SQLException {
+// assertFalse(
+// "result set's own inserts are visible for TYPE_FORWARD_ONLY type",
+// meta.ownInsertsAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+// assertFalse(
+// "result set's own inserts are visible for TYPE_SCROLL_INSENSITIVE type",
+// meta.ownInsertsAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+// assertFalse(
+// "result set's own inserts are visible for TYPE_SCROLL_SENSITIVE type",
+// meta.ownInsertsAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+ assertFalse("result set's own inserts are visible for unknown type",
+ meta.ownInsertsAreVisible(100));
+ }
+
+ /**
+ * @tests {@link java.sql.DatabaseMetaData#ownUpdatesAreVisible(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported. Verification with invalid parameters missed.",
+ method = "ownUpdatesAreVisible",
+ args = {int.class}
+ )
+ @KnownFailure("Not supported ops applied")
+ public void test_ownUpdatesAreVisibleI() throws SQLException {
+ // NOT_FEASIBLE not supported
+ assertFalse(
+ "result set's own updates are visible for TYPE_FORWARD_ONLY type",
+ meta.ownUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+ assertFalse(
+ "result set's own updates are visible for TYPE_SCROLL_INSENSITIVE type",
+ meta.ownUpdatesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+ assertFalse(
+ "result set's own updates are visible for TYPE_SCROLL_SENSITIVE type",
+ meta.ownUpdatesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+ assertFalse("result set's own updates are visible for unknown type",
+ meta.ownUpdatesAreVisible(100));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesLowerCaseIdentifiers()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "storesLowerCaseIdentifiers",
+ args = {}
+ )
+ public void test_storesLowerCaseIdentifiers() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesLowerCaseQuotedIdentifiers()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "storesLowerCaseQuotedIdentifiers",
+ args = {}
+ )
+ public void test_storesLowerCaseQuotedIdentifiers() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesUpperCaseIdentifiers()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "storesUpperCaseIdentifiers",
+ args = {}
+ )
+ public void test_storesUpperCaseIdentifiers() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesUpperCaseQuotedIdentifiers()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "storesUpperCaseQuotedIdentifiers",
+ args = {}
+ )
+ public void test_storesUpperCaseQuotedIdentifiers() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsANSI92EntryLevelSQL()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsANSI92EntryLevelSQL",
+ args = {}
+ )
+ public void test_supportsANSI92EntryLevelSQL() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsANSI92FullSQL()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsANSI92FullSQL",
+ args = {}
+ )
+ public void test_supportsANSI92FullSQL() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsANSI92IntermediateSQL()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsANSI92IntermediateSQL",
+ args = {}
+ )
+ public void test_supportsANSI92IntermediateSQL() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsAlterTableWithAddColumn()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsAlterTableWithAddColumn",
+ args = {}
+ )
+ public void test_supportsAlterTableWithAddColumn() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsAlterTableWithDropColumn()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsAlterTableWithDropColumn",
+ args = {}
+ )
+ public void test_supportsAlterTableWithDropColumn() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsBatchUpdates()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsBatchUpdates",
+ args = {}
+ )
+ public void test_supportsBatchUpdates() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInDataManipulation()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsCatalogsInDataManipulation",
+ args = {}
+ )
+ public void test_supportsCatalogsInDataManipulation() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInIndexDefinitions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsCatalogsInIndexDefinitions",
+ args = {}
+ )
+ public void test_supportsCatalogsInIndexDefinitions() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInPrivilegeDefinitions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsCatalogsInPrivilegeDefinitions",
+ args = {}
+ )
+ public void test_supportsCatalogsInPrivilegeDefinitions()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInProcedureCalls()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsCatalogsInProcedureCalls",
+ args = {}
+ )
+ public void test_supportsCatalogsInProcedureCalls() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInTableDefinitions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsCatalogsInTableDefinitions",
+ args = {}
+ )
+ public void test_supportsCatalogsInTableDefinitions() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsConvert()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsConvert",
+ args = {}
+ )
+ public void test_supportsConvert() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsConvert(int, int)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsConvert",
+ args = {int.class, int.class}
+ )
+ public void test_supportsConvertII() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCoreSQLGrammar()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsCoreSQLGrammar",
+ args = {}
+ )
+ public void test_supportsCoreSQLGrammar() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCorrelatedSubqueries()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsCorrelatedSubqueries",
+ args = {}
+ )
+ public void test_supportsCorrelatedSubqueries() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsDataDefinitionAndDataManipulationTransactions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsDataDefinitionAndDataManipulationTransactions",
+ args = {}
+ )
+ public void test_supportsDataDefinitionAndDataManipulationTransactions()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsDataManipulationTransactionsOnly()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsDataManipulationTransactionsOnly",
+ args = {}
+ )
+ public void test_supportsDataManipulationTransactionsOnly()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsDifferentTableCorrelationNames()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsDifferentTableCorrelationNames",
+ args = {}
+ )
+ public void test_supportsDifferentTableCorrelationNames()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsExtendedSQLGrammar()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsExtendedSQLGrammar",
+ args = {}
+ )
+ public void test_supportsExtendedSQLGrammar() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsFullOuterJoins()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsFullOuterJoins",
+ args = {}
+ )
+ public void test_supportsFullOuterJoins() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsGetGeneratedKeys()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsGetGeneratedKeys",
+ args = {}
+ )
+ public void test_supportsGetGeneratedKeys() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsGroupByBeyondSelect()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsGroupByBeyondSelect",
+ args = {}
+ )
+ public void test_supportsGroupByBeyondSelect() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsIntegrityEnhancementFacility()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsIntegrityEnhancementFacility",
+ args = {}
+ )
+ public void test_supportsIntegrityEnhancementFacility() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsLikeEscapeClause()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsLikeEscapeClause",
+ args = {}
+ )
+ public void test_supportsLikeEscapeClause() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsLimitedOuterJoins()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsLimitedOuterJoins",
+ args = {}
+ )
+ public void test_supportsLimitedOuterJoins() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMinimumSQLGrammar()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsMinimumSQLGrammar",
+ args = {}
+ )
+ public void test_supportsMinimumSQLGrammar() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMixedCaseIdentifiers()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsMixedCaseIdentifiers",
+ args = {}
+ )
+ public void test_supportsMixedCaseIdentifiers() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMixedCaseQuotedIdentifiers()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsMixedCaseQuotedIdentifiers",
+ args = {}
+ )
+ public void test_supportsMixedCaseQuotedIdentifiers() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMultipleOpenResults()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsMultipleOpenResults",
+ args = {}
+ )
+ public void test_supportsMultipleOpenResults() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMultipleResultSets()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsMultipleResultSets",
+ args = {}
+ )
+ public void test_supportsMultipleResultSets() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMultipleTransactions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsMultipleTransactions",
+ args = {}
+ )
+ public void test_supportsMultipleTransactions() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsNamedParameters()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsNamedParameters",
+ args = {}
+ )
+ public void test_supportsNamedParameters() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOpenCursorsAcrossCommit()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsOpenCursorsAcrossCommit",
+ args = {}
+ )
+ public void test_supportsOpenCursorsAcrossCommit() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOpenCursorsAcrossRollback()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsOpenCursorsAcrossRollback",
+ args = {}
+ )
+ public void test_supportsOpenCursorsAcrossRollback() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOpenStatementsAcrossCommit()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsOpenStatementsAcrossCommit",
+ args = {}
+ )
+ public void test_supportsOpenStatementsAcrossCommit() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOpenStatementsAcrossRollback()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsOpenStatementsAcrossRollback",
+ args = {}
+ )
+ public void test_supportsOpenStatementsAcrossRollback() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOuterJoins()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsOuterJoins",
+ args = {}
+ )
+ public void test_supportsOuterJoins() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsPositionedDelete()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsPositionedDelete",
+ args = {}
+ )
+ public void test_supportsPositionedDelete() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsPositionedUpdate()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsPositionedUpdate",
+ args = {}
+ )
+ public void test_supportsPositionedUpdate() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsResultSetConcurrency(int, int)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsResultSetConcurrency",
+ args = {int.class, int.class}
+ )
+ public void test_supportsResultSetConcurrencyII() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsResultSetHoldability(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsResultSetHoldability",
+ args = {int.class}
+ )
+ public void test_supportsResultSetHoldabilityI() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsResultSetType(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported. Verification with invalid parameters missed.",
+ method = "supportsResultSetType",
+ args = {int.class}
+ )
+ public void test_supportsResultSetTypeI() throws SQLException {
+ // NOT_FEASIBLE not supported
+// assertFalse("database supports TYPE_FORWARD_ONLY type", meta
+// .supportsResultSetType(ResultSet.TYPE_FORWARD_ONLY));
+// assertTrue("database doesn't support TYPE_SCROLL_INSENSITIVE type",
+// meta.supportsResultSetType(ResultSet.TYPE_SCROLL_INSENSITIVE));
+// assertFalse("database supports TYPE_SCROLL_SENSITIVE type", meta
+// .supportsResultSetType(ResultSet.TYPE_SCROLL_SENSITIVE));
+ assertFalse("database supports unknown type", meta
+ .supportsResultSetType(100));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSavepoints()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSavepoints",
+ args = {}
+ )
+ public void test_supportsSavepoints() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInDataManipulation()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSchemasInDataManipulation",
+ args = {}
+ )
+ public void test_supportsSchemasInDataManipulation() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInIndexDefinitions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSchemasInIndexDefinitions",
+ args = {}
+ )
+ public void test_supportsSchemasInIndexDefinitions() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInPrivilegeDefinitions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSchemasInPrivilegeDefinitions",
+ args = {}
+ )
+ public void test_supportsSchemasInPrivilegeDefinitions()
+ throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInProcedureCalls()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSchemasInProcedureCalls",
+ args = {}
+ )
+ public void test_supportsSchemasInProcedureCalls() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInTableDefinitions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSchemasInTableDefinitions",
+ args = {}
+ )
+ public void test_supportsSchemasInTableDefinitions() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsStatementPooling()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsStatementPooling",
+ args = {}
+ )
+ public void test_supportsStatementPooling() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsStoredProcedures()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsStoredProcedures",
+ args = {}
+ )
+ public void test_supportsStoredProcedures() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSubqueriesInComparisons()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSubqueriesInComparisons",
+ args = {}
+ )
+ public void test_supportsSubqueriesInComparisons() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSubqueriesInIns()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSubqueriesInIns",
+ args = {}
+ )
+ public void test_supportsSubqueriesInIns() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSubqueriesInQuantifieds()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsSubqueriesInQuantifieds",
+ args = {}
+ )
+ public void test_supportsSubqueriesInQuantifieds() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsTransactions()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsTransactions",
+ args = {}
+ )
+ public void test_supportsTransactions() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsUnion()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsUnion",
+ args = {}
+ )
+ public void test_supportsUnion() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsUnionAll()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "supportsUnionAll",
+ args = {}
+ )
+ public void test_supportsUnionAll() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#usesLocalFilePerTable()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "usesLocalFilePerTable",
+ args = {}
+ )
+ public void test_usesLocalFilePerTable() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#usesLocalFiles()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "usesLocalFiles",
+ args = {}
+ )
+ public void test_usesLocalFiles() throws SQLException {
+ // NOT_FEASIBLE: SQLITE does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxBinaryLiteralLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxBinaryLiteralLength",
+ args = {}
+ )
+ public void test_getMaxBinaryLiteralLength() throws SQLException {
+ assertTrue("Incorrect binary literal length", meta
+ .getMaxBinaryLiteralLength() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxCatalogNameLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxCatalogNameLength",
+ args = {}
+ )
+ public void test_getMaxCatalogNameLength() throws SQLException {
+ assertTrue("Incorrect name length", meta.getMaxCatalogNameLength() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxCharLiteralLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxCharLiteralLength",
+ args = {}
+ )
+ public void test_getMaxCharLiteralLength() throws SQLException {
+ assertTrue("Incorrect char literal length", meta
+ .getMaxCharLiteralLength() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnNameLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxColumnNameLength",
+ args = {}
+ )
+ public void test_getMaxColumnNameLength() throws SQLException {
+ assertTrue("Incorrect column name length", meta
+ .getMaxColumnNameLength() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInGroupBy()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxColumnsInGroupBy",
+ args = {}
+ )
+ public void test_getMaxColumnsInGroupBy() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInGroupBy() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInIndex()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxColumnsInIndex",
+ args = {}
+ )
+ public void test_getMaxColumnsInIndex() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInIndex() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInOrderBy()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxColumnsInOrderBy",
+ args = {}
+ )
+ public void test_getMaxColumnsInOrderBy() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInOrderBy() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInSelect()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxColumnsInSelect",
+ args = {}
+ )
+ public void test_getMaxColumnsInSelect() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInSelect() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInTable()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxColumnsInTable",
+ args = {}
+ )
+ public void test_getMaxColumnsInTable() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInTable() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxConnections()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxConnections",
+ args = {}
+ )
+ public void test_getMaxConnections() throws SQLException {
+ assertTrue("Incorrect number of connections",
+ meta.getMaxConnections() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxIndexLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getMaxIndexLength",
+ args = {}
+ )
+ public void test_getMaxIndexLength() throws SQLException {
+ assertTrue("Incorrect length of index", meta.getMaxIndexLength() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxProcedureNameLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getMaxProcedureNameLength",
+ args = {}
+ )
+ public void test_getMaxProcedureNameLength() throws SQLException {
+ assertTrue("Incorrect length of procedure name", meta
+ .getMaxProcedureNameLength() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxRowSize()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getMaxRowSize",
+ args = {}
+ )
+ public void test_getMaxRowSize() throws SQLException {
+ assertTrue("Incorrect size of row", meta.getMaxRowSize() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxSchemaNameLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getMaxSchemaNameLength",
+ args = {}
+ )
+ public void test_getMaxSchemaNameLength() throws SQLException {
+ assertTrue("Incorrect length of schema name", meta
+ .getMaxSchemaNameLength() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxStatementLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getMaxStatementLength",
+ args = {}
+ )
+ public void test_getMaxStatementLength() throws SQLException {
+ assertTrue("Incorrect length of statement", meta
+ .getMaxStatementLength() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxStatements()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getMaxStatements",
+ args = {}
+ )
+ public void test_getMaxStatements() throws SQLException {
+ assertTrue("Incorrect number of statements",
+ meta.getMaxStatements() == 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxTableNameLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getMaxTableNameLength",
+ args = {}
+ )
+ public void test_getMaxTableNameLength() throws SQLException {
+ assertTrue("Now supported", meta
+ .getMaxTableNameLength() == 0);
+
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getMaxTableNameLength();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxTablesInSelect()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getMaxTablesInSelect",
+ args = {}
+ )
+ public void test_getMaxTablesInSelect() throws SQLException {
+ assertTrue("Tables in select is now supported: change test implementation\"",
+ meta.getMaxTablesInSelect() == 0);
+
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getMaxTablesInSelect();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxUserNameLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "usernames not supported",
+ method = "getMaxUserNameLength",
+ args = {}
+ )
+ public void test_getMaxUserNameLength() throws SQLException {
+ assertTrue("Usernames are now supported: change test implementation",
+ meta.getMaxUserNameLength() == 0);
+
+ //Excpetion checking
+ conn.close();
+
+ try {
+ meta.getMaxUserNameLength();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+
+}
diff --git a/sql/src/test/java/tests/java/sql/DatabaseMetaDataTest.java b/sql/src/test/java/tests/java/sql/DatabaseMetaDataTest.java
new file mode 100755
index 0000000..fe7b227
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/DatabaseMetaDataTest.java
@@ -0,0 +1,2819 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package tests.java.sql;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Random;
+import java.util.StringTokenizer;
+
+@TestTargetClass(DatabaseMetaData.class)
+public class DatabaseMetaDataTest extends TestCase {
+ private static String VIEW_NAME = "myView";
+
+ private static String CREATE_VIEW_QUERY = "CREATE VIEW " + VIEW_NAME
+ + " AS SELECT * FROM " + DatabaseCreator.TEST_TABLE1;
+
+ private static String DROP_VIEW_QUERY = "DROP VIEW " + VIEW_NAME;
+
+ protected static Connection conn;
+
+ protected static DatabaseMetaData meta;
+
+ protected static Statement statement;
+
+ protected static Statement statementForward;
+
+ private static int id = 1;
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ DatabaseMetaDataTest.class)) {
+ protected void setUp() {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ meta = conn.getMetaData();
+ statement = conn.createStatement();
+ createTestTables();
+ } catch (SQLException e) {
+ System.out.println("Error in test setup: "+e.getMessage());
+ }
+ }
+
+ protected void tearDown() {
+ try {
+ conn = Support_SQL.getConnection();
+ meta = conn.getMetaData();
+ statement = conn.createStatement();
+ deleteTestTables();
+ } catch (SQLException e) {
+ System.out.println("Error in teardown: "+e.getMessage());
+ } finally {
+ try {
+ conn.close();
+ } catch (SQLException e) {
+ }
+ }
+ }
+
+ private void createTestTables() {
+ try {
+ ResultSet userTab = meta.getTables(null, null, null, null);
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE3)) {
+ statement.execute(DatabaseCreator.DROP_TABLE3);
+ } else if (tableName.equals(VIEW_NAME)) {
+ statement.execute(DROP_VIEW_QUERY);
+ }
+ }
+ userTab.close();
+ statement.execute(DatabaseCreator.CREATE_TABLE3);
+ statement.execute(DatabaseCreator.CREATE_TABLE1);
+ statement.execute(CREATE_VIEW_QUERY);
+ meta = conn.getMetaData();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ private void deleteTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ statement.execute(DatabaseCreator.DROP_TABLE3);
+ statement.execute(DROP_VIEW_QUERY);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ } finally {
+ try {
+ if (! conn.isClosed()) {
+ conn.close();
+ }
+ } catch (SQLException e) {
+
+ }
+ }
+ }
+ };
+ return setup;
+ }
+
+ public void setUp() {
+ try {
+ super.setUp();
+ try {
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ statementForward = conn.createStatement(
+ ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_UPDATABLE);
+ meta = conn.getMetaData();
+
+ assertFalse(conn.isClosed());
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+
+ } catch (Exception e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * @tests {@link java.sql.DatabaseMetaData #getBestRowIdentifier(java.lang.String,
+ * java.lang.String, java.lang.String, int, boolean) }
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Not All variants of parameters can be tested: updates on resultSets are not supported.",
+ method = "getBestRowIdentifier",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, int.class, boolean.class}
+ )
+ public void test_getBestRowIdentifierLjava_lang_StringLjava_lang_StringLjava_lang_StringIZ()
+ throws SQLException {
+ ResultSet result = statementForward.executeQuery("SELECT * FROM "
+ + DatabaseCreator.TEST_TABLE1);
+
+ // TODO not supported
+ // try {
+ // result.moveToInsertRow();
+ // result.updateInt("id", 1234567);
+ // result.updateString("field1", "test1");
+ // result.insertRow();
+ // } catch (SQLException e) {
+ // fail("Unexpected SQLException " + e.toString());
+ // }
+
+ result.close();
+
+ ResultSet rs = meta.getBestRowIdentifier(null, null,
+ DatabaseCreator.TEST_TABLE1, DatabaseMetaData.bestRowSession,
+ true);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ assertTrue("Rows not obtained", rs.next());
+ int col = rsmd.getColumnCount();
+ assertEquals("Incorrect number of columns", 8, col);
+ String[] columnNames = {
+ "SCOPE", "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME",
+ "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_DIGITS",
+ "PSEUDO_COLUMN"};
+ for (int c = 1; c <= col; ++c) {
+ assertEquals("Incorrect column name", columnNames[c - 1], rsmd
+ .getColumnName(c));
+ }
+ assertEquals("Incorrect scope", DatabaseMetaData.bestRowSession, rs
+ .getShort("SCOPE"));
+ assertEquals("Incorrect column name", "_ROWID_", rs.getString("COLUMN_NAME"));
+ assertEquals("Incorrect data type", java.sql.Types.INTEGER, rs.getInt("DATA_TYPE"));
+ assertEquals("Incorrect type name", "INTEGER", rs.getString("TYPE_NAME"));
+ rs.close();
+
+ // Exception testing
+ conn.close();
+
+ try {
+ meta.getColumns(null, null,
+ DatabaseCreator.TEST_TABLE1, "%");
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getColumns(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Tests Columns and search for arbitrary columns. test fails: Columns Name's not according to spec.",
+ method = "getColumns",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ @KnownFailure("Not supported : pattern with %")
+ public void test_getColumnsArbitrary() throws SQLException {
+ ResultSet setAllNull = null;
+ ResultSet setMixed = null;
+ ResultSet allArbitrary = null;
+ String[] tablesName = {DatabaseCreator.TEST_TABLE1,
+ DatabaseCreator.TEST_TABLE3};
+ Arrays.sort(tablesName);
+ int setSize = 0;
+ try {
+ allArbitrary = meta.getColumns("%","%","%","%");
+ assertNotNull(allArbitrary);
+ checkColumnsShape(allArbitrary);
+ setSize = crossCheckGetColumnsAndResultSetMetaData(allArbitrary, false);
+ assertEquals(6, setSize);
+
+ setMixed = meta.getColumns(null, null,"%","%");
+ assertNotNull(setMixed);
+ checkColumnsShape(setMixed);
+ setSize = crossCheckGetColumnsAndResultSetMetaData(setMixed, false);
+ assertEquals(6, setSize);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ // Exception testing
+ conn.close();
+
+ try {
+ meta.getColumns(null, null,
+ DatabaseCreator.TEST_TABLE1, "%");
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getColumns(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Tests getColumns with no Catalog and Schema. test fails on arguments: '', '', '%', '%'",
+ method = "getColumns",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ @KnownFailure("Not supported ops applied: test fails on arguments: '', '', '%', '%' ")
+ public void test_getColumnsTableWithNoCatalogSchema() throws SQLException{
+
+ try {
+ ResultSet noSchemaTable = meta.getColumns("", "",
+ DatabaseCreator.TEST_TABLE1, "fkey");
+ assertNotNull(noSchemaTable);
+ noSchemaTable.last();
+ int size = noSchemaTable.getRow();
+ assertEquals(
+ "Does not support empty string as input parameter or Wildcard %",
+ 1, size);
+
+
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ ResultSet noSchemaTable = meta.getColumns("", "",
+ DatabaseCreator.TEST_TABLE1, "%");
+ assertNotNull(noSchemaTable);
+ noSchemaTable.last();
+ int size = noSchemaTable.getRow();
+ assertEquals(
+ "Does not support empty string as input parameter or Wildcard %",
+ 5, size);
+
+
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ ResultSet noSchemaTable = meta.getColumns("", "", "%", "%");
+ assertNotNull(noSchemaTable);
+ noSchemaTable.last();
+ int size = noSchemaTable.getRow();
+ assertEquals(
+ "Does not support double Wildcard '%' as input",
+ 6, size);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getColumns(null, null,
+ DatabaseCreator.TEST_TABLE1, "%");
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getColumns(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "tests for specific tables. test fails: invalid nullable value.",
+ method = "getColumns",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ @KnownFailure("Wildcard operator does not seem wo work correctly.")
+ public void test_getColumnsSpecific() throws SQLException {
+ String[] tablesName = {
+ DatabaseCreator.TEST_TABLE1, DatabaseCreator.TEST_TABLE3};
+ String[] fields = {"id", "field1", "field2", "field3", "fkey"};
+ String[] nullable = {"YES", "NO",""};
+ int[] nullableInt = {
+ DatabaseMetaData.columnNoNulls,
+ DatabaseMetaData.columnNullable,
+ DatabaseMetaData.columnNullableUnknown};
+ Arrays.sort(tablesName);
+ Arrays.sort(fields);
+ Arrays.sort(nullableInt);
+ Arrays.sort(nullable);
+ int countSingle = 0;
+ int countAll1 = 0;
+ int countAll2 = 0;
+
+ try {
+ ResultSet rs = meta.getColumns(null, null,
+ DatabaseCreator.TEST_TABLE1, "%");
+
+ while (rs.next()) {
+ assertTrue("Invalid table name", Arrays.binarySearch(
+ tablesName, rs.getString("TABLE_NAME")) > -1);
+ assertTrue("Invalid field name", Arrays.binarySearch(fields, rs
+ .getString("COLUMN_NAME")) > -1);
+ assertTrue("Invalid nullable value", Arrays.binarySearch(
+ nullable, rs.getString("IS_NULLABLE")) > -1);
+ assertTrue("Invalid nullable code", Arrays.binarySearch(
+ nullableInt, rs.getInt("NULLABLE")) > -1);
+ countSingle++;
+ }
+ assertEquals("Not all results are found", 5, countSingle);
+ rs.close();
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ ResultSet rs = meta.getColumns(null, null, "%"+DatabaseCreator.CREATE_TABLE1.substring(0, 3)+"%","%" );
+ while (rs.next()) {
+ assertTrue("Wrong table name", Arrays.binarySearch(tablesName,
+ rs.getString("TABLE_NAME")) > -1);
+ countAll1++;
+ }
+ assertEquals("Not all results are found", 6, countAll1);
+ rs.close();
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ ResultSet rs = meta.getColumns(null, null, "%TEST_%", "%");
+
+ while (rs.next()) {
+ assertTrue("Wrong table name", Arrays.binarySearch(tablesName,
+ rs.getString("TABLE_NAME")) > -1);
+ countAll2++;
+ }
+ assertEquals("Not all results are found", 6, countAll2);
+ rs.close();
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getColumns(null, null,
+ DatabaseCreator.TEST_TABLE1, "%");
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+
+
+ }
+
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getConnection()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getConnection",
+ args = {}
+ )
+ public void test_getConnection() throws SQLException {
+ assertEquals("Incorrect connection value", conn, meta.getConnection());
+
+ // Exception checking
+ conn.close();
+
+ try {
+ Connection con = meta.getConnection();
+ assertTrue(con.isClosed());
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getCrossReference(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test fails: Foreign keys not supported",
+ method = "getCrossReference",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ @KnownFailure("(Ticket 91) Tables apply foreign key constraint. Catalogs not supported")
+ public void test_getCrossReferenceLjava_lang_StringLjava_lang_StringLjava_lang_StringLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ ResultSet rs = meta.getCrossReference(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE3, conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ assertTrue("Rows do not obtained", rs.next());
+ int col = rsmd.getColumnCount();
+ assertEquals("Incorrect number of columns", 14, col);
+ String[] columnNames = { "PKTABLE_CAT", "PKTABLE_SCHEM",
+ "PKTABLE_NAME", "PKCOLUMN_NAME", "FKTABLE_CAT",
+ "FKTABLE_SCHEM", "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
+ "UPDATE_RULE", "DELETE_RULE", "FK_NAME", "PK_NAME",
+ "DEFERRABILITY" };
+ for (int c = 1; c <= col; ++c) {
+ assertEquals("Incorrect column name", columnNames[c - 1], rsmd
+ .getColumnName(c));
+ }
+// TODO getCatalog is not supported
+// assertEquals("Incorrect primary key table catalog", conn.getCatalog(),
+// rs.getString("PKTABLE_CAT"));
+ assertEquals("Incorrect primary key table schema", "", rs
+ .getString("PKTABLE_SCHEM"));
+ assertEquals("Incorrect primary key table name",
+ DatabaseCreator.TEST_TABLE3, rs.getString("PKTABLE_NAME"));
+ assertEquals("Incorrect primary key column name", "fkey", rs
+ .getString("PKCOLUMN_NAME"));
+ // TODO getCatalog is not supported
+// assertEquals("Incorrect foreign key table catalog", conn.getCatalog(),
+// rs.getString("FKTABLE_CAT"));
+ assertEquals("Incorrect foreign key table schema", "", rs
+ .getString("FKTABLE_SCHEM"));
+ assertEquals("Incorrect foreign key table name",
+ DatabaseCreator.TEST_TABLE1, rs.getString("FKTABLE_NAME"));
+ assertEquals("Incorrect foreign key column name", "fk", rs
+ .getString("FKCOLUMN_NAME"));
+ assertEquals("Incorrect sequence number within foreign key", 1, rs
+ .getShort("KEY_SEQ"));
+ assertEquals("Incorrect update rule value",
+ DatabaseMetaData.importedKeyNoAction, rs
+ .getShort("UPDATE_RULE"));
+ assertEquals("Incorrect delete rule value",
+ DatabaseMetaData.importedKeyNoAction, rs
+ .getShort("DELETE_RULE"));
+ assertNull("Incorrect foreign key name", rs.getString("FK_NAME"));
+ assertNull("Incorrect primary key name", rs.getString("PK_NAME"));
+ assertEquals("Incorrect deferrability",
+ DatabaseMetaData.importedKeyNotDeferrable, rs
+ .getShort("DEFERRABILITY"));
+ rs.close();
+
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getCrossReference(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE3, conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1);
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getCrossReference(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE3, conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1);
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDatabaseMajorVersion()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getDatabaseMajorVersion",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getDatabaseMajorVersion() throws SQLException {
+ assertTrue("Incorrdct database major version", meta
+ .getDatabaseMajorVersion() >= 0);
+ /*
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getDatabaseMajorVersion();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDatabaseMinorVersion()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getDatabaseMinorVersion",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getDatabaseMinorVersion() throws SQLException {
+ assertTrue("Incorrect database minor version", meta
+ .getDatabaseMinorVersion() >= 0);
+
+ /*
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getDatabaseMinorVersion();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDatabaseProductName()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getDatabaseProductName",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getDatabaseProductName() throws SQLException {
+ assertTrue("Incorrect database product name", !"".equals(meta
+ .getDatabaseProductName().trim()));
+
+ /*
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getDatabaseProductName();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDatabaseProductVersion()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getDatabaseProductVersion",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getDatabaseProductVersion() throws SQLException {
+ assertTrue("Incorrect database product version", !"".equals(meta
+ .getDatabaseProductVersion().trim()));
+ /*
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getDatabaseProductVersion();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDefaultTransactionIsolation()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getDefaultTransactionIsolation",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getDefaultTransactionIsolation() throws SQLException {
+ int defaultLevel = meta.getDefaultTransactionIsolation();
+ switch (defaultLevel) {
+ case Connection.TRANSACTION_NONE:
+ case Connection.TRANSACTION_READ_COMMITTED:
+ case Connection.TRANSACTION_READ_UNCOMMITTED:
+ case Connection.TRANSACTION_REPEATABLE_READ:
+ case Connection.TRANSACTION_SERIALIZABLE:
+ // these levels are OK
+ break;
+ default:
+ fail("Incorrect value of default transaction isolation level");
+ }
+
+ /*
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getDefaultTransactionIsolation();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDriverMajorVersion()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDriverMajorVersion",
+ args = {}
+ )
+ public void test_getDriverMajorVersion() throws SQLException {
+ assertTrue("Incorrect driver major version", meta
+ .getDriverMajorVersion() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDriverMinorVersion()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDriverMinorVersion",
+ args = {}
+ )
+ public void test_getDriverMinorVersion() {
+ assertTrue("Incorrect driver minor version", meta
+ .getDriverMinorVersion() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDriverName()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getDriverName",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getDriverName() throws SQLException {
+ String driverName = meta.getDriverName();
+ assertTrue("Incorrect driver name", driverName.trim().startsWith(
+ "SQLite"));
+
+ /*
+ // Exception checking
+ conn.close();
+
+ try {
+ meta.getDriverName();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDriverVersion()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDriverVersion",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getDriverVersion() throws SQLException {
+ assertTrue("Incorrect driver version", !"".equals(meta
+ .getDriverVersion().trim()));
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getDriverVersion();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ */
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getImportedKeys(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "Test fails: Keys are not supported",
+ method = "getImportedKeys",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ @KnownFailure("Keys are not supported: Ticket 91")
+ public void test_getImportedKeysLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ ResultSet rs = meta.getImportedKeys(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ assertTrue("Rows do not obtained", rs.next());
+ int col = rsmd.getColumnCount();
+ assertEquals("Incorrect number of columns", 14, col);
+ String[] columnNames = { "PKTABLE_CAT", "PKTABLE_SCHEM",
+ "PKTABLE_NAME", "PKCOLUMN_NAME", "FKTABLE_CAT",
+ "FKTABLE_SCHEM", "FKTABLE_NAME", "FKCOLUMN_NAME", "KEY_SEQ",
+ "UPDATE_RULE", "DELETE_RULE", "FK_NAME", "PK_NAME",
+ "DEFERRABILITY" };
+ for (int c = 1; c <= col; ++c) {
+ assertEquals("Incorrect column name", columnNames[c - 1], rsmd
+ .getColumnName(c));
+ }
+// TODO getCatalog is not supported
+// assertEquals("Incorrect primary key table catalog", conn.getCatalog(),
+// rs.getString("PKTABLE_CAT"));
+ assertEquals("Incorrect primary key table schema", "", rs
+ .getString("PKTABLE_SCHEM"));
+ assertEquals("Incorrect primary key table name",
+ DatabaseCreator.TEST_TABLE3, rs.getString("PKTABLE_NAME"));
+ assertEquals("Incorrect primary key column name", "fkey", rs
+ .getString("PKCOLUMN_NAME"));
+// assertEquals("Incorrect foreign key table catalog", conn.getCatalog(),
+// rs.getString("FKTABLE_CAT"));
+ assertEquals("Incorrect foreign key table schema", "", rs
+ .getString("FKTABLE_SCHEM"));
+ assertEquals("Incorrect foreign key table name",
+ DatabaseCreator.TEST_TABLE1, rs.getString("FKTABLE_NAME"));
+ assertEquals("Incorrect foreign key column name", "fk", rs
+ .getString("FKCOLUMN_NAME"));
+ assertEquals("Incorrect sequence number within foreign key", 1, rs
+ .getShort("KEY_SEQ"));
+ assertEquals("Incorrect update rule value",
+ DatabaseMetaData.importedKeyNoAction, rs
+ .getShort("UPDATE_RULE"));
+ assertEquals("Incorrect delete rule value",
+ DatabaseMetaData.importedKeyNoAction, rs
+ .getShort("DELETE_RULE"));
+ // assertNotNull("Incorrect foreign key name", rs.getString("FK_NAME"));
+ assertEquals("Incorrect primary key name", null, rs
+ .getString("PK_NAME"));
+ assertEquals("Incorrect deferrability",
+ DatabaseMetaData.importedKeyNotDeferrable, rs
+ .getShort("DEFERRABILITY"));
+ rs.close();
+
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getImportedKeys(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1);
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxCursorNameLength()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMaxCursorNameLength",
+ args = {}
+ )
+ public void test_getMaxCursorNameLength() throws SQLException {
+ int nameLength = meta.getMaxCursorNameLength();
+ if (nameLength > 0) {
+ try {
+ statement.setCursorName(new String(new byte[nameLength + 1]));
+ fail("Expected SQLException was not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+ } else if (nameLength < 0) {
+ fail("Incorrect length of cursor name");
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getJDBCMinorVersion()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getJDBCMinorVersion",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getJDBCMinorVersion() throws SQLException {
+ assertTrue("Incorrect JDBC minor version",
+ meta.getJDBCMinorVersion() >= 0);
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getJDBCMinorVersion();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getJDBCMajorVersion()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getJDBCMajorVersion",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getJDBCMajorVersion() throws SQLException {
+ assertTrue("Incorrect JDBC major version",
+ meta.getJDBCMajorVersion() >= 0);
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getJDBCMajorVersion();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getNumericFunctions()
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Test fails. Not implemented correctly. SQLException checking test fails",
+ method = "getNumericFunctions",
+ args = {}
+ )
+ @KnownFailure("Not supported feature, Ticket 98. Broken because "+
+ "NUMERIC_FUNCTIONS not complete. When fixed change to @KnownFailure")
+ public void test_getNumericFunctions() throws SQLException {
+ escapedFunctions(NUMERIC_FUNCTIONS, meta.getNumericFunctions());
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getNumericFunctions();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getPrimaryKeys(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Functionality test fails: keys and catalogs are not supported. SQLException checking test fails",
+ method = "getPrimaryKeys",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class}
+ )
+ @KnownFailure(" Ticket 91 : relies on not supported features: getCatalog, keys")
+ public void test_getPrimaryKeysLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ ResultSet rs = meta.getPrimaryKeys(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ assertTrue("Rows not obtained", rs.next());
+ int col = rsmd.getColumnCount();
+ assertEquals("Incorrect number of columns", 6, col);
+ String[] columnNames = { "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "KEY_SEQ", "PK_NAME" };
+ for (int c = 1; c <= col; ++c) {
+ assertEquals("Incorrect column name", columnNames[c - 1], rsmd
+ .getColumnName(c));
+ }
+// assertEquals("Incorrect table catalogue", conn.getCatalog(), rs
+// .getString("TABLE_CAT").toLowerCase());
+ assertEquals("Incorrect table schema", "", rs
+ .getString("TABLE_SCHEM"));
+ assertEquals("Incorrect table name", DatabaseCreator.TEST_TABLE1, rs
+ .getString("TABLE_NAME").toLowerCase());
+ assertEquals("Incorrect column name", "id", rs.getString("COLUMN_NAME")
+ .toLowerCase());
+ assertEquals("Incorrect sequence number", 1, rs.getShort("KEY_SEQ"));
+ // assertEquals("Incorrect primary key name", "primary", rs.getString(
+ // "PK_NAME").toLowerCase());
+ rs.close();
+
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getPrimaryKeys(conn.getCatalog(), null,
+ DatabaseCreator.TEST_TABLE1);
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getResultSetHoldability()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getResultSetHoldability",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getResultSetHoldability() throws SQLException {
+ int hdb = meta.getResultSetHoldability();
+ switch (hdb) {
+ case ResultSet.HOLD_CURSORS_OVER_COMMIT:
+ case ResultSet.CLOSE_CURSORS_AT_COMMIT:
+ // these holdabilities are OK
+ break;
+ default:
+ fail("Incorrect value of holdability");
+ }
+ assertFalse("Incorrect result set holdability", meta
+ .supportsResultSetHoldability(hdb));
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getResultSetHoldability();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSQLKeywords()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getSQLKeywords",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getSQLKeywords() throws SQLException {
+ assertTrue("Incorrect SQL keywords", !"".equals(meta.getSQLKeywords()
+ .trim()));
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getSQLKeywords();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSQLStateType()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getSQLStateType",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getSQLStateType() throws SQLException {
+ int type = meta.getSQLStateType();
+ switch (type) {
+ case DatabaseMetaData.sqlStateSQL99:
+ case DatabaseMetaData.sqlStateXOpen:
+ // these types are OK
+ break;
+ default:
+ fail("Incorrect SQL state types");
+ }
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getSQLStateType();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSchemas()
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getSchemas",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getSchemas() throws SQLException {
+ ResultSet rs = meta.getSchemas();
+ ResultSetMetaData rsmd = rs.getMetaData();
+ assertTrue("Rows do not obtained", rs.next());
+ int col = rsmd.getColumnCount();
+ assertEquals("Incorrect number of columns", 1, col);
+ String[] columnNames = { "TABLE_SCHEM", "TABLE_CATALOG" };
+ for (int c = 1; c <= col; ++c) {
+ assertEquals("Incorrect column name", columnNames[c - 1], rsmd
+ .getColumnName(c));
+ }
+ rs.close();
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getSchemas();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSearchStringEscape()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getSearchStringEscape",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getSearchStringEscape() throws SQLException {
+ assertTrue("Incorrect search string escape", !"".equals(meta
+ .getSearchStringEscape().trim()));
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getSearchStringEscape();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getStringFunctions()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Functionality test fails. SQLException checking test fails",
+ method = "getStringFunctions",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void test_getStringFunctions() throws SQLException {
+ escapedFunctions(STRING_FUNCTIONS, meta.getStringFunctions());
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getStringFunctions();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSystemFunctions()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Functionality test fails. SQLException checking test fails",
+ method = "getSystemFunctions",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void test_getSystemFunctions() throws SQLException {
+ escapedFunctions(SYSTEM_FUNCTIONS, meta.getSystemFunctions());
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getSystemFunctions();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getTableTypes()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getTableTypes",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getTableTypes() throws SQLException {
+ String[] tableTypes = { "LOCAL TEMPORARY", "TABLE", "VIEW" };
+ ResultSet rs = meta.getTableTypes();
+
+ while (rs.next()) {
+ assertTrue("Wrong table type", Arrays.binarySearch(tableTypes, rs
+ .getString("TABLE_TYPE")) > -1);
+ }
+ rs.close();
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getTableTypes();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getTables(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String[])
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test fails.",
+ method = "getTables",
+ args = {java.lang.String.class, java.lang.String.class, java.lang.String.class, java.lang.String[].class}
+ )
+ @KnownFailure("If no schema is associated: returns empty string or shouldn't null be returned?. Ticket 98")
+ public void test_getTablesLjava_lang_StringLjava_lang_StringLjava_lang_String$Ljava_lang_String()
+ throws SQLException {
+ String[] tablesName = {
+ VIEW_NAME, DatabaseCreator.TEST_TABLE1,
+ DatabaseCreator.TEST_TABLE3};
+ String[] tablesType = {"TABLE", "VIEW"};
+ Arrays.sort(tablesName);
+ Arrays.sort(tablesType);
+
+ // case 1. get all tables. There are two tables and one view in the
+ // database
+ ResultSet rs = meta.getTables(null, null, null, null);
+ while (rs.next()) {
+ assertTrue("Wrong table name", Arrays.binarySearch(tablesName, rs
+ .getString("TABLE_NAME")) > -1);
+ //No Schema associated
+// assertNull("Wrong table schema: "+rs.getString("TABLE_SCHEM"), rs.getString("TABLE_SCHEM"));
+ assertTrue("Wrong table type", Arrays.binarySearch(tablesType, rs
+ .getString("TABLE_TYPE")) > -1);
+ assertEquals("Wrong parameter REMARKS", "", rs.getString("REMARKS"));
+ }
+ rs.close();
+
+ // case 2. get tables with specified types. There are no tables of such
+ // types
+ rs = meta.getTables(conn.getCatalog(), null, null, new String[] {
+ "SYSTEM TABLE", "LOCAL TEMPORARY" });
+ assertFalse("Some tables exist", rs.next());
+ rs.close();
+
+ // case 3. get tables with specified types. There is a table of such
+ // types
+ rs = meta.getTables(conn.getCatalog(), null, null, new String[] {
+ "VIEW", "LOCAL TEMPORARY" });
+
+ assertTrue("No tables exist", rs.next());
+ assertEquals("Wrong table name", VIEW_NAME, rs.getString("TABLE_NAME"));
+// assertNull("Wrong table schema: "+rs.getString("TABLE_SCHEM"), rs.getString("TABLE_SCHEM"));
+ assertEquals("Wrong table type", "VIEW", rs.getString("TABLE_TYPE"));
+ assertEquals("Wrong parameter REMARKS", "", rs.getString("REMARKS"));
+ assertFalse("Wrong size of result set", rs.next());
+ assertFalse("Some tables exist", rs.next());
+ rs.close();
+
+ // case 4. get all tables using tables pattern.
+ // There are two tables and one view in the database
+ rs = meta.getTables(null, null, "%", null);
+
+ while (rs.next()) {
+ assertTrue("Wrong table name", Arrays.binarySearch(tablesName, rs
+ .getString("TABLE_NAME")) > -1);
+// assertNull("Wrong table schema ", rs.getString("TABLE_SCHEM"));
+ assertTrue("Wrong table type", Arrays.binarySearch(tablesType, rs
+ .getString("TABLE_TYPE")) > -1);
+ assertEquals("Wrong parameter REMARKS", "", rs.getString("REMARKS"));
+ }
+ rs.close();
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getTables(null, null, null, null);
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getTimeDateFunctions()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Does not return any functions. test fails. SQLException checking test fails",
+ method = "getTimeDateFunctions",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void test_getTimeDateFunctions() throws SQLException {
+
+ escapedFunctions(TIMEDATE_FUNCTIONS, meta.getTimeDateFunctions());
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getTimeDateFunctions();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getTypeInfo()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getTypeInfo",
+ args = {}
+ )
+ public void test_getTypeInfo() throws SQLException {
+ insertNewRecord();
+
+ ResultSet rs = meta.getTypeInfo();
+
+ final String[] names = { "TYPE_NAME", "DATA_TYPE", "PRECISION",
+ "LITERAL_PREFIX", "LITERAL_SUFFIX", "CREATE_PARAMS",
+ "NULLABLE", "CASE_SENSITIVE", "SEARCHABLE",
+ "UNSIGNED_ATTRIBUTE", "FIXED_PREC_SCALE", "AUTO_INCREMENT",
+ "LOCAL_TYPE_NAME", "MINIMUM_SCALE", "MAXIMUM_SCALE",
+ "SQL_DATA_TYPE", "SQL_DATETIME_SUB", "NUM_PREC_RADIX" };
+ Arrays.sort(names);
+
+ for (int i = 0; i < rs.getMetaData().getColumnCount(); i++) {
+ assertTrue("wrong column was return", Arrays.binarySearch(names, rs
+ .getMetaData().getColumnName(i + 1)) > -1);
+ }
+
+ int[] types = { Types.ARRAY, Types.BIGINT, Types.BINARY, Types.BIT,
+ Types.BLOB, Types.BOOLEAN, Types.CHAR, Types.CLOB,
+ Types.DATALINK, Types.DATE, Types.DECIMAL, Types.DISTINCT,
+ Types.DOUBLE, Types.FLOAT, Types.INTEGER, Types.JAVA_OBJECT,
+ Types.LONGVARBINARY, Types.LONGVARCHAR, Types.NULL,
+ Types.NUMERIC, Types.OTHER, Types.REAL, Types.REF,
+ Types.SMALLINT, Types.STRUCT, Types.TIME, Types.TIMESTAMP,
+ Types.TINYINT, Types.VARBINARY, Types.VARCHAR };
+ Arrays.sort(types);
+
+ while (rs.next()) {
+ assertTrue("wrong type was return ", Arrays.binarySearch(types, rs
+ .getInt("DATA_TYPE")) > -1);
+ }
+ rs.close();
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getTypeInfo();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getURL()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getURL",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getURL() throws SQLException {
+ assertEquals("Wrong url", Support_SQL.sqlUrl, meta.getURL());
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getURL();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getUserName()
+ *
+ * NOT_FEASIBLE not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "getUserName",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_getUserName() throws SQLException {
+ assertEquals("Wrong user name", Support_SQL.sqlUser, meta.getUserName());
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.getUserName();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#insertsAreDetected(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "insertsAreDetected",
+ args = {int.class}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_insertsAreDetectedI() throws SQLException {
+ assertFalse(
+ "visible row insert can be detected for TYPE_FORWARD_ONLY type",
+ meta.insertsAreDetected(ResultSet.TYPE_FORWARD_ONLY));
+ assertFalse(
+ "visible row insert can be detected for TYPE_SCROLL_INSENSITIVE type",
+ meta.insertsAreDetected(ResultSet.TYPE_SCROLL_INSENSITIVE));
+ assertFalse(
+ "visible row insert can be detected for TYPE_SCROLL_SENSITIVE type",
+ meta.insertsAreDetected(ResultSet.TYPE_SCROLL_SENSITIVE));
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.insertsAreDetected(ResultSet.TYPE_SCROLL_SENSITIVE);
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#isReadOnly()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "isReadOnly",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_isReadOnly() throws SQLException {
+ assertFalse("database is not read-only", meta.isReadOnly());
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.isReadOnly();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#othersDeletesAreVisible(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails.",
+ method = "othersDeletesAreVisible",
+ args = {int.class}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_othersDeletesAreVisibleI() throws SQLException {
+ assertFalse(
+ "deletes made by others are visible for TYPE_FORWARD_ONLY type",
+ meta.othersDeletesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+ assertFalse(
+ "deletes made by others are visible for TYPE_SCROLL_INSENSITIVE type",
+ meta.othersDeletesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+ assertFalse(
+ "deletes made by others are visible for TYPE_SCROLL_SENSITIVE type",
+ meta.othersDeletesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ assertFalse("inserts made by others are visible for unknown type", meta
+ .othersDeletesAreVisible(ResultSet.CONCUR_READ_ONLY));
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#othersInsertsAreVisible(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "othersInsertsAreVisible",
+ args = {int.class}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_othersInsertsAreVisibleI() throws SQLException {
+ assertFalse(
+ "inserts made by others are visible for TYPE_FORWARD_ONLY type",
+ meta.othersInsertsAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+ assertFalse(
+ "inserts made by others are visible for TYPE_SCROLL_INSENSITIVE type",
+ meta.othersInsertsAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+ assertFalse(
+ "inserts made by others are visible for TYPE_SCROLL_SENSITIVE type",
+ meta.othersInsertsAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ assertFalse("inserts made by others are visible for unknown type", meta
+ .othersInsertsAreVisible(ResultSet.CONCUR_READ_ONLY));
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#othersUpdatesAreVisible(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = " Verification with invalid parameters missed.",
+ method = "othersUpdatesAreVisible",
+ args = {int.class}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_othersUpdatesAreVisibleI() throws SQLException {
+ assertFalse(
+ "updates made by others are visible for TYPE_FORWARD_ONLY type",
+ meta.othersUpdatesAreVisible(ResultSet.TYPE_FORWARD_ONLY));
+ assertFalse(
+ "updates made by others are visible for TYPE_SCROLL_INSENSITIVE type",
+ meta.othersUpdatesAreVisible(ResultSet.TYPE_SCROLL_INSENSITIVE));
+ assertFalse(
+ "updates made by others are visible for TYPE_SCROLL_SENSITIVE type",
+ meta.othersUpdatesAreVisible(ResultSet.TYPE_SCROLL_SENSITIVE));
+
+ //Exception checking
+
+ try {
+ assertFalse("updates made by others are visible for unknown type", meta
+ .othersUpdatesAreVisible(ResultSet.CONCUR_READ_ONLY));
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesMixedCaseQuotedIdentifiers()
+ */
+ @TestTargets ({
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "storesMixedCaseQuotedIdentifiers",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "storesMixedCaseIdentifiers",
+ args = {}
+ )
+ })
+ public void test_storesMixedCaseQuotedIdentifiers() throws SQLException {
+ String quote = meta.getIdentifierQuoteString();
+
+
+
+ insertNewRecord();
+
+ String selectQuery = "SELECT " + quote + "fieLD1" + quote + " FROM "
+ + DatabaseCreator.TEST_TABLE1;
+
+ try {
+ statement.executeQuery(selectQuery);
+ if (!meta.storesMixedCaseIdentifiers()) {
+ fail("mixed case is supported");
+ }
+ } catch (SQLException e) {
+ if (meta.storesMixedCaseQuotedIdentifiers()) {
+ fail("quoted case is not supported");
+ }
+ }
+
+ //Exception checking
+ /*
+ conn.close();
+
+ try {
+ meta.storesMixedCaseIdentifiers();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ conn.close();
+
+ try {
+ meta.storesMixedCaseQuotedIdentifiers();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Exception test fails.",
+ method = "getIdentifierQuoteString",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void testGetIdentifierQuoteString() throws SQLException {
+ assertNotNull(
+ meta.getIdentifierQuoteString()
+ );
+
+ //Exception test
+ /*
+ conn.close();
+ try {
+ meta.getIdentifierQuoteString();
+ fail("Should throw exception");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsColumnAliasing()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "supportsColumnAliasing",
+ args = {}
+ )
+ public void test_supportsColumnAliasing() throws SQLException {
+ insertNewRecord();
+
+ String alias = "FIELD3";
+ String selectQuery = "SELECT field1 AS " + alias + " FROM "
+ + DatabaseCreator.TEST_TABLE1;
+ ResultSet rs = statement.executeQuery(selectQuery);
+ ResultSetMetaData rsmd = rs.getMetaData();
+
+ if (meta.supportsColumnAliasing()) {
+ // supports aliasing
+ assertEquals("Wrong count of columns", 1, rsmd.getColumnCount());
+ assertEquals("Aliasing is not supported", alias, rsmd
+ .getColumnLabel(1));
+ } else {
+ // doesn't support aliasing
+ assertEquals("Aliasing is supported", 0, rsmd.getColumnCount());
+ }
+ rs.close();
+
+ //Exception checking
+ /*
+ conn.close();
+
+ try {
+ meta.supportsColumnAliasing();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsExpressionsInOrderBy()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "supportsExpressionsInOrderBy",
+ args = {}
+ )
+ public void test_supportsExpressionsInOrderBy() throws SQLException {
+ insertNewRecord();
+
+ String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1
+ + " ORDER BY id + field3";
+
+ try {
+ statement.executeQuery(selectQuery);
+ if (!meta.supportsExpressionsInOrderBy()) {
+ fail("Expressions in order by are supported");
+ }
+ } catch (SQLException e) {
+ if (meta.supportsExpressionsInOrderBy()) {
+ fail("Expressions in order by are not supported");
+ }
+ }
+
+ //Exception checking
+ /*
+ conn.close();
+
+ try {
+ meta.supportsExpressionsInOrderBy();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsGroupBy()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "supportsGroupBy",
+ args = {}
+ )
+ public void test_supportsGroupBy() throws SQLException {
+ insertNewRecord();
+
+ String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1
+ + " GROUP BY field3";
+
+ try {
+ statement.executeQuery(selectQuery);
+ if (!meta.supportsGroupBy()) {
+ fail("group by are supported");
+ }
+ } catch (SQLException e) {
+ if (meta.supportsGroupBy()) {
+ fail("group by are not supported");
+ }
+ }
+
+ //Exception checking
+ /*
+ conn.close();
+
+ try {
+ meta.supportsGroupBy();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsGroupByUnrelated()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "supportsGroupByUnrelated",
+ args = {}
+ )
+ public void test_supportsGroupByUnrelated() throws SQLException {
+ insertNewRecord();
+
+ String selectQuery = "SELECT field1, field2 FROM "
+ + DatabaseCreator.TEST_TABLE1 + " GROUP BY field3";
+
+ try {
+ statement.executeQuery(selectQuery);
+ if (!meta.supportsGroupByUnrelated()) {
+ fail("unrelated columns in group by are supported");
+ }
+ } catch (SQLException e) {
+ if (meta.supportsGroupByUnrelated()) {
+ fail("unrelated columns in group by are not supported");
+ }
+ }
+
+ //Exception checking
+ /*
+ conn.close();
+
+ try {
+ meta.supportsGroupByUnrelated();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsNonNullableColumns()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException thrown",
+ method = "supportsNonNullableColumns",
+ args = {}
+ )
+ @KnownFailure("Ticket 98")
+ public void test_supportsNonNullableColumns() throws SQLException {
+ assertTrue(
+ "columns in this database may not be defined as non-nullable",
+ meta.supportsNonNullableColumns());
+ statementForward.execute("create table companies(id integer not null);");
+ statementForward.execute("drop table companies");
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.supportsNonNullableColumns();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOrderByUnrelated()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "supportsOrderByUnrelated",
+ args = {}
+ )
+ public void test_supportsOrderByUnrelated() throws SQLException {
+ insertNewRecord();
+
+ String selectQuery = "SELECT field1, field2 FROM "
+ + DatabaseCreator.TEST_TABLE1 + " ORDER BY id + field3";
+
+ try {
+ statement.executeQuery(selectQuery);
+ if (!meta.supportsOrderByUnrelated()) {
+ fail("unrelated columns in order by are supported");
+ }
+ } catch (SQLException e) {
+ if (meta.supportsOrderByUnrelated()) {
+ fail("unrelated columns in order by are not supported");
+ }
+ }
+
+ //Exception checking
+
+ /*
+ conn.close();
+
+ try {
+ meta.supportsOrderByUnrelated();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSelectForUpdate()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "supportsSelectForUpdate",
+ args = {}
+ )
+ public void test_supportsSelectForUpdate() throws SQLException {
+ insertNewRecord();
+
+ String selectQuery = "SELECT field1 FROM "
+ + DatabaseCreator.TEST_TABLE1 + " FOR UPDATE";
+
+ try {
+ statement.executeQuery(selectQuery);
+ if (!meta.supportsSelectForUpdate()) {
+ fail("select for update are supported");
+ }
+ } catch (SQLException e) {
+ if (!meta.supportsSelectForUpdate()) {
+ fail("select for update are not supported");
+ }
+ }
+
+
+ //Exception checking
+ /*
+ conn.close();
+
+ try {
+ meta.supportsSelectForUpdate();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSubqueriesInExists()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "supportsSubqueriesInExists",
+ args = {}
+ )
+ public void test_supportsSubqueriesInExists() throws SQLException {
+ insertNewRecord();
+
+ String selectQuery = "SELECT field1 FROM "
+ + DatabaseCreator.TEST_TABLE1
+ + " WHERE EXISTS(SELECT field2 FROM "
+ + DatabaseCreator.TEST_TABLE1 + ")";
+
+ try {
+ statement.executeQuery(selectQuery);
+ if (!meta.supportsSubqueriesInExists()) {
+ fail("Subqueries in exists are supported");
+ }
+ } catch (SQLException e) {
+ if (meta.supportsSubqueriesInExists()) {
+ fail("Subqueries in exists are not supported");
+ }
+ }
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.supportsSubqueriesInExists();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsTableCorrelationNames()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking test fails",
+ method = "supportsTableCorrelationNames",
+ args = {}
+ )
+ public void test_supportsTableCorrelationNames() throws SQLException {
+
+ insertNewRecord();
+ assertFalse(conn.isClosed());
+
+ String corelationName = "TABLE_NAME";
+ String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1
+ + " AS " + corelationName;
+ ResultSet rs = statementForward.executeQuery(selectQuery);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int numOfColumn = rsmd.getColumnCount();
+
+ for (int i = 0; i < numOfColumn; i++) {
+ if (meta.supportsTableCorrelationNames()) {
+ assertEquals("Corelation names is now supported",
+ corelationName, rsmd.getTableName(i + 1));
+ } else {
+ assertEquals("Corelation names is supported",
+ DatabaseCreator.TEST_TABLE1, rsmd.getTableName(i + 1));
+ }
+ }
+
+ /*
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.supportsTableCorrelationNames();
+ fail("SQLException not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsTransactionIsolationLevel(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = " Not all Transaction isolation levels supported.",
+ method = "supportsTransactionIsolationLevel",
+ args = {int.class}
+ )
+ public void test_supportsTransactionIsolationLevelI() throws SQLException {
+ assertFalse("database supports TRANSACTION_NONE isolation level", meta
+ .supportsTransactionIsolationLevel(Connection.TRANSACTION_NONE));
+ // TODO only Connection.TRANSACTION_SERIALIZABLE is supported
+// assertTrue(
+// "database doesn't supports TRANSACTION_READ_COMMITTED isolation level",
+// meta
+// .supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_COMMITTED));
+// assertTrue(
+// "database doesn't supports TRANSACTION_READ_UNCOMMITTED isolation level",
+// meta
+// .supportsTransactionIsolationLevel(Connection.TRANSACTION_READ_UNCOMMITTED));
+// assertTrue(
+// "database doesn't supports TRANSACTION_REPEATABLE_READ isolation level",
+// meta
+// .supportsTransactionIsolationLevel(Connection.TRANSACTION_REPEATABLE_READ));
+ assertTrue(
+ "database doesn't supports TRANSACTION_SERIALIZABLE isolation level",
+ meta
+ .supportsTransactionIsolationLevel(Connection.TRANSACTION_SERIALIZABLE));
+
+
+ //Exception checking
+
+ try {
+ assertFalse("database supports unknown isolation level", meta
+ .supportsTransactionIsolationLevel(Integer.MAX_VALUE));;
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#updatesAreDetected(int)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = " Verification with invalid parameters missed.",
+ method = "updatesAreDetected",
+ args = {int.class}
+ )
+ public void test_updatesAreDetectedI() throws SQLException {
+ assertFalse(
+ "visible row update can be detected for TYPE_FORWARD_ONLY type",
+ meta.updatesAreDetected(ResultSet.TYPE_FORWARD_ONLY));
+ assertFalse(
+ "visible row update can be detected for TYPE_SCROLL_INSENSITIVE type",
+ meta.updatesAreDetected(ResultSet.TYPE_SCROLL_INSENSITIVE));
+ assertFalse(
+ "visible row update can be detected for TYPE_SCROLL_SENSITIVE type",
+ meta.updatesAreDetected(ResultSet.TYPE_SCROLL_SENSITIVE));
+ assertFalse("visible row update can be detected for unknown type", meta
+ .updatesAreDetected(100));
+
+ //Exception checking
+ conn.close();
+
+ try {
+ meta.updatesAreDetected(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ assertFalse("visible row update can be detected for unknown type", meta
+ .updatesAreDetected(ResultSet.CLOSE_CURSORS_AT_COMMIT));
+
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+
+ protected static void insertNewRecord() throws SQLException {
+ if (conn.isClosed()) {
+ System.out.println("DatabaseMetaDataTest.insertNewRecord() : closed");
+ }
+
+ String insertQuery = "INSERT INTO " + DatabaseCreator.TEST_TABLE1
+ + " (id, field1, field2, field3) VALUES(" + id + ", '"
+ + "value" + id + "', " + id + ", " + id + ")";
+ id++;
+ statement.execute(insertQuery);
+ }
+
+ //BEGIN APACHE-DERBY
+
+ /**
+ * Test Method from Apache Derby Project
+ * Class
+ * org.apache.derbyTesting.functionTests.tests.jdbcapi.DatabaseMetaDataTest
+ *
+ * Compare a ResultSet from getColumns() with ResultSetMetaData returned
+ * from a SELECT * against the table. This method handles situations where a
+ * full set of the columns are in the ResultSet. The first action is to call
+ * rs.next(). The ResultSet will be closed by this method.
+ *
+ * @param rs
+ * resultset to crossCheck
+ * @param partial
+ * used to indicate if ordinal position should get checked
+ * @return the number of rows in the resultSet
+ * @throws SQLException
+ */
+ private int crossCheckGetColumnsAndResultSetMetaData(ResultSet rs,
+ boolean partial)
+ throws SQLException
+ {
+ Statement s = conn.createStatement();
+ while (rs.next())
+ {
+ String schema = rs.getString("TABLE_SCHEM");
+ String table = rs.getString("TABLE_NAME");
+
+ ResultSet rst = s.executeQuery(
+ "SELECT * FROM " + schema+"."+table);
+ ResultSetMetaData rsmdt = rst.getMetaData();
+
+
+ for (int col = 1; col <= rsmdt.getColumnCount() ; col++)
+ {
+ if (!partial) {
+ if (col != 1)
+ assertTrue(rs.next());
+
+ assertEquals("ORDINAL_POSITION",
+ col, rs.getInt("ORDINAL_POSITION"));
+ }
+
+ assertEquals("TABLE_CAT",
+ "", rs.getString("TABLE_CAT"));
+ assertEquals("TABLE_SCHEM",
+ schema, rs.getString("TABLE_SCHEM"));
+ assertEquals("TABLE_NAME",
+ table, rs.getString("TABLE_NAME"));
+
+ crossCheckGetColumnRowAndResultSetMetaData(rs, rsmdt);
+ if (partial)
+ break;
+
+ }
+ rst.close();
+
+
+ }
+ int count = rs.getRow();
+ rs.close();
+ s.close();
+ return count;
+ }
+
+ /**
+ * * Test Method from Apache Derby Project
+ * Class
+ * org.apache.derbyTesting.functionTests.tests.jdbcapi.DatabaseMetaDataTest
+ *
+ * Cross check a single row from getColumns() with ResultSetMetaData
+ * for a SELECT * from the same table.
+ * @param rs ResultSet from getColumns already positioned on the row.
+ * @param rsmdt ResultSetMetaData for the SELECT *
+ * @param odbc 0 for JDBC call, 1 for ODBC. Needed to allow for difference
+ * in using BUFFER_LENGTH (ODBC) or no(JDBC).
+ * @throws SQLException
+ */
+ public static void crossCheckGetColumnRowAndResultSetMetaData(
+ ResultSet rs, ResultSetMetaData rsmdt)
+ throws SQLException
+ {
+ int col = rs.getInt("ORDINAL_POSITION");
+
+ assertEquals("RSMD.getCatalogName",
+ rsmdt.getCatalogName(col), rs.getString("TABLE_CAT"));
+ assertEquals("RSMD.getSchemaName",
+ rsmdt.getSchemaName(col), rs.getString("TABLE_SCHEM"));
+ assertEquals("RSMD.getTableName",
+ rsmdt.getTableName(col), rs.getString("TABLE_NAME"));
+
+ assertEquals("COLUMN_NAME",
+ rsmdt.getColumnName(col), rs.getString("COLUMN_NAME"));
+
+ // DERBY-2285 BOOLEAN columns appear different on
+ // network client.
+ // meta returns BOOLEAN
+ // RSMD returns SMALLINT
+ int metaColumnType = rs.getInt("DATA_TYPE");
+ if (metaColumnType == Types.BOOLEAN )
+ {
+ assertEquals("TYPE_NAME",
+ "BOOLEAN", rs.getString("TYPE_NAME"));
+ assertEquals("TYPE_NAME",
+ "SMALLINT", rsmdt.getColumnTypeName(col));
+
+ assertEquals("DATA_TYPE",
+ Types.SMALLINT, rsmdt.getColumnType(col));
+ }
+ else if (metaColumnType == Types.JAVA_OBJECT)
+ {
+ // meta returns JAVA_OBJECT
+ // RSMD returns LONGVARBINARY!
+ assertEquals("DATA_TYPE",
+ Types.LONGVARBINARY, rsmdt.getColumnType(col));
+ }
+ else if (metaColumnType == Types.VARBINARY )
+ {
+ // meta returns different type name to RSMD
+ assertEquals("DATA_TYPE",
+ Types.VARBINARY, rsmdt.getColumnType(col));
+ }
+ else if (metaColumnType == Types.BINARY )
+ {
+ // meta returns different type name to RSMD
+ assertEquals("DATA_TYPE",
+ Types.BINARY, rsmdt.getColumnType(col));
+ }
+ else if (metaColumnType == Types.NUMERIC )
+ {
+ // DERBY-584 inconsistency in numeric & decimal
+ assertEquals("DATA_TYPE",
+ Types.DECIMAL, rsmdt.getColumnType(col));
+
+ assertEquals("TYPE_NAME",
+ "DECIMAL", rsmdt.getColumnTypeName(col));
+
+ assertEquals("TYPE_NAME",
+ "NUMERIC", rs.getString("TYPE_NAME"));
+ }
+ else
+ {
+ assertEquals("DATA_TYPE",
+ rsmdt.getColumnType(col), rs.getInt("DATA_TYPE"));
+ assertEquals("TYPE_NAME",
+ rsmdt.getColumnTypeName(col), rs.getString("TYPE_NAME"));
+ }
+
+ /*
+ if (metaColumnType != Types.JAVA_OBJECT) {
+ System.out.println("TYPE " + rs.getInt("DATA_TYPE"));
+ System.out.println(JDBC.escape(schema, table) + " " + rs.getString("COLUMN_NAME"));
+ assertEquals("COLUMN_SIZE",
+ rsmdt.getPrecision(col), rs.getInt("COLUMN_SIZE"));
+ }
+ */
+
+ /*
+ assertEquals("DECIMAL_DIGITS",
+ rsmdt.getScale(col), rs.getInt("DECIMAL_DIGITS"));
+ */
+
+ // This assumes the constants defined by meta and ResultSet
+ // for nullability are equal. They are by inspection
+ // and since they are static final and part of a defined
+ // api by definition they cannot change. We also
+ // check statically this is true in the testConstants fixture.
+ assertEquals("NULLABLE",
+ rsmdt.isNullable(col), rs.getInt("NULLABLE"));
+
+ // REMARKS set to empty string by Derby
+ assertEquals("REMARKS", "", rs.getString("REMARKS"));
+
+
+ // IS_NULLABLE
+ switch (rsmdt.isNullable(col))
+ {
+ case ResultSetMetaData.columnNoNulls:
+ assertEquals("IS_NULLABLE", "NO", rs.getString("IS_NULLABLE"));
+ break;
+ case ResultSetMetaData.columnNullable:
+ assertEquals("IS_NULLABLE", "YES", rs.getString("IS_NULLABLE"));
+ break;
+ case ResultSetMetaData.columnNullableUnknown:
+ assertEquals("IS_NULLABLE", "", rs.getString("IS_NULLABLE"));
+ break;
+ default:
+ fail("invalid return from rsmdt.isNullable(col)");
+ }
+
+ // SCOPE not supported
+ assertNull("SCOPE_CATLOG", rs.getString("SCOPE_CATLOG"));
+ assertNull("SCOPE_SCHEMA", rs.getString("SCOPE_SCHEMA"));
+ assertNull("SCOPE_TABLE", rs.getString("SCOPE_TABLE"));
+
+ // DISTINCT not supported
+ assertEquals("SOURCE_DATA_TYPE", 0, rs.getShort("SOURCE_DATA_TYPE"));
+ assertTrue(rs.wasNull());
+
+ // IS_AUTOINCREMENT added in JDBC 4.0
+ assertEquals("IS_AUTOINCREMENT",
+ rsmdt.isAutoIncrement(col) ? "YES" : "NO",
+ rs.getString("IS_AUTOINCREMENT"));
+ assertFalse(rs.wasNull());
+ }
+
+ /*
+ * Check the shape of the ResultSet from any getColumns call.
+ */
+ private void checkColumnsShape(ResultSet rs) throws SQLException {
+ int[] columnTypes = new int[] {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.SMALLINT, Types.VARCHAR, Types.INTEGER, Types.INTEGER,
+ Types.INTEGER, Types.INTEGER, Types.INTEGER, Types.VARCHAR,
+ Types.VARCHAR, Types.INTEGER, Types.INTEGER, Types.INTEGER,
+ Types.INTEGER, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT, Types.VARCHAR};
+
+ assertMetaDataResultSet(rs, new String[] {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME", "COLUMN_NAME",
+ "DATA_TYPE", "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH",
+ "DECIMAL_DIGITS", "NUM_PREC_RADIX", "NULLABLE", "REMARKS",
+ "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB",
+ "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE",
+ "SCOPE_CATLOG", "SCOPE_SCHEMA", "SCOPE_TABLE",
+ "SOURCE_DATA_TYPE", "IS_AUTOINCREMENT"}, columnTypes, null);
+
+ }
+
+ public static void assertMetaDataResultSet(ResultSet rs,
+ String[] columnNames, int[] columnTypes,
+ boolean[] nullability) throws SQLException
+ {
+ // see ResultSetGetterTest, getType() -> this test fails currently
+ assertEquals(ResultSet.TYPE_FORWARD_ONLY, rs.getType());
+ assertEquals(ResultSet.CONCUR_READ_ONLY, rs.getConcurrency());
+
+ if (columnNames != null)
+ assertColumnNames(rs, columnNames);
+ if (columnTypes != null)
+ assertColumnTypes(rs, columnTypes);
+ if (nullability != null)
+ assertNullability(rs, nullability);
+ }
+
+ /**
+ * * Test Method from Apache Derby Project
+ * Class
+ * org.apache.derbyTesting.functionTests.tests.jdbcapi.DatabaseMetaDataTest
+ *
+ * Takes a result set and an array of expected colum names (as
+ * Strings) and asserts that the column names in the result
+ * set metadata match the number, order, and names of those
+ * in the array.
+ *
+ * @param rs ResultSet for which we're checking column names.
+ * @param expectedColNames Array of expected column names.
+ */
+ public static void assertColumnNames(ResultSet rs,
+ String [] expectedColNames) throws SQLException
+ {
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int actualCols = rsmd.getColumnCount();
+
+ for (int i = 0; i < actualCols; i++)
+ {
+ assertEquals("Column names do not match:",
+ expectedColNames[i], rsmd.getColumnName(i+1));
+ }
+
+ assertEquals("Unexpected column count:",
+ expectedColNames.length, rsmd.getColumnCount());
+ }
+
+ /**
+ * Test Method from Apache Derby Project
+ * Class
+ * org.apache.derbyTesting.functionTests.tests.jdbcapi.DatabaseMetaDataTest
+ *
+ * Takes a result set and an array of expected column types
+ * from java.sql.Types
+ * and asserts that the column types in the result
+ * set metadata match the number, order, and names of those
+ * in the array.
+ *
+ * No length information for variable length types
+ * can be passed. For ResultSets from JDBC DatabaseMetaData
+ * the specification only indicates the types of the
+ * columns, not the length.
+ *
+ * @param rs ResultSet for which we're checking column names.
+ * @param expectedTypes Array of expected column types.
+ */
+ public static void assertColumnTypes(ResultSet rs,
+ int[] expectedTypes) throws SQLException
+ {
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int actualCols = rsmd.getColumnCount();
+
+ assertEquals("Unexpected column count:",
+ expectedTypes.length, rsmd.getColumnCount());
+
+ for (int i = 0; i < actualCols; i++)
+ {
+ assertEquals("Column types do not match for column " + (i+1),
+ expectedTypes[i], rsmd.getColumnType(i+1));
+ }
+ }
+
+ /**
+ * Check the nullability of the column definitions for
+ * the ResultSet matches the expected values.
+ * @param rs
+ * @param nullability
+ * @throws SQLException
+ */
+ public static void assertNullability(ResultSet rs,
+ boolean[] nullability) throws SQLException
+ {
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int actualCols = rsmd.getColumnCount();
+
+ assertEquals("Unexpected column count:",
+ nullability.length, rsmd.getColumnCount());
+
+ for (int i = 0; i < actualCols; i++)
+ {
+ int expected = nullability[i] ?
+ ResultSetMetaData.columnNullable : ResultSetMetaData.columnNoNulls;
+ assertEquals("Column nullability do not match for column " + (i+1),
+ expected, rsmd.isNullable(i+1));
+ }
+ }
+
+ //BEGIN Apache Derby DatabaseMetaDataTest
+
+ /*
+ * Escaped function testing TODO complete this list
+ */
+ private static final String[][] NUMERIC_FUNCTIONS = {
+ // Section C.1 JDBC 3.0 spec.
+ {"ABS", "-25.67"},
+
+// {"ACOS", "0.0707"}, {"ASIN", "0.997"},
+// {"ATAN", "14.10"}, {"ATAN2", "0.56", "1.2"}, {"CEILING", "3.45"},
+// {"COS", "1.2"}, {"COT", "3.4"}, {"DEGREES", "2.1"}, {"EXP", "2.3"},
+// {"FLOOR", "3.22"}, {"LOG", "34.1"}, {"LOG10", "18.7"},
+// {"MOD", "124", "7"}, {"PI"}, {"POWER", "2", "3"},
+// {"RADIANS", "54"}, {"RAND", "17"},
+
+ {"ROUND", "345.345", "1"}
+
+// {"SIGN", "-34"}, {"SIN", "0.32"}, {"SQRT", "6.22"},
+// {"TAN", "0.57",}, {"TRUNCATE", "345.395", "1"}
+
+ };
+
+ private static final String[][] TIMEDATE_FUNCTIONS = {
+ // Section C.3 JDBC 3.0 spec.
+
+ {"date","'now'"}
+
+ //TODO Complete list
+
+ };
+
+ private static final String[][] SYSTEM_FUNCTIONS = {
+ // Section C.4 JDBC 3.0 spec.
+ {"IFNULL", "'this'", "'that'"}, {"USER"}
+ };
+
+ /*
+ * TODO complete or check this list
+ */
+ private static final String[][] STRING_FUNCTIONS = {
+ // Section C.2 JDBC 3.0 spec.
+// {"ASCII", "'Yellow'"}, {"CHAR", "65"},
+// {"CONCAT", "'hello'", "'there'"},
+// {"DIFFERENCE", "'Pires'", "'Piers'"},
+// {"INSERT", "'Bill Clinton'", "4", "'William'"},
+// {"LCASE", "'Fernando Alonso'"}, {"LEFT", "'Bonjour'", "3"},
+// {"LENGTH", "'four '"}, {"LOCATE", "'jour'", "'Bonjour'"},
+ {"LTRIM", "' left trim '"},
+// {"REPEAT", "'echo'", "3"},
+// {"REPLACE", "'to be or not to be'", "'be'", "'England'"},
+// {"RTRIM", "' right trim '"}, {"SOUNDEX", "'Derby'"},
+// {"SPACE", "12"},
+// {"SUBSTRING", "'Ruby the Rubicon Jeep'", "10", "7",},
+// {"UCASE", "'Fernando Alonso'"}
+ };
+
+ /**
+ * Six combinations of valid identifiers with mixed case, to see how the
+ * various pattern matching and returned values handle them. This test only
+ * creates objects in these schemas.
+ */
+ private static final String[] IDS = {
+ "one_meta_test", "TWO_meta_test", "ThReE_meta_test",
+ "\"four_meta_test\"", "\"FIVE_meta_test\"", "\"sIx_meta_test\""};
+
+ /**
+ * All the builtin schemas.
+ */
+ private static final String[] BUILTIN_SCHEMAS = {
+ //TODO: Are there any other built in schemas?
+
+ };
+
+ public static String getStoredIdentifier(String sqlIdentifier) {
+ if (sqlIdentifier.charAt(0) == '"')
+ return sqlIdentifier.substring(1, sqlIdentifier.length() - 1);
+ else
+ return sqlIdentifier.toUpperCase();
+ }
+
+ /**
+ * Test getSchemas() without modifying the database.
+ *
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Derby test for getSchema",
+ method = "getSchemas",
+ args = {}
+ )
+ public void testGetSchemasReadOnly() throws SQLException {
+
+ ResultSet rs = meta.getSchemas();
+ checkSchemas(rs, new String[0]);
+ }
+
+
+ /**
+ * Check the returned information from a getSchemas(). The passed in
+ * String[] expected is a list of the schemas expected to be present in the
+ * returned set. The returned set may contain additional schemas which will
+ * be ignored, thus this test can be used regardless of the database state.
+ * The builtin schemas are automatically checked and must not be part of the
+ * passed in list.
+ */
+ public static void checkSchemas(ResultSet rs, String[] userExpected)
+ throws SQLException {
+
+ // Add in the system schemas
+ String[] expected = new String[BUILTIN_SCHEMAS.length
+ + userExpected.length];
+
+ System.arraycopy(BUILTIN_SCHEMAS, 0, expected, 0,
+ BUILTIN_SCHEMAS.length);
+ System.arraycopy(userExpected, 0, expected, BUILTIN_SCHEMAS.length,
+ userExpected.length);
+
+ // Remove any quotes from user schemas and upper case
+ // those without quotes.
+ for (int i = BUILTIN_SCHEMAS.length; i < expected.length; i++) {
+ expected[i] = getStoredIdentifier(expected[i]);
+ }
+
+ // output is ordered by TABLE_SCHEM
+ Arrays.sort(expected);
+
+ int nextMatch = 0;
+
+ while (rs.next()) {
+ String schema = rs.getString("TABLE_SCHEM");
+ assertNotNull(schema);
+
+ // Catalogs not supported
+// assertNull(rs.getString("TABLE_CATALOG"));
+
+ if (nextMatch < expected.length) {
+ if (expected[nextMatch].equals(schema)) nextMatch++;
+ }
+ }
+ rs.close();
+ assertEquals("Schemas missing ", expected.length, nextMatch);
+ }
+
+ private void assertMatchesPattern(String pattern, String result) {
+ if (!doesMatch(pattern, 0, result, 0)) {
+ fail("Bad pattern matching:" + pattern + " result:" + result);
+ }
+
+ }
+
+ /**
+ * See if a string matches the pattern as defined by DatabaseMetaData. By
+ * passing in non-zero values can check sub-sets of the pattern against the
+ * sub strings of the result.
+ * _ matches a single character
+ * % matches zero or more characters
+ * Other characters match themselves.
+ *
+ * @param pattern
+ * Pattern
+ * @param pp
+ * Position in pattern to start the actual pattern from
+ * @param result
+ * result string
+ * @param rp
+ * position in result to starting checking
+ * @return true if a match is found
+ */
+ private boolean doesMatch(String pattern, int pp, String result, int rp) {
+ // Find a match
+ for (;;) {
+ if (pp == pattern.length() && rp == result.length()) return true;
+
+ // more characters to match in the result but
+ // no more pattern.
+ if (pp == pattern.length()) return false;
+
+ char pc = pattern.charAt(pp);
+ if (pc == '_') {
+ // need to match a single character but
+ // exhausted result, so no match.
+ if (rp == result.length()) return false;
+
+ pp++;
+ rp++;
+ } else if (pc == '%') {
+ // % at end, complete match regardless of
+ // position of result since % matches zero or more.
+ if (pp == pattern.length() - 1) {
+ return true;
+ }
+
+ // Brut force, we have a pattern like %X
+ // and we are say in the third character of
+ // abCdefgX
+ // then start a 'CdefgX' and look for a match,
+ // then 'defgX' etc.
+ for (int sp = rp; sp < result.length(); sp++) {
+ if (doesMatch(pattern, pp + 1, result, sp)) {
+ // Have a match for the pattern after the %
+ // which means we have a match for the pattern
+ // with the % since we can match 0 or mor characters
+ // with %.
+ return true;
+ }
+ }
+
+ // Could not match the pattern after the %
+ return false;
+ } else {
+ // need to match a single character but
+ // exhausted result, so no match.
+ if (rp == result.length()) return false;
+
+ // Single character, must match exactly.
+ if (pc != result.charAt(rp)) {
+ // Computer says no.
+ return false;
+ }
+ pp++;
+ rp++;
+ }
+
+ }
+
+ }
+
+
+ /**
+ * Check that the list of escaped functions provided by the driver is a
+ * strict subet of the specified set, the list does not contain duplicates,
+ * all the functions listed can be executed and that if a function is not in
+ * the list but is specified it cannot be executed.
+ */
+ private void escapedFunctions(String[][] specList, String metaDataList)
+ throws SQLException {
+
+ boolean[] seenFunction = new boolean[specList.length];
+
+ StringTokenizer st = new StringTokenizer(metaDataList, ",");
+ int counter = 0;
+ while (st.hasMoreTokens()) {
+ counter++;
+ String function = st.nextToken();
+
+ // find this function in the list
+ boolean isSpecFunction = false;
+ for (int f = 0; f < specList.length; f++) {
+ String[] specDetails = specList[f];
+ if (function.equals(specDetails[0])) {
+ // Matched spec.
+ if (seenFunction[f])
+ fail("Function in list twice: " + function);
+ seenFunction[f] = true;
+ isSpecFunction = true;
+ executeEscaped(specDetails);
+ break;
+ }
+ }
+
+ if (!isSpecFunction) {
+ fail("Non-JDBC spec function in list: " + function);
+ }
+ }
+
+ // Now see if any speced functions are not in the metadata list
+ assertSame("Function missing in metadata impl",specList.length, counter);
+ for (int f = 0; f < specList.length; f++) {
+ if (seenFunction[f]) continue;
+ String[] specDetails = specList[f];
+
+ // bug DERBY-723 CHAR maps to wrong function
+ if ("CHAR".equals(specDetails[0])) continue;
+ try {
+ executeEscaped(specDetails);
+ fail("function works but not declared in list: "
+ + specDetails[0]);
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+ }
+
+ /**
+ * Test we can execute a function listed as a supported
+ * JDBC escaped function. We don't care about the actual
+ * return value, that should be tested elsewhere in
+ * the specific test of a function.
+ */
+ private void executeEscaped(String[] specDetails)
+ throws SQLException
+ {
+
+ String sql = "SELECT " + specDetails[0] + "(";
+
+ for (int p = 0; p < specDetails.length - 1; p++)
+ {
+ if (p != 0)
+ sql = sql + ", ";
+
+ sql = sql + specDetails[p + 1];
+ }
+
+ sql = sql + ") ;";
+
+ System.out.println("DatabaseMetaDataTest.executeEscaped() "+sql);
+ Statement st = conn.createStatement();
+ ResultSet rs = st.executeQuery(sql);
+
+ assertNotNull("not supported function: "+sql,rs);
+
+ rs.close();
+ st.close();
+ }
+
+ //END APACHE-DERBY
+}
diff --git a/sql/src/test/java/tests/java/sql/DeleteFunctionalityTest.java b/sql/src/test/java/tests/java/sql/DeleteFunctionalityTest.java
new file mode 100755
index 0000000..6209548
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/DeleteFunctionalityTest.java
@@ -0,0 +1,268 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package tests.java.sql;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+@TestTargetClass(Statement.class)
+public class DeleteFunctionalityTest extends TestCase {
+
+ private static Connection conn = null;
+
+ private static Statement statement = null;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ DatabaseCreator.fillParentTable(conn);
+ }
+
+ protected void tearDown() throws Exception {
+ statement.execute("DELETE FROM " + DatabaseCreator.FKSTRICT_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.FKCASCADE_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.PARENT_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.TEST_TABLE5);
+ super.tearDown();
+ }
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ DeleteFunctionalityTest.class)) {
+ protected void setUp() throws Exception {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ createTestTables();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ deleteTestTables();
+ statement.close();
+ conn.close();
+ }
+
+ private void createTestTables() {
+ try {
+ DatabaseMetaData meta = conn.getMetaData();
+ ResultSet userTab = meta.getTables(null, null, null, null);
+
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.PARENT_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_PARENT);
+ } else if (tableName
+ .equals(DatabaseCreator.FKCASCADE_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_FKCASCADE);
+ } else if (tableName
+ .equals(DatabaseCreator.FKSTRICT_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_FKSTRICT);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE5)) {
+ statement.execute(DatabaseCreator.DROP_TABLE5);
+ }
+ }
+ userTab.close();
+ statement.execute(DatabaseCreator.CREATE_TABLE_PARENT);
+ statement.execute(DatabaseCreator.CREATE_TABLE_FKSTRICT);
+ statement.execute(DatabaseCreator.CREATE_TABLE_FKCASCADE);
+ statement.execute(DatabaseCreator.CREATE_TABLE5);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ private void deleteTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE_FKCASCADE);
+ statement.execute(DatabaseCreator.DROP_TABLE_FKSTRICT);
+ statement.execute(DatabaseCreator.DROP_TABLE_PARENT);
+ statement.execute(DatabaseCreator.DROP_TABLE5);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * @tests DeleteFunctionalityTest#testDelete1(). Deletes row with no
+ * referencing ones and RESTRICT action
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Deletes row with no referencing ones and RESTRICT action",
+ method = "execute",
+ args = {java.lang.String.class}
+ )
+ public void testDelete1() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ statement.execute("DELETE FROM " + DatabaseCreator.PARENT_TABLE
+ + " WHERE id = 3;");
+ }
+
+ /**
+ * @tests DeleteFunctionalityTest#testDelete2(). Attempts to delete row with
+ * referencing ones and RESTRICT action - expecting SQLException
+ * TODO foreign key functionality is not supported
+ */
+/* public void testDelete2() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ try {
+ statement.execute("DELETE FROM " + DatabaseCreator.PARENT_TABLE
+ + " WHERE id = 1;");
+ fail("expecting SQLException");
+ } catch (SQLException ex) {
+ // expected
+ }
+ }
+*/
+ /**
+ * @tests DeleteFunctionalityTest#testDelete3(). Deletes all referencing
+ * rows and then deletes referenced one
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Deletes all referencing rows and then deletes referenced one",
+ method = "execute",
+ args = {java.lang.String.class}
+ )
+ public void testDelete3() throws SQLException {
+ statement.execute("DELETE FROM " + DatabaseCreator.FKSTRICT_TABLE
+ + " WHERE name_id = 1;");
+ statement.execute("DELETE FROM " + DatabaseCreator.FKSTRICT_TABLE
+ + " WHERE id = 1;");
+ }
+
+ /**
+ * @tests DeleteFunctionalityTest#testDelete4(). Deletes row with no
+ * referencing ones and CASCADE action
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Deletes row with no referencing ones and CASCADE action",
+ method = "execute",
+ args = {java.lang.String.class}
+ )
+ public void testDelete4() throws SQLException {
+ DatabaseCreator.fillFKCascadeTable(conn);
+ statement.execute("DELETE FROM " + DatabaseCreator.PARENT_TABLE
+ + " WHERE id = 3;");
+ }
+
+ /**
+ * @tests DeleteFunctionalityTest#testDelete5(). Attempts to delete row with
+ * referencing ones and CASCADE action - expecting all referencing
+ * rows will also be deleted
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Attempts to delete row with referencing ones and CASCADE action - expecting all referencing rows will also be deleted",
+ method = "execute",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Attempts to delete row with referencing ones and CASCADE action - expecting all referencing rows will also be deleted",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testDelete5() throws SQLException {
+ statement.execute("DELETE FROM " + DatabaseCreator.PARENT_TABLE
+ + " WHERE id = 1;");
+
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) FROM "
+ + DatabaseCreator.FKCASCADE_TABLE + " WHERE name_id = 1;");
+ r.next();
+ assertEquals("Should be no rows", 0, r.getInt(1));
+ r.close();
+ }
+
+ /**
+ * @tests DeleteFunctionalityTest#testDelete6().
+ * TODO Foreign key functionality is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Deletes rows using subquery in WHERE clause with foreign keys. Foreign keys not supported.",
+ method = "execute",
+ args = {String.class}
+ )
+ @KnownFailure("not supported")
+ public void testDelete6() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ statement.execute("DELETE FROM " + DatabaseCreator.FKSTRICT_TABLE
+ + " WHERE name_id = ANY (SELECT id FROM "
+ + DatabaseCreator.PARENT_TABLE + " WHERE id > 1)");
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) FROM "
+ + DatabaseCreator.FKSTRICT_TABLE + " WHERE name_id = 1;");
+ r.next();
+ assertEquals("Should be 2 rows", 2, r.getInt(1));
+ r.close();
+ }
+
+ /**
+ * @tests DeleteFunctionalityTest#testDelete7(). Deletes rows using
+ * PreparedStatement
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Deletes rows using PreparedStatement",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void testDelete7() throws SQLException {
+ DatabaseCreator.fillTestTable5(conn);
+ PreparedStatement stat = conn.prepareStatement("DELETE FROM "
+ + DatabaseCreator.TEST_TABLE5 + " WHERE testID = ?");
+ stat.setInt(1, 1);
+ stat.execute();
+ stat.setInt(1, 2);
+ stat.execute();
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) FROM "
+ + DatabaseCreator.TEST_TABLE5 + " WHERE testID < 3 ");
+ r.next();
+ assertEquals(0, r.getInt(1));
+ r.close();
+ stat.close();
+ }
+}
diff --git a/sql/src/test/java/tests/java/sql/InsertFunctionalityTest.java b/sql/src/test/java/tests/java/sql/InsertFunctionalityTest.java
new file mode 100755
index 0000000..4d26751
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/InsertFunctionalityTest.java
@@ -0,0 +1,321 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package tests.java.sql;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import tests.support.Support_SQL;
+import tests.support.DatabaseCreator;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+@TestTargetClass(Statement.class)
+public class InsertFunctionalityTest extends TestCase {
+
+ private static Connection conn = null;
+
+ private static Statement statement = null;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ Support_SQL.loadDriver();
+ conn = Support_SQL.getConnection();
+
+ }
+
+ protected void tearDown() throws Exception {
+ statement.execute("DELETE FROM " + DatabaseCreator.SIMPLE_TABLE2);
+ statement.execute("DELETE FROM " + DatabaseCreator.SIMPLE_TABLE1);
+ statement.execute("DELETE FROM " + DatabaseCreator.FKSTRICT_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.FKCASCADE_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.PARENT_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.TEST_TABLE5);
+ super.tearDown();
+ }
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ InsertFunctionalityTest.class)) {
+ protected void setUp() throws Exception {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ createTestTables();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ deleteTestTables();
+ statement.close();
+ conn.close();
+ }
+
+ private void createTestTables() {
+ try {
+ DatabaseMetaData meta = conn.getMetaData();
+ ResultSet userTab = meta.getTables(null, null, null, null);
+
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.PARENT_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_PARENT);
+ } else if (tableName
+ .equals(DatabaseCreator.FKCASCADE_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_FKCASCADE);
+ } else if (tableName
+ .equals(DatabaseCreator.FKSTRICT_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_FKSTRICT);
+ } else if (tableName
+ .equals(DatabaseCreator.SIMPLE_TABLE1)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_SIMPLE1);
+ } else if (tableName
+ .equals(DatabaseCreator.SIMPLE_TABLE2)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_SIMPLE2);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE5)) {
+ statement.execute(DatabaseCreator.DROP_TABLE5);
+ }
+ }
+ userTab.close();
+ statement.execute(DatabaseCreator.CREATE_TABLE_PARENT);
+ statement.execute(DatabaseCreator.CREATE_TABLE_FKSTRICT);
+ statement.execute(DatabaseCreator.CREATE_TABLE_FKCASCADE);
+ statement.execute(DatabaseCreator.CREATE_TABLE_SIMPLE2);
+ statement.execute(DatabaseCreator.CREATE_TABLE_SIMPLE1);
+ statement.execute(DatabaseCreator.CREATE_TABLE5);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ private void deleteTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE_FKCASCADE);
+ statement.execute(DatabaseCreator.DROP_TABLE_FKSTRICT);
+ statement.execute(DatabaseCreator.DROP_TABLE_PARENT);
+ statement.execute(DatabaseCreator.DROP_TABLE_SIMPLE2);
+ statement.execute(DatabaseCreator.DROP_TABLE_SIMPLE1);
+ statement.execute(DatabaseCreator.DROP_TABLE5);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * @tests InsertFunctionalityTest#testInsert1(). Attempts to insert row into
+ * table with integrity checking
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Attempts to insert row into table with integrity checking",
+ method = "execute",
+ args = {java.lang.String.class}
+ )
+ @KnownFailure(" SQLite.Exception: error in prepare/compile")
+ public void testInsert1() throws SQLException {
+ DatabaseCreator.fillParentTable(conn);
+ DatabaseCreator.fillFKStrictTable(conn);
+ DatabaseCreator.fillFKCascadeTable(conn);
+ statement.execute("INSERT INTO " + DatabaseCreator.FKSTRICT_TABLE
+ + " VALUES(4, 1, 'testInsert')");
+ statement.execute("INSERT INTO " + DatabaseCreator.FKCASCADE_TABLE
+ + " VALUES(4, 1, 'testInsert')");
+ }
+
+ /**
+ * @tests InsertFunctionalityTest#testInsert2(). Attempts to insert row into
+ * table with integrity checking when row has incorrect foreign key
+ * value - expecting SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Attempts to insert row into table with integrity checking when row has incorrect foreign key value - expecting SQLException",
+ method = "execute",
+ args = {java.lang.String.class}
+ )
+ @KnownFailure(" SQLite.Exception: error in prepare/compile")
+ public void testInsert2() throws SQLException {
+ DatabaseCreator.fillParentTable(conn);
+ DatabaseCreator.fillFKStrictTable(conn);
+ DatabaseCreator.fillFKCascadeTable(conn);
+ try {
+ statement.execute("INSERT INTO " + DatabaseCreator.FKSTRICT_TABLE
+ + " VALUES(4, 4, 'testInsert')");
+ // TODO Foreign key functionality isn't supported
+ // fail("expecting SQLException");
+ } catch (SQLException ex) {
+ // expected
+ }
+ try {
+ statement.execute("INSERT INTO " + DatabaseCreator.FKCASCADE_TABLE
+ + " VALUES(4, 4, 'testInsert')");
+ // TODO Foreign key functionality isn't supported
+ // fail("expecting SQLException");
+ } catch (SQLException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests InsertFunctionalityTest#testInsert3(). Tests INSERT ... SELECT
+ * functionality
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Tests INSERT ... SELECT functionality",
+ method = "execute",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Tests INSERT ... SELECT functionality",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ @KnownFailure(" SQLite.Exception: error in prepare/compile")
+ public void testInsert3() throws SQLException {
+ DatabaseCreator.fillParentTable(conn);
+ DatabaseCreator.fillFKStrictTable(conn);
+ statement.execute("INSERT INTO " + DatabaseCreator.TEST_TABLE5
+ + " SELECT id AS testId, value AS testValue " + "FROM "
+ + DatabaseCreator.FKSTRICT_TABLE + " WHERE name_id = 1");
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) FROM "
+ + DatabaseCreator.TEST_TABLE5);
+ r.next();
+ assertEquals("Should be 2 rows", 2, r.getInt(1));
+ r.close();
+ }
+
+ /**
+ * @tests InsertFunctionalityTest#testInsert4(). Tests INSERT ... SELECT
+ * with expressions in SELECT query
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Tests INSERT ... SELECT with expressions in SELECT query",
+ method = "execute",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Tests INSERT ... SELECT with expressions in SELECT query",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ @KnownFailure(" SQLite.Exception: error in prepare/compile")
+ public void testInsert4() throws SQLException {
+ DatabaseCreator.fillSimpleTable1(conn);
+ statement.execute("INSERT INTO " + DatabaseCreator.SIMPLE_TABLE2
+ + " SELECT id, speed*10 AS speed, size-1 AS size FROM "
+ + DatabaseCreator.SIMPLE_TABLE1);
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) FROM "
+ + DatabaseCreator.SIMPLE_TABLE2 + " AS a JOIN "
+ + DatabaseCreator.SIMPLE_TABLE1
+ + " AS b ON a.speed = 10*b.speed AND a.size = b.size-1");
+ r.next();
+ assertEquals("Should be 2 rows", 2, r.getInt(1));
+ r.close();
+ }
+
+ /**
+ * @tests InsertFunctionalityTest#testInsert5(). Inserts multiple rows using
+ * UNION ALL
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Inserts multiple rows using UNION ALL",
+ method = "execute",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Inserts multiple rows using UNION ALL",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testInsert5() throws SQLException {
+ statement.execute("INSERT INTO " + DatabaseCreator.TEST_TABLE5
+ + " SELECT 1 as testId, 2 as testValue "
+ + "UNION SELECT 2 as testId, 3 as testValue "
+ + "UNION SELECT 3 as testId, 4 as testValue");
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) FROM "
+ + DatabaseCreator.TEST_TABLE5);
+ r.next();
+ assertEquals("Should be 3 rows", 3, r.getInt(1));
+ r.close();
+ }
+
+ /**
+ * @tests InsertFunctionalityTest#testInsert6(). Tests INSERT with
+ * PreparedStatement
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Tests INSERT with PreparedStatement",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ @KnownFailure(" SQLite.Exception: error in prepare")
+ public void testInsertPrepared() throws SQLException {
+ PreparedStatement stat = conn.prepareStatement("INSERT INTO "
+ + DatabaseCreator.TEST_TABLE5 + " VALUES(?, ?)");
+ stat.setInt(1, 1);
+ stat.setString(2, "1");
+ stat.execute();
+ stat.setInt(1, 2);
+ stat.setString(2, "3");
+ stat.execute();
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) FROM "
+ + DatabaseCreator.TEST_TABLE5
+ + " WHERE (testId = 1 AND testValue = '1') "
+ + "OR (testId = 2 AND testValue = '3')");
+ r.next();
+ assertEquals("Incorrect number of records", 2, r.getInt(1));
+ r.close();
+ stat.close();
+ }
+}
diff --git a/sql/src/test/java/tests/java/sql/MultiThreadAccessTest.java b/sql/src/test/java/tests/java/sql/MultiThreadAccessTest.java
new file mode 100755
index 0000000..9675fce
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/MultiThreadAccessTest.java
@@ -0,0 +1,473 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import tests.support.ThreadPool;
+
+@TestTargetClass(Statement.class)
+public class MultiThreadAccessTest extends TestCase {
+
+ private static Connection conn;
+
+ private static Statement statement;
+
+ private static final int numThreads = 10;
+
+ private static final int numOfRecords = 20;
+
+ private ThreadPool threadPool;
+
+ protected void setUp() throws Exception {
+ threadPool = new ThreadPool(numThreads);
+ }
+
+ protected void tearDown() throws Exception {
+ threadPool.join();
+ }
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ MultiThreadAccessTest.class)) {
+ protected void setUp() throws Exception {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ createTestTables();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ deleteTestTables();
+ conn.close();
+ statement.close();
+ }
+
+ private void createTestTables() {
+ try {
+ ResultSet userTab = conn.getMetaData().getTables(null,
+ null, null, null);
+
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE2)) {
+ statement.execute(DatabaseCreator.DROP_TABLE2);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE4)) {
+ statement.execute(DatabaseCreator.DROP_TABLE4);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE3)) {
+ statement.execute(DatabaseCreator.DROP_TABLE3);
+ }
+ }
+
+ userTab.close();
+ statement.execute(DatabaseCreator.CREATE_TABLE3);
+ statement.execute(DatabaseCreator.CREATE_TABLE4);
+ statement.execute(DatabaseCreator.CREATE_TABLE1);
+ statement.execute(DatabaseCreator.CREATE_TABLE2);
+
+ DatabaseCreator.fillTestTable1(conn, numOfRecords);
+ DatabaseCreator.fillTestTable2(conn, numOfRecords);
+ DatabaseCreator.fillTestTable4(conn, numOfRecords);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ private void deleteTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ statement.execute(DatabaseCreator.DROP_TABLE2);
+ statement.execute(DatabaseCreator.DROP_TABLE3);
+ statement.execute(DatabaseCreator.DROP_TABLE4);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * A few threads execute select operation in the same time for one table in
+ * the database. Number of threads is defined by numThreads variable
+ *
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Functionality test: A few threads execute select operation in the same time for one table in the database.",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_MultipleAccessToOneTable() throws SQLException {
+ for (int i = 0; i < numThreads; i++) {
+ threadPool.runTask(createTask1(i));
+ }
+ }
+
+ /**
+ * A few threads execute select operation in the same time for different
+ * tables in the database. Number of threads is defined by numThreads
+ * variable
+ *
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Functionality test: A few threads execute select operation in the same time for different tables in the database",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_MultipleAccessToSeveralTables() throws SQLException {
+ threadPool.runTask(createTask1(1));
+ threadPool.runTask(createTask2(2));
+ threadPool.runTask(createTask3(3));
+ }
+
+ /**
+ * A few threads execute update, insert and delete operations in the same
+ * time for one table in the database. Number of threads is defined by
+ * numThreads variable
+ *
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Functionality test: A few threads execute update, insert and delete operations in the same time for one table in the database",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_MultipleOperationsInSeveralTables() throws SQLException {
+ int id1 = numOfRecords - 1;
+ threadPool.runTask(createTask4(id1));
+
+ int id2 = numOfRecords + 1;
+ threadPool.runTask(createTask5(id2));
+
+ int oldID = 5;
+ int newID = 100;
+ threadPool.runTask(createTask6(oldID, newID));
+
+ threadPool.join();
+
+ Statement statement = conn.createStatement();
+ String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1
+ + " WHERE id=";
+
+ ResultSet result = statement.executeQuery(selectQuery + id1);
+ assertFalse("The record was not deleted", result.next());
+
+ result = statement.executeQuery(selectQuery + id2);
+ assertTrue("The record was not inserted", result.next());
+
+ assertEquals("Wrong value of field1", DatabaseCreator.defaultString
+ + id2, result.getString("field1"));
+// TODO getBigDecimal is not supported
+ assertEquals("Wrong value of field2", Integer.valueOf(id2).intValue(), result
+ .getInt("field2"));
+ assertEquals("Wrong value of field3", Integer.valueOf(id2).intValue(), result
+ .getInt("field3"));
+ result.close();
+
+ result = statement.executeQuery(selectQuery + oldID);
+ assertFalse("The record was not deleted", result.next());
+ result.close();
+
+ result = statement.executeQuery(selectQuery + newID);
+ assertTrue("The record was not updated", result.next());
+
+ assertEquals("Wrong value of field1", DatabaseCreator.defaultString
+ + newID, result.getString("field1"));
+ // TODO getBigDecimal is not supported
+ assertEquals("Wrong value of field2", Integer.valueOf(newID).intValue(), result
+ .getInt("field2"));
+ assertEquals("Wrong value of field3", Integer.valueOf(newID).intValue(), result
+ .getInt("field3"));
+ result.close();
+ }
+
+ /**
+ * A few threads execute update operation in the same time for one tables in
+ * the database. Number of threads is defined by numThreads variable
+ *
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL,
+ notes = "Functional test: A few threads execute update operation in the same time for one tables in the database",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_MultipleUpdatesInOneTables() throws SQLException {
+ int id = 1;
+ String field = "field3";
+
+ String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1
+ + " WHERE id=" + id;
+ Statement statement = conn.createStatement();
+
+ ResultSet result = statement.executeQuery(selectQuery);
+ assertTrue("There is no records with id = " + id, result.next());
+ // TODO getBigDecimal is not supported
+// assertEquals("Wrong value of field " + field, BigDecimal.valueOf(id),
+// result.getBigDecimal(field));
+ result.close();
+
+ for (int i = 0; i < numThreads; i++) {
+ threadPool.runTask(createTask7(id, field));
+ }
+
+ threadPool.join();
+
+ double expectedVal = id + numThreads;
+ result = statement.executeQuery(selectQuery);
+ assertTrue("There is no records with id = " + id, result.next());
+ // TODO getBigDecimal is not supported ->
+// assertEquals("Wrong value of field " + field, expectedVal, result
+// .getBigDecimal(field).doubleValue());
+ result.close();
+ }
+
+ /**
+ * This method creates a Runnable that executes select operation for the
+ * first table
+ *
+ * @param taskID
+ * @return
+ */
+ private static Runnable createTask1(final int taskID) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Statement statement = conn.createStatement();
+ ResultSet result = statement.executeQuery("SELECT * FROM "
+ + DatabaseCreator.TEST_TABLE1);
+
+ while (result.next()) {
+ assertEquals("Wrong value of id ",
+ DatabaseCreator.defaultString
+ + result.getInt("id"), result
+ .getString("field1"));
+ assertEquals("Wrong value of field2 ", result.getInt("id"), result
+ .getInt("field2"));
+ assertEquals("Wrong value of field3 ",result.getInt("id"), result
+ .getInt("field3"));
+ }
+ result.close();
+ } catch (Exception e) {
+ System.err.println("Task 1 "+e.getMessage());
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that execute select operation for the
+ * second table
+ *
+ * @param taskID
+ */
+ private static Runnable createTask2(final int taskID) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Statement statement = conn.createStatement();
+ ResultSet result = statement.executeQuery("SELECT * FROM "
+ + DatabaseCreator.TEST_TABLE2);
+
+ while (result.next()) {
+ while (result.next()) {
+ int id = result.getInt("finteger");
+ assertEquals("Wrong value of ftext",
+ DatabaseCreator.defaultString + id, result
+ .getString("ftext"));
+ assertEquals("Wrong value of fcharacter",
+ DatabaseCreator.defaultCharacter + id,
+ result.getString("fcharacter"));
+ assertEquals("Wrong value of fdecimal",
+ DatabaseCreator.defaultDouble + id, result
+ .getDouble("fdecimal"));
+ assertEquals("Wrong value of fnumeric",
+ DatabaseCreator.defaultDouble + id, result
+ .getDouble("fnumeric"));
+ assertEquals("Wrong value of fsmallint", result
+ .getInt("finteger"), result
+ .getShort("fsmallint"));
+ assertEquals("Wrong value of ffloat",
+ (float) DatabaseCreator.defaultDouble + id,
+ result.getFloat("ffloat"));
+ assertEquals("Wrong value of freal",
+ (float) DatabaseCreator.defaultDouble + id,
+ result.getFloat("freal"));
+ assertEquals("Wrong value of fdouble",
+ DatabaseCreator.defaultDouble + id, result
+ .getDouble("fdouble"));
+ }
+ }
+ result.close();
+ } catch (Exception e) {
+ System.err.println("Task2 "+e.getMessage());
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that execute select operation for the
+ * third table
+ *
+ * @param taskID
+ */
+ private static Runnable createTask3(final int taskID) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Statement statement = conn.createStatement();
+ ResultSet result = statement.executeQuery("SELECT * FROM "
+ + DatabaseCreator.TEST_TABLE4);
+
+ while (result.next()) {
+ assertEquals("Wrong value of field1",
+ DatabaseCreator.defaultString
+ + result.getInt("fk"), result
+ .getString("field1"));
+ }
+ result.close();
+ } catch (Exception e) {
+ System.err.println("Task 3 "+e.getMessage());
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that executes delete operation for the
+ * first table
+ *
+ * @param taskID
+ */
+ private static Runnable createTask4(final int id) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Statement statement = conn.createStatement();
+ statement.execute("DELETE FROM "
+ + DatabaseCreator.TEST_TABLE1 + " WHERE id=" + id);
+ } catch (Exception e) {
+ System.err.println("Task 4 "+e.getMessage());
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that executes insert operation for the
+ * first table
+ *
+ * @param taskID
+ */
+ private static Runnable createTask5(final int id) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Statement statement = conn.createStatement();
+ String value = DatabaseCreator.defaultString + id;
+
+ String insertQuery = "INSERT INTO "
+ + DatabaseCreator.TEST_TABLE1
+ + " (id, field1, field2, field3) VALUES(" + id
+ + ", '" + value + "', " + id + ", " + id + ")";
+ statement.execute(insertQuery);
+ } catch (Exception e) {
+ System.err.println("Task 5 "+e.getMessage());
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that executes update operation for the one
+ * record of the first table
+ *
+ * @param taskID
+ */
+ private static Runnable createTask6(final int oldID, final int newID) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Statement statement = conn.createStatement();
+ String value = DatabaseCreator.defaultString + newID;
+ String updateQuery = "UPDATE "
+ + DatabaseCreator.TEST_TABLE1 + " SET id=" + newID
+ + ", field1='" + value + "', field2=" + newID
+ + ", field3=" + newID + " WHERE id=" + oldID;
+ statement.execute(updateQuery);
+ } catch (Exception e) {
+ System.err.println("Task 6 "+e.getMessage());
+ }
+ }
+ };
+ }
+
+ /**
+ * This method creates a Runnable that executes update operation for the one
+ * field of one record with identifier id in the first table
+ *
+ * @param taskID
+ */
+ private static Runnable createTask7(final int id, final String field) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Statement statement = conn.createStatement();
+ String updateQuery = "UPDATE "
+ + DatabaseCreator.TEST_TABLE1 + " SET " + field
+ + "= " + field + "+ 1 WHERE id=" + id;
+ statement.execute(updateQuery);
+ } catch (Exception e) {
+ System.err.println("Task 7 "+e.getMessage());
+ }
+ }
+ };
+ }
+}
\ No newline at end of file
diff --git a/sql/src/test/java/tests/java/sql/QueryTimeoutTest.java b/sql/src/test/java/tests/java/sql/QueryTimeoutTest.java
new file mode 100644
index 0000000..c6452b5
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/QueryTimeoutTest.java
@@ -0,0 +1,766 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package tests.java.sql;
+
+import SQLite.Database;
+import SQLite.Function;
+import SQLite.FunctionContext;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+import tests.support.Support_SQL;
+
+import java.sql.CallableStatement;
+import java.sql.Connection;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+
+
+/**
+ * Functional test for the Statement.setQueryTimeout() method. Adopted from
+ * Apache Derby project (Apache License 2.0).
+ *
+ * TODO Test requires transaction isolation to be supported. => Ticket 69
+ *
+ * This test consists of four parts: 1. Executes a SELECT
+ * query in 4 different threads concurrently. The query calls a user-defined,
+ * server-side function which delays the execution, so that it takes several
+ * seconds even though the data volume is really low. The fetch operations take
+ * longer time than the timeout value set. Hence, this part tests getting
+ * timeouts from calls to ResultSet.next(). Two connections are used, two
+ * threads execute their statement in the context of one connection, the other
+ * two threads in the context of the other connection. Of the 4 threads, only
+ * one executes its statement with a timeout value. This way, the test ensures
+ * that the correct statement is affected by setQueryTimeout(), regardless of
+ * what connection/transaction it and other statements are executed in the
+ * context of.
+ *
+ * 2. Executes an INSERT query in multiple threads. This part tests
+ * getting timeouts from calls to Statement.execute(). Each thread executes the
+ * query in the context of a separate connection. There is no point in executing
+ * multiple statements on the same connection; since only one statement per
+ * connection executes at a time, there will be no interleaving of execution
+ * between them (contrary to the first part of this test, where calls to
+ * ResultSet.next() may be interleaved between the different threads). Half of
+ * the threads execute their statement with a timeout value set, this is to
+ * verify that the correct statements are affected by the timeout, while the
+ * other statements execute to completion.
+ * 3. Sets an invalid (negative)
+ * timeout. Verifies that the correct exception is thrown.
+ * 4. Tests that the query timeout value is not forgotten after the execution of a statement.
+ */
+@TestTargetClass(Statement.class)
+public class QueryTimeoutTest extends TestCase {
+
+ private static Statement statement;
+
+ private static final int TIMEOUT = 1; // In seconds
+ private static final int CONNECTIONS = 100;
+
+ private static Connection[] connections = new Connection[CONNECTIONS];
+
+ private static void printSQLException(SQLException e) {
+ while (e != null) {
+ e.printStackTrace();
+ e = e.getNextException();
+ }
+ }
+
+ /**
+ * This Exception class is used for getting fail-fast behaviour in this
+ * test. There is no point in wasting cycles running a test to the end when
+ * we know that it has failed. In order to enable chaining of exceptions in
+ * J2ME, this class defines its own "cause", duplicating existing
+ * functionality in J2SE.
+ */
+ private static class TestFailedException extends Exception {
+ private Throwable cause;
+
+ public TestFailedException(Throwable t) {
+ super();
+ cause = t;
+ }
+
+ public TestFailedException(String message) {
+ super(message);
+ cause = null;
+ }
+
+ public TestFailedException(String message, Throwable t) {
+ super(message);
+ cause = t;
+ }
+
+ public String toString() {
+ if (cause != null) {
+ return super.toString() + ": " + cause.toString();
+ } else {
+ return super.toString();
+ }
+ }
+
+ public void printStackTrace() {
+ super.printStackTrace();
+ if (cause != null) {
+ if (cause instanceof SQLException) {
+ QueryTimeoutTest.printSQLException((SQLException) cause);
+ } else {
+ cause.printStackTrace();
+ }
+ }
+ }
+ }
+
+ /**
+ * Used for executing the SQL statements for setting up this test (the
+ * preparation phase). The queries testing setQueryTimeout() are run by the
+ * StatementExecutor class.
+ */
+ private static void exec(Connection connection, String queryString,
+ Collection ignoreExceptions) throws TestFailedException {
+ Statement statement = null;
+ try {
+ statement = connection.createStatement();
+ System.out.println(" Executing "+queryString);
+ statement.execute(queryString);
+ } catch (SQLException e) {
+ String sqlState = e.getSQLState();
+ if (!ignoreExceptions.contains(sqlState)) {
+ throw new TestFailedException(e); // See finally block below
+ }
+ } finally {
+ if (statement != null) {
+ try {
+ statement.close();
+ } catch (SQLException ee) {
+ // This will discard an exception possibly thrown above :-(
+ // But we don't worry too much about this, since:
+ // 1. This is just a test
+ // 2. We don't expect close() to throw
+ // 3. If it does, this will be inspected by a developer
+ throw new TestFailedException(ee);
+ }
+ }
+ }
+ }
+
+ // Convenience method
+ private static void exec(Connection connection, String queryString)
+ throws TestFailedException {
+ exec(connection, queryString, Collections.EMPTY_SET);
+ }
+
+ private static void dropTables(Connection conn, String tablePrefix)
+ throws TestFailedException {
+ Collection ignore = new HashSet();
+ //ignore.add("42Y55");
+
+ exec(conn, "drop table if exists " + tablePrefix + "_orig;", ignore);
+ exec(conn, "drop table if exists " + tablePrefix + "_copy;", ignore);
+ }
+
+ private static void prepareTables(Connection conn, String tablePrefix)
+ throws TestFailedException {
+ System.out.println("Initializing tables with prefix " + tablePrefix);
+
+ dropTables(conn, tablePrefix);
+
+ exec(conn, "create table " + tablePrefix + "_orig (a int)");
+
+ exec(conn, "create table " + tablePrefix + "_copy (a int)");
+
+ for (int i = 0; i < 7; i++) {
+ exec(conn, "insert into " + tablePrefix + "_orig"
+ + " values ("+i+");");
+ }
+ }
+
+ private static String getFetchQuery(String tablePrefix) {
+ /**
+ * The reason for using the mod function here is to force at least one
+ * invocation of ResultSet.next() to read more than one row from the
+ * table before returning. This is necessary since timeout is checked
+ * only when reading rows from base tables, and when the first row is
+ * read, the query still has not exceeded the timeout.
+ */
+ return "select a from " + tablePrefix
+ + "_orig where mod(DELAY(1,a),3)=0";
+ }
+
+ private static String getExecQuery(String tablePrefix) {
+ return "insert into " + tablePrefix + "_copy select a from "
+ + tablePrefix + "_orig where DELAY(1,1)=1";
+ }
+
+ private static class StatementExecutor extends Thread {
+ private PreparedStatement statement;
+ private boolean doFetch;
+ private int timeout;
+ private SQLException sqlException;
+ private String name;
+ private long highestRunTime;
+
+ public StatementExecutor(PreparedStatement statement, boolean doFetch,
+ int timeout) {
+ this.statement = statement;
+ this.doFetch = doFetch;
+ this.timeout = timeout;
+ highestRunTime = 0;
+ sqlException = null;
+ if (timeout > 0) {
+ try {
+ statement.setQueryTimeout(timeout);
+ } catch (SQLException e) {
+ sqlException = e;
+ }
+ }
+ }
+
+ private void setHighestRunTime(long runTime) {
+ synchronized (this) {
+ highestRunTime = runTime;
+ }
+ }
+
+ public long getHighestRunTime() {
+ synchronized (this) {
+ return highestRunTime;
+ }
+ }
+
+ private boolean fetchRow(ResultSet resultSet) throws SQLException {
+ long startTime = System.currentTimeMillis();
+ boolean hasNext = resultSet.next();
+ long endTime = System.currentTimeMillis();
+ long runTime = endTime - startTime;
+ if (runTime > highestRunTime) setHighestRunTime(runTime);
+ return hasNext;
+ }
+
+ public void run() {
+ if (sqlException != null) return;
+
+ ResultSet resultSet = null;
+
+ try {
+ if (doFetch) {
+ long startTime = System.currentTimeMillis();
+ resultSet = statement.executeQuery();
+ long endTime = System.currentTimeMillis();
+ setHighestRunTime(endTime - startTime);
+ while (fetchRow(resultSet)) {
+ yield();
+ }
+ } else {
+ long startTime = System.currentTimeMillis();
+ statement.execute();
+ long endTime = System.currentTimeMillis();
+ setHighestRunTime(endTime - startTime);
+ }
+ } catch (SQLException e) {
+ synchronized (this) {
+ sqlException = e;
+ }
+ } finally {
+ if (resultSet != null) {
+ try {
+ resultSet.close();
+ } catch (SQLException ex) {
+ if (sqlException != null) {
+ System.err.println("Discarding previous exception");
+ sqlException.printStackTrace();
+ }
+ sqlException = ex;
+ }
+ }
+ }
+ }
+
+ public SQLException getSQLException() {
+ synchronized (this) {
+ return sqlException;
+ }
+ }
+ }
+
+ /**
+ * This method compares a thrown SQLException's SQLState value to an
+ * expected SQLState. If they do not match, a TestFailedException is thrown
+ * with the given message string.
+ */
+ private static void expectException(String expectSqlState,
+ SQLException sqlException, String failMsg)
+ throws TestFailedException {
+ if (sqlException == null) {
+ throw new TestFailedException(failMsg);
+ } else {
+ String sqlState = sqlException.getSQLState();
+ if (!expectSqlState.equals(sqlState)) {
+ throw new TestFailedException(sqlException);
+ }
+ }
+ }
+
+ // A convenience method which wraps a SQLException
+ private static PreparedStatement prepare(Connection conn, String query)
+ throws TestFailedException {
+ try {
+ return conn.prepareStatement(query);
+ } catch (SQLException e) {
+ throw new TestFailedException(e);
+ }
+ }
+
+ /**
+ * Part 1 of this test.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Testing timeout with fetch operations",
+ method = "setQueryTimeout",
+ args = {int.class}
+ )
+ public static void testTimeoutWithFetch() throws TestFailedException {
+ System.out.println("Testing timeout with fetch operations");
+
+ Connection conn1 = connections[0];
+ Connection conn2 = connections[1];
+
+ try {
+ conn1.setAutoCommit(false);
+ conn2.setAutoCommit(false);
+ } catch (SQLException e) {
+ throw new TestFailedException("Unexpected Exception", e);
+ }
+
+ // The idea with these 4 statements is as follows:
+ // A - should time out
+ // B - different stmt on the same connection; should NOT time out
+ // C - different stmt on different connection; should NOT time out
+ // D - here just to create equal contention on conn1 and conn2
+
+ PreparedStatement statementA = prepare(conn1, getFetchQuery("t"));
+ PreparedStatement statementB = prepare(conn1, getFetchQuery("t"));
+ PreparedStatement statementC = prepare(conn2, getFetchQuery("t"));
+ PreparedStatement statementD = prepare(conn2, getFetchQuery("t"));
+
+ StatementExecutor[] statementExecutor = new StatementExecutor[4];
+ statementExecutor[0] = new StatementExecutor(statementA, true, TIMEOUT);
+ statementExecutor[1] = new StatementExecutor(statementB, true, 0);
+ statementExecutor[2] = new StatementExecutor(statementC, true, 0);
+ statementExecutor[3] = new StatementExecutor(statementD, true, 0);
+
+ for (int i = 3; i >= 0; --i) {
+ statementExecutor[i].start();
+ }
+
+ for (int i = 0; i < 4; ++i) {
+ try {
+ statementExecutor[i].join();
+ } catch (InterruptedException e) {
+ throw new TestFailedException("Should never happen", e);
+ }
+ }
+
+ /**
+ * Actually, there is no guarantee that setting a query timeout for a
+ * statement will actually cause a timeout, even if execution of the
+ * statement takes longer than the specified timeout. However, these
+ * queries execute significantly longer than the specified query
+ * timeout. Also, the cancellation mechanism implemented should be quite
+ * responsive. In sum, we expect the statement to always time out. If it
+ * does not time out, however, we print the highest execution time for
+ * the query, as an assistance in determining why it failed. Compare the
+ * number to the TIMEOUT constant in this class (note that the TIMEOUT
+ * constant is in seconds, while the execution time is in milliseconds).
+ */
+ expectException("XCL52", statementExecutor[0].getSQLException(),
+ "fetch did not time out. Highest execution time: "
+ + statementExecutor[0].getHighestRunTime() + " ms");
+
+ System.out.println("Statement 0 timed out");
+
+ for (int i = 1; i < 4; ++i) {
+ SQLException sqlException = statementExecutor[i].getSQLException();
+ if (sqlException != null) {
+ throw new TestFailedException("Unexpected exception in " + i,
+ sqlException);
+ }
+ System.out.println("Statement " + i + " completed");
+ }
+
+ try {
+ statementA.close();
+ statementB.close();
+ statementC.close();
+ statementD.close();
+ conn1.commit();
+ conn2.commit();
+ } catch (SQLException e) {
+ throw new TestFailedException(e);
+ }
+ }
+
+ /**
+ *
+ * @test {@link java.sql.Statement#setQueryTimeout(int) }
+ *
+ * Part two of this test.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "test timeout with st.exec()",
+ method = "setQueryTimeout",
+ args = {int.class}
+ )
+ public static void testTimeoutWithExec()
+ throws TestFailedException {
+ System.out.println("Testing timeout with an execute operation");
+
+ for (int i = 0; i < connections.length; ++i) {
+ try {
+ connections[i].setAutoCommit(true);
+ } catch (SQLException e) {
+ throw new TestFailedException("Unexpected Exception", e);
+ }
+ }
+
+ PreparedStatement statements[] = new PreparedStatement[connections.length];
+ for (int i = 0; i < statements.length; ++i) {
+ statements[i] = prepare(connections[i], getExecQuery("t"));
+ }
+
+ StatementExecutor[] executors = new StatementExecutor[statements.length];
+ for (int i = 0; i < executors.length; ++i) {
+ int timeout = (i % 2 == 0) ? TIMEOUT : 0;
+ executors[i] = new StatementExecutor(statements[i], false, timeout);
+ }
+
+ for (int i = 0; i < executors.length; ++i) {
+ executors[i].start();
+ }
+
+ for (int i = 0; i < executors.length; ++i) {
+ try {
+ executors[i].join();
+ } catch (InterruptedException e) {
+ throw new TestFailedException("Should never happen", e);
+ }
+ }
+
+ /**
+ * Actually, there is no guarantee that setting a query timeout for a
+ * statement will actually cause a timeout, even if execution of the
+ * statement takes longer than the specified timeout. However, these
+ * queries execute significantly longer than the specified query
+ * timeout. Also, the cancellation mechanism implemented should be quite
+ * responsive. In sum, we expect the statement to always time out. If it
+ * does not time out, however, we print the highest execution time for
+ * the query, as an assistance in determining why it failed. Compare the
+ * number to the TIMEOUT constant in this class (note that the TIMEOUT
+ * constant is in seconds, while the execution time is in milliseconds).
+ */
+ for (int i = 0; i < executors.length; ++i) {
+ int timeout = (i % 2 == 0) ? TIMEOUT : 0;
+ if (timeout > 0) {
+ expectException("XCL52", executors[i].getSQLException(),
+ "exec did not time out. Execution time: "
+ + executors[i].getHighestRunTime() + " ms");
+ } else {
+ SQLException sqlException = executors[i].getSQLException();
+ if (sqlException != null) {
+ throw new TestFailedException(sqlException);
+ }
+ }
+ }
+
+ System.out
+ .println("Statements that should time out timed out, and statements that should complete completed");
+
+ for (int i = 0; i < statements.length; ++i) {
+ try {
+ statements[i].close();
+ } catch (SQLException e) {
+ throw new TestFailedException(e);
+ }
+ }
+ }
+
+
+ /**
+ *
+ * @test {@link java.sql.Statement#setQueryTimeout(int) }
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Testing setting a negative timeout value",
+ method = "setQueryTimeout",
+ args = {int.class}
+ )
+ public static void testInvalidTimeoutValue(Connection conn)
+ throws TestFailedException {
+
+ try {
+ conn.setAutoCommit(true);
+ } catch (SQLException e) {
+ throw new TestFailedException("Unexpected Exception", e);
+ }
+
+ // Create statement
+ PreparedStatement stmt = null;
+ try {
+ stmt = conn.prepareStatement("select * from sys.systables");
+ } catch (SQLException e) {
+ throw new TestFailedException("Unexpected Exception", e);
+ }
+
+ // Set (invalid) timeout value - expect exception
+ try {
+ stmt.setQueryTimeout(-1);
+ } catch (SQLException e) {
+ expectException("XJ074", e,
+ "negative timeout value should give exception");
+ }
+
+ System.out
+ .println("Negative timeout value caused exception, as expected");
+
+ // Execute the statement and fetch result
+ ResultSet rs = null;
+ try {
+ rs = stmt.executeQuery();
+ System.out.println("Execute returned a ResultSet");
+ rs.close();
+ } catch (SQLException e) {
+ throw new TestFailedException("Unexpected Exception", e);
+ } finally {
+ try {
+ stmt.close();
+ } catch (SQLException e) {
+ // This will discard an exception possibly thrown above :-(
+ // But we don't worry too much about this, since:
+ // 1. This is just a test
+ // 2. We don't expect close() to throw
+ // 3. If it does, this will be inspected by a developer
+ throw new TestFailedException("close should not throw", e);
+ }
+ }
+ }
+
+ /**
+ *
+ * @test {@link java.sql.Statement#setQueryTimeout(int) }
+ *
+ * Part two of this test.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "timeout with executeUpdate call",
+ method = "setQueryTimeout",
+ args = {int.class}
+ )
+ public static void testTimeoutWithExecuteUpdate()
+ throws TestFailedException {
+ System.out.println("Testing timeout with executeUpdate call.");
+ try {
+ Statement stmt = connections[0].createStatement();
+ stmt.setQueryTimeout(TIMEOUT);
+ stmt.executeUpdate(getExecQuery("t"));
+ } catch (SQLException sqle) {
+ expectException("XCL52", sqle, "Should have timed out.");
+ }
+ }
+
+ /** Test for DERBY-1692. */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Testing that Statement considers timeout.",
+ method = "setQueryTimeout",
+ args = {int.class}
+ )
+ public static void testRememberTimeoutValue()
+ throws TestFailedException {
+ String sql = getFetchQuery("t");
+ try {
+ Statement stmt = connections[0].createStatement();
+ statementRemembersTimeout(stmt);
+ PreparedStatement ps = connections[0].prepareStatement(sql);
+ statementRemembersTimeout(ps);
+ CallableStatement cs = connections[0].prepareCall(sql);
+ statementRemembersTimeout(cs);
+ } catch (SQLException sqle) {
+ throw new TestFailedException("Unexpected Exception", sqle);
+ }
+ }
+
+ public static void statementRemembersTimeout(Statement stmt)
+ throws SQLException, TestFailedException {
+ System.out.println("Testing that Statement remembers timeout.");
+ stmt.setQueryTimeout(1);
+ for (int i = 0; i < 3; i++) {
+ try {
+ ResultSet rs = stmt.executeQuery(getFetchQuery("t"));
+ while (rs.next()) {
+ // do nothing
+ }
+ throw new TestFailedException("Should have timed out.");
+ } catch (SQLException sqle) {
+ expectException("XCL52", sqle, "Should have timed out.");
+ }
+ }
+ stmt.close();
+ }
+
+ private static void statementRemembersTimeout(PreparedStatement ps)
+ throws SQLException, TestFailedException {
+ String name = (ps instanceof CallableStatement) ? "CallableStatement"
+ : "PreparedStatement";
+ System.out.println("Testing that " + name + " remembers timeout.");
+ ps.setQueryTimeout(1);
+ for (int i = 0; i < 3; i++) {
+ try {
+ ResultSet rs = ps.executeQuery();
+ while (rs.next()) {
+ // do nothing
+ }
+ throw new TestFailedException("Should have timed out.");
+ } catch (SQLException sqle) {
+ expectException("XCL52", sqle, "Should have timed out.");
+ }
+ }
+ ps.close();
+ }
+
+ /**
+ * A function
+ * arg0 : int seconds
+ *
+ */
+ static class Delay implements SQLite.Function {
+
+ public void function(FunctionContext fc, String[] args) {
+ int seconds = new Integer(args[0]).intValue();
+ int value = new Integer(args[1]).intValue();
+ try {
+ Thread.sleep(seconds * 1000);
+ } catch (InterruptedException e) {
+ // Ignore
+ }
+ fc.set_result(value);
+
+ }
+
+ public void last_step(FunctionContext fc) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public void step(FunctionContext fc, String[] args) {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+ /**
+ * The actual main bulk of this test. Sets up the environment, prepares
+ * tables, runs the tests, and shuts down.
+ */
+ public static Test suite() {
+
+ TestSetup setup = new TestSetup( new TestSuite (QueryTimeoutTest.class)) {
+ public void setUp() {
+
+ // Establish connections
+ Support_SQL.loadDriver();
+ try {
+
+ for (int i = 0; i < connections.length; ++i) {
+ connections[i] = Support_SQL.getConnection();
+ }
+
+ for (int i = 0; i < connections.length; ++i) {
+ connections[i]
+ .setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+ }
+
+ // setup Delay function
+ prepare();
+
+ } catch (Throwable e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+
+ System.out.println("Connections set up");
+
+ }
+
+ public void tearDown() {
+ for (int i = connections.length - 1; i >= 0; --i) {
+ if (connections[i] != null) {
+ try {
+ connections[i].close();
+ } catch (SQLException ex) {
+ printSQLException(ex);
+ }
+ }
+ }
+ System.out.println("Closed connections");
+ }
+
+ public void prepare() throws TestFailedException {
+ System.out.println("Preparing for testing queries with timeout");
+ Database db = new Database();
+
+ Connection conn = connections[0];
+
+
+ try {
+ db.open(Support_SQL.getFilename(), 1);
+ conn.setAutoCommit(true);
+ } catch (Exception e) {
+ throw new TestFailedException("Unexpected Exception", e);
+ }
+
+ Function delayFc = new Delay();
+ db.create_function("DELAY", 2, delayFc);
+
+ prepareTables(conn, "t");
+ }
+ };
+
+ TestSuite ts = new TestSuite();
+ ts.addTestSuite(QueryTimeoutTest.class);
+
+ return setup;
+ }
+
+}
diff --git a/sql/src/test/java/tests/java/sql/SelectFunctionalityTest.java b/sql/src/test/java/tests/java/sql/SelectFunctionalityTest.java
new file mode 100755
index 0000000..5c8f189
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/SelectFunctionalityTest.java
@@ -0,0 +1,632 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.java.sql;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.io.CharArrayReader;
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Time;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.HashMap;
+import java.util.HashSet;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+@TestTargetClass(Statement.class)
+public class SelectFunctionalityTest extends TestCase {
+
+ private static Connection conn;
+
+ private static Statement statement;
+
+ private static Date date;
+
+ private static Time time;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ }
+
+ protected void tearDown() throws Exception {
+ super.tearDown();
+ }
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ SelectFunctionalityTest.class)) {
+ protected void setUp() throws Exception {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ createTestTables();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ deleteTestTables();
+ conn.close();
+ statement.close();
+ }
+
+ private void createTestTables() {
+ try {
+ ResultSet userTab = conn.getMetaData().getTables(null,
+ null, null, null);
+
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE2)) {
+ statement.execute(DatabaseCreator.DROP_TABLE2);
+ } else if (tableName
+ .equals(DatabaseCreator.SALESPEOPLE_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_SALESPEOPLE);
+ } else if (tableName
+ .equals(DatabaseCreator.CUSTOMERS_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_CUSTOMERS);
+ } else if (tableName
+ .equals(DatabaseCreator.ORDERS_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_ORDERS);
+ }
+ }
+ userTab.close();
+
+ statement.execute(DatabaseCreator.CREATE_TABLE2);
+ statement.execute(DatabaseCreator.CREATE_TABLE_SALESPEOPLE);
+ statement.execute(DatabaseCreator.CREATE_TABLE_CUSTOMERS);
+ statement.execute(DatabaseCreator.CREATE_TABLE_ORDERS);
+
+ long currentTime = Calendar.getInstance().getTimeInMillis();
+ date = new Date(currentTime);
+ time = new Time(currentTime);
+
+ DatabaseCreator.fillTestTable2(conn, 1, 5, currentTime);
+ DatabaseCreator.fillCustomersTable(conn);
+ DatabaseCreator.fillOrdersTable(conn);
+ DatabaseCreator.fillSalesPeopleTable(conn);
+
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ private void deleteTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE2);
+ statement.execute(DatabaseCreator.DROP_TABLE_SALESPEOPLE);
+ statement.execute(DatabaseCreator.DROP_TABLE_CUSTOMERS);
+ statement.execute(DatabaseCreator.DROP_TABLE_ORDERS);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectSimple(). Selects all records
+ * from the table
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects all records from the table",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectSimple() throws SQLException {
+ String sql = "SELECT * FROM " + DatabaseCreator.TEST_TABLE2;
+ ResultSet result = statement.executeQuery(sql);
+ int counter = 0;
+
+ while (result.next()) {
+ int id = result.getInt("finteger");
+ assertEquals("expected value doesn't equal actual",
+ DatabaseCreator.defaultString + id, result
+ .getString("ftext"));
+ assertEquals("expected value doesn't equal actual",
+ DatabaseCreator.defaultCharacter + id, result
+ .getString("fcharacter"));
+
+ // TODO getBigDecimal is not supported
+// assertEquals("expected value doesn't equal actual", BigDecimal
+// .valueOf(id + 0.1), result.getBigDecimal("fdecimal"));
+// assertEquals("expected value doesn't equal actual", BigDecimal
+// .valueOf(id + 0.1), result.getBigDecimal("fnumeric"));
+// assertEquals("expected value doesn't equal actual", id, result
+// .getInt("fsmallint"));
+ assertEquals("expected value doesn't equal actual", BigDecimal
+ .valueOf(id + 0.1).floatValue(), result.getFloat("ffloat"));
+ assertEquals("expected value doesn't equal actual", BigDecimal
+ .valueOf(id + 0.1).doubleValue(), result.getDouble("freal"));
+ assertEquals("expected value doesn't equal actual", BigDecimal
+ .valueOf(id + 0.1).doubleValue(), result
+ .getDouble("fdouble"));
+ assertEquals("expected value doesn't equal actual",
+ date.toString(), result.getDate("fdate").toString());
+ assertEquals("expected value doesn't equal actual",
+ time.toString(), result.getTime("ftime").toString());
+ counter++;
+ }
+
+ assertEquals("number of rows in ResultSet is wrong", 5, counter);
+ result.close();
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectPrepared(). Selects all records
+ * from the table using parametric query
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects all records from the table using parametric query",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectPrepared() throws SQLException {
+ String sql = "SELECT finteger, ftext, fcharacter, fdecimal, fnumeric,"
+ + " fsmallint, ffloat, freal, fdouble, fdate, ftime" + " FROM "
+ + DatabaseCreator.TEST_TABLE2
+ + " WHERE finteger = ? AND ftext = ? AND fcharacter = ? AND"
+ + " fdecimal = ? AND fnumeric = ? AND fsmallint = ? AND"
+ + " freal = ? AND fdouble = ? AND fdate = ?" + " AND ftime = ?";
+ PreparedStatement prepStatement = conn.prepareStatement(sql);
+
+ CharArrayReader reader = new CharArrayReader(new String(
+ DatabaseCreator.defaultCharacter + "1").toCharArray());
+ prepStatement.setInt(1, 1);
+ prepStatement.setString(2, DatabaseCreator.defaultString + "1");
+// TODO setCharacterStream and setBigDecimal are not supported
+// prepStatement.setCharacterStream(3, reader, 4);
+// prepStatement.setBigDecimal(4, BigDecimal.valueOf(1.1));
+// prepStatement.setBigDecimal(5, BigDecimal.valueOf(1.1));
+ prepStatement.setInt(6, 1);
+ prepStatement.setDouble(7, 1.1);
+ prepStatement.setDouble(8, 1.1);
+ prepStatement.setDate(9, date);
+ prepStatement.setTime(10, time);
+
+ int counter = 0;
+ ResultSet result = prepStatement.executeQuery();
+ while (result.next()) {
+ int id = result.getInt("finteger");
+ assertEquals("expected value doesn't equal actual",
+ DatabaseCreator.defaultString + id, result
+ .getString("ftext"));
+ assertEquals("expected value doesn't equal actual",
+ DatabaseCreator.defaultCharacter + id, result
+ .getString("fcharacter"));
+// TODO getBigDecimal is not supported
+// assertEquals("expected value doesn't equal actual", BigDecimal
+// .valueOf(1.1), result.getBigDecimal("fdecimal"));
+// assertEquals("expected value doesn't equal actual", BigDecimal
+// .valueOf(1.1), result.getBigDecimal("fnumeric"));
+ assertEquals("expected value doesn't equal actual", id, result
+ .getInt("fsmallint"));
+ assertEquals("expected value doesn't equal actual",
+ (float) (id + 0.1), result.getFloat("ffloat"));
+ assertEquals("expected value doesn't equal actual",
+ (double) (id + 0.1), result.getDouble("freal"));
+ assertEquals("expected value doesn't equal actual",
+ (double) (id + 0.1), result.getDouble("fdouble"));
+ assertEquals("expected value doesn't equal actual",
+ date.toString(), result.getDate("fdate").toString());
+ assertEquals("expected value doesn't equal actual",
+ time.toString(), result.getTime("ftime").toString());
+ counter++;
+ }
+// TODO query wasn't executed due to "not supported" methods
+// assertEquals("number of rows in ResultSet is wrong", 1, counter);
+ prepStatement.close();
+ result.close();
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SubSelect(). Selects records from the
+ * table using subselect
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from the table using subselect",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SubSelect() throws SQLException {
+ String sql = "SELECT finteger," + " (SELECT ftext FROM "
+ + DatabaseCreator.TEST_TABLE2 + " WHERE finteger = 1) as ftext"
+ + " FROM " + DatabaseCreator.TEST_TABLE2;
+ ResultSet result = statement.executeQuery(sql);
+
+ HashMap value = new HashMap();
+ value.put(1, DatabaseCreator.defaultString + "1");
+ value.put(2, DatabaseCreator.defaultString + "1");
+ value.put(3, DatabaseCreator.defaultString + "1");
+ value.put(4, DatabaseCreator.defaultString + "1");
+ value.put(5, DatabaseCreator.defaultString + "1");
+
+ while (result.next()) {
+ int key = result.getInt("finteger");
+ String val = result.getString("ftext");
+ assertTrue("wrong value of finteger field", value.containsKey(key));
+ assertEquals("wrong value of ftext field", value.get(key), val);
+ value.remove(key);
+ }
+ assertTrue("expected rows number doesn't equal actual rows number",
+ value.isEmpty());
+ result.close();
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectThreeTables(). Selects records
+ * from a few tables
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from a few tables",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectThreeTables() throws SQLException {
+ String sql = "SELECT onum, " + DatabaseCreator.ORDERS_TABLE + ".cnum"
+ + " FROM " + DatabaseCreator.SALESPEOPLE_TABLE + ", "
+ + DatabaseCreator.CUSTOMERS_TABLE + ", "
+ + DatabaseCreator.ORDERS_TABLE + " WHERE "
+ + DatabaseCreator.CUSTOMERS_TABLE + ".city <> "
+ + DatabaseCreator.SALESPEOPLE_TABLE + ".city" + " AND "
+ + DatabaseCreator.ORDERS_TABLE + ".cnum = "
+ + DatabaseCreator.CUSTOMERS_TABLE + ".cnum" + " AND "
+ + DatabaseCreator.ORDERS_TABLE + ".snum = "
+ + DatabaseCreator.SALESPEOPLE_TABLE + ".snum";
+ ResultSet result = statement.executeQuery(sql);
+
+ HashMap value = new HashMap();
+ value.put(3001, 2008);
+ value.put(3002, 2007);
+ value.put(3006, 2008);
+ value.put(3009, 2002);
+ value.put(3007, 2004);
+ value.put(3010, 2004);
+
+ while (result.next()) {
+ int key = result.getInt("onum");
+ int val = result.getInt("cnum");
+ assertTrue("wrong value of onum field", value.containsKey(key));
+ assertEquals("wrong value of cnum field", value.get(key),
+ (Integer) val);
+ value.remove(key);
+ }
+ assertTrue("expected rows number doesn't equal actual rows number",
+ value.isEmpty());
+ result.close();
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectThreeTables(). Selects records
+ * from a table using union
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from a table using union",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectUnionItself() throws SQLException {
+ String sql = "SELECT b.cnum, b.cname" + " FROM "
+ + DatabaseCreator.CUSTOMERS_TABLE + " a, "
+ + DatabaseCreator.CUSTOMERS_TABLE + " b"
+ + " WHERE a.snum = 1002" + " AND b.city = a.city";
+ ResultSet result = statement.executeQuery(sql);
+
+ HashMap value = new HashMap();
+ value.put(2003, "Liu");
+ value.put(2004, "Grass");
+ value.put(2008, "Cisneros");
+
+ while (result.next()) {
+ int key = result.getInt("cnum");
+ String val = result.getString("cname");
+ assertTrue("wrong value of cnum field", value.containsKey(key));
+ assertEquals("wrong value of cname field", value.get(key), val);
+ value.remove(key);
+ }
+ assertTrue("expected rows number doesn't equal actual rows number",
+ value.isEmpty());
+ result.close();
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectLeftOuterJoin(). Selects
+ * records from a table using left join
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from a table using left join",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectLeftOuterJoin() throws SQLException {
+ String sql = "SELECT distinct s.snum as ssnum, c.snum as ccnum FROM "
+ + DatabaseCreator.CUSTOMERS_TABLE + " c left outer join "
+ + DatabaseCreator.SALESPEOPLE_TABLE + " s on s.snum=c.snum";
+ ResultSet result = statement.executeQuery(sql);
+
+ HashMap value = new HashMap();
+ value.put(1001, 1001);
+ value.put(1002, 1002);
+ value.put(1003, 1003);
+ value.put(1004, 1004);
+ value.put(1007, 1007);
+
+ while (result.next()) {
+ int key = result.getInt("ssnum");
+ Object val = result.getObject("ccnum");
+ assertTrue("wrong value of ssnum field", value.containsKey(key));
+ assertEquals("wrong value of ccnum field", value.get(key),
+ (Integer) val);
+ value.remove(key);
+ }
+ assertTrue("expected rows number doesn't equal actual rows number",
+ value.isEmpty());
+ result.close();
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectRightOuterJoin(). Selects
+ * records from a table using right join
+ *
+ * TODO RIGHT and FULL OUTER JOINs are not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "tests right outer joins. RIGHT and FULL OUTER JOINs are not supported",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ @KnownFailure("not supported")
+ public void test_SelectRightOuterJoin() throws SQLException {
+ String sql = "SELECT distinct s.snum as ssnum, c.snum as ccnum FROM "
+ + DatabaseCreator.CUSTOMERS_TABLE + " c right outer join "
+ + DatabaseCreator.SALESPEOPLE_TABLE + " s on s.snum=c.snum";
+ ResultSet result = statement.executeQuery(sql);
+
+ HashMap value = new HashMap();
+ value.put(1001, 1001);
+ value.put(1002, 1002);
+ value.put(1003, 1003);
+ value.put(1004, 1004);
+ value.put(1007, 1007);
+ value.put(1013, null);
+
+ while (result.next()) {
+ int key = result.getInt("ssnum");
+ Object val = result.getObject("ccnum");
+ assertTrue("wrong value of ssnum field", value.containsKey(key));
+ assertEquals("wrong value of ccnum field", value.get(key),
+ (Integer) val);
+ value.remove(key);
+ }
+ assertTrue("expected rows number doesn't equal actual rows number",
+ value.isEmpty());
+ result.close();
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectGroupBy(). Selects records from
+ * a table using group by
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from a table using group by",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectGroupBy() throws SQLException {
+ String selectQuery = "SELECT rating, SUM(snum) AS sum FROM "
+ + DatabaseCreator.CUSTOMERS_TABLE + " GROUP BY rating";
+ ResultSet result = statement.executeQuery(selectQuery);
+
+ HashMap values = new HashMap();
+ values.put(100, 3006);
+ values.put(200, 2005);
+ values.put(300, 2009);
+
+ while (result.next()) {
+ int rating = result.getInt("rating");
+ int sum = result.getInt("sum");
+ assertTrue("Wrong value of rating field", values
+ .containsKey(rating));
+ assertEquals("Wrong value of sum field", values.get(rating),
+ new Integer(sum));
+ assertEquals(new Integer(sum), values.remove(rating));
+ }
+ result.close();
+ assertTrue("Result set has wrong size", values.isEmpty());
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectOrderBy(). Selects records from
+ * a table using order by
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from a table using order by",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectOrderBy() throws SQLException {
+ String selectQuery = "SELECT onum FROM " + DatabaseCreator.ORDERS_TABLE
+ + " ORDER BY onum";
+ ResultSet result = statement.executeQuery(selectQuery);
+
+ ArrayList values = new ArrayList();
+ values.add(Integer.valueOf(3001));
+ values.add(Integer.valueOf(3002));
+ values.add(Integer.valueOf(3003));
+ values.add(Integer.valueOf(3005));
+ values.add(Integer.valueOf(3006));
+ values.add(Integer.valueOf(3007));
+ values.add(Integer.valueOf(3008));
+ values.add(Integer.valueOf(3009));
+ values.add(Integer.valueOf(3010));
+ values.add(Integer.valueOf(3011));
+
+ int index = 0;
+ while (result.next()) {
+ Integer onum = result.getInt("onum");
+ assertTrue("result set doesn't contain value", values
+ .contains(onum));
+ assertEquals("result set is not sorted", index, values
+ .indexOf(onum));
+ index++;
+ }
+ result.close();
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectDistinct(). Selects records
+ * from a table using distinct
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from a table using distinct",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectDistinct() throws SQLException {
+ String selectQuery = "SELECT DISTINCT rating FROM "
+ + DatabaseCreator.CUSTOMERS_TABLE;
+ ResultSet result = statement.executeQuery(selectQuery);
+
+ HashSet values = new HashSet();
+ values.add(Integer.valueOf(100));
+ values.add(Integer.valueOf(200));
+ values.add(Integer.valueOf(300));
+
+ while (result.next()) {
+ Integer rating = result.getInt("rating");
+ assertTrue("result set doesn't contain value", values
+ .contains(rating));
+ assertTrue("wrong value in the result set", values.remove(rating));
+ }
+ result.close();
+ assertTrue("Result set has wrong size", values.isEmpty());
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectAgregateFunctions(). Selects
+ * records from a table using agregate functions
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from a table using agregate functions",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectAgregateFunctions() throws SQLException {
+ String selectCount = "SELECT count(onum) as count FROM "
+ + DatabaseCreator.ORDERS_TABLE;
+ String selectSum = "SELECT sum(onum) as sum FROM "
+ + DatabaseCreator.ORDERS_TABLE;
+ String selectAvg = "SELECT avg(onum) as avg FROM "
+ + DatabaseCreator.ORDERS_TABLE;
+ String selectMax = "SELECT max(onum) as max FROM "
+ + DatabaseCreator.ORDERS_TABLE;
+ String selectMin = "SELECT min(onum) as min FROM "
+ + DatabaseCreator.ORDERS_TABLE;
+
+ func("count", selectCount, 10);
+ func("sum", selectSum, 30062);
+ func("avg", selectAvg, 3006);
+ func("max", selectMax, 3011);
+ func("min", selectMin, 3001);
+ }
+
+ private void func(String name, String query, int expected) {
+ int res = 0;
+ double resDouble = 0.0;
+ try {
+ ResultSet result = statement.executeQuery(query);
+ while (result.next()) {
+ res = result.getInt(name);
+ if (res != 0 ) {
+ assertEquals(expected,res);
+ break;
+ }
+ // for Double: getInt not supported yet
+ resDouble = Double.parseDouble(result.getString(name));
+ res = (int) Math.rint(resDouble);
+ assertEquals(expected,res);
+
+ }
+ assertFalse("wrong size of result set", result.next());
+ result.close();
+ } catch (SQLException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ /**
+ * @tests SelectFunctionalityTest#test_SelectHaving(). Selects records from
+ * a table using having
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Selects records from a table using having",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void test_SelectHaving() throws SQLException {
+ String selectQuery = "SELECT snum, max(amt) AS max FROM "
+ + DatabaseCreator.ORDERS_TABLE
+ + " GROUP BY snum HAVING max(amt) > 3000";
+ ResultSet result = statement.executeQuery(selectQuery);
+
+ HashSet values = new HashSet();
+ values.add(Double.valueOf(9891.88));
+ values.add(Double.valueOf(5160.45));
+
+ while (result.next()) {
+ Double max = result.getDouble("max");
+ assertTrue("result set doesn't contain value", values.contains(max));
+ assertTrue("wrong value in the result set", values.remove(max));
+ }
+ result.close();
+ assertTrue("Result set has wrong size", values.isEmpty());
+ }
+}
diff --git a/sql/src/test/java/tests/java/sql/StressTest.java b/sql/src/test/java/tests/java/sql/StressTest.java
new file mode 100755
index 0000000..2f1b26b
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/StressTest.java
@@ -0,0 +1,382 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.java.sql;
+
+import dalvik.annotation.BrokenTest;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Properties;
+import java.util.Vector;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+import tests.support.ThreadPool;
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+@TestTargetClass(Statement.class)
+public class StressTest extends TestCase {
+ Vector vc = new Vector();
+
+ private static Connection conn;
+
+ private static Statement statement;
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(StressTest.class)) {
+
+ protected void setUp() throws Exception {
+ Support_SQL.loadDriver();
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ createTestTables();
+ }
+
+ protected void tearDown() throws Exception {
+ dropTestTables();
+ statement.close();
+ conn.close();
+ }
+
+ private void createTestTables() {
+ try {
+ DatabaseMetaData meta = conn.getMetaData();
+ ResultSet userTab = meta.getTables(null, null, null, null);
+
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE2)) {
+ statement.execute(DatabaseCreator.DROP_TABLE2);
+ }
+ }
+ statement.execute(DatabaseCreator.CREATE_TABLE2);
+ } catch (SQLException sql) {
+ fail("Unexpected SQLException " + sql.toString());
+ }
+ return;
+ }
+
+ private void dropTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE2);
+ } catch (SQLException sql) {
+ fail("Unexpected SQLException " + sql.toString());
+ }
+ return;
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * @see junit.framework.TestCase#setUp()
+ */
+ @Override
+ protected void setUp() throws Exception {
+ super.setUp();
+ vc.clear();
+ }
+
+ /**
+ * @see junit.framework.TestCase#tearDown()
+ */
+ @Override
+ protected void tearDown() throws Exception {
+ closeConnections();
+ statement.execute("DELETE FROM " + DatabaseCreator.TEST_TABLE2);
+ super.tearDown();
+ }
+
+ /**
+ * @tests StressTest#testManyConnectionsUsingOneThread(). Create many
+ * connections to the DataBase using one thread.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "connect",
+ clazz = Driver.class,
+ args = {String.class, Properties.class}
+ )
+ public void testManyConnectionsUsingOneThread() {
+ try {
+ int maxConnections = getConnectionNum();
+ openConnections(maxConnections);
+ assertEquals("Incorrect number of created connections",
+ maxConnections, vc.size());
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.toString());
+ }
+ }
+
+ /**
+ * @tests StressTest#testManyConnectionsUsingManyThreads(). Create many
+ * connections to the DataBase using some threads.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Stress test: Create many connections to the DataBase using some threads",
+ method = "connect",
+ clazz = Driver.class,
+ args = {String.class, Properties.class}
+ )
+ public void testManyConnectionsUsingManyThreads() {
+ int numTasks = getConnectionNum();
+
+ ThreadPool threadPool = new ThreadPool(numTasks);
+
+ // run example tasks
+ for (int i = 0; i < numTasks; i++) {
+ threadPool.runTask(createTask(i));
+ }
+ // close the pool and wait for all tasks to finish.
+ threadPool.join();
+ assertEquals("Unable to create a connection", numTasks, vc.size());
+ if (numTasks != Support_SQL.sqlMaxConnections) {
+ try {
+ // try to create connection n + 1
+ Connection c = Support_SQL.getConnection();
+ c.close();
+ fail("It is possible to create more than " + numTasks
+ + "connections");
+ } catch (SQLException sql) {
+ // expected
+ }
+ }
+ }
+
+ /**
+ * @tests StressTest#testInsertOfManyRowsUsingOneThread(). Insert a lot of
+ * records to the Database using a maximum number of connections.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "connect",
+ clazz = Driver.class,
+ args = {String.class, Properties.class}
+ )
+ public void testInsertOfManyRowsUsingOneThread() {
+
+ Logger.global
+ .info("java.sql stress test: single thread and many operations.");
+ int maxConnections = getConnectionNum();
+ Logger.global.info("Opening " + maxConnections + " to database "
+ + Support_SQL.getFilename());
+ openConnections(maxConnections);
+
+ int tasksPerConnection = Support_SQL.sqlMaxTasks / maxConnections;
+ Logger.global.info("TasksPerConnection = " + Support_SQL.sqlMaxTasks
+ + " by (maxConnections) " + maxConnections + " = "
+ + tasksPerConnection);
+ int pk = 1;
+ for (int i = 0; i < vc.size(); ++i) {
+ Logger.global.info(" creating " + tasksPerConnection
+ + "tasks for Connection " + i);
+ Connection c = vc.elementAt(i);
+ for (int j = 0; j < tasksPerConnection; ++j) {
+ insertNewRecord(c, pk++);
+ }
+ }
+ try {
+ ResultSet rs = statement
+ .executeQuery("SELECT COUNT(*) as counter FROM "
+ + DatabaseCreator.TEST_TABLE2);
+ assertTrue("RecordSet is empty", rs.next());
+ assertEquals("Incorrect number of records", tasksPerConnection
+ * maxConnections, rs.getInt("counter"));
+ rs.close();
+ } catch (SQLException sql) {
+ fail("Unexpected SQLException " + sql.toString());
+ }
+
+ }
+
+ /**
+ * @tests
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ method = "connect",
+ clazz = Driver.class,
+ args = {String.class, Properties.class}
+ )
+ @BrokenTest("Error in ThreadPool implementation threads do not get"
+ +" more tasks (only one): there seems to be a deadlock or something."
+ )
+ public void testInsertOfManyRowsUsingManyThreads() {
+ Logger.global.info("java.sql stress test: multiple threads and many operations.");
+
+ int numConnections = getConnectionNum();
+ int tasksPerConnection = Support_SQL.sqlMaxTasks / numConnections;
+
+ Logger.global.info("Opening "+numConnections+" to database "+Support_SQL.getFilename());
+
+ ThreadPool threadPool = new ThreadPool(numConnections);
+
+ for (int i = 0; i < numConnections; ++i) {
+ Logger.global.info(" creating "+tasksPerConnection+ " tasks for Connection "+i);
+ threadPool.runTask(insertTask(numConnections, i));
+ }
+ // close the pool and wait for all tasks to finish.
+ threadPool.join();
+ assertEquals("Unable to create a connection", numConnections, vc.size());
+
+ try {
+ ResultSet rs = statement
+ .executeQuery("SELECT COUNT(*) as counter FROM "
+ + DatabaseCreator.TEST_TABLE2);
+ assertTrue("RecordSet is empty", rs.next());
+
+
+ assertEquals("Incorrect number of records", tasksPerConnection
+ * numConnections, rs.getInt("counter"));
+ rs.close();
+ } catch (SQLException sql) {
+ fail("Unexpected SQLException " + sql.toString());
+
+ }
+
+ }
+
+ private int getConnectionNum() {
+ int num = Support_SQL.sqlMaxConnections;
+ try {
+ int mc = conn.getMetaData().getMaxConnections();
+ if (mc != 0) {
+ if (num != mc) {
+ System.err.println("Will be used no more than " + mc
+ + " connections to the DataBase");
+ }
+ num = mc;
+ }
+ } catch (SQLException sql) {
+ fail("Unexpected SQLException " + sql.toString());
+ }
+ return num;
+ }
+
+ private void openConnections(int maxConnections) {
+ int i = 0;
+ try {
+ for (; i < maxConnections; ++i) {
+ Connection c = Support_SQL.getConnection();
+ if (c == null) {
+ assertEquals("Unable to create a connection",
+ maxConnections, i);
+ }
+ vc.add(c);
+ }
+ } catch (SQLException sql) {
+ assertEquals("Unable to create a connection", maxConnections, i);
+ }
+ return;
+ }
+
+ private void closeConnections() {
+ int i = 0;
+ try {
+ for (; i < vc.size(); ++i) {
+ vc.elementAt(i).close();
+ }
+ } catch (SQLException sql) {
+ assertEquals("Unable to close a connection", vc.size(), i);
+ }
+ return;
+ }
+
+ private Runnable createTask(final int taskID) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Connection c = Support_SQL.getConnection();
+ if (c == null) {
+ return;
+ }
+ synchronized (this) {
+ vc.add(c);
+ }
+ } catch (SQLException sql) {
+ // nothing to do
+ }
+ }
+ };
+ }
+
+ private Runnable insertTask(final int numConnections, final int taskID) {
+ return new Runnable() {
+ public void run() {
+ try {
+ Connection c = Support_SQL.getConnection();
+ if (c == null) {
+ return;
+ }
+ synchronized (this) {
+ vc.add(c);
+ }
+ int tasksPerConnection = Support_SQL.sqlMaxTasks
+ / numConnections;
+ for (int i = 0; i < tasksPerConnection; ++i) {
+ insertNewRecord(c, (i + 1) + tasksPerConnection
+ * taskID);
+ }
+ } catch (SQLException sql) {
+ // do nothing
+ }
+ }
+ };
+ }
+
+ private void insertNewRecord(Connection c, int pk) {
+ String query = "INSERT INTO " + DatabaseCreator.TEST_TABLE2
+ + "(finteger, ftext, fcharacter, fdecimal, fnumeric,"
+ + " fsmallint, ffloat, freal, fdouble, fdate, ftime)"
+ + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";
+ try {
+ PreparedStatement ps = c.prepareStatement(query);
+ ps.setInt(1, pk);
+ ps.setString(2, "text");
+ ps.setString(3, "chr");
+ ps.setFloat(4, 0.1f);
+ ps.setFloat(5, 0.2f);
+ ps.setShort(6, (short) 3);
+ ps.setFloat(7, 0.4f);
+ ps.setDouble(8, 0.5);
+ ps.setDouble(9, 0.6);
+ ps.setDate(10, new java.sql.Date(System.currentTimeMillis()));
+ ps.setTime(11, new java.sql.Time(System.currentTimeMillis()));
+ ps.execute();
+ ps.close();
+ } catch (SQLException sql) {
+ fail("Unexpected SQLException " + sql.toString());
+ }
+ return;
+ }
+}
diff --git a/sql/src/test/java/tests/java/sql/UpdateFunctionalityTest.java b/sql/src/test/java/tests/java/sql/UpdateFunctionalityTest.java
new file mode 100755
index 0000000..2a94f08
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/UpdateFunctionalityTest.java
@@ -0,0 +1,483 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.java.sql;
+
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.math.BigDecimal;
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.HashSet;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+@TestTargetClass(Statement.class)
+public class UpdateFunctionalityTest extends TestCase {
+
+ private static final int numberOfRecords = 20;
+
+ private static Connection conn;
+
+ private static Statement statement;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ DatabaseCreator.fillTestTable1(conn, numberOfRecords);
+ DatabaseCreator.fillTestTable2(conn, numberOfRecords);
+ }
+
+ protected void tearDown() throws Exception {
+ String deleteQuery1 = "DELETE FROM " + DatabaseCreator.TEST_TABLE1;
+ String deleteQuery2 = "DELETE FROM " + DatabaseCreator.TEST_TABLE2;
+
+ statement.execute(deleteQuery1);
+ statement.execute(deleteQuery2);
+ super.tearDown();
+ }
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ UpdateFunctionalityTest.class)) {
+ protected void setUp() throws Exception {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ createTestTables();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ deleteTestTables();
+ statement.close();
+ conn.close();
+ }
+
+ private void createTestTables() {
+ try {
+ DatabaseMetaData meta = conn.getMetaData();
+ ResultSet userTab = meta.getTables(null, null, null, null);
+
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.TEST_TABLE1)) {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE2)) {
+ statement.execute(DatabaseCreator.DROP_TABLE2);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE3)) {
+ statement.execute(DatabaseCreator.DROP_TABLE3);
+ }
+ }
+ userTab.close();
+
+ statement.execute(DatabaseCreator.CREATE_TABLE3);
+ statement.execute(DatabaseCreator.CREATE_TABLE2);
+ statement.execute(DatabaseCreator.CREATE_TABLE1);
+
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ private void deleteTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE1);
+ statement.execute(DatabaseCreator.DROP_TABLE2);
+ statement.execute(DatabaseCreator.DROP_TABLE3);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest#testUpdate1(). Updates all values in one
+ * column in the table
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates all values in one column in the table",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates all values in one column in the table",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate1() {
+ String newValue = "newValue";
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field1='" + newValue + "'";
+ try {
+ int num = statement.executeUpdate(updateQuery);
+ assertEquals("Not all records in the database were updated",
+ numberOfRecords, num);
+ String selectQuery = "SELECT field1 FROM "
+ + DatabaseCreator.TEST_TABLE1;
+ ResultSet result = statement.executeQuery(selectQuery);
+ while (result.next()) {
+ assertEquals("The field field1 was not updated", newValue,
+ result.getString("field1"));
+ }
+ result.close();
+ } catch (SQLException e) {
+ fail("Unexpected exception" + e.getMessage());
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest#testUpdate2(). Updates values in one
+ * column in the table using where condition in update command
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates values in one column in the table using where condition in update command",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates values in one column in the table using where condition in update command",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate2() {
+ String newValue = "newValue";
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field1='" + newValue + "' WHERE (id > 2) and (id < 10)";
+ try {
+ int num = statement.executeUpdate(updateQuery);
+ int expectedUpdated = 7;
+ assertEquals("Not all records in the database were updated",
+ expectedUpdated, num);
+ String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1;
+ ResultSet result = statement.executeQuery(selectQuery);
+ while (result.next()) {
+ int id = result.getInt("id");
+ String field1 = result.getString("field1");
+ if ((id > 2) && (id < 10)) {
+ assertEquals("The field field1 was not updated", newValue,
+ field1);
+ } else {
+ assertEquals("The field field1 was not updated",
+ DatabaseCreator.defaultString + id, field1);
+ }
+ }
+ result.close();
+ } catch (SQLException e) {
+ fail("Unexpected exception" + e.getMessage());
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest#testUpdate3(). Updates values in a several
+ * columns in the table
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates values in a several columns in the table",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates values in a several columns in the table",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate3() {
+ int newValue1 = -1;
+ int newValue2 = -2;
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field2=" + newValue1 + ", field3=" + newValue2;
+ try {
+ int num = statement.executeUpdate(updateQuery);
+ assertEquals("Not all records in the database were updated",
+ numberOfRecords, num);
+ String selectQuery = "SELECT field2, field3 FROM "
+ + DatabaseCreator.TEST_TABLE1;
+ ResultSet result = statement.executeQuery(selectQuery);
+ while (result.next()) {
+ // TODO getBigDecimal is not supported
+// assertEquals("The field field2 was not updated", newValue1,
+// result.getBigDecimal("field2").intValue());
+// assertEquals("The field field3 was not updated", newValue2,
+// result.getBigDecimal("field3").intValue());
+ }
+ result.close();
+ } catch (SQLException e) {
+ fail("Unexpected exception" + e.getMessage());
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest#testUpdate4(). Updates values in a several
+ * columns in the table using where condition in update command
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates values in a several columns in the table using where condition in update command",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates values in a several columns in the table using where condition in update command",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate4() {
+ int newValue1 = -1;
+ int newValue2 = -2;
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field2=" + newValue1 + ", field3=" + newValue2
+ + " WHERE id > 10";
+ try {
+ int num = statement.executeUpdate(updateQuery);
+ int expectedUpdated = 9;
+ assertEquals("Not all records in the database were updated",
+ expectedUpdated, num);
+ String selectQuery = "SELECT id, field2, field3 FROM "
+ + DatabaseCreator.TEST_TABLE1;
+ ResultSet result = statement.executeQuery(selectQuery);
+ while (result.next()) {
+ int id = result.getInt("id");
+ // TODO getBigDecimal is not supported
+// int value2 = result.getBigDecimal("field2").intValue();
+// int value3 = result.getBigDecimal("field3").intValue();
+// if (id > expectedUpdated + 1) {
+// assertEquals("The field field2 was not updated", newValue1,
+// value2);
+// assertEquals("The field field3 was not updated", newValue2,
+// value3);
+// } else {
+// assertEquals("The field field2 was not updated", id, value2);
+// assertEquals("The field field3 was not updated", id, value3);
+// }
+ }
+ result.close();
+ } catch (SQLException e) {
+ fail("Unexpected exception" + e.getMessage());
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest#testUpdate5(). Updates values in one
+ * columns in the table using condition
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates values in one columns in the table using condition",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates values in one columns in the table using condition",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate5() {
+ int factor = 3;
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field2=field2 *" + factor;
+ try {
+ String selectQuery = "SELECT field2 FROM "
+ + DatabaseCreator.TEST_TABLE1;
+ ResultSet result = statement.executeQuery(selectQuery);
+ HashSet values = new HashSet();
+ // TODO getBigDecimal is not supported
+// while (result.next()) {
+// values.add(BigDecimal.valueOf(result.getBigDecimal("field2")
+// .intValue()
+// * factor));
+// }
+
+ int num = statement.executeUpdate(updateQuery);
+ assertEquals("Not all records in the database were updated",
+ numberOfRecords, num);
+ result = statement.executeQuery(selectQuery);
+ // TODO getBigDecimal is not supported
+// while (result.next()) {
+// BigDecimal value = result.getBigDecimal("field2");
+// assertTrue("Wrong value of field2 after update"
+// + value.intValue(), values.remove(value));
+// }
+ assertTrue("Not all records were updated", values.isEmpty());
+
+ result.close();
+ } catch (SQLException e) {
+ fail("Unexpected exception" + e.getMessage());
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest#testUpdate6(). Sets value of field2 to
+ * default
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Sets value of field2 to default",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Sets value of field2 to default",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate6() {
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field2='1'";
+ try {
+
+ int num = statement.executeUpdate(updateQuery);
+ assertEquals("Not all records in the database were updated",
+ numberOfRecords, num);
+ String selectQuery = "SELECT field2 FROM "
+ + DatabaseCreator.TEST_TABLE1;
+ ResultSet result = statement.executeQuery(selectQuery);
+ // TODO getBigDecimal is not supported
+// while (result.next()) {
+// assertEquals("value of field2 should be default ",
+// DatabaseCreator.defaultInt, result.getBigDecimal(
+// "field2").intValue());
+// }
+ result.close();
+ } catch (SQLException e) {
+ fail("Unexpected exception" + e.getMessage());
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest#testUpdate7(). Updates records in the
+ * table using subquery in update command
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates records in the table using subquery in update command",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates records in the table using subquery in update command",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate7() {
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field2='1' WHERE id < ( SELECT COUNT(*) FROM "
+ + DatabaseCreator.TEST_TABLE2 + " WHERE finteger > 15)";
+ try {
+ int num = statement.executeUpdate(updateQuery);
+ int expectedUpdated = 4;
+ assertEquals("Not all records in the database were updated",
+ expectedUpdated, num);
+ String selectQuery = "SELECT id, field2 FROM "
+ + DatabaseCreator.TEST_TABLE1;
+ ResultSet result = statement.executeQuery(selectQuery);
+ while (result.next()) {
+ // TODO getBigDecimal is not supported
+// int value = result.getBigDecimal("field2").intValue();
+// int id = result.getInt("id");
+// if (id < expectedUpdated) {
+// assertEquals("value of field2 should be default ",
+// DatabaseCreator.defaultInt, value);
+// } else {
+// assertEquals("wrong value of field2", id, value);
+// }
+ }
+ result.close();
+ } catch (SQLException e) {
+ fail("Unexpected exception" + e.getMessage());
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest#testUpdate8(). Sets value of field2 to
+ * NULL
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Sets value of field2 to NULL",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Sets value of field2 to NULL",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate8() {
+ String updateQuery = "UPDATE " + DatabaseCreator.TEST_TABLE1
+ + " SET field2=NULL";
+ try {
+
+ int num = statement.executeUpdate(updateQuery);
+ assertEquals("Not all records in the database were updated",
+ numberOfRecords, num);
+ String selectQuery = "SELECT field2 FROM "
+ + DatabaseCreator.TEST_TABLE1;
+ ResultSet result = statement.executeQuery(selectQuery);
+ while (result.next()) {
+ assertNull("value of field2 should be NULL", result
+ .getObject("field2"));
+ }
+ result.close();
+ } catch (SQLException e) {
+ fail("Unexpected exception" + e.getMessage());
+ }
+ }
+}
diff --git a/sql/src/test/java/tests/java/sql/UpdateFunctionalityTest2.java b/sql/src/test/java/tests/java/sql/UpdateFunctionalityTest2.java
new file mode 100755
index 0000000..f14bbfa
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/UpdateFunctionalityTest2.java
@@ -0,0 +1,387 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.java.sql;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import tests.support.DatabaseCreator;
+import tests.support.Support_SQL;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+@TestTargetClass(Statement.class)
+public class UpdateFunctionalityTest2 extends TestCase {
+
+ private static Connection conn = null;
+
+ private static Statement statement = null;
+
+ protected void setUp() throws Exception {
+ super.setUp();
+ DatabaseCreator.fillParentTable(conn);
+ DatabaseCreator.fillSimpleTable3(conn);
+ DatabaseCreator.fillSimpleTable1(conn);
+ }
+
+ protected void tearDown() throws Exception {
+ statement.execute("DELETE FROM " + DatabaseCreator.SIMPLE_TABLE3);
+ statement.execute("DELETE FROM " + DatabaseCreator.SIMPLE_TABLE1);
+ statement.execute("DELETE FROM " + DatabaseCreator.FKSTRICT_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.FKCASCADE_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.PARENT_TABLE);
+ statement.execute("DELETE FROM " + DatabaseCreator.TEST_TABLE5);
+ super.tearDown();
+ }
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ UpdateFunctionalityTest2.class)) {
+ protected void setUp() throws Exception {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ createTestTables();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ deleteTestTables();
+ statement.close();
+ conn.close();
+ }
+
+ private void createTestTables() {
+ try {
+ DatabaseMetaData meta = conn.getMetaData();
+ ResultSet userTab = meta.getTables(null, null, null, null);
+
+ while (userTab.next()) {
+ String tableName = userTab.getString("TABLE_NAME");
+ if (tableName.equals(DatabaseCreator.PARENT_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_PARENT);
+ } else if (tableName
+ .equals(DatabaseCreator.FKCASCADE_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_FKCASCADE);
+ } else if (tableName
+ .equals(DatabaseCreator.FKSTRICT_TABLE)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_FKSTRICT);
+ } else if (tableName
+ .equals(DatabaseCreator.SIMPLE_TABLE1)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_SIMPLE1);
+ } else if (tableName
+ .equals(DatabaseCreator.SIMPLE_TABLE3)) {
+ statement
+ .execute(DatabaseCreator.DROP_TABLE_SIMPLE3);
+ } else if (tableName
+ .equals(DatabaseCreator.TEST_TABLE5)) {
+ statement.execute(DatabaseCreator.DROP_TABLE5);
+ }
+ }
+ userTab.close();
+ statement.execute(DatabaseCreator.CREATE_TABLE_PARENT);
+ statement.execute(DatabaseCreator.CREATE_TABLE_FKSTRICT);
+ statement.execute(DatabaseCreator.CREATE_TABLE_FKCASCADE);
+ statement.execute(DatabaseCreator.CREATE_TABLE_SIMPLE3);
+ statement.execute(DatabaseCreator.CREATE_TABLE_SIMPLE1);
+ statement.execute(DatabaseCreator.CREATE_TABLE5);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ private void deleteTestTables() {
+ try {
+ statement.execute(DatabaseCreator.DROP_TABLE_FKCASCADE);
+ statement.execute(DatabaseCreator.DROP_TABLE_FKSTRICT);
+ statement.execute(DatabaseCreator.DROP_TABLE_PARENT);
+ statement.execute(DatabaseCreator.DROP_TABLE_SIMPLE3);
+ statement.execute(DatabaseCreator.DROP_TABLE_SIMPLE1);
+ statement.execute(DatabaseCreator.DROP_TABLE5);
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate1(). Updates row with no
+ * referencing ones and RESTRICT action
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates row with no referencing ones and RESTRICT action",
+ method = "execute",
+ args = {java.lang.String.class}
+ )
+ public void testUpdate1() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ statement.execute("UPDATE " + DatabaseCreator.PARENT_TABLE
+ + " SET id = 4 WHERE id = 3");
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate2(). Attempts to update row
+ * with referencing ones and RESTRICT action - expecting SQLException
+ *
+ * TODO not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Attempts to update row with referencing ones and RESTRICT action - expecting SQLException",
+ method = "execute",
+ args = {java.lang.String.class}
+ )
+ @KnownFailure("not supported")
+ public void testUpdate2() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ try {
+ statement.executeUpdate("UPDATE " + DatabaseCreator.PARENT_TABLE
+ + " SET id = 5 WHERE id = 1;");
+ fail("expecting SQLException");
+ } catch (SQLException ex) {
+ // expected
+
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate3(). Deletes all referencing
+ * rows and then updates referenced one
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Deletes all referencing rows and then updates referenced one",
+ method = "execute",
+ args = {java.lang.String.class}
+ )
+ public void testUpdate3() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ statement.execute("DELETE FROM " + DatabaseCreator.FKSTRICT_TABLE
+ + " WHERE name_id = 1;");
+ statement.execute("UPDATE " + DatabaseCreator.PARENT_TABLE
+ + " SET id = 5 WHERE id = 1;");
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate4(). Attempts to set incorrect
+ * foreign key value - expecting SQLException
+ *
+ * TODO foreign key functionality is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Attempts to set incorrect foreign key value - expecting SQLException",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ )
+ @KnownFailure("not supported")
+ public void testUpdate4() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ try {
+ statement.executeUpdate("UPDATE " + DatabaseCreator.FKSTRICT_TABLE
+ + " SET name_id = 6 WHERE name_id = 2");
+ fail("expecting SQLException");
+ } catch (SQLException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate5(). Updates row with
+ * referencing ones and CASCADE action - expecting that all
+ * referencing rows will also be updated
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates row with referencing ones and CASCADE action - expecting that all referencing rows will also be updated",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates row with referencing ones and CASCADE action - expecting that all referencing rows will also be updated",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate5() throws SQLException {
+ DatabaseCreator.fillFKCascadeTable(conn);
+ statement.executeUpdate("UPDATE " + DatabaseCreator.PARENT_TABLE
+ + " SET id = 5 WHERE id = 1;");
+
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) " + "FROM "
+ + DatabaseCreator.FKCASCADE_TABLE + " WHERE name_id = 1;");
+ r.next();
+ assertEquals("Should be 2 rows", 2, r.getInt(1));
+ r = statement.executeQuery("SELECT COUNT(*) " + "FROM "
+ + DatabaseCreator.FKCASCADE_TABLE + " WHERE name_id = 5;");
+ r.next();
+ assertEquals("Should be 0 rows", 0, r.getInt(1));
+ r.close();
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate6(). Attempts to set incorrect
+ * foreign key value to row with CASCADE action - expecting
+ * SQLException
+ *
+ * TODO Foreign key functionality is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Attempts to set incorrect\n" +
+ "foreign key value to row with CASCADE action - expecting SQLException: not supported",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ )
+ @KnownFailure("not supported")
+ public void testUpdate6() throws SQLException {
+ DatabaseCreator.fillFKCascadeTable(conn);
+ try {
+ statement.executeUpdate("UPDATE " + DatabaseCreator.FKCASCADE_TABLE
+ + " SET name_id = 6 WHERE name_id = 2");
+ fail("expecting SQLException");
+ } catch (SQLException ex) {
+ // expected
+ }
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate7(). Updates table using
+ * subquery in WHERE clause
+ *
+ * TODO Foreign key functionality is not supported
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates table using subquery in WHERE clause. Not supported: FK",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates table using subquery in WHERE clause. Not supported: FK.",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ )
+ })
+ @KnownFailure("not supported")
+ public void testUpdate7() throws SQLException {
+
+ DatabaseCreator.fillFKStrictTable(conn);
+ statement.executeUpdate("UPDATE " + DatabaseCreator.FKSTRICT_TABLE
+ + " SET value = 'updated' WHERE name_id = ANY (SELECT id FROM "
+ + DatabaseCreator.PARENT_TABLE + " WHERE id > 1)");
+ ResultSet r = statement.executeQuery("SELECT COUNT(*) FROM "
+ + DatabaseCreator.FKSTRICT_TABLE + " WHERE value = 'updated';");
+ r.next();
+ assertEquals("Should be 1 row", 1, r.getInt(1));
+ r.close();
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate8(). Updates table using scalar
+ * subquery as new field value
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates table using scalar subquery as new field value",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates table using scalar subquery as new field value",
+ method = "executeUpdate",
+ args = {java.lang.String.class}
+ )
+ })
+ public void testUpdate8() throws SQLException {
+ statement.executeUpdate("UPDATE " + DatabaseCreator.SIMPLE_TABLE3
+ + " SET speed = (SELECT MAX(speed) FROM "
+ + DatabaseCreator.SIMPLE_TABLE1
+ + ") WHERE id = (SELECT id FROM "
+ + DatabaseCreator.SIMPLE_TABLE1
+ + " WHERE speed = (SELECT MAX(speed) FROM "
+ + DatabaseCreator.SIMPLE_TABLE1 + "))");
+ ResultSet r = statement.executeQuery("SELECT id FROM "
+ + DatabaseCreator.SIMPLE_TABLE3
+ + " WHERE speed = (SELECT MAX(speed) FROM "
+ + DatabaseCreator.SIMPLE_TABLE1 + ");");
+ r.next();
+ assertEquals("Incorrect id updated", 1, r.getInt(1));
+ r.close();
+ }
+
+ /**
+ * @tests UpdateFunctionalityTest2#testUpdate9(). Updates table using
+ * PreparedStatement
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Functionality test: Updates table using PreparedStatement",
+ method = "executeQuery",
+ args = {java.lang.String.class}
+ )
+ public void testUpdate9() throws SQLException {
+ DatabaseCreator.fillTestTable5(conn);
+ PreparedStatement stat = conn.prepareStatement("UPDATE "
+ + DatabaseCreator.TEST_TABLE5
+ + " SET testValue = ? WHERE testID = ?");
+ stat.setString(1, "1");
+ stat.setInt(2, 1);
+ stat.execute();
+ stat.setString(1, "2");
+ stat.setInt(2, 2);
+ stat.execute();
+ ResultSet r = statement.executeQuery("SELECT testId, testValue FROM "
+ + DatabaseCreator.TEST_TABLE5
+ + " WHERE testID < 3 ORDER BY testID");
+ while (r.next()) {
+ assertEquals("Incorrect value was returned", new Integer(r
+ .getInt(1)).toString(), r.getString(2));
+ }
+ r.close();
+ stat.close();
+ }
+}
diff --git a/sql/src/test/java/tests/javax/sql/ConnectionEventListenerTest.java b/sql/src/test/java/tests/javax/sql/ConnectionEventListenerTest.java
new file mode 100644
index 0000000..a89b026
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/ConnectionEventListenerTest.java
@@ -0,0 +1,42 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import javax.sql.ConnectionEvent;
+import javax.sql.ConnectionEventListener;
+
+@TestTargetClass(ConnectionEventListener.class)
+public class ConnectionEventListenerTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.ConnectionEventListener#connectionClosed(javax.sql.ConnectionEvent)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "connectionClosed",
+ args = {javax.sql.ConnectionEvent.class}
+ )
+ public void testConnectionClosed() {
+ fail("Not yet implemented"); // TODO
+ }
+
+ /**
+ * @test {@link javax.sql.ConnectionEventListener#connectionErrorOccurred(ConnectionEvent)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "connectionErrorOccurred",
+ args = {javax.sql.ConnectionEvent.class}
+ )
+ public void testConnectionErrorOccurred() {
+ fail("Not yet implemented"); // TODO
+ }
+
+}
diff --git a/sql/src/test/java/tests/javax/sql/ConnectionPoolDataSourceTest.java b/sql/src/test/java/tests/javax/sql/ConnectionPoolDataSourceTest.java
new file mode 100644
index 0000000..7dafc46
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/ConnectionPoolDataSourceTest.java
@@ -0,0 +1,96 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import java.io.PrintWriter;
+
+import javax.sql.ConnectionPoolDataSource;
+
+
+@TestTargetClass(ConnectionPoolDataSource.class)
+public class ConnectionPoolDataSourceTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.ConnectionPoolDataSource#getLoginTimeout()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getLoginTimeout",
+ args = {}
+ )
+ public void testGetLoginTimeout() {
+ fail("Not yet implemented"); // NOT_FEASIBLE
+ }
+
+ /**
+ * @tests {@link javax.sql.ConnectionPoolDataSource#getLogWriter()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getLogWriter",
+ args = {}
+ )
+ public void testGetLogWriter() {
+ fail("Not yet implemented"); // NOT_FEASIBLE
+ }
+
+ /**
+ * @tests {@link javax.sql.ConnectionPoolDataSource#getPooledConnection()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getPooledConnection",
+ args = {}
+ )
+ public void testGetPooledConnection() {
+ fail("Not yet implemented"); // NOT_FEASIBLE
+ }
+
+ /**
+ * @tests {@link javax.sql.ConnectionPoolDataSource#getPooledConnection(String, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getPooledConnection",
+ args = {String.class, String.class}
+ )
+ public void testGetPooledConnectionStringString() {
+ fail("Not yet implemented"); // NOT_FEASIBLE
+ }
+
+ /**
+ * @tests {@link javax.sql.ConnectionPoolDataSource#setLoginTimeout(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setLoginTimeout",
+ args = {int.class}
+ )
+ public void testSetLoginTimeout() {
+ fail("Not yet implemented"); // NOT_FEASIBLE
+ }
+
+ /**
+ * @tests {@link javax.sql.ConnectionPoolDataSource#setLogWriter(java.io.PrintWriter)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setLogWriter",
+ args = {java.io.PrintWriter.class}
+ )
+ public void testSetLogWriter() {
+ fail("Not yet implemented"); // NOT_FEASIBLE
+ }
+
+}
diff --git a/sql/src/test/java/tests/javax/sql/DataSourceTest.java b/sql/src/test/java/tests/javax/sql/DataSourceTest.java
new file mode 100644
index 0000000..8aeb666
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/DataSourceTest.java
@@ -0,0 +1,96 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import java.io.PrintWriter;
+
+import javax.sql.DataSource;
+
+@TestTargetClass(DataSource.class)
+public class DataSourceTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.DataSource#getConnection()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getConnection",
+ args = {}
+ )
+ public void testGetConnection() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.DataSource#getConnection(String, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getConnection",
+ args = {java.lang.String.class, java.lang.String.class}
+ )
+ public void testGetConnectionStringString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.DataSource#getLoginTimeout()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getLoginTimeout",
+ args = {}
+ )
+ public void testGetLoginTimeout() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.DataSource#getLogWriter()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getLogWriter",
+ args = {}
+ )
+ public void testGetLogWriter() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.DataSource#setLoginTimeout(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setLoginTimeout",
+ args = {int.class}
+ )
+ public void testSetLoginTimeout() {
+ fail("Not yet implemented");
+ }
+
+
+ /**
+ * @tests {@link javax.sql.DataSource#setLogWriter(java.io.PrintWriter)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setLogWriter",
+ args = {PrintWriter.class}
+ )
+ public void testSetLogWriter() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/javax/sql/PooledConnectionTest.java b/sql/src/test/java/tests/javax/sql/PooledConnectionTest.java
new file mode 100644
index 0000000..4eb09fb
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/PooledConnectionTest.java
@@ -0,0 +1,68 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import javax.sql.ConnectionEventListener;
+import javax.sql.PooledConnection;
+
+@TestTargetClass(PooledConnection.class)
+public class PooledConnectionTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.PooledConnection#addConnectionEventListener(javax.sql.ConnectionEventListener)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "addConnectionEventListener",
+ args = {javax.sql.ConnectionEventListener.class}
+ )
+ public void testAddConnectionEventListener() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.PooledConnection#close()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "close",
+ args = {}
+ )
+ public void testClose() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.PooledConnection#getConnection()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getConnection",
+ args = {}
+ )
+ public void testGetConnection() {
+ fail("Not yet implemented");
+ }
+
+
+ /**
+ * @tests {@link javax.sql.PooledConnection#removeConnectionEventListener(ConnectionEventListener)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "removeConnectionEventListener",
+ args = {javax.sql.ConnectionEventListener.class}
+ )
+ public void testRemoveConnectionEventListener() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/javax/sql/RowSetInternalTest.java b/sql/src/test/java/tests/javax/sql/RowSetInternalTest.java
new file mode 100644
index 0000000..ff9de34
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/RowSetInternalTest.java
@@ -0,0 +1,78 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import javax.sql.RowSetInternal;
+import javax.sql.RowSetMetaData;
+
+@TestTargetClass(RowSetInternal.class)
+public class RowSetInternalTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.RowSetInternal#getConnection()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getConnection",
+ args = {}
+ )
+ public void testGetConnection() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetInternal#getOriginal()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getOriginal",
+ args = {}
+ )
+ public void testGetOriginal() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetInternal#getOriginalRow()}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getOriginalRow",
+ args = {}
+ )
+ public void testGetOriginalRow() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getParams",
+ args = {}
+ )
+ public void testGetParams() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetInternal#setMetaData(javax.sql.RowSetMetaData)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setMetaData",
+ args = {javax.sql.RowSetMetaData.class}
+ )
+ public void testSetMetaData() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/javax/sql/RowSetListenerTest.java b/sql/src/test/java/tests/javax/sql/RowSetListenerTest.java
new file mode 100644
index 0000000..d238a42
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/RowSetListenerTest.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import javax.sql.RowSetEvent;
+import javax.sql.RowSetListener;
+
+/**
+ *
+ */
+@TestTargetClass(RowSetListener.class)
+public class RowSetListenerTest extends TestCase {
+
+ /**
+ * Test method for {@link javax.sql.RowSetListener#cursorMoved(javax.sql.RowSetEvent)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "cursorMoved",
+ args = {javax.sql.RowSetEvent.class}
+ )
+ public void testCursorMoved() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link javax.sql.RowSetListener#rowChanged(javax.sql.RowSetEvent)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "rowChanged",
+ args = {javax.sql.RowSetEvent.class}
+ )
+ public void testRowChanged() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link javax.sql.RowSetListener#rowSetChanged(javax.sql.RowSetEvent)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "rowSetChanged",
+ args = {javax.sql.RowSetEvent.class}
+ )
+ public void testRowSetChanged() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/javax/sql/RowSetMetaDataTest.java b/sql/src/test/java/tests/javax/sql/RowSetMetaDataTest.java
new file mode 100644
index 0000000..0a3db18
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/RowSetMetaDataTest.java
@@ -0,0 +1,241 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import javax.sql.RowSetMetaData;
+
+/**
+ * @author AGR
+ *
+ */
+@TestTargetClass(RowSetMetaData.class)
+public class RowSetMetaDataTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setAutoIncrement(int, boolean)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setAutoIncrement",
+ args = {int.class, boolean.class}
+ )
+ public void testSetAutoIncrement() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setCaseSensitive(int, boolean)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setCaseSensitive",
+ args = {int.class, boolean.class}
+ )
+ public void testSetCaseSensitive() {
+ fail("Not yet implemented");
+ }
+
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setCatalogName(int, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setCatalogName",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetCatalogName() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setColumnCount(int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setColumnCount",
+ args = {int.class}
+ )
+ public void testSetColumnCount() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setColumnDisplaySize(int, int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setColumnDisplaySize",
+ args = {int.class, int.class}
+ )
+ public void testSetColumnDisplaySize() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setColumnLabel(int, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setColumnLabel",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetColumnLabel() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setColumnName(int, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setColumnName",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetColumnName() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setColumnType(int, int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setColumnType",
+ args = {int.class, int.class}
+ )
+ public void testSetColumnType() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setColumnTypeName(int, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setColumnTypeName",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetColumnTypeName() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setCurrency(int, boolean)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setCurrency",
+ args = {int.class, boolean.class}
+ )
+ public void testSetCurrency() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setNullable(int, int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setNullable",
+ args = {int.class, int.class}
+ )
+ public void testSetNullable() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setPrecision(int, int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setPrecision",
+ args = {int.class, int.class}
+ )
+ public void testSetPrecision() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setScale(int, int)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setScale",
+ args = {int.class, int.class}
+ )
+ public void testSetScale() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setSchemaName(int, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setSchemaName",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetSchemaName() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setSearchable(int, boolean)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setSearchable",
+ args = {int.class, boolean.class}
+ )
+ public void testSetSearchable() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setSigned(int, boolean)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setSigned",
+ args = {int.class, boolean.class}
+ )
+ public void testSetSigned() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSetMetaData#setTableName(int, String)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTableName",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetTableName() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/javax/sql/RowSetReaderTest.java b/sql/src/test/java/tests/javax/sql/RowSetReaderTest.java
new file mode 100644
index 0000000..0a24234
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/RowSetReaderTest.java
@@ -0,0 +1,29 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import javax.sql.RowSetInternal;
+import javax.sql.RowSetReader;
+
+@TestTargetClass(RowSetReader.class)
+public class RowSetReaderTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.RowSetReader#readData(RowSetInternal)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "readData",
+ args = {javax.sql.RowSetInternal.class}
+ )
+ public void testReadData() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/javax/sql/RowSetTest.java b/sql/src/test/java/tests/javax/sql/RowSetTest.java
new file mode 100644
index 0000000..3dc2ba7
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/RowSetTest.java
@@ -0,0 +1,624 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.Ref;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+
+import javax.sql.RowSet;
+import javax.sql.RowSetListener;
+
+/**
+ *No Implementation class of this interface is available: tests not feasible
+ */
+@TestTargetClass(RowSet.class)
+public class RowSetTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.RowSet#addRowSetListener(javax.sql.RowSetListener)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "addRowSetListener",
+ args = {javax.sql.RowSetListener.class}
+ )
+ public void testAddRowSetListener() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSet#clearParameters()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "clearParameters",
+ args = {}
+ )
+ public void testClearParameters() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSet#addRowSetListener(javax.sql.RowSetListener)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "execute",
+ args = {}
+ )
+ public void testExecute() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSet#getCommand()}.
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setCommand",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getCommand",
+ args = {}
+ )
+ })
+ public void testSetGetCommand() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * @tests {@link javax.sql.RowSet#getDataSourceName()}.
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setDataSourceName",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getDataSourceName",
+ args = {}
+ )
+ })
+ public void testSetGetDataSourceName() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getEscapeProcessing",
+ args = {}
+ )
+ public void testSetGetEscapeProcessing() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getMaxFieldSize",
+ args = {}
+ )
+ public void testSetGetMaxFieldSize() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getMaxRows",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setMaxRows",
+ args = {int.class}
+ )
+ })
+ public void testSetGetMaxRows() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getPassword",
+ args = {}
+ )
+ public void testSetGetPassword() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getQueryTimeout",
+ args = {}
+ )
+ public void testSetGetQueryTimeout() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTransactionIsolation",
+ args = {}
+ )
+ public void testSetGetTransactionIsolation() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTypeMap",
+ args = {}
+ )
+ public void testSetGetTypeMap() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setUrl",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getUrl",
+ args = {}
+ )
+ })
+ public void testSetGetUrl() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setUsername",
+ args = {java.lang.String.class}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getUsername",
+ args = {}
+ )
+ })
+ public void testSetGetUsername() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "isReadOnly",
+ args = {}
+ )
+ public void testIsReadOnly() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "removeRowSetListener",
+ args = {javax.sql.RowSetListener.class}
+ )
+ public void testRemoveRowSetListener() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setArray",
+ args = {int.class, java.sql.Array.class}
+ )
+ public void testSetArray() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setAsciiStream",
+ args = {int.class, java.io.InputStream.class, int.class}
+ )
+ public void testSetGetAsciiStream() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBigDecimal",
+ args = {int.class, java.math.BigDecimal.class}
+ )
+ public void testSetGetBigDecimal() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBinaryStream",
+ args = {int.class, java.io.InputStream.class, int.class}
+ )
+ public void testSetGetBinaryStream() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBlob",
+ args = {int.class, java.sql.Blob.class}
+ )
+ public void testSetGetBlob() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBoolean",
+ args = {int.class, boolean.class}
+ )
+ public void testSetGetBoolean() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setByte",
+ args = {int.class, byte.class}
+ )
+ public void testSetGetByte() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBytes",
+ args = {int.class, byte[].class}
+ )
+ public void testSetGetBytes() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setCharacterStream",
+ args = {int.class, java.io.Reader.class, int.class}
+ )
+ public void testSetGetCharacterStream() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setClob",
+ args = {int.class, java.sql.Clob.class}
+ )
+ public void testSetGetClob() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setConcurrency",
+ args = {int.class}
+ )
+ public void testSetGetConcurrency() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setDate",
+ args = {int.class, java.sql.Date.class}
+ )
+ public void testSetGetDateIntDate() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setDate",
+ args = {int.class, java.sql.Date.class, java.util.Calendar.class}
+ )
+ public void testSetDateIntDateCalendar() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setEscapeProcessing",
+ args = {boolean.class}
+ )
+ public void testSetEscapeProcessing() {
+
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setDouble",
+ args = {int.class, double.class}
+ )
+ public void testSetGetDouble() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setFloat",
+ args = {int.class, float.class}
+ )
+ public void testSetGetFloat() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setInt",
+ args = {int.class, int.class}
+ )
+ public void testSetGetInt() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setLong",
+ args = {int.class, long.class}
+ )
+ public void testSetGetLong() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getMaxFieldSize",
+ args = {}
+ ),
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setMaxFieldSize",
+ args = {int.class}
+ )
+ })
+ public void testSetGetGetMaxFieldSize() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setNull",
+ args = {int.class, int.class}
+ )
+ public void testSetGetNullIntInt() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setNull",
+ args = {int.class, int.class, java.lang.String.class}
+ )
+ public void testSetGetNullIntIntString() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setObject",
+ args = {int.class, java.lang.Object.class}
+ )
+ public void testSetGetObjectIntObject() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setObject",
+ args = {int.class, java.lang.Object.class, int.class}
+ )
+ public void testSetGetObjectIntObjectInt() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setObject",
+ args = {int.class, java.lang.Object.class, int.class, int.class}
+ )
+ public void testSetGetObjectIntObjectIntInt() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setPassword",
+ args = {java.lang.String.class}
+ )
+ public void testSetPassword() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setQueryTimeout",
+ args = {int.class}
+ )
+ public void testSetQueryTimeout() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setReadOnly",
+ args = {boolean.class}
+ )
+ public void testSetReadOnly() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setRef",
+ args = {int.class, java.sql.Ref.class}
+ )
+ public void testSetRef() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setShort",
+ args = {int.class, short.class}
+ )
+ public void testSetShort() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setString",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetString() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTime",
+ args = {int.class, java.sql.Time.class}
+ )
+ public void testSetTimeIntTime() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTime",
+ args = {int.class, java.sql.Time.class, java.util.Calendar.class}
+ )
+ public void testSetTimeIntTimeCalendar() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTimestamp",
+ args = {int.class, java.sql.Timestamp.class}
+ )
+ public void testSetTimestampIntTimestamp() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTimestamp",
+ args = {int.class, java.sql.Timestamp.class, java.util.Calendar.class}
+ )
+ public void testSetTimestampIntTimestampCalendar() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTransactionIsolation",
+ args = {int.class}
+ )
+ public void testSetTransactionIsolation() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setType",
+ args = {int.class}
+ )
+ public void testSetType() {
+ fail("Not yet implemented");
+ }
+
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTypeMap",
+ args = {java.util.Map.class}
+ )
+ public void testSetTypeMap() {
+ fail("Not yet implemented");
+ }
+}
diff --git a/sql/src/test/java/tests/javax/sql/RowSetWriterTest.java b/sql/src/test/java/tests/javax/sql/RowSetWriterTest.java
new file mode 100644
index 0000000..1b9f972
--- /dev/null
+++ b/sql/src/test/java/tests/javax/sql/RowSetWriterTest.java
@@ -0,0 +1,29 @@
+package tests.javax.sql;
+
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import junit.framework.TestCase;
+
+import javax.sql.RowSetInternal;
+import javax.sql.RowSetWriter;
+
+@TestTargetClass(RowSetWriter.class)
+public class RowSetWriterTest extends TestCase {
+
+ /**
+ * @tests {@link javax.sql.RowSetWriter#writeData(javax.sql.RowSetInternal)}
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "writeData",
+ args = {javax.sql.RowSetInternal.class}
+ )
+ public void testWriteData() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/sql/AllTests.java b/sql/src/test/java/tests/sql/AllTests.java
new file mode 100644
index 0000000..7693d2d
--- /dev/null
+++ b/sql/src/test/java/tests/sql/AllTests.java
@@ -0,0 +1,48 @@
+/* Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.
+ */
+
+package tests.sql;
+
+import junit.framework.Test;
+import junit.framework.TestSuite;
+
+/**
+ * Test suite that includes all tests for the Math project.
+ */
+public class AllTests {
+
+ public static void main(String[] args) {
+ junit.textui.TestRunner.run(AllTests.suite());
+ }
+
+ public static Test suite() {
+ TestSuite suite = tests.TestSuiteFactory.createTestSuite("All SQL test suites");
+ // $JUnit-BEGIN$
+ suite.addTest(org.apache.harmony.sql.tests.java.sql.AllTests.suite());
+ suite.addTest(org.apache.harmony.sql.tests.javax.sql.AllTests.suite());
+ suite.addTest(tests.java.sql.AllTests.suite());
+ suite.addTest(tests.SQLite.AllTests.suite());
+
+ suite.addTestSuite(tests.sql.ConnectionTest.class);
+ suite.addTestSuite(tests.sql.PreparedStatementTest.class);
+ suite.addTestSuite(tests.sql.ResultSetGetterTests.class);
+ suite.addTestSuite(tests.sql.ResultSetMetaDataTest.class);
+ suite.addTestSuite(tests.sql.ResultSetTest.class);
+ suite.addTestSuite(tests.sql.StatementTest.class);
+ // $JUnit-END$
+ return suite;
+ }
+}
diff --git a/sql/src/test/java/tests/sql/ArrayTest.java b/sql/src/test/java/tests/sql/ArrayTest.java
new file mode 100644
index 0000000..f3b49d6
--- /dev/null
+++ b/sql/src/test/java/tests/sql/ArrayTest.java
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.sql;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import java.sql.Array;
+import java.util.Map;
+
+/**
+ * @author andrea@google.com (Your Name Here)
+ *
+ */
+@TestTargetClass(Array.class)
+public class ArrayTest extends TestCase {
+
+ /**
+ * Test method for {@link java.sql.Array#getArray()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getArray",
+ args = {}
+ )
+ public void testGetArray() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getArray(long, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getArray",
+ args = {long.class, int.class}
+ )
+ public void testGetArrayLongInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getArray(long, int, java.util.Map)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getArray",
+ args = {long.class, int.class, Map.class}
+ )
+ public void testGetArrayLongIntMapOfStringClassOfQ() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getArray(java.util.Map)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getArray",
+ args = {Map.class}
+ )
+ public void testGetArrayMapOfStringClassOfQ() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getBaseType()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBaseType",
+ args = {}
+ )
+ public void testGetBaseType() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getBaseTypeName()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBaseTypeName",
+ args = {}
+ )
+ public void testGetBaseTypeName() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getResultSet()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getResultSet",
+ args = {}
+ )
+ public void testGetResultSet() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getResultSet(long, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getResultSet",
+ args = {long.class, int.class}
+ )
+ public void testGetResultSetLongInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getResultSet(long, int, java.util.Map)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getResultSet",
+ args = {long.class, int.class, Map.class}
+ )
+ public void testGetResultSetLongIntMapOfStringClassOfQ() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Array#getResultSet(java.util.Map)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getResultSet",
+ args = {Map.class}
+ )
+ public void testGetResultSetMapOfStringClassOfQ() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/sql/BlobTest.java b/sql/src/test/java/tests/sql/BlobTest.java
new file mode 100644
index 0000000..43fb2a6
--- /dev/null
+++ b/sql/src/test/java/tests/sql/BlobTest.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.sql;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import java.sql.Blob;
+
+/**
+ * @author andrea@google.com (Your Name Here)
+ *
+ */
+@TestTargetClass(Blob.class)
+public class BlobTest extends TestCase {
+
+ /**
+ * Test method for {@link java.sql.Blob#getBinaryStream()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBinaryStream",
+ args = {}
+ )
+ public void testGetBinaryStream() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Blob#getBytes(long, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBytes",
+ args = {long.class, int.class}
+ )
+ public void testGetBytes() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Blob#length()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "length",
+ args = {}
+ )
+ public void testLength() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Blob#position(java.sql.Blob, long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "position",
+ args = {Blob.class, long.class}
+ )
+ public void testPositionBlobLong() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Blob#position(byte[], long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "position",
+ args = {byte[].class, long.class}
+ )
+ public void testPositionByteArrayLong() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Blob#setBinaryStream(long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBinaryStream",
+ args = {long.class}
+ )
+ public void testSetBinaryStream() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Blob#setBytes(long, byte[])}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBytes",
+ args = {long.class, byte[].class}
+ )
+ public void testSetBytesLongByteArray() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Blob#setBytes(long, byte[], int, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBytes",
+ args = {long.class, byte[].class, int.class, int.class}
+ )
+ public void testSetBytesLongByteArrayIntInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Blob#truncate(long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "truncate",
+ args = {long.class}
+ )
+ public void testTruncate() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/sql/CallableStatementTest.java b/sql/src/test/java/tests/sql/CallableStatementTest.java
new file mode 100644
index 0000000..db7aca1
--- /dev/null
+++ b/sql/src/test/java/tests/sql/CallableStatementTest.java
@@ -0,0 +1,1070 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.sql;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import java.io.InputStream;
+import java.io.Reader;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.CallableStatement;
+import java.sql.Date;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.util.Calendar;
+import java.util.Map;
+
+/**
+ * @author andrea@google.com (Your Name Here)
+ *
+ */
+@TestTargetClass(CallableStatement.class)
+public class CallableStatementTest extends TestCase {
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getArray(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getArray",
+ args = {int.class}
+ )
+ public void testGetArrayInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getArray(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getArray",
+ args = {String.class}
+ )
+ public void testGetArrayString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBigDecimal(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBigDecimal",
+ args = {int.class}
+ )
+ public void testGetBigDecimalInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBigDecimal(int, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBigDecimal",
+ args = {int.class, int.class}
+ )
+ public void testGetBigDecimalIntInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBigDecimal(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBigDecimal",
+ args = {String.class}
+ )
+ public void testGetBigDecimalString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBlob(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBlob",
+ args = {int.class}
+ )
+ public void testGetBlobInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBlob(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBlob",
+ args = {String.class}
+ )
+ public void testGetBlobString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBoolean(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBoolean",
+ args = {int.class}
+ )
+ public void testGetBooleanInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBoolean(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBoolean",
+ args = {String.class}
+ )
+ public void testGetBooleanString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getByte(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getByte",
+ args = {int.class}
+ )
+ public void testGetByteInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getByte(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getByte",
+ args = {String.class}
+ )
+ public void testGetByteString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBytes(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBytes",
+ args = {int.class}
+ )
+ public void testGetBytesInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getBytes(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBytes",
+ args = {String.class}
+ )
+ public void testGetBytesString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getClob(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getClob",
+ args = {int.class}
+ )
+ public void testGetClobInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getClob(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getClob",
+ args = {String.class}
+ )
+ public void testGetClobString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getDate(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getDate",
+ args = {int.class}
+ )
+ public void testGetDateInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getDate(int, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getDate",
+ args = {int.class, Calendar.class}
+ )
+ public void testGetDateIntCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getDate(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getDate",
+ args = {String.class}
+ )
+ public void testGetDateString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getDate(java.lang.String, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getDate",
+ args = {String.class, Calendar.class}
+ )
+ public void testGetDateStringCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getDouble(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getDouble",
+ args = {int.class}
+ )
+ public void testGetDoubleInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getDouble(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getDouble",
+ args = {String.class}
+ )
+ public void testGetDoubleString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getFloat(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getFloat",
+ args = {int.class}
+ )
+ public void testGetFloatInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getFloat(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getFloat",
+ args = {String.class}
+ )
+ public void testGetFloatString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getInt(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getInt",
+ args = {int.class}
+ )
+ public void testGetIntInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getInt(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getInt",
+ args = {String.class}
+ )
+ public void testGetIntString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getLong(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getLong",
+ args = {int.class}
+ )
+ public void testGetLongInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getLong(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getLong",
+ args = {String.class}
+ )
+ public void testGetLongString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getObject(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getObject",
+ args = {int.class}
+ )
+ public void testGetObjectInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getObject(int, java.util.Map)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getObject",
+ args = {int.class, Map.class}
+ )
+ public void testGetObjectIntMapOfStringClassOfQ() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getObject(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getObject",
+ args = {String.class}
+ )
+ public void testGetObjectString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getObject(java.lang.String, java.util.Map)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getObject",
+ args = {String.class, Map.class}
+ )
+ public void testGetObjectStringMapOfStringClassOfQ() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getRef(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getRef",
+ args = {int.class}
+ )
+ public void testGetRefInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getRef(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getRef",
+ args = {String.class}
+ )
+ public void testGetRefString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getShort(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getShort",
+ args = {int.class}
+ )
+ public void testGetShortInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getShort(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getShort",
+ args = {String.class}
+ )
+ public void testGetShortString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getString(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getString",
+ args = {int.class}
+ )
+ public void testGetStringInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getString(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getString",
+ args = {String.class}
+ )
+ public void testGetStringString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getTime(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTime",
+ args = {int.class}
+ )
+ public void testGetTimeInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getTime(int, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTime",
+ args = {int.class, Calendar.class}
+ )
+ public void testGetTimeIntCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getTime(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTime",
+ args = {String.class}
+ )
+ public void testGetTimeString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getTime(java.lang.String, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTime",
+ args = {String.class, Calendar.class}
+ )
+ public void testGetTimeStringCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getTimestamp(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTimestamp",
+ args = {int.class}
+ )
+ public void testGetTimestampInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getTimestamp(int, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTimestamp",
+ args = {int.class, Calendar.class}
+ )
+ public void testGetTimestampIntCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getTimestamp(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTimestamp",
+ args = {String.class}
+ )
+ public void testGetTimestampString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getTimestamp(java.lang.String, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getTimestamp",
+ args = {String.class, Calendar.class}
+ )
+ public void testGetTimestampStringCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getURL(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getURL",
+ args = {int.class}
+ )
+ public void testGetURLInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#getURL(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getURL",
+ args = {String.class}
+ )
+ public void testGetURLString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#registerOutParameter(int, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "registerOutParameter",
+ args = {int.class, int.class}
+ )
+ public void testRegisterOutParameterIntInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#registerOutParameter(int, int, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "registerOutParameter",
+ args = {int.class, int.class, int.class}
+ )
+ public void testRegisterOutParameterIntIntInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#registerOutParameter(int, int, java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "registerOutParameter",
+ args = {int.class, int.class, String.class}
+ )
+ public void testRegisterOutParameterIntIntString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#registerOutParameter(java.lang.String, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "registerOutParameter",
+ args = {String.class, int.class}
+ )
+ public void testRegisterOutParameterStringInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#registerOutParameter(java.lang.String, int, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "registerOutParameter",
+ args = {String.class, int.class, int.class}
+ )
+ public void testRegisterOutParameterStringIntInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#registerOutParameter(java.lang.String, int, java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "registerOutParameter",
+ args = {String.class, int.class, String.class}
+ )
+ public void testRegisterOutParameterStringIntString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setAsciiStream(java.lang.String, java.io.InputStream, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setAsciiStream",
+ args = {String.class, InputStream.class, int.class}
+ )
+ public void testSetAsciiStreamStringInputStreamInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setBigDecimal(java.lang.String, java.math.BigDecimal)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBigDecimal",
+ args = {String.class, BigDecimal.class}
+ )
+ public void testSetBigDecimalStringBigDecimal() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setBinaryStream(java.lang.String, java.io.InputStream, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBinaryStream",
+ args = {String.class, InputStream.class, int.class}
+ )
+ public void testSetBinaryStreamStringInputStreamInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setBoolean(java.lang.String, boolean)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBoolean",
+ args = {String.class, boolean.class}
+ )
+ public void testSetBooleanStringBoolean() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setByte(java.lang.String, byte)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setByte",
+ args = {String.class, byte.class}
+ )
+ public void testSetByteStringByte() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setBytes(java.lang.String, byte[])}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setBytes",
+ args = {String.class, byte[].class}
+ )
+ public void testSetBytesStringByteArray() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setCharacterStream(java.lang.String, java.io.Reader, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setCharacterStream",
+ args = {String.class, Reader.class, int.class}
+ )
+ public void testSetCharacterStreamStringReaderInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setDate(java.lang.String, java.sql.Date)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setDate",
+ args = {String.class, Date.class}
+ )
+ public void testSetDateStringDate() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setDate(java.lang.String, java.sql.Date, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setDate",
+ args = {String.class, Date.class, Calendar.class}
+ )
+ public void testSetDateStringDateCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setDouble(java.lang.String, double)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setDouble",
+ args = {String.class, double.class}
+ )
+ public void testSetDoubleStringDouble() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setFloat(java.lang.String, float)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setFloat",
+ args = {String.class, float.class}
+ )
+ public void testSetFloatStringFloat() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setInt(java.lang.String, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setInt",
+ args = {String.class, int.class}
+ )
+ public void testSetIntStringInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setLong(java.lang.String, long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setLong",
+ args = {String.class, long.class}
+ )
+ public void testSetLongStringLong() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setNull(java.lang.String, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setNull",
+ args = {String.class, int.class}
+ )
+ public void testSetNullStringInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setNull(java.lang.String, int, java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setNull",
+ args = {String.class, int.class, String.class}
+ )
+ public void testSetNullStringIntString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setObject(java.lang.String, java.lang.Object)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setObject",
+ args = {String.class, Object.class}
+ )
+ public void testSetObjectStringObject() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setObject(java.lang.String, java.lang.Object, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setObject",
+ args = {String.class, Object.class, int.class}
+ )
+ public void testSetObjectStringObjectInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setObject(java.lang.String, java.lang.Object, int, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setObject",
+ args = {String.class, Object.class, int.class, int.class}
+ )
+ public void testSetObjectStringObjectIntInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setShort(java.lang.String, short)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setShort",
+ args = {String.class, short.class}
+ )
+ public void testSetShortStringShort() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setString(java.lang.String, java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setString",
+ args = {String.class, String.class}
+ )
+ public void testSetStringStringString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setTime(java.lang.String, java.sql.Time)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTime",
+ args = {String.class, Time.class}
+ )
+ public void testSetTimeStringTime() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setTime(java.lang.String, java.sql.Time, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTime",
+ args = {String.class, Time.class, Calendar.class}
+ )
+ public void testSetTimeStringTimeCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setTimestamp(java.lang.String, java.sql.Timestamp)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTimestamp",
+ args = {String.class, Timestamp.class}
+ )
+ public void testSetTimestampStringTimestamp() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setTimestamp(java.lang.String, java.sql.Timestamp, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setTimestamp",
+ args = {String.class, Timestamp.class, Calendar.class}
+ )
+ public void testSetTimestampStringTimestampCalendar() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#setURL(java.lang.String, java.net.URL)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setURL",
+ args = {String.class, URL.class}
+ )
+ public void testSetURLStringURL() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.CallableStatement#wasNull()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "wasNull",
+ args = {}
+ )
+ public void testWasNull() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/sql/ClobTest.java b/sql/src/test/java/tests/sql/ClobTest.java
new file mode 100644
index 0000000..c0f218f
--- /dev/null
+++ b/sql/src/test/java/tests/sql/ClobTest.java
@@ -0,0 +1,177 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.sql;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import java.sql.Clob;
+
+/**
+ * @author andrea@google.com (Your Name Here)
+ *
+ */
+@TestTargetClass(Clob.class)
+public class ClobTest extends TestCase {
+
+ /**
+ * Test method for {@link java.sql.Clob#getAsciiStream()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getAsciiStream",
+ args = {}
+ )
+ public void testGetAsciiStream() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#getCharacterStream()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getCharacterStream",
+ args = {}
+ )
+ public void testGetCharacterStream() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#getSubString(long, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getSubString",
+ args = {long.class, int.class}
+ )
+ public void testGetSubString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#length()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "length",
+ args = {}
+ )
+ public void testLength() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#position(java.sql.Clob, long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "position",
+ args = {Clob.class, long.class}
+ )
+ public void testPositionClobLong() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#position(java.lang.String, long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "position",
+ args = {String.class, long.class}
+ )
+ public void testPositionStringLong() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#setAsciiStream(long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setAsciiStream",
+ args = {long.class}
+ )
+ public void testSetAsciiStream() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#setCharacterStream(long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setCharacterStream",
+ args = {long.class}
+ )
+ public void testSetCharacterStream() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#setString(long, java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setString",
+ args = {long.class, String.class}
+ )
+ public void testSetStringLongString() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#setString(long, java.lang.String, int, int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setString",
+ args = {long.class, String.class, int.class, int.class}
+ )
+ public void testSetStringLongStringIntInt() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Clob#truncate(long)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "truncate",
+ args = {long.class}
+ )
+ public void testTruncate() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/sql/ConnectionTest.java b/sql/src/test/java/tests/sql/ConnectionTest.java
new file mode 100755
index 0000000..1bf2ff6
--- /dev/null
+++ b/sql/src/test/java/tests/sql/ConnectionTest.java
@@ -0,0 +1,2817 @@
+/*
+ * Copyright (C) 2007 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.sql;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+
+import java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.SQLWarning;
+import java.sql.Savepoint;
+import java.sql.Statement;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+
+import java.sql.CallableStatement;
+import java.util.Map;
+
+import junit.framework.Test;
+
+@TestTargetClass(Connection.class)
+public class ConnectionTest extends SQLTest {
+
+ /**
+ * @test {@link java.sql.Connection#createStatement()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "createStatement",
+ args = {}
+ )
+ public void testCreateStatement() {
+
+ Statement statement = null;
+ try {
+ statement = conn.createStatement();
+ assertNotNull(statement);
+ //check default values
+ assertEquals(ResultSet.FETCH_UNKNOWN, statement.getFetchDirection());
+ assertNull(statement.getWarnings());
+ assertTrue(statement.getQueryTimeout() > 0);
+ } catch (SQLException sqle) {
+ fail("SQL Exception was thrown: " + sqle.getMessage());
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ }
+ try {
+ conn.close();
+ statement.executeQuery("select * from zoo");
+ fail("SQLException is not thrown after close");
+ } catch (SQLException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @test {@link java.sql.Connection#createStatement(int resultSetType, int
+ * resultSetConcurrency)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Exception tests fail.",
+ method = "createStatement",
+ args = {int.class, int.class}
+ )
+ @KnownFailure("Scrolling on a forward only RS not allowed. conn.close() does not wrap up")
+ public void testCreateStatement_int_int() throws SQLException {
+ Statement st = null;
+ ResultSet rs = null;
+
+ // test read only
+ try {
+ st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ st.execute("select id, name from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.deleteRow();
+ fail("Could delete row for READ_ONLY ResultSet");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ // test forward only: scrolling not allowed
+ try {
+ st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ st.execute("select id, name from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.absolute(1);
+ rs.previous();
+ fail("Could scroll backwards");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ // test forward only
+ try {
+ st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ st.execute("select id, name from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.last();
+ rs.first();
+ fail("Could scroll backwards");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+
+ // test updating ResultSets
+ try {
+ st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
+ ResultSet.CONCUR_UPDATABLE);
+ st.execute("select name, family from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.insertRow();
+ rs.updateObject("family", "bird");
+ rs.next();
+ rs.previous();
+ assertEquals("parrot", (rs.getString(1)));
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
+ ResultSet.CONCUR_UPDATABLE);
+ st.execute("select name, family from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.insertRow();
+ rs.updateObject("family", "bird");
+ rs.next();
+ rs.previous();
+ assertEquals("bird", (rs.getString(1)));
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ conn.close();
+
+ try {
+ // exception is not specified for this case
+ conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, -1);
+ fail("Illigal arguments: should return exception.");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ // exception is not specified for this case
+ conn.createStatement(Integer.MIN_VALUE, ResultSet.CONCUR_READ_ONLY);
+ fail("Illigal arguments: should return exception.");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#createStatement(int resultSetType, int
+ * resultSetConcurrency, int resultSetHoldability)
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "ResultSet.HOLD_CURSORS_AT_COMMIT",
+ method = "createStatement",
+ args = {int.class, int.class, int.class}
+ )
+ public void testCreateStatement_int_int_int() {
+ Statement st = null;
+ try {
+ assertNotNull(conn);
+ st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ assertNotNull(st);
+ st.execute("select id, name from zoo");
+ ResultSet rs = st.getResultSet();
+ rs.next();
+ int pos = rs.getRow();
+ conn.commit();
+ assertEquals("ResultSet cursor position has changed",pos, rs.getRow());
+ try {
+ rs.close();
+ } catch (SQLException sqle) {
+ fail("Unexpected exception was thrown during closing ResultSet");
+ }
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ if (st != null) st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY, -100);
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ //ok
+ }
+
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "ResultSet.CLOSE_CURSORS_AT_COMMIT as argument is not supported",
+ method = "createStatement",
+ args = {int.class, int.class, int.class}
+ )
+ @KnownFailure("not supported")
+ public void testCreateStatementIntIntIntNotSupported() {
+ /*
+ Statement st = null;
+ try {
+ st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ assertNotNull(st);
+ st.execute("select id, name from zoo");
+ ResultSet rs = st.getResultSet();
+
+ try {
+ rs.close();
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ if (st != null) {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#getMetaData()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException test fails",
+ method = "getMetaData",
+ args = {}
+ )
+ @KnownFailure("conn.close() does not wrap up")
+ public void testGetMetaData() throws SQLException{
+ try {
+ DatabaseMetaData md = conn.getMetaData();
+ Connection con = md.getConnection();
+ assertEquals(conn, con);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+
+ conn.close();
+ try {
+ conn.getMetaData();
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#clearWarnings()
+ *
+ * TODO clearWarnings is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "test fails. not supported. always returns null.",
+ method = "clearWarnings",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void testClearWarnings() throws SQLException {
+
+ try {
+ SQLWarning w = conn.getWarnings();
+ assertNull(w);
+ } catch (Exception e) {
+ fail("Unexpected Exception: " + e.getMessage());
+ }
+
+
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute("select animals from zoo");
+ fail("SQLException was not thrown");
+ } catch (SQLException e) {
+ assertNotNull(conn.getWarnings());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ conn.clearWarnings();
+ SQLWarning w = conn.getWarnings();
+ assertNull(w);
+ } catch (Exception e) {
+ fail("Unexpected Exception: " + e.getMessage());
+ }
+
+ try {
+ st = conn.createStatement();
+ st.execute("select monkey from zoo");
+ fail("SQLException was not thrown");
+ } catch (SQLException e) {
+ assertEquals("SQLite.Exception: error in prepare/compile",e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ //Test for correct functionality
+ try {
+ SQLWarning w = conn.getWarnings();
+ assertNotNull(w);
+ } catch (Exception e) {
+ fail("Unexpected Exception: " + e.getMessage());
+ }
+
+ conn.close();
+ try {
+ conn.clearWarnings();
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ }
+
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#getWarnings()
+ *
+ * TODO GetWarnings is not supported: returns null
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported. always returns null. SQLException test fails",
+ method = "getWarnings",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void testGetWarnings() throws SQLException {
+ Statement st = null;
+ int errorCode1 = -1;
+ int errorCode2 = -1;
+
+ try {
+ st = conn.createStatement();
+ st.execute("select animals from zoooo");
+ fail("SQLException was not thrown");
+ } catch (SQLException e) {
+ // expected
+ errorCode1 = e.getErrorCode();
+ }
+
+ try {
+ SQLWarning wrs = conn.getWarnings();
+ assertNull(wrs);
+ } catch (Exception e) {
+ fail("Change test implementation: get warnings is supported now");
+ }
+
+ // tests implementation: but errorcodes need to change too -> change impl.
+ /*
+ Statement st = null;
+ int errorCode1 = -1;
+ int errorCode2 = -1;
+
+ try {
+ st = conn.createStatement();
+ st.execute("select animals from zoooo");
+ fail("SQLException was not thrown");
+ } catch (SQLException e) {
+ // expected
+ errorCode1 = e.getErrorCode();
+ }
+
+ try {
+ SQLWarning wrs = conn.getWarnings();
+ assertNotNull(wrs);
+ assertEquals(errorCode1, wrs.getErrorCode());
+ assertNull(wrs.getNextWarning());
+ } catch (Exception e) {
+ fail("Unexpected Exception: " + e.getMessage());
+ }
+ try {
+ st.execute("select horse from zoooooo");
+ } catch (SQLException e) {
+ // expected
+ errorCode2 = e.getErrorCode();
+ }
+
+ try {
+ SQLWarning wrs = conn.getWarnings();
+ assertEquals(errorCode1, wrs.getErrorCode());
+ assertNotNull(wrs.getNextWarning());
+ assertEquals(errorCode2, wrs.getErrorCode());
+ } catch (Exception e) {
+ fail("Unexpected Exception: " + e.getMessage());
+ }
+
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+
+ */
+
+ conn.close();
+ try {
+ conn.getWarnings();
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#getAutoCommit()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException checking missed",
+ method = "getAutoCommit",
+ args = {}
+ )
+ public void testGetAutoCommit() {
+ try {
+ conn.setAutoCommit(true);
+ assertTrue(conn.getAutoCommit());
+ conn.setAutoCommit(false);
+ assertFalse(conn.getAutoCommit());
+ conn.setAutoCommit(true);
+ assertTrue(conn.getAutoCommit());
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setAutoCommit(boolean)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "SQLException test throws exception",
+ method = "setAutoCommit",
+ args = {boolean.class}
+ )
+ @KnownFailure("conn.close() does not wrap up")
+ public void testSetAutoCommit() throws SQLException {
+
+ Statement st = null;
+ ResultSet rs = null;
+ ResultSet rs1 = null;
+ try {
+ conn.setAutoCommit(true);
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (3, 'Chichichi', 'monkey');");
+ conn.commit();
+ } catch (SQLException e) {
+ //ok
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ // even though exception was thrown value is committed
+ try {
+ st = conn.createStatement();
+ st.execute("select * from zoo");
+ rs = st.getResultSet();
+ assertEquals(3, getCount(rs));
+ } catch (SQLException e) {
+ fail("Unexpected Exception thrown");
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+
+ try {
+ conn.setAutoCommit(false);
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (4, 'Burenka', 'cow');");
+ st.execute("select * from zoo");
+ rs = st.getResultSet();
+ assertEquals(4, getCount(rs));
+ conn.commit();
+ // Check cursors closed after commit
+ rs1 = st.getResultSet();
+ assertEquals(0, getCount(rs1));
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ rs1.close();
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ conn.close();
+
+ try {
+ conn.setAutoCommit(true);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#isReadOnly()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Instead of SQLException nullpointer exception is thrown.",
+ method = "isReadOnly",
+ args = {}
+ )
+ @KnownFailure("conn.close() does not wrap up")
+ public void testIsReadOnly() throws SQLException {
+ try {
+ conn.setReadOnly(true);
+ assertTrue(conn.isReadOnly());
+ conn.setReadOnly(false);
+ assertFalse(conn.isReadOnly());
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.getMessage());
+ }
+
+ conn.close();
+ try {
+ conn.isReadOnly();
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#setReadOnly(boolean)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Not supported. test fails",
+ method = "setReadOnly",
+ args = {boolean.class}
+ )
+ @KnownFailure("not supported")
+ public void testSetReadOnly() throws SQLException {
+
+ // Pseudo test: not supported test
+ Statement st = null;
+ try {
+ conn.setReadOnly(true);
+ st = conn.createStatement();
+ st.execute("insert into zoo (id, name, family) values (3, 'ChiChiChi', 'monkey');");
+ // fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ fail("Set readonly is actually implemented: activate correct test");
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ // test for correct implementation
+ st = null;
+ try {
+ conn.setReadOnly(true);
+ st = conn.createStatement();
+ st.execute("insert into zoo (id, name, family) values (3, 'ChiChiChi', 'monkey');");
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ conn.setReadOnly(true);
+ st = conn.createStatement();
+ st.executeUpdate("insert into zoo (id, name, family) values (4, 'ChaChaCha', 'monkey');");
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ conn.setReadOnly(false);
+ st = conn.createStatement();
+ st.execute("insert into zoo (id, name, family) values (4, 'ChiChiChi', 'monkey');");
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ conn.close();
+ try {
+ conn.setReadOnly(true);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#getHoldability()
+ *
+ * TODO ResultSet.CLOSE_CURSORS_AT_COMMIT is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "+option ResultSet.CLOSE_CURSORS_AT_COMMIT not supported. SQLException test fails.",
+ method = "getHoldability",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void testGetHoldability() throws SQLException {
+ try {
+ conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn
+ .getHoldability());
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.getMessage());
+ }
+
+ try {
+ conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, conn
+ .getHoldability());
+ } catch (SQLException e) {
+ assertEquals("not supported", e.getMessage());
+ }
+
+ // Exception checking
+
+ conn.close();
+
+ try {
+ conn.getHoldability();
+ fail("Could execute statement on closed connection.");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setHoldability(int)
+ *
+ * TODO ResultSet.CLOSE_CURSORS_AT_COMMIT is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "ResultSet.CLOSE_CURSORS_AT_COMMIT is not supported",
+ method = "setHoldability",
+ args = {int.class}
+ )
+ @KnownFailure("not supported")
+ public void testSetHoldability() {
+ Statement st = null;
+ try {
+ conn.setAutoCommit(false);
+ conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, conn
+ .getHoldability());
+ st = conn.createStatement();
+ st.execute("insert into zoo (id, name, family) values (4, 'ChiChiChi', 'monkey');");
+ ResultSet rs = st.getResultSet();
+ conn.commit();
+ try {
+ rs.next();
+ } catch (SQLException sqle) {
+ //ok
+ }
+ conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn
+ .getHoldability());
+ st = conn.createStatement();
+ st.execute("insert into zoo (id, name, family) values (4, 'ChiChiChi', 'monkey');");
+ rs = st.getResultSet();
+ conn.commit();
+ try {
+ rs.next();
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.getMessage());
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ conn.setHoldability(-1);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#getTransactionIsolation()
+ *
+ * TODO only Connection.TRANSACTION_SERIALIZABLE is supported
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "SQLException testing throws exception. Connection.TRANSACTION_SERIALIZABLE.",
+ method = "getTransactionIsolation",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void testGetTransactionIsolation() throws SQLException {
+ try {
+ conn
+ .setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+ assertEquals(Connection.TRANSACTION_READ_UNCOMMITTED, conn
+ .getTransactionIsolation());
+ conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn
+ .getTransactionIsolation());
+ conn
+ .setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+ assertEquals(Connection.TRANSACTION_REPEATABLE_READ, conn
+ .getTransactionIsolation());
+ conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ assertEquals(Connection.TRANSACTION_SERIALIZABLE, conn
+ .getTransactionIsolation());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+
+ // Exception checking
+
+ conn.close();
+
+ try {
+ conn.getTransactionIsolation();
+ fail("Could execute statement on closed connection.");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#getTransactionIsolation()
+ *
+ * TODO only Connection.TRANSACTION_SERIALIZABLE is supported
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "not supported options",
+ method = "getTransactionIsolation",
+ args = {}
+ )
+ public void testGetTransactionIsolationNotSupported() throws SQLException {
+ /*
+ try {
+ conn
+ .setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+ assertEquals(Connection.TRANSACTION_READ_UNCOMMITTED, conn
+ .getTransactionIsolation());
+ conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+ assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn
+ .getTransactionIsolation());
+ conn
+ .setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+ assertEquals(Connection.TRANSACTION_REPEATABLE_READ, conn
+ .getTransactionIsolation());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#setTransactionIsolation(int)
+ *
+ * TODO only Connection.TRANSACTION_SERIALIZABLE is supported
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "not fully supported",
+ method = "setTransactionIsolation",
+ args = {int.class}
+ )
+ public void testSetTransactionIsolation() {
+ try {
+// conn
+// .setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
+// assertEquals(Connection.TRANSACTION_READ_UNCOMMITTED, conn
+// .getTransactionIsolation());
+// conn.setTransactionIsolation(Connection.TRANSACTION_READ_COMMITTED);
+// assertEquals(Connection.TRANSACTION_READ_COMMITTED, conn
+// .getTransactionIsolation());
+// conn
+// .setTransactionIsolation(Connection.TRANSACTION_REPEATABLE_READ);
+// assertEquals(Connection.TRANSACTION_REPEATABLE_READ, conn
+// .getTransactionIsolation());
+ conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE);
+ assertEquals(Connection.TRANSACTION_SERIALIZABLE, conn
+ .getTransactionIsolation());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+
+ try {
+ conn.setTransactionIsolation(0);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setCatalog(String catalog)
+ *
+ * TODO setCatalog method does nothing: Hint default catalog sqlite_master.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setCatalog",
+ args = {java.lang.String.class}
+ )
+ public void testSetCatalog() {
+
+ String[] catalogs = { "test", "test1", "test" };
+ Statement st = null;
+ try {
+ for (int i = 0; i < catalogs.length; i++) {
+ conn.setCatalog(catalogs[i]);
+ assertNull(catalogs[i], conn.getCatalog());
+ st = conn.createStatement();
+ st
+ .equals("create table test_table (id integer not null, name varchar(20), primary key(id));");
+ st.equals("drop table test_table;");
+
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ /*
+ String[] catalogs = { "test"};
+ Statement st = null;
+ try {
+ for (int i = 0; i < catalogs.length; i++) {
+ conn.setCatalog(catalogs[i]);
+ fail("illegal catalog name");
+ assertEquals(catalogs[i], conn.getCatalog());
+ st = conn.createStatement();
+ st
+ .equals("create table test_table (id integer not null, name varchar(20), primary key(id));");
+ st.equals("drop table test_table;");
+ }
+ } catch (SQLException sqle) {
+ System.out.println("TODO: Test for correct error message: name with ,\"sqlite_\" prefix expected");
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ String[] catalogs = { "sqlite_test", "sqlite_test1", "sqlite_test" };
+ Statement st = null;
+ try {
+ for (int i = 0; i < catalogs.length; i++) {
+ conn.setCatalog(catalogs[i]);
+ assertEquals(catalogs[i], conn.getCatalog());
+ st = conn.createStatement();
+ st
+ .equals("create table test_table (id integer not null, name varchar(20), primary key(id));");
+ st.equals("drop table test_table;");
+
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ conn.setCatalog(null);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+
+ try {
+ conn.setCatalog("not_exist");
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+ */
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#getCatalog()
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported. test fails",
+ method = "getCatalog",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void testGetCatalog() throws SQLException {
+
+
+ // test default catalog
+ try {
+ assertEquals("sqlite_master", conn.getCatalog());
+ } catch (SQLException sqle) {
+ fail("SQL Exception " + sqle.getMessage());
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ }
+
+
+ String[] catalogs = { "sqlite_test", "sqlite_test1", "sqlite_test" };
+ Statement st = null;
+ try {
+ for (int i = 0; i < catalogs.length; i++) {
+ conn.setCatalog(catalogs[i]);
+ assertNull(conn.getCatalog());
+ }
+ } catch (SQLException sqle) {
+ fail("SQL Exception " + sqle.getMessage());
+ } catch (Exception e) {
+ fail("Reeimplement tests now that the method is implemented");
+ }
+
+ // Exception checking
+
+ conn.close();
+
+ try {
+ conn.getCatalog();
+ fail("Could execute statement on closed connection.");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setTypeMap(Map> map)
+ *
+ * TODO setTypeMap is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setTypeMap",
+ args = {java.util.Map.class}
+ )
+ public void testSetTypeMap() {
+ /*
+ try {
+ java.util.Map map = conn.getTypeMap();
+ map
+ .put(
+ "org.apache.harmony.sql.tests.java.sql.TestHelper_Connection1",
+ Class.forName("TestHelper_Connection1"));
+ conn.setTypeMap(map);
+ assertEquals(map, conn.getTypeMap());
+ } catch (SQLException sqle) {
+ //ok
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ }
+
+ try {
+ conn.setTypeMap(null);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+ */
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#getTypeMap()
+ *
+ * TODO getTypeMap is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "getTypeMap",
+ args = {}
+ )
+ public void testGetTypeMap() throws SQLException {
+ /*
+ try {
+ java.util.Map map = conn.getTypeMap();
+ map
+ .put(
+ "org.apache.harmony.sql.tests.java.sql.TestHelper_Connection1",
+ Class.forName("TestHelper_Connection1"));
+ conn.setTypeMap(map);
+ assertEquals(map, conn.getTypeMap());
+ } catch (SQLException sqle) {
+ //ok
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ }
+
+// Exception checking
+
+ conn.close();
+
+ try {
+ conn.setTypeMap(null);
+ fail("Could execute statement on closed connection.");
+ } catch (SQLException e) {
+ //ok
+ }
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#nativeSQL(String sql)
+ *
+ * TODO nativeSQL is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "nativeSQL",
+ args = {java.lang.String.class}
+ )
+ public void testNativeSQL() throws SQLException{
+ String[] queries = {
+ "select * from zoo;",
+ "insert into zoo (id, name, family) values (3, 'Chichichi', 'monkey');",
+ "create table zoo_office(id integer not null, name varchar(20), primary key(id));",
+ "drop table zoo_office;" };
+ String[] native_queries = {
+ "select * from zoo;",
+ "insert into zoo (id, name, family) values (3, 'Chichichi', 'monkey');",
+ "create table zoo_office(id integer not null, name varchar(20), primary key(id));",
+ "drop table zoo_office;" };
+ Statement st = null;
+ String nativeQuery = "";
+ try {
+ for (int i = 0; i < queries.length; i++) {
+ nativeQuery = conn.nativeSQL(queries[i]);
+ assertEquals(native_queries[i], nativeQuery);
+ st = conn.createStatement();
+ st.execute(nativeQuery);
+ }
+ } catch (SQLException sqle) {
+ //ok
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ String[] inc_queries = { "", " ", "not query" };
+ for (int i = 0; i < inc_queries.length; i++) {
+ try {
+ nativeQuery = conn.nativeSQL(inc_queries[i]);
+ assertEquals(inc_queries[i], nativeQuery);
+ } catch (SQLException e) {
+ assertEquals("not supported",e.getMessage());
+ }
+ }
+
+ // Exception checking
+
+ conn.close();
+
+ try {
+ conn.nativeSQL(inc_queries[0]);
+ fail("Could execute statement on closed connection.");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ }
+
+ /**
+ * @test java.sql.Connection#prepareCall(String sql)
+ *
+ * TODO prepareCall is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "prepareCall",
+ args = {java.lang.String.class}
+ )
+ public void testPrepareCall() throws SQLException {
+ CallableStatement cstmt = null;
+ ResultSet rs = null;
+ ResultSet rs1 = null;
+ Statement st = null;
+ Statement st1 = null;
+ try {
+ cstmt = conn.prepareCall("call welcomeAnimal(3, 'Petya', 'Cock')");
+ st = conn.createStatement();
+ st.execute("select * from zoo");
+ rs = st.getResultSet();
+ assertEquals(2, getCount(rs));
+ cstmt.execute();
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(3, getCount(rs1));
+
+ } catch (SQLException e) {
+ //ok not supported
+ } finally {
+ try {
+ st.close();
+ st1.close();
+ rs.close();
+ rs1.close();
+ cstmt.close();
+ } catch (Exception ee) {
+ }
+ }
+
+
+ try {
+ conn.prepareCall("welcomeAnimal(4, 'Petya', 'Cock')");
+ fail("SQL Exception is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+
+ try {
+ conn.prepareCall(null);
+ fail("SQL Exception is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+
+ // Exception checking
+
+ conn.close();
+
+ try {
+ conn.prepareCall("");
+ fail("Could execute statement on closed connection.");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ }
+
+ /**
+ * @test java.sql.Connection#prepareCall(String sql, int resultSetType, int
+ * resultSetConcurrency)
+ *
+ * TODO prepareCall is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "prepareCall",
+ args = {java.lang.String.class, int.class, int.class}
+ )
+ public void testPrepareCall_String_int_int() {
+ CallableStatement cstmt = null;
+ ResultSet rs = null;
+
+ try {
+ String query = "call welcomeAnimal(3, 'Petya', 'Cock')";
+ cstmt = conn.prepareCall(query, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ } catch (SQLException e) {
+ //ok
+ }
+
+ /*
+ try {
+ String query = "call welcomeAnimal(3, 'Petya', 'Dino')";
+ cstmt = conn.prepareCall(query, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ cstmt.execute("select id, name from zoo");
+ rs = cstmt.getResultSet();
+ try {
+ rs.deleteRow();
+ fail("Can delete row for READ_ONLY ResultSet");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ rs.absolute(0);
+ fail("Can move cursor to the last position for TYPE_FORWARD_ONLY ResultSet");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ cstmt.close();
+ } catch (Exception ee) {
+ }
+ }
+ Statement st = null;
+ try {
+ st = conn.createStatement(ResultSet.TYPE_SCROLL_INSENSITIVE,
+ ResultSet.CONCUR_UPDATABLE);
+ st.execute("select name, family from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.insertRow();
+ rs.updateObject("family", "bird");
+ rs.next();
+ rs.previous();
+ assertEquals("parrot", (rs.getString(1)));
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE,
+ ResultSet.CONCUR_UPDATABLE);
+ st.execute("select name, family from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.insertRow();
+ rs.updateObject("family", "bird");
+ rs.next();
+ rs.previous();
+ assertEquals("bird", (rs.getString(1)));
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, -1);
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ conn.createStatement(Integer.MIN_VALUE, ResultSet.CONCUR_READ_ONLY);
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#prepareCall(String sql, int resultSetType, int
+ * resultSetConcurrency, int resultSetHoldability)
+ *
+ * TODO prepareCall is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "prepareCall",
+ args = {java.lang.String.class, int.class, int.class, int.class}
+ )
+ public void testPrepareCall_String_int_int_int() {
+ CallableStatement cstmt = null;
+ ResultSet rs = null;
+
+ try {
+ String query = "call welcomeAnimal(?, ?, ?)";
+ cstmt = conn.prepareCall(query, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ } catch (SQLException e) {
+ //ok
+ }
+ /*
+ try {
+ String query = "call welcomeAnimal(?, ?, ?)";
+ cstmt = conn.prepareCall(query, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ cstmt.setInt(1, 3);
+ cstmt.setString(2, "Petya");
+ cstmt.setString(3, "Cock");
+ cstmt.execute("select id, name from zoo");
+ rs = cstmt.getResultSet();
+ try {
+ rs.close();
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ fail("Unexpected exception was thrown during closing ResultSet");
+ }
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ cstmt.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ Statement st = null;
+
+ try {
+ st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ st.execute("select id, name from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.close();
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ }
+
+ try {
+ conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY, -100);
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ */
+
+ }
+
+ /**
+ * @test java.sql.Connection#prepareStatement(String sql)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "prepareStatement",
+ args = {java.lang.String.class}
+ )
+ public void testPrepareStatement() {
+ PreparedStatement prst = null;
+ Statement st = null;
+ ResultSet rs = null;
+ ResultSet rs1 = null;
+ try {
+ String update = "update zoo set family = ? where name = ?;";
+ prst = conn.prepareStatement(update);
+ prst.setString(1, "cat");
+ prst.setString(2, "Yasha");
+ st = conn.createStatement();
+ st.execute("select * from zoo where family = 'cat'");
+ rs = st.getResultSet();
+ assertEquals(0, getCount(rs));
+ prst.executeUpdate();
+ st.execute("select * from zoo where family = 'cat'");
+ rs1 = st.getResultSet();
+ assertEquals(1, getCount(rs1));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ rs1.close();
+ prst.close();
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ prst = conn.prepareStatement("");
+ prst.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ try {
+ conn.prepareStatement(null);
+ fail("SQLException is not thrown");
+ } catch (Exception e) {
+ //ok
+ }
+
+
+ }
+
+
+ /**
+ * @test { @link java.sql.Connection#prepareStatement(String sql, int
+ * autoGeneratedKeys) }
+ */
+// TODO Crashes VM. Fix later.
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Statment.Return_generated_keys/getGeneratedKeys is not supported",
+ method = "prepareStatement",
+ args = {java.lang.String.class, int.class}
+ )
+ @KnownFailure("not supported")
+ public void testPrepareStatement_String_int() {
+ PreparedStatement prst = null;
+ PreparedStatement prst1 = null;
+ Statement st = null;
+ ResultSet rs = null;
+ ResultSet rs1 = null;
+ ResultSet rs4 = null;
+ ResultSet rs5 = null;
+
+
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ prst = conn.prepareStatement(insert,
+ Statement.RETURN_GENERATED_KEYS);
+ fail("Fail: prepareStatement does not fail");
+ } catch (SQLException e) {
+ //ok not supported
+ }
+
+
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+
+ prst = conn.prepareStatement(insert,
+ Statement.NO_GENERATED_KEYS);
+ prst.setInt(1, 8);
+ prst.setString(2, "Tuzik");
+ prst.setString(3, "dog");
+ st = conn.createStatement();
+ st.execute("select * from zoo");
+ rs = st.getResultSet();
+ assertEquals(2, getCount(rs));
+ prst.execute();
+ st.execute("select * from zoo where family = 'dog'");
+ rs1 = st.getResultSet();
+ assertEquals(1, getCount(rs1));
+ /*
+// TODO getGeneratedKeys is not supported
+ rs4 = prst.getGeneratedKeys();
+ assertEquals(0, getCount(rs4));
+
+
+
+ prst1 = conn.prepareStatement(insert, Statement.RETURN_GENERATED_KEYS);
+ prst1.setInt(1, 5);
+ prst1.setString(2, "Layka");
+ prst1.setString(3, "dog");
+
+ prst1.execute();
+
+
+
+ rs5 = prst1.getGeneratedKeys();
+ assertEquals(0, getCount(rs5));
+
+ */
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ rs1.close();
+ prst.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+
+ }
+
+ /**
+ * @test java.sql.Connection#commit()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "commit",
+ args = {}
+ )
+ public void testCommit() {
+ Statement st = null;
+ Statement st1 = null;
+ Statement st2 = null;
+ Statement st3 = null;
+ Statement st4 = null;
+ ResultSet rs1 = null;
+ ResultSet rs2 = null;
+ ResultSet rs3 = null;
+ ResultSet rs4 = null;
+ try {
+ conn.setAutoCommit(false);
+
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (3, 'Vorobey', 'sparrow');");
+ st
+ .execute("insert into zoo (id, name, family) values (4, 'Orel', 'eagle');");
+
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ try {
+ conn.commit();
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st3 = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ st3.execute("select * from zoo");
+ rs3 = st3.getResultSet();
+ conn.commit();
+ assertEquals(4, getCount(rs3));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ if (rs3 != null) rs3.close();
+ if (st3 != null) st3.close();
+ } catch (SQLException ee) {
+ }
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.toString());
+ } finally {
+ try {
+ rs1.close();
+ st.close();
+ st1.close();
+ } catch (Exception ee) {
+ }
+ }
+
+
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.Connection#rollback()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "rollback",
+ args = {}
+ )
+ public void testRollback() throws SQLException {
+ Statement st = null;
+ Statement st1 = null;
+ ResultSet rs1 = null;
+ ResultSet rs2 = null;
+ ResultSet rs3 = null;
+
+ try {
+ conn.setAutoCommit(false);
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (3, 'Vorobey', 'sparrow');");
+ st
+ .execute("insert into zoo (id, name, family) values (4, 'Orel', 'eagle');");
+ conn.rollback();
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals("Rollback was ineffective",2, getCount(rs1));
+
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ } finally {
+ conn.setAutoCommit(true);
+ try {
+ st.close();
+ st1.close();
+ rs1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ try {
+ conn.setAutoCommit(false);
+
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (3, 'Vorobey', 'sparrow');");
+ st
+ .execute("insert into zoo (id, name, family) values (4, 'Orel', 'eagle');");
+
+ if (!conn.getAutoCommit()) {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ Statement st2 = null;
+ Statement st3 = null;
+ try {
+ conn.commit();
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ // rollback after commit ineffective
+ conn.rollback();
+ st3 = conn.createStatement();
+ st3.execute("select * from zoo");
+ rs3 = st3.getResultSet();
+ assertEquals(4, getCount(rs3));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ conn.setAutoCommit(true);
+ try {
+ rs2.close();
+ rs3.close();
+ st2.close();
+ st3.close();
+ } catch (SQLException ee) {
+ }
+ }
+ } else {
+ fail("Error in test setup: cannot turn autocommit off.");
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ } finally {
+ try {
+ st.close();
+ st1.close();
+ rs1.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ conn.close();
+ try {
+ conn.rollback();
+ fail("SQLException expected");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setSavepoint()
+ *
+ * TODO setSavepoint is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setSavepoint",
+ args = {}
+ )
+ public void testSetSavepoint() {
+
+ try {
+ conn.setAutoCommit(false);
+
+ try {
+ Savepoint sp = conn.setSavepoint();
+ } catch (SQLException e) {
+ // ok not supported
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+
+
+ //Complete test but: not supported exception is thrown
+ /*
+ try {
+ conn.setAutoCommit(false);
+
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (3, 'Vorobey', 'sparrow');");
+ st
+ .execute("insert into zoo (id, name, family) values (4, 'Orel', 'eagle');");
+
+ if (!conn.getAutoCommit()) {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ Statement st2 = null;
+ ResultSet rs2 = null;
+ try {
+ Savepoint sp = conn.setSavepoint();
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.rollback(sp);
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ Savepoint sp1 = conn.setSavepoint();
+ assertNotNull(sp1);
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint();
+ assertNotNull(sp2);
+ st
+ .execute("insert into zoo (id, name, family) values (6, 'grach', 'rook');");
+ conn.rollback(sp1);
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ Savepoint sp1 = conn.setSavepoint();
+ assertNotNull(sp1);
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint();
+ assertNotNull(sp2);
+ st
+ .execute("insert into zoo (id, name, family) values (6, 'grach', 'rook');");
+ conn.rollback();
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ } else {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ try {
+ Savepoint sp = conn.setSavepoint();
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.rollback(sp);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ } finally {
+ try {
+ rs1.close();
+ st.close();
+ st1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#setSavepoint(String name)
+ *
+ * TODO setSavepoint is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setSavepoint",
+ args = {java.lang.String.class}
+ )
+ public void testSetSavepoint_String() {
+
+ String testSavepoint = "testSavepoint";
+
+ try {
+ conn.setAutoCommit(false);
+
+ try {
+ Savepoint sp = conn.setSavepoint(testSavepoint);
+ } catch (SQLException e) {
+ // ok not supported
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+
+ /*
+ Statement st = null;
+ Statement st1 = null;
+ ResultSet rs1 = null;
+ try {
+ conn.setAutoCommit(false);
+
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (3, 'Vorobey', 'sparrow');");
+ st
+ .execute("insert into zoo (id, name, family) values (4, 'Orel', 'eagle');");
+
+ if (!conn.getAutoCommit()) {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ Statement st2 = null;
+ ResultSet rs2 = null;
+ try {
+ Savepoint sp = conn.setSavepoint("one");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.rollback(sp);
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ Savepoint sp1 = conn.setSavepoint("one");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint("two");
+ st
+ .execute("insert into zoo (id, name, family) values (6, 'grach', 'rook');");
+ conn.rollback(sp1);
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ Savepoint sp1 = conn.setSavepoint("three");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint("four");
+ st
+ .execute("insert into zoo (id, name, family) values (6, 'grach', 'rook');");
+ conn.rollback();
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ } else {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ try {
+ Savepoint sp = conn.setSavepoint("five");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.rollback(sp);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ } finally {
+ try {
+ rs1.close();
+ st.close();
+ st1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#rollback(Savepoint savepoint)
+ *
+ * TODO Savepoint is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "rollback",
+ args = {java.sql.Savepoint.class}
+ )
+ public void testRollback_Savepoint() {
+ Savepoint sp = new DummySavePoint();
+ try {
+ conn.setAutoCommit(false);
+
+ try {
+ conn.rollback(sp);
+ } catch (SQLException e) {
+ //ok
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ /*
+ Statement st = null;
+ Statement st1 = null;
+ ResultSet rs1 = null;
+ try {
+ conn.setAutoCommit(false);
+
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (3, 'Vorobey', 'sparrow');");
+ st
+ .execute("insert into zoo (id, name, family) values (4, 'Orel', 'eagle');");
+
+ if (!conn.getAutoCommit()) {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ Statement st2 = null;
+ ResultSet rs2 = null;
+ try {
+ Savepoint sp = conn.setSavepoint("one");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.rollback(sp);
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ Savepoint sp1 = conn.setSavepoint("one");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint("two");
+ st
+ .execute("insert into zoo (id, name, family) values (6, 'grach', 'rook');");
+ conn.rollback(sp1);
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ Savepoint sp1 = conn.setSavepoint("three");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint("four");
+ st
+ .execute("insert into zoo (id, name, family) values (6, 'grach', 'rook');");
+ conn.rollback();
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ } else {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ try {
+ Savepoint sp = conn.setSavepoint("five");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.rollback(sp);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ } finally {
+ try {
+ rs1.close();
+ st.close();
+ st1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#releaseSavepoint(Savepoint savepoint)
+ *
+ * TODO Savepoint is not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "releaseSavepoint",
+ args = {java.sql.Savepoint.class}
+ )
+ public void testReleaseSavepoint_Savepoint() {
+ Savepoint sp = new DummySavePoint();
+ try {
+ conn.setAutoCommit(false);
+
+ try {
+ conn.releaseSavepoint(sp);
+ } catch (SQLException e) {
+ //ok
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ /*
+
+ Statement st = null;
+ Statement st1 = null;
+ ResultSet rs1 = null;
+ try {
+ conn.setAutoCommit(false);
+
+ st = conn.createStatement();
+ st
+ .execute("insert into zoo (id, name, family) values (3, 'Vorobey', 'sparrow');");
+ st
+ .execute("insert into zoo (id, name, family) values (4, 'Orel', 'eagle');");
+
+ if (!conn.getAutoCommit()) {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ Statement st2 = null;
+ ResultSet rs2 = null;
+ try {
+ Savepoint sp = conn.setSavepoint("one");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.rollback(sp);
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.releaseSavepoint(sp);
+ try {
+ conn.rollback(sp);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ conn.rollback();
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ Savepoint sp1 = conn.setSavepoint("one");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint("two");
+ st
+ .execute("insert into zoo (id, name, family) values (6, 'grach', 'rook');");
+ conn.releaseSavepoint(sp1);
+ try {
+ conn.rollback(sp1);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ conn.commit();
+ conn.rollback(sp2);
+ st2 = conn.createStatement();
+ st2.execute("select * from zoo");
+ rs2 = st2.getResultSet();
+ assertEquals(4, getCount(rs2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ rs2.close();
+ st2.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ } else {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ try {
+ Savepoint sp = conn.setSavepoint("five");
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ conn.releaseSavepoint(sp);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ } finally {
+ try {
+ rs1.close();
+ st.close();
+ st1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#prepareStatement(String sql, int[]
+ * columnIndexes)
+ *
+ * TODO prepareStatement(String sql, int[] columnIndexes) is not
+ * supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "prepareStatement",
+ args = {java.lang.String.class, int[].class}
+ )
+ public void testPrepareStatement_String_intArray() {
+ PreparedStatement prst = null;
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ prst = conn.prepareStatement(insert, new int[] { 0, 1, 2 });
+ } catch (SQLException e) {
+ //ok not supported
+ } finally {
+ try {
+ prst.close();
+ } catch (Exception ee) {
+ }
+ }
+ /*
+
+ Statement st = null;
+ PreparedStatement prst1 = null;
+ PreparedStatement prst = null;
+ ResultSet rs = null;
+ ResultSet rs1 = null;
+ ResultSet rs4 = null;
+ ResultSet rs5 = null;
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ prst = conn.prepareStatement(insert, new int[] { 0, 1, 2 });
+ prst.setInt(1, 8);
+ prst.setString(2, "Tuzik");
+ prst.setString(3, "dog");
+
+ st = conn.createStatement();
+ st.execute("select * from zoo");
+ rs = st.getResultSet();
+ assertEquals(2, getCount(rs));
+ prst.execute();
+ st.execute("select * from zoo where family = 'dog'");
+ rs1 = st.getResultSet();
+ assertEquals(1, getCount(rs1));
+
+ rs4 = prst.getGeneratedKeys();
+ assertEquals(0, getCount(rs4));
+
+ prst1 = conn.prepareStatement(insert, new int[] { 0, 1, 2, 10 });
+ prst1.setInt(1, 5);
+ prst1.setString(2, "Layka");
+ prst1.setString(3, "dog");
+
+ prst1.execute();
+
+ rs5 = prst1.getGeneratedKeys();
+ assertEquals(0, getCount(rs5));
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ rs1.close();
+ rs4.close();
+ rs5.close();
+ st.close();
+ prst1.close();
+ prst.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ conn.prepareStatement(insert, new int[] {});
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ conn.prepareStatement(insert, (int[]) null);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+ */
+ }
+
+ /**
+ * @test java.sql.Connection#prepareStatement(String sql, int resultSetType,
+ * int resultSetConcurrency)
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "not fully supported",
+ method = "prepareStatement",
+ args = {java.lang.String.class, int.class, int.class}
+ )
+ public void testPrepareStatement_String_int_int() {
+ String query = "insert into zoo (id, name, family) values (?, ?, ?);";
+ PreparedStatement st = null;
+ ResultSet rs = null;
+ try {
+
+ st = conn.prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY);
+ st.execute("select id, name from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.deleteRow();
+ fail("Can delete row for READ_ONLY ResultSet");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ if (rs != null) rs.close();
+ if (st != null) st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st = conn.prepareStatement(query, ResultSet.TYPE_SCROLL_SENSITIVE,
+ ResultSet.CONCUR_UPDATABLE);
+ st.execute("select name, family from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.insertRow();
+ rs.updateObject("family", "bird");
+ rs.next();
+ rs.previous();
+ assertEquals("bird", (rs.getString(1)));
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ conn.prepareStatement(query, ResultSet.TYPE_SCROLL_SENSITIVE, -1);
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ conn.prepareStatement(query, Integer.MIN_VALUE,
+ ResultSet.CONCUR_READ_ONLY);
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "not supported options: ResultSet.TYPE_SCROLL_INSENSITIVE," +
+ "ResultSet.CONCUR_UPDATABLE",
+ method = "prepareStatement",
+ args = {java.lang.String.class, int.class, int.class}
+ )
+ @KnownFailure("not supported")
+ public void testPrepareStatementNotSupported() {
+ String query = "insert into zoo (id, name, family) values (?, ?, ?);";
+ PreparedStatement st = null;
+ ResultSet rs = null;
+ try {
+ st = conn.prepareStatement(query,
+ ResultSet.TYPE_SCROLL_INSENSITIVE,
+ ResultSet.CONCUR_UPDATABLE);
+ st.execute("select name, family from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.insertRow();
+ rs.updateObject("family", "bird");
+ rs.next();
+ rs.previous();
+ assertEquals("parrot", (rs.getString(1)));
+ } catch (SQLException sqle) {
+ fail("Got Exception "+sqle.getMessage());
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ if (rs != null) rs.close();
+ if (st != null) st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ }
+
+
+
+ /**
+ * @test java.sql.Connection#prepareStatement(String sql, int resultSetType,
+ * int resultSetConcurrency, int resultSetHoldability)
+ */
+ // TODO Crashes VM. Fix later.
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Not fully implemented: ResultSet.CLOSE_CURSORS_AT_COMMIT not supported",
+ method = "prepareStatement",
+ args = {java.lang.String.class, int.class, int.class, int.class}
+ )
+ public void testPrepareStatement_String_int_int_int() {
+ String query = "insert into zoo (id, name, family) values (?, ?, ?);";
+ PreparedStatement st = null;
+ ResultSet rs = null;
+ try {
+ st = conn.prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ st.setInt(1, 3);
+ st.setString(2, "Petya");
+ st.setString(3, "Cock");
+ st.execute("select id, name from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.close();
+ } catch (SQLException sqle) {
+ fail("Unexpected exception was thrown during closing ResultSet");
+ }
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ if (rs != null) rs.close();
+ if (st != null) st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ /*
+ //TODO ResultSet.CLOSE_CURSORS_AT_COMMIT is not supported
+ try {
+ st = conn.prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ st.execute("select id, name from zoo");
+ rs = st.getResultSet();
+ try {
+ rs.close();
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ rs.close();
+ } catch (SQLException ee) {
+ }
+ }
+ */
+
+ try {
+ conn.prepareStatement(query, ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY, -100);
+ fail("SQLException was not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ }
+
+ /**
+ * @test java.sql.Connection#prepareStatement(String sql, String[]
+ * columnNames)
+ *
+ * TODO prepareStatement(String sql, String[] columnNames) method is
+ * not supported
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "prepareStatement",
+ args = {java.lang.String.class, java.lang.String[].class}
+ )
+ public void testPrepareStatement_String_StringArray() {
+ PreparedStatement prst = null;
+ PreparedStatement prst1 = null;
+ ResultSet rs = null;
+ ResultSet rs1 = null;
+ ResultSet rs4 = null;
+ ResultSet rs5 = null;
+
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ conn.prepareStatement(insert, new String[] { "id", "name",
+ "family" });
+ } catch (SQLException e) {
+ //ok not supported
+ }
+
+ /*
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ conn.prepareStatement(insert, new String[] {});
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ conn.prepareStatement(insert, (String[]) null);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+
+ try {
+ String insert = "insert into zoo (id, name, family) values (?, ?, ?);";
+ prst = conn.prepareStatement(insert, new String[] { "id", "name",
+ "family" });
+ prst.setInt(1, 8);
+ prst.setString(2, "Tuzik");
+ prst.setString(3, "dog");
+
+ Statement st = conn.createStatement();
+ st.execute("select * from zoo");
+ rs = st.getResultSet();
+ assertEquals(2, getCount(rs));
+ prst.execute();
+ st.execute("select * from zoo where family = 'dog'");
+ rs1 = st.getResultSet();
+ assertEquals(1, getCount(rs1));
+
+ rs4 = prst.getGeneratedKeys();
+ assertEquals(0, getCount(rs4));
+
+ prst1 = conn.prepareStatement(insert, new String[] { "id", "name", "" });
+ prst1.setInt(1, 5);
+ prst1.setString(2, "Layka");
+ prst1.setString(3, "dog");
+
+ prst1.execute();
+
+ rs5 = prst1.getGeneratedKeys();
+ assertEquals(0, getCount(rs5));
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ rs1.close();
+ rs4.close();
+ rs5.close();
+ prst.close();
+ prst1.close();
+ } catch (Exception ee) {
+ }
+ }
+ */
+
+
+ }
+
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported: it should release all resources but it doesn't",
+ method = "close",
+ args = {}
+ )
+ public void testClose() {
+ try {
+
+
+
+ if (! conn.isClosed()) {
+ conn.close();
+ }
+ assertTrue(conn.isClosed());
+
+ try {
+ conn.prepareCall("select * from zoo");
+ fail("Should not be able to prepare query closed connection");
+ } catch (SQLException e) {
+ //ok
+ }
+ } catch (SQLException e) {
+ fail("Error in implementation");
+ e.printStackTrace();
+ }
+
+ }
+
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "isClosed",
+ args = {}
+ )
+ public void testIsClosed() {
+ try {
+ assertFalse(conn.isClosed());
+ conn.close();
+ assertTrue(conn.isClosed());
+ } catch (SQLException e) {
+ fail("Error in implementation");
+ e.printStackTrace();
+ }
+
+ try {
+ this.setUp();
+ assertFalse(conn.isClosed());
+ Statement st = conn.createStatement();
+ st.execute("select * from zoo");
+ } catch (SQLException e2) {
+ fail("Error in test setup");
+ }
+ }
+
+
+ private static class DummySavePoint implements Savepoint{
+
+ public int getSavepointId() {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public String getSavepointName() {
+ // TODO Auto-generated method stub
+ return "NoName";
+ }
+
+ }
+}
diff --git a/sql/src/test/java/tests/sql/ParameterMetaDataTest.java b/sql/src/test/java/tests/sql/ParameterMetaDataTest.java
new file mode 100644
index 0000000..f522450
--- /dev/null
+++ b/sql/src/test/java/tests/sql/ParameterMetaDataTest.java
@@ -0,0 +1,150 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.sql;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import java.sql.ParameterMetaData;
+
+/**
+ *
+ */
+@TestTargetClass(ParameterMetaData.class)
+public class ParameterMetaDataTest extends TestCase {
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#getParameterClassName(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getParameterClassName",
+ args = {int.class}
+ )
+ public void testGetParameterClassName() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#getParameterCount()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getParameterCount",
+ args = {}
+ )
+ public void testGetParameterCount() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#getParameterMode(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getParameterMode",
+ args = {int.class}
+ )
+ public void testGetParameterMode() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#getParameterType(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getParameterType",
+ args = {int.class}
+ )
+ public void testGetParameterType() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#getParameterTypeName(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getParameterTypeName",
+ args = {int.class}
+ )
+ public void testGetParameterTypeName() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#getPrecision(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getPrecision",
+ args = {int.class}
+ )
+ public void testGetPrecision() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#getScale(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getScale",
+ args = {int.class}
+ )
+ public void testGetScale() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#isNullable(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "isNullable",
+ args = {int.class}
+ )
+ public void testIsNullable() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.ParameterMetaData#isSigned(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "isSigned",
+ args = {int.class}
+ )
+ public void testIsSigned() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/sql/PreparedStatementTest.java b/sql/src/test/java/tests/sql/PreparedStatementTest.java
new file mode 100755
index 0000000..68d5117
--- /dev/null
+++ b/sql/src/test/java/tests/sql/PreparedStatementTest.java
@@ -0,0 +1,3250 @@
+/*
+ * Copyright (C) 2007 Google Inc.
+ *
+ * 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.
+ */
+
+package tests.sql;
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.math.BigDecimal;
+import java.net.URL;
+import java.sql.Array;
+import java.sql.Blob;
+import java.sql.Clob;
+import java.sql.Date;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.Ref;
+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.text.SimpleDateFormat;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+@TestTargetClass(PreparedStatement.class)
+public class PreparedStatementTest extends SQLTest {
+
+ String queryAllSelect = "select * from type";
+
+ String[] queries = {
+ "create table type (" +
+
+ " BoolVal BOOLEAN," + " IntVal INT," + " LongVal LONG,"
+ + " Bint BIGINT," + " Tint TINYINT," + " Sint SMALLINT,"
+ + " Mint MEDIUMINT, " +
+
+ " IntegerVal INTEGER, " + " RealVal REAL, "
+ + " DoubleVal DOUBLE, " + " FloatVal FLOAT, "
+ + " DecVal DECIMAL, " +
+
+ " NumVal NUMERIC, " + " charStr CHAR(20), "
+ + " dateVal DATE, " + " timeVal TIME, " + " TS TIMESTAMP, "
+ +
+
+ " DT DATETIME, " + " TBlob TINYBLOB, " + " BlobVal BLOB, "
+ + " MBlob MEDIUMBLOB, " + " LBlob LONGBLOB, " +
+
+ " TText TINYTEXT, " + " TextVal TEXT, "
+ + " MText MEDIUMTEXT, " + " LText LONGTEXT " + ");",
+
+ "insert into type (BoolVal, IntVal, LongVal, Bint, Tint, Sint, Mint,"
+ + "IntegerVal, RealVal, DoubleVal, FloatVal, DecVal,"
+ + "NumVal, charStr, dateVal, timeVal, TS,"
+ + "DT, TBlob, BlobVal, MBlob, LBlob,"
+ + "TText, TextVal, MText, LText"
+ + ") "
+ + "values (1, -1, 22, 2, 33,"
+ + "3, 1, 2, 3.9, 23.2, 33.3, 44,"
+ + "5, 'test string', '1799-05-26', '12:35:45', '2007-10-09 14:28:02.0',"
+ + "'1221-09-22 10:11:55', 1, 2, 3, 4,"
+ + "'Test text message tiny', 'Test text message', 'Test text message medium', 'Test text message long');" };
+
+ public void setUp() {
+ super.setUp();
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ for (int i = 0; i < queries.length; i++) {
+ st.execute(queries[i]);
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ public void tearDown() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute("drop table if exists type");
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ super.tearDown();
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#addBatch()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "addBatch",
+ args = {}
+ )
+ public void testAddBatch() throws SQLException {
+ PreparedStatement ps = null;
+ try {
+ ps = conn
+ .prepareStatement("INSERT INTO zoo VALUES (3,'Tuzik', ?);");
+ ps.addBatch("INSERT INTO zoo VALUES (?,'Burenka', ?); ");
+ ps.addBatch("INSERT INTO zoo VALUES (?,'Mashka','cat')");
+ try {
+ ps.executeBatch();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown for executeBatch()");
+ }
+ ps.setString(1, "dog");
+ Statement st = null;
+ try {
+ ps.executeBatch();
+ st = conn.createStatement();
+ st.execute("select * from zoo");
+ ResultSet rs = st.getResultSet();
+ assertEquals(2, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown for executeBatch()");
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown "+e.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps = conn
+ .prepareStatement("INSERT INTO zoo VALUES (3,'Tuzik', ?);");
+ ps.addBatch("");
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps = conn
+ .prepareStatement("INSERT INTO zoo VALUES (3,'Tuzik', ?);");
+ ps.addBatch(null);
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+
+ /**
+ * @test java.sql.PreparedStatement#execute()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "execute",
+ args = {}
+ )
+ @KnownFailure("preparedStatement.execute() does not return false on update.")
+ public void testExecute() {
+ Statement st = null;
+ PreparedStatement ps = null;
+ try {
+ //update
+ String query = "insert into zoo(id, family, name) values(?, ?, 'unknown animal')";
+ ps = conn.prepareStatement(query);
+ ps.setInt(1, 3);
+ ps.setString(2, "No name");
+ assertFalse(ps.execute());
+ assertEquals(1,ps.getUpdateCount());
+
+ // select
+ ps = conn.prepareStatement("select * from zoo");
+ assertTrue(ps.execute());
+ assertEquals(3, getCount(ps.getResultSet()));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ String query = "update zoo set name='Masha', family=? where id=?;";
+ ps = conn.prepareStatement(query);
+ ps.setString(1, "cat");
+ ps.setInt(2, 2);
+ assertFalse(ps.execute());
+ assertEquals(1, ps.getUpdateCount());
+ st = conn.createStatement();
+ st.execute("select family from zoo where id=2");
+ ResultSet rs = st.getResultSet();
+ rs.next();
+ assertEquals("cat", rs.getString(1));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ ps.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ conn.createStatement().execute("drop table if exists hutch");
+ String query = "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));";
+ ps = conn.prepareStatement(query);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ String query = "select name, family from zoo where id = ?";
+ ps = conn.prepareStatement(query);
+ ps.setInt(1, 1);
+ assertTrue(ps.execute());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ String query = "select name, family from zoo where id = ?";
+ ps = conn.prepareStatement(query);
+ ps.execute();
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ //Exception test
+ try {
+ String query = "update zoo set name='Masha', family=? where id=?;";
+ ps = conn.prepareStatement(query);
+ ps.setString(1, "cat");
+ ps.setInt(2, 2);
+ assertTrue(ps.execute("update zoo set name='Masha', family='cat' where id=2;"));
+ } catch (SQLException e) {
+ // ok Should not provide string argument for a prepared Statement
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+
+ /**
+ * @test java.sql.PreparedStatement#executeQuery()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "executeQuery",
+ args = {}
+ )
+ public void testExecuteQuery() {
+
+ String[] queries2 = {
+ "update zoo set name='Masha', family='cat' where id=;",
+ "insert into hutch (id, animal_id, address) values (1, ?,'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (?, 1, 'Horse-house, 5');",
+ "create view address as select address from hutch where animal_id=?"};
+
+ for (int i = 0; i < queries2.length; i++) {
+ PreparedStatement ps = null;
+ try {
+ ps = conn.prepareStatement(queries2[i]);
+ ps.executeQuery();
+ fail("SQLException is not thrown for query: " + queries2[i]);
+ } catch (SQLException sqle) {
+ // expected
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ String query = "select * from zoo where id = ?";
+ PreparedStatement ps = null;
+ try {
+ ps = conn.prepareStatement(query);
+ ps.setInt(1, 1);
+ ResultSet rs = ps.executeQuery();
+ rs.next();
+ assertEquals(1, rs.getInt(1));
+ assertEquals("Kesha", rs.getString(2));
+ assertEquals("parrot", rs.getString(3));
+ } catch (SQLException e) {
+ fail("SQLException is thrown for query");
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps = conn.prepareStatement(query);
+ ps.setInt(1, 5);
+ ResultSet rs = ps.executeQuery();
+ assertNotNull(rs);
+ assertFalse(rs.next());
+ } catch (SQLException e) {
+ fail("SQLException is thrown for query");
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ // TODO Crashes VM. Fix later.
+ /**
+ * @test {@link java.sql.PreparedStatement#executeUpdate()}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "executeUpdate",
+ args = {}
+ )
+ public void testExecuteUpdate() {
+ String[] queries1 = { "insert into hutch (id, animal_id, address) values (1, ?, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (?, 1, 'Horse-house, 5');",
+ "create view address as select address from hutch where animal_id=2" };
+
+ for (int i = 0; i < queries1.length; i++) {
+ PreparedStatement ps = null;
+ try {
+ ps = conn.prepareStatement(queries1[i]);
+ ps.executeUpdate();
+ fail("SQLException is not thrown for query: " + queries1[i]);
+ } catch(SQLException sqle) {
+ // expected
+ } finally {
+ try {
+ ps.close();
+ } catch(Exception ee) {}
+ }
+ }
+
+ String query = "update zoo set name='Masha', family='cat' where id=?;";
+ PreparedStatement ps = null;
+ try {
+ ps = conn.prepareStatement(query);
+ ps.setInt(1, 2);
+ int updateCount = ps.executeUpdate();
+ assertEquals(1, updateCount);
+ ps.setInt(1, 1);
+ int updateCount1 = ps.executeUpdate();
+ assertEquals(1, updateCount1);
+ } catch (SQLException e) {
+ fail("SQLException is thrown for query");
+ } finally {
+ try {
+ ps.close();
+ } catch(Exception ee) {}
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#getMetaData()
+ *
+ * Test Fails:
+ * TODO Doesn't pass. according to Java docs:
+ * it is possible to invoke the method getMetaData on a
+ * PreparedStatement object before it is executed.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getMetaData",
+ args = {}
+ )
+ @KnownFailure("it is not possible to invoke the method getMetaData on a " +
+ "PreparedStatement object before it is executed: got NullPointerException."+
+ "Test passes on RI.")
+ public void testGetMetaData() {
+ PreparedStatement ps = null;
+
+ // Specification testing
+
+ try {
+ String query = "update zoo set name='Masha', family='cat' where id=?;";
+ ps = conn.prepareStatement(query);
+ assertNotNull(ps);
+ ResultSetMetaData meta = ps.getMetaData();
+ assertNotNull(meta);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ sqle.printStackTrace();
+ } catch (Exception e) {
+ fail("Unspecified Exception: " + e.toString());
+ e.printStackTrace();
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ String query = "select * from zoo where id = ?";
+ ps = conn.prepareStatement(query);
+ ResultSetMetaData rsmd = ps.getMetaData();
+ assertNotNull(rsmd);
+ assertEquals(3, rsmd.getColumnCount());
+ assertEquals("id", rsmd.getColumnName(1));
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ // ps closed
+ try {
+ ps.getMetaData();
+ fail("SQLException expected");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.PreparedStatement#getParameterMetaData()
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "not supported",
+ method = "getParameterMetaData",
+ args = {}
+ )
+ @KnownFailure("not supported")
+ public void testGetParameterMetaData() throws SQLException {
+ PreparedStatement ps = null;
+ String query = "select * from zoo where id = ?";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ParameterMetaData rsmd = ps.getParameterMetaData();
+ } catch (SQLException e) {
+ assertEquals("not supported",e.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ ps.close();
+
+ try {
+ ps.getParameterMetaData();
+ fail("SQLException expected");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+
+ /**
+ * @test java.sql.PreparedStatement#clearParameters()
+ * Test fails: clearparameters should be implemented with Stmt.reset()
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Test fails: clearparameters should be implemented with Stmt.reset()",
+ method = "clearParameters",
+ args = {}
+ )
+ @KnownFailure("First Exception test fails: parameters not cleared.")
+ public void testClearParameters() {
+ PreparedStatement ps = null;
+ try {
+ String query = "select * from zoo where id = ? and family=?";
+ ps = conn.prepareStatement(query);
+ ps.clearParameters();
+ try {
+ ps.execute();
+ fail("SQLException is not thrown during execute method after calling clearParameters()");
+ } catch (SQLException sql) {
+
+ }
+ ps.setInt(1, 2);
+ ps.setString(2, "dog");
+ ps.clearParameters();
+ try {
+ ps.execute();
+ fail("SQLException is not thrown during execute method after calling clearParameters()");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ ps.setInt(1, 2);
+ ps.clearParameters();
+ try {
+ ps.execute();
+ fail("SQLException is not thrown during execute method after calling clearParameters()");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ ps.setInt(1, 2);
+ ps.setString(2, "cat");
+
+ try {
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown during execute method after calling clearParameters() twice");
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setInt(int parameterIndex, int x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setInt",
+ args = {int.class, int.class}
+ )
+ public void testSetInt() throws SQLException {
+
+ PreparedStatement ps = null;
+ Statement st = null;
+ try {
+ String query = "insert into type (IntVal) values (?);";
+ ps = conn.prepareStatement(query);
+ try {
+ ps.setInt(1, Integer.MAX_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where IntVal="
+ + Integer.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ ps.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ ps = conn.prepareStatement(query);
+ try {
+ ps.setInt(1, Integer.MIN_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where IntVal="
+ + Integer.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ ps.close();
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ ps = conn.prepareStatement(query);
+ ps.close();
+ try {
+ ps.setInt(1, Integer.MIN_VALUE);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setLong(int parameterIndex, long x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setLong",
+ args = {int.class, long.class}
+ )
+ public void testSetLong() {
+
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (LongVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setLong(1, Long.MAX_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st
+ .execute("select * from type where LongVal="
+ + Long.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setLong(1, Long.MIN_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st
+ .execute("select * from type where LongVal="
+ + Long.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ ps.close();
+ try {
+ ps.setLong(1, Long.MIN_VALUE);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.PreparedStatement#setFloat(int parameterIndex, float x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setFloat",
+ args = {int.class, float.class}
+ )
+ public void testSetFloat() throws SQLException {
+ float value1 = 12345678.12345689f;
+ float value2 = -12345678.12345689f;
+
+ PreparedStatement ps = null;
+ String query = "insert into type (FloatVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+
+ Statement st = null;
+ try {
+ ps.setFloat(1, value1);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where FloatVal=" + value1);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setFloat(1, value2);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where FloatVal=" + value2);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+
+ }
+ }
+ ps.close();
+ try {
+ ps.setFloat(1, Float.MIN_VALUE);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @throws SQLException
+ * @test java.sql.PreparedStatement#setDouble(int parameterIndex, double x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setDouble",
+ args = {int.class, double.class}
+ )
+ public void testSetDouble() throws SQLException {
+
+ PreparedStatement ps = null;
+ String query = "insert into type (DoubleVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+
+ Statement st = null;
+ try {
+ ps.setDouble(1, Double.MAX_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where DoubleVal="
+ + Double.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setDouble(1, Double.MIN_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where DoubleVal="
+ + Double.MIN_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ ps.close();
+ try {
+ ps.setDouble(1, 2.0);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setString",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetString_charField() {
+
+ PreparedStatement ps = null;
+
+ try {
+ String query = "insert into type (charStr) values (?);";
+ ps = conn.prepareStatement(query);
+
+ String str = "test^text$test%";
+ Statement st = null;
+ try {
+ ps.setString(1, str);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where charStr='" + str + "'");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, "");
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where charStr=''");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, " ");
+ ps.execute();
+ st = conn.createStatement();
+ st
+ .execute("select * from type where charStr=' '");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, " test & text * test % text * test ^ text ");
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ }
+
+ try {
+ ps.setString(1, null);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ ps.close();
+
+ try {
+ ps.setString(1, "test text");
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setString",
+ args = {int.class, java.lang.String.class}
+ )
+ @KnownFailure("statment.close() does not wrap up")
+ public void testSetString_tinyTextField() {
+
+ PreparedStatement ps = null;
+ try {
+ String str = "test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test";
+ String query = "insert into type (TText) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setString(1, str);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where TText='" + str + "'");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, "");
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where TText=''");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, " ");
+ ps.execute();
+ st = conn.createStatement();
+ st
+ .execute("select * from type where TText=' '");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps.setString(
+ 1,
+ "test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test*test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test-test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test+test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test?test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test#test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test ");
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ }
+
+ try {
+ ps.setString(1, null);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ ps.close();
+
+ try {
+ ps.setString(1, "test text");
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setString",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetString_textField() {
+
+ PreparedStatement ps = null;
+ try {
+ String str = "test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test";
+ String query = "insert into type (TextVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setString(1, str);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where TextVal='" + str + "'");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, "");
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where TextVal=''");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, " ");
+ ps.execute();
+ st = conn.createStatement();
+ st
+ .execute("select * from type where TextVal=' '");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+
+ try {
+ String longString = " test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/";
+ for (int i = 0; i < 10; i++) {
+ longString += longString;
+ }
+ ps.setString(1, longString);
+ ps.execute();
+
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ }
+
+ try {
+ ps.setString(1, null);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ ps.close();
+
+ try {
+ ps.setString(2, "test text");
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setString",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetString_mediumTextField() {
+
+ PreparedStatement ps = null;
+ try {
+ String str = "test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test";
+ String query = "insert into type (MText) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setString(1, str);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where MText='" + str + "'");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, "");
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where MText=''");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, " ");
+ ps.execute();
+ st = conn.createStatement();
+ st
+ .execute("select * from type where MText=' '");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, null);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ ps.close();
+
+ try {
+ ps.setString(2, "test text");
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setString",
+ args = {int.class, java.lang.String.class}
+ )
+ public void testSetString_longTextField() {
+
+ PreparedStatement ps = null;
+ try {
+ String str = "test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test/test^text$test%test(text)test@text5test~test^text$test%test(text)test@text5test";
+ String query = "insert into type (LText) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setString(1, str);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where LText='" + str + "'");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, "");
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where LText=''");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, " ");
+ ps.execute();
+ st = conn.createStatement();
+ st
+ .execute("select * from type where LText=' '");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setString(1, null);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ ps.close();
+
+ try {
+ ps.setString(1, "test text");
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setShort(int parameterIndex, short x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setShort",
+ args = {int.class, short.class}
+ )
+ public void testSetShort() {
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ PreparedStatement ps2 = null;
+ try {
+ String query = "insert into type (Sint) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setShort(1, Short.MAX_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where Sint=" + Short.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setShort(1, Short.MIN_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where Sint=" + Short.MIN_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ ps.close();
+
+ try {
+ ps.setShort(1, Short.MIN_VALUE);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+ try {
+ ps1.setShort(1, Short.MAX_VALUE);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: "+sqle.getMessage());
+ }
+
+ String query2 = "insert into type (IntVal) values (?);";
+ ps2 = conn.prepareStatement(query2);
+ try {
+ ps2.setShort(1, Short.MAX_VALUE);
+ ps2.execute();
+ st = conn.createStatement();
+ st
+ .execute("select * from type where IntVal="
+ + Short.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ ps1.close();
+ ps2.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setBoolean(int parameterIndex, boolean
+ * x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setBoolean",
+ args = {int.class, boolean.class}
+ )
+ public void testSetBoolean() {
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (BoolVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setBoolean(1, false);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where BoolVal = 0");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setBoolean(1, true);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where BoolVal= 1");
+ ResultSet rs = st.getResultSet();
+ assertEquals(2, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ ps.close();
+
+ try {
+ ps.setBoolean(1, false);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+ try {
+ ps1.setBoolean(1, true);
+ ps1.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setByte(int parameterIndex, byte x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setByte",
+ args = {int.class, byte.class}
+ )
+ public void testSetByte() {
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (Tint) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setByte(1, Byte.MAX_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where Tint=" + Byte.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps.setByte(1, Byte.MIN_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where Tint=" + Byte.MIN_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps.setByte(2, Byte.MAX_VALUE);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+
+ ps.close();
+
+ try {
+ ps.setByte(1, Byte.MIN_VALUE);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ String query1 = "insert into type (IntVal) values (?);";
+ ps1 = conn.prepareStatement(query1);
+ try {
+ ps1.setByte(1, Byte.MAX_VALUE);
+ ps1.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setBytes(int parameterIndex, byte[] x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setBytes",
+ args = {int.class, byte[].class}
+ )
+ @KnownFailure("preparedStatement.execute() does not return false on update.")
+ public void testSetBytes() {
+
+ byte[] bytesArray = {1, 0};
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (LBlob) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setBytes(1, bytesArray);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ try {
+ ps.setBytes(2, bytesArray);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected RuntimeException or SQLException
+ }
+
+ ps.close();
+
+ try {
+ ps.setBytes(1, bytesArray);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ String query1 = "insert into type (TBlob) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps.setBytes(1, bytesArray);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ if (ps != null) ps.close();
+ if (ps1 != null) ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setBigDecimal(int parameterIndex,
+ * BigDecimal x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setBigDecimal",
+ args = {int.class, java.math.BigDecimal.class}
+ )
+ @KnownFailure("preparedStatement.execute() does not return false on update.")
+ public void testSetBigDecimal() {
+
+ BigDecimal bd = new BigDecimal("50");
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (DecVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setBigDecimal(1, bd);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+
+ try {
+ ps.setBigDecimal(2, bd);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ assertEquals("bad parameter index", sqle.getMessage());
+ }
+
+ try {
+ ps.setBigDecimal(-2, bd);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ assertEquals("bad parameter index", sqle.getMessage());
+ }
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setBigDecimal(1, bd);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ if (ps != null) ps.close();
+ if (ps1 != null) ps1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setDate(int parameterIndex, Date x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "First exception test fails: integer and date are incompatible"
+ +" by spec.",
+ method = "setDate",
+ args = {int.class, java.sql.Date.class}
+ )
+ @KnownFailure("preparedStatement.execute() does not return false on update. "+
+ "Setting a data for a declared INTEGER should throw Exception")
+ public void testSetDate_int_Date() {
+ Calendar cal = new GregorianCalendar(1799, 5, 26);
+
+ Date[] dates = {
+ new Date(cal.getTimeInMillis()), new Date(Integer.MAX_VALUE),
+ new Date(123456789)};
+
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (dateVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ for (int i = 0; i < dates.length; i++) {
+ try {
+ ps.setDate(1, dates[i]);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ }
+
+ try {
+ ps.setDate(2, dates[0]);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+
+ ps.close();
+
+ try {
+ ps.setDate(1, dates[0]);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setDate(1, dates[0]);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ assertEquals("SQLite.Exception: error in prepare", sqle
+ .getMessage());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ if (ps != null) ps.close();
+ if (ps1 != null) ps1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setDate(int parameterIndex, Date x,
+ * Calendar cal)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setDate",
+ args = {int.class, java.sql.Date.class, java.util.Calendar.class}
+ )
+ @KnownFailure("preparedStatement.execute() does not return false on update.")
+ public void testSetDate_int_Date_Calendar() {
+
+ Calendar[] cals = { Calendar.getInstance(),
+ Calendar.getInstance(Locale.GERMANY),
+ Calendar.getInstance(TimeZone.getDefault()) };
+ Calendar cal = new GregorianCalendar(1799,5,26);
+
+ Date[] dates = { new Date(cal.getTimeInMillis()), new Date(Integer.MAX_VALUE),
+ new Date(123456789) };
+
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (dateVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ for (int i = 0; i < dates.length; i++) {
+
+ try {
+ ps.setDate(1, dates[i], cals[i]);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ }
+
+ try {
+ ps.setDate(2, dates[0], cals[0]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+
+ ps.close();
+
+ try {
+ ps.setDate(1, dates[0], cals[1]);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setDate(1, dates[0], cals[2]);
+ ps1.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ if (ps != null) ps.close();
+ if (ps1 != null) ps1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setNull(int parameterIndex, int sqlType)
+ *
+ * this test doesn't passed on RI
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setNull",
+ args = {int.class, int.class}
+ )
+ public void testSetNull_int_int() {
+
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (BoolVal, IntVal) values ('true', ?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setNull(1, Types.INTEGER);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, LongVal) values ('true', ?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.BIGINT);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, DecVal) values ('true', ?)";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.DECIMAL);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, dateVal) values ('true', ?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.DATE);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, BlobVal) values ('true', ?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.BLOB);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, TextVal) values ('true', ?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.CHAR);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setNull(int, int, String)}
+ *
+ * UDTs and Ref types not supported in SQLite v 3
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setNull",
+ args = {int.class, int.class, java.lang.String.class}
+ )
+ public void testSetNullIntintString() {
+ // test UDT
+ String typeCreationStmtUDT = "CREATE TYPE addressType AS "
+ +"( street INTEGER, zip TEXT);";
+ String personTableCreateUDT = "CREATE TABLE person (name TEXT, address addressType);";
+ Statement st = null;
+ PreparedStatement ps = null;
+ try {
+ st = conn.createStatement();
+ st.execute(typeCreationStmtUDT);
+ st.execute(personTableCreateUDT);
+ fail("UDTs and Ref Types not supported");
+ String query = "insert into person (name, address) values ('Hans', ?);";
+ ps = conn.prepareStatement(query);
+ try {
+ ps.setNull(1, Types.DATALINK);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ sqle.printStackTrace();
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ } catch (SQLException e) {
+ // UDTs or Ref types not supported
+ // ok
+ } finally {
+ try {
+ st.execute("drop table if exists person");
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ // test non UDT REF type Exception checking
+ String personTableCreate = "create table person (name TEXT, Address TEXT)";
+ try {
+
+ st = conn.createStatement();
+ st.execute(personTableCreate);
+ String insert = "insert into person (name, address) values (?, '1600 Amphitheatre Mountain View');";
+ ps = conn.prepareStatement(insert);
+ try {
+ ps.setNull(1,1, "");
+ ps.execute();
+ } catch (SQLException sqle) {
+ assertEquals("SQLite.Exception: error in step",sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ try {
+ st.execute("drop table if exists person");
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ // test non UDT REF type OK
+
+ personTableCreate = "create table person (name TEXT, Address TEXT)";
+ try {
+
+ st = conn.createStatement();
+ st.execute("drop table if exists person");
+ st.execute(personTableCreate);
+ String insert = "insert into person (name, address) values (?, '1600 Amphitheatre Mountain View');";
+ ps = conn.prepareStatement(insert);
+ try {
+ ps.setNull(1,1, "");
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ sqle.printStackTrace();
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ e.printStackTrace();
+ } finally {
+ try {
+ st.execute("drop table if exists person");
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+
+ }
+
+
+ /**
+ * @test java.sql.PreparedStatement#setObject(int parameterIndex, Object x)
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setObject",
+ args = {int.class, java.lang.Object.class}
+ )
+ public void testSetObject_int_Object() {
+
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (IntVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setObject(1, Integer.MAX_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where IntVal="
+ + Integer.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (LongVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, "test text");
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where LongVal='test text';");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ query = "insert into type (DecVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, new Object());
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ }
+
+ query = "insert into type (dateVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Date d = new Date(123456789);
+
+ try {
+ ps.setObject(1, d);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where dateVal='"
+ + d.getTime() + "';");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ // this sub test doesn't pass on RI
+ query = "insert into type (BlobVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, null);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ try {
+ ps.setObject(1, "test text");
+ fail("Exception not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setObject(int parameterIndex, Object x,
+ * int targetSqlType)
+ *
+ * this test doesn't pass on RI
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setObject",
+ args = {int.class, java.lang.Object.class, int.class}
+ )
+ public void testSetObject_int_Object_int() {
+
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (IntVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setObject(1, Integer.MAX_VALUE, Types.INTEGER);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where IntVal="
+ + Integer.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (LongVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, "test text", Types.CHAR);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where LongVal='test text';");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (DecVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, new Object(), Types.DECIMAL);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+
+ query = "insert into type (dateVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Date d = new Date(123456789);
+
+
+ try {
+ ps.setObject(1, d, Types.DATE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where dateVal='"
+ + d.getTime() + "';");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ // this sub test doesn't pass on RI
+ query = "insert into type (BlobVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, "", Types.BLOB);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setObject(1, Integer.MAX_VALUE, Types.INTEGER);
+ fail("Exception not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setObject(int parameterIndex, Object x,
+ * int targetSqlType, int scale)
+ *
+ * this test doesn't pass on RI
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setObject",
+ args = {int.class, java.lang.Object.class, int.class, int.class}
+ )
+ public void testSetObject_int_Object_int_int() {
+
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (IntVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setObject(1, Integer.MAX_VALUE, Types.INTEGER,
+ Integer.MAX_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where IntVal="
+ + Integer.MAX_VALUE);
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (LongVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, "test text", Types.CHAR, Integer.MIN_VALUE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where LongVal='test text';");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (DecVal) values (?);";
+ ps = conn.prepareStatement(query);
+ BigDecimal bd2 = new BigDecimal("12.21");
+
+ try {
+ ps.setObject(1, bd2, Types.DECIMAL, 2);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+
+ query = "insert into type (dateVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Date d = new Date(123456789);
+ try {
+ ps.setObject(1, d , Types.DATE, -1);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where dateVal='"
+ + d.getTime() + "';");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ // this sub test doesn't pass on RI
+ query = "insert into type(BlobVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, "", Types.BLOB, 0);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setObject(1, "test text", Types.CHAR, Integer.MIN_VALUE);
+ fail("Exception not thrown");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setTime(int parameterIndex, Time x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setTime",
+ args = {int.class, java.sql.Time.class}
+ )
+ @KnownFailure("statment.close() does not wrap up")
+ public void testSetTimeint_Time() {
+
+ Time[] times = { new Time(24, 25, 26), new Time(Integer.MAX_VALUE),
+ new Time(123456789) };
+
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (timeVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ for (int i = 0; i < times.length; i++) {
+ try {
+ ps.setTime(1, times[i]);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where timeVal='"
+ + times[i].getTime() + "'");
+ ResultSet rs = st.getResultSet();
+ assertEquals(1, getCount(rs));
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ try {
+ ps.setTime(2, times[0]);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected index out of bounds
+ }
+
+ ps.close();
+
+ try {
+ ps.setTime(1, times[0]);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ String query1 = "insert into type (Tint) values (?)";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setTime(1, times[0]);
+ ps1.execute();
+
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setTime(int parameterIndex, Time x,
+ * Calendar cal)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setTime",
+ args = {int.class, java.sql.Time.class, java.util.Calendar.class}
+ )
+ @KnownFailure("preparedStatement.execute() does not return False on update.")
+ public void testSetTime_int_Time_Calendar() {
+
+ Calendar[] cals = { Calendar.getInstance(),
+ Calendar.getInstance(Locale.GERMANY),
+ Calendar.getInstance(TimeZone.getDefault()) };
+
+ Time[] times = { new Time(24, 25, 26), new Time(Integer.MAX_VALUE),
+ new Time(123456789) };
+
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (timeVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ for (int i = 0; i < times.length; i++) {
+ try {
+ ps.setTime(1, times[i], cals[i]);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ try {
+ ps.setTime(2, times[0], cals[0]);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+
+ ps.close();
+
+ try {
+ ps.setTime(-2, times[0], cals[1]);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setTime(1, times[0], cals[2]);
+ ps1.execute();
+
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setTimestamp(int parameterIndex,
+ * Timestamp x)
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setTimestamp",
+ args = {int.class, java.sql.Timestamp.class}
+ )
+ @KnownFailure("preparedStatement.execute() does not return false on update.")
+ public void testSetTimestamp_int_Timestamp() {
+
+ Timestamp[] timestamps = { new Timestamp(2007, 10, 17, 19, 06, 50, 23),
+ new Timestamp(123) };
+
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (TS) values (?);";
+ ps = conn.prepareStatement(query);
+
+ for (int i = 0; i < timestamps.length; i++) {
+ try {
+ ps.setTimestamp(1, timestamps[i]);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ }
+
+ try {
+ ps.setTimestamp(2, timestamps[0]);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+
+ try {
+ ps.setTimestamp(-2, timestamps[0]);
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setTimestamp(1, timestamps[0]);
+ ps1.execute();
+
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setBlob(int, java.sql.Blob)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setBlob",
+ args = {int.class, java.sql.Blob.class}
+ )
+ public void testSetBlob() {
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ Blob mock = new MockBlob();
+ try {
+ String neverExecutedQuery = "select TBlob from type;";
+ ps = conn.prepareStatement(neverExecutedQuery);
+ ps.setBlob(1,mock);
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setClob(int, java.sql.Clob)}
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setClob",
+ args = {int.class, java.sql.Clob.class}
+ )
+ public void testSetClob() {
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ Clob mock = new MockClob();
+ try {
+ String neverExecutedQuery = "select TBlob from type;";
+ ps = conn.prepareStatement(neverExecutedQuery);
+ ps.setClob(1,mock);
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setTimestamp(int, Timestamp, Calendar)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "setTimestamp",
+ args = {int.class, java.sql.Timestamp.class, java.util.Calendar.class}
+ )
+ @KnownFailure("preparedStatement.execute() does not return false on update.")
+ public void testSetTimestampIntTimestampCalendar() {
+ Calendar[] cals = { Calendar.getInstance(),
+ Calendar.getInstance(Locale.GERMANY),
+ Calendar.getInstance(TimeZone.getDefault()) };
+
+ Timestamp[] timestamps = { new Timestamp(2007, 10, 17, 19, 06, 50, 23),
+ new Timestamp(123) };
+
+
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (timeVal) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ for (int i = 0; i < timestamps.length; i++) {
+ try {
+ ps.setTimestamp(1, timestamps[i], cals[i]);
+ assertFalse(ps.execute());
+ assertTrue(ps.getUpdateCount() > 0);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ try {
+ ps.setTimestamp(2, timestamps[0], cals[0]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (Exception sqle) {
+ // expected
+ }
+ ps.close();
+ try {
+ ps.setTimestamp(1, timestamps[0], cals[1]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setTimestamp(1, timestamps[0], cals[2]);
+ ps1.execute();
+
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setURL(int, java.net.URL)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setURL",
+ args = {int.class, java.net.URL.class}
+ )
+ public void testSetURL() {
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (TText) values (?);";
+ ps = conn.prepareStatement(query);
+ ps.setURL(1, new URL("http://www.android.com"));
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ //ok
+ } catch (Exception e) {
+ fail("Error in test setup "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setArray(int, java.sql.Array)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setArray",
+ args = {int.class, java.sql.Array.class}
+ )
+ public void testSetArray() {
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ Array a = new MockArray();
+ try {
+ String query = "insert into type (TText) values (?);";
+ ps = conn.prepareStatement(query);
+ ps.setArray(1, new MockArray());
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ //ok
+ } catch (Exception e) {
+ fail("Error in test setup "+e.getMessage());
+ e.printStackTrace();
+ }
+
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setRef(int, java.sql.Ref)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setRef",
+ args = {int.class, java.sql.Ref.class}
+ )
+ public void testSetRef() {
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ Ref mock = new MockRef();
+ try {
+ String neverExecutedQuery = "select TBlob from type;";
+ ps = conn.prepareStatement(neverExecutedQuery);
+ ps.setRef(1,mock);
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setUnicodeStream(int, java.io.InputStream, int)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setUnicodeStream",
+ args = {int.class, java.io.InputStream.class, int.class}
+ )
+ public void testSetUnicodestream() {
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (TText) values (?);";
+ ps = conn.prepareStatement(query);
+ InputStream file = Class.forName(this.getClass().getName())
+ .getResourceAsStream("/blob.c");
+ ps.setUnicodeStream(0, file, 100);
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ //ok
+ } catch (Exception e) {
+ fail("Error in test setup "+e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setCharacterStream(int, java.io.Reader, int)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setCharacterStream",
+ args = {int.class, java.io.Reader.class, int.class}
+ )
+ public void testSetCharacterSteam() {
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (TText) values (?);";
+ ps = conn.prepareStatement(query);
+ InputStream file = Class.forName(this.getClass().getName())
+ .getResourceAsStream("/blob.c");
+ assertNotNull("Error in test setup: file not found",file);
+ Reader reader = new InputStreamReader(file);
+ ps.setCharacterStream(1, reader, 100);
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ // ok
+ } catch (Exception e) {
+ fail("Error in test setup "+e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setAsciiStream(int, InputStream, int)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setAsciiStream",
+ args = {int.class, java.io.InputStream.class, int.class}
+ )
+ public void testSetAxciiStream() {
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (TText) values (?);";
+ ps = conn.prepareStatement(query);
+ InputStream file = Class.forName(this.getClass().getName())
+ .getResourceAsStream("/blob.c");
+ ps.setAsciiStream(0, file, 100);
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ // ok
+ } catch (Exception e) {
+ fail("Error in test setup "+e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ /**
+ * @test {@link java.sql.PreparedStatement#setBinaryStream(int, InputStream, int)}
+ *
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not supported",
+ method = "setBinaryStream",
+ args = {int.class, java.io.InputStream.class, int.class}
+ )
+ public void testSetBinaryStream() {
+
+ ResultSet res = null;
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (TText) values (?);";
+ ps = conn.prepareStatement(query);
+ InputStream file = Class.forName(this.getClass().getName())
+ .getResourceAsStream("/blob.c");
+ ps.setBinaryStream(0, file, 100);
+ fail("Exception expected not supported");
+ } catch (SQLException e) {
+ // ok
+ } catch (Exception e) {
+ fail("Error in test setup "+e.getMessage());
+ e.printStackTrace();
+ }
+ }
+
+ private class MockRef implements Ref {
+
+ public String getBaseTypeName() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Object getObject() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Object getObject(Map> map) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public void setObject(Object value) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+ private class MockArray implements Array {
+
+ public Object getArray() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Object getArray(long index, int count) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Object getArray(long index, int count, Map> map)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Object getArray(Map> map) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int getBaseType() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public String getBaseTypeName() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public ResultSet getResultSet() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public ResultSet getResultSet(long index, int count)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public ResultSet getResultSet(long index, int count,
+ Map> map) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public ResultSet getResultSet(Map> map)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ }
+
+ private class MockBlob implements Blob {
+
+ public InputStream getBinaryStream() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public byte[] getBytes(long pos, int length) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public long length() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public long position(Blob pattern, long start) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public long position(byte[] pattern, long start) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public OutputStream setBinaryStream(long pos) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int setBytes(long pos, byte[] theBytes) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int setBytes(long pos, byte[] theBytes, int offset, int len)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public void truncate(long len) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+
+ private class MockClob implements Clob {
+
+ public InputStream getAsciiStream() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Reader getCharacterStream() throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public String getSubString(long pos, int length) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public long length() throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public long position(Clob searchstr, long start) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public long position(String searchstr, long start) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public OutputStream setAsciiStream(long pos) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public Writer setCharacterStream(long pos) throws SQLException {
+ // TODO Auto-generated method stub
+ return null;
+ }
+
+ public int setString(long pos, String str) throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public int setString(long pos, String str, int offset, int len)
+ throws SQLException {
+ // TODO Auto-generated method stub
+ return 0;
+ }
+
+ public void truncate(long len) throws SQLException {
+ // TODO Auto-generated method stub
+
+ }
+
+ }
+}
diff --git a/sql/src/test/java/tests/sql/RefTest.java b/sql/src/test/java/tests/sql/RefTest.java
new file mode 100644
index 0000000..6109623
--- /dev/null
+++ b/sql/src/test/java/tests/sql/RefTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package tests.sql;
+
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetClass;
+import dalvik.annotation.TestTargetNew;
+
+import junit.framework.TestCase;
+
+import java.sql.Ref;
+import java.util.Map;
+
+/**
+ * @author andrea@google.com (Your Name Here)
+ *
+ */
+@TestTargetClass(Ref.class)
+public class RefTest extends TestCase {
+
+ /**
+ * Test method for {@link java.sql.Ref#getBaseTypeName()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getBaseTypeName",
+ args = {}
+ )
+ public void testGetBaseTypeName() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Ref#getObject()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getObject",
+ args = {}
+ )
+ public void testGetObject() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Ref#getObject(java.util.Map)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "getObject",
+ args = {Map.class}
+ )
+ public void testGetObjectMapOfStringClassOfQ() {
+ fail("Not yet implemented");
+ }
+
+ /**
+ * Test method for {@link java.sql.Ref#setObject(java.lang.Object)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.NOT_FEASIBLE,
+ notes = "",
+ method = "setObject",
+ args = {Object.class}
+ )
+ public void testSetObject() {
+ fail("Not yet implemented");
+ }
+
+}
diff --git a/sql/src/test/java/tests/sql/ResultSetGetterTests.java b/sql/src/test/java/tests/sql/ResultSetGetterTests.java
new file mode 100644
index 0000000..302dbee
--- /dev/null
+++ b/sql/src/test/java/tests/sql/ResultSetGetterTests.java
@@ -0,0 +1,2190 @@
+/*
+ * Copyright (C) 2007 Google Inc.
+ *
+ * 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.
+ */
+
+package tests.sql;
+
+
+import dalvik.annotation.KnownFailure;
+import dalvik.annotation.TestTargets;
+import dalvik.annotation.TestLevel;
+import dalvik.annotation.TestTargetNew;
+import dalvik.annotation.TestTargetClass;
+
+
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.sql.DatabaseMetaData;
+import java.sql.Date;
+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.util.Arrays;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+
+/**
+ * Tests based on
+ * JDBC 1.0 API spec
+ * Table 1.0
+ */
+@TestTargetClass(ResultSet.class)
+public class ResultSetGetterTests extends SQLTest {
+
+ String queryAllSelect = "select * from type";
+
+ ResultSet res = null;
+
+ Statement st = null;
+
+ // Judgement concerning support is based on the result of ResultSet.getOject
+ // and Table 1 of JDBC 1.0 spec.
+ static boolean booleanSupported = false;
+ static boolean blobSupported = false;
+ static boolean bigIntSupported = false;
+ static boolean smallIntSupported = false;
+ static boolean mediumIntSupported = false;
+ static boolean realSupported = false;
+ static boolean floatSupported = false;
+ static boolean dateSupported = false;
+ static boolean timeSupported = false;
+ static boolean timeStampSupported = false;
+ static boolean dateTimeSupported = false;
+ static boolean urlSupported= false;
+ static boolean tinyIntSupported = false;
+ static boolean decimalSupported = false;
+ static boolean numericSupported = false;
+
+ static List colNames = Arrays.asList("BoolVal", "IntVal", "LongVal",
+ "Bint", "Tint", "Sint", "Mint", "IntegerVal", "RealVal",
+ "DoubleVal", "FloatVal", "DecVal", "NumVal", "charStr",
+ "dateVal", "timeVal", "TS", "DT", "TBlob", "BlobVal", "MBlob",
+ "LBlob", "TText", "TextVal", "MText", "LText", "MaxLongVal",
+ "MinLongVal", "validURL", "invalidURL");
+
+ static List values = Arrays.asList("1", "-1", "22", "2", "33",
+ "3","1","2","3.9","23.2","33.3","44",
+ "5", "test string", "1799-05-26", "12:35:45", "2007-10-09 14:28:02.0",
+ "1221-09-22 10:11:55","1","2","3","4","Test text message tiny",
+ "Test text", "Test text message medium",
+ "Test text message long");
+
+ static boolean[] supported = new boolean[]{
+ booleanSupported,
+ true,
+ true,
+ bigIntSupported,
+ tinyIntSupported,
+ smallIntSupported,
+ mediumIntSupported,
+ true,
+ realSupported,
+ true,
+ floatSupported,
+ decimalSupported,
+ numericSupported,
+ true,
+ dateSupported,
+ timeSupported,
+ timeStampSupported,
+ dateTimeSupported,
+ blobSupported,
+ blobSupported,
+ blobSupported,
+ blobSupported,
+ true,
+ true,
+ true,
+ true,
+ bigIntSupported,
+ bigIntSupported,
+ urlSupported,
+ urlSupported
+ };
+
+ // Not supported: BIT,VARBINARY, LONGVARBINARY, BINARY, VARCHAR, LONGVARCHAR
+ static Class[] typeMap = new Class[]{
+ java.lang.String.class, //
+ java.lang.Integer.class,//Types.INTEGER,
+ java.lang.Integer.class, //Types.LONG, not a JDBC 1.0 type
+ java.lang.Long.class, // Types.BIGINT,
+ java.lang.Byte.class, // Types.TINYINT,
+ java.lang.Short.class, // Types.SMALLINT,
+ java.lang.Integer.class, //Types.MEDIUMINT, , not a JDBC 1.0 type
+ java.lang.Integer.class, // Types.Integer
+ java.lang.Float.class, // Types.REAL,
+ java.lang.Double.class, // Types.FLOAT,
+ java.lang.Double.class, // Types.DOUBLE,
+ java.math.BigDecimal.class, // Types.DECIMAL,
+ java.math.BigDecimal.class, // Types.NUMERIC,
+ java.lang.String.class, // Types.CHAR
+ java.sql.Date.class, // Types.DATE,
+ java.sql.Time.class, // Types.TIME,
+ java.sql.Timestamp.class, // Types.TIMESTAMP,
+ java.sql.Date.class, // types datetime, not a JDBC 1.0 type
+ java.sql.Blob.class, // Types.BLOB, not a JDBC 1.0 type
+ java.sql.Blob.class, // Types.BLOB, not a JDBC 1.0 type
+ java.sql.Blob.class, // Types.BLOB, not a JDBC 1.0 type
+ java.sql.Blob.class, // Types.BLOB, not a JDBC 1.0 type
+ java.lang.String.class, // not a JDBC 1.0 type
+ java.lang.String.class, // not a JDBC 1.0 type
+ java.lang.String.class, // not a JDBC 1.0 type
+ java.lang.String.class, // not a JDBC 1.0 type
+ java.lang.Long.class, // Types.BIGINT,
+ java.lang.Long.class, // Types.BIGINT,
+ java.net.URL.class, // not a JDBC 1.0 type
+ java.net.URL.class // not a JDBC 1.0 type
+
+
+ };
+
+ // first inserted row : actual values
+ // second inserted row: null values
+ String[] queries = {
+ "create table type (" +
+
+ " BoolVal BOOLEAN," + " IntVal INT," + " LongVal LONG,"
+ + " Bint BIGINT," + " Tint TINYINT," + " Sint SMALLINT,"
+ + " Mint MEDIUMINT, " +
+
+ " IntegerVal INTEGER, " + " RealVal REAL, "
+ + " DoubleVal DOUBLE, " + " FloatVal FLOAT, "
+ + " DecVal DECIMAL, " +
+
+ " NumVal NUMERIC, " + " charStr CHAR(20), "
+ + " dateVal DATE, " + " timeVal TIME, " + " TS TIMESTAMP, "
+ +
+
+ " DT DATETIME, " + " TBlob TINYBLOB, " + " BlobVal BLOB, "
+ + " MBlob MEDIUMBLOB, " + " LBlob LONGBLOB, " +
+
+ " TText TINYTEXT, " + " TextVal TEXT, "
+ + " MText MEDIUMTEXT, " + " LText LONGTEXT, " +
+
+ " MaxLongVal BIGINT, MinLongVal BIGINT, "+
+
+ " validURL URL, invalidURL URL "+
+
+ ");"
+ ,
+
+ "insert into type (BoolVal, IntVal, LongVal, Bint, Tint, Sint, Mint,"
+ + "IntegerVal, RealVal, DoubleVal, FloatVal, DecVal,"
+ + "NumVal, charStr, dateVal, timeVal, TS,"
+ + "DT, TBlob, BlobVal, MBlob, LBlob,"
+ + "TText, TextVal, MText, LText, MaxLongVal, MinLongVal,"
+ + " validURL, invalidURL"
+ + ") "
+ + "values (1, -1, 22, 2, 33,"
+ + "3, 1, 2, 3.9, 23.2, 33.3, 44,"
+ + "5, 'test string', '1799-05-26', '12:35:45', '2007-10-09 14:28:02.0',"
+ + "'1221-09-22 10:11:55', 1, 2, 3, 4,"
+ + "'Test text message tiny', 'Test text',"
+ + " 'Test text message medium', 'Test text message long', "
+ + Long.MAX_VALUE+", "+Long.MIN_VALUE+", "
+ + "'http://www.android.com', 'helloWorld' "+
+ ");"
+ ,
+
+ "insert into type (BoolVal, IntVal, LongVal, Bint, Tint, Sint, Mint,"
+ + "IntegerVal, RealVal, DoubleVal, FloatVal, DecVal,"
+ + "NumVal, charStr, dateVal, timeVal, TS,"
+ + "DT, TBlob, BlobVal, MBlob, LBlob,"
+ + "TText, TextVal, MText, LText, MaxLongVal, MinLongVal,"
+ +" validURL, invalidURL"
+ + ") "
+ + "values (null, null, null, null, null,"
+ + "null, null, null, null, null, null, null,"
+ + "null, null, null, null, null,"
+ + "null, null, null, null, null,"
+ + "null, null, null, null,null, null, null, null);"
+ };
+
+ @Override
+ public void setUp() {
+ super.setUp();
+ try {
+ conn.setAutoCommit(false);
+ st = conn.createStatement();
+ for (int i = 0; i < queries.length; i++) {
+ st.execute(queries[i]);
+ }
+ res = st.executeQuery(queryAllSelect);
+ assertTrue(res.next());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+ }
+
+ public void tearDown() {
+ try {
+ st.execute("drop table if exists type");
+ st.close();
+ res.close();
+ } catch (SQLException e) {
+ fail("SQLException is thrown "+e.getMessage());
+ } finally {
+ try {
+ st.close();
+ res.close();
+ } catch (SQLException ee) {
+ }
+ }
+ super.tearDown();
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getBytes(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Exception testing",
+ method = "getBytes",
+ args = {int.class}
+ )
+ public void testGetBytesInt() {
+ int i = 1;
+
+
+ // null value
+ try {
+ i = 1;
+ res.next();
+ for (String t : values) {
+ assertNull(res.getBytes(i));
+ i++;
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.close();
+ res.getBytes(24);
+ fail("Should get Exception");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getBytes(int)}.
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "VARBINARY value",
+ method = "getBytes",
+ args = {int.class}
+ )
+ @KnownFailure("last assertion fails: invalid conversion. Test passes on RI")
+ public void testGetBytesIntVarbinary() throws SQLException {
+
+ Statement st = null;
+ Statement stQuery = null;
+ PreparedStatement stPrep = null;
+ ResultSet res = null;
+
+ // setup
+ try {
+ String testString = "HelloWorld";
+ st = conn.createStatement();
+ st.executeUpdate("create table testBinary (VARBINARY value);");
+ stPrep = conn
+ .prepareStatement("insert into testBinary values (?);");
+ stPrep.setBytes(1, testString.getBytes());
+ stPrep.execute();
+
+ stQuery = conn.createStatement();
+ res = stQuery.executeQuery("select * from testBinary");
+ try {
+ assertTrue(res.next());
+ byte[] output = res.getBytes(1);
+ String helloTest = new String(output);
+ assertNotNull(helloTest);
+ assertEquals(testString, helloTest);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ } finally {
+ if (res != null) res.close();
+ if (stPrep != null) stPrep.close();
+ if (st != null) st.close();
+ if (stQuery != null) stQuery.close();
+ }
+
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getBytes(int)}.
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "BINARY value",
+ method = "getBytes",
+ args = {int.class}
+ )
+ @KnownFailure("last assertion fails: invalid conversion. Test passes on RI")
+ public void testGetBytesIntBinary() throws SQLException {
+
+ Statement st = null;
+ Statement stQuery = null;
+ PreparedStatement stPrep = null;
+ ResultSet res = null;
+
+
+ // setup
+
+ String testString = "HelloWorld";
+ st = conn.createStatement();
+ st.executeUpdate("create table testBinary (BINARY value);");
+ stPrep = conn.prepareStatement("insert into testBinary values (?);");
+ stPrep.setBytes(1, testString.getBytes());
+ stPrep.execute();
+ try {
+ stQuery = conn.createStatement();
+ res = stQuery.executeQuery("select * from testBinary");
+ try {
+ assertTrue(res.next());
+ byte[] output = res.getBytes(1);
+ String helloTest = new String(output);
+ assertNotNull(helloTest);
+ assertEquals(testString, helloTest);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ } finally {
+ if (res != null) res.close();
+ if (stPrep != null) stPrep.close();
+ if (st != null) st.close();
+ if (stQuery != null) stQuery.close();
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getBytes(String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "Exception testing",
+ method = "getBytes",
+ args = {String.class}
+ )
+ public void testGetBytesString() {
+ int i = 1;
+
+ // null value
+ try {
+
+ res.next();
+ for (String t : colNames) {
+ assertNull(res.getBytes(t));
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.close();
+ res.getBytes(colNames.get(24));
+ fail("Should get Exception");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getBytes(int)}.
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "VARBINARY value",
+ method = "getBytes",
+ args = {String.class}
+ )
+ @KnownFailure("last assertion fails: invalid conversion. Test passes on RI")
+ public void testGetBytesStringVarbinary() throws SQLException {
+
+ Statement st = null;
+ Statement stQuery = null;
+ PreparedStatement stPrep = null;
+ ResultSet res = null;
+
+ // setup
+ try {
+ String testString = "HelloWorld";
+ st = conn.createStatement();
+ st.executeUpdate("create table testBinary (VARBINARY value);");
+ stPrep = conn
+ .prepareStatement("insert into testBinary values (?);");
+ stPrep.setBytes(1, testString.getBytes());
+ stPrep.execute();
+
+ stQuery = conn.createStatement();
+ res = stQuery.executeQuery("select value from testBinary");
+ try {
+ assertTrue(res.next());
+ byte[] output = res.getBytes("value");
+ String helloTest = new String(output);
+ assertNotNull(helloTest);
+ assertEquals(testString, helloTest);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ } finally {
+ if (res != null) res.close();
+ if (stPrep != null) stPrep.close();
+ if (st != null) st.close();
+ if (stQuery != null) stQuery.close();
+ }
+
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getBytes(int)}.
+ * @throws SQLException
+ */
+ @TestTargetNew(
+ level = TestLevel.PARTIAL_COMPLETE,
+ notes = "BINARY value",
+ method = "getBytes",
+ args = {String.class}
+ )
+ @KnownFailure("last assertion fails: invalid conversion. Test passes on RI")
+ public void testGetBytesStringBinary() throws SQLException {
+
+ Statement st = null;
+ Statement stQuery = null;
+ PreparedStatement stPrep = null;
+ ResultSet res = null;
+
+
+ // setup
+
+ String testString = "HelloWorld";
+ st = conn.createStatement();
+ st.executeUpdate("create table testBinary (BINARY value);");
+ stPrep = conn.prepareStatement("insert into testBinary values (?);");
+ stPrep.setBytes(1, testString.getBytes());
+ stPrep.execute();
+ try {
+ stQuery = conn.createStatement();
+ res = stQuery.executeQuery("select value from testBinary");
+ try {
+ assertTrue(res.next());
+ byte[] output = res.getBytes("value");
+ String helloTest = new String(output);
+ assertNotNull(helloTest);
+ assertEquals(testString, helloTest);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ } finally {
+ if (res != null) res.close();
+ if (stPrep != null) stPrep.close();
+ if (st != null) st.close();
+ if (stQuery != null) stQuery.close();
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getConcurrency()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Not fully supported: CONCUR_UPDATABLE not supported",
+ method = "getConcurrency",
+ args = {}
+ )
+ public void testGetConcurrency() {
+ try {
+ assertEquals(ResultSet.CONCUR_READ_ONLY, res.getConcurrency());
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getDate(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDate",
+ args = {int.class}
+ )
+ public void testGetDateInt() {
+ try {
+
+ GregorianCalendar testCal = new GregorianCalendar(1799, Calendar.MAY, 26, 0, 0);
+ Date input = new Date(testCal.getTimeInMillis());
+ Date d = res.getDate(15);
+ assertEquals(input.toString(),"1799-05-26");
+ assertEquals(input,d);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ try {
+ Date d = res.getDate(500);
+ fail("Should get exception");
+ } catch (SQLException e) {
+ //ok
+ } catch (Exception e) {
+ fail("Got unspecified Exception "+ e.getMessage());
+ }
+
+ // null value
+ try {
+ assertTrue(res.next());
+ Date d = res.getDate(15);
+ assertNull(d);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getDate(int, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Not fully supported",
+ method = "getDate",
+ args = {int.class, java.util.Calendar.class}
+ )
+ public void testGetDateIntCalendar() {
+ GregorianCalendar testCal = new GregorianCalendar(1799, Calendar.MAY, 26, 0, 0);
+ try {
+
+ Date input = new Date(testCal.getTimeInMillis());
+ Date d = res.getDate(15, testCal);
+
+ assertEquals(input.toString(),"1799-05-26");
+ assertEquals(input,d);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ try {
+ Date d = res.getDate(500, testCal);
+ fail("Should get exception");
+ } catch (SQLException e) {
+ //ok
+ } catch (Exception e) {
+ fail("Got unspecified Exception "+ e.getMessage());
+ }
+
+
+ // null value
+ try {
+ assertTrue(res.next());
+ Date d = res.getDate(15,testCal);
+ assertNull(d);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getDate(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Not fully supported",
+ method = "getDate",
+ args = {java.lang.String.class}
+ )
+ public void testGetDateString() {
+ try {
+ GregorianCalendar testCal = new GregorianCalendar(1799, Calendar.MAY, 26, 0, 0);
+ Date input = new Date(testCal.getTimeInMillis());
+ Date d = res.getDate("dateVal");
+ assertEquals(input.toString(),"1799-05-26");
+ assertEquals(input,d);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ try {
+ Date d = res.getDate("bla");
+ fail("Should get exception");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ // null value
+ try {
+ assertTrue(res.next());
+ Date d = res.getDate("dateVal");
+ assertNull(d);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getDate(java.lang.String, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDate",
+ args = {java.lang.String.class, java.util.Calendar.class}
+ )
+ public void testGetDateStringCalendar() {
+ GregorianCalendar testCal = new GregorianCalendar(1799, Calendar.MAY, 26, 0, 0);
+ try {
+ Date input = new Date(testCal.getTimeInMillis());
+ Date d = res.getDate("dateVal", testCal);
+
+ assertEquals(input.toString(),"1799-05-26");
+ assertEquals(input,d);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ try {
+ Date d = res.getDate("bla", testCal);
+ fail("Should get exception");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ // null value
+ try {
+ assertTrue(res.next());
+ Date d = res.getDate("dateVal",testCal);
+ assertNull(d);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getDouble(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getDouble",
+ args = {int.class}
+ )
+ public void testGetDoubleInt() {
+
+ double output = 0.0;
+ try {
+ double[] input = {2.0, 3.9 , 23.2};
+
+ output = res.getDouble(8);
+ assertEquals(input[0],output);
+
+ output = res.getDouble(9);
+ assertEquals(input[1],output);
+
+ output = res.getDouble(10);
+ assertEquals(input[2],output);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getDouble(500);
+ } catch (SQLException e) {
+ //ok
+ }
+
+ // null value
+ try {
+ res.next();
+ output = res.getDouble(8);
+ assertEquals(0.0,output);
+
+ output = res.getDouble(9);
+ assertEquals(0.0,output);
+
+ output = res.getDouble(10);
+ assertEquals(0.0,output);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getDouble(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Not fully supported: eg. getDouble from TinyInt ",
+ method = "getDouble",
+ args = {java.lang.String.class}
+ )
+ public void testGetDoubleString() {
+ double input = 23.2;
+ double output = 0.0;
+
+ try{
+ output = res.getDouble("DoubleVal");
+ assertEquals (input,output);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try{
+ output = res.getDouble("bla");
+ fail("Exception expected");
+ } catch (SQLException e) {
+ // ok
+ }
+
+ // null value
+ try{
+ assertTrue(res.next());
+ output = res.getDouble("DoubleVal");
+ assertEquals (0.0 , output);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getFloat(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Not fully supported: eg.: getFloat from TinyInt according to JDBC 1.0 spec",
+ method = "getFloat",
+ args = {int.class}
+ )
+ public void testGetFloatInt() {
+ float defaultF = 0.0f;
+ try {
+ float[] input = {3.9f, 23.2f, 33.3f};
+
+
+ float output = res.getFloat(9);
+ assertEquals(input[0], output);
+
+ output = res.getFloat(10);
+ assertEquals(input[1], output);
+
+ output = res.getFloat(11);
+ assertEquals(input[2], output);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getFloat(500);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ try {
+ res.next();
+ float output = res.getFloat(8);
+ assertEquals(defaultF, output);
+
+ output = res.getFloat(9);
+ assertEquals(defaultF, output);
+
+ output = res.getFloat(10);
+ assertEquals(defaultF, output);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getFloat(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "Not fully supported",
+ method = "getFloat",
+ args = {java.lang.String.class}
+ )
+ public void testGetFloatString() {
+ float defaultF = 0.0f;
+ try {
+ String[] input = {"RealVal", "DoubleVal", "FloatVal"};
+ float[] inputF = {3.9f, 23.2f, 33.3f};
+
+
+ float output = res.getFloat(input[0]);
+ assertEquals(inputF[0], output);
+
+ output = res.getFloat(input[1]);
+ assertEquals(inputF[1], output);
+
+ output = res.getFloat(input[2]);
+ assertEquals(inputF[2], output);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getFloat(500);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ try {
+ res.next();
+ float output = res.getFloat(8);
+ assertEquals(defaultF, output);
+
+ output = res.getFloat(9);
+ assertEquals(defaultF, output);
+
+ output = res.getFloat(10);
+ assertEquals(defaultF, output);
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getInt(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getInt",
+ args = {int.class}
+ )
+ public void testGetIntInt() {
+
+ // real input val -1, 22, 2, 33,3, 1, 2
+ List input = Arrays.asList(1, -1, 22, 2, 33,3, 1, 2);
+ ListIterator it = input.listIterator();
+ Double test2 = new Double(23.2);
+ try {
+ for (int i = 1;i<9;i++ ) {
+ assertEquals(it.next().intValue(),res.getInt(i));
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getInt(500);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ try {
+ res.next();
+ for (int i = 2;i<11;i++ ) {
+ assertEquals(0,res.getInt(i));
+ }
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getInt(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getInt",
+ args = {java.lang.String.class}
+ )
+ public void testGetIntString() {
+ List inputS = Arrays.asList("BoolVal", "IntVal", "LongVal",
+ "Bint", "Tint", "Sint", "Mint", "IntegerVal");
+ ListIterator itS = inputS.listIterator();
+ List input = Arrays.asList(1, -1, 22, 2, 33, 3, 1, 2);
+ ListIterator it = input.listIterator();
+ try {
+ while (it.hasNext()) {
+ assertEquals(it.next().intValue(), res.getInt(itS.next()));
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getInt("bla");
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ try {
+ res.next();
+ for (String s : inputS) {
+ assertEquals(0, res.getInt(s));
+ }
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getLong(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getLong",
+ args = {int.class}
+ )
+ public void testGetLongInt() {
+ long maxVal = Long.MAX_VALUE;
+ long minVal = Long.MIN_VALUE;
+
+ try {
+ assertEquals(maxVal, res.getLong(27));
+ assertEquals(minVal, res.getLong(28));
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getInt(500);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ try {
+ res.next();
+
+ assertEquals(0,res.getLong(27));
+ assertEquals(0,res.getLong(28));
+
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getLong(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getLong",
+ args = {java.lang.String.class}
+ )
+ public void testGetLongString() {
+ long maxVal = Long.MAX_VALUE;
+ long minVal = Long.MIN_VALUE;
+
+ try {
+ assertEquals(maxVal, res.getLong("MaxLongVal"));
+ assertEquals(minVal, res.getLong("MinLongVal"));
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getInt("bla");
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ try {
+ res.next();
+
+ assertEquals(0,res.getLong("MaxLongVal"));
+ assertEquals(0,res.getLong("MinLongVal"));
+
+
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getMetaData()}.
+ * type mappings according to
+ * http://java.sun.com/j2se/1.3/docs/guide/jdbc/spec/jdbc-spec.frame8.html
+ * Not supported datatypes are not checked.
+ */
+ @TestTargets({
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "checks supported data types ,not supported types are not checked.",
+ method = "getMetaData",
+ args = {}
+ )
+ })
+ public void testGetMetaData() {
+ /*
+ * List types = Arrays.asList("BOOLEAN", "INT", "LONG",
+ * "BIGINT", "TINYINT", "SMALLINT", "MEDIUMINT", "INTEGER", "REAL",
+ * "DOUBLE", "FLOAT", "DECIMAL", "NUMERIC", "CHAR(20)", "DATE", "TIME",
+ * "TIMESTAMP", "DATETIME", "TINYBLOB", "BLOB", "MEDIUMBLOB",
+ * "LONGBLOB", "TINYTEXT", "TEXT", "MEDIUMTEXT", "LONGTEXT", "BIGINT",
+ * "BIGINT","URL","URL");
+ */
+ List types = Arrays.asList("VARCHAR", "INTEGER", "INTEGER",
+ "BIGINT", "SMALLINT", "SHORT", "INTEGER", "INTEGER", "FLOAT",
+ "DOUBLE", "DOUBLE", "DECIMAL", "NUMERIC", "VARCHAR", "DATE",
+ "TIME", "TIMESTAMP", "DATETIME", "BLOB", "BLOB", "BLOB",
+ "BLOB", "VARCHAR", "VARCHAR", "VARCHAR", "VARCHAR", "BIGINT",
+ "BIGINT", "URL", "URL");
+
+
+
+ ListIterator it = types.listIterator();
+ ListIterator colNameIt = colNames.listIterator();
+ try {
+ ResultSetMetaData meta = res.getMetaData();
+ assertNotNull(meta);
+ assertEquals("Error in test setup. Columns do not match", types
+ .size(), meta.getColumnCount());
+ for (int i = 1; i < 31; i++) {
+ String colName = colNameIt.next();
+ String type = it.next();
+ if (supported[i - 1]) {
+ assertTrue("Wrong column name at " + i, colName
+ .equalsIgnoreCase(meta.getColumnName(i)));
+ assertTrue("Wrong type at " + i, type.equalsIgnoreCase(meta
+ .getColumnTypeName(i)));
+ }
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getObject(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.SUFFICIENT,
+ notes = "not supported types BIT,VARBINARY, LONGVARBINARY, BINARY, VARCHAR, LONGVARCHAR",
+ method = "getObject",
+ args = {int.class}
+ )
+ public void testGetObjectInt() {
+
+ try {
+ for (int i = 1; i <= typeMap.length; i++) {
+ if (supported[i-1]) {
+ Object value = res.getObject(i);
+ assertTrue("value " + value.getClass().getName()
+ + " does not correspond " + typeMap[i-1] + "at "+i, value
+ .getClass().equals(typeMap[i-1]));
+ }
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getObject(500);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ try {
+ res.next();
+ for (int i = 1; i <= typeMap.length; i++) {
+ Object value = res.getObject(i);
+ assertNull(value);
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+
+ }
+
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getObject(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "not fully supported",
+ method = "getObject",
+ args = {java.lang.String.class}
+ )
+ public void testGetObjectString() {
+ ListIterator colNameIt = colNames.listIterator();
+ try {
+ for (int i = 1; i <= typeMap.length; i++) {
+ String name = colNameIt.next();
+ if (supported[i-1]) {
+ Object value = res.getObject(name);
+ assertTrue("value " + value.getClass().getName()
+ + " does not correspond " + typeMap[i-1] + "at "+i, value
+ .getClass().equals(typeMap[i-1]));
+ }
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getObject("bla");
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+
+ try {
+ colNameIt = colNames.listIterator();
+ res.next();
+ for (int i = 1; i <= typeMap.length; i++) {
+ Object value = res.getObject(colNameIt.next());
+ assertNull(value);
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ }
+
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getRow()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "Exception testing missed, test fails. According to spec afterlast row is 0 but returns 3",
+ method = "getRow",
+ args = {}
+ )
+ @KnownFailure("If there is no current row 0 must be returned. res.close() does not wrap up")
+ public void testGetRow() {
+ try {
+ assertEquals(1, res.getRow());
+ assertTrue(res.isFirst());
+ res.next();
+ assertEquals(2, res.getRow());
+ assertTrue(res.isLast());
+ res.next();
+ assertTrue(res.isAfterLast());
+ assertEquals(0, res.getRow());
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.close();
+ res.getRow();
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getShort(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getShort",
+ args = {int.class}
+ )
+ public void testGetShortInt() {
+ try {
+ short shorty = res.getShort(6);
+ assertEquals(3,shorty);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.next();
+ short shorty = res.getShort(6);
+ assertEquals(0,shorty);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+
+ try {
+ res.getShort(500);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getShort(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getShort",
+ args = {java.lang.String.class}
+ )
+ public void testGetShortString() {
+ try {
+ short shorty = res.getShort("Sint");
+ assertEquals(3,shorty);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.next();
+ short shorty = res.getShort("Sint");
+ assertEquals(0,shorty);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+
+ try {
+ res.getShort("bla");
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getStatement()}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "test fails. According to spec info.getStatement should return"+
+ " null but an exception is thrown: stale result set.",
+ method = "getStatement",
+ args = {}
+ )
+ @KnownFailure("According to spec info.getStatement should return null"+
+ " but an exception is thrown: stale result set.")
+ public void testGetStatement() {
+ try {
+ DatabaseMetaData meta = conn.getMetaData();
+ ResultSet info = meta.getTypeInfo();
+ Statement statement2 = info.getStatement();
+ assertNull(statement2);
+ } catch(SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ Statement statement2 = res.getStatement();
+ assertEquals(st, statement2);
+ } catch(SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ // exception testing
+ try {
+ res.close();
+ res.getStatement();
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getString(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getString",
+ args = {int.class}
+ )
+ public void testGetStringInt() {
+ List texts = Arrays.asList("Test text message tiny",
+ "Test text", "Test text message medium",
+ "Test text message long");
+ int i = 23;
+
+ //text and exception testing
+ try {
+ for (String t : texts) {
+ assertEquals(t, res.getString(i));
+ i++;
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ // the rest: everything should work with getString
+
+ texts = Arrays.asList("1", "-1", "22", "2", "33",
+ "3","1","2","3.9","23.2","33.3","44",
+ "5", "test string", "1799-05-26", "12:35:45", "2007-10-09 14:28:02.0",
+ "1221-09-22 10:11:55","1","2","3","4");
+ i= 1;
+
+ try {
+ for (String t : texts) {
+ assertEquals(t, res.getString(i));
+ i++;
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ //null testing
+
+ try {
+ i = 1;
+ res.next();
+ for (String t : values) {
+ assertNull(res.getString(i));
+ i++;
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ // exception testing
+ try {
+ res.getString(500);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getString(java.lang.String)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "exception test missed",
+ method = "getString",
+ args = {java.lang.String.class}
+ )
+ public void testGetStringString() {
+
+ ListIterator colNameIt = colNames.listIterator();
+ try {
+ for (String t : values) {
+ assertEquals(t, res.getString(colNameIt.next()));
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.next();
+
+ for (String name: colNames) {
+ assertNull(res.getString(name));
+ }
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getString("bla");
+ fail("Exception expected");
+ } catch (SQLException e) {
+ //ok
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getTime(int)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getTime",
+ args = {int.class}
+ )
+ @KnownFailure("getTime should return Time value for a TIMESTAMP type but returns null")
+ public void testGetTimeInt() {
+ // values "12:35:45", "2007-10-09 14:28:02.0", "1221-09-22 10:11:55"
+
+ Calendar cal = new GregorianCalendar();
+ cal.clear();
+ cal.set(Calendar.HOUR_OF_DAY, 12);
+ cal.set(Calendar.MINUTE, 35);
+ cal.set(Calendar.SECOND, 45);
+ cal.set(Calendar.MILLISECOND, 0);
+ // set with calendar value (correct init time: since epoch)
+ long millis = cal.getTime().getTime();
+ Time t1 = new java.sql.Time(millis);
+ assertNotNull("t1", t1);
+
+
+ Calendar cal2 = new GregorianCalendar();
+ cal2.set(Calendar.YEAR, 2007);
+ cal2.set(Calendar.MONTH, Calendar.OCTOBER);
+ cal2.set(Calendar.DATE, 9);
+ cal2.set(Calendar.HOUR_OF_DAY, 14);
+ cal2.set(Calendar.MINUTE, 28);
+ cal2.set(Calendar.SECOND, 02);
+ cal2.set(Calendar.MILLISECOND, 0);
+
+ long millis2 = cal2.getTime().getTime();
+ Time t2 = new java.sql.Time(millis2);
+
+ int i = 16;
+
+ try {
+ Time resTime = res.getTime(i);
+ assertNotNull("Pos " + i + " null", resTime);
+ assertEquals(t1.toString(), resTime.toString());
+ assertEquals(t1.getTime(), resTime.getTime());
+ assertEquals(t1, resTime);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+ // Compatibility Test: TIMESTAMP value
+ i = 17;
+
+ try {
+ Time resTime = res.getTime(i);
+ assertNotNull("Pos " + i + " null", resTime);
+ assertEquals(t2.toString(), resTime.toString());
+ assertEquals(t2.getTime(), resTime.getTime());
+ assertEquals(t2, resTime);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ i = 16;
+ res.next();
+ assertNull(res.getTime(i));
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ }
+
+ try {
+ res.getTime(500);
+ fail("Exception expected");
+ } catch (SQLException e) {
+ // ok
+ }
+ }
+
+ /**
+ * Test method for {@link java.sql.ResultSet#getTime(int, java.util.Calendar)}.
+ */
+ @TestTargetNew(
+ level = TestLevel.COMPLETE,
+ notes = "",
+ method = "getTime",
+ args = {int.class, java.util.Calendar.class}
+ )
+ @KnownFailure("getTime on TIMESTAMP value fails: returns null")
+ public void testGetTimeIntCalendar() {
+ List