summaryrefslogtreecommitdiffstats
path: root/sql
diff options
context:
space:
mode:
Diffstat (limited to 'sql')
-rw-r--r--sql/MODULE_LICENSE_APACHE20
-rw-r--r--sql/MODULE_LICENSE_BSD_LIKE0
-rw-r--r--sql/src/main/java/SQLite/Authorizer.java25
-rw-r--r--sql/src/main/java/SQLite/Blob.java323
-rw-r--r--sql/src/main/java/SQLite/BusyHandler.java20
-rw-r--r--sql/src/main/java/SQLite/Callback.java68
-rw-r--r--sql/src/main/java/SQLite/Constants.java157
-rw-r--r--sql/src/main/java/SQLite/Database.java615
-rw-r--r--sql/src/main/java/SQLite/Exception.java18
-rw-r--r--sql/src/main/java/SQLite/Function.java59
-rw-r--r--sql/src/main/java/SQLite/FunctionContext.java82
-rw-r--r--sql/src/main/java/SQLite/JDBC2y/JDBCConnection.java452
-rw-r--r--sql/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java1578
-rw-r--r--sql/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java752
-rw-r--r--sql/src/main/java/SQLite/JDBC2y/JDBCResultSet.java932
-rw-r--r--sql/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java212
-rw-r--r--sql/src/main/java/SQLite/JDBC2y/JDBCStatement.java287
-rw-r--r--sql/src/main/java/SQLite/JDBC2y/TableResultX.java37
-rw-r--r--sql/src/main/java/SQLite/JDBCDriver.java109
-rw-r--r--sql/src/main/java/SQLite/ProgressHandler.java17
-rw-r--r--sql/src/main/java/SQLite/Shell.java669
-rw-r--r--sql/src/main/java/SQLite/Stmt.java288
-rw-r--r--sql/src/main/java/SQLite/StringEncoder.java201
-rw-r--r--sql/src/main/java/SQLite/TableResult.java133
-rw-r--r--sql/src/main/java/SQLite/Trace.java17
-rw-r--r--sql/src/main/java/SQLite/Vm.java78
-rw-r--r--sql/src/main/java/java/sql/Array.java133
-rw-r--r--sql/src/main/java/java/sql/BatchUpdateException.java147
-rw-r--r--sql/src/main/java/java/sql/Blob.java160
-rw-r--r--sql/src/main/java/java/sql/CallableStatement.java1302
-rw-r--r--sql/src/main/java/java/sql/Clob.java174
-rw-r--r--sql/src/main/java/java/sql/Connection.java759
-rw-r--r--sql/src/main/java/java/sql/DataTruncation.java126
-rw-r--r--sql/src/main/java/java/sql/DatabaseMetaData.java3081
-rw-r--r--sql/src/main/java/java/sql/Date.java233
-rw-r--r--sql/src/main/java/java/sql/Driver.java113
-rw-r--r--sql/src/main/java/java/sql/DriverManager.java433
-rw-r--r--sql/src/main/java/java/sql/DriverPropertyInfo.java72
-rw-r--r--sql/src/main/java/java/sql/ParameterMetaData.java183
-rw-r--r--sql/src/main/java/java/sql/PreparedStatement.java631
-rw-r--r--sql/src/main/java/java/sql/Ref.java79
-rw-r--r--sql/src/main/java/java/sql/ResultSet.java1870
-rw-r--r--sql/src/main/java/java/sql/ResultSetMetaData.java277
-rw-r--r--sql/src/main/java/java/sql/SQLData.java106
-rw-r--r--sql/src/main/java/java/sql/SQLException.java153
-rw-r--r--sql/src/main/java/java/sql/SQLInput.java280
-rw-r--r--sql/src/main/java/java/sql/SQLOutput.java280
-rw-r--r--sql/src/main/java/java/sql/SQLPermission.java60
-rw-r--r--sql/src/main/java/java/sql/SQLWarning.java103
-rw-r--r--sql/src/main/java/java/sql/Savepoint.java43
-rw-r--r--sql/src/main/java/java/sql/Statement.java620
-rw-r--r--sql/src/main/java/java/sql/Struct.java66
-rw-r--r--sql/src/main/java/java/sql/Time.java221
-rw-r--r--sql/src/main/java/java/sql/Timestamp.java478
-rw-r--r--sql/src/main/java/java/sql/Types.java184
-rw-r--r--sql/src/main/java/java/sql/package.html7
-rw-r--r--sql/src/main/java/javax/sql/ConnectionEvent.java72
-rw-r--r--sql/src/main/java/javax/sql/ConnectionEventListener.java59
-rw-r--r--sql/src/main/java/javax/sql/ConnectionPoolDataSource.java123
-rw-r--r--sql/src/main/java/javax/sql/DataSource.java138
-rw-r--r--sql/src/main/java/javax/sql/PooledConnection.java111
-rw-r--r--sql/src/main/java/javax/sql/RowSet.java856
-rw-r--r--sql/src/main/java/javax/sql/RowSetEvent.java53
-rw-r--r--sql/src/main/java/javax/sql/RowSetInternal.java86
-rw-r--r--sql/src/main/java/javax/sql/RowSetListener.java62
-rw-r--r--sql/src/main/java/javax/sql/RowSetMetaData.java283
-rw-r--r--sql/src/main/java/javax/sql/RowSetReader.java50
-rw-r--r--sql/src/main/java/javax/sql/RowSetWriter.java52
-rw-r--r--sql/src/main/java/javax/sql/package.html8
-rw-r--r--sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java124
-rw-r--r--sql/src/main/java/org/apache/harmony/sql/internal/nls/messages.properties42
-rw-r--r--sql/src/main/native/sqlite_jni.c4398
-rw-r--r--sql/src/main/native/sqlite_jni.h657
-rw-r--r--sql/src/main/native/sqlite_jni_defs.h39
-rw-r--r--sql/src/main/native/sqlite_jni_registration.c308
-rw-r--r--sql/src/main/native/sub.mk19
-rw-r--r--sql/src/test/java/SQLite/JDBCDriverTest.java86
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/AllTests.java57
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.java384
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ConnectionTest.java89
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.java501
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.java119
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java380
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java582
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverPropertyInfoTest.java107
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ParameterMetaDataTest.java94
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetMetaDataTest.java84
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetTest.java101
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.java541
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLPermissionTest.java74
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.java398
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/StatementTest.java92
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_ClassLoader.java219
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Connection1.java176
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver1.java116
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver2.java50
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver3.java36
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver4.java129
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_Driver5.java44
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_DriverManager.java113
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimeTest.java304
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java624
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TypesTest.java101
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/AllTests.java42
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java57
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_PooledConnection.java38
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/Impl_RowSet.java738
-rw-r--r--sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.java36
-rw-r--r--sql/src/test/java/tests/java/sql/AllTests.java48
-rwxr-xr-xsql/src/test/java/tests/java/sql/DatabaseMetaDataTest.java2191
-rwxr-xr-xsql/src/test/java/tests/java/sql/DeleteFunctionalityTest.java219
-rwxr-xr-xsql/src/test/java/tests/java/sql/InsertFunctionalityTest.java250
-rwxr-xr-xsql/src/test/java/tests/java/sql/MultiThreadAccessTest.java445
-rwxr-xr-xsql/src/test/java/tests/java/sql/SelectFunctionalityTest.java542
-rwxr-xr-xsql/src/test/java/tests/java/sql/StressTest.java310
-rwxr-xr-xsql/src/test/java/tests/java/sql/UpdateFunctionalityTest.java365
-rwxr-xr-xsql/src/test/java/tests/java/sql/UpdateFunctionalityTest2.java296
-rw-r--r--sql/src/test/java/tests/sql/AbstractSqlTest.java212
-rw-r--r--sql/src/test/java/tests/sql/AllTests.java46
-rwxr-xr-xsql/src/test/java/tests/sql/ConnectionTest.java1958
-rwxr-xr-xsql/src/test/java/tests/sql/PreparedStatementTest.java2473
-rwxr-xr-xsql/src/test/java/tests/sql/ResultSetMetaDataTest.java252
-rwxr-xr-xsql/src/test/java/tests/sql/SQLTest.java123
-rwxr-xr-xsql/src/test/java/tests/sql/StatementTest.java955
-rwxr-xr-xsql/src/test/java/tests/support/DatabaseCreator.java401
-rw-r--r--sql/src/test/java/tests/support/Support_SQL.java90
-rw-r--r--sql/src/test/java/tests/support/ThreadPool.java116
-rw-r--r--sql/src/test/resources/connection.properties9
-rw-r--r--sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.golden.serbin0 -> 1724 bytes
-rw-r--r--sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.golden.serbin0 -> 1754 bytes
-rw-r--r--sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.golden.serbin0 -> 2716 bytes
-rw-r--r--sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.golden.serbin0 -> 2146 bytes
-rw-r--r--sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/TimestampTest.golden.serbin0 -> 91 bytes
-rw-r--r--sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.golden.serbin0 -> 2229 bytes
-rw-r--r--sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/rowset/RowSetMetaDataImplTest.golden.serbin0 -> 671 bytes
-rw-r--r--sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/rowset/serial/SerialExceptionTest.golden.serbin0 -> 1661 bytes
136 files changed, 44856 insertions, 0 deletions
diff --git a/sql/MODULE_LICENSE_APACHE2 b/sql/MODULE_LICENSE_APACHE2
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sql/MODULE_LICENSE_APACHE2
diff --git a/sql/MODULE_LICENSE_BSD_LIKE b/sql/MODULE_LICENSE_BSD_LIKE
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/sql/MODULE_LICENSE_BSD_LIKE
diff --git a/sql/src/main/java/SQLite/Authorizer.java b/sql/src/main/java/SQLite/Authorizer.java
new file mode 100644
index 0000000..cdc321d
--- /dev/null
+++ b/sql/src/main/java/SQLite/Authorizer.java
@@ -0,0 +1,25 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's authorizer function.
+ */
+
+public interface Authorizer {
+
+ /**
+ * Callback to authorize access.
+ *
+ * @param what integer indicating type of access
+ * @param arg1 first argument (table, view, index, or trigger name)
+ * @param arg2 second argument (file, table, or column name)
+ * @param arg3 third argument (database name)
+ * @param arg4 third argument (trigger name)
+ * @return Constants.SQLITE_OK for success, Constants.SQLITE_IGNORE
+ * for don't allow access but don't raise an error, Constants.SQLITE_DENY
+ * for abort SQL statement with error.
+ */
+
+ public int authorize(int what, String arg1, String arg2, String arg3,
+ String arg4);
+}
+
diff --git a/sql/src/main/java/SQLite/Blob.java b/sql/src/main/java/SQLite/Blob.java
new file mode 100644
index 0000000..3de9f8a
--- /dev/null
+++ b/sql/src/main/java/SQLite/Blob.java
@@ -0,0 +1,323 @@
+package SQLite;
+
+import java.io.*;
+
+/**
+ * Internal class implementing java.io.InputStream on
+ * SQLite 3.4.0 incremental blob I/O interface.
+ */
+
+class BlobR extends InputStream {
+
+ /**
+ * Blob instance
+ */
+
+ private Blob blob;
+
+ /**
+ * Read position, file pointer.
+ */
+
+ private int pos;
+
+ /**
+ * Contruct InputStream from blob instance.
+ */
+
+ BlobR(Blob blob) {
+ this.blob = blob;
+ this.pos = 0;
+ }
+
+ /**
+ * Return number of available bytes for reading.
+ * @return available input bytes
+ */
+
+ public int available() throws IOException {
+ int ret = blob.size - pos;
+ return (ret < 0) ? 0 : ret;
+ }
+
+ /**
+ * Mark method; dummy to satisfy InputStream class.
+ */
+
+ public void mark(int limit) {
+ }
+
+ /**
+ * Reset method; dummy to satisfy InputStream class.
+ */
+
+ public void reset() throws IOException {
+ }
+
+ /**
+ * Mark support; not for this class.
+ * @return always false
+ */
+
+ public boolean markSupported() {
+ return false;
+ }
+
+ /**
+ * Close this blob InputStream.
+ */
+
+ public void close() throws IOException {
+ blob.close();
+ blob = null;
+ pos = 0;
+ }
+
+ /**
+ * Skip over blob data.
+ */
+
+ public long skip(long n) throws IOException {
+ long ret = pos + n;
+ if (ret < 0) {
+ ret = 0;
+ pos = 0;
+ } else if (ret > blob.size) {
+ ret = blob.size;
+ pos = blob.size;
+ } else {
+ pos = (int) ret;
+ }
+ return ret;
+ }
+
+ /**
+ * Read single byte from blob.
+ * @return byte read
+ */
+
+ public int read() throws IOException {
+ byte b[] = new byte[1];
+ int n = blob.read(b, 0, pos, b.length);
+ if (n > 0) {
+ pos += n;
+ return b[0];
+ }
+ return -1;
+ }
+
+ /**
+ * Read byte array from blob.
+ * @param b byte array to be filled
+ * @return number of bytes read
+ */
+
+ public int read(byte b[]) throws IOException {
+ int n = blob.read(b, 0, pos, b.length);
+ if (n > 0) {
+ pos += n;
+ return n;
+ }
+ return -1;
+ }
+
+ /**
+ * Read slice of byte array from blob.
+ * @param b byte array to be filled
+ * @param off offset into byte array
+ * @param len length to be read
+ * @return number of bytes read
+ */
+
+ public int read(byte b[], int off, int len) throws IOException {
+ if (off + len > b.length) {
+ len = b.length - off;
+ }
+ if (len < 0) {
+ return -1;
+ }
+ if (len == 0) {
+ return 0;
+ }
+ int n = blob.read(b, off, pos, len);
+ if (n > 0) {
+ pos += n;
+ return n;
+ }
+ return -1;
+ }
+}
+
+/**
+ * Internal class implementing java.io.OutputStream on
+ * SQLite 3.4.0 incremental blob I/O interface.
+ */
+
+class BlobW extends OutputStream {
+
+ /**
+ * Blob instance
+ */
+
+ private Blob blob;
+
+ /**
+ * Read position, file pointer.
+ */
+
+ private int pos;
+
+ /**
+ * Contruct OutputStream from blob instance.
+ */
+
+ BlobW(Blob blob) {
+ this.blob = blob;
+ this.pos = 0;
+ }
+
+ /**
+ * Flush blob; dummy to satisfy OutputStream class.
+ */
+
+ public void flush() throws IOException {
+ }
+
+ /**
+ * Close this blob OutputStream.
+ */
+
+ public void close() throws IOException {
+ blob.close();
+ blob = null;
+ pos = 0;
+ }
+
+ /**
+ * Write blob data.
+ * @param v byte to be written at current position.
+ */
+
+ public void write(int v) throws IOException {
+ byte b[] = new byte[1];
+ b[0] = (byte) v;
+ pos += blob.write(b, 0, pos, 1);
+ }
+
+ /**
+ * Write blob data.
+ * @param b byte array to be written at current position.
+ */
+
+ public void write(byte[] b) throws IOException {
+ if (b != null && b.length > 0) {
+ pos += blob.write(b, 0, pos, b.length);
+ }
+ }
+
+ /**
+ * Write blob data.
+ * @param b byte array to be written.
+ * @param off offset within byte array
+ * @param len length of data to be written
+ */
+
+ public void write(byte[] b, int off, int len) throws IOException {
+ if (b != null) {
+ if (off + len > b.length) {
+ len = b.length - off;
+ }
+ if (len <= 0) {
+ return;
+ }
+ pos += blob.write(b, off, pos, len);
+ }
+ }
+}
+
+/**
+ * Class to represent SQLite3 3.4.0 incremental blob I/O interface.
+ *
+ * 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 Blob {
+
+ /**
+ * Internal handle for the SQLite3 blob.
+ */
+
+ private long handle = 0;
+
+ /**
+ * Cached size of blob, setup right after blob
+ * has been opened.
+ */
+
+ protected int size = 0;
+
+ /**
+ * Return InputStream for this blob
+ * @return InputStream
+ */
+
+ public InputStream getInputStream() {
+ return (InputStream) new BlobR(this);
+ }
+
+ /**
+ * Return OutputStream for this blob
+ * @return OutputStream
+ */
+
+ public OutputStream getOutputStream() {
+ return (OutputStream) new BlobW(this);
+ }
+
+ /**
+ * Close blob.
+ */
+
+ public native void close();
+
+ /**
+ * Internal blob write method.
+ * @param b byte array to be written
+ * @param off offset into byte array
+ * @param pos offset into blob
+ * @param len length to be written
+ * @return number of bytes written to blob
+ */
+
+ native int write(byte[] b, int off, int pos, int len) throws IOException;
+
+ /**
+ * Internal blob read method.
+ * @param b byte array to be written
+ * @param off offset into byte array
+ * @param pos offset into blob
+ * @param len length to be written
+ * @return number of bytes written to blob
+ */
+
+ native int read(byte[] b, int off, int pos, int len) throws IOException;
+
+ /**
+ * 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/BusyHandler.java b/sql/src/main/java/SQLite/BusyHandler.java
new file mode 100644
index 0000000..c39b39d
--- /dev/null
+++ b/sql/src/main/java/SQLite/BusyHandler.java
@@ -0,0 +1,20 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's user defined busy handler.
+ */
+
+public interface BusyHandler {
+
+ /**
+ * Invoked when a table is locked by another process
+ * or thread. The method should return true for waiting
+ * until the table becomes unlocked, or false in order
+ * to abandon the action.<BR><BR>
+ *
+ * @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.
+ * <BR><BR>
+ * Example:<BR>
+ *
+ * <PRE>
+ * class TableFmt implements SQLite.Callback {
+ * public void columns(String cols[]) {
+ * System.out.println("&lt;TH&gt;&lt;TR&gt;");
+ * for (int i = 0; i &lt; cols.length; i++) {
+ * System.out.println("&lt;TD&gt;" + cols[i] + "&lt;/TD&gt;");
+ * }
+ * System.out.println("&lt;/TR&gt;&lt;/TH&gt;");
+ * }
+ * public boolean newrow(String cols[]) {
+ * System.out.println("&lt;TR&gt;");
+ * for (int i = 0; i &lt; cols.length; i++) {
+ * System.out.println("&lt;TD&gt;" + cols[i] + "&lt;/TD&gt;");
+ * }
+ * System.out.println("&lt;/TR&gt;");
+ * return false;
+ * }
+ * }
+ * ...
+ * SQLite.Database db = new SQLite.Database();
+ * db.open("db", 0);
+ * System.out.println("&lt;TABLE&gt;");
+ * db.exec("select * from TEST", new TableFmt());
+ * System.out.println("&lt;/TABLE&gt;");
+ * ...
+ * </PRE>
+ */
+
+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.<BR><BR>
+ *
+ * @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.<BR><BR>
+ *
+ * @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.<BR><BR>
+ *
+ * @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.<P>
+ *
+ * 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.
+ * <BR><BR>
+ * Example:<BR>
+ * <PRE>
+ * String args[] = new String[1];
+ * args[0] = "tab%";
+ * db.exec("select * from sqlite_master where type like '%q'",
+ * null, args);
+ * </PRE>
+ *
+ * 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, <tt>unknown</tt> 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 <A HREF="Constants.html">Constants</A>
+ * 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
+ * <A HREF="FunctionContext.html">FunctionContext</A> object
+ * which is used to set the function result or error code.
+ * <BR><BR>
+ * Example:<BR>
+ *
+ * <PRE>
+ * class SinFunc implements SQLite.Function {
+ * public void function(SQLite.FunctionContext fc, String args[]) {
+ * try {
+ * Double d = new Double(args[0]);
+ * fc.set_result(Math.sin(d.doubleValue()));
+ * } catch (Exception e) {
+ * fc.set_error("sin(" + args[0] + "):" + e);
+ * }
+ * }
+ * ...
+ * }
+ * SQLite.Database db = new SQLite.Database();
+ * db.open("db", 0);
+ * db.create_function("sin", 1, SinFunc);
+ * ...
+ * db.exec("select sin(1.0) from test", null);
+ * </PRE>
+ */
+
+public interface Function {
+
+ /**
+ * Callback for regular function.
+ *
+ * @param fc function's context for reporting result
+ * @param args String array of arguments
+ */
+
+ public void function(FunctionContext fc, String args[]);
+
+ /**
+ * Callback for one step in aggregate function.
+ *
+ * @param fc function's context for reporting result
+ * @param args String array of arguments
+ */
+
+ public void step(FunctionContext fc, String args[]);
+
+ /**
+ * Callback for final step in aggregate function.
+ *
+ * @param fc function's context for reporting result
+ */
+
+ public void last_step(FunctionContext fc);
+
+}
diff --git a/sql/src/main/java/SQLite/FunctionContext.java b/sql/src/main/java/SQLite/FunctionContext.java
new file mode 100644
index 0000000..d0b5182
--- /dev/null
+++ b/sql/src/main/java/SQLite/FunctionContext.java
@@ -0,0 +1,82 @@
+package SQLite;
+
+/**
+ * Context for execution of SQLite's user defined functions.
+ * A reference to an instance of this class is passed to
+ * user defined functions.
+ */
+
+public class FunctionContext {
+
+ /**
+ * Internal handle for the native SQLite API.
+ */
+
+ private long handle = 0;
+
+ /**
+ * Set function result from string.
+ *
+ * @param r result string
+ */
+
+ public native void set_result(String r);
+
+ /**
+ * Set function result from integer.
+ *
+ * @param r result integer
+ */
+
+ public native void set_result(int r);
+
+ /**
+ * Set function result from double.
+ *
+ * @param r result double
+ */
+
+ public native void set_result(double r);
+
+ /**
+ * Set function result from error message.
+ *
+ * @param r result string (error message)
+ */
+
+ public native void set_error(String r);
+
+ /**
+ * Set function result from byte array.
+ * Only provided by SQLite3 databases.
+ *
+ * @param r result byte array
+ */
+
+ public native void set_result(byte[] r);
+
+ /**
+ * Set function result as empty blob given size.
+ * Only provided by SQLite3 databases.
+ *
+ * @param n size for empty blob
+ */
+
+ public native void set_result_zeroblob(int n);
+
+ /**
+ * Retrieve number of rows for aggregate function.
+ */
+
+ public native int count();
+
+ /**
+ * Internal native initializer.
+ */
+
+ private static native void internal_init();
+
+ static {
+ internal_init();
+ }
+}
diff --git a/sql/src/main/java/SQLite/JDBC2y/JDBCConnection.java b/sql/src/main/java/SQLite/JDBC2y/JDBCConnection.java
new file mode 100644
index 0000000..20c98e3
--- /dev/null
+++ b/sql/src/main/java/SQLite/JDBC2y/JDBCConnection.java
@@ -0,0 +1,452 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.util.*;
+
+public class JDBCConnection
+ implements java.sql.Connection, SQLite.BusyHandler {
+
+ /**
+ * Open database.
+ */
+ protected DatabaseX db;
+
+ /**
+ * Database URL.
+ */
+ protected String url;
+
+ /**
+ * Character encoding.
+ */
+ protected String enc;
+
+ /**
+ * Autocommit flag, true means autocommit.
+ */
+ protected boolean autocommit = true;
+
+ /**
+ * In-transaction flag.
+ * Can be true only when autocommit false.
+ */
+ protected boolean intrans = false;
+
+ /**
+ * Timeout for Database.exec()
+ */
+ protected int timeout = 1000000;
+
+ /**
+ * File name of database.
+ */
+ private String dbfile = null;
+
+ /**
+ * Reference to meta data or null.
+ */
+ private JDBCDatabaseMetaData meta = null;
+
+ /**
+ * Base time value for timeout handling.
+ */
+ private long t0;
+
+ /**
+ * Database in readonly mode.
+ */
+ private boolean readonly = false;
+
+
+ private boolean busy0(DatabaseX db, int count) {
+ if (count <= 1) {
+ t0 = System.currentTimeMillis();
+ }
+ if (db != null) {
+ long t1 = System.currentTimeMillis();
+ if (t1 - t0 > timeout) {
+ return false;
+ }
+ db.wait(100);
+ return true;
+ }
+ return false;
+ }
+
+ public boolean busy(String table, int count) {
+ return busy0(db, count);
+ }
+
+ protected boolean busy3(DatabaseX db, int count) {
+ if (count <= 1) {
+ t0 = System.currentTimeMillis();
+ }
+ if (db != null) {
+ long t1 = System.currentTimeMillis();
+ if (t1 - t0 > timeout) {
+ return false;
+ }
+ return true;
+ }
+ return false;
+ }
+
+ private DatabaseX open(boolean readonly) throws SQLException {
+ DatabaseX db = null;
+ try {
+ db = new DatabaseX();
+ db.open(dbfile, readonly ? 0444 : 0644);
+ db.set_encoding(enc);
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ int loop = 0;
+ while (true) {
+ try {
+ db.exec("PRAGMA short_column_names = off;", null);
+ db.exec("PRAGMA full_column_names = on;", null);
+ db.exec("PRAGMA empty_result_callbacks = on;", null);
+ if (SQLite.Database.version().compareTo("2.6.0") >= 0) {
+ db.exec("PRAGMA show_datatypes = on;", null);
+ }
+ } catch (SQLite.Exception e) {
+ if (db.last_error() != SQLite.Constants.SQLITE_BUSY ||
+ !busy0(db, ++loop)) {
+ try {
+ db.close();
+ } catch (SQLite.Exception ee) {
+ }
+ throw new SQLException(e.toString());
+ }
+ continue;
+ }
+ break;
+ }
+ return db;
+ }
+
+ public JDBCConnection(String url, String enc) throws SQLException {
+ if (url.startsWith("sqlite:/")) {
+ dbfile = url.substring(8);
+ } else if (url.startsWith("jdbc:sqlite:/")) {
+ dbfile = url.substring(13);
+ } else {
+ throw new SQLException("unsupported url");
+ }
+ this.url = url;
+ this.enc = enc;
+ try {
+ db = open(readonly);
+ db.busy_handler(this);
+ } catch (SQLException e) {
+ if (db != null) {
+ try {
+ db.close();
+ } catch (SQLite.Exception ee) {
+ }
+ }
+ throw e;
+ }
+ }
+
+ /* non-standard */
+ public SQLite.Database getSQLiteDatabase() {
+ return (SQLite.Database) db;
+ }
+
+ public Statement createStatement() {
+ JDBCStatement s = new JDBCStatement(this);
+ return s;
+ }
+
+ public Statement createStatement(int resultSetType,
+ int resultSetConcurrency)
+ throws SQLException {
+ JDBCStatement s = new JDBCStatement(this);
+ return s;
+ }
+
+ public DatabaseMetaData getMetaData() throws SQLException {
+ if (meta == null) {
+ meta = new JDBCDatabaseMetaData(this);
+ }
+ return meta;
+ }
+
+ public void close() throws SQLException {
+ try {
+ rollback();
+ } catch (SQLException e) {
+ /* ignored */
+ }
+ intrans = false;
+ if (db != null) {
+ try {
+ db.close();
+ db = null;
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ }
+ }
+
+ public boolean isClosed() throws SQLException {
+ return db == null;
+ }
+
+ public boolean isReadOnly() throws SQLException {
+ return readonly;
+ }
+
+ public void clearWarnings() throws SQLException {
+ }
+
+ public void commit() throws SQLException {
+ if (db == null) {
+ throw new SQLException("stale connection");
+ }
+ if (!intrans) {
+ return;
+ }
+ try {
+ db.exec("COMMIT", null);
+ intrans = false;
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ }
+
+ public boolean getAutoCommit() throws SQLException {
+ return autocommit;
+ }
+
+ public String getCatalog() throws SQLException {
+ return null;
+ }
+
+ public int getTransactionIsolation() throws SQLException {
+ return TRANSACTION_SERIALIZABLE;
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return null;
+ }
+
+ public String nativeSQL(String sql) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public CallableStatement prepareCall(String sql) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public CallableStatement prepareCall(String sql, int x, int y)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public PreparedStatement prepareStatement(String sql) throws SQLException {
+ JDBCPreparedStatement s = new JDBCPreparedStatement(this, sql);
+ return s;
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency)
+ throws SQLException {
+ JDBCPreparedStatement s = new JDBCPreparedStatement(this, sql);
+ return s;
+ }
+
+ public void rollback() throws SQLException {
+ if (db == null) {
+ throw new SQLException("stale connection");
+ }
+ if (!intrans) {
+ return;
+ }
+ try {
+ db.exec("ROLLBACK", null);
+ intrans = false;
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ }
+
+ public void setAutoCommit(boolean ac) throws SQLException {
+ if (ac && intrans && db != null) {
+ try {
+ db.exec("ROLLBACK", null);
+ } catch (SQLite.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ }
+ intrans = false;
+ autocommit = ac;
+ }
+
+ public void setCatalog(String catalog) throws SQLException {
+ }
+
+ public void setReadOnly(boolean ro) throws SQLException {
+ if (intrans) {
+ throw new SQLException("incomplete transaction");
+ }
+ if (ro != readonly) {
+ DatabaseX db = null;
+ try {
+ db = open(ro);
+ this.db.close();
+ this.db = db;
+ db = null;
+ readonly = ro;
+ } catch (SQLException e) {
+ throw e;
+ } catch (SQLite.Exception ee) {
+ if (db != null) {
+ try {
+ db.close();
+ } catch (SQLite.Exception eee) {
+ }
+ }
+ throw new SQLException(ee.toString());
+ }
+ }
+ }
+
+ public void setTransactionIsolation(int level) throws SQLException {
+ if (level != TRANSACTION_SERIALIZABLE) {
+ throw new SQLException("not supported");
+ }
+ }
+
+ public java.util.Map<String, Class<?>> getTypeMap() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTypeMap(java.util.Map map) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getHoldability() throws SQLException {
+ return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ }
+
+ public void setHoldability(int holdability) throws SQLException {
+ if (holdability == ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+ return;
+ }
+ throw new SQLException("not supported");
+ }
+
+ public Savepoint setSavepoint() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Savepoint setSavepoint(String name) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void rollback(Savepoint x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void releaseSavepoint(Savepoint x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Statement createStatement(int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability)
+ throws SQLException {
+ if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+ throw new SQLException("not supported");
+ }
+ return createStatement(resultSetType, resultSetConcurrency);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency,
+ int resultSetHoldability)
+ throws SQLException {
+ if (resultSetHoldability != ResultSet.HOLD_CURSORS_OVER_COMMIT) {
+ throw new SQLException("not supported");
+ }
+ return prepareStatement(sql, resultSetType, resultSetConcurrency);
+ }
+
+ public CallableStatement prepareCall(String sql, int x, int y, int z)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public PreparedStatement prepareStatement(String sql, int autokeys)
+ throws SQLException {
+ if (autokeys != Statement.NO_GENERATED_KEYS) {
+ throw new SQLException("not supported");
+ }
+ return prepareStatement(sql);
+ }
+
+ public PreparedStatement prepareStatement(String sql, int colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public PreparedStatement prepareStatement(String sql, String columns[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+}
+
+class DatabaseX extends SQLite.Database {
+
+ static Object lock = new Object();
+
+ public DatabaseX() {
+ super();
+ }
+
+ void wait(int ms) {
+ try {
+ synchronized (lock) {
+ lock.wait(ms);
+ }
+ } catch (java.lang.Exception e) {
+ }
+ }
+
+ public void exec(String sql, SQLite.Callback cb)
+ throws SQLite.Exception {
+ super.exec(sql, cb);
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ }
+
+ public void exec(String sql, SQLite.Callback cb, String args[])
+ throws SQLite.Exception {
+ super.exec(sql, cb, args);
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ }
+
+ public SQLite.TableResult get_table(String sql, String args[])
+ throws SQLite.Exception {
+ SQLite.TableResult ret = super.get_table(sql, args);
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ return ret;
+ }
+
+ public void get_table(String sql, String args[], SQLite.TableResult tbl)
+ throws SQLite.Exception {
+ super.get_table(sql, args, tbl);
+ synchronized (lock) {
+ lock.notifyAll();
+ }
+ }
+
+}
diff --git a/sql/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java b/sql/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java
new file mode 100644
index 0000000..8c14d1d
--- /dev/null
+++ b/sql/src/main/java/SQLite/JDBC2y/JDBCDatabaseMetaData.java
@@ -0,0 +1,1578 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.util.Hashtable;
+
+public class JDBCDatabaseMetaData implements DatabaseMetaData {
+
+ private JDBCConnection conn;
+
+ public JDBCDatabaseMetaData(JDBCConnection conn) {
+ this.conn = conn;
+ }
+
+ public boolean allProceduresAreCallable() throws SQLException {
+ return false;
+ }
+
+ public boolean allTablesAreSelectable() throws SQLException {
+ return true;
+ }
+
+ public String getURL() throws SQLException {
+ return conn.url;
+ }
+
+ public String getUserName() throws SQLException {
+ return "";
+ }
+
+ public boolean isReadOnly() throws SQLException {
+ return false;
+ }
+
+ public boolean nullsAreSortedHigh() throws SQLException {
+ return false;
+ }
+
+ public boolean nullsAreSortedLow() throws SQLException {
+ return false;
+ }
+
+ public boolean nullsAreSortedAtStart() throws SQLException {
+ return false;
+ }
+
+ public boolean nullsAreSortedAtEnd() throws SQLException {
+ return false;
+ }
+
+ public String getDatabaseProductName() throws SQLException {
+ return "SQLite";
+ }
+
+ public String getDatabaseProductVersion() throws SQLException {
+ return SQLite.Database.version();
+ }
+
+ public String getDriverName() throws SQLException {
+ return "SQLite/JDBC";
+ }
+
+ public String getDriverVersion() throws SQLException {
+ return "" + SQLite.JDBCDriver.MAJORVERSION + "." +
+ SQLite.JDBCDriver.MINORVERSION;
+ }
+
+ public int getDriverMajorVersion() {
+ return SQLite.JDBCDriver.MAJORVERSION;
+ }
+
+ public int getDriverMinorVersion() {
+ return SQLite.JDBCDriver.MINORVERSION;
+ }
+
+ public boolean usesLocalFiles() throws SQLException {
+ return true;
+ }
+
+ public boolean usesLocalFilePerTable() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsMixedCaseIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesUpperCaseIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesLowerCaseIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesMixedCaseIdentifiers() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException {
+ return false;
+ }
+
+ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException {
+ return true;
+ }
+
+ public String getIdentifierQuoteString() throws SQLException {
+ return "\"";
+ }
+
+ public String getSQLKeywords() throws SQLException {
+ return "SELECT,UPDATE,CREATE,TABLE,VIEW,DELETE,FROM,WHERE" +
+ ",COMMIT,ROLLBACK,TRIGGER";
+ }
+
+ public String getNumericFunctions() throws SQLException {
+ return "";
+ }
+
+ public String getStringFunctions() throws SQLException {
+ return "";
+ }
+
+ public String getSystemFunctions() throws SQLException {
+ return "";
+ }
+
+ public String getTimeDateFunctions() throws SQLException {
+ return "";
+ }
+
+ public String getSearchStringEscape() throws SQLException {
+ return "\\";
+ }
+
+ public String getExtraNameCharacters() throws SQLException {
+ return "";
+ }
+
+ public boolean supportsAlterTableWithAddColumn() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsAlterTableWithDropColumn() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsColumnAliasing() throws SQLException {
+ return true;
+ }
+
+ public boolean nullPlusNonNullIsNull() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsConvert() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsConvert(int fromType, int toType)
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsTableCorrelationNames() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsDifferentTableCorrelationNames()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsExpressionsInOrderBy() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsOrderByUnrelated() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsGroupBy() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsGroupByUnrelated() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsGroupByBeyondSelect() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsLikeEscapeClause() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsMultipleResultSets() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsMultipleTransactions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsNonNullableColumns() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsMinimumSQLGrammar() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsCoreSQLGrammar() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsExtendedSQLGrammar() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsANSI92EntryLevelSQL() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsANSI92IntermediateSQL() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsANSI92FullSQL() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsIntegrityEnhancementFacility()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOuterJoins() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsFullOuterJoins() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsLimitedOuterJoins() throws SQLException {
+ return false;
+ }
+
+ public String getSchemaTerm() throws SQLException {
+ return "";
+ }
+
+ public String getProcedureTerm() throws SQLException {
+ return "";
+ }
+
+ public String getCatalogTerm() throws SQLException {
+ return "";
+ }
+
+ public boolean isCatalogAtStart() throws SQLException {
+ return false;
+ }
+
+ public String getCatalogSeparator() throws SQLException {
+ return "";
+ }
+
+ public boolean supportsSchemasInDataManipulation() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSchemasInProcedureCalls() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSchemasInTableDefinitions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSchemasInIndexDefinitions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSchemasInPrivilegeDefinitions()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInDataManipulation() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInProcedureCalls() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInTableDefinitions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInIndexDefinitions() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCatalogsInPrivilegeDefinitions()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean supportsPositionedDelete() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsPositionedUpdate() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSelectForUpdate() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsStoredProcedures() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsSubqueriesInComparisons() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsSubqueriesInExists() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsSubqueriesInIns() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsSubqueriesInQuantifieds() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsCorrelatedSubqueries() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsUnion() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsUnionAll() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOpenCursorsAcrossCommit() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOpenCursorsAcrossRollback() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOpenStatementsAcrossCommit() throws SQLException {
+ return false;
+ }
+
+ public boolean supportsOpenStatementsAcrossRollback() throws SQLException {
+ return false;
+ }
+
+ public int getMaxBinaryLiteralLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxCharLiteralLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInGroupBy() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInIndex() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInOrderBy() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInSelect() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxColumnsInTable() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxConnections() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxCursorNameLength() throws SQLException {
+ return 8;
+ }
+
+ public int getMaxIndexLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxSchemaNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxProcedureNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxCatalogNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxRowSize() throws SQLException {
+ return 0;
+ }
+
+ public boolean doesMaxRowSizeIncludeBlobs() throws SQLException {
+ return true;
+ }
+
+ public int getMaxStatementLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxStatements() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxTableNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxTablesInSelect() throws SQLException {
+ return 0;
+ }
+
+ public int getMaxUserNameLength() throws SQLException {
+ return 0;
+ }
+
+ public int getDefaultTransactionIsolation() throws SQLException {
+ return Connection.TRANSACTION_SERIALIZABLE;
+ }
+
+ public boolean supportsTransactions() throws SQLException {
+ return true;
+ }
+
+ public boolean supportsTransactionIsolationLevel(int level)
+ throws SQLException {
+ return level == Connection.TRANSACTION_SERIALIZABLE;
+ }
+
+ public boolean supportsDataDefinitionAndDataManipulationTransactions()
+ throws SQLException {
+ return true;
+ }
+
+ public boolean supportsDataManipulationTransactionsOnly()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean dataDefinitionCausesTransactionCommit()
+ throws SQLException {
+ return false;
+ }
+
+ public boolean dataDefinitionIgnoredInTransactions() throws SQLException {
+ return false;
+ }
+
+ public ResultSet getProcedures(String catalog, String schemaPattern,
+ String procedureNamePattern)
+ throws SQLException {
+ return null;
+ }
+
+ public ResultSet getProcedureColumns(String catalog,
+ String schemaPattern,
+ String procedureNamePattern,
+ String columnNamePattern)
+ throws SQLException {
+ return null;
+ }
+
+ public ResultSet getTables(String catalog, String schemaPattern,
+ String tableNamePattern, String types[])
+ throws SQLException {
+ JDBCStatement s = new JDBCStatement(conn);
+ StringBuffer sb = new StringBuffer();
+ sb.append("SELECT '' AS 'TABLE_CAT', " +
+ "'' AS 'TABLE_SCHEM', " +
+ "tbl_name AS 'TABLE_NAME', " +
+ "upper(type) AS 'TABLE_TYPE', " +
+ "'' AS REMARKS FROM sqlite_master " +
+ "WHERE tbl_name like ");
+ if (tableNamePattern != null) {
+ sb.append(SQLite.Shell.sql_quote(tableNamePattern));
+ } else {
+ sb.append("'%'");
+ }
+ sb.append(" AND ");
+ if (types == null || types.length == 0) {
+ sb.append("(type = 'table' or type = 'view')");
+ } else {
+ sb.append("(");
+ String sep = "";
+ for (int i = 0; i < types.length; i++) {
+ sb.append(sep);
+ sb.append("type = ");
+ sb.append(SQLite.Shell.sql_quote(types[i].toLowerCase()));
+ sep = " or ";
+ }
+ sb.append(")");
+ }
+ ResultSet rs = null;
+ try {
+ rs = s.executeQuery(sb.toString());
+ s.close();
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s.close();
+ }
+ return rs;
+ }
+
+ public ResultSet getSchemas() throws SQLException {
+ String cols[] = { "TABLE_SCHEM" };
+ SQLite.TableResult tr = new SQLite.TableResult();
+ tr.columns(cols);
+ String row[] = { "" };
+ tr.newrow(row);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ return (ResultSet) rs;
+ }
+
+ public ResultSet getCatalogs() throws SQLException {
+ String cols[] = { "TABLE_CAT" };
+ SQLite.TableResult tr = new SQLite.TableResult();
+ tr.columns(cols);
+ String row[] = { "" };
+ tr.newrow(row);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ return (ResultSet) rs;
+ }
+
+ public ResultSet getTableTypes() throws SQLException {
+ String cols[] = { "TABLE_TYPE" };
+ SQLite.TableResult tr = new SQLite.TableResult();
+ tr.columns(cols);
+ String row[] = new String[1];
+ row[0] = "TABLE";
+ tr.newrow(row);
+ row = new String[1];
+ row[0] = "VIEW";
+ tr.newrow(row);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ return (ResultSet) rs;
+ }
+
+ public ResultSet getColumns(String catalog, String schemaPattern,
+ String tableNamePattern,
+ String columnNamePattern)
+ throws SQLException {
+ JDBCStatement s = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s.executeQuery("PRAGMA table_info(" +
+ SQLite.Shell.sql_quote(tableNamePattern) +
+ ")"));
+ s.close();
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s.close();
+ }
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "DATA_TYPE", "TYPE_NAME",
+ "COLUMN_SIZE", "BUFFER_LENGTH", "DECIMAL_POINTS",
+ "NUM_PREC_RADIX", "NULLABLE", "REMARKS",
+ "COLUMN_DEF", "SQL_DATA_TYPE", "SQL_DATETIME_SUB",
+ "CHAR_OCTET_LENGTH", "ORDINAL_POSITION", "IS_NULLABLE"
+ };
+ int types[] = {
+ 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
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ Hashtable<String, Integer> h = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h.put(rs0.tr.column[i], new Integer(i));
+ }
+ if (columnNamePattern != null &&
+ columnNamePattern.charAt(0) == '%') {
+ columnNamePattern = null;
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h.get("name")).intValue();
+ if (columnNamePattern != null) {
+ if (r0[col].compareTo(columnNamePattern) != 0) {
+ continue;
+ }
+ }
+ String row[] = new String[cols.length];
+ row[0] = "";
+ row[1] = "";
+ row[2] = tableNamePattern;
+ row[3] = r0[col];
+ col = ((Integer) h.get("type")).intValue();
+ String typeStr = r0[col];
+ int type = mapSqlType(typeStr);
+ row[4] = "" + type;
+ row[5] = mapTypeName(type);
+ row[6] = "" + getD(typeStr, type);
+ row[7] = "" + getM(typeStr, type);
+ row[8] = "10";
+ row[9] = "0";
+ row[11] = null;
+ col = ((Integer) h.get("dflt_value")).intValue();
+ row[12] = r0[col];
+ row[13] = "0";
+ row[14] = "0";
+ row[15] = "65536";
+ col = ((Integer) h.get("cid")).intValue();
+ Integer cid = new Integer(r0[col]);
+ row[16] = "" + (cid.intValue() + 1);
+ col = ((Integer) h.get("notnull")).intValue();
+ row[17] = (r0[col].charAt(0) == '0') ? "YES" : "NO";
+ row[10] = (r0[col].charAt(0) == '0') ? "" + columnNullable :
+ "" + columnNoNulls;
+ tr.newrow(row);
+ }
+ }
+ return rs;
+ }
+
+ public ResultSet getColumnPrivileges(String catalog, String schema,
+ String table,
+ String columnNamePattern)
+ throws SQLException {
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "GRANTOR", "GRANTEE",
+ "PRIVILEGE", "IS_GRANTABLE"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ return rs;
+ }
+
+ public ResultSet getTablePrivileges(String catalog, String schemaPattern,
+ String tableNamePattern)
+ throws SQLException {
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "GRANTOR", "GRANTEE",
+ "PRIVILEGE", "IS_GRANTABLE"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ return rs;
+ }
+
+ public ResultSet getBestRowIdentifier(String catalog, String schema,
+ String table, int scope,
+ boolean nullable)
+ throws SQLException {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ JDBCStatement s1 = new JDBCStatement(conn);
+ JDBCResultSet rs1 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA index_list(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ rs1 = (JDBCResultSet)
+ (s1.executeQuery("PRAGMA table_info(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ s1.close();
+ }
+ String cols[] = {
+ "SCOPE", "COLUMN_NAME", "DATA_TYPE",
+ "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH",
+ "DECIMAL_DIGITS", "PSEUDO_COLUMN"
+ };
+ int types[] = {
+ Types.SMALLINT, Types.VARCHAR, Types.SMALLINT,
+ Types.VARCHAR, Types.INTEGER, Types.INTEGER,
+ Types.SMALLINT, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0 &&
+ rs1 != null && rs1.tr != null && rs1.tr.nrows > 0) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h0.put(rs0.tr.column[i], new Integer(i));
+ }
+ Hashtable<String, Integer> h1 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs1.tr.ncolumns; i++) {
+ h1.put(rs1.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("unique")).intValue();
+ String uniq = r0[col];
+ col = ((Integer) h0.get("name")).intValue();
+ String iname = r0[col];
+ if (uniq.charAt(0) == '0') {
+ continue;
+ }
+ JDBCStatement s2 = new JDBCStatement(conn);
+ JDBCResultSet rs2 = null;
+ try {
+ rs2 = (JDBCResultSet)
+ (s2.executeQuery("PRAGMA index_info(" +
+ SQLite.Shell.sql_quote(iname) + ")"));
+ } catch (SQLException e) {
+ } finally {
+ s2.close();
+ }
+ if (rs2 == null || rs2.tr == null || rs2.tr.nrows <= 0) {
+ continue;
+ }
+ Hashtable<String, Integer> h2 =
+ new Hashtable<String, Integer>();
+ for (int k = 0; k < rs2.tr.ncolumns; k++) {
+ h2.put(rs2.tr.column[k], new Integer(k));
+ }
+ for (int k = 0; k < rs2.tr.nrows; k++) {
+ String r2[] = (String [])(rs2.tr.rows.elementAt(k));
+ col = ((Integer) h2.get("name")).intValue();
+ String cname = r2[col];
+ for (int m = 0; m < rs1.tr.nrows; m++) {
+ String r1[] = (String [])(rs1.tr.rows.elementAt(m));
+ col = ((Integer) h1.get("name")).intValue();
+ if (cname.compareTo(r1[col]) == 0) {
+ String row[] = new String[cols.length];
+ row[0] = "" + scope;
+ row[1] = cname;
+ row[2] = "" + Types.VARCHAR;
+ row[3] = "VARCHAR";
+ row[4] = "65536";
+ row[5] = "0";
+ row[6] = "0";
+ row[7] = "" + bestRowNotPseudo;
+ tr.newrow(row);
+ }
+ }
+ }
+ }
+ }
+ if (tr.nrows <= 0) {
+ String row[] = new String[cols.length];
+ row[0] = "" + scope;
+ row[1] = "_ROWID_";
+ row[2] = "" + Types.INTEGER;
+ row[3] = "INTEGER";
+ row[4] = "10";
+ row[5] = "0";
+ row[6] = "0";
+ row[7] = "" + bestRowPseudo;
+ tr.newrow(row);
+ }
+ return rs;
+ }
+
+ public ResultSet getVersionColumns(String catalog, String schema,
+ String table) throws SQLException {
+ String cols[] = {
+ "SCOPE", "COLUMN_NAME", "DATA_TYPE",
+ "TYPE_NAME", "COLUMN_SIZE", "BUFFER_LENGTH",
+ "DECIMAL_DIGITS", "PSEUDO_COLUMN"
+ };
+ int types[] = {
+ Types.SMALLINT, Types.VARCHAR, Types.SMALLINT,
+ Types.VARCHAR, Types.INTEGER, Types.INTEGER,
+ Types.SMALLINT, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ return rs;
+ }
+
+ public ResultSet getPrimaryKeys(String catalog, String schema,
+ String table) throws SQLException {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA index_list(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ }
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "COLUMN_NAME", "KEY_SEQ", "PK_NAME"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT, Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h0.put(rs0.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("unique")).intValue();
+ String uniq = r0[col];
+ col = ((Integer) h0.get("name")).intValue();
+ String iname = r0[col];
+ if (uniq.charAt(0) == '0') {
+ continue;
+ }
+ JDBCStatement s1 = new JDBCStatement(conn);
+ JDBCResultSet rs1 = null;
+ try {
+ rs1 = (JDBCResultSet)
+ (s1.executeQuery("PRAGMA index_info(" +
+ SQLite.Shell.sql_quote(iname) + ")"));
+ } catch (SQLException e) {
+ } finally {
+ s1.close();
+ }
+ if (rs1 == null || rs1.tr == null || rs1.tr.nrows <= 0) {
+ continue;
+ }
+ Hashtable<String, Integer> h1 =
+ new Hashtable<String, Integer>();
+ for (int k = 0; k < rs1.tr.ncolumns; k++) {
+ h1.put(rs1.tr.column[k], new Integer(k));
+ }
+ for (int k = 0; k < rs1.tr.nrows; k++) {
+ String r1[] = (String [])(rs1.tr.rows.elementAt(k));
+ String row[] = new String[cols.length];
+ row[0] = "";
+ row[1] = "";
+ row[2] = table;
+ col = ((Integer) h1.get("name")).intValue();
+ row[3] = r1[col];
+ col = ((Integer) h1.get("seqno")).intValue();
+// BEGIN android-changed
+ row[4] = "" + (Integer.parseInt(r1[col]) + 1);
+// END android-changed
+ row[5] = iname;
+ tr.newrow(row);
+ }
+ }
+ }
+ JDBCStatement s1 = new JDBCStatement(conn);
+ try {
+ rs0 = (JDBCResultSet)
+ (s1.executeQuery("PRAGMA table_info(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s1.close();
+ }
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h0.put(rs0.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("type")).intValue();
+ String type = r0[col];
+ if (!type.equalsIgnoreCase("integer")) {
+ continue;
+ }
+ col = ((Integer) h0.get("pk")).intValue();
+ String pk = r0[col];
+ if (pk.charAt(0) == '0') {
+ continue;
+ }
+ String row[] = new String[cols.length];
+ row[0] = "";
+ row[1] = "";
+ row[2] = table;
+ col = ((Integer) h0.get("name")).intValue();
+ row[3] = r0[col];
+ col = ((Integer) h0.get("cid")).intValue();
+// BEGIN android-changed
+ row[4] = "" + (Integer.parseInt(r0[col]) + 1);
+// END android-changed
+ row[5] = "";
+ tr.newrow(row);
+ }
+ }
+ return rs;
+ }
+
+ private void internalImportedKeys(String table, String pktable,
+ JDBCResultSet in, TableResultX out) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < in.tr.ncolumns; i++) {
+ h0.put(in.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < in.tr.nrows; i++) {
+ String r0[] = (String [])(in.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("table")).intValue();
+ String pktab = r0[col];
+ if (pktable != null && !pktable.equalsIgnoreCase(pktab)) {
+ continue;
+ }
+ col = ((Integer) h0.get("from")).intValue();
+ String pkcol = r0[col];
+ col = ((Integer) h0.get("to")).intValue();
+ String fkcol = r0[col];
+ col = ((Integer) h0.get("seq")).intValue();
+ String seq = r0[col];
+ String row[] = new String[out.ncolumns];
+ row[0] = "";
+ row[1] = "";
+ row[2] = pktab;
+ row[3] = pkcol;
+ row[4] = "";
+ row[5] = "";
+ row[6] = table;
+ row[7] = fkcol == null ? pkcol : fkcol;
+// BEGIN android-changed
+ row[8] = "" + ((Integer.parseInt(seq)) + 1);
+// END android-changed
+ row[9] =
+ "" + java.sql.DatabaseMetaData.importedKeyNoAction;
+ row[10] =
+ "" + java.sql.DatabaseMetaData.importedKeyNoAction;
+ row[11] = null;
+ row[12] = null;
+ row[13] =
+ "" + java.sql.DatabaseMetaData.importedKeyNotDeferrable;
+ out.newrow(row);
+ }
+ }
+
+ public ResultSet getImportedKeys(String catalog, String schema,
+ String table) throws SQLException {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA foreign_key_list(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ }
+ String cols[] = {
+ "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"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
+ Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet((SQLite.TableResult) tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ internalImportedKeys(table, null, rs0, tr);
+ }
+ return rs;
+ }
+
+ public ResultSet getExportedKeys(String catalog, String schema,
+ String table) throws SQLException {
+ String cols[] = {
+ "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"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
+ Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ return rs;
+ }
+
+ public ResultSet getCrossReference(String primaryCatalog,
+ String primarySchema,
+ String primaryTable,
+ String foreignCatalog,
+ String foreignSchema,
+ String foreignTable)
+ throws SQLException {
+ JDBCResultSet rs0 = null;
+ if (foreignTable != null && foreignTable.charAt(0) != '%') {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA foreign_key_list(" +
+ SQLite.Shell.sql_quote(foreignTable) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ }
+ }
+ String cols[] = {
+ "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"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.VARCHAR, Types.VARCHAR, Types.SMALLINT,
+ Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
+ Types.VARCHAR, Types.SMALLINT
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ String pktable = null;
+ if (primaryTable != null && primaryTable.charAt(0) != '%') {
+ pktable = primaryTable;
+ }
+ internalImportedKeys(foreignTable, pktable, rs0, tr);
+ }
+ return rs;
+ }
+
+ public ResultSet getTypeInfo() throws SQLException {
+ String cols[] = {
+ "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"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.SMALLINT, Types.INTEGER,
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.SMALLINT, Types.BIT, Types.SMALLINT,
+ Types.BIT, Types.BIT, Types.BIT,
+ Types.VARCHAR, Types.SMALLINT, Types.SMALLINT,
+ Types.INTEGER, Types.INTEGER, Types.INTEGER
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ String row1[] = {
+ "VARCHAR", "" + Types.VARCHAR, "65536",
+ "'", "'", null,
+ "" + typeNullable, "1", "" + typeSearchable,
+ "0", "0", "0",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row1);
+ String row2[] = {
+ "INTEGER", "" + Types.INTEGER, "32",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "2"
+ };
+ tr.newrow(row2);
+ String row3[] = {
+ "DOUBLE", "" + Types.DOUBLE, "16",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "10"
+ };
+ tr.newrow(row3);
+ String row4[] = {
+ "FLOAT", "" + Types.FLOAT, "7",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "10"
+ };
+ tr.newrow(row4);
+ String row5[] = {
+ "SMALLINT", "" + Types.SMALLINT, "16",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "2"
+ };
+ tr.newrow(row5);
+ String row6[] = {
+ "BIT", "" + Types.BIT, "1",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "2"
+ };
+ tr.newrow(row6);
+ String row7[] = {
+ "TIMESTAMP", "" + Types.TIMESTAMP, "30",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row7);
+ String row8[] = {
+ "DATE", "" + Types.DATE, "10",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row8);
+ String row9[] = {
+ "TIME", "" + Types.TIME, "8",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row9);
+ String row10[] = {
+ "BINARY", "" + Types.BINARY, "65536",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row10);
+ String row11[] = {
+ "VARBINARY", "" + Types.VARBINARY, "65536",
+ null, null, null,
+ "" + typeNullable, "0", "" + typeSearchable,
+ "0", "0", "1",
+ null, "0", "0",
+ "0", "0", "0"
+ };
+ tr.newrow(row11);
+ return rs;
+ }
+
+ public ResultSet getIndexInfo(String catalog, String schema, String table,
+ boolean unique, boolean approximate)
+ throws SQLException {
+ JDBCStatement s0 = new JDBCStatement(conn);
+ JDBCResultSet rs0 = null;
+ try {
+ rs0 = (JDBCResultSet)
+ (s0.executeQuery("PRAGMA index_list(" +
+ SQLite.Shell.sql_quote(table) + ")"));
+ } catch (SQLException e) {
+ throw e;
+ } finally {
+ s0.close();
+ }
+ String cols[] = {
+ "TABLE_CAT", "TABLE_SCHEM", "TABLE_NAME",
+ "NON_UNIQUE", "INDEX_QUALIFIER", "INDEX_NAME",
+ "TYPE", "ORDINAL_POSITION", "COLUMN_NAME",
+ "ASC_OR_DESC", "CARDINALITY", "PAGES",
+ "FILTER_CONDITION"
+ };
+ int types[] = {
+ Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
+ Types.BIT, Types.VARCHAR, Types.VARCHAR,
+ Types.SMALLINT, Types.SMALLINT, Types.VARCHAR,
+ Types.VARCHAR, Types.INTEGER, Types.INTEGER,
+ Types.VARCHAR
+ };
+ TableResultX tr = new TableResultX();
+ tr.columns(cols);
+ tr.sql_types(types);
+ JDBCResultSet rs = new JDBCResultSet(tr, null);
+ if (rs0 != null && rs0.tr != null && rs0.tr.nrows > 0) {
+ Hashtable<String, Integer> h0 = new Hashtable<String, Integer>();
+ for (int i = 0; i < rs0.tr.ncolumns; i++) {
+ h0.put(rs0.tr.column[i], new Integer(i));
+ }
+ for (int i = 0; i < rs0.tr.nrows; i++) {
+ String r0[] = (String [])(rs0.tr.rows.elementAt(i));
+ int col = ((Integer) h0.get("unique")).intValue();
+ String uniq = r0[col];
+ col = ((Integer) h0.get("name")).intValue();
+ String iname = r0[col];
+ if (unique && uniq.charAt(0) == '0') {
+ continue;
+ }
+ JDBCStatement s1 = new JDBCStatement(conn);
+ JDBCResultSet rs1 = null;
+ try {
+ rs1 = (JDBCResultSet)
+ (s1.executeQuery("PRAGMA index_info(" +
+ SQLite.Shell.sql_quote(iname) + ")"));
+ } catch (SQLException e) {
+ } finally {
+ s1.close();
+ }
+ if (rs1 == null || rs1.tr == null || rs1.tr.nrows <= 0) {
+ continue;
+ }
+ Hashtable<String, Integer> h1 =
+ new Hashtable<String, Integer>();
+ for (int k = 0; k < rs1.tr.ncolumns; k++) {
+ h1.put(rs1.tr.column[k], new Integer(k));
+ }
+ for (int k = 0; k < rs1.tr.nrows; k++) {
+ String r1[] = (String [])(rs1.tr.rows.elementAt(k));
+ String row[] = new String[cols.length];
+ row[0] = "";
+ row[1] = "";
+ row[2] = table;
+ row[3] = (uniq.charAt(0) != '0' ||
+ (iname.charAt(0) == '(' &&
+ iname.indexOf(" autoindex ") > 0)) ? "0" : "1";
+ row[4] = "";
+ row[5] = iname;
+ row[6] = "" + tableIndexOther;
+ col = ((Integer) h1.get("seqno")).intValue();
+// BEGIN android-changed
+ row[7] = "" + (Integer.parseInt(r1[col]) + 1);
+// END android-changed
+ col = ((Integer) h1.get("name")).intValue();
+ row[8] = r1[col];
+ row[9] = "A";
+ row[10] = "0";
+ row[11] = "0";
+ row[12] = null;
+ tr.newrow(row);
+ }
+ }
+ }
+ return rs;
+ }
+
+ public boolean supportsResultSetType(int type) throws SQLException {
+ return type == ResultSet.CONCUR_READ_ONLY;
+ }
+
+ public boolean supportsResultSetConcurrency(int type, int concurrency)
+ throws SQLException {
+ return false;
+ }
+
+ public boolean ownUpdatesAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean ownDeletesAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean ownInsertsAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean othersUpdatesAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean othersDeletesAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean othersInsertsAreVisible(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean updatesAreDetected(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean deletesAreDetected(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean insertsAreDetected(int type) throws SQLException {
+ return false;
+ }
+
+ public boolean supportsBatchUpdates() throws SQLException {
+ return false;
+ }
+
+ public ResultSet getUDTs(String catalog, String schemaPattern,
+ String typeNamePattern, int[] types)
+ throws SQLException {
+ return null;
+ }
+
+ public Connection getConnection() throws SQLException {
+ return conn;
+ }
+
+ static String mapTypeName(int type) {
+ switch (type) {
+ case Types.INTEGER: return "integer";
+ case Types.SMALLINT: return "smallint";
+ case Types.FLOAT: return "float";
+ case Types.DOUBLE: return "double";
+ case Types.TIMESTAMP: return "timestamp";
+ case Types.DATE: return "date";
+ case Types.TIME: return "time";
+ case Types.BINARY: return "binary";
+ case Types.VARBINARY: return "varbinary";
+ }
+ return "varchar";
+ }
+
+ static int mapSqlType(String type) {
+ if (type == null) {
+ return Types.VARCHAR;
+ }
+ type = type.toLowerCase();
+ if (type.startsWith("inter")) {
+ return Types.VARCHAR;
+ }
+ if (type.startsWith("numeric") ||
+ type.startsWith("int")) {
+ return Types.INTEGER;
+ }
+ if (type.startsWith("tinyint") ||
+ type.startsWith("smallint")) {
+ return Types.SMALLINT;
+ }
+ if (type.startsWith("float")) {
+ return Types.FLOAT;
+ }
+ if (type.startsWith("double")) {
+ return Types.DOUBLE;
+ }
+ if (type.startsWith("datetime") ||
+ type.startsWith("timestamp")) {
+ return Types.TIMESTAMP;
+ }
+ if (type.startsWith("date")) {
+ return Types.DATE;
+ }
+ if (type.startsWith("time")) {
+ return Types.TIME;
+ }
+ if (type.startsWith("blob")) {
+ return Types.BINARY;
+ }
+ if (type.startsWith("binary")) {
+ return Types.BINARY;
+ }
+ if (type.startsWith("varbinary")) {
+ return Types.VARBINARY;
+ }
+ return Types.VARCHAR;
+ }
+
+ static int getM(String typeStr, int type) {
+ int m = 65536;
+ switch (type) {
+ case Types.INTEGER: m = 11; break;
+ case Types.SMALLINT: m = 6; break;
+ case Types.FLOAT: m = 25; break;
+ case Types.DOUBLE: m = 54; break;
+ case Types.TIMESTAMP: return 30;
+ case Types.DATE: return 10;
+ case Types.TIME: return 8;
+ }
+ typeStr = typeStr.toLowerCase();
+ int i1 = typeStr.indexOf('(');
+ if (i1 > 0) {
+ ++i1;
+ int i2 = typeStr.indexOf(',', i1);
+ if (i2 < 0) {
+ i2 = typeStr.indexOf(')', i1);
+ }
+ if (i2 - i1 > 0) {
+ String num = typeStr.substring(i1, i2);
+ try {
+ m = java.lang.Integer.parseInt(num, 10);
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+ return m;
+ }
+
+ static int getD(String typeStr, int type) {
+ int d = 0;
+ switch (type) {
+ case Types.INTEGER: d = 10; break;
+ case Types.SMALLINT: d = 5; break;
+ case Types.FLOAT: d = 24; break;
+ case Types.DOUBLE: d = 53; break;
+ default: return getM(typeStr, type);
+ }
+ typeStr = typeStr.toLowerCase();
+ int i1 = typeStr.indexOf('(');
+ if (i1 > 0) {
+ ++i1;
+ int i2 = typeStr.indexOf(',', i1);
+ if (i2 < 0) {
+ return getM(typeStr, type);
+ }
+ i1 = i2;
+ i2 = typeStr.indexOf(')', i1);
+ if (i2 - i1 > 0) {
+ String num = typeStr.substring(i1, i2);
+ try {
+ d = java.lang.Integer.parseInt(num, 10);
+ } catch (NumberFormatException e) {
+ }
+ }
+ }
+ return d;
+ }
+
+ public boolean supportsSavepoints() {
+ return false;
+ }
+
+ public boolean supportsNamedParameters() {
+ return false;
+ }
+
+ public boolean supportsMultipleOpenResults() {
+ return false;
+ }
+
+ public boolean supportsGetGeneratedKeys() {
+ return false;
+ }
+
+ public boolean supportsResultSetHoldability(int x) {
+ return false;
+ }
+
+ public boolean supportsStatementPooling() {
+ return false;
+ }
+
+ public boolean locatorsUpdateCopy() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSet getSuperTypes(String catalog, String schemaPattern,
+ String typeNamePattern)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSet getSuperTables(String catalog, String schemaPattern,
+ String tableNamePattern)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSet getAttributes(String catalog, String schemaPattern,
+ String typeNamePattern,
+ String attributeNamePattern)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getResultSetHoldability() throws SQLException {
+ return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ }
+
+ public int getDatabaseMajorVersion() {
+ return SQLite.JDBCDriver.MAJORVERSION;
+ }
+
+ public int getDatabaseMinorVersion() {
+ return SQLite.JDBCDriver.MINORVERSION;
+ }
+
+ public int getJDBCMajorVersion() {
+ return 1;
+ }
+
+ public int getJDBCMinorVersion() {
+ return 0;
+ }
+
+ public int getSQLStateType() throws SQLException {
+ return sqlStateXOpen;
+ }
+
+}
diff --git a/sql/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java b/sql/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java
new file mode 100644
index 0000000..ab81867
--- /dev/null
+++ b/sql/src/main/java/SQLite/JDBC2y/JDBCPreparedStatement.java
@@ -0,0 +1,752 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.math.BigDecimal;
+import java.util.*;
+
+class BatchArg {
+ String arg;
+ boolean blob;
+
+ BatchArg(String arg, boolean blob) {
+ if (arg == null) {
+ this.arg = null;
+ } else {
+ this.arg = new String(arg);
+ }
+ this.blob = blob;
+ }
+}
+
+public class JDBCPreparedStatement extends JDBCStatement
+ implements java.sql.PreparedStatement {
+
+ private String sql;
+ private String args[];
+ private boolean blobs[];
+ private ArrayList<BatchArg> batch;
+ private static final boolean nullrepl =
+ SQLite.Database.version().compareTo("2.5.0") < 0;
+
+ public JDBCPreparedStatement(JDBCConnection conn, String sql) {
+ super(conn);
+ this.args = null;
+ this.blobs = null;
+ this.batch = null;
+ this.sql = fixup(sql);
+ }
+
+ private String fixup(String sql) {
+ StringBuffer sb = new StringBuffer();
+ boolean inq = false;
+ int nparm = 0;
+ for (int i = 0; i < sql.length(); i++) {
+ char c = sql.charAt(i);
+ if (c == '\'') {
+ if (inq) {
+ char nextChar = 0;
+ if(i + 1 < sql.length()) {
+ nextChar = sql.charAt(i + 1);
+ }
+ if (nextChar == '\'') {
+ sb.append(c);
+ sb.append(nextChar);
+ i++;
+ } else {
+ inq = false;
+ sb.append(c);
+ }
+ } else {
+ inq = true;
+ sb.append(c);
+ }
+ } else if (c == '?') {
+ if (inq) {
+ sb.append(c);
+ } else {
+ ++nparm;
+ sb.append(nullrepl ? "'%q'" : "%Q");
+ }
+ } else if (c == ';') {
+ if (!inq) {
+ break;
+ }
+ sb.append(c);
+ } else if (c == '%') {
+ sb.append("%%");
+ } else {
+ sb.append(c);
+ }
+ }
+ args = new String[nparm];
+ blobs = new boolean[nparm];
+ try {
+ clearParameters();
+ } catch (SQLException e) {
+ }
+ return sb.toString();
+ }
+
+ private String fixup2(String sql) {
+ if (!conn.db.is3()) {
+ return sql;
+ }
+ StringBuffer sb = new StringBuffer();
+ int parm = -1;
+ for (int i = 0; i < sql.length(); i++) {
+ char c = sql.charAt(i);
+ if (c == '%') {
+ sb.append(c);
+ ++i;
+ c = sql.charAt(i);
+ if (c == 'Q') {
+ parm++;
+ if (blobs[parm]) {
+ c = 's';
+ }
+ }
+ }
+ sb.append(c);
+ }
+ return sb.toString();
+ }
+
+ public ResultSet executeQuery() throws SQLException {
+ return executeQuery(fixup2(sql), args, false);
+ }
+
+ public int executeUpdate() throws SQLException {
+ executeQuery(fixup2(sql), args, true);
+ return updcnt;
+ }
+
+ public void setNull(int parameterIndex, int sqlType) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setBoolean(int parameterIndex, boolean x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = x ? "1" : "0";
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setByte(int parameterIndex, byte x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setShort(int parameterIndex, short x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setInt(int parameterIndex, int x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setLong(int parameterIndex, long x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setFloat(int parameterIndex, float x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setDouble(int parameterIndex, double x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ args[parameterIndex - 1] = "" + x;
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setBigDecimal(int parameterIndex, BigDecimal x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = "" + x;
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setString(int parameterIndex, String x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = x;
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setBytes(int parameterIndex, byte x[]) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ blobs[parameterIndex - 1] = false;
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ if (conn.db.is3()) {
+ args[parameterIndex - 1] = SQLite.StringEncoder.encodeX(x);
+ blobs[parameterIndex - 1] = true;
+ } else {
+ args[parameterIndex - 1] = SQLite.StringEncoder.encode(x);
+ }
+ }
+ }
+
+ public void setDate(int parameterIndex, java.sql.Date x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setTime(int parameterIndex, java.sql.Time x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setTimestamp(int parameterIndex, java.sql.Timestamp x)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setAsciiStream(int parameterIndex, java.io.InputStream x,
+ int length) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ @Deprecated
+ public void setUnicodeStream(int parameterIndex, java.io.InputStream x,
+ int length) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBinaryStream(int parameterIndex, java.io.InputStream x,
+ int length) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void clearParameters() throws SQLException {
+ for (int i = 0; i < args.length; i++) {
+ args[i] = nullrepl ? "" : null;
+ blobs[i] = false;
+ }
+ }
+
+ public void setObject(int parameterIndex, Object x, int targetSqlType,
+ int scale) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ if (x instanceof byte[]) {
+ byte[] bx = (byte[]) x;
+ if (conn.db.is3()) {
+ args[parameterIndex - 1] =
+ SQLite.StringEncoder.encodeX(bx);
+ blobs[parameterIndex - 1] = true;
+ return;
+ }
+ args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx);
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setObject(int parameterIndex, Object x, int targetSqlType)
+ throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ if (x instanceof byte[]) {
+ byte[] bx = (byte[]) x;
+ if (conn.db.is3()) {
+ args[parameterIndex - 1] =
+ SQLite.StringEncoder.encodeX(bx);
+ blobs[parameterIndex - 1] = true;
+ return;
+ }
+ args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx);
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public void setObject(int parameterIndex, Object x) throws SQLException {
+ if (parameterIndex < 1 || parameterIndex > args.length) {
+ throw new SQLException("bad parameter index");
+ }
+ if (x == null) {
+ args[parameterIndex - 1] = nullrepl ? "" : null;
+ } else {
+ if (x instanceof byte[]) {
+ byte[] bx = (byte[]) x;
+ if (conn.db.is3()) {
+ args[parameterIndex - 1] =
+ SQLite.StringEncoder.encodeX(bx);
+ blobs[parameterIndex - 1] = true;
+ return;
+ }
+ args[parameterIndex - 1] = SQLite.StringEncoder.encode(bx);
+ } else {
+ args[parameterIndex - 1] = x.toString();
+ }
+ }
+ blobs[parameterIndex - 1] = false;
+ }
+
+ public boolean execute() throws SQLException {
+ return executeQuery(fixup2(sql), args, false) != null;
+ }
+
+ public void addBatch() throws SQLException {
+ if (batch == null) {
+ batch = new ArrayList<BatchArg>(args.length);
+ }
+ for (int i = 0; i < args.length; i++) {
+ batch.add(new BatchArg(args[i], blobs[i]));
+ }
+ }
+
+ public int[] executeBatch() throws SQLException {
+ if (batch == null) {
+ return new int[0];
+ }
+ int[] ret = new int[batch.size() / args.length];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = EXECUTE_FAILED;
+ }
+ int errs = 0;
+ int index = 0;
+ for (int i = 0; i < ret.length; i++) {
+ for (int k = 0; k < args.length; k++) {
+ BatchArg b = (BatchArg) batch.get(index++);
+
+ args[i] = b.arg;
+ blobs[i] = b.blob;
+ }
+ try {
+ ret[i] = executeUpdate();
+ } catch (SQLException e) {
+ ++errs;
+ }
+ }
+ if (errs > 0) {
+ throw new BatchUpdateException("batch failed", ret);
+ }
+ return ret;
+ }
+
+ public void clearBatch() throws SQLException {
+ if (batch != null) {
+ batch.clear();
+ batch = null;
+ }
+ }
+
+ public void setCharacterStream(int parameterIndex,
+ java.io.Reader reader,
+ int length) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setRef(int i, Ref x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBlob(int i, Blob x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setClob(int i, Clob x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setArray(int i, Array x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ return rs.getMetaData();
+ }
+
+ public void setDate(int parameterIndex, java.sql.Date x, Calendar cal)
+ throws SQLException {
+ setDate(parameterIndex, x);
+ }
+
+ public void setTime(int parameterIndex, java.sql.Time x, Calendar cal)
+ throws SQLException {
+ setTime(parameterIndex, x);
+ }
+
+ public void setTimestamp(int parameterIndex, java.sql.Timestamp x,
+ Calendar cal) throws SQLException {
+ setTimestamp(parameterIndex, x);
+ }
+
+ public void setNull(int parameterIndex, int sqlType, String typeName)
+ throws SQLException {
+ setNull(parameterIndex, sqlType);
+ }
+
+ public ParameterMetaData getParameterMetaData() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void registerOutputParameter(String parameterName, int sqlType)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void registerOutputParameter(String parameterName, int sqlType,
+ int scale)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void registerOutputParameter(String parameterName, int sqlType,
+ String typeName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.net.URL getURL(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setURL(int parameterIndex, java.net.URL url)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setNull(String parameterName, int sqlType)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBoolean(String parameterName, boolean val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setByte(String parameterName, byte val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setShort(String parameterName, short val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setInt(String parameterName, int val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setLong(String parameterName, long val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setFloat(String parameterName, float val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setDouble(String parameterName, double val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBigDecimal(String parameterName, BigDecimal val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setString(String parameterName, String val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBytes(String parameterName, byte val[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setDate(String parameterName, java.sql.Date val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTime(String parameterName, java.sql.Time val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTimestamp(String parameterName, java.sql.Timestamp val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setAsciiStream(String parameterName,
+ java.io.InputStream s, int length)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setBinaryStream(String parameterName,
+ java.io.InputStream s, int length)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setObject(String parameterName, Object val, int targetSqlType,
+ int scale)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setObject(String parameterName, Object val, int targetSqlType)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setObject(String parameterName, Object val)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setCharacterStream(String parameterName,
+ java.io.Reader r, int length)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setDate(String parameterName, java.sql.Date val,
+ Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTime(String parameterName, java.sql.Time val,
+ Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setTimestamp(String parameterName, java.sql.Timestamp val,
+ Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setNull(String parameterName, int sqlType, String typeName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public String getString(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean getBoolean(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte getByte(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public short getShort(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getInt(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public long getLong(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public float getFloat(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public double getDouble(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte[] getBytes(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Date getDate(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Time getTime(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Timestamp getTimestamp(String parameterName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public BigDecimal getBigDecimal(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(String parameterName, Map map)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(int parameterIndex, Map map)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Ref getRef(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Ref getRef(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Blob getBlob(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Blob getBlob(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Clob getClob(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Clob getClob(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Array getArray(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Array getArray(int parameterIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Date getDate(String parameterName, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Date getDate(int parameterIndex, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Time getTime(String parameterName, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Time getTime(int parameterIndex, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Timestamp getTimestamp(String parameterName, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Timestamp getTimestamp(int parameterIndex, Calendar cal)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.net.URL getURL(String parameterName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+}
diff --git a/sql/src/main/java/SQLite/JDBC2y/JDBCResultSet.java b/sql/src/main/java/SQLite/JDBC2y/JDBCResultSet.java
new file mode 100644
index 0000000..06384eb
--- /dev/null
+++ b/sql/src/main/java/SQLite/JDBC2y/JDBCResultSet.java
@@ -0,0 +1,932 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.math.BigDecimal;
+
+public class JDBCResultSet implements java.sql.ResultSet {
+
+ /**
+ * Current row to be retrieved.
+ */
+ private int row;
+
+ /**
+ * Table returned by Database.get_table()
+ */
+ protected SQLite.TableResult tr;
+
+ /**
+ * Statement from which result set was produced.
+ */
+ private JDBCStatement s;
+
+ /**
+ * Meta data for result set or null.
+ */
+ private JDBCResultSetMetaData m;
+
+ /**
+ * Last result cell retrieved or null.
+ */
+ private String lastg;
+
+
+ public JDBCResultSet(SQLite.TableResult tr, JDBCStatement s) {
+ this.tr = tr;
+ this.s = s;
+ this.m = null;
+ this.lastg = null;
+ this.row = -1;
+ }
+
+ public boolean next() throws SQLException {
+ if (tr == null) {
+ return false;
+ }
+ row++;
+ return row < tr.nrows;
+ }
+
+ public int findColumn(String columnName) throws SQLException {
+ JDBCResultSetMetaData m = (JDBCResultSetMetaData) getMetaData();
+ return m.findColByName(columnName);
+ }
+
+ public int getRow() throws SQLException {
+ if (tr == null) {
+ throw new SQLException("no rows");
+ }
+ return row + 1;
+ }
+
+ public boolean previous() throws SQLException {
+ if (tr == null) {
+ return false;
+ }
+ if (row >= 0) {
+ row--;
+ }
+ return row >= 0;
+ }
+
+ public boolean absolute(int row) throws SQLException {
+ if (tr == null) {
+ return false;
+ }
+ if (row < 0) {
+ row = tr.nrows + 1 + row;
+ }
+ row--;
+ if (row < 0 || row > tr.nrows) {
+ return false;
+ }
+ this.row = row;
+ return true;
+ }
+
+ public boolean relative(int row) throws SQLException {
+ if (tr == null) {
+ return false;
+ }
+ if (this.row + row < 0 || this.row + row >= tr.nrows) {
+ return false;
+ }
+ this.row += row;
+ return true;
+ }
+
+ public void setFetchDirection(int dir) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getFetchDirection() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setFetchSize(int fsize) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getFetchSize() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public String getString(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ return lastg;
+ }
+
+ public String getString(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getString(col);
+ }
+
+ public int getInt(int columnIndex) throws SQLException {
+ Integer i = internalGetInt(columnIndex);
+ if (i != null) {
+ return i.intValue();
+ }
+ return 0;
+ }
+
+ private Integer internalGetInt(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Integer.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public int getInt(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getInt(col);
+ }
+
+ public boolean getBoolean(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean getBoolean(String columnName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSetMetaData getMetaData() throws SQLException {
+ if (m == null) {
+ m = new JDBCResultSetMetaData(this);
+ }
+ return m;
+ }
+
+ public short getShort(int columnIndex) throws SQLException {
+ Short s = internalGetShort(columnIndex);
+ if (s != null) {
+ return s.shortValue();
+ }
+ return 0;
+ }
+
+ private Short internalGetShort(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Short.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public short getShort(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getShort(col);
+ }
+
+ public java.sql.Time getTime(int columnIndex) throws SQLException {
+ return internalGetTime(columnIndex, null);
+ }
+
+ private java.sql.Time internalGetTime(int columnIndex,
+ java.util.Calendar cal)
+ throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return java.sql.Time.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public java.sql.Time getTime(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getTime(col);
+ }
+
+ public java.sql.Time getTime(int columnIndex, java.util.Calendar cal)
+ throws SQLException {
+ return internalGetTime(columnIndex, cal);
+ }
+
+ public java.sql.Time getTime(String columnName, java.util.Calendar cal)
+ throws SQLException{
+ int col = findColumn(columnName);
+ return getTime(col, cal);
+ }
+
+ public java.sql.Timestamp getTimestamp(int columnIndex)
+ throws SQLException{
+ return internalGetTimestamp(columnIndex, null);
+ }
+
+ private java.sql.Timestamp internalGetTimestamp(int columnIndex,
+ java.util.Calendar cal)
+ throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return java.sql.Timestamp.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public java.sql.Timestamp getTimestamp(String columnName)
+ throws SQLException{
+ int col = findColumn(columnName);
+ return getTimestamp(col);
+ }
+
+ public java.sql.Timestamp getTimestamp(int columnIndex,
+ java.util.Calendar cal)
+ throws SQLException {
+ return internalGetTimestamp(columnIndex, cal);
+ }
+
+ public java.sql.Timestamp getTimestamp(String columnName,
+ java.util.Calendar cal)
+ throws SQLException {
+ int col = findColumn(columnName);
+ return getTimestamp(col, cal);
+ }
+
+ public java.sql.Date getDate(int columnIndex) throws SQLException {
+ return internalGetDate(columnIndex, null);
+ }
+
+ private java.sql.Date internalGetDate(int columnIndex,
+ java.util.Calendar cal)
+ throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return java.sql.Date.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public java.sql.Date getDate(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getDate(col);
+ }
+
+ public java.sql.Date getDate(int columnIndex, java.util.Calendar cal)
+ throws SQLException{
+ return internalGetDate(columnIndex, cal);
+ }
+
+ public java.sql.Date getDate(String columnName, java.util.Calendar cal)
+ throws SQLException{
+ int col = findColumn(columnName);
+ return getDate(col, cal);
+ }
+
+ public double getDouble(int columnIndex) throws SQLException {
+ Double d = internalGetDouble(columnIndex);
+ if (d != null) {
+ return d.doubleValue();
+ }
+ return 0;
+ }
+
+ private Double internalGetDouble(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Double.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public double getDouble(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getDouble(col);
+ }
+
+ public float getFloat(int columnIndex) throws SQLException {
+ Float f = internalGetFloat(columnIndex);
+ if (f != null) {
+ return f.floatValue();
+ }
+ return 0;
+ }
+
+ private Float internalGetFloat(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Float.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public float getFloat(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getFloat(col);
+ }
+
+ public long getLong(int columnIndex) throws SQLException {
+ Long l = internalGetLong(columnIndex);
+ if (l != null) {
+ return l.longValue();
+ }
+ return 0;
+ }
+
+ private Long internalGetLong(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ try {
+ return Long.valueOf(lastg);
+ } catch (java.lang.Exception e) {
+ lastg = null;
+ }
+ return null;
+ }
+
+ public long getLong(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getLong(col);
+ }
+
+ @Deprecated
+ public java.io.InputStream getUnicodeStream(int columnIndex)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ @Deprecated
+ public java.io.InputStream getUnicodeStream(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.InputStream getAsciiStream(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.InputStream getAsciiStream(int columnIndex)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public BigDecimal getBigDecimal(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ @Deprecated
+ public BigDecimal getBigDecimal(String columnName, int scale)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ @Deprecated
+ public BigDecimal getBigDecimal(int columnIndex, int scale)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.InputStream getBinaryStream(int columnIndex)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.InputStream getBinaryStream(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte getByte(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte getByte(String columnName) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public byte[] getBytes(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ byte ret[] = null;
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ if (lastg != null) {
+ ret = SQLite.StringEncoder.decode(lastg);
+ }
+ return ret;
+ }
+
+ public byte[] getBytes(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getBytes(col);
+ }
+
+ public String getCursorName() throws SQLException {
+ return null;
+ }
+
+ public Object getObject(int columnIndex) throws SQLException {
+ if (tr == null || columnIndex < 1 || columnIndex > tr.ncolumns) {
+ throw new SQLException("column " + columnIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[columnIndex - 1];
+ Object ret = lastg;
+ if (tr instanceof TableResultX) {
+ switch (((TableResultX) tr).sql_type[columnIndex - 1]) {
+ case Types.SMALLINT:
+ ret = internalGetShort(columnIndex);
+ break;
+ case Types.INTEGER:
+ ret = internalGetInt(columnIndex);
+ break;
+ case Types.DOUBLE:
+ ret = internalGetDouble(columnIndex);
+ break;
+ case Types.FLOAT:
+ ret = internalGetFloat(columnIndex);
+ break;
+ case Types.BIGINT:
+ ret = internalGetLong(columnIndex);
+ break;
+ case Types.BINARY:
+ case Types.VARBINARY:
+ case Types.LONGVARBINARY:
+ ret = getBytes(columnIndex);
+ break;
+ case Types.NULL:
+ ret = null;
+ break;
+ /* defaults to String below */
+ }
+ }
+ return ret;
+ }
+
+ public Object getObject(String columnName) throws SQLException {
+ int col = findColumn(columnName);
+ return getObject(col);
+ }
+
+ public Object getObject(int columnIndex, java.util.Map map)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Object getObject(String columnIndex, java.util.Map map)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Ref getRef(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Ref getRef(String columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Blob getBlob(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Blob getBlob(String columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Clob getClob(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Clob getClob(String columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Array getArray(int columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.sql.Array getArray(String columnIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.Reader getCharacterStream(int columnIndex)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public java.io.Reader getCharacterStream(String columnName)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean wasNull() throws SQLException {
+ return lastg == null;
+ }
+
+ public void clearWarnings() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean isFirst() throws SQLException {
+ if (tr == null) {
+ return true;
+ }
+ return row == 0;
+ }
+
+ public boolean isBeforeFirst() throws SQLException {
+ if (tr == null || tr.nrows <= 0) {
+ return false;
+ }
+ return row < 0;
+ }
+
+ public void beforeFirst() throws SQLException {
+ if (tr == null) {
+ return;
+ }
+ row = -1;
+ }
+
+ public boolean first() throws SQLException {
+ if (tr == null || tr.nrows <= 0) {
+ return false;
+ }
+ row = 0;
+ return true;
+ }
+
+ public boolean isAfterLast() throws SQLException {
+ if (tr == null || tr.nrows <= 0) {
+ return false;
+ }
+ return row >= tr.nrows;
+ }
+
+ public void afterLast() throws SQLException {
+ if (tr == null) {
+ return;
+ }
+ row = tr.nrows;
+ }
+
+ public boolean isLast() throws SQLException {
+ if (tr == null) {
+ return true;
+ }
+ return row == tr.nrows - 1;
+ }
+
+ public boolean last() throws SQLException {
+ if (tr == null || tr.nrows <= 0) {
+ return false;
+ }
+ row = tr.nrows -1;
+ return true;
+ }
+
+ public int getType() throws SQLException {
+ return TYPE_SCROLL_INSENSITIVE;
+ }
+
+ public int getConcurrency() throws SQLException {
+ return CONCUR_READ_ONLY;
+ }
+
+ public boolean rowUpdated() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean rowInserted() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean rowDeleted() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void insertRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void deleteRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void refreshRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void cancelRowUpdates() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void moveToInsertRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void moveToCurrentRow() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateNull(int colIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBoolean(int colIndex, boolean b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateByte(int colIndex, byte b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateShort(int colIndex, short b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateInt(int colIndex, int b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateLong(int colIndex, long b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateFloat(int colIndex, float f) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateDouble(int colIndex, double f) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBigDecimal(int colIndex, BigDecimal f)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateString(int colIndex, String s) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBytes(int colIndex, byte[] s) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateDate(int colIndex, java.sql.Date d) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateTime(int colIndex, java.sql.Time t) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateTimestamp(int colIndex, java.sql.Timestamp t)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateAsciiStream(int colIndex, java.io.InputStream in, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBinaryStream(int colIndex, java.io.InputStream in, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateCharacterStream(int colIndex, java.io.Reader in, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateObject(int colIndex, Object obj) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateObject(int colIndex, Object obj, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateNull(String colIndex) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBoolean(String colIndex, boolean b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateByte(String colIndex, byte b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateShort(String colIndex, short b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateInt(String colIndex, int b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateLong(String colIndex, long b) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateFloat(String colIndex, float f) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateDouble(String colIndex, double f) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBigDecimal(String colIndex, BigDecimal f)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateString(String colIndex, String s) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBytes(String colIndex, byte[] s) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateDate(String colIndex, java.sql.Date d)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateTime(String colIndex, java.sql.Time t)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateTimestamp(String colIndex, java.sql.Timestamp t)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateAsciiStream(String colIndex, java.io.InputStream in,
+ int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBinaryStream(String colIndex, java.io.InputStream in,
+ int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateCharacterStream(String colIndex, java.io.Reader in,
+ int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateObject(String colIndex, Object obj)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateObject(String colIndex, Object obj, int s)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public Statement getStatement() throws SQLException {
+ if (s == null) {
+ throw new SQLException("stale result set");
+ }
+ return s;
+ }
+
+ public void close() throws SQLException {
+ s = null;
+ tr = null;
+ lastg = null;
+ row = -1;
+ }
+
+ public java.net.URL getURL(int colIndex) throws SQLException {
+ if (tr == null || colIndex < 1 || colIndex > tr.ncolumns) {
+ throw new SQLException("column " + colIndex + " not found");
+ }
+ String rd[] = (String []) tr.rows.elementAt(row);
+ lastg = rd[colIndex - 1];
+ java.net.URL url = null;
+ if (lastg == null) {
+ return url;
+ }
+ try {
+ url = new java.net.URL(lastg);
+ } catch (java.lang.Exception e) {
+ url = null;
+ }
+ return url;
+ }
+
+ public java.net.URL getURL(String colIndex) throws SQLException {
+ int col = findColumn(colIndex);
+ return getURL(col);
+ }
+
+ public void updateRef(int colIndex, java.sql.Ref x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateRef(String colIndex, java.sql.Ref x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBlob(int colIndex, java.sql.Blob x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateBlob(String colIndex, java.sql.Blob x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateClob(int colIndex, java.sql.Clob x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateClob(String colIndex, java.sql.Clob x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateArray(int colIndex, java.sql.Array x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void updateArray(String colIndex, java.sql.Array x)
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+}
diff --git a/sql/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java b/sql/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java
new file mode 100644
index 0000000..934ca78
--- /dev/null
+++ b/sql/src/main/java/SQLite/JDBC2y/JDBCResultSetMetaData.java
@@ -0,0 +1,212 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+
+public class JDBCResultSetMetaData implements java.sql.ResultSetMetaData {
+
+ private JDBCResultSet r;
+
+ public JDBCResultSetMetaData(JDBCResultSet r) {
+ this.r = r;
+ }
+
+ public String getCatalogName(int column) throws java.sql.SQLException {
+ return null;
+ }
+
+ public String getColumnClassName(int column) throws java.sql.SQLException {
+ column--;
+ if (r != null && r.tr != null) {
+ if (column < 0 || column >= r.tr.ncolumns) {
+ return null;
+ }
+ if (r.tr instanceof TableResultX) {
+ switch (((TableResultX) r.tr).sql_type[column]) {
+ case Types.SMALLINT: return "java.lang.Short";
+ case Types.INTEGER: return "java.lang.Integer";
+ case Types.DOUBLE: return "java.lang.Double";
+ case Types.FLOAT: return "java.lang.Float";
+ case Types.BIGINT: return "java.lang.Long";
+ case Types.DATE: return "java.sql.Date";
+ case Types.TIME: return "java.sql.Time";
+ case Types.TIMESTAMP: return "java.sql.Timestamp";
+ case Types.BINARY:
+ case Types.VARBINARY: return "[B";
+ /* defaults to varchar below */
+ }
+ }
+ return "java.lang.String";
+ }
+ return null;
+ }
+
+ public int getColumnCount() throws java.sql.SQLException {
+ if (r != null && r.tr != null) {
+ return r.tr.ncolumns;
+ }
+ return 0;
+ }
+
+ public int getColumnDisplaySize(int column) throws java.sql.SQLException {
+ return 0;
+ }
+
+ public String getColumnLabel(int column) throws java.sql.SQLException {
+ column--;
+ String c = null;
+ if (r != null && r.tr != null) {
+ if (column < 0 || column >= r.tr.ncolumns) {
+ return c;
+ }
+ c = r.tr.column[column];
+ }
+ return c;
+ }
+
+ public String getColumnName(int column) throws java.sql.SQLException {
+ column--;
+ String c = null;
+ if (r != null && r.tr != null) {
+ if (column < 0 || column >= r.tr.ncolumns) {
+ return c;
+ }
+ c = r.tr.column[column];
+ if (c != null) {
+ int i = c.indexOf('.');
+ if (i > 0) {
+ return c.substring(i + 1);
+ }
+ }
+ }
+ return c;
+ }
+
+ public int getColumnType(int column) throws java.sql.SQLException {
+ column--;
+ if (r != null && r.tr != null) {
+ if (column >= 0 && column < r.tr.ncolumns) {
+ if (r.tr instanceof TableResultX) {
+ return ((TableResultX) r.tr).sql_type[column];
+ }
+ return Types.VARCHAR;
+ }
+ }
+ throw new SQLException("bad column index");
+ }
+
+ public String getColumnTypeName(int column) throws java.sql.SQLException {
+ column--;
+ if (r != null && r.tr != null) {
+ if (column >= 0 && column < r.tr.ncolumns) {
+ if (r.tr instanceof TableResultX) {
+ switch (((TableResultX) r.tr).sql_type[column]) {
+ case Types.SMALLINT: return "smallint";
+ case Types.INTEGER: return "integer";
+ case Types.DOUBLE: return "double";
+ case Types.FLOAT: return "float";
+ case Types.BIGINT: return "bigint";
+ case Types.DATE: return "date";
+ case Types.TIME: return "time";
+ case Types.TIMESTAMP: return "timestamp";
+ case Types.BINARY: return "binary";
+ case Types.VARBINARY: return "varbinary";
+ /* defaults to varchar below */
+ }
+ }
+ return "varchar";
+ }
+ }
+ throw new SQLException("bad column index");
+ }
+
+ public int getPrecision(int column) throws java.sql.SQLException {
+ return 0;
+ }
+
+ public int getScale(int column) throws java.sql.SQLException {
+ return 0;
+ }
+
+ public String getSchemaName(int column) throws java.sql.SQLException {
+ return null;
+ }
+
+ public String getTableName(int column) throws java.sql.SQLException {
+ column--;
+ String c = null;
+ if (r != null && r.tr != null) {
+ if (column < 0 || column >= r.tr.ncolumns) {
+ return c;
+ }
+ c = r.tr.column[column];
+ if (c != null) {
+ int i = c.indexOf('.');
+ if (i > 0) {
+ return c.substring(0, i);
+ }
+ c = null;
+ }
+ }
+ return c;
+ }
+
+ public boolean isAutoIncrement(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isCaseSensitive(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isCurrency(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isDefinitelyWritable(int column)
+ throws java.sql.SQLException {
+ return true;
+ }
+
+ public int isNullable(int column) throws java.sql.SQLException {
+ return columnNullableUnknown;
+ }
+
+ public boolean isReadOnly(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isSearchable(int column) throws java.sql.SQLException {
+ return true;
+ }
+
+ public boolean isSigned(int column) throws java.sql.SQLException {
+ return false;
+ }
+
+ public boolean isWritable(int column) throws java.sql.SQLException {
+ return true;
+ }
+
+ int findColByName(String columnName) throws java.sql.SQLException {
+ String c = null;
+ if (r != null && r.tr != null) {
+ for (int i = 0; i < r.tr.ncolumns; i++) {
+ c = r.tr.column[i];
+ if (c != null) {
+ if (c.compareToIgnoreCase(columnName) == 0) {
+ return i + 1;
+ }
+ int k = c.indexOf('.');
+ if (k > 0) {
+ c = c.substring(k + 1);
+ if (c.compareToIgnoreCase(columnName) == 0) {
+ return i + 1;
+ }
+ }
+ }
+ c = null;
+ }
+ }
+ throw new SQLException("column " + columnName + " not found");
+ }
+}
diff --git a/sql/src/main/java/SQLite/JDBC2y/JDBCStatement.java b/sql/src/main/java/SQLite/JDBC2y/JDBCStatement.java
new file mode 100644
index 0000000..99d12d3
--- /dev/null
+++ b/sql/src/main/java/SQLite/JDBC2y/JDBCStatement.java
@@ -0,0 +1,287 @@
+package SQLite.JDBC2y;
+
+import java.sql.*;
+import java.util.*;
+
+public class JDBCStatement implements java.sql.Statement {
+
+ protected JDBCConnection conn;
+ protected JDBCResultSet rs;
+ protected int updcnt;
+ private ArrayList<String> batch;
+
+ public JDBCStatement(JDBCConnection conn) {
+ this.conn = conn;
+ this.updcnt = 0;
+ this.rs = null;
+ this.batch = null;
+ }
+
+ public void setFetchSize(int fetchSize) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getFetchSize() throws SQLException {
+ return 1;
+ }
+
+ public int getMaxRows() throws SQLException {
+ return 0;
+ }
+
+ public void setMaxRows(int max) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setFetchDirection(int fetchDirection) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getFetchDirection() throws SQLException {
+ return ResultSet.FETCH_UNKNOWN;
+ }
+
+ public int getResultSetConcurrency() throws SQLException {
+ return ResultSet.CONCUR_READ_ONLY;
+ }
+
+ public int getResultSetType() throws SQLException {
+ return ResultSet.TYPE_SCROLL_INSENSITIVE;
+ }
+
+ public void setQueryTimeout(int seconds) throws SQLException {
+ conn.timeout = seconds * 1000;
+ if (conn.timeout < 0) {
+ conn.timeout = 120000;
+ } else if (conn.timeout < 1000) {
+ conn.timeout = 5000;
+ }
+ }
+
+ public int getQueryTimeout() throws SQLException {
+ return conn.timeout;
+ }
+
+ public ResultSet getResultSet() throws SQLException {
+ return rs;
+ }
+
+ ResultSet executeQuery(String sql, String args[], boolean updonly)
+ throws SQLException {
+ SQLite.TableResult tr = null;
+ if (rs != null) {
+ rs.close();
+ rs = null;
+ }
+ updcnt = -1;
+ if (conn == null || conn.db == null) {
+ throw new SQLException("stale connection");
+ }
+ int busy = 0;
+ boolean starttrans = !conn.autocommit && !conn.intrans;
+ while (true) {
+ try {
+ if (starttrans) {
+ conn.db.exec("BEGIN TRANSACTION", null);
+ conn.intrans = true;
+ }
+ if (args == null) {
+ if (updonly) {
+ conn.db.exec(sql, null);
+ } else {
+ tr = conn.db.get_table(sql);
+ }
+ } else {
+ if (updonly) {
+ conn.db.exec(sql, null, args);
+ } else {
+ tr = conn.db.get_table(sql, args);
+ }
+ }
+ updcnt = (int) conn.db.changes();
+ } catch (SQLite.Exception e) {
+ if (conn.db.is3() &&
+ conn.db.last_error() == SQLite.Constants.SQLITE_BUSY &&
+ conn.busy3(conn.db, ++busy)) {
+ try {
+ if (starttrans && conn.intrans) {
+ conn.db.exec("ROLLBACK", null);
+ conn.intrans = false;
+ }
+ } catch (SQLite.Exception ee) {
+ }
+ try {
+ int ms = 20 + busy * 10;
+ if (ms > 1000) {
+ ms = 1000;
+ }
+ synchronized (this) {
+ this.wait(ms);
+ }
+ } catch (java.lang.Exception eee) {
+ }
+ continue;
+ }
+ throw new SQLException(e.toString());
+ }
+ break;
+ }
+ if (!updonly && tr == null) {
+ throw new SQLException("no result set produced");
+ }
+ if (!updonly && tr != null) {
+ rs = new JDBCResultSet(new TableResultX(tr), this);
+ }
+ return rs;
+ }
+
+ public ResultSet executeQuery(String sql) throws SQLException {
+ return executeQuery(sql, null, false);
+ }
+
+ public boolean execute(String sql) throws SQLException {
+ return executeQuery(sql) != null;
+ }
+
+ public void cancel() throws SQLException {
+ if (conn == null || conn.db == null) {
+ throw new SQLException("stale connection");
+ }
+ conn.db.interrupt();
+ }
+
+ public void clearWarnings() throws SQLException {
+ }
+
+ public Connection getConnection() throws SQLException {
+ return conn;
+ }
+
+ public void addBatch(String sql) throws SQLException {
+ if (batch == null) {
+ batch = new ArrayList<String>(1);
+ }
+ batch.add(sql);
+ }
+
+ public int[] executeBatch() throws SQLException {
+ if (batch == null) {
+ return new int[0];
+ }
+ int[] ret = new int[batch.size()];
+ for (int i = 0; i < ret.length; i++) {
+ ret[i] = EXECUTE_FAILED;
+ }
+ int errs = 0;
+ for (int i = 0; i < ret.length; i++) {
+ try {
+ execute((String) batch.get(i));
+ ret[i] = updcnt;
+ } catch (SQLException e) {
+ ++errs;
+ }
+ }
+ if (errs > 0) {
+ throw new BatchUpdateException("batch failed", ret);
+ }
+ return ret;
+ }
+
+ public void clearBatch() throws SQLException {
+ if (batch != null) {
+ batch.clear();
+ batch = null;
+ }
+ }
+
+ public void close() throws SQLException {
+ clearBatch();
+ conn = null;
+ }
+
+ public int executeUpdate(String sql) throws SQLException {
+ executeQuery(sql, null, true);
+ return updcnt;
+ }
+
+ public int getMaxFieldSize() throws SQLException {
+ return 0;
+ }
+
+ public boolean getMoreResults() throws SQLException {
+ if (rs != null) {
+ rs.close();
+ rs = null;
+ }
+ return false;
+ }
+
+ public int getUpdateCount() throws SQLException {
+ return updcnt;
+ }
+
+ public SQLWarning getWarnings() throws SQLException {
+ return null;
+ }
+
+ public void setCursorName(String name) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setEscapeProcessing(boolean enable) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public void setMaxFieldSize(int max) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean getMoreResults(int x) throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public ResultSet getGeneratedKeys() throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int executeUpdate(String sql, int autokeys)
+ throws SQLException {
+ if (autokeys != Statement.NO_GENERATED_KEYS) {
+ throw new SQLException("not supported");
+ }
+ return executeUpdate(sql);
+ }
+
+ public int executeUpdate(String sql, int colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int executeUpdate(String sql, String colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean execute(String sql, int autokeys)
+ throws SQLException {
+ if (autokeys != Statement.NO_GENERATED_KEYS) {
+ throw new SQLException("not supported");
+ }
+ return execute(sql);
+ }
+
+ public boolean execute(String sql, int colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public boolean execute(String sql, String colIndexes[])
+ throws SQLException {
+ throw new SQLException("not supported");
+ }
+
+ public int getResultSetHoldability() throws SQLException {
+ return ResultSet.HOLD_CURSORS_OVER_COMMIT;
+ }
+
+}
diff --git a/sql/src/main/java/SQLite/JDBC2y/TableResultX.java b/sql/src/main/java/SQLite/JDBC2y/TableResultX.java
new file mode 100644
index 0000000..205372f
--- /dev/null
+++ b/sql/src/main/java/SQLite/JDBC2y/TableResultX.java
@@ -0,0 +1,37 @@
+package SQLite.JDBC2y;
+
+import java.sql.Types;
+import java.util.Vector;
+
+public class TableResultX extends SQLite.TableResult {
+ public int sql_type[];
+
+ public TableResultX() {
+ super();
+ sql_type = new int[this.ncolumns];
+ for (int i = 0; i < this.ncolumns; i++) {
+ sql_type[i] = Types.VARCHAR;
+ }
+ }
+
+ public TableResultX(SQLite.TableResult tr) {
+ this.column = tr.column;
+ this.rows = tr.rows;
+ this.ncolumns = tr.ncolumns;
+ this.nrows = tr.nrows;
+ this.types = tr.types;
+ sql_type = new int[tr.ncolumns];
+ for (int i = 0; i < this.ncolumns; i++) {
+ sql_type[i] = Types.VARCHAR;
+ }
+ if (tr.types != null) {
+ for (int i = 0; i < tr.types.length; i++) {
+ sql_type[i] = JDBCDatabaseMetaData.mapSqlType(tr.types[i]);
+ }
+ }
+ }
+
+ void sql_types(int types[]) {
+ sql_type = types;
+ }
+}
diff --git a/sql/src/main/java/SQLite/JDBCDriver.java b/sql/src/main/java/SQLite/JDBCDriver.java
new file mode 100644
index 0000000..63b95ee
--- /dev/null
+++ b/sql/src/main/java/SQLite/JDBCDriver.java
@@ -0,0 +1,109 @@
+package SQLite;
+
+import java.sql.*;
+import java.util.Properties;
+
+public class JDBCDriver implements java.sql.Driver {
+
+ public static final int MAJORVERSION = 1;
+ public static final int MINORVERSION = 2;
+
+ private static java.lang.reflect.Constructor makeConn = null;
+
+ protected Connection conn;
+
+ static {
+ try {
+ Class connClass = null;
+ Class args[] = new Class[2];
+ args[0] = Class.forName("java.lang.String");
+ args[1] = args[0];
+ String jvers = java.lang.System.getProperty("java.version");
+ String cvers;
+ if (jvers == null || jvers.startsWith("1.0")) {
+ throw new java.lang.Exception("unsupported java version");
+ } else if (jvers.startsWith("1.1")) {
+ cvers = "SQLite.JDBC1.JDBCConnection";
+ } else if (jvers.startsWith("1.2") || jvers.startsWith("1.3")) {
+ cvers = "SQLite.JDBC2.JDBCConnection";
+ } else if (jvers.startsWith("1.4")) {
+ cvers = "SQLite.JDBC2x.JDBCConnection";
+ } else if (jvers.startsWith("1.5")) {
+ cvers = "SQLite.JDBC2y.JDBCConnection";
+ try {
+ Class.forName(cvers);
+ } catch (java.lang.Exception e) {
+ cvers = "SQLite.JDBC2x.JDBCConnection";
+ }
+ } else {
+ cvers = "SQLite.JDBC2z.JDBCConnection";
+ try {
+ Class.forName(cvers);
+ } catch (java.lang.Exception e) {
+ cvers = "SQLite.JDBC2y.JDBCConnection";
+ try {
+ Class.forName(cvers);
+ } catch (java.lang.Exception ee) {
+ cvers = "SQLite.JDBC2x.JDBCConnection";
+ }
+ }
+ }
+ connClass = Class.forName(cvers);
+ makeConn = connClass.getConstructor(args);
+ java.sql.DriverManager.registerDriver(new JDBCDriver());
+ } catch (java.lang.Exception e) {
+ System.err.println(e);
+ }
+ }
+
+ public JDBCDriver() {
+ }
+
+ public boolean acceptsURL(String url) throws SQLException {
+ return url.startsWith("sqlite:/") ||
+ url.startsWith("jdbc:sqlite:/");
+ }
+
+ public Connection connect(String url, Properties info)
+ throws SQLException {
+ if (!acceptsURL(url)) {
+ return null;
+ }
+ Object args[] = new Object[2];
+ args[0] = url;
+ if (info != null) {
+ args[1] = info.getProperty("encoding");
+ }
+ if (args[1] == null) {
+ args[1] = java.lang.System.getProperty("SQLite.encoding");
+ }
+ try {
+ conn = (Connection) makeConn.newInstance(args);
+ } catch (java.lang.reflect.InvocationTargetException ie) {
+ throw new SQLException(ie.getTargetException().toString());
+ } catch (java.lang.Exception e) {
+ throw new SQLException(e.toString());
+ }
+ return conn;
+ }
+
+ public int getMajorVersion() {
+ return MAJORVERSION;
+ }
+
+ public int getMinorVersion() {
+ return MINORVERSION;
+ }
+
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
+ throws SQLException {
+ DriverPropertyInfo p[] = new DriverPropertyInfo[1];
+ DriverPropertyInfo pp = new DriverPropertyInfo("encoding", "");
+ p[0] = pp;
+ return p;
+ }
+
+ public boolean jdbcCompliant() {
+ return false;
+ }
+}
diff --git a/sql/src/main/java/SQLite/ProgressHandler.java b/sql/src/main/java/SQLite/ProgressHandler.java
new file mode 100644
index 0000000..b2ec7c0
--- /dev/null
+++ b/sql/src/main/java/SQLite/ProgressHandler.java
@@ -0,0 +1,17 @@
+package SQLite;
+
+/**
+ * Callback interface for SQLite's user defined progress handler.
+ */
+
+public interface ProgressHandler {
+
+ /**
+ * Invoked for N SQLite VM opcodes.
+ * The method should return true to continue the
+ * current query, or false in order
+ * to abandon the action.<BR><BR>
+ */
+
+ public boolean progress();
+}
diff --git a/sql/src/main/java/SQLite/Shell.java b/sql/src/main/java/SQLite/Shell.java
new file mode 100644
index 0000000..78d37a1
--- /dev/null
+++ b/sql/src/main/java/SQLite/Shell.java
@@ -0,0 +1,669 @@
+package SQLite;
+
+import SQLite.*;
+import java.io.*;
+import java.util.*;
+
+/**
+ * SQLite command line shell. This is a partial reimplementaion
+ * of sqlite/src/shell.c and can be invoked by:<P>
+ *
+ * <verb>
+ * java SQLite.Shell [OPTIONS] database [SHELLCMD]
+ * or
+ * java -jar sqlite.jar [OPTIONS] database [SHELLCMD]
+ * </verb>
+ */
+
+public class Shell implements Callback {
+ Database db;
+ boolean echo;
+ int count;
+ int mode;
+ boolean showHeader;
+ String tableName;
+ String sep;
+ String cols[];
+ int colwidth[];
+ String destTable;
+ PrintWriter pw;
+ PrintWriter err;
+
+ static final int MODE_Line = 0;
+ static final int MODE_Column = 1;
+ static final int MODE_List = 2;
+ static final int MODE_Semi = 3;
+ static final int MODE_Html = 4;
+ static final int MODE_Insert = 5;
+ static final int MODE_Insert2 = 6;
+
+ public Shell(PrintWriter pw, PrintWriter err) {
+ this.pw = pw;
+ this.err = err;
+ }
+
+ public Shell(PrintStream ps, PrintStream errs) {
+ pw = new PrintWriter(ps);
+ err = new PrintWriter(errs);
+ }
+
+ protected Object clone() {
+ Shell s = new Shell(this.pw, this.err);
+ s.db = db;
+ s.echo = echo;
+ s.mode = mode;
+ s.count = 0;
+ s.showHeader = showHeader;
+ s.tableName = tableName;
+ s.sep = sep;
+ s.colwidth = colwidth;
+ return s;
+ }
+
+ static public String sql_quote_dbl(String str) {
+ if (str == null) {
+ return "NULL";
+ }
+ int i, single = 0, dbl = 0;
+ for (i = 0; i < str.length(); i++) {
+ if (str.charAt(i) == '\'') {
+ single++;
+ } else if (str.charAt(i) == '"') {
+ dbl++;
+ }
+ }
+ if (dbl == 0) {
+ return "\"" + str + "\"";
+ }
+ StringBuffer sb = new StringBuffer("\"");
+ for (i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == '"') {
+ sb.append("\"\"");
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ static public String sql_quote(String str) {
+ if (str == null) {
+ return "NULL";
+ }
+ int i, single = 0, dbl = 0;
+ for (i = 0; i < str.length(); i++) {
+ if (str.charAt(i) == '\'') {
+ single++;
+ } else if (str.charAt(i) == '"') {
+ dbl++;
+ }
+ }
+ if (single == 0) {
+ return "'" + str + "'";
+ }
+ if (dbl == 0) {
+ return "\"" + str + "\"";
+ }
+ StringBuffer sb = new StringBuffer("'");
+ for (i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == '\'') {
+ sb.append("''");
+ } else {
+ sb.append(c);
+ }
+ }
+ return sb.toString();
+ }
+
+ static String html_quote(String str) {
+ if (str == null) {
+ return "NULL";
+ }
+ StringBuffer sb = new StringBuffer();
+ for (int i = 0; i < str.length(); i++) {
+ char c = str.charAt(i);
+ if (c == '<') {
+ sb.append("&lt;");
+ } else if (c == '>') {
+ sb.append("&gt;");
+ } else if (c == '&') {
+ sb.append("&amp;");
+ } else {
+ int x = c;
+ if (x < 32 || x > 127) {
+ sb.append("&#" + x + ";");
+ } else {
+ sb.append(c);
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ static boolean is_numeric(String str) {
+ try {
+ Double d = Double.valueOf(str);
+ } catch (java.lang.Exception e) {
+ return false;
+ }
+ return true;
+ }
+
+ void set_table_name(String str) {
+ if (str == null) {
+ tableName = "";
+ return;
+ }
+ tableName = Shell.sql_quote(str);
+ }
+
+ public void columns(String args[]) {
+ cols = args;
+ }
+
+ public void types(String args[]) {
+ /* Empty body to satisfy SQLite.Callback interface. */
+ }
+
+ public boolean newrow(String args[]) {
+ int i;
+ String tname;
+ switch (mode) {
+ case Shell.MODE_Line:
+ if (args.length == 0) {
+ break;
+ }
+ if (count++ > 0) {
+ pw.println("");
+ }
+ for (i = 0; i < args.length; i++) {
+ pw.println(cols[i] + " = " +
+ args[i] == null ? "NULL" : args[i]);
+ }
+ break;
+ case Shell.MODE_Column:
+ String csep = "";
+ if (count++ == 0) {
+ colwidth = new int[args.length];
+ for (i = 0; i < args.length; i++) {
+ int w, n;
+ w = cols[i].length();
+ if (w < 10) {
+ w = 10;
+ }
+ colwidth[i] = w;
+ if (showHeader) {
+ pw.print(csep + cols[i]);
+ csep = " ";
+ }
+ }
+ if (showHeader) {
+ pw.println("");
+ }
+ }
+ if (args.length == 0) {
+ break;
+ }
+ csep = "";
+ for (i = 0; i < args.length; i++) {
+ pw.print(csep + (args[i] == null ? "NULL" : args[i]));
+ csep = " ";
+ }
+ pw.println("");
+ break;
+ case Shell.MODE_Semi:
+ case Shell.MODE_List:
+ if (count++ == 0 && showHeader) {
+ for (i = 0; i < args.length; i++) {
+ pw.print(cols[i] +
+ (i == args.length - 1 ? "\n" : sep));
+ }
+ }
+ if (args.length == 0) {
+ break;
+ }
+ for (i = 0; i < args.length; i++) {
+ pw.print(args[i] == null ? "NULL" : args[i]);
+ if (mode == Shell.MODE_Semi) {
+ pw.print(";");
+ } else if (i < args.length - 1) {
+ pw.print(sep);
+ }
+ }
+ pw.println("");
+ break;
+ case MODE_Html:
+ if (count++ == 0 && showHeader) {
+ pw.print("<TR>");
+ for (i = 0; i < args.length; i++) {
+ pw.print("<TH>" + html_quote(cols[i]) + "</TH>");
+ }
+ pw.println("</TR>");
+ }
+ if (args.length == 0) {
+ break;
+ }
+ pw.print("<TR>");
+ for (i = 0; i < args.length; i++) {
+ pw.print("<TD>" + html_quote(args[i]) + "</TD>");
+ }
+ pw.println("</TR>");
+ 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:<BR>
+ * <PRE>
+ * ...
+ * 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();
+ * }
+ * </PRE>
+ *
+ * @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' <code>decode</code> 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' <code>encode</code> 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
+ * <A HREF="Database.html#get_table(java.lang.String)">Database.get_table</A>
+ * convenience method.
+ * <BR><BR>
+ * Example:<BR>
+ *
+ * <PRE>
+ * ...
+ * SQLite.Database db = new SQLite.Database();
+ * db.open("db", 0);
+ * System.out.print(db.get_table("select * from TEST"));
+ * ...
+ * </PRE>
+ * Example output:<BR>
+ *
+ * <PRE>
+ * id|firstname|lastname|
+ * 0|John|Doe|
+ * 1|Speedy|Gonzales|
+ * ...
+ * </PRE>
+ */
+
+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.<BR><BR>
+ *
+ * Example:<BR>
+ * <PRE>
+ * ...
+ * 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) {
+ * }
+ * </PRE>
+ *
+ * @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..e1d903e
--- /dev/null
+++ b/sql/src/main/java/java/sql/Array.java
@@ -0,0 +1,133 @@
+/*
+ * 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 ARRAY type.
+ */
+public interface Array {
+
+ /**
+ * Retrieves the contents of the SQL ARRAY value as a Java array object.
+ *
+ * @return A Java array containing the elements of this Array
+ * @throws SQLException
+ */
+ public Object getArray() throws SQLException;
+
+ /**
+ * Returns part of the SQL ARRAY associated with this Array, starting at a
+ * particular index and comprising up to count successive elements of the
+ * SQL array.
+ *
+ * @param index
+ * @param count
+ * @return A Java array containing the subportion of elements of this Array
+ * @throws SQLException
+ */
+ public Object getArray(long index, int count) throws SQLException;
+
+ /**
+ * Returns part of the SQL ARRAY associated with this Array, starting at a
+ * particular index and comprising up to count successive elements of the
+ * SQL array.
+ *
+ * @param index
+ * @param count
+ * @param map
+ * @return A Java array containing the subportion of elements of this Array
+ * @throws SQLException
+ */
+ public Object getArray(long index, int count, Map<String, Class<?>> map)
+ throws SQLException;
+
+ /**
+ * Returns the SQL ARRAY associated with this Array.
+ *
+ * @param map
+ * @return A Java array containing the elements of this Array
+ * @throws SQLException
+ */
+ public Object getArray(Map<String, Class<?>> map) throws SQLException;
+
+ /**
+ * Returns the JDBC type of the entries in this Array's associated array.
+ *
+ * @return An integer constant from the java.sql.Types class
+ * @throws SQLException
+ */
+ public int getBaseType() throws SQLException;
+
+ /**
+ * Returns the SQL type name of the entries in the array associated with
+ * this Array.
+ *
+ * @return The database specific name or a fully-qualified SQL type name.
+ * @throws SQLException
+ */
+ public String getBaseTypeName() throws SQLException;
+
+ /**
+ * Returns a ResultSet object which holds the entries of the SQL ARRAY
+ * associated with this Array.
+ *
+ * @return the ResultSet
+ * @throws SQLException
+ */
+ public ResultSet getResultSet() throws SQLException;
+
+ /**
+ * Returns a ResultSet object that holds the entries of a subarray,
+ * beginning at a particular index and comprising up to count successive
+ * entries.
+ *
+ * @param index
+ * @param count
+ * @return the ResultSet
+ * @throws SQLException
+ */
+ public ResultSet getResultSet(long index, int count) throws SQLException;
+
+ /**
+ * Returns a ResultSet object that holds the entries of a subarray,
+ * beginning at a particular index and comprising up to count successive
+ * entries.
+ *
+ * @param index
+ * @param count
+ * @param map
+ * @return the ResultSet
+ * @throws SQLException
+ */
+ public ResultSet getResultSet(long index, int count,
+ Map<String, Class<?>> map) throws SQLException;
+
+ /**
+ * Returns a ResultSet object which holds the entries of the SQL ARRAY
+ * associated with this Array.
+ *
+ * @param map
+ * @return the ResultSet
+ * @throws SQLException
+ */
+ public ResultSet getResultSet(Map<String, Class<?>> 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..f39dc5e
--- /dev/null
+++ b/sql/src/main/java/java/sql/BatchUpdateException.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.
+ */
+
+package java.sql;
+
+import java.io.Serializable;
+
+/**
+ * An exception thrown if a problem occurs during a batch update operation.
+ * <p>
+ * A BatchUpdateException provides additional information about the problem that
+ * occurred, compared with a standard SQLException. It supplies update counts
+ * for successful commands that executed within the batch update, but before the
+ * exception was encountered.
+ * <p>
+ * The element order in the array of update counts matches the order that the
+ * commands were added to the batch operation.
+ * <p>
+ * Once a batch update command fails and a 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 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
+ * Statement.EXECUTE_FAILED.
+ */
+public class BatchUpdateException extends SQLException implements Serializable {
+
+ private static final long serialVersionUID = 5977529877145521757L;
+
+ private int[] updateCounts = null;
+
+ /**
+ * Creates a BatchUpdateException with the Reason, SQLState, and Update
+ * Counts set to null and a Vendor Code of 0.
+ */
+ public BatchUpdateException() {
+ super();
+ }
+
+ /**
+ * Creates a BatchUpdateException with the Update Counts set to the supplied
+ * value and the Reason, SQLState set to null and a Vendor Code of 0.
+ *
+ * @param updateCounts
+ * the array of Update Counts to use in initialization
+ */
+ public BatchUpdateException(int[] updateCounts) {
+ super();
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Creates a BatchUpdateException with the Update Counts set to the supplied
+ * value, the Reason set to the supplied value and SQLState set to null and
+ * a Vendor Code of 0.
+ *
+ * @param reason
+ * the initialization value for Reason
+ * @param updateCounts
+ * the array of Update Counts to set
+ */
+ public BatchUpdateException(String reason, int[] updateCounts) {
+ super(reason);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Creates a BatchUpdateException with the Update Counts set to the supplied
+ * value, the Reason set to the supplied value, the SQLState initialized to
+ * the supplied value and the Vendor Code initialized to 0.
+ *
+ * @param reason
+ * the value to use for the Reason
+ * @param SQLState
+ * the X/OPEN value to use for the SQLState
+ * @param updateCounts
+ * the array of Update Counts to set
+ */
+ public BatchUpdateException(String reason, String SQLState,
+ int[] updateCounts) {
+ super(reason, SQLState);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Creates a BatchUpdateException with the Update Counts set to the supplied
+ * value, the Reason set to the supplied value, the SQLState initialized to
+ * the supplied value and the Vendor Code set to the supplied value.
+ *
+ * @param reason
+ * the value to use for the Reason
+ * @param SQLState
+ * the X/OPEN value to use for the SQLState
+ * @param vendorCode
+ * the value to use for the vendor error code
+ * @param updateCounts
+ * the array of Update Counts to set
+ */
+ public BatchUpdateException(String reason, String SQLState, int vendorCode,
+ int[] updateCounts) {
+ super(reason, SQLState, vendorCode);
+ this.updateCounts = updateCounts;
+ }
+
+ /**
+ * Gets the Update Counts array.
+ * <p>
+ * If a batch update command fails and a 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</code> 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 Statement.EXECUTE_FAILED.
+ *
+ * @return an array that contains the successful update counts, before this
+ * exception. Alternatively, if the driver continues to process
+ * commands following an error, one of these listed items for every
+ * command the batch contains:
+ * <ol>
+ * <li>an count of the updates</li>
+ * <li><code>Statement.SUCCESS_NO_INFO</code> indicating that the
+ * command completed successfully, but the amount of altered rows is
+ * not known.</li>
+ * <li><code>Statement.EXECUTE_FAILED</code> indicating that the
+ * command was unsuccessful.
+ * </ol>
+ */
+ 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..2b3cff5
--- /dev/null
+++ b/sql/src/main/java/java/sql/Blob.java
@@ -0,0 +1,160 @@
+/*
+ * 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 mapping for the SQL BLOB type.
+ * <p>
+ * An SQL CLOB type stores a large array of bytes (binary data) as the value in
+ * a column of a database.
+ * <p>
+ * The java.sql.Blob interface provides methods for setting and retrieving data
+ * in the Blob, for querying Clob data length, for searching for data within the
+ * Blob.
+ */
+public interface Blob {
+
+ /**
+ * Retrieves this Blob object as a binary stream.
+ *
+ * @return a binary InputStream giving access to the Blob data
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ public InputStream getBinaryStream() throws SQLException;
+
+ /**
+ * Gets a portion of the value of this Blob as an array of bytes.
+ *
+ * @param pos
+ * the position of the first byte in the Blob to get, where the
+ * first byte in the Blob has position = 1
+ * @param length
+ * the number of bytes to get
+ * @return a byte array containing the data from the Blob, starting at pos
+ * and of length up to <code>length</code> bytes long
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ public byte[] getBytes(long pos, int length) throws SQLException;
+
+ /**
+ * Gets the number of bytes in this Blob object.
+ *
+ * @return an long value with the length of the Blob in bytes
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ public long length() throws SQLException;
+
+ /**
+ * Search for the position in this Blob at which a specified pattern begins,
+ * starting at a specified position within the Blob.
+ *
+ * @param pattern
+ * a Blob containing the pattern of data to search for in this
+ * Blob
+ * @param start
+ * the position within this Blob to start the search, where the
+ * first position in the Blob is 1
+ * @return a long value with the position at which the pattern begins. -1 if
+ * the pattern is not found in this Blob.
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ public long position(Blob pattern, long start) throws SQLException;
+
+ /**
+ * Search for the position in this Blob at which the specified pattern
+ * begins, starting at a specified position within the Blob.
+ *
+ * @param pattern
+ * a byte array containing the pattern of data to search for in
+ * this Blob
+ * @param start
+ * the position within this Blob to start the search, where the
+ * first position in the Blob is 1
+ * @return a long value with the position at which the pattern begins. -1 if
+ * the pattern is not found in this Blob.
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ public long position(byte[] pattern, long start) throws SQLException;
+
+ /**
+ * Gets a stream that can be used to write binary data to this Blob.
+ *
+ * @param pos
+ * the position within this Blob at which to start writing, where
+ * the first position in the Blob is 1
+ * @return a binary InputStream which can be used to write data into the
+ * Blob starting at the specified position.
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ public OutputStream setBinaryStream(long pos) throws SQLException;
+
+ /**
+ * Writes a specified array of bytes to this Blob. object, starting at a
+ * specified position. Returns the number of bytes written.
+ *
+ * @param pos
+ * the position within this Blob at which to start writing, where
+ * the first position in the Blob is 1
+ * @param theBytes
+ * an array of bytes to write into the Blob
+ * @return an integer containing the number of bytes written to the Blob
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ public int setBytes(long pos, byte[] theBytes) throws SQLException;
+
+ /**
+ * Writes a portion of a specified byte array to this Blob. Returns the
+ * number of bytes written.
+ *
+ * @param pos
+ * the position within this Blob at which to start writing, where
+ * the first position in the Blob is 1
+ * @param theBytes
+ * an array of bytes to write into the Blob
+ * @param offset
+ * the offset into the byte array from which to start writing
+ * data - the first byte in the array has offset 0.
+ * @param len
+ * the length of data to write, as the number of bytes
+ * @return an integer containing the number of bytes written to the Blob
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ public int setBytes(long pos, byte[] theBytes, int offset, int len)
+ throws SQLException;
+
+ /**
+ * Truncate the value of this Blob object to a specified length in bytes.
+ *
+ * @param len
+ * the length of data in bytes to truncate the value of this Blob
+ * @throws SQLException
+ * if an error occurs accessing the Blob
+ */
+ 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..2097277
--- /dev/null
+++ b/sql/src/main/java/java/sql/CallableStatement.java
@@ -0,0 +1,1302 @@
+/*
+ * 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.
+ * <p>
+ * 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 OUT parameter. Other parameters can be declared as IN, OUT or INOUT.
+ * Parameters are referenced either by name or by a numerical index, with the
+ * first parameter being 1, the second 1 and so on. Here are examples of the two
+ * forms of the escape syntax: <code>
+ *
+ * { ?= call &lt.procedurename&gt.[([parameter1,parameter2,...])]}
+ *
+ * {call &lt.procedurename&gt.[([parameter1,parameter2,...])]}
+ * </code>
+ * <p>
+ * IN parameters are set before calling the procedure, using the setter methods
+ * which are inherited from <code>PreparedStatement</code>. For OUT
+ * parameters, their Type must be registered before executing the stored
+ * procedure, and the value is retrieved using the getter methods defined in the
+ * CallableStatement interface.
+ * <p>
+ * CallableStatements can return one or more ResultSets. Where multiple
+ * ResultSets are returned they are accessed using the methods inherited from
+ * the <code>Statement</code> interface.
+ */
+public interface CallableStatement extends PreparedStatement {
+
+ /**
+ * Gets the value of a specified JDBC <code>ARRAY</code> parameter as a
+ * java.sql.Array.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a java.sql.Array containing the parameter value
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Array getArray(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC ARRAY parameter as a java.sql.Array.
+ *
+ * @param parameterName
+ * the parameter of interest's name
+ * @return a <code>java.sql.Array</code> containing the parameter value
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Array getArray(String parameterName) throws SQLException;
+
+ /**
+ * Returns a new {@link BigDecimal} representation of the JDBC
+ * <code>NUMERIC</code> parameter specified by the input index.
+ *
+ * @param parameterIndex
+ * the parameter number index (starts from 1)
+ * @return a <code>java.math.BigDecimal</code> with the value of the
+ * specified parameter. The value <code>null</code> is returned if
+ * the parameter in question is an SQL <code>NULL</code>
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public BigDecimal getBigDecimal(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns a new {@link BigDecimal} representation of the JDBC
+ * <code>NUMERIC</code> parameter specified by the input index. The number
+ * of digits after the decimal point is specified by <code>scale</code>.
+ *
+ * @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</code> with the value of the
+ * specified parameter. The value <code>null</code> is returned if
+ * the parameter in question is an SQL <code>NULL</code>
+ * @throws SQLException
+ * if there is a problem accessing the database
+ * @deprecated Use {@link #getBigDecimal(int)} or {@link #getBigDecimal(String)}
+ */
+ @Deprecated
+ public BigDecimal getBigDecimal(int parameterIndex, int scale)
+ throws SQLException;
+
+ /**
+ * Returns a new {@link BigDecimal} representation of the JDBC
+ * <code>NUMERIC</code> parameter specified by the input name.
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @return a java.math.BigDecimal with the value of the specified parameter.
+ * null if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public BigDecimal getBigDecimal(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC BLOB parameter as a java.sql.Blob
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a java.sql.Blob with the value. null if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Blob getBlob(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC BLOB parameter as a java.sql.Blob
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @return a java.sql.Blob with the value. null if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Blob getBlob(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC BIT parameter as a boolean
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a boolean representing the parameter value. false if the value is
+ * SQL NULL
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean getBoolean(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC <code>BIT</code> parameter as a
+ * boolean
+ *
+ * @param parameterName
+ * the parameter of interest's name
+ * @return a <code>boolean</code> representation of the value of the
+ * parameter. <code>false</code> is returned if the SQL value is
+ * <code>NULL</code>.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public boolean getBoolean(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC TINYINT parameter as a byte
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a byte with the value of the parameter. 0 if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public byte getByte(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC <code>TINYINT</code> parameter as a
+ * Java <code>byte</code>.
+ *
+ * @param parameterName
+ * the parameter of interest's name
+ * @return a <code>byte</code> representation of the value of the
+ * parameter. <code>0</code> is returned if the SQL value is
+ * <code>NULL</code>.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public byte getByte(String parameterName) throws SQLException;
+
+ /**
+ * Returns a byte array representation of the indexed JDBC
+ * <code>BINARY</code> or <code>VARBINARY</code> parameter.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return an array of bytes with the value of the parameter. null if the
+ * value is SQL NULL.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public byte[] getBytes(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns a byte array representation of the named JDBC <code>BINARY</code>
+ * or <code>VARBINARY</code> parameter.
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @return an array of bytes with the value of the parameter. null if the
+ * value is SQL NULL.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public byte[] getBytes(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC CLOB parameter as a java.sql.Clob
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a java.sql.Clob with the value of the parameter. null if the
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Clob getClob(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC CLOB parameter as a java.sql.Clob
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @return a java.sql.Clob with the value of the parameter. null if the
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Clob getClob(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC DATE parameter as a java.sql.Date.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return the java.sql.Date with the parameter value. null if the value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Date getDate(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC DATE parameter as a java.sql.Date.,
+ * using a specified Calendar to construct the date.
+ * <p>
+ * The JDBC driver uses the Calendar to create the Date using a particular
+ * timezone and locale. Default behaviour 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 Calendar to use to construct the Date
+ * @return the java.sql.Date with the parameter value. null if the value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Date getDate(int parameterIndex, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC DATE parameter as a java.sql.Date.
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @return the java.sql.Date with the parameter value. null if the value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Date getDate(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC DATE parameter as a java.sql.Date.,
+ * using a specified Calendar to construct the date.
+ * <p>
+ * The JDBC driver uses the Calendar to create the Date using a particular
+ * timezone and locale. Default behaviour of the driver is to use the Java
+ * virtual machine default settings.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param cal
+ * used for creating the returned <code>Date</code>
+ * @return the java.sql.Date with the parameter value. null if the value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Date getDate(String parameterName, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC DOUBLE parameter as a double
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return the double with the parameter value. 0.0 if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public double getDouble(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC DOUBLE parameter as a double
+ *
+ * @param parameterName
+ * the parameter name
+ * @return the parameter value as represented in a Java <code>double</code>.
+ * An SQL value of <code>NULL</code> gets represented as
+ * <code>0</code> (zero).
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public double getDouble(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC FLOAT parameter as a float
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return the float with the parameter value. 0.0 if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public float getFloat(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC <code>FLOAT</code> parameter as a
+ * Java <code>float</code>.
+ *
+ * @param parameterName
+ * the parameter name
+ * @return the parameter value as represented in a Java <code>float</code>.
+ * An SQL value of <code>NULL</code> gets represented as
+ * <code>0</code> (zero).
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public float getFloat(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC INTEGER parameter as an int
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return the int with the parameter value. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getInt(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC INTEGER parameter as an int
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @return the int with the parameter value. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getInt(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC BIGINT parameter as a long
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return the long with the parameter value. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public long getLong(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC BIGINT parameter as a long
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @return the long with the parameter value. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public long getLong(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified parameter as a Java <code>Object</code>.
+ * <p>
+ * The object type returned is the JDBC type registered for the parameter
+ * with a <code>registerOutParameter</code> call. If a parameter was
+ * registered as a <code>java.sql.Types.OTHER</code> 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 there is a problem accessing the database
+ */
+ public Object getObject(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified parameter as an Object. A Map is supplied
+ * to provide custom mapping of the parameter value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param map
+ * the Map holing the mapping from SQL types to Java classes
+ * @return an Object holding the value of the parameter.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Object getObject(int parameterIndex, Map<String, Class<?>> map)
+ throws SQLException;
+
+ /**
+ * Gets the value of a specified parameter as an Object.
+ * <p>
+ * The object type returned is the JDBC type registered for the parameter
+ * with a <code>registerOutParameter</code> call. If a parameter was
+ * registered as a <code>java.sql.Types.OTHER</code> then it may hold
+ * abstract types that are particular to the connected database.
+ *
+ * @param parameterName
+ * the parameter name
+ * @return the Java <code>Object</code> representation of the value of the
+ * parameter.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Object getObject(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified parameter as an Object. A Map is supplied
+ * to provide custom mapping of the parameter value.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param map
+ * the <code>Map</code> of SQL types to their Java counterparts
+ * @return an <code>Object</code> holding the value of the parameter.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Object getObject(String parameterName, Map<String, Class<?>> map)
+ throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC REF(<structured type>) parameter as a
+ * java.sql.Ref
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a java.sql.Ref with the parameter value. null if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Ref getRef(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC REF(<structured type>) parameter as a
+ * java.sql.Ref
+ *
+ * @param parameterName
+ * the parameter name
+ * @return the target parameter's value in the form of a
+ * <code>java.sql.Ref</code>. A <code>null</code> reference is
+ * returned for a parameter value of SQL <code>NULL</code>.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Ref getRef(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC SMALLINT parameter as a short
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a short with the parameter value. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public short getShort(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC <code>SMALLINT</code> parameter as a
+ * short
+ *
+ * @param parameterName
+ * the parameter name
+ * @return the value of the target parameter as a Java <code>short</code>.
+ * If the value is an SQL <code>NULL</code> then <code>0</code>
+ * (zero) is returned.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public short getShort(String parameterName) throws SQLException;
+
+ /**
+ * Returns the indexed parameter's value as a string. The parameter value
+ * must be one of the JDBC types <code>CHAR</code>, <code>VARCHAR</code>
+ * or <code>LONGVARCHAR</code>.
+ * <p>
+ * The string corresponding to a <code>CHAR</code> 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 a String with the parameter value. null if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ 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>, <code>VARCHAR</code> or
+ * <code>LONGVARCHAR</code>.
+ * <p>
+ * The string corresponding to a <code>CHAR</code> of fixed length will be
+ * of identical length to the value in the database inclusive of padding
+ * characters.
+ *
+ * @param parameterName
+ * the parameter name
+ * @return a String with the parameter value. null if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public String getString(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC TIME parameter as a java.sql.Time.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a java.sql.Time with the parameter value. null if the value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Time getTime(int parameterIndex) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC TIME parameter as a java.sql.Time,
+ * using the supplied Calendar to construct the time. The JDBC driver uses
+ * the Calendar to handle specific timezones and locales when creating the
+ * Time.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param cal
+ * the Calendar to use in constructing the Time.
+ * @return a java.sql.Time with the parameter value. null if the value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Time getTime(int parameterIndex, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC <code>TIME</code> parameter as a
+ * <code>java.sql.Time</code>
+ *
+ * @param parameterName
+ * the parameter name
+ * @return a new <code>java.sql.Time</code> with the parameter value. A
+ * <code>null</code> reference is returned for an SQL value of
+ * <code>NULL</code>
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Time getTime(String parameterName) throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC TIME parameter as a java.sql.Time,
+ * using the supplied Calendar to construct the time. The JDBC driver uses
+ * the Calendar to handle specific timezones and locales when creating the
+ * Time.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param cal
+ * used for creating the returned <code>Time</code>
+ * @return a <code>java.sql.Time</code> with the parameter value. A
+ * <code>null</code> reference is returned for an SQL value of
+ * <code>NULL</code>
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Time getTime(String parameterName, Calendar cal) throws SQLException;
+
+ /**
+ * Returns the indexed parameter's <code>TIMESTAMP</code> value as a
+ * <code>java.sql.Timestamp</code>.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a new <code>java.sql.Timestamp</code> with the parameter value.
+ * A <code>null</code> reference is returned for an SQL value of
+ * <code>NULL</code>
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Timestamp getTimestamp(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns the indexed parameter's <code>TIMESTAMP</code> value as a
+ * <code>java.sql.Timestamp</code>. The JDBC driver uses the supplied
+ * <code>Calendar</code> 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</code>
+ * @return a new <code>java.sql.Timestamp</code> with the parameter value.
+ * A <code>null</code> reference is returned for an SQL value of
+ * <code>NULL</code>
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Timestamp getTimestamp(int parameterIndex, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Returns the named parameter's <code>TIMESTAMP</code> value as a
+ * <code>java.sql.Timestamp</code>.
+ *
+ * @param parameterName
+ * the parameter name
+ * @return a new <code>java.sql.Timestamp</code> with the parameter value.
+ * A <code>null</code> reference is returned for an SQL value of
+ * <code>NULL</code>
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Timestamp getTimestamp(String parameterName) throws SQLException;
+
+ /**
+ * Returns the indexed parameter's <code>TIMESTAMP</code> value as a
+ * <code>java.sql.Timestamp</code>. The JDBC driver uses the supplied
+ * <code>Calendar</code> to handle specific timezones and locales when
+ * creating the result.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param cal
+ * used for creating the returned <code>Timestamp</code>
+ * @return a new <code>java.sql.Timestamp</code> with the parameter value.
+ * A <code>null</code> reference is returned for an SQL value of
+ * <code>NULL</code>
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Timestamp getTimestamp(String parameterName, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Gets the value of a specified JDBC DATALINK parameter as a java.net.URL.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @return a java.sql.Datalink with the parameter value. null if the value
+ * is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public URL getURL(int parameterIndex) throws SQLException;
+
+ /**
+ * Returns the named parameter's JDBC <code>DATALINK</code> value in a new
+ * Java <code>java.net.URL</code>.
+ *
+ * @param parameterName
+ * the parameter name
+ * @return a new <code>java.net.URL</code> encapsulating the parameter
+ * value. A <code>null</code> reference is returned for an SQL
+ * value of <code>NULL</code>
+ * @throws SQLException
+ * if a database error happens
+ */
+ public URL getURL(String parameterName) throws SQLException;
+
+ /**
+ * Defines the Type of a specified OUT parameter. All OUT parameters must
+ * have their Type defined before a stored procedure is executed.
+ * <p>
+ * The Type defined by this method fixes the Java type that must be
+ * retrieved using the getter methods of CallableStatement. If a database
+ * specific type is expected for a parameter, the Type java.sql.Types.OTHER
+ * should be used. Note that there is another variant of this method for
+ * User Defined Types or a REF type.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param sqlType
+ * the JDBC type as defined by java.sql.Types. The JDBC types
+ * NUMERIC and DECIMAL should be defined using the version of
+ * <code>registerOutParameter</code> that takes a
+ * <code>scale</code> parameter.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void registerOutParameter(int parameterIndex, int sqlType)
+ throws SQLException;
+
+ /**
+ * Defines the Type of a specified OUT parameter. All OUT parameters must
+ * have their Type defined before a stored procedure is executed. This
+ * version of the registerOutParameter method, which has a scale parameter,
+ * should be used for the JDBC types NUMERIC and DECIMAL, where there is a
+ * need to specify the number of digits expected after the decimal point.
+ * <p>
+ * The Type defined by this method fixes the Java type that must be
+ * retrieved using the getter methods of CallableStatement.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param sqlType
+ * the JDBC type as defined by 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 happens
+ */
+ public void registerOutParameter(int parameterIndex, int sqlType, int scale)
+ throws SQLException;
+
+ /**
+ * Defines the Type of a specified OUT parameter. This variant of the method
+ * is designed for use with parameters that are User Defined Types (UDT) or
+ * a 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 REF type, this name should be the
+ * fully qualified name of the referenced type.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void registerOutParameter(int paramIndex, int sqlType,
+ String typeName) throws SQLException;
+
+ /**
+ * Defines the Type of a specified OUT parameter. All OUT parameters must
+ * have their Type defined before a stored procedure is executed.
+ * <p>
+ * The Type defined by this method fixes the Java type that must be
+ * retrieved using the getter methods of CallableStatement. If a database
+ * specific type is expected for a parameter, the Type java.sql.Types.OTHER
+ * should be used. Note that there is another variant of this method for
+ * User Defined Types or a REF type.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param sqlType
+ * a JDBC type expressed as a constant from {@link Types}. Types
+ * NUMERIC and DECIMAL should be defined using the variant of
+ * this method that takes a <code>scale</code> parameter.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void registerOutParameter(String parameterName, int sqlType)
+ throws SQLException;
+
+ /**
+ * Defines the Type of a specified OUT parameter. All OUT parameters must
+ * have their Type defined before a stored procedure is executed. This
+ * version of the registerOutParameter method, which has a scale parameter,
+ * should be used for the JDBC types NUMERIC and DECIMAL, where there is a
+ * need to specify the number of digits expected after the decimal point.
+ * <p>
+ * The Type defined by this method fixes the Java type that must be
+ * retrieved using the getter methods of 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 happens
+ */
+ public void registerOutParameter(String parameterName, int sqlType,
+ int scale) throws SQLException;
+
+ /**
+ * Defines the Type of a specified OUT parameter. This variant of the method
+ * is designed for use with parameters that are User Defined Types (UDT) or
+ * a REF type, although it can be used for any type.Registers the designated
+ * output parameter.
+ *
+ * @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 REF
+ * type, this name should be the fully qualified name of the
+ * referenced type.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void registerOutParameter(String parameterName, int sqlType,
+ String typeName) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the content of a supplied
+ * InputStream, which has a specified number of bytes.
+ * <p>
+ * This is a good method for setting an SQL LONVARCHAR parameter where the
+ * length of the data is large. Data is read from the InputStream until
+ * end-of-file is reached or the specified number of bytes is copied.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theInputStream
+ * the ASCII InputStream carrying the data to update the
+ * parameter with
+ * @param length
+ * the number of bytes in the InputStream to copy to the
+ * parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setAsciiStream(String parameterName,
+ InputStream theInputStream, int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied
+ * java.math.BigDecimal value.
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @param theBigDecimal
+ * the java.math.BigInteger value to set
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setBigDecimal(String parameterName, BigDecimal theBigDecimal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the content of a supplied
+ * binary InputStream, which has a specified number of bytes.
+ * <p>
+ * Use this method when a large amount of data needs to be set into a
+ * LONGVARBINARY parameter.
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @param theInputStream
+ * the binary InputStream carrying the data to update the
+ * parameter
+ * @param length
+ * the number of bytes in the InputStream to copy to the
+ * parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setBinaryStream(String parameterName,
+ InputStream theInputStream, int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied boolean value.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theBoolean
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setBoolean(String parameterName, boolean theBoolean)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied byte value.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theByte
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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</code> or else
+ * <code>LONGVARBINARY</code> 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 happens
+ */
+ public void setBytes(String parameterName, byte[] theBytes)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the character content of a
+ * 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</code>
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setCharacterStream(String parameterName, Reader reader,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied 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 happens
+ */
+ public void setDate(String parameterName, Date theDate) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied 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 DATE in the
+ * database - without the supplied Calendar, 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 Calendar to use to construct the SQL DATE value
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setDate(String parameterName, Date theDate, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied double value.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theDouble
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setDouble(String parameterName, double theDouble)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to to a supplied float value.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theFloat
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setFloat(String parameterName, float theFloat)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied int value.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theInt
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setInt(String parameterName, int theInt) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied long value.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theLong
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setLong(String parameterName, long theLong) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to SQL NULL. Don't use this
+ * version of setNull for User Defined Types or for 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 happens
+ */
+ public void setNull(String parameterName, int sqlType) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to be SQL NULL where the
+ * parameter type is either <code>REF</code> or user defined (e.g.
+ * <code>STRUCT</code>, <code>JAVA_OBJECT</code> etc).
+ * <p>
+ * 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, or the name of the type being referenced if a REF).
+ *
+ * @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 UDT or REF type - ignored if the parameter
+ * is not a UDT.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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</code>
+ * is transformed to the corresponding SQL type according to the normal Java
+ * to SQL mapping rules.
+ * <p>
+ * If the object's class implements the interface SQLData, the JDBC driver
+ * calls <code>SQLData.writeSQL</code> to write it to the SQL data stream.
+ * If <code>theObject</code> implements any of the following interfaces
+ * then it is the role of the driver to flow the value to the connected
+ * database using the appropriate SQL type :
+ * <ul>
+ * <li>{@link Ref}
+ * <li>{@link Struct}
+ * <li>{@link Array}
+ * <li>{@link Clob}
+ * <li>{@link Blob}
+ * </ul>
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theObject
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setObject(String parameterName, Object theObject)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ * <p>
+ * The Object is converted to the given targetSqlType before it is sent to
+ * the database. If the object has a custom mapping (its class implements
+ * the interface SQLData), the JDBC driver will call the method
+ * SQLData.writeSQL to write it to the SQL data stream. If
+ * <code>theObject</code> implements any of the following interfaces then
+ * it is the role of the driver to flow the value to the connected database
+ * using the appropriate SQL type :
+ * <ul>
+ * <li>{@link Ref}
+ * <li>{@link Struct}
+ * <li>{@link Array}
+ * <li>{@link Clob}
+ * <li>{@link Blob}
+ * </ul>
+ *
+ * @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 happens
+ */
+ public void setObject(String parameterName, Object theObject,
+ int targetSqlType) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ * <p>
+ * The Object is converted to the given targetSqlType before it is sent to
+ * the database. If the object has a custom mapping (its class implements
+ * the interface SQLData), the JDBC driver will call the method
+ * SQLData.writeSQL to write it to the SQL data stream. If
+ * <code>theObject</code> implements any of the following interfaces then
+ * it is the role of the driver to flow the value to the connected database
+ * using the appropriate SQL type :
+ * <ul>
+ * <li>{@link Ref}
+ * <li>{@link Struct}
+ * <li>{@link Array}
+ * <li>{@link Clob}
+ * <li>{@link Blob}
+ * </ul>
+ *
+ * @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 happens
+ */
+ public void setObject(String parameterName, Object theObject,
+ int targetSqlType, int scale) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied short value.
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @param theShort
+ * a short value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setShort(String parameterName, short theShort)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied String.
+ *
+ * @param parameterName
+ * the name of the parameter
+ * @param theString
+ * a String value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setString(String parameterName, String theString)
+ throws SQLException;
+
+ /**
+ * Sets the value of the parameter named <code>parameterName</code> to the
+ * value of the supplied <code>java.sql.Time</code>.
+ *
+ * @param parameterName
+ * the parameter name
+ * @param theTime
+ * the new value with which to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setTime(String parameterName, Time theTime) throws SQLException;
+
+ /**
+ * Sets the value of the parameter named <code>parameterName</code> to the
+ * value of the supplied <code>java.sql.Time</code> using the supplied
+ * Calendar.
+ * <p>
+ * The driver uses the supplied Calendar to create the SQL 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</code> value
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setTime(String parameterName, Time theTime, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied 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 happens
+ */
+ public void setTimestamp(String parameterName, Timestamp theTimestamp)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied java.sql.Timestamp
+ * value, using the supplied Calendar.
+ * <p>
+ * The driver uses the supplied Calendar to create the SQL 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</code> value
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setTimestamp(String parameterName, Timestamp theTimestamp,
+ Calendar cal) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the supplied 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 happens
+ */
+ public void setURL(String parameterName, URL theURL) throws SQLException;
+
+ /**
+ * Gets whether the value of the last OUT parameter read was SQL NULL.
+ *
+ * @return true if the last parameter was SQL NULL, false otherwise.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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..e97b3b1
--- /dev/null
+++ b/sql/src/main/java/java/sql/Clob.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 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.
+ * <p>
+ * An SQL CLOB type stores a large array of characters as the value in a column
+ * of a database.
+ * <p>
+ * The java.sql.Clob interface provides methods for setting and retrieving data
+ * in the Clob, for querying Clob data length, for searching for data within the
+ * Clob.
+ */
+public interface Clob {
+
+ /**
+ * Gets the value of this Clob object as an ASCII stream.
+ *
+ * @return an ASCII InputStream giving access to the Clob data
+ * @throws SQLException
+ * if an error occurs accessing the Clob
+ */
+ public InputStream getAsciiStream() throws SQLException;
+
+ /**
+ * Gets the value of this Clob object as a java.io.Reader.
+ *
+ * @return a character stream Reader object giving access to the Clob data
+ * @throws SQLException
+ * if an error occurs accessing the Clob
+ */
+ public Reader getCharacterStream() throws SQLException;
+
+ /**
+ * Gets a copy of a specified substring in this Clob.
+ *
+ * @param pos
+ * the index of the start of the substring in the 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 Clob
+ */
+ public String getSubString(long pos, int length) throws SQLException;
+
+ /**
+ * Retrieves the number of characters in this Clob object.
+ *
+ * @return a long value with the number of character in this Clob.
+ * @throws SQLException
+ * if an error occurs accessing the Clob
+ */
+ public long length() throws SQLException;
+
+ /**
+ * Retrieves the character position at which a specified Clob object appears
+ * in this Clob object.
+ *
+ * @param searchstr
+ * the specified Clob to search for
+ * @param start
+ * the position within this Clob to start the search
+ * @return a long value with the position at which the specified Clob occurs
+ * within this Clob.
+ * @throws SQLException
+ * if an error occurs accessing the Clob
+ */
+ public long position(Clob searchstr, long start) throws SQLException;
+
+ /**
+ * Retrieves the character position at which a specified substring appears
+ * in this Clob object.
+ *
+ * @param searchstr
+ * th String to search for
+ * @param start
+ * the position at which to start the search within this Clob.
+ * @return a long value with the position at which the specified String
+ * occurs within this Clob.
+ * @throws SQLException
+ * if an error occurs accessing the Clob
+ */
+ public long position(String searchstr, long start) throws SQLException;
+
+ /**
+ * Retrieves a stream which can be used to write Ascii characters to this
+ * 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 Clob.
+ * @throws SQLException
+ * if an error occurs accessing the Clob
+ */
+ public OutputStream setAsciiStream(long pos) throws SQLException;
+
+ /**
+ * Retrieves a stream which can be used to write a stream of Unicode
+ * characters to this 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
+ * Clob.
+ * @throws SQLException
+ * if an error occurs accessing the Clob
+ */
+ public Writer setCharacterStream(long pos) throws SQLException;
+
+ /**
+ * Writes a given Java String to this 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 Clob
+ */
+ public int setString(long pos, String str) throws SQLException;
+
+ /**
+ * Writes len characters of String, starting at a specified character
+ * offset, to this Clob.
+ *
+ * @param pos
+ * the position at which to start the writing
+ * @param str
+ * the String to write
+ * @param offset
+ * the offset within 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 Clob
+ */
+ public int setString(long pos, String str, int offset, int len)
+ throws SQLException;
+
+ /**
+ * Truncates this Clob to have a specified length of characters.
+ *
+ * @param len
+ * the length in characters to truncate this Clob
+ * @throws SQLException
+ * if an error occurs accessing the Clob
+ */
+ 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..4683299
--- /dev/null
+++ b/sql/src/main/java/java/sql/Connection.java
@@ -0,0 +1,759 @@
+/*
+ * 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.
+ *
+ */
+public interface Connection {
+
+ /**
+ * A constant indicating that transactions are not supported.
+ */
+ public static final int TRANSACTION_NONE = 0;
+
+ /**
+ * No dirty reads are permitted. Transactions may not read a row containing
+ * changes that have not yet been committed.
+ */
+ public static final int TRANSACTION_READ_COMMITTED = 2;
+
+ /**
+ * Dirty reads (reading from table rows containing changes that have not yet
+ * been committed), non-repeatable reads (reading table rows more than once
+ * in a transaction but getting back different data because other
+ * transactions may have altered rows between reads), and phantom reads
+ * (retrieving additional "phantom" rows in the course of repeated table
+ * reads because other transactions may have inserted additional rows that
+ * satisfy an SQL <code>WHERE</code> clause) are <b>all permitted</b>.
+ */
+ public static final int TRANSACTION_READ_UNCOMMITTED = 1;
+
+ /**
+ * A constant indicating that dirty reads and non-repeatable reads are
+ * prevented; phantom reads can occur.
+ */
+ public static final int TRANSACTION_REPEATABLE_READ = 4;
+
+ /**
+ * Dirty reads (reading from table rows containing changes that have not yet
+ * been committed), non-repeatable reads (reading table rows more than once
+ * in a transaction but getting back different data because other
+ * transactions may have altered rows between reads), and phantom reads
+ * (retrieving additional "phantom" rows in the course of repeated table
+ * reads because other transactions may have inserted additional rows that
+ * satisfy an SQL <code>WHERE</code> clause) are <b>all prevented</b>.
+ */
+ public static final int TRANSACTION_SERIALIZABLE = 8;
+
+ /**
+ * Throws away any warnings that may have arisen for this connection.
+ * Subsequent calls to {@link #getWarnings()} will return <code>null</code>
+ * up until a brand 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 will have no effect.
+ * <p>
+ * It is strongly recommended that all Connections are closed before they
+ * are dereferenced by the application ready for garbage collection. While
+ * the finalize method of the Connection will close the Connection before
+ * garbage collection takes place, it is not advisable to leave the close
+ * operation to take place in this way. Unpredictable performance may result
+ * from closing Connections in the finalizer.
+ *
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public void close() throws SQLException;
+
+ /**
+ * Commits all of the changes made subsequent to the last commit or rollback
+ * of the associated transaction. All locks in the database held by this
+ * connection are also relinquished. Calling this operation on connection
+ * objects in auto-commit mode is 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</code> for issuing SQL
+ * commands to the remote database.
+ * <p>
+ * ResultSets generated by the returned Statement will default to type
+ * <code>TYPE_FORWARD_ONLY</code> and concurrency level
+ * <code>CONCUR_READ_ONLY</code>.
+ *
+ * @return a <code>Statement</code> object with default settings.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Statement createStatement() throws SQLException;
+
+ /**
+ * Returns a new instance of <code>Statement</code> whose associated
+ * <code>ResultSet</code>s will have the characteristics specified in the
+ * type, concurrency and holdability arguments.
+ *
+ * @param resultSetType
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ * <li>{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ * <li>{@link ResultSet#TYPE_FORWARD_ONLY}
+ * </ul>
+ * @param resultSetConcurrency
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#CONCUR_UPDATABLE}
+ * <li>{@link ResultSet#CONCUR_READ_ONLY}
+ * </ul>
+ * @return a new instance of <code>Statement</code> capable of
+ * manufacturing <code>ResultSet</code>s that satisfy the
+ * specified <code>resultSetType</code> and
+ * <code>resultSetConcurrency</code> 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</code> whose associated
+ * <code>ResultSet</code>s will have the characteristics specified in the
+ * type, concurrency and holdability arguments.
+ *
+ * @param resultSetType
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ * <li>{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ * <li>{@link ResultSet#TYPE_FORWARD_ONLY}
+ * </ul>
+ * @param resultSetConcurrency
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#CONCUR_UPDATABLE}
+ * <li>{@link ResultSet#CONCUR_READ_ONLY}
+ * </ul>
+ * @param resultSetHoldability
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ * <li>{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ * </ul>
+ * @return a new instance of <code>Statement</code> capable of
+ * manufacturing <code>ResultSet</code>s that satisfy the
+ * specified <code>resultSetType</code>,
+ * <code>resultSetConcurrency</code> and
+ * <code>resultSetHoldability</code> values.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Statement createStatement(int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException;
+
+ /**
+ * Returns a boolean indication of whether or not this connection is in the
+ * auto-commit operating mode.
+ *
+ * @return <code>true</code> if auto-commit is on, otherwise
+ * <code>false</code>
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public boolean getAutoCommit() throws SQLException;
+
+ /**
+ * Gets this Connection object's current catalog name.
+ *
+ * @return the catalog name. <code>null</code> if there is no catalog
+ * name.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public String getCatalog() throws SQLException;
+
+ /**
+ * Returns the kind of holdability that any <code>ResultSet</code>s made
+ * from this instance will have.
+ *
+ * @return one of :
+ * <ul>
+ * <li>{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ * <li>{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ * </ul>
+ * @throws SQLException
+ * if there is a problem accessing the a database
+ */
+ public int getHoldability() throws SQLException;
+
+ /**
+ * Gets the metadata about the database referenced by this connection. The
+ * returned <code>DatabaseMetaData</code> describes the database
+ * topography, available stored procedures, SQL syntax and so on.
+ *
+ * @return a <code>DatabaseMetaData</code> object containing the database
+ * description
+ * @throws SQLException
+ * if there is a problem accessing the a database
+ */
+ public DatabaseMetaData getMetaData() throws SQLException;
+
+ /**
+ * Returns the present value of transaction isolation for this Connection
+ * instance.
+ *
+ * @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
+ */
+ public int getTransactionIsolation() throws SQLException;
+
+ /**
+ * Returns the Type Map associated with this Connection object. The type map
+ * will be empty unless the application has added at least one entry.
+ *
+ * @return the Type Map as a <code>java.util.Map</code>
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Map<String, Class<?>> getTypeMap() throws SQLException;
+
+ /**
+ * Gets the first instance of any <code>SQLWarning</code> 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</code> indicates that no warnings have occurred.
+ * <p>
+ * By invoking the {@link SQLWarning#getNextWarning()} method of the
+ * returned <code>SQLWarning</code> object it is possible to obtain all
+ * warning objects.
+ *
+ * @return the first warning as an SQLWarning object (may be
+ * <code>null</code>)
+ * @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.
+ */
+ public SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * Returns a boolean indication of whether or not this connection is in the
+ * closed state. The 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</code> if closed, otherwise <code>false</code>
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public boolean isClosed() throws SQLException;
+
+ /**
+ * Returns a boolean indication of whether or not this connection is
+ * currently in read-only state.
+ *
+ * @return <code>true</code> if in read-only state, otherwise
+ * <code>false</code>.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public boolean isReadOnly() throws SQLException;
+
+ /**
+ * Returns a string representation of the input SQL statement
+ * <code>sql</code> 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</code> 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</code> representing
+ * the SQL statement. <code>ResultSet</code>s emitted from this
+ * <code>CallableStatement</code> 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
+ */
+ public CallableStatement prepareCall(String sql) throws SQLException;
+
+ /**
+ * Returns a new instance of <code>CallableStatement</code> that may be
+ * used for making stored procedure calls to the database.
+ * <code>ResultSet</code>s emitted from this
+ * <code>CallableStatement</code> will satisfy the specified
+ * <code>resultSetType</code> and <code>resultSetConcurrency</code>
+ * values.
+ *
+ * @param sql
+ * the SQL statement
+ * @param resultSetType
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ * <li>{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ * <li>{@link ResultSet#TYPE_FORWARD_ONLY}
+ * </ul>
+ * @param resultSetConcurrency
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#CONCUR_READ_ONLY}
+ * <li>{@link ResultSet#CONCUR_UPDATABLE}
+ * </ul>
+ * @return a new instance of <code>CallableStatement</code> representing
+ * the precompiled SQL statement. <code>ResultSet</code>s emitted
+ * from this <code>CallableStatement</code> will satisfy the
+ * specified <code>resultSetType</code> and
+ * <code>resultSetConcurrency</code> values.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException;
+
+ /**
+ * Returns a new instance of <code>CallableStatement</code> that may be
+ * used for making stored procedure calls to the database. ResultSets
+ * created from this <code>CallableStatement</code> will have
+ * characteristics determined by the specified type, concurrency and
+ * holdability arguments.
+ *
+ * @param sql
+ * the SQL statement
+ * @param resultSetType
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ * <li>{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ * <li>{@link ResultSet#TYPE_FORWARD_ONLY}
+ * </ul>
+ * @param resultSetConcurrency
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#CONCUR_READ_ONLY}
+ * <li>{@link ResultSet#CONCUR_UPDATABLE}
+ * </ul>
+ * @param resultSetHoldability
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ * <li>{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ * </ul>
+ * @return a new instance of <code>CallableStatement</code> representing
+ * the precompiled SQL statement. <code>ResultSet</code>s emitted
+ * from this <code>CallableStatement</code> will satisfy the
+ * specified <code>resultSetType</code>,
+ * <code>resultSetConcurrency</code> and
+ * <code>resultSetHoldability</code> values.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public CallableStatement prepareCall(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException;
+
+ /**
+ * Returns a new instance of <code>PreparedStatement</code> that may be
+ * used any number of times to execute parameterized requests on the
+ * database server.
+ * <p>
+ * 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 flowing precompiled statements, the
+ * statement will not reach the database server until it is executed. This
+ * will have a bearing on precisely when <code>SQLException</code>
+ * instances get raised.
+ * <p>
+ * By default, ResultSets 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 PreparedStatement containing the supplied SQL statement
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public PreparedStatement prepareStatement(String sql) throws SQLException;
+
+ /**
+ * Creates a default PreparedStatement that can retrieve automatically
+ * generated keys. Parameter <code>autoGeneratedKeys</code> may be used to
+ * specify to the driver if such keys should be made accessible. This is
+ * only the case when <code>sql</code> is an insert statement.
+ * <p>
+ * An SQL statement which may have IN parameters can be stored and
+ * precompiled in a PreparedStatement. The PreparedStatement can then be
+ * used to execute the statement multiple times in an efficient way.
+ * <p>
+ * 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 flowing precompiled statements, the
+ * statement will not reach the database server until it is executed. This
+ * will have a bearing on precisely when <code>SQLException</code>
+ * instances get raised.
+ * <p>
+ * By default, ResultSets 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 :
+ * <ul>
+ * <li>{@link Statement#RETURN_GENERATED_KEYS}
+ * <li>{@link Statement#NO_GENERATED_KEYS}
+ * </ul>
+ * @return a new <code>PreparedStatement</code> instance representing the
+ * input SQL statement.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
+ throws SQLException;
+
+ /**
+ * Creates a default PreparedStatement that can retrieve the auto-generated
+ * keys designated by a supplied array. If <code>sql</code> is an SQL
+ * <code>INSERT</code> statement, parameter <code>columnIndexes</code>
+ * 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</code> is ignored.
+ * <p>
+ * 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 flowing precompiled statements, the
+ * statement will not reach the database server until it is executed. This
+ * will have a bearing on precisely when <code>SQLException</code>
+ * instances get raised.
+ * <p>
+ * By default, ResultSets 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 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
+ */
+ public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
+ throws SQLException;
+
+ /**
+ * Creates a PreparedStatement that generates ResultSets with the specified
+ * values of <code>resultSetType</code> and
+ * <code>resultSetConcurrency</code>.
+ *
+ * @param sql
+ * the SQL statement. It can contain one or more '?' IN parameter
+ * placeholders
+ * @param resultSetType
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ * <li>{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ * <li>{@link ResultSet#TYPE_FORWARD_ONLY}
+ * </ul>
+ * @param resultSetConcurrency
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#CONCUR_READ_ONLY}
+ * <li>{@link ResultSet#CONCUR_UPDATABLE}
+ * </ul>
+ * @return a new instance of <code>PreparedStatement</code> containing the
+ * SQL statement <code>sql</code>. <code>ResultSet</code>s
+ * emitted from this <code>PreparedStatement</code> will satisfy
+ * the specified <code>resultSetType</code> and
+ * <code>resultSetConcurrency</code> values.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency) throws SQLException;
+
+ /**
+ * Creates a PreparedStatement that generates ResultSets with the specified
+ * type, concurrency and holdability
+ *
+ * @param sql
+ * the SQL statement. It can contain one or more '?' IN parameter
+ * placeholders
+ * @param resultSetType
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#TYPE_SCROLL_SENSITIVE}
+ * <li>{@link ResultSet#TYPE_SCROLL_INSENSITIVE}
+ * <li>{@link ResultSet#TYPE_FORWARD_ONLY}
+ * </ul>
+ * @param resultSetConcurrency
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#CONCUR_READ_ONLY}
+ * <li>{@link ResultSet#CONCUR_UPDATABLE}
+ * </ul>
+ * @param resultSetHoldability
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ * <li>{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ * </ul>
+ *
+ * @return a new instance of <code>PreparedStatement</code> containing the
+ * SQL statement <code>sql</code>. <code>ResultSet</code>s
+ * emitted from this <code>PreparedStatement</code> will satisfy
+ * the specified <code>resultSetType</code>,
+ * <code>resultSetConcurrency</code> and
+ * <code>resultSetHoldability</code> values.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public PreparedStatement prepareStatement(String sql, int resultSetType,
+ int resultSetConcurrency, int resultSetHoldability)
+ throws SQLException;
+
+ /**
+ * Creates a default PreparedStatement that can retrieve the auto-generated
+ * keys designated by a supplied array. If <code>sql</code> is an SQL
+ * <code>INSERT</code> statement, <code>columnNames</code> 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</code> is ignored.
+ * <p>
+ * 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 flowing precompiled statements, the
+ * statement will not reach the database server until it is executed. This
+ * will have a bearing on precisely when <code>SQLException</code>
+ * instances get raised.
+ * <p>
+ * By default, ResultSets 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 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
+ */
+ public PreparedStatement prepareStatement(String sql, String[] columnNames)
+ throws SQLException;
+
+ /**
+ * Releases <code>savepoint</code> from the present transaction. Once
+ * removed, the <code>Savepoint</code> 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</code> is considered not valid in this
+ * transaction.
+ */
+ public void releaseSavepoint(Savepoint savepoint) throws SQLException;
+
+ /**
+ * Rolls back all updates made so far in this transaction as well as
+ * relinquishing 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.
+ */
+ public void rollback() throws SQLException;
+
+ /**
+ * Undoes all changes made after the supplied 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
+ */
+ public void rollback(Savepoint savepoint) throws SQLException;
+
+ /**
+ * Sets this connection's auto-commit mode on or off.
+ * <p>
+ * Putting a Connection into auto-commit mode means that all associated SQL
+ * statements will be run and committed in their own separate transactions.
+ * Alternatively, auto-commit set to 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.
+ * <p>
+ * Auto-commit is the default mode for new connection instances.
+ * <p>
+ * 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 complete until all associated
+ * <code>ResultSet</code>s and output parameters have been obtained or
+ * closed.
+ * <p>
+ * Calling this operation during an uncommitted transaction will result in
+ * it being committed.
+ *
+ * @param autoCommit
+ * boolean indication of whether to put the target connection
+ * into auto-commit mode (<code>true</code>) or not (<code>false</code>)
+ *
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ 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
+ */
+ public void setCatalog(String catalog) throws SQLException;
+
+ /**
+ * Sets the holdability of ResultSets created by this Connection.
+ *
+ * @param holdability
+ * one of :
+ * <ul>
+ * <li>{@link ResultSet#CLOSE_CURSORS_AT_COMMIT}
+ * <li>{@link ResultSet#HOLD_CURSORS_OVER_COMMIT}
+ * <li>
+ * </ul>
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public void setHoldability(int holdability) throws SQLException;
+
+ /**
+ * Sets this connection to read-only mode.
+ * <p>
+ * This serves as a hint to the driver, which can enable database
+ * optimizations.
+ *
+ * @param readOnly
+ * true to set the Connection to read only mode. false disables
+ * read-only mode
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public void setReadOnly(boolean readOnly) throws SQLException;
+
+ /**
+ * Creates an unnamed Savepoint in the current transaction.
+ *
+ * @return a Savepoint object for this savepoint.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Savepoint setSavepoint() throws SQLException;
+
+ /**
+ * Creates a named Savepoint in the current transaction.
+ *
+ * @param name
+ * the name to use for the new Savepoint.
+ * @return a Savepoint object for this savepoint.
+ * @throws SQLException
+ * if there is a problem accessing the database
+ */
+ public Savepoint setSavepoint(String name) throws SQLException;
+
+ /**
+ * Sets the transaction isolation level for this Connection.
+ * <p>
+ * 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 :
+ * <ul>
+ * <li>{@link #TRANSACTION_READ_COMMITTED}
+ * <li>{@link #TRANSACTION_READ_UNCOMMITTED}
+ * <li>{@link #TRANSACTION_REPEATABLE_READ}
+ * <li>{@link #TRANSACTION_SERIALIZABLE}
+ * </ul>
+ * @throws SQLException
+ * if there is a problem with the database or if the value of
+ * <code>level</code> is not one of the expected constant
+ * values.
+ */
+ public void setTransactionIsolation(int level) throws SQLException;
+
+ /**
+ * Sets the <code>TypeMap</code> for this connection. The input
+ * <code>map</code> 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</code> is not an instance of {@link Map}.
+ */
+ public void setTypeMap(Map<String, Class<?>> 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..7150ec7
--- /dev/null
+++ b/sql/src/main/java/java/sql/DataTruncation.java
@@ -0,0 +1,126 @@
+/*
+ * 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 or when writing data.
+ *
+ * The SQLState value for a <code>DataTruncation</code> is <code>01004</code>.
+ */
+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 a DataTruncation. The Reason is set to "Data truncation", the
+ * ErrorCode is set to the SQLException default value and other fields are
+ * set to the values supplied on this method.
+ *
+ * @param index
+ * the Index value of the column value or parameter that was
+ * truncated
+ * @param parameter
+ * true if it was a Parameter value that was truncated, false
+ * otherwise
+ * @param read
+ * true if the truncation occurred on a read operation, false
+ * otherwise
+ * @param dataSize
+ * the original size of the truncated data
+ * @param transferSize
+ * the size of the data after truncation
+ */
+ 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 may be set to -1 if the size is unknown.
+ */
+ 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.
+ */
+ public int getIndex() {
+ return index;
+ }
+
+ /**
+ * Gets whether the value truncated was a parameter value or a column value.
+ *
+ * @return true if the value truncated was a Parameter value, false if it
+ * was a column value
+ */
+ public boolean getParameter() {
+ return parameter;
+ }
+
+ /**
+ * Gets whether the value was truncated on a read operation or a write
+ * operation
+ *
+ * @return true if the value was truncated on a read operation, false
+ * otherwise.
+ */
+ 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 -1 if the size is unknown.
+ */
+ 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..8c0f17c
--- /dev/null
+++ b/sql/src/main/java/java/sql/DatabaseMetaData.java
@@ -0,0 +1,3081 @@
+/*
+ * 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.
+ * <p>
+ * This interface is implemented by JDBC driver writers in order to provide
+ * information about the underlying Database capabilities and the JDBC driver
+ * capabilities taken together.
+ * <p>
+ * Some of the methods in this interface take String parameters which are
+ * Patterns. Within these string Patterns, '%' and '_' characters have special
+ * meanings. '%' means "match any substring of 0 or more characters". '_' means
+ * "match any one character". Only metadata entries that match the pattern are
+ * returned. If such a search pattern string is set to <code>null</code>,
+ * that argument's criteria are dropped from the search.
+ *
+ */
+public interface DatabaseMetaData {
+
+ /**
+ * States that it may not be permitted to store <code>NULL</code> values.
+ */
+ public static final short attributeNoNulls = 0;
+
+ /**
+ * States that <code>NULL</code> values are definitely permitted.
+ */
+ public static final short attributeNullable = 1;
+
+ /**
+ * States that whether <code>NULL</code> values are permitted is unknown.
+ */
+ public static final short attributeNullableUnknown = 2;
+
+ /**
+ * States the best row identifier is <em>NOT</em> a pseudo column.
+ */
+ public static final int bestRowNotPseudo = 1;
+
+ /**
+ * States that the best row identifier is a pseudo column.
+ */
+ public static final int bestRowPseudo = 2;
+
+ /**
+ * States that the remainder of the current session is used as the scope for
+ * the best row identifier.
+ */
+ public static final int bestRowSession = 2;
+
+ /**
+ * States that best row identifier scope lasts only while the row is being
+ * used.
+ */
+ public static final int bestRowTemporary = 0;
+
+ /**
+ * States that the remainder of the current transaction is used as the scope
+ * for the best row identifier.
+ */
+ public static final int bestRowTransaction = 1;
+
+ /**
+ * States that the best row identifier may or may not be a pseudo column.
+ */
+ public static final int bestRowUnknown = 0;
+
+ /**
+ * States that the column might not allow <code>NULL</code> values.
+ */
+ public static final int columnNoNulls = 0;
+
+ /**
+ * States that the column definitely allows <code>NULL</code> values.
+ */
+ public static final int columnNullable = 1;
+
+ /**
+ * States that it is unknown whether the columns may be nulled.
+ */
+ public static final int columnNullableUnknown = 2;
+
+ /**
+ * For the column UPDATE_RULE, States that when the primary key is updated,
+ * the foreign key (imported key) is changed to agree with it.
+ */
+ public static final int importedKeyCascade = 0;
+
+ /**
+ * States deferrability.
+ */
+ public static final int importedKeyInitiallyDeferred = 5;
+
+ /**
+ * States defer-ability.
+ */
+ public static final int importedKeyInitiallyImmediate = 6;
+
+ /**
+ * For the columns UPDATE_RULE and DELETE_RULE, States that if the primary
+ * key has been imported, it cannot be updated or deleted.
+ */
+ public static final int importedKeyNoAction = 3;
+
+ /**
+ * States defer-ability.
+ */
+ 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 UPDATE_RULE.
+ */
+ 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
+ * UPDATE_RULE and DELETE_RULE columns.
+ */
+ 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</code>. Applies to the
+ * UPDATE_RULE and DELETE_RULE columns.
+ */
+ public static final int importedKeySetNull = 2;
+
+ /**
+ * States that this column stores IN type parameters.
+ */
+ public static final int procedureColumnIn = 1;
+
+ /**
+ * States that this column stores INOUT type parameters.
+ */
+ public static final int procedureColumnInOut = 2;
+
+ /**
+ * States that this column stores OUT type parameters.
+ */
+ public static final int procedureColumnOut = 4;
+
+ /**
+ * States that the column stores results
+ */
+ public static final int procedureColumnResult = 3;
+
+ /**
+ * States that the column stores return values.
+ */
+ public static final int procedureColumnReturn = 5;
+
+ /**
+ * States that type of the column is unknown.
+ */
+ public static final int procedureColumnUnknown = 0;
+
+ /**
+ * States that <code>NULL</code> values are not permitted.
+ */
+ public static final int procedureNoNulls = 0;
+
+ /**
+ * States that the procedure does not return a result.
+ */
+ public static final int procedureNoResult = 1;
+
+ /**
+ * States that <code>NULL</code> values are permitted.
+ */
+ public static final int procedureNullable = 1;
+
+ /**
+ * States that whether <code>NULL</code> values are permitted is unknown.
+ */
+ public static final int procedureNullableUnknown = 2;
+
+ /**
+ * States that it is unknown whether or not the procedure returns a result.
+ */
+ public static final int procedureResultUnknown = 0;
+
+ /**
+ * States that the procedure returns a result.
+ */
+ public static final int procedureReturnsResult = 2;
+
+ /**
+ * States that the value is an SQL99 SQLSTATE value.
+ */
+ public static final int sqlStateSQL99 = 2;
+
+ /**
+ * States that the value is an SQL CLI SQLSTATE value as defined by X/Open
+ * (who are now know as Open Group) .
+ */
+ public static final int sqlStateXOpen = 1;
+
+ /**
+ * States that this table index is a clustered index.
+ */
+ public static final short tableIndexClustered = 1;
+
+ /**
+ * States that this table index is a hashed index.
+ */
+ 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.
+ */
+ 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.
+ */
+ public static final short tableIndexStatistic = 0;
+
+ /**
+ * States that a <code>NULL</code> value is <em>NOT</em> permitted for
+ * this data type.
+ */
+ public static final int typeNoNulls = 0;
+
+ /**
+ * States that a <code>NULL</code> value is permitted for this data type.
+ */
+ public static final int typeNullable = 1;
+
+ /**
+ * States that it is unknown if a <code>NULL</code> value is permitted for
+ * this data type.
+ */
+ public static final int typeNullableUnknown = 2;
+
+ /**
+ * States that one can base all WHERE search clauses except WHERE .
+ */
+ public static final int typePredBasic = 2;
+
+ /**
+ * States that <code>WHERE</code> is the only WHERE search clause that may
+ * be based on this type.
+ */
+ public static final int typePredChar = 1;
+
+ /**
+ * States that this type does not support <code>WHERE</code> search
+ * clauses.
+ */
+ public static final int typePredNone = 0;
+
+ /**
+ * States that all WHERE search clauses may be based on this type.
+ */
+ 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 <code>getProcedures</code>
+ * can be called by the current user.
+ *
+ * @return <code>true</code> if all procedures can be called by the
+ * current user, <code>false</code> otherwise.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean allProceduresAreCallable() throws SQLException;
+
+ /**
+ * Returns whether all the tables returned by <code>getTables</code> can
+ * be used by the current user in a SELECT statement.
+ *
+ * @return <code>true</code> if all the tables can be used,<code>false</code>
+ * otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean allTablesAreSelectable() throws SQLException;
+
+ /**
+ * Returns if a data definition statement in a transaction forces a commit
+ * of the transaction.
+ *
+ * @return <code>true</code> if the statement forces a commit,
+ * <code>false</code> otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean dataDefinitionCausesTransactionCommit() throws SQLException;
+
+ /**
+ * Returns whether the database ignores data definition statements within a
+ * transaction.
+ *
+ * @return <code>true</code> if the database ignores a data definition
+ * statement, <code>false</code> otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean dataDefinitionIgnoredInTransactions() throws SQLException;
+
+ /**
+ * Returns whether a visible row delete can be detected by calling
+ * <code>ResultSet.rowDeleted</code>.
+ *
+ * @param type
+ * the type of the ResultSet involved:
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @return <code>true</code> if the visible row delete can be detected,
+ * <code>false</code> otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean deletesAreDetected(int type) throws SQLException;
+
+ /**
+ * Returns whether the return value of <code>getMaxRowSize</code> includes
+ * the SQL data types <code>LONGVARCHAR</code> and
+ * <code>LONGVARBINARY</code>.
+ *
+ * @return <code>true</code> if the return value includes
+ * <code>LONGVARBINARY</code> and <code>LONGVARCHAR</code>,
+ * otherwise <code>false</code>.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean doesMaxRowSizeIncludeBlobs() throws SQLException;
+
+ /**
+ * Returns a description of the specified attribute of the specified type
+ * for an SQL User Defined Type (UDT) for a specified schema and catalog.
+ * The descriptions returned are ordered by <code>TYPE_SCHEM</code>,
+ * <code>TYPE_NAME</code> and ORDINAL_POSITION. The descriptions do not
+ * contain inherited attributes.
+ * <p>
+ * The returned ResultSet object has rows with the following column names
+ * and meanings:
+ * <ol>
+ * <li><code>TYPE_CAT</code> - String - the Type Catalog name (possibly
+ * <code>null</code>)</li>
+ * <li><code>TYPE_SCHEM</code> - String - the Type Schema name (possibly
+ * <code>null</code>)</li>
+ * <li><code>TYPE_NAME</code> - String - the Type name</li>
+ * <li><code>ATTR_NAME</code> - String - the Attribute name</li>
+ * <li><code>DATA_TYPE</code> - int - the Attribute type as defined in
+ * <code>java.sql.Types</code></li>
+ * <li><code>ATTR_TYPE_NAME</code> - String - the Attribute type name.
+ * This depends on the data source. For a <code>UDT</code> the name is
+ * fully qualified. For a <code>REF</code> it is both fully qualified and
+ * represents the target type of the reference.</li>
+ * <li><code>ATTR_SIZE</code> - 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.</li>
+ * <li><code>DECIMAL_DIGITS</code> - int - how many fractional digits are
+ * supported</li>
+ * <li><code>NUM_PREC_RADIX</code> - int - numeric values radix</li>
+ * <li><code>NULLABLE</code> - int - whether <code>NULL</code> is
+ * permitted:
+ * <ul>
+ * <li>DatabaseMetaData.attributeNoNulls - might not allow
+ * <code>NULL</code>s</li>
+ * <li>DatabaseMetaData.attributeNullable - <code>NULL</code>s
+ * definitely permitted</li>
+ * <li>DatabaseMetaData.attributeNullableUnknown - unknown</li>
+ * </ul>
+ * </li>
+ * <li><code>REMARKS</code> - String - A comment describing the attribute
+ * (possibly <code>null</code>)</li>
+ * <li>ATTR_DEF - String - Default value for the attribute (possibly
+ * <code>null</code>)</li>
+ * <li><code>SQL_DATA_TYPE</code> - int - not used</li>
+ * <li>SQL_DATETIME_SUB - int - not used</li>
+ * <li>CHAR_OCTET_LENGTH - int - For <code>CHAR</code> types, the max
+ * number of bytes in the column</li>
+ * <li>ORDINAL_POSITION - int - The Index of the column in the Table (based
+ * on 1)</li>
+ * <li>IS_NULLABLE - String - "NO" = column does not allow
+ * <code>NULL</code>s, "YES" = column allows <code>NULL</code>s "" =
+ * <code>NULL</code> status unknown</li>
+ * <li><code>SCOPE_CATALOG</code> - String - Catalog for table,
+ * <code>SCOPE</code> of Reference attribute. NULL if
+ * <code>DATA_TYPE</code> is not REF.</li>
+ * <li><code>SCOPE_SCHEMA</code> - String - Schema for table,
+ * <code>SCOPE</code> of Reference attribute. NULL if
+ * <code>DATA_TYPE</code> is not REF.</li>
+ * <li><code>SCOPE_TABLE</code> - String - Table name for
+ * <code>SCOPE</code> of Reference attribute. <code>NULL</code> if
+ * <code>DATA_TYPE</code> is not REF.</li>
+ * <li><code>SOURCE_DATA_TYPE</code> - String - The source type for user
+ * generated REF type or for a Distinct type. (<code>NULL</code> if
+ * <code>DATA_TYPE</code> is not DISTINCT or user generated REF)</li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. <code>null</code> 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 schemaPattern
+ * a Schema Name Pattern. <code>null</code> 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. This pattern must match the type name stored in
+ * the database.
+ * @param attributeNamePattern
+ * an Attribute name. Must match the attribute name as stored in
+ * the database.
+ * @return a ResultSet, where each Row is an attribute description
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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
+ * identifies a row. The results are ordered by <code>SCOPE</code> (see
+ * below).
+ * <p>
+ * The results are returned as a table, with one entry for each column, as
+ * follows:
+ * <ol>
+ * <li><code>SCOPE</code> - short - the <code>SCOPE</code> of the
+ * result, as follows:
+ * <ul>
+ * <li>DatabaseMetaData.bestRowTemporary - very temporary, while using row
+ * </li>
+ * <li>DatabaseMetaData.bestRowTransaction - good for remainder of current
+ * transaction </li>
+ * <li>DatabaseMetaData.bestRowSession - good for remainder of database
+ * session </li>
+ * </ul>
+ * </li>
+ * <li><code>COLUMN_NAME</code> - String - the column name </li>
+ * <li><code>DATA_TYPE</code> - int - the Type of the data, as defined in
+ * <code>java.sql.Types</code> </li>
+ * <li><code>TYPE_NAME</code> - String - Name of the type - database
+ * dependent. For UDT types the name is fully qualified </li>
+ * <li><code>COLUMN_SIZE</code> - int - The precision of the data in the
+ * column </li>
+ * <li><code>BUFFER_LENGTH</code> - int - not used </li>
+ * <li><code>DECIMAL_DIGITS</code> - short - number of fractional digits
+ * </li>
+ * <li><code>PSEUDO_COLUMN</code> - short - whether this is a pseudo
+ * column eg. and Oracle ROWID:
+ * <ul>
+ * <li>DatabaseMetaData.bestRowUnknown - don't know whether this is a
+ * pseudo column</li>
+ * <li>DatabaseMetaData.bestRowNotPseudo - column is not pseudo</li>
+ * <li>DatabaseMetaData.bestRowPseudo - column is a pseudo column</li>
+ * </ul>
+ * </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. <code>null</code> 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</code> 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 table
+ * the table name. This must match the name of the table as
+ * declared in the database.
+ * @param scope
+ * the <code>SCOPE</code> of interest, values as defined above
+ * @param nullable
+ * <code>true</code> = include columns that are nullable,
+ * <code>false</code> = do not include
+ * @return a 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
+ */
+ 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 ResultSet containing the Catalog names, with each row
+ * containing one Catalog name contained as a String in the single
+ * column named <code>TABLE_CAT</code>.
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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
+ */
+ 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
+ */
+ 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.
+ * <p>
+ * The description is returned as a ResultSet with rows of data for each
+ * access right, with columns as follows:
+ * <ol>
+ * <li><code>TABLE_CAT</code> - String - Catalog name (possibly
+ * <code>null</code>)</li>
+ * <li><code>TABLE_SCHEM</code> - String - Schema name (possibly
+ * <code>null</code>) </li>
+ * <li><code>TABLE_NAME</code> - String - The Table name </li>
+ * <li><code>COLUMN_NAME</code> - String - The Column name</li>
+ * <li><code>GRANTOR</code> - String - The grantor of access (possibly
+ * <code>null</code>)</li>
+ * <li><code>PRIVILEGE</code> - String - Access right - one of SELECT,
+ * INSERT, UPDATE, REFERENCES,...</li>
+ * <li><code>IS_GRANTABLE</code> - String - "YES" implies that the
+ * receiver can grant access to others, "NO" if the receiver cannot grant
+ * access to others, <code>null</code> if unknown.</li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. <code>null</code> 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</code> 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 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 ResultSet containing the access rights, one row for each
+ * privilege description
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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.
+ * <p>
+ * The descriptions are returned as a ResultSet conforming to the following
+ * data layout, with one row per table column:
+ * <ol>
+ * <li><code>TABLE_CAT</code> - String - Catalog name (possibly
+ * <code>null</code>)</li>
+ * <li><code>TABLE_SCHEM</code> - String - Schema name (possibly
+ * <code>null</code>) </li>
+ * <li><code>TABLE_NAME</code> - String - The Table name </li>
+ * <li><code>COLUMN_NAME</code> - String - The Column name</li>
+ * <li><code>DATA_TYPE</code> - int - The SQL type as specified in
+ * <code>java.sql.Types</code></li>
+ * <li><code>TYPE_NAME</code> - String - Name for the data type, depends
+ * on database, UDT names are fully qualified</li>
+ * <li><code>COLUMN_SIZE</code> - int - Column size - the precision for
+ * numeric types, max characters for char and date types</li>
+ * <li><code>BUFFER_LENGTH</code> - int - Not used </li>
+ * <li><code>DECIMAL_DIGITS</code> - int - maximum number of fractional
+ * digits </li>
+ * <li><code>NUM_PREC_RADIX</code> - int - the Radix </li>
+ * <li><code>NULLABLE</code> - int - does the column allow
+ * <code>null</code>s:
+ * <ul>
+ * <li>DatabaseMetaData.columnNoNulls = may not allow <code>NULL</code>s</li>
+ * <li>DatabaseMetaData.columnNullable = does allow <code>NULL</code>s</li>
+ * <li>DatabaseMetaData.columnNullableUnknown = unknown <code>NULL</code>
+ * status</li>
+ * </ul>
+ * </li>
+ * <li><code>REMARKS</code> - String - A description of the column
+ * (possibly <code>null</code>) </li>
+ * <li><code>COLUMN_DEF</code> - String - Default value for the column
+ * (possibly <code>null</code>)</li>
+ * <li><code>SQL_DATA_TYPE</code> - int - not used </li>
+ * <li><code>SQL_DATETIME_SUB</code> - int - not used </li>
+ * <li><code>CHAR_OCTET_LENGTH</code> - int - maximum number of bytes in
+ * the char type columns </li>
+ * <li><code>ORDINAL_POSITION</code> - int - Column index in the table (1
+ * based) </li>
+ * <li><code>IS_NULLABLE</code> - String - "NO" = column does not allow
+ * NULLs, "YES" = column allows NULLs "" = <code>NULL</code> status
+ * unknown</li>
+ * <li><code>SCOPE</code>_CATALOG - String - Catalog for table,
+ * <code>SCOPE</code> of Reference attribute. NULL if
+ * <code>DATA_TYPE</code> is not REF.</li>
+ * <li><code>SCOPE_SCHEMA</code> - String - Schema for table, scope of
+ * Reference attribute. <code>NULL</code> if <code>DATA_TYPE</code> is
+ * not REF.</li>
+ * <li><code>SCOPE_TABLE</code> - String - Table name for scope of
+ * Reference attribute. <code>NULL</code> if <code>DATA_TYPE</code> is
+ * not REF.</li>
+ * <li><code>SOURCE_DATA_TYPE</code> - String - The source type for user
+ * generated REF type or for a Distinct type. (<code>NULL</code> if
+ * <code>DATA_TYPE</code> is not DISTINCT or user generated REF)</li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. <code>null</code> 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 schemaPattern
+ * a Schema Name Pattern. <code>null</code> 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 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 ResultSet with rows in the form defined
+ * above
+ * @throws SQLException
+ * if there is a database error
+ */
+ public ResultSet getColumns(String catalog, String schemaPattern,
+ String tableNamePattern, String columnNamePattern)
+ throws SQLException;
+
+ /**
+ * Returns the database connection that created this metadata.
+ *
+ * @return the connection
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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.
+ * <p>
+ * The descriptions are returned as a ResultSet with one row for each
+ * Foreign key, with the following layout:
+ * <ol>
+ * <li><code>PKTABLE_CAT</code> - String - from the primary key table :
+ * Catalog (possibly <code>null</code>)</li>
+ * <li><code>PKTABLE_SCHEM</code> - String - from the primary key table :
+ * Schema (possibly <code>null</code>) </li>
+ * <li><code>PKTABLE_NAME</code> - String - primary key table : name
+ * </li>
+ * <li><code>PKCOLUMN_NAME</code> - String - primary key column : name</li>
+ * <li><code>FKTABLE_CAT</code> - String - from the foreign key table :
+ * the catalog name being exported (possibly <code>null</code>)</li>
+ * <li><code>FKTABLE_SCHEM</code> - String - foreign key table : Schema
+ * name being exported (possibly <code>null</code>) </li>
+ * <li><code>FKTABLE_NAME</code> - String - foreign key table : the name
+ * being exported</li>
+ * <li><code>FKCOLUMN_NAME</code> - String - foreign key column : the
+ * name being exported</li>
+ * <li><code>KEY_SEQ</code> - short - sequence number (in the foreign
+ * key)</li>
+ * <li><code>UPDATE_RULE</code> - short - how to treat foreign key when
+ * primary key is updated:
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyNoAction - don't allow update of primary
+ * key if imported</li>
+ * <li>DatabaseMetaData.importedKeyCascade - change imported key to match
+ * the primary key update</li>
+ * <li>DatabaseMetaData.importedKeySetNull - set the imported key to
+ * <code>null</code></li>
+ * <li>DatabaseMetaData.importedKeySetDefault - set the imported key to
+ * default values</li>
+ * <li>DatabaseMetaData.importedKeyRestrict - same as importedKeyNoAction</li>
+ * </ul>
+ * </li>
+ * <li><code>DELETE_RULE</code> - short - how to treat foreign key when
+ * primary key is deleted:
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyNoAction - don't allow delete of primary
+ * key if imported</li>
+ * <li>DatabaseMetaData.importedKeyCascade - delete those rows that import
+ * a deleted key</li>
+ * <li>DatabaseMetaData.importedKeySetNull - set the imported key to
+ * <code>null</code></li>
+ * <li>DatabaseMetaData.importedKeySetDefault - set the imported key to
+ * default values</li>
+ * <li>DatabaseMetaData.importedKeyRestrict - same as importedKeyNoAction</li>
+ * </ul>
+ * </li>
+ * <li>FK_NAME - String - foreign key name (possibly <code>null</code>)</li>
+ * <li>PK_NAME - String - primary key name (possibly <code>null</code>)</li>
+ * <li>DEFERRABILITY - short - can foreign key constraints be deferred
+ * until commit (see SQL92 specification for definitions)?:
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyInitiallyDeferred</li>
+ * <li>DatabaseMetaData.importedKeyInitiallyImmediate</li>
+ * <li>DatabaseMetaData.importedKeyNotDeferrable</li>
+ * </ul>
+ * </li>
+ * </ol>
+ *
+ * @param primaryCatalog
+ * a Catalog Name. <code>null</code> 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 primarySchema
+ * a Schema Name. <code>null</code> 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 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. <code>null</code> 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 foreignSchema
+ * a Schema Name. <code>null</code> 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 foreignTable
+ * the name of the table importing the key. It must match the
+ * name of the table in the database
+ * @return a 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
+ */
+ 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
+ */
+ 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
+ */
+ public int getDatabaseMinorVersion() throws SQLException;
+
+ /**
+ * Returns the name of the database software.
+ *
+ * @return a String with the name of the database software.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public String getDatabaseProductName() throws SQLException;
+
+ /**
+ * Returns the version number of this database software.
+ *
+ * @return a String with the version number of the database software.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public String getDatabaseProductVersion() throws SQLException;
+
+ /**
+ * Returns the default transaction isolation level for this database.
+ *
+ * @return the default transaction isolation level. One of
+ * <code>TRANSACTION_NONE</code>,
+ * <code>TRANSACTION_READ_COMMITTED</code>,
+ * <code>TRANSACTION_READ_UNCOMMITTED</code>,
+ * <code>TRANSACTION_REPEATABLE_READ</code> or
+ * <code>TRANSACTION_SERIALIZABLE</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public int getDefaultTransactionIsolation() throws SQLException;
+
+ /**
+ * Returns the JDBC driver's major version number.
+ *
+ * @return the driver's major version number
+ */
+ public int getDriverMajorVersion();
+
+ /**
+ * Returns the JDBC driver's minor version number.
+ *
+ * @return the driver's minor version number
+ */
+ public int getDriverMinorVersion();
+
+ /**
+ * Returns the name of this JDBC driver.
+ *
+ * @return a String containing the name of the JDBC driver
+ * @throws SQLException
+ * a database error occurred
+ */
+ public String getDriverName() throws SQLException;
+
+ /**
+ * Returns the version number of this JDBC driver.
+ *
+ * @return a String containing the complete version number of the JDBC
+ * driver
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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).
+ * <p>
+ * The list is returned as a ResultSet with a row for each of the foreign
+ * key columns, ordered by <code>FKTABLE_CAT</code>,
+ * <code>FKTABLE_SCHEM</code>, <code>FKTABLE_NAME</code>, and
+ * <code>KEY_SEQ</code>, with the format for each row being:
+ * <ol>
+ * <li><code>PKTABLE_CAT</code> - String - primary key table : Catalog
+ * (possibly <code>null</code>)</li>
+ * <li><code>PKTABLE_SCHEM</code> - String - primary key table : Schema
+ * (possibly <code>null</code>) </li>
+ * <li><code>PKTABLE_NAME</code> - String - primary key table : name
+ * </li>
+ * <li><code>PKCOLUMN_NAME</code> - String - primary key column : name</li>
+ * <li><code>FKTABLE_CAT</code> - String - foreign key table : Catalog
+ * name being exported (possibly <code>null</code>)</li>
+ * <li><code>FKTABLE_SCHEM</code> - String - foreign key table : Schema
+ * name being exported (possibly <code>null</code>) </li>
+ * <li><code>FKTABLE_NAME</code> - String - foreign key table : name
+ * being exported</li>
+ * <li><code>FKCOLUMN_NAME</code> - String - foreign key column : name
+ * being exported</li>
+ * <li>KEY_SEQ - short - sequence number in the foreign key</li>
+ * <li>UPDATE_RULE - short - how to treat foreign key when primary key is
+ * updated:
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyNoAction - don't allow update of primary
+ * key if imported</li>
+ * <li>DatabaseMetaData.importedKeyCascade - change imported key to match
+ * the primary key update</li>
+ * <li>DatabaseMetaData.importedKeySetNull - set the imported key to
+ * <code>null</code></li>
+ * <li>DatabaseMetaData.importedKeySetDefault - set the imported key to
+ * default values</li>
+ * <li>DatabaseMetaData.importedKeyRestrict - same as importedKeyNoAction</li>
+ * </ul>
+ * </li>
+ * <li>DELETE_RULE - short - how to treat foreign key when primary key is
+ * deleted:
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyNoAction - don't allow delete of primary
+ * key if imported</li>
+ * <li>DatabaseMetaData.importedKeyCascade - the deletion should also
+ * delete rows that import a deleted key</li>
+ * <li>DatabaseMetaData.importedKeySetNull - it should set the imported key
+ * to <code>null</code></li>
+ * <li>DatabaseMetaData.importedKeySetDefault - deletion sets the imported
+ * key to default values</li>
+ * <li>DatabaseMetaData.importedKeyRestrict - same as importedKeyNoAction</li>
+ * </ul>
+ * </li>
+ * <li>FK_NAME - String - foreign key name (possibly <code>null</code>)</li>
+ * <li>PK_NAME - String - primary key name (possibly <code>null</code>)</li>
+ * <li>DEFERRABILITY - short - defines whether foreign key constraints can
+ * be deferred until commit (see SQL92 specification for definitions):
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyInitiallyDeferred</li>
+ * <li>DatabaseMetaData.importedKeyInitiallyImmediate</li>
+ * <li>DatabaseMetaData.importedKeyNotDeferrable</li>
+ * </ul>
+ * </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. <code>null</code> 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. <code>null</code> 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 table
+ * a table name, which must match the name of a table in the
+ * database
+ * @return a ResultSet containing a row for each of the foreign key columns,
+ * as defined above
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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 a-z, A-Z, 0-9 and _ are always permitted.
+ *
+ * @return a String containing all the extra characters
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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
+ */
+ 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).
+ * <p>
+ * The list returned is a <code>ResultSet</code> with a row entry for each
+ * primary key column, ordered by <code>PKTABLE_CAT</code>,
+ * <code>PKTABLE_SCHEM</code>, <code>PKTABLE_NAME</code>, and
+ * <code>KEY_SEQ</code>, with the following format:
+ * <ol>
+ * <li><code>PKTABLE_CAT</code> - String - primary key Catalog name being
+ * imported (possibly <code>null</code>)</li>
+ * <li><code>PKTABLE_SCHEM</code> - String - primary key Schema name
+ * being imported (possibly <code>null</code>) </li>
+ * <li><code>PKTABLE_NAME</code> - String - primary key Table name being
+ * imported </li>
+ * <li><code>PKCOLUMN_NAME</code> - String - primary key column name
+ * being imported</li>
+ * <li><code>FKTABLE_CAT</code> - String - foreign key table catalog name
+ * (possibly <code>null</code>)</li>
+ * <li><code>FKTABLE_SCHEM</code> - String - foreign key table Schema
+ * name (possibly <code>null</code>) </li>
+ * <li><code>FKTABLE_NAME</code> - String - foreign key table name</li>
+ * <li><code>FKCOLUMN_NAME</code> - String - foreign key column name</li>
+ * <li>KEY_SEQ - short - sequence number in the foreign key</li>
+ * <li>UPDATE_RULE - short - how to treat foreign key when primary key is
+ * updated:
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyNoAction - don't allow update of primary
+ * key if imported</li>
+ * <li>DatabaseMetaData.importedKeyCascade - change imported key to match
+ * the primary key update</li>
+ * <li>DatabaseMetaData.importedKeySetNull - set the imported key to
+ * <code>null</code></li>
+ * <li>DatabaseMetaData.importedKeySetDefault - set the imported key to
+ * default values</li>
+ * <li>DatabaseMetaData.importedKeyRestrict - same as importedKeyNoAction</li>
+ * </ul>
+ * </li>
+ * <li>DELETE_RULE - short - how to treat foreign key when primary key is
+ * deleted:
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyNoAction - don't allow delete of primary
+ * key if imported</li>
+ * <li>DatabaseMetaData.importedKeyCascade - delete those rows that import
+ * a deleted key</li>
+ * <li>DatabaseMetaData.importedKeySetNull - set the imported key to
+ * <code>null</code></li>
+ * <li>DatabaseMetaData.importedKeySetDefault - set the imported key to
+ * default values</li>
+ * <li>DatabaseMetaData.importedKeyRestrict - same as importedKeyNoAction</li>
+ * </ul>
+ * </li>
+ * <li>FK_NAME - String - foreign key name (possibly <code>null</code>)</li>
+ * <li>PK_NAME - String - primary key name (possibly <code>null</code>)</li>
+ * <li>DEFERRABILITY - short - defines whether foreign key constraints can
+ * be deferred until commit (see SQL92 specification for definitions):
+ * <ul>
+ * <li>DatabaseMetaData.importedKeyInitiallyDeferred</li>
+ * <li>DatabaseMetaData.importedKeyInitiallyImmediate</li>
+ * <li>DatabaseMetaData.importedKeyNotDeferrable</li>
+ * </ul>
+ * </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. <code>null</code> 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. <code>null</code> 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 table
+ * a table name, which must match the name of a table in the
+ * database
+ * @return a ResultSet containing the list of primary key columns as rows in
+ * the format defined above.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public ResultSet getImportedKeys(String catalog, String schema, String table)
+ throws SQLException;
+
+ /**
+ * Returns a list of indices and statistics for a specified table.
+ * <p>
+ * The list is returned as a ResultSet, with one row for each index or
+ * statistic. The list is ordered by NON_UNIQUE, TYPE, INDEX_NAME, and
+ * ORDINAL_POSITION. Each row has the following format:
+ * <ol>
+ * <li><code>TABLE_CAT</code> - String - table catalog name (possibly
+ * <code>null</code>)</li>
+ * <li><code>TABLE_SCHEM</code> - String - Table Schema name (possibly
+ * <code>null</code>) </li>
+ * <li><code>TABLE_NAME</code> - String - The Table name </li>
+ * <li><code>NON_UNIQUE</code> - boolean - <code>true</code> when index
+ * values can be non-unique. Must be <code>false</code> when TYPE is
+ * tableIndexStatistic</li>
+ * <li><code>INDEX_QUALIFIER</code> - String : index catalog name.
+ * <code>null</code> when TYPE is 'tableIndexStatistic'</li>
+ * <li><code>INDEX_NAME</code> - String : index name. <code>null</code>
+ * when TYPE is 'tableIndexStatistic'</li>
+ * <li>TYPE - short - the index type. One of:
+ * <ul>
+ * <li>DatabaseMetaData.tableIndexStatistic - table statistics returned
+ * with Index descriptions</li>
+ * <li>DatabaseMetaData.tableIndexClustered - a clustered Index</li>
+ * <li>DatabaseMetaData.tableIndexHashed - a hashed Index</li>
+ * <li>DatabaseMetaData.tableIndexOther - other style of Index</li>
+ * </ul>
+ * </li>
+ * <li>ORDINAL_POSITION - short - column sequence within Index. 0 when TYPE
+ * is tableIndexStatistic </li>
+ * <li><code>COLUMN_NAME</code> - String - the column name.
+ * <code>null</code> when TYPE is tableIndexStatistic</li>
+ * <li>ASC_OR_DESC - String - column sort sequence. <code>null</code> if
+ * sequencing not supported or TYPE is tableIndexStatistic; otherwise "A"
+ * means sort ascending and "D" means sort descending. </li>
+ * <li>CARDINALITY - int - Number of unique values in the Index. If TYPE is
+ * tableIndexStatistic, this is number of rows in the table.</li>
+ * <li>PAGES - int - Number of pages for current Index. If TYPE is
+ * tableIndexStatistic, this is number of pages used for the table.</li>
+ * <li>FILTER_CONDITION - String - Filter condition. (possibly null) </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. 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. 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 table
+ * a table name, which must match the name of a table in the
+ * database
+ * @param unique
+ * <code>true</code> means only return indices for unique
+ * values, <code>false</code> implies that they can be returned
+ * even if not unique.
+ * @param approximate
+ * <code>true</code> implies that the list can contain
+ * approximate or "out of data" values, <code>false</code>
+ * implies that all values must be precisely accurate
+ * @return a ResultSet containing the list of indices and statistics for the
+ * table, in the format defined above.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ public int getMaxColumnNameLength() throws SQLException;
+
+ /**
+ * Get the maximum number of columns in a GROUP BY clause for this database.
+ *
+ * @return the maximum number of columns in a GROUP BY clause. If the limit
+ * is unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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
+ */
+ public int getMaxColumnsInIndex() throws SQLException;
+
+ /**
+ * Returns the maximum number of columns in an ORDER BY clause for this
+ * database.
+ *
+ * @return the maximum number of columns in an ORDER BY clause. If the limit
+ * is unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public int getMaxColumnsInOrderBy() throws SQLException;
+
+ /**
+ * Returns the maximum number of columns in a SELECT list for this database.
+ *
+ * @return the maximum number of columns in a SELECT list. If the limit is
+ * unknown, or the value is unlimited, then the result is zero.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ public int getMaxTableNameLength() throws SQLException;
+
+ /**
+ * Returns the maximum number of tables permitted in a SELECT statement for
+ * the database.
+ *
+ * @return the maximum number of tables permitted in a SELECT statement. If
+ * the limit is unknown, or the value is unlimited, then the result
+ * is zero.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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
+ */
+ 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
+ */
+ public String getNumericFunctions() throws SQLException;
+
+ /**
+ * Returns a list of the primary key columns of a specified table.
+ * <p>
+ * The list is returned as a ResultSet with one row for each primary key
+ * column, ordered by <code>COLUMN_NAME</code>, with each row having the
+ * structure as follows:
+ * <ol>
+ * <li><code>TABLE_CAT</code> - String - table catalog name (possibly
+ * null)</li>
+ * <li><code>TABLE_SCHEM</code> - String - Table Schema name (possibly
+ * null) </li>
+ * <li><code>TABLE_NAME</code> - String - The Table name </li>
+ * <li><code>COLUMN_NAME</code> - String - The Column name </li>
+ * <li><code>KEY_SEQ</code> - short - the sequence number for this column
+ * in the primary key</li>
+ * <li><code>PK_NAME</code> - String - the primary key name (possibly
+ * null)</li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. <code>null</code> 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 the
+ * empty string used to retrieve those without a Catalog Name.
+ * @param schema
+ * a Schema Name. <code>null</code> is used to imply no
+ * narrowing of the search using 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 ResultSet containing the list of keys in the format defined
+ * above
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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.
+ * <p>
+ * The list is returned as a ResultSet with one row for each parameter or
+ * result column. The data is ordered by PROCEDURE_SCHEM and 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 ResultSet columns in column number order. Each row has the
+ * following structure:
+ * <ol>
+ * <li>PROCEDURE_CAT - String - the procedure catalog name</li>
+ * <li>PROCEDURE_SCHEM - String - the procedure schema name (possibly null)
+ * </li>
+ * <li>PROCEDURE_NAME - String - the procedure name</li>
+ * <li><code>COLUMN_NAME</code> - String - the name of the column</li>
+ * <li>COLUMN_TYPE - short - the kind of column or parameter, as follows:
+ * <ul>
+ * <li>DatabaseMetaData.procedureColumnUnknown - type unknown</li>
+ * <li>DatabaseMetaData.procedureColumnIn - an IN parameter</li>
+ * <li>DatabaseMetaData.procedureColumnInOut - an INOUT parameter</li>
+ * <li>DatabaseMetaData.procedureColumnOut - an OUT parameter</li>
+ * <li>DatabaseMetaData.procedureColumnReturn - a return value</li>
+ * <li>DatabaseMetaData.procedureReturnsResult - a result column in a
+ * result set</li>
+ * </ul>
+ * </li>
+ * <li><code>DATA_TYPE</code> - int - the SQL type of the data, as in
+ * <code>java.sql.Types</code> </li>
+ * <li><code>TYPE_NAME</code> - String - the SQL type name, for a UDT it
+ * is fully qualified</li>
+ * <li>PRECISION - int - the precision</li>
+ * <li>LENGTH - int - the length of the data in bytes </li>
+ * <li>SCALE - short - the scale for numeric types</li>
+ * <li>RADIX - short - the Radix for numeric data (typically 2 or 10) </li>
+ * <li>NULLABLE - short - can the data contain null:
+ * <ul>
+ * <li>DatabaseMetaData.procedureNoNulls - <code>NULL</code>s not
+ * permitted</li>
+ * <li>DatabaseMetaData.procedureNullable - <code>NULL</code>s are
+ * permitted </li>
+ * <li>DatabaseMetaData.procedureNullableUnknown - <code>NULL</code>
+ * status unknown </li>
+ * </ul>
+ * </li>
+ * <li><code>REMARKS</code> - String - an explanatory comment about the
+ * data item </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. 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 schemaPattern
+ * a Schema Name Pattern. 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 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 ResultSet with the list of parameter and result columns in the
+ * format defined above
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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.
+ * <p>
+ * The list is returned as a ResultSet with one row for each stored
+ * procedure, ordered by PROCEDURE_SCHEME and PROCEDURE_NAME, with the data
+ * in each row as follows:
+ * <ol>
+ * <li><code>PROCEDURE_CAT</code> - String : the procedure catalog name</li>
+ * <li><code>PROCEDURE_SCHEM</code> - String : the procedure schema name
+ * (possibly <code>null</code>) </li>
+ * <li><code>PROCEDURE_NAME</code> - String : the procedure name</li>
+ * <li><code>Reserved</code></li>
+ * <li><code>Reserved</code></li>
+ * <li><code>Reserved</code></li>
+ * <li><code>REMARKS</code> - String - information about the procedure</li>
+ * <li><code>PROCEDURE_TYPE</code> - short : one of:
+ * <ul>
+ * <li>DatabaseMetaData.procedureResultUnknown - procedure may return a
+ * result </li>
+ * <li>DatabaseMetaData.procedureNoResult - procedure does not return a
+ * result</li>
+ * <li>DatabaseMetaData.procedureReturnsResult - procedure definitely
+ * returns a result</li>
+ * </ul>
+ * </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. 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 schemaPattern
+ * a Schema Name Pattern. 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 procedureNamePattern
+ * a procedure name pattern, which must match the procedure name
+ * stored in the database
+ * @return a ResultSet where each row is a description of a stored procedure
+ * in the format defined above.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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
+ */
+ public String getProcedureTerm() throws SQLException;
+
+ /**
+ * Returns the result set's default hold-ability.
+ *
+ * @return one of <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
+ * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
+ * @throws SQLException
+ * a database error occurred
+ */
+ public int getResultSetHoldability() throws SQLException;
+
+ /**
+ * Returns a list of the schema names in the database. The list is returned
+ * as a ResultSet, ordered by the Schema name, with one row per Schema in
+ * the following format:
+ * <ol>
+ * <li><code>TABLE_SCHEM</code> - String - the Schema name</li>
+ * <li><code>TABLE_CAT</code>ALOG - String - the Catalog name (possibly
+ * null) </li>
+ * </ol>
+ *
+ * @return a ResultSet with one row for each schema in the format defined
+ * above.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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
+ */
+ public String getSchemaTerm() throws SQLException;
+
+ /**
+ * Returns the string that is used to escape wildcard characters. This
+ * string is used to escape the '_' and '%' wildcard characters in catalog
+ * search strings which are a pattern and so which use the wildcard
+ * characters. '_' is used to represent any single character wile '%' 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
+ */
+ 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
+ */
+ public String getSQLKeywords() throws SQLException;
+
+ /**
+ * States the type of SQLState value returned by 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 DatabaseMetaData.sqlStateSQL99 or
+ * DatabaseMetaData.sqlStateXOpen.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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
+ */
+ public String getStringFunctions() throws SQLException;
+
+ /**
+ * Returns a listing of the hierarchies of tables in a specified schema in
+ * the database.
+ * <p>
+ * The listing only contains entries for tables that have a super table.
+ * Super and sub tables must be defined in the same Catalog and Schema. The
+ * list is returned as a ResultSet, with one row for each table that has a
+ * super table, in the following format:
+ * <ol>
+ * <li><code>TABLE_CAT</code> - String - table catalog name (possibly
+ * null)</li>
+ * <li><code>TABLE_SCHEM</code> - String - Table Schema name (possibly
+ * null) </li>
+ * <li><code>TABLE_NAME</code> - String - The Table name </li>
+ * <li>SUPER<code>TABLE_NAME</code> - String - The Super Table name
+ * </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. 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 schemaPattern
+ * a Schema Name Pattern. 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 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 ResultSet with one row for each table which has a super table,
+ * in the format defined above. An empty ResultSet is returned if
+ * the database does not support table hierarchies.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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.
+ * <p>
+ * The listing is returned as a ResultSet where there is one row for a
+ * specific UDT which describes its supertype, with the data organized in
+ * columns as follows:
+ * <ol>
+ * <li><code>TYPE_CAT</code> - String - the UDT Catalog name (possibly
+ * null)</li>
+ * <li><code>TYPE_SCHEM</code> - String - the UDT Schema name (possibly
+ * null) </li>
+ * <li><code>TYPE_NAME</code> - String - the UDT type name </li>
+ * <li>SUPER<code>TYPE_CAT</code> - String - direct supertype's Catalog
+ * name (possibly null)</li>
+ * <li>SUPER<code>TYPE_SCHEM</code> - String - direct supertype's Schema
+ * name (possibly null) </li>
+ * <li>SUPER<code>TYPE_NAME</code> - String - direct supertype's name
+ * </li>
+ * </ol>
+ *
+ * @param catalog
+ * the Catalog name. "" means get the UDTs without a catalog.
+ * 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 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
+ */
+ 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
+ */
+ 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.
+ * <p>
+ * The privileges are returned as a ResultSet, with one row for each
+ * privilege, ordered by <code>TABLE_SCHEM</code>,
+ * <code>TABLE_NAME</code>, PRIVILEGE, and each row has data as defined
+ * in the following column definitions:
+ * <ol>
+ * <li><code>TABLE_CAT</code> - String - table catalog name (possibly
+ * null)</li>
+ * <li><code>TABLE_SCHEM</code> - String - Table Schema name (possibly
+ * null) </li>
+ * <li><code>TABLE_NAME</code> - String - The Table name </li>
+ * <li>GRANTOR - String - who granted the access</li>
+ * <li>GRANTEE - String - who received the access grant </li>
+ * <li>PRIVILEGE - String - the type of access granted - one of SELECT,
+ * INSERT, UPDATE, REFERENCES,... </li>
+ * <li>IS_GRANTABLE - String - "YES" implies the grantee can grant access
+ * to others, "NO" implies guarantee cannot grant access to others, null
+ * means this status is unknown</li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. 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 schemaPattern
+ * a Schema Name Pattern. 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 tableNamePattern
+ * a Table Name, which should match the Table name as stored in
+ * the database.
+ * @return a ResultSet containing a list with one row for each table in the
+ * format defined above.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public ResultSet getTablePrivileges(String catalog, String schemaPattern,
+ String tableNamePattern) throws SQLException;
+
+ /**
+ * Returns a description of the tables in a specified catalog.
+ * <p>
+ * The descriptions are returned as rows in a ResultSet, one row for each
+ * Table. The ResultSet is ordered by <code>TABLE_TYPE</code>,
+ * <code>TABLE_SCHEM</code> and <code>TABLE_NAME</code>. Each row in
+ * the ResultSet consists of a series of columns as follows:
+ * <ol>
+ * <li><code>TABLE_CAT</code> - String - table catalog name (possibly
+ * null)</li>
+ * <li><code>TABLE_SCHEM</code> - String - Table Schema name (possibly
+ * null) </li>
+ * <li><code>TABLE_NAME</code> - String - The Table name </li>
+ * <li><code>TABLE_TYPE</code> - String - Typical names include "TABLE",
+ * "VIEW", "SYSTEM TABLE", "ALIAS", "SYNONYM", "GLOBAL TEMPORARY"</li>
+ * <li><code>REMARKS</code> - String - A comment describing the table
+ * </li>
+ * <li><code>TYPE_CAT</code> - String - the 'Types' catalog(possibly
+ * null)</li>
+ * <li><code>TYPE_SCHEM</code> - String - the 'Types' schema(possibly
+ * null) </li>
+ * <li><code>TYPE_NAME</code> - String - the 'Types' name (possibly null)
+ * </li>
+ * <li><code>SELF_REFERENCING_COL_NAME</code> - String - the name of a
+ * designated identifier column in a typed table (possibly null) </li>
+ * <li>REF_GENERATION - String - one of the following values : "SYSTEM" |
+ * "USER" | "DERIVED" - specifies how values in the
+ * <code>SELF_REFERENCING_COL_NAME</code> are created (possibly null)
+ * </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. 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 schemaPattern
+ * a Schema Name Pattern. 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 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. null implies
+ * list all types.
+ * @return a ResultSet with one row per table in the format defined above.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public ResultSet getTables(String catalog, String schemaPattern,
+ String tableNamePattern, String[] types) throws SQLException;
+
+ /**
+ * Returns a list of table types supported by the database.
+ * <p>
+ * The list is returned as a ResultSet with one row per table type, ordered
+ * by the table type. The information in the ResultSet is structured into a
+ * single column per row, as follows:
+ * <ol>
+ * <li><code>TABLE_TYPE</code> - String - the Table Type. Typical names
+ * include "TABLE", "VIEW", "SYSTEM TABLE", "ALIAS", "SYNONYM", "GLOBAL
+ * TEMPORARY" </li>
+ * </ol>
+ *
+ * @return a ResultSet with one row per table type in the format defined
+ * above.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public ResultSet getTableTypes() throws SQLException;
+
+ /**
+ * Returns a list of time and date functions available for the database.
+ *
+ * @return a String contain a comma separated list of the time and date
+ * functions.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public String getTimeDateFunctions() throws SQLException;
+
+ /**
+ * Get a list of the standard SQL Types supported by this database. The list
+ * is returned as a ResultSet, with one row for each type, ordered by the
+ * <code>DATA_TYPE</code> value, where the data in each row is structured
+ * into the following columns:
+ * <ol>
+ * <li><code>TYPE_NAMR</code> - String : the Type name</li>
+ * <li><code>DATA_TYPE</code> - int : the SQL data type value as defined
+ * in <code>java.sql.Types</code></li>
+ * <li><code>PRECISION</code> - int - the maximum precision of the type</li>
+ * <li><code>LITERAL_PREFIX</code> - String : the prefix to be used when
+ * quoting a literal value (possibly <code>null</code>)</li>
+ * <li><code>LITERAL_SUFFIX</code> - String : the suffix to be used when
+ * quoting a literal value (possibly <code>null</code>)</li>
+ * <li><code>CREATE_PARAMS</code> - String : params used when creating
+ * the type (possibly <code>null</code>)</li>
+ * <li><code>NULLABLE</code> - short : shows if the value is null-able:
+ * <ul>
+ * <li>DatabaseMetaData.typeNoNulls : <code>NULL</code>s not permitted</li>
+ * <li>DatabaseMetaData.typeNullable : <code>NULL</code>s are permitted
+ * </li>
+ * <li>DatabaseMetaData.typeNullableUnknown : <code>NULL</code> status
+ * unknown </li>
+ * </ul>
+ * </li>
+ * <li>CASE_SENSITIVE - boolean : true if the type is case sensitive</li>
+ * <li>SEARCHABLE - short : how this type can be used with WHERE clauses:
+ * <ul>
+ * <li>DatabaseMetaData.typePredNone - cannot be used </li>
+ * <li>DatabaseMetaData.typePredChar - support for WHERE...LIKE only</li>
+ * <li>DatabaseMetaData.typePredBasic - support except for WHERE...LIKE</li>
+ * <li>DatabaseMetaData.typeSearchable - support for all WHERE clauses</li>
+ * </ul>
+ * </li>
+ * <li>UNSIGNED_ATTRIBUTE - boolean - the type is unsigned or not </li>
+ * <li>FIXED_PREC_SCALE - boolean - fixed precision = it can be used as a
+ * money value </li>
+ * <li>AUTO_INCREMENT - boolean - can be used as an auto-increment value
+ * </li>
+ * <li>LOCAL_<code>TYPE_NAME</code> - String - a localized version of
+ * the type name (possibly null)</li>
+ * <li>MINIMUM_SCALE - short - the minimum scale supported </li>
+ * <li>MAXIMUM_SCALE - short - the maximum scale supported </li>
+ * <li>SQL_<code>DATA_TYPE</code> - int - not used </li>
+ * <li>SQL_DATETIME_SUB - int - not used </li>
+ * <li>NUM_PREC_RADIX - int - number radix (typically 2 or 10) </li>
+ * </ol>
+ *
+ * @return a ResultSet which is structured as described above
+ * @throws SQLException
+ * a database error occurred
+ */
+ public ResultSet getTypeInfo() throws SQLException;
+
+ /**
+ * Returns a description of the User Defined Types (UDTs) defined in a given
+ * schema, which includes the types DISTINCT, STRUCT and JAVA_OBJECT.
+ * <p>
+ * The types matching the supplied the specified Catalog, Schema, Type Name
+ * and Type are returned as rows in a ResultSet with columns of information
+ * as follows:
+ * <ol>
+ * <li><code>TABLE_CAT</code> - String - Catalog name (possibly null)</li>
+ * <li><code>TABLE_SCHEM</code> - String - Schema name (possibly null)
+ * </li>
+ * <li><code>TABLE_NAME</code> - String - The Table name </li>
+ * <li><code>CLASS_NAME</code> - String - The Java class name</li>
+ * <li><code>DATA_TYPE</code> - int - The SQL type as specified in
+ * <code>java.sql.Types</code>. One of DISTINCT, STRUCT and JAVA_OBJECT</li>
+ * <li><code>REMARKS</code> - String - A comment which describes the type
+ * </li>
+ * <li><code>BASE_TYPE</code> - 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</code>. This is defined in
+ * <code>java.sql.Types</code>, and will be <code>null</code> if the
+ * <code>DATA_TYPE</code> does not match these criteria.</li>
+ * </ol>
+ * If the driver does not support UDTs, the ResultSet will be empty.
+ *
+ * @param catalog
+ * a Catalog Name. 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 schemaPattern
+ * a Schema Name Pattern. <code>null</code> 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, 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
+ * DISTINCT, STRUCT or JAVA_OBJECT.
+ * @return a ResultSet in the format described above
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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</code> if it cannot be
+ * generated.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public String getURL() throws SQLException;
+
+ /**
+ * Determine the user name as known by the database.
+ *
+ * @return the user name
+ * @throws SQLException
+ * a database error occurred
+ */
+ public String getUserName() throws SQLException;
+
+ /**
+ * Returns which of a table's columns are automatically updated when any
+ * value in a row is updated.
+ * <p>
+ * The result is laid-out in the following columns:
+ * <ol>
+ * <li><code>SCOPE</code> - short - not used </li>
+ * <li><code>COLUMN_NAME</code> - String - Column name</li>
+ * <li><code>DATA_TYPE</code> - int - The SQL data type, as defined in
+ * <code>java.sql.Types</code> </li>
+ * <li><code>TYPE_NAME</code> - String - The SQL type name, data source
+ * dependent </li>
+ * <li><code>COLUMN_SIZE</code> - int - Precision for numeric types </li>
+ * <li><code>BUFFER_LENGTH</code> - int - Length of a column value in
+ * bytes </li>
+ * <li><code>DECIMAL_DIGITS</code> - short - Number of digits after the
+ * decimal point </li>
+ * <li><code>PSEUDO_COLUMN</code> - short - If this is a pseudo-column
+ * (for example, an Oracle ROWID):
+ * <ul>
+ * <li>DatabaseMetaData.bestRowUnknown - don't know whether this is a
+ * pseudo column</li>
+ * <li>DatabaseMetaData.bestRowNotPseudo - column is not pseudo</li>
+ * <li>DatabaseMetaData.bestRowPseudo - column is a pseudo column</li>
+ * </ul>
+ * </li>
+ * </ol>
+ *
+ * @param catalog
+ * a Catalog Name. <code>null</code> 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</code> 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 table
+ * a table name. It must match the name of a table in the
+ * database.
+ * @return a ResultSet containing the descriptions, one row for each column,
+ * in the format defined above.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public ResultSet getVersionColumns(String catalog, String schema,
+ String table) throws SQLException;
+
+ /**
+ * Determine if a visible row insert can be detected by calling
+ * ResultSet.rowInserted.
+ *
+ * @param type
+ * the ResultSet type. This may be one of
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> or
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code> or
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+ * @return <code>true</code> if ResultSet.rowInserted detects a visible
+ * row insert otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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</code> if the catalog appears at the start of a
+ * fully qualified table name, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean isCatalogAtStart() throws SQLException;
+
+ /**
+ * Determine if the database is in read-only mode.
+ *
+ * @return <code>true</code> if the database is in read-only mode,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean isReadOnly() throws SQLException;
+
+ /**
+ * Determine if updates are made to a copy of, or directly on, Large Objects
+ * (LOBs).
+ *
+ * @return <code>true</code> if updates are made to a copy of the Large
+ * Object, <code>false</code> otherwise
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean locatorsUpdateCopy() throws SQLException;
+
+ /**
+ * Determine if the database handles concatenations between
+ * <code>NULL</code> and non-<code>NULL</code> values by producing a
+ * <code>NULL</code> output.
+ *
+ * @return <code>true</code> if <code>NULL</code> to non-<code>NULL</code>
+ * concatenations produce a <code>NULL</code> result,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean nullPlusNonNullIsNull() throws SQLException;
+
+ /**
+ * Determine if <code>NULL</code> 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</code>
+ * values may be present.
+ *
+ * @return <code>true</code> if <code>NULL</code> values are sorted at
+ * the end, <code>false</code> otherwise
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean nullsAreSortedAtEnd() throws SQLException;
+
+ /**
+ * Determine if <code>NULL</code> 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</code> if <code>NULL</code> values are sorted at
+ * the start, <code>false</code> otherwise
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean nullsAreSortedAtStart() throws SQLException;
+
+ /**
+ * Determine if <code>NULL</code> values are sorted high - i.e. they are
+ * sorted as if they are higher than any other values.
+ *
+ * @return <code>true</code> if <code>NULL</code> values are sorted
+ * high, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean nullsAreSortedHigh() throws SQLException;
+
+ /**
+ * Determine if <code>NULL</code> values are sorted low - ie they are
+ * sorted as if they are lower than any other values.
+ *
+ * @return <code>true</code> if <code>NULL</code> values are sorted low,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean nullsAreSortedLow() throws SQLException;
+
+ /**
+ * Determine if deletes made by others are visible, for a specified
+ * ResultSet type.
+ *
+ * @param type
+ * the type of the ResultSet. It may be either
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code> or
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>)
+ * @return <code>true</code> if others' deletes are visible,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean othersDeletesAreVisible(int type) throws SQLException;
+
+ /**
+ * Determine if inserts made by others are visible, for a specified
+ * ResultSet type.
+ *
+ * @param type
+ * the type of the ResultSet. May be
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>, or
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @return <code>true</code> if others' inserts are visible otherwise
+ * <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean othersInsertsAreVisible(int type) throws SQLException;
+
+ /**
+ * Determine if updates made by others are visible, for a specified
+ * ResultSet type.
+ *
+ * @param type
+ * the type of the ResultSet. May be
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>, or
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @return <code>true</code> if others' inserts are visible otherwise
+ * <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean othersUpdatesAreVisible(int type) throws SQLException;
+
+ /**
+ * Determine if a ResultSet's own deletes are visible, for a specified
+ * ResultSet type.
+ *
+ * @param type
+ * the type of the ResultSet:
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @return <code>true</code> if the delete's are seen by the own ResultSet
+ * otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean ownDeletesAreVisible(int type) throws SQLException;
+
+ /**
+ * Determine if its own inserts are visible to a given ResultSet type.
+ *
+ * @param type
+ * the type of the ResultSet:
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @return <code>true</code> if inserts are visible for this type
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean ownInsertsAreVisible(int type) throws SQLException;
+
+ /**
+ * Determine if for a supplied type of ResultSet, the ResultSet's own
+ * updates are visible.
+ *
+ * @param type
+ * the type of the ResultSet:
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @return <code>true</code> if updates are visible to in this ResultSet
+ * type otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean ownUpdatesAreVisible(int type) throws SQLException;
+
+ /**
+ * Determine whether the database treats SQL identifiers that are in mixed
+ * case (and unquoted) as case insensitive. If true then the database stores
+ * them in lower case.
+ *
+ * @return <code>true</code> if unquoted SQL identifiers are stored in
+ * lower case, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean storesLowerCaseIdentifiers() throws SQLException;
+
+ /**
+ * Determine whether the database considers mixed case quoted SQL
+ * identifiers as case insensitive and stores them in lower case.
+ *
+ * @return <code>true</code> if quoted SQL identifiers are stored in lower
+ * case, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean storesLowerCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * Determine whether the database considers mixed case unquoted SQL
+ * identifiers as case insensitive and stores them in mixed case.
+ *
+ * @return <code>true</code> if unquoted SQL identifiers as stored in
+ * mixed case, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean storesMixedCaseIdentifiers() throws SQLException;
+
+ /**
+ * Determine 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</code> if quoted SQL identifiers are stored in mixed
+ * case, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean storesMixedCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * Determine whether the database considers mixed case unquoted SQL
+ * identifiers as case insensitive and stores them in upper case.
+ *
+ * @return <code>true</code> if unquoted SQL identifiers are stored in
+ * upper case, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean storesUpperCaseIdentifiers() throws SQLException;
+
+ /**
+ * Determine whether the database considers mixed case quoted SQL
+ * identifiers as case insensitive and stores them in upper case.
+ *
+ * @return <code>true</code> if quoted SQL identifiers are stored in upper
+ * case, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean storesUpperCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * Determine if the database supports ALTER TABLE operation with add column.
+ *
+ * @return <code>true</code> if ALTER TABLE with add column is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsAlterTableWithAddColumn() throws SQLException;
+
+ /**
+ * Determine if the database supports ALTER TABLE operation with drop
+ * column.
+ *
+ * @return <code>true</code> if ALTER TABLE with drop column is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsAlterTableWithDropColumn() throws SQLException;
+
+ /**
+ * Determine if the database supports the ANSI92 entry level SQL grammar.
+ *
+ * @return <code>true</code> if the ANSI92 entry level SQL grammar is
+ * supported, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsANSI92EntryLevelSQL() throws SQLException;
+
+ /**
+ * Determine if the database supports the ANSI92 full SQL grammar.
+ *
+ * @return <code>true</code> if the ANSI92 full SQL grammar is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsANSI92FullSQL() throws SQLException;
+
+ /**
+ * Determine if the database supports the ANSI92 intermediate SQL Grammar.
+ *
+ * @return <code>true</code> if the ANSI92 intermediate SQL grammar is
+ * supported, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsANSI92IntermediateSQL() throws SQLException;
+
+ /**
+ * Determine if the database supports Batch Updates.
+ *
+ * @return <code>true</code> if batch updates are supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsBatchUpdates() throws SQLException;
+
+ /**
+ * Determine whether catalog names may be used in data manipulation
+ * statements.
+ *
+ * @return <code>true</code> if catalog names can be used in data
+ * manipulation statements, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsCatalogsInDataManipulation() throws SQLException;
+
+ /**
+ * Determine if catalog names can be used in Index Definition statements.
+ *
+ * @return <code>true</code> if catalog names can be used in Index
+ * Definition statements, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsCatalogsInIndexDefinitions() throws SQLException;
+
+ /**
+ * Determine if catalog names can be used in privilege definition
+ * statements.
+ *
+ * @return <code>true</code> if catalog names can be used in privilege
+ * definition statements, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException;
+
+ /**
+ * Determine if catalog names can be used in procedure call statements.
+ *
+ * @return <code>true</code> if catalog names can be used in procedure
+ * call statements.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsCatalogsInProcedureCalls() throws SQLException;
+
+ /**
+ * Determine if catalog names may be used in table definition statements.
+ *
+ * @return <code>true</code> if catalog names can be used in definition
+ * statements, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsCatalogsInTableDefinitions() throws SQLException;
+
+ /**
+ * Determine if the database supports column aliasing.
+ * <p>
+ * 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</code> if column aliasing is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsColumnAliasing() throws SQLException;
+
+ /**
+ * Determine if the database supports the CONVERT operation between SQL
+ * types.
+ *
+ * @return <code>true</code> if the CONVERT operation is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsConvert() throws SQLException;
+
+ /**
+ * Determine if the database supports CONVERT operation for two supplied SQL
+ * types.
+ *
+ * @param fromType
+ * the Type to convert from, as defined by
+ * <code>java.sql.Types</code>
+ * @param toType
+ * the Type to convert to, as defined by
+ * <code>java.sql.Types</code>
+ * @return <code>true</code> if the CONVERT operation is supported for
+ * these types, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsConvert(int fromType, int toType)
+ throws SQLException;
+
+ /**
+ * Determine if the database supports the Core SQL Grammar for ODBC.
+ *
+ * @return <code>true</code> if the Core SQL Grammar is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsCoreSQLGrammar() throws SQLException;
+
+ /**
+ * Determine if the database supports correlated sub-queries.
+ *
+ * @return <code>true</code> if the database does support correlated
+ * sub-queries and <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsCorrelatedSubqueries() throws SQLException;
+
+ /**
+ * Determine if the database allows both data definition and data
+ * manipulation statements inside a transaction.
+ *
+ * @return <code>true</code> if both types of statement are permitted,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsDataDefinitionAndDataManipulationTransactions()
+ throws SQLException;
+
+ /**
+ * Determine if the database only allows data manipulation statements inside
+ * a transaction.
+ *
+ * @return <code>true</code> if only data manipulation statements are
+ * permitted, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsDataManipulationTransactionsOnly()
+ throws SQLException;
+
+ /**
+ * Determine if table correlation names are restricted to be different from
+ * the names of the tables, when they are supported.
+ *
+ * @return <code>true</code> if correlation names must be different to
+ * table names, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsDifferentTableCorrelationNames() throws SQLException;
+
+ /**
+ * Determine whether expressions in ORDER BY lists are supported.
+ *
+ * @return <code>true</code> if expressions in ORDER BY lists are
+ * supported.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsExpressionsInOrderBy() throws SQLException;
+
+ /**
+ * Determine whether the Extended SQL Grammar for ODBC is supported.
+ *
+ * @return <code>true</code> if the Extended SQL Grammar is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsExtendedSQLGrammar() throws SQLException;
+
+ /**
+ * Determine if the database supports full nested outer joins.
+ *
+ * @return <code>true</code> if full nested outer joins are supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsFullOuterJoins() throws SQLException;
+
+ /**
+ * Determine if auto generated keys can be returned when a statement
+ * executes.
+ *
+ * @return <code>true</code> if auto generated keys can be returned,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsGetGeneratedKeys() throws SQLException;
+
+ /**
+ * Determine if the database supports a form of GROUP BY clause.
+ *
+ * @return <code>true</code> if a form of GROUP BY clause is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsGroupBy() throws SQLException;
+
+ /**
+ * Determine if the database supports using a column name in a GROUP BY
+ * clause not included in the SELECT statement as long as all of the columns
+ * in the SELECT statement are used in the GROUP BY clause.
+ *
+ * @return <code>true</code> if GROUP BY clauses can use column names in
+ * this way, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsGroupByBeyondSelect() throws SQLException;
+
+ /**
+ * Determine if the database supports using a column name in a GROUP BY
+ * clause that is not in the SELECT statement.
+ *
+ * @return <code>true</code> if GROUP BY clause can use a column name not
+ * in the SELECT statement, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsGroupByUnrelated() throws SQLException;
+
+ /**
+ * Determine whether the database supports SQL Integrity Enhancement
+ * Facility.
+ *
+ * @return <code>true</code> if the Integrity Enhancement Facility is
+ * supported, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsIntegrityEnhancementFacility() throws SQLException;
+
+ /**
+ * Determine if the database supports using a LIKE escape clause.
+ *
+ * @return <code>true</code> if LIKE escape clause is supported,
+ * <code>false</code> otherwise
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsLikeEscapeClause() throws SQLException;
+
+ /**
+ * Determine if the database provides limited support for outer Join
+ * operations.
+ *
+ * @return <code>true</code> if there is limited support for outer Join
+ * operations, <code>false</code> otherwise. This will be
+ * <code>true</code> if <code>supportsFullOuterJoins</code>
+ * returns <code>true</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsLimitedOuterJoins() throws SQLException;
+
+ /**
+ * Determine if the database supports Minimum SQL Grammar for ODBC.
+ *
+ * @return <code>true</code> if the Minimum SQL Grammar is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsMinimumSQLGrammar() throws SQLException;
+
+ /**
+ * Determine if the database treats mixed case unquoted SQL identifiers as
+ * case sensitive storing them in mixed case.
+ *
+ * @return <code>true</code> if unquoted SQL identifiers are stored in
+ * mixed case, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsMixedCaseIdentifiers() throws SQLException;
+
+ /**
+ * Determine whether the database considers mixed case quoted SQL
+ * identifiers as case sensitive, storing them in mixed case.
+ *
+ * @return <code>true</code> if quoted SQL identifiers are stored in mixed
+ * case, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException;
+
+ /**
+ * Determine if it is possible for a single CallableStatement to return
+ * multiple ResultSets simultaneously.
+ *
+ * @return <code>true</code> if a single CallableStatement can return
+ * multiple ResultSets simultaneously, <code>false</code>
+ * otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsMultipleOpenResults() throws SQLException;
+
+ /**
+ * Determine whether retrieving multiple ResultSets from a single call to
+ * the <code>execute</code> method is supported.
+ *
+ * @return <code>true</code> if multiple ResultSets can be retrieved,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsMultipleResultSets() throws SQLException;
+
+ /**
+ * Determine whether multiple transactions in progress at at time on
+ * different connections are supported.
+ *
+ * @return <code>true</code> if multiple open transactions are supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsMultipleTransactions() throws SQLException;
+
+ /**
+ * Determine whether call-able statements with named parameters is
+ * supported.
+ *
+ * @return <code>true</code> if named parameters can be used with
+ * call-able statements, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsNamedParameters() throws SQLException;
+
+ /**
+ * Determine if columns in the database can be defined as non-nullable.
+ *
+ * @return <code>true</code> if Columns can be defined non-nullable,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsNonNullableColumns() throws SQLException;
+
+ /**
+ * Determine whether keeping Cursors open across Commit operations is
+ * supported.
+ *
+ * @return <code>true</code> if Cursors can be kept open across Commit
+ * operations, <code>false</code> if they might get closed.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsOpenCursorsAcrossCommit() throws SQLException;
+
+ /**
+ * Determine if the database can keep Cursors open across Rollback
+ * operations.
+ *
+ * @return <code>true</code> if Cursors can be kept open across Rollback
+ * operations, <code>false</code> if they might get closed.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsOpenCursorsAcrossRollback() throws SQLException;
+
+ /**
+ * Determine whether keeping Statements open across Commit operations is
+ * supported.
+ *
+ * @return <code>true</code> if Statements can be kept open,
+ * <code>false</code> if they might not.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsOpenStatementsAcrossCommit() throws SQLException;
+
+ /**
+ * Determine whether keeping Statements open across Rollback operations is
+ * supported.
+ *
+ * @return <code>true</code> if Statements can be kept open,
+ * <code>false</code> if they might not.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsOpenStatementsAcrossRollback() throws SQLException;
+
+ /**
+ * Determine whether using a column in an ORDER BY clause that is not in the
+ * SELECT statement is supported.
+ *
+ * @return <code>true</code> if it is possible to ORDER using a column not
+ * in the SELECT, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsOrderByUnrelated() throws SQLException;
+
+ /**
+ * Determine whether outer join operations are supported.
+ *
+ * @return <code>true</code> if outer join operations are supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsOuterJoins() throws SQLException;
+
+ /**
+ * Determine whether positioned DELETE statements are supported.
+ *
+ * @return <code>true</code> if the database supports positioned DELETE
+ * statements.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsPositionedDelete() throws SQLException;
+
+ /**
+ * Determine whether positioned UPDATE statements are supported.
+ *
+ * @return <code>true</code> if the database supports positioned UPDATE
+ * statements, <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsPositionedUpdate() throws SQLException;
+
+ /**
+ * Determine whether there is support for a given concurrency style for the
+ * given ResultSet.
+ *
+ * @param type
+ * the ResultSet type, as defined in
+ * <code>java.sql.ResultSet</code>:
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @param concurrency
+ * a concurrency type, which may be one of
+ * <code>ResultSet.CONCUR_READ_ONLY</code> or
+ * <code>ResultSet.CONCUR_UPDATABLE</code>.
+ * @return <code>true</code> if that concurrency and ResultSet type
+ * pairing is supported otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsResultSetConcurrency(int type, int concurrency)
+ throws SQLException;
+
+ /**
+ * Determine whether the supplied ResultSet holdability is supported.
+ *
+ * @param holdability
+ * as specified in java.sql.ResultSet:
+ * ResultSet.HOLD_CURSORS_OVER_COMMIT or
+ * ResultSet.CLOSE_CURSORS_AT_COMMIT
+ * @return <code>true</code> if the given ResultSet holdability is
+ * supported and if it isn't then <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsResultSetHoldability(int holdability)
+ throws SQLException;
+
+ /**
+ * Determine whether the supplied ResultSet type is supported.
+ *
+ * @param type
+ * the ResultSet type as defined in java.sql.ResultSet:
+ * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @return <code>true</code> if the ResultSet type is supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsResultSetType(int type) throws SQLException;
+
+ /**
+ * Determine whether Savepoints for transactions are supported.
+ *
+ * @return <code>true</code> if Savepoints are supported,
+ * <code>false</code> otherwise.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSavepoints() throws SQLException;
+
+ /**
+ * Determine whether a schema name may be used in a data manipulation
+ * statement.
+ *
+ * @return <code>true</code> if a schema name can be used in a data
+ * manipulation otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSchemasInDataManipulation() throws SQLException;
+
+ /**
+ * Determine whether a schema name may be used in an index definition
+ * statement.
+ *
+ * @return <code>true</code> if a schema name can be used in an index
+ * definition otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSchemasInIndexDefinitions() throws SQLException;
+
+ /**
+ * Determine whether a database schema name can be used in a privilege
+ * definition statement.
+ *
+ * @return <code>true</code> if a database schema name may be used in a
+ * privilege definition otherwise <code>false</code>
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException;
+
+ /**
+ * Determine if a procedure call statement may be contain in a schema name.
+ *
+ * @return <code>true</code> if a schema name can be used in a procedure
+ * call otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSchemasInProcedureCalls() throws SQLException;
+
+ /**
+ * Determine if a schema name can be used in a table definition statement.
+ *
+ * @return <code>true</code> if a schema name can be used in a table
+ * definition otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSchemasInTableDefinitions() throws SQLException;
+
+ /**
+ * Determine if this <code>SELECT FOR UPDATE</code> statements ar
+ * supported.
+ *
+ * @return <code>true</code> if <code>SELECT FOR UPDATE</code>
+ * statements are supported otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSelectForUpdate() throws SQLException;
+
+ /**
+ * Determine whether statement pooling is supported.
+ *
+ * @return <code>true</code> of the database does support statement
+ * pooling otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsStatementPooling() throws SQLException;
+
+ /**
+ * Determine whether stored procedure calls using the stored procedure
+ * escape syntax is supported.
+ *
+ * @return <code>true</code> if stored procedure calls using the stored
+ * procedure escape syntax are supported otherwise
+ * <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsStoredProcedures() throws SQLException;
+
+ /**
+ * Determine whether subqueries in comparison expressions are supported.
+ *
+ * @return <code>true</code> if subqueries are supported in comparison
+ * expressions.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSubqueriesInComparisons() throws SQLException;
+
+ /**
+ * Determine whether subqueries in EXISTS expressions are supported.
+ *
+ * @return <code>true</code> if subqueries are supported in EXISTS
+ * expressions otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSubqueriesInExists() throws SQLException;
+
+ /**
+ * Determine whether subqueries in <code>IN</code> statements are
+ * supported.
+ *
+ * @return <code>true</code> if subqueries are supported in IN statements
+ * otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSubqueriesInIns() throws SQLException;
+
+ /**
+ * Determine whether subqueries in quantified expressions are supported.
+ *
+ * @return <code>true</code> if subqueries are supported otherwise
+ * <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsSubqueriesInQuantifieds() throws SQLException;
+
+ /**
+ * Determine whether the database has table correlation names support.
+ *
+ * @return <code>true</code> if table correlation names are supported
+ * otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsTableCorrelationNames() throws SQLException;
+
+ /**
+ * Determine whether a specified transaction isolation level is supported.
+ *
+ * @param level
+ * the transaction isolation level, as specified in
+ * <code>java.sql.Connection</code>:
+ * <code>TRANSACTION_NONE</code>,
+ * <code>TRANSACTION_READ_COMMITTED</code>,
+ * <code>TRANSACTION_READ_UNCOMMITTED</code>,
+ * <code>TRANSACTION_REPEATABLE_READ</code>,
+ * <code>TRANSACTION_SERIALIZABLE</code>
+ * @return <code>true</code> if the specific isolation level is supported
+ * otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsTransactionIsolationLevel(int level)
+ throws SQLException;
+
+ /**
+ * Determine whether transactions are supported.
+ * <p>
+ * If transactions are not supported, then the <code>commit</code> method
+ * does nothing and the transaction isolation level is always
+ * <code>TRANSACTION_NONE</code>.
+ *
+ * @return <code>true</code> if transactions are supported otherwise
+ * <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsTransactions() throws SQLException;
+
+ /**
+ * Determine whether the <code>SQL UNION</code> operation is supported.
+ *
+ * @return <code>true</code> of the database does support
+ * <code>UNION</code> otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsUnion() throws SQLException;
+
+ /**
+ * Determine whether the <code>SQL UNION ALL</code> operation is
+ * supported.
+ *
+ * @return <code>true</code> if the database does support UNION ALL
+ * otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean supportsUnionAll() throws SQLException;
+
+ /**
+ * Determine if the method <code>ResultSet.rowUpdated</code> can detect a
+ * visible row update.
+ *
+ * @param type
+ * ResultSet type: <code>ResultSet.TYPE_FORWARD_ONLY</code>,
+ * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
+ * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
+ * @return <code>true</code> detecting changes is possible otherwise
+ * <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean updatesAreDetected(int type) throws SQLException;
+
+ /**
+ * Determine if this database uses a file for each table.
+ *
+ * @return <code>true</code> if the database uses one file for each table
+ * otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ public boolean usesLocalFilePerTable() throws SQLException;
+
+ /**
+ * Determine whether this database uses a local file to store tables.
+ *
+ * @return <code>true</code> of the database does store tables in a local
+ * file otherwise <code>false</code>.
+ * @throws SQLException
+ * a database error occurred
+ */
+ 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..ce31b01
--- /dev/null
+++ b/sql/src/main/java/java/sql/Date.java
@@ -0,0 +1,233 @@
+/*
+ * 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 Date class which can consume and produce dates in SQL Date format.
+ * <p>
+ * The SQL date format represents a date as yyyy-mm-dd. Note that this date
+ * format only deals with year, month and day values. There are no values for
+ * hours, minutes, seconds.
+ * <p>
+ * This contrasts with regular java.util.Date values, which include time values
+ * for hours, minutes, seconds, milliseconds.
+ * <p>
+ * Time points are handled as millisecond values - milliseconds since the epoch,
+ * January 1st 1970, 00:00:00.000 GMT. Time values passed to the java.sql.Date
+ * class are "normalized" to the time 00:00:00.000 GMT on the date implied by
+ * the time value.
+ */
+public class Date extends java.util.Date {
+
+ private static final long serialVersionUID = 1511598038487230103L;
+
+ /**
+ * @deprecated Please use the constructor {@link #Date(long)} Constructs a Date
+ * object corresponding to the supplied Year, Month and Day.
+ * @param theYear
+ * the year, specified as the year minus 1900. Must be in the
+ * range 0 to 8099.
+ * @param theMonth
+ * the month, specified as a number with 0 = January. Must be in
+ * the range 0 to 11.
+ * @param theDay
+ * the day in the month. Must be in the range 1 to 31.
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ public Date(int theYear, int theMonth, int theDay) {
+ super(theYear, theMonth, theDay);
+ }
+
+ /**
+ * Creates a Date which corresponds to the day implied by the supplied
+ * theDate milliseconds time value.
+ *
+ * @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 Date object is adjusted to
+ * correspond to 00:00:00 GMT on the day implied by the supplied
+ * time value.
+ */
+ public Date(long theDate) {
+ super(normalizeTime(theDate));
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL Date
+ * values do not have an hours component.
+ * @return does not return
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getHours() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL Date
+ * values do not have a minutes component.
+ * @return does not return
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getMinutes() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL Date
+ * values do not have a seconds component.
+ * @return does not return
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getSeconds() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL Date
+ * values do not have an hours component.
+ * @param theHours
+ * the number of hours to set
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setHours(int theHours) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL Date
+ * values do not have a minutes component.
+ * @param theMinutes
+ * the number of minutes to set
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setMinutes(int theMinutes) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. SQL Date
+ * values do not have a seconds component.
+ * @param theSeconds
+ * the number of seconds to set
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @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 after removing any time elements
+ * finer than a day, based on zero GMT for that day.
+ *
+ * @param theTime
+ * the time in milliseconds since the Epoch
+ */
+ @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 - "yyyy-mm-dd".
+ */
+ @Override
+ public String toString() {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); //$NON-NLS-1$
+ return dateFormat.format(this);
+ }
+
+ /**
+ * Creates a Date from a string representation of a date in SQL format.
+ *
+ * @param dateString
+ * the string representation of a date in SQL format -
+ * "yyyy-mm-dd".
+ * @return the Date object
+ * @throws IllegalArgumentException
+ * if the format of the supplied string does not match the SQL
+ * format.
+ */
+ 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..7833724
--- /dev/null
+++ b/sql/src/main/java/java/sql/Driver.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 java.sql;
+
+import java.util.Properties;
+
+/**
+ * An Interface to a JDBC Driver.
+ * <p>
+ * The JDBC Driver uses URLs to specify the location of specific data. URL
+ * format typically takes the form "xxxx:yyyy:SpecificData", where "xxxx:yyyy"
+ * is termed the subprotocol and is normally the same for all uses of a
+ * particular driver. "SpecificData" is a string which identifies the particular
+ * data source that the driver should use.
+ *
+ */
+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 true if the driver thinks that is can open a connection to the
+ * supplied URL, false otherwise. Typically, the driver will respond
+ * true if it thinks that it can handle the subprotocol specified by
+ * the driver.
+ * @throws SQLException
+ */
+ public boolean acceptsURL(String url) throws SQLException;
+
+ /**
+ * Attempts to make a database connection to a datasource 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 "user" and "password" in order to
+ * pass authentication to the database.
+ * @return a Connection object representing the connection to the database.
+ * @throws SQLException
+ * if a database error occurs
+ */
+ 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.
+ */
+ public int getMajorVersion();
+
+ /**
+ * Gets the driver's minor version number.
+ *
+ * @return the minor version number of the Driver - typically starts at 0.
+ */
+ public int getMinorVersion();
+
+ /**
+ * Gets information about possible properties for this driver.
+ * <p>
+ * This method is intended to provide a listing of possible properties that
+ * the user of the driver may need to supply in order to correct connect 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. A using program 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
+ * @return an array of DriverPropertyInfo records which provide detail on
+ * each property that the driver will accept.
+ * @throws SQLException
+ */
+ public DriverPropertyInfo[] getPropertyInfo(String url, Properties info)
+ throws SQLException;
+
+ /**
+ * Reports whether this driver is a genuine JDBC CompliantTM driver. The
+ * driver may only return true from this method if it passes all the JDBC
+ * Compliance tests.
+ * <p>
+ * A driver may not be fully compliant if the underlying database has
+ * limited functionality.
+ *
+ * @return true if the driver is fully JDBC compliant, false otherwise.
+ */
+ 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..78f362c
--- /dev/null
+++ b/sql/src/main/java/java/sql/DriverManager.java
@@ -0,0 +1,433 @@
+/*
+ * 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;
+import org.apache.harmony.kernel.vm.VM;
+
+/**
+ * Provides facilities for managing JDBC Drivers.
+ * <p>
+ * The DriverManager class will load JDBC drivers during its initialization,
+ * from the list of drivers referenced by the System Property "jdbc.drivers".
+ */
+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<Driver> theDriverSet = new HashSet<Driver>(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 DriverManager's registered driver list. This
+ * will only succeed where the caller's classloader loaded the driver that
+ * is to be removed. If the driver was loaded by a different classloader,
+ * the removal of the driver will fail silently.
+ * <p>
+ * If the removal succeeds, the DriverManager will not in future use this
+ * driver when asked to get a Connection.
+ *
+ * @param driver
+ * @throws SQLException
+ * if there is an exception accessing the database.
+ */
+ public static void deregisterDriver(Driver driver) throws SQLException {
+ if (driver == null) {
+ return;
+ }
+// ClassLoader callerClassLoader = VM.callerClassLoader(); //???SQL VM.callerClassLoader not implemented -> null
+//
+// 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 Connection to the database identified by the URL. null if no
+ * connection can be made.
+ * @throws SQLException
+ * if there is an error while attempting to connect to the
+ * database identified by the URL
+ */
+ 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 "user" and "password" should
+ * be passed, with appropriate settings for the userid and its
+ * corresponding password to get access to the database
+ * concerned.
+ * @return a Connection to the database identified by the URL. null if no
+ * connection can be made.
+ * @throws SQLException
+ * if there is an error while attempting to connect to the
+ * database identified by the URL
+ */
+ 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 userid used to login to the database
+ * @param password
+ * a password for the userid to login to the database
+ * @return a Connection to the database identified by the URL. null if no
+ * connection can be made.
+ * @throws SQLException
+ * if there is an error while attempting to connect to the
+ * database identified by the URL
+ */
+ 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 Driver that can understand the given URL. null if no Driver
+ * understands the URL
+ * @throws SQLException
+ * if there is any kind of Database Access problem
+ */
+ public static Driver getDriver(String url) throws SQLException {
+// ClassLoader callerClassLoader = VM.callerClassLoader(); //???SQL VM.callerClassLoader not implemented -> null
+
+ 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<Driver> theIterator = theDriverSet.iterator();
+ while (theIterator.hasNext()) {
+ Driver theDriver = theIterator.next();
+ if (theDriver.acceptsURL(url)
+// && DriverManager.isClassFromClassLoader(theDriver,
+// callerClassLoader)) { //???SQL VM.callerClassLoader not implemented -> null
+ ){
+ 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 Enumeration that contains all of the loaded JDBC drivers that
+ * the current caller can access.
+ *
+ * @return An Enumeration containing all the currently loaded JDBC Drivers
+ */
+ public static Enumeration<Driver> getDrivers() {
+// ClassLoader callerClassLoader = VM.callerClassLoader(); //???SQL VM.callerClassLoader not implemented -> null
+ /*
+ * 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<Driver> theVector = new Vector<Driver>();
+ Iterator<Driver> theIterator = theDriverSet.iterator();
+ while (theIterator.hasNext()) {
+ Driver theDriver = theIterator.next();
+// if (DriverManager.isClassFromClassLoader(theDriver, //???SQL VM.callerClassLoader not implemented -> null
+// callerClassLoader)) {
+ theVector.add(theDriver);
+// }
+ }
+ return theVector.elements();
+ }
+ }
+
+ /**
+ * Returns the login timeout when connecting to a database, in seconds.
+ *
+ * @return the login timeout in seconds
+ */
+ public static int getLoginTimeout() {
+ return loginTimeout;
+ }
+
+ /**
+ * @deprecated Gets the log PrintStream used by the DriverManager and all
+ * the JDBC Drivers.
+ * @return the PrintStream used for logging activity
+ */
+ @Deprecated
+ public static PrintStream getLogStream() {
+ return thePrintStream;
+ }
+
+ /**
+ * Retrieves the log writer.
+ *
+ * @return A PrintWriter object used as the log writer. null if no log
+ * writer is set.
+ */
+ public static PrintWriter getLogWriter() {
+ return thePrintWriter;
+ }
+
+ /**
+ * Prints a message to the current JDBC log stream. This is either the
+ * PrintWriter or (deprecated) the PrintStream, if set.
+ *
+ * @param message
+ * the message to print to the JDBC log stream
+ */
+ 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 DriverManager.
+ * <p>
+ * A newly loaded JDBC driver class should register itself with the
+ * DriverManager by calling this method.
+ *
+ * @param driver
+ * the Driver to register with the 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);
+ }
+ }
+
+ /**
+ * Set the login timeout when connecting to a database, in seconds.
+ *
+ * @param seconds
+ * seconds until timeout. 0 indicates wait forever.
+ */
+ public static void setLoginTimeout(int seconds) {
+ loginTimeout = seconds;
+ return;
+ }
+
+ /**
+ * @deprecated Sets the Print Stream to use for logging data from the
+ * DriverManager and the JDBC drivers.
+ * <p>
+ * Use {@link #setLogWriter} instead.
+ * @param out
+ * the PrintStream to use for logging.
+ */
+ @Deprecated
+ public static void setLogStream(PrintStream out) {
+ checkLogSecurity();
+ thePrintStream = out;
+ }
+
+ /**
+ * Sets the PrintWriter that will be used by all loaded drivers, and also
+ * the DriverManager.
+ *
+ * @param out
+ * the PrintWriter to be used
+ */
+ 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);
+ }
+ }
+
+ /**
+ * Finds if a supplied Object belongs to the given ClassLoader.
+ *
+ * @param theObject
+ * the object to check
+ * @param theClassLoader
+ * the ClassLoader
+ * @return true if the Object does belong to the ClassLoader, 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..bf261db
--- /dev/null
+++ b/sql/src/main/java/java/sql/DriverPropertyInfo.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 java.sql;
+
+/**
+ * A class holding information about Driver Properties for making a Connection.
+ * This class is returned from the <code>Driver.getDriverProperties</code>
+ * method and is useful in using Connections in an advanced way.
+ */
+public class DriverPropertyInfo {
+
+ /**
+ * If the value member can be chosen from a set of possible values, they are
+ * contained here. Otherwise choices is null.
+ */
+ public String[] choices;
+
+ /**
+ * A description of the property. May be null.
+ */
+ public String description;
+
+ /**
+ * The name of the property.
+ */
+ public String name;
+
+ /**
+ * True when the value member must be provided during Driver.connect. False
+ * otherwise.
+ */
+ public boolean required;
+
+ /**
+ * The current value associated with this property. This is based on the
+ * data gathered by the getPropertyInfo method, the general Java environment
+ * and the default values for the driver.
+ */
+ public String value;
+
+ /**
+ * Creates a DriverPropertyInfo instance with the supplied name and value.
+ * Other members take their default values.
+ *
+ * @param name
+ * The property name
+ * @param value
+ * The property value
+ */
+ 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..7d644d3
--- /dev/null
+++ b/sql/src/main/java/java/sql/ParameterMetaData.java
@@ -0,0 +1,183 @@
+/*
+ * 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 PreparedStatement object.
+ */
+public interface ParameterMetaData {
+
+ /**
+ * Indicates that the parameter mode is IN.
+ */
+ public static final int parameterModeIn = 1;
+
+ /**
+ * Indicates that the parameter mode is INOUT.
+ */
+ public static final int parameterModeInOut = 2;
+
+ /**
+ * Indicates that the parameter mode is OUT.
+ */
+ public static final int parameterModeOut = 4;
+
+ /**
+ * Indicates that the parameter mode is not known.
+ */
+ public static final int parameterModeUnknown = 0;
+
+ /**
+ * Indicates that a parameter is not permitted to be NULL.
+ */
+ public static final int parameterNoNulls = 0;
+
+ /**
+ * Indicates that a parameter is permitted to be NULL.
+ */
+ public static final int parameterNullable = 1;
+
+ /**
+ * Indicates that whether a parameter is allowed to be null or not is not
+ * known.
+ */
+ 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</code>.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has an index of 1
+ * @return a String with the fully qualified Java class name of the
+ * parameter with the specified index. This class name is used for
+ * custom mapping.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public String getParameterClassName(int paramIndex) throws SQLException;
+
+ /**
+ * Gets the number of parameters in the PreparedStatement for which this
+ * ParameterMetaData contains information.
+ *
+ * @return the number of parameters as an int
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getParameterCount() throws SQLException;
+
+ /**
+ * Gets the mode of the specified parameter.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has an index of 1
+ * @return the parameters mode. Can be: ParameterMetaData.parameterModeIn,
+ * ParameterMetaData.parameterModeOut,
+ * ParameterMetaData.parameterModeInOut or
+ * ParameterMetaData.parameterModeUnknown.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 an index of 1
+ * @return the type of the parameter - an SQL type as defined in
+ * java.sql.Types.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 an index of 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.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 an index of 1
+ * @return the number of decimal digits ("the precision") for the parameter.
+ * 0 if the parameter is not a numeric type.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 an index of 1
+ * @return the number of digits after the decimal point ("the scale") for
+ * the parameter. 0 if the parameter is not a numeric type.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getScale(int paramIndex) throws SQLException;
+
+ /**
+ * Gets whether null values are allowed for the specified parameter.
+ *
+ * @param paramIndex
+ * the index number of the parameter, where the first parameter
+ * has an index of 1
+ * @return indicator of nullability, can be:
+ * ParameterMetaData.parameterNoNulls,
+ * ParameterMetaData.parameterNullable, or
+ * ParameterMetaData.parameterNullableUnknown
+ * @throws SQLException
+ * if a database error is encountered
+ */
+ 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 an index of 1
+ * @return true if values can be signed numbers for this parameter, false
+ * otherwise.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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..5941200
--- /dev/null
+++ b/sql/src/main/java/java/sql/PreparedStatement.java
@@ -0,0 +1,631 @@
+/*
+ * 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.
+ * <p>
+ * An SQL Statement is put into a PreparedStatement and is precompiled so that
+ * it can be executed multiple times efficiently.
+ * <p>
+ * Setter methods are supplied in the PreparedStatement interface for the
+ * setting of IN parameters for the Statement. The setter method used for each
+ * IN parameter must match the type of the IN parameter being set.
+ */
+public interface PreparedStatement extends Statement {
+
+ /**
+ * Add a set of parameters to the PreparedStatement's command batch.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void addBatch() throws SQLException;
+
+ /**
+ * Clear the current parameter values.
+ * <p>
+ * Typically, parameter values are retained for multiple executions of the
+ * 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
+ */
+ public void clearParameters() throws SQLException;
+
+ /**
+ * Executes the SQL statement in this PreparedStatement.
+ * <p>
+ * A PreparedStatement may return multiple results. The execute method
+ * returns a flag indicating the kind of result produced by
+ * PreparedStatement. The methods <code>
+ * getResultSet</code> or
+ * <code>getUpdateCount</code> are used to retrieve the first result,
+ * while <code>getMoreResults</code> must be used to retrieve the second
+ * and subsequent results.
+ *
+ * @return true if the result of the execution is a ResultSet, false if
+ * there is no result or if the result is an update count.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean execute() throws SQLException;
+
+ /**
+ * Execute the SQL query in the PreparedStatement and return the ResultSet
+ * generated by the query.
+ *
+ * @return the ResultSet generated by the query - never null.
+ * @throws SQLException
+ * if a database error happens or if the SQL statement does not
+ * produce a ResultSet.
+ */
+ public ResultSet executeQuery() throws SQLException;
+
+ /**
+ * Invoke the SQL command contained within the Prepared Statement. This must
+ * be INSERT, UPDATE, DELETE, or a command that returns nothing.
+ *
+ * @return the count of rows for INSERT, UPDATE or DELETE statements, 0 for
+ * statements that return nothing
+ * @throws SQLException
+ * if a database error happens or if the SQL statement returns a
+ * ResultSet.
+ */
+ public int executeUpdate() throws SQLException;
+
+ /**
+ * Returns a ResultSetMetaData containing data from the ResultSet that is
+ * produced when the PreparedStatement is invoked.
+ * <p>
+ * It is possible to know the Metadata for the ResultSet without executing
+ * the PreparedStatement, because the PreparedStatement is precompiled. As a
+ * result the Metadata can be queried ahead of time without actually
+ * executing the statement.
+ *
+ * @return a ResultSetMetaData object with the information about the columns
+ * of the ResultSet, if the driver can return a ResultSetMetaData.
+ * null otherwise.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public ResultSetMetaData getMetaData() throws SQLException;
+
+ /**
+ * Gets information about the parameters of the PreparedStatement.
+ *
+ * @return a ParameterMetaData object which holds information about the
+ * number, type and properties of the parameters of this
+ * PreparedStatement.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public ParameterMetaData getParameterMetaData() throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the supplied Array object.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theArray
+ * a java.sql.Array holing the data to set.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setArray(int parameterIndex, Array theArray)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the content of a supplied
+ * InputStream, which has a specified number of bytes.
+ * <p>
+ * This is a good method for setting an SQL LONVARCHAR parameter where the
+ * length of the data is large. Data is read from the 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 InputStream carrying the data to update the
+ * parameter
+ * @param length
+ * the number of bytes in the InputStream to copy to the
+ * parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setAsciiStream(int parameterIndex, InputStream theInputStream,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied
+ * java.math.BigDecimal value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theBigDecimal
+ * the java.math.BigInteger value to set
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the content of a supplied
+ * binary InputStream, which has a specified number of bytes.
+ * <p>
+ * Use this method when a large amount of data needs to be set into a
+ * LONGVARBINARY parameter.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theInputStream
+ * the binary InputStream carrying the data to update the
+ * parameter
+ * @param length
+ * the number of bytes in the InputStream to copy to the
+ * parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setBinaryStream(int parameterIndex, InputStream theInputStream,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the given Blob object.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theBlob
+ * a java.sql.Blob holding the data to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setBlob(int parameterIndex, Blob theBlob) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied boolean value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theBoolean
+ * the boolean value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setBoolean(int parameterIndex, boolean theBoolean)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied byte value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theByte
+ * the byte value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 VARBINARY or LONGVARBINARY in the database.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theBytes
+ * the array of bytes to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setBytes(int parameterIndex, byte[] theBytes)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the character content of a
+ * Reader object, with the specified length of character data.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param reader
+ * the java.io.Reader encompassing the character data
+ * @param length
+ * the amount of characters to be read
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setCharacterStream(int parameterIndex, Reader reader, int length)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to the given Clob object.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theClob
+ * a java.sql.Clob holding the data to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setClob(int parameterIndex, Clob theClob) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied java.sql.Date
+ * value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theDate
+ * a java.sql.Date to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setDate(int parameterIndex, Date theDate) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied 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 DATE in the
+ * database - without the supplied 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 java.sql.Date to update the parameter
+ * @param cal
+ * a Calendar to use to construct the SQL DATE value
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setDate(int parameterIndex, Date theDate, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied double value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theDouble
+ * the double value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setDouble(int parameterIndex, double theDouble)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to to a supplied float value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theFloat
+ * the float value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setFloat(int parameterIndex, float theFloat)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied int value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theInt
+ * the int value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setInt(int parameterIndex, int theInt) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied long value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theLong
+ * the long value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setLong(int parameterIndex, long theLong) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to SQL NULL. Don't use this
+ * version of setNull for User Defined Types 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 java.sql.Types
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setNull(int parameterIndex, int sqlType) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to SQL NULL. This version of
+ * setNull should be used for User Defined Types (UDTs) and also REF types.
+ * UDTs can be STRUCT, DISTINCT, JAVA_OBJECT and named array types.
+ * <p>
+ * Applications must provide the SQL Type code and also a fully qualified
+ * SQL Type name when supplying a 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 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
+ */
+ public void setNull(int paramIndex, int sqlType, String typeName)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ * <p>
+ * 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. 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 SQLData, the JDBC driver calls <code>SQLData.writeSQL</code>
+ * to write it to the SQL data stream. If the object's class implements Ref,
+ * Blob, Clob, Struct, or 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 update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setObject(int parameterIndex, Object theObject)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ * <p>
+ * The Object is converted to the given targetSqlType before it is sent to
+ * the database. If the object has a custom mapping (its class implements
+ * the interface SQLData), the JDBC driver will call the method
+ * SQLData.writeSQL to write it to the SQL data stream. If the object's
+ * class implements Ref, Blob, Clob, Struct, or 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 update the parameter
+ * @param targetSqlType
+ * the SQL Type to send to the database, as defined in
+ * java.sql.Types
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setObject(int parameterIndex, Object theObject,
+ int targetSqlType) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter using a supplied object.
+ * <p>
+ * The Object is converted to the given targetSqlType before it is sent to
+ * the database. If the object has a custom mapping (its class implements
+ * the interface SQLData), the JDBC driver will call the method
+ * SQLData.writeSQL to write it to the SQL data stream. If the object's
+ * class implements Ref, Blob, Clob, Struct, or 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 update the parameter
+ * @param targetSqlType
+ * the SQL Type to send to the database, as defined in
+ * java.sql.Types
+ * @param scale
+ * the number of digits after the decimal point - only applies to
+ * the types java.sql.Types.DECIMAL and java.sql.Types.NUMERIC -
+ * ignored for all other types.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setObject(int parameterIndex, Object theObject,
+ int targetSqlType, int scale) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied REF(<structured-type>)
+ * value. This is stored as an SQL REF.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theRef
+ * a java.sql.Ref value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setRef(int parameterIndex, Ref theRef) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied short value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theShort
+ * a short value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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
+ * a String value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setString(int parameterIndex, String theString)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied java.sql.Time
+ * value.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theTime
+ * a java.sql.Time value to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setTime(int parameterIndex, Time theTime) throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied java.sql.Time
+ * value, using a supplied Calendar.
+ * <p>
+ * The driver uses the supplied Calendar to create the SQL 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 java.sql.Time value to update the parameter
+ * @param cal
+ * a Calendar to use to construct the SQL TIME value
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp)
+ throws SQLException;
+
+ /**
+ * Sets the value of a specified parameter to a supplied java.sql.Timestamp
+ * value, using the supplied Calendar.
+ * <p>
+ * The driver uses the supplied Calendar to create the SQL 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 java.sql.Timestamp value to update the parameter
+ * @param cal
+ * a Calendar to use to construct the SQL TIMESTAMP value
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp,
+ Calendar cal) throws SQLException;
+
+ /**
+ * @deprecated Sets the value of a specified parameter to the characters
+ * from a supplied InputStream, with a specified number of
+ * bytes.
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theInputStream
+ * the InputStream with the character data to update the
+ * parameter
+ * @param length
+ * the number of bytes to read from the 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 java.net.URL.
+ *
+ * @param parameterIndex
+ * the parameter number index, where the first parameter has
+ * index 1
+ * @param theURL
+ * the URL to update the parameter
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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..cc0adf4
--- /dev/null
+++ b/sql/src/main/java/java/sql/Ref.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 java.sql;
+
+import java.util.Map;
+
+/**
+ * A manifestation of the SQL REF type - a reference to an SQL type contained in
+ * the database.
+ * <p>
+ * The SQL REF's are held in a table along with SQL structured types. Every REF
+ * has an individual identifier for each single instance. The SQL REF is used
+ * instead of the structured type it references.
+ * <p>
+ * A Ref object is stored into the database using the PreparedStatement.setRef
+ * method.
+ */
+public interface Ref {
+
+ /**
+ * Gets the fully-qualified SQL name of the SQL structured type that this
+ * Ref references.
+ *
+ * @return the fully qualified name of the SQL structured type
+ * @throws SQLException
+ * if there is a database error
+ */
+ public String getBaseTypeName() throws SQLException;
+
+ /**
+ * Gets the SQL structured type instance referenced by this 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
+ */
+ public Object getObject() throws SQLException;
+
+ /**
+ * Returns the associated object and uses the relevant mapping to convert it
+ * to a Java type.
+ *
+ * @param map
+ * a java.util.Map which contains the mapping to use
+ * @return a Java object whose type is defined by the mapping for the SQL
+ * structured type.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Object getObject(Map<String, Class<?>> map) throws SQLException;
+
+ /**
+ * Sets the value of the structured typethat this Ref references to a
+ * supplied Object.
+ *
+ * @param value
+ * the Object representing the new SQL structured type that this
+ * Ref will reference.
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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..dd2334e
--- /dev/null
+++ b/sql/src/main/java/java/sql/ResultSet.java
@@ -0,0 +1,1870 @@
+/*
+ * 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 to an Object which represents a Table of Data, typically
+ * returned as the result of a Query to a Database.
+ * <p>
+ * <code>ResultSets</code> have a Cursor which points to a current row of
+ * data. When a ResultSet is created, the Cursor is positioned before the first
+ * row. To move the Cursor to the next row in the table, use the
+ * <code>next</code> method. The next method returns true until there are no
+ * more rows in the ResultSet, when it returns false.
+ * <p>
+ * The default type of ResultSet cannot be updated and its cursor can only move
+ * forward through the rows of data. This means that it is only possible to read
+ * through it once. However, it is possible to create types of ResultSet that
+ * can be updated and also types where the cursor can be scrolled forward and
+ * backward through the rows of data. This is shown in the following code
+ * example: <code>
+ * Connection con;
+ * Statement aStatement = con.createStatement( ResultSet.TYPE_SCROLL_SENSITIVE,
+ * ResultSet.CONCUR_UPDATABLE );
+ * ResultSet theResultSet = theStatement.executeQuery("SELECT price, quantity FROM STOCKTABLE");
+ * // theResultSet will be both scrollable and updateable
+ * </code>
+ * <p>
+ * The ResultSet interface provides a series of methods for retrieving data from
+ * columns in the current row, such as getDate, getFloat. The columns are
+ * identified 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.
+ * <p>
+ * When reading data, 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 of allowable mappings from SQL types to
+ * Java types.
+ * <p>
+ * There are also methods for writing data into the ResultSet, such as
+ * updateInt, updateString. The update methods can be used either to modify the
+ * data of an existing row or to insert new data rows into the 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 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
+ * ResultSet.insertRow method.
+ * <p>
+ * A ResultSet is closed if the Statement object which generated it closed,
+ * executed again or is used to retrieve the next result from a sequence of
+ * results.
+ *
+ */
+public interface ResultSet {
+
+ /**
+ * A constant used to indicate that a ResultSet object must be closed when
+ * the method Connection.commit is invoked.
+ */
+ public static final int CLOSE_CURSORS_AT_COMMIT = 2;
+
+ /**
+ * A constant used to indicate that a ResultSet object must not be closed
+ * when the method Connection.commit is invoked.
+ */
+ public static final int HOLD_CURSORS_OVER_COMMIT = 1;
+
+ /**
+ * A constant used to indicate the Concurrency Mode for a ResultSet object
+ * that cannot be updated.
+ */
+ public static final int CONCUR_READ_ONLY = 1007;
+
+ /**
+ * A constant used to indicate the Concurrency Mode for a ResultSet object
+ * that can be updated.
+ */
+ public static final int CONCUR_UPDATABLE = 1008;
+
+ /**
+ * A constant used to indicate processing of the rows of a ResultSet in the
+ * forward direction, first to last
+ */
+ public static final int FETCH_FORWARD = 1000;
+
+ /**
+ * A constant used to indicate processing of the rows of a ResultSet in the
+ * reverse direction, last to first
+ */
+ public static final int FETCH_REVERSE = 1001;
+
+ /**
+ * A constant used to indicate that the order of processing of the rows of a
+ * ResultSet is unknown.
+ */
+ public static final int FETCH_UNKNOWN = 1002;
+
+ /**
+ * A constant used to indicate a ResultSet object whose Cursor can only move
+ * forward
+ */
+ public static final int TYPE_FORWARD_ONLY = 1003;
+
+ /**
+ * A constant used to indicate a ResultSet object which is Scrollable but
+ * which is not sensitive to changes made by others
+ */
+ public static final int TYPE_SCROLL_INSENSITIVE = 1004;
+
+ /**
+ * A constant used to indicate a ResultSet object which is Scrollable but
+ * which is sensitive to changes made by others
+ */
+ public static final int TYPE_SCROLL_SENSITIVE = 1005;
+
+ /**
+ * Moves the Cursor to a specified row number in the ResultSet.
+ *
+ * @param row
+ * The new row number for the Cursor
+ * @return true if the new Cursor position is on the ResultSet, false
+ * otherwise
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean absolute(int row) throws SQLException;
+
+ /**
+ * Moves the Cursor to the end of the ResultSet, after the last row.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void afterLast() throws SQLException;
+
+ /**
+ * Moves the Cursor to the start of the ResultSet, before the first row.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void beforeFirst() throws SQLException;
+
+ /**
+ * Cancels any updates made to the current row in the ResultSet.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void cancelRowUpdates() throws SQLException;
+
+ /**
+ * Clears all the warnings related to this ResultSet.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void clearWarnings() throws SQLException;
+
+ /**
+ * Releases this ResultSet's database and JDBC resources. You are strongly
+ * advised to use this method rather than relying on the release being done
+ * when the ResultSet's finalize method is called during garbage collection
+ * process. Note that the close() method might take some time to complete
+ * since it is dependent on the behaviour of the connection to the database
+ * and the database itself.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void close() throws SQLException;
+
+ /**
+ * Deletes the current row from the ResultSet and from the underlying
+ * database.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void deleteRow() throws SQLException;
+
+ /**
+ * Gets the index number for a column in the ResultSet from the provided
+ * Column Name.
+ *
+ * @param columnName
+ * the column name
+ * @return the index of the column in the ResultSet for the column name
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int findColumn(String columnName) throws SQLException;
+
+ /**
+ * Shifts the cursor position to the first row in the ResultSet.
+ *
+ * @return true if the position is in a legitimate row, false if the
+ * ResultSet contains no rows.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean first() throws SQLException;
+
+ /**
+ * Gets the content of a column specified as a column index in the current
+ * row of this ResultSet as a java.sql.Array.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a java.sql.Array with the data from the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Array getArray(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a
+ * java.sql.Array.
+ *
+ * @param colName
+ * the name of the column to read
+ * @return a java.sql.Array with the data from the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Array getArray(String colName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as an ASCII
+ * character stream.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return an InputStream with the data from the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public InputStream getAsciiStream(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as an ASCII
+ * character stream.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return an InputStream with the data from the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public InputStream getAsciiStream(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a
+ * java.math.BigDecimal.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a BigDecimal with the value of the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public BigDecimal getBigDecimal(int columnIndex) throws SQLException;
+
+ /**
+ * @deprecated Gets the value of a column specified as a column index as a
+ * java.math.BigDecimal.
+ * @param columnIndex
+ * the index of the column to read
+ * @param scale
+ * the number of digits after the decimal point
+ * @return a BigDecimal with the value of the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ @Deprecated
+ public BigDecimal getBigDecimal(int columnIndex, int scale)
+ throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a
+ * java.math.BigDecimal.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a BigDecimal with the value of the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public BigDecimal getBigDecimal(String columnName) throws SQLException;
+
+ /**
+ * @deprecated Gets the value of a column specified as a column name, as a
+ * java.math.BigDecimal.
+ * @param columnName
+ * the name of the column to read
+ * @param scale
+ * the number of digits after the decimal point
+ * @return a BigDecimal with the value of the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ @Deprecated
+ public BigDecimal getBigDecimal(String columnName, int scale)
+ throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a binary
+ * stream.
+ * <p>
+ * This method can be used to read LONGVARBINARY values. All of the data in
+ * the InputStream should be read before getting data from any other column.
+ * A further call to a getter method will implicitly close the InputStream.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return an InputStream with the data from the column. If the column value
+ * is SQL NULL, null is returned.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public InputStream getBinaryStream(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a binary stream.
+ * <p>
+ * This method can be used to read LONGVARBINARY values. All of the data in
+ * the InputStream should be read before getting data from any other column.
+ * A further call to a getter method will implicitly close the InputStream.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return an InputStream with the data from the column If the column value
+ * is SQL NULL, null is returned.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public InputStream getBinaryStream(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a java.sql.Blob
+ * object.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a java.sql.Blob with the value of the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Blob getBlob(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a java.sql.Blob
+ * object.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a java.sql.Blob with the value of the column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Blob getBlob(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a boolean.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a boolean value from the column. If the column is SQL NULL, false
+ * is returned.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean getBoolean(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a boolean.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a boolean value from the column. If the column is SQL NULL, false
+ * is returned.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean getBoolean(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a byte.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a byte containing the value of the column. 0 if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public byte getByte(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a byte.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a byte containing the value of the column. 0 if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public byte getByte(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a 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. null if the
+ * column contains SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public byte[] getBytes(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a 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. null if the
+ * column contains SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public byte[] getBytes(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a
+ * java.io.Reader object.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a Reader holding the value of the column. null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Reader getCharacterStream(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a java.io.Reader
+ * object.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a Reader holding the value of the column. null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Reader getCharacterStream(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a
+ * java.sql.Clob.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a Clob object representing the value in the column. null if the
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Clob getClob(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a java.sql.Clob.
+ *
+ * @param colName
+ * the name of the column to read
+ * @return a Clob object representing the value in the column. null if the
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Clob getClob(String colName) throws SQLException;
+
+ /**
+ * Gets the concurrency mode of this ResultSet.
+ *
+ * @return the concurrency mode - one of: ResultSet.CONCUR_READ_ONLY,
+ * ResultSet.CONCUR_UPDATABLE
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getConcurrency() throws SQLException;
+
+ /**
+ * Gets the name of the SQL cursor of this ResultSet.
+ *
+ * @return a String containing the SQL cursor name
+ * @throws SQLException
+ * if a database error happens
+ */
+ public String getCursorName() throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a
+ * java.sql.Date.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a java.sql.Date matching the column value. null if the column is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Date getDate(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a
+ * 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 java.util.Calendar to use in constructing the Date.
+ * @return a java.sql.Date matching the column value. null if the column is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Date getDate(int columnIndex, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a java.sql.Date.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a java.sql.Date matching the column value. null if the column is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Date getDate(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a java.sql.Date
+ * object.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @param cal
+ * java.util.Calendar to use in constructing the Date.
+ * @return a java.sql.Date matching the column value. null if the column is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Date getDate(String columnName, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a double value.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a double containing the column value. 0.0 if the column is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public double getDouble(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a double value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a double containing the column value. 0.0 if the column is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public double getDouble(String columnName) throws SQLException;
+
+ /**
+ * Gets the direction in which rows are fetched for this ResultSet object.
+ *
+ * @return the fetch direction. Will be: ResultSet.FETCH_FORWARD,
+ * ResultSet.FETCH_REVERSE or ResultSet.FETCH_UNKNOWN
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getFetchDirection() throws SQLException;
+
+ /**
+ * Gets the fetch size (in number of rows) for this ResultSet
+ *
+ * @return the fetch size as an int
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getFetchSize() throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a float value.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a float containing the column value. 0.0 if the column is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public float getFloat(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a float value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a float containing the column value. 0.0 if the column is SQL
+ * NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public float getFloat(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as an int value.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return an int containing the column value. 0 if the column is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getInt(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as an int value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return an int containing the column value. 0 if the column is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getInt(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a long value.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a long containing the column value. 0 if the column is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public long getLong(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a long value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a long containing the column value. 0 if the column is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public long getLong(String columnName) throws SQLException;
+
+ /**
+ * Gets the Metadata for this ResultSet. This defines the number, types and
+ * properties of the columns in the ResultSet.
+ *
+ * @return a ResultSetMetaData object with information about this ResultSet.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public ResultSetMetaData getMetaData() throws SQLException;
+
+ /**
+ * Gets the value of a specified column as a Java 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.
+ * <p>
+ * For SQL User Defined Types, if a column value is Structured or Distinct,
+ * this method behaves the same as a call to: getObject(columnIndex,
+ * this.getStatement().getConnection().getTypeMap())
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return an Object containing the value of the column. null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Object getObject(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a Java Object.
+ * <p>
+ * 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 columnIndex
+ * the index of the column to read
+ * @param map
+ * a java.util.Map containing a mapping from SQL Type names to
+ * Java classes.
+ * @return an Object containing the value of the column. null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Object getObject(int columnIndex, Map<String, Class<?>> map)
+ throws SQLException;
+
+ /**
+ * Gets the value of a specified column as a Java 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.
+ * <p>
+ * For SQL User Defined Types, if a column value is Structured or Distinct,
+ * this method behaves the same as a call to: getObject(columnIndex,
+ * this.getStatement().getConnection().getTypeMap())
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return an Object containing the value of the column. null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Object getObject(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a Java Object.
+ * <p>
+ * 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 java.util.Map containing a mapping from SQL Type names to
+ * Java classes.
+ * @return an Object containing the value of the column. null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Object getObject(String columnName, Map<String, Class<?>> map)
+ throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a Java
+ * 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
+ */
+ public Ref getRef(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a Java
+ * java.sql.Ref.
+ *
+ * @param colName
+ * the name 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
+ */
+ public Ref getRef(String colName) throws SQLException;
+
+ /**
+ * Gets the number of the current row in the ResultSet. Row numbers start at
+ * 1 for the first row.
+ *
+ * @return the index number of the current row. 0 is returned if there is no
+ * current row.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public int getRow() throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a short value.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a short value containing the value of the column. 0 if the value
+ * is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public short getShort(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a short value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a short value containing the value of the column. 0 if the value
+ * is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public short getShort(String columnName) throws SQLException;
+
+ /**
+ * Gets the Statement that produced this ResultSet. If the ResultSet was not
+ * created by a Statement (eg it was returned from one of the
+ * DatabaseMetaData methods), null is returned.
+ *
+ * @return the Statement which produced this ResultSet, or null if the
+ * ResultSet was not created by a Statement.
+ * @throws SQLException
+ */
+ public Statement getStatement() throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a String.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return the String representing the value of the column, null if the
+ * column is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public String getString(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a String.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return the String representing the value of the column, null if the
+ * column is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public String getString(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a java.sql.Time
+ * value.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a Time representing the column value, null if the column value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Time getTime(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a java.sql.Time
+ * value. The supplied Calendar is used to map between the SQL Time value
+ * and the Java Time value.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @param cal
+ * a Calendar to use in creating the Java Time value.
+ * @return a Time representing the column value, null if the column value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Time getTime(int columnIndex, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a java.sql.Time
+ * value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a Time representing the column value, null if the column value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Time getTime(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index, as a
+ * java.sql.Time value. The supplied Calendar is used to map between the SQL
+ * Time value and the Java Time value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @param cal
+ * a Calendar to use in creating the Java Time value.
+ * @return a Time representing the column value, null if the column value is
+ * SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Time getTime(String columnName, Calendar cal) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a
+ * java.sql.Timestamp value.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a Timestamp representing the column value, null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Timestamp getTimestamp(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index, as a
+ * java.sql.Timestamp value. The supplied Calendar is used to map between
+ * the SQL Timestamp value and the Java 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, null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Timestamp getTimestamp(int columnIndex, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a
+ * java.sql.Timestamp value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a Timestamp representing the column value, null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Timestamp getTimestamp(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name, as a
+ * java.sql.Timestamp value. The supplied Calendar is used to map between
+ * the SQL Timestamp value and the Java Timestamp value.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @param cal
+ * Calendar to use in creating the Java Timestamp value.
+ * @return a Timestamp representing the column value, null if the column
+ * value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public Timestamp getTimestamp(String columnName, Calendar cal)
+ throws SQLException;
+
+ /**
+ * Gets the type of the ResultSet.
+ *
+ * @return The ResultSet type, one of: ResultSet.TYPE_FORWARD_ONLY,
+ * ResultSet.TYPE_SCROLL_INSENSITIVE, or
+ * ResultSet.TYPE_SCROLL_SENSITIVE
+ * @throws SQLException
+ * if there is a database error
+ */
+ public int getType() throws SQLException;
+
+ /**
+ * @deprecated Use {@link #getCharacterStream}.
+ * <p>
+ * Gets the value of the column as an InputStream of Unicode
+ * characters.
+ * @param columnIndex
+ * the index of the column to read
+ * @return an InputStream holding the value of the column. null if the
+ * column value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ @Deprecated
+ public InputStream getUnicodeStream(int columnIndex) throws SQLException;
+
+ /**
+ * @deprecated Use {@link #getCharacterStream}
+ * <p>
+ * Gets the value of the column as an InputStream of Unicode
+ * characters.
+ * @param columnName
+ * the name of the column to read
+ * @return an InputStream holding the value of the column. null if the
+ * column value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ @Deprecated
+ public InputStream getUnicodeStream(String columnName) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column index as a java.net.URL.
+ *
+ * @param columnIndex
+ * the index of the column to read
+ * @return a URL. null if the column value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public URL getURL(int columnIndex) throws SQLException;
+
+ /**
+ * Gets the value of a column specified as a column name as a java.net.URL
+ * object.
+ *
+ * @param columnName
+ * the name of the column to read
+ * @return a URL. null if the column value is SQL NULL.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public URL getURL(String columnName) throws SQLException;
+
+ /**
+ * Gets the first warning generated by calls on this ResultSet. Subsequent
+ * warnings on this ResultSet are chained to the first one.
+ * <p>
+ * The warnings are cleared when a new Row is read from the ResultSet. The
+ * warnings returned by this method are only the warnings generated by
+ * ResultSet method calls - warnings generated by Statement methods are held
+ * by the Statement.
+ * <p>
+ * An SQLException is generated if this method is called on a closed
+ * ResultSet.
+ *
+ * @return an SQLWarning which is the first warning for this ResultSet. null
+ * if there are no warnings.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * Insert the insert row into the 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.
+ */
+ public void insertRow() throws SQLException;
+
+ /**
+ * Gets if the cursor is after the last row of the ResultSet.
+ *
+ * @return true if the Cursor is after the last Row in the ResultSet, false
+ * if the cursor is at any other position in the ResultSet.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean isAfterLast() throws SQLException;
+
+ /**
+ * Gets if the cursor is before the first row of the ResultSet.
+ *
+ * @return true if the Cursor is before the last Row in the ResultSet, false
+ * if the cursor is at any other position in the ResultSet.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean isBeforeFirst() throws SQLException;
+
+ /**
+ * Gets if the cursor is on the first row of the ResultSet.
+ *
+ * @return true if the Cursor is on the first Row in the ResultSet, false if
+ * the cursor is at any other position in the ResultSet.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean isFirst() throws SQLException;
+
+ /**
+ * Gets if the cursor is on the last row of the ResultSet
+ *
+ * @return true if the Cursor is on the last Row in the ResultSet, false if
+ * the cursor is at any other position in the ResultSet.
+ * @throws SQLException
+ */
+ public boolean isLast() throws SQLException;
+
+ /**
+ * Shifts the cursor position to the last row of the ResultSet.
+ *
+ * @return true if the new position is in a legitimate row, false if the
+ * ResultSet contains no rows.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean last() throws SQLException;
+
+ /**
+ * Moves the cursor to the remembered position, usually the current row.
+ * This only applies if the cursor is on the Insert row.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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</code> to insert the new row into the
+ * database.
+ *
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void moveToInsertRow() throws SQLException;
+
+ /**
+ * Shifts the cursor position down one row in this ResultSet object.
+ * <p>
+ * Any InputStreams associated with the current row are closed and any
+ * warnings are cleared.
+ *
+ * @return true if the updated cursor position is pointing to a valid row,
+ * false otherwise (ie when the cursor is after the last row in the
+ * ResultSet).
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean next() throws SQLException;
+
+ /**
+ * Relocates the cursor position to the preceding row in this ResultSet.
+ *
+ * @return true if the new position is in a legitimate row, false if the
+ * cursor is now before the first row.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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.
+ * <p>
+ * If any columns in the current row have been updated but the
+ * <code>updateRow</code> 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.
+ */
+ 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 or end rows, the cursor position is
+ * set before the first row/after the last row.
+ *
+ * @param rows
+ * a number of rows to move the cursor - may be positive or
+ * negative
+ * @return true if the new cursor position is on a row, false otherwise
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 true if a row has been deleted and if deletions are detected,
+ * false otherwise.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 true if a row has been inserted and if insertions are detected,
+ * false otherwise.
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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 true if the current row has been updated and if updates can be
+ * detected, false otherwise.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public boolean rowUpdated() throws SQLException;
+
+ /**
+ * Indicates which direction (forward/reverse) will be used to process the
+ * rows of this ResultSet object. This is treated as a hint by the JDBC
+ * driver.
+ *
+ * @param direction
+ * can be ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE, or
+ * ResultSet.FETCH_UNKNOWN
+ * @throws SQLException
+ * if there is a database error
+ */
+ public void setFetchDirection(int direction) throws SQLException;
+
+ /**
+ * Indicates the amount of rows to fetch from the database when extra rows
+ * are required for this ResultSet. This used as a hint to the JDBC driver.
+ *
+ * @param rows
+ * the number of rows to fetch. 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 ResultSet.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void setFetchSize(int rows) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateArray(int columnIndex, Array x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ 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
+ */
+ 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
+ */
+ public void updateAsciiStream(String columnName, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateBigDecimal(int columnIndex, BigDecimal x)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ 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
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void updateBinaryStream(String columnName, InputStream x, int length)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateBlob(int columnIndex, Blob x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateBlob(String columnName, Blob x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a boolean value.
+ *
+ * @param columnIndex
+ * @param x
+ * the new value for the specified column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void updateBoolean(int columnIndex, boolean x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateBoolean(String columnName, boolean x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateByte(int columnIndex, byte x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateByte(String columnName, byte x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ public void updateCharacterStream(String columnName, Reader reader,
+ int length) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateClob(int columnIndex, Clob x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateClob(String columnName, Clob x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateDate(int columnIndex, Date x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateDate(String columnName, Date x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateDouble(int columnIndex, double x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateDouble(String columnName, double x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateFloat(int columnIndex, float x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateFloat(String columnName, float x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with an 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
+ */
+ public void updateInt(int columnIndex, int x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with an 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
+ */
+ public void updateInt(String columnName, int x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateLong(int columnIndex, long x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateLong(String columnName, long x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a null value.
+ *
+ * @param columnIndex
+ * the index of the column to update
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void updateNull(int columnIndex) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a null value.
+ *
+ * @param columnName
+ * the name of the column to update
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void updateNull(String columnName) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with an 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
+ */
+ public void updateObject(int columnIndex, Object x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with an 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 java.sql.Types.DECIMAL or
+ * java.sql.Types.NUMERIC, this specifies the number of digits
+ * after the decimal point.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void updateObject(int columnIndex, Object x, int scale)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with an 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
+ */
+ public void updateObject(String columnName, Object x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with an 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 java.sql.Types.DECIMAL or
+ * java.sql.Types.NUMERIC, this specifies the number of digits
+ * after the decimal point.
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void updateObject(String columnName, Object x, int scale)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateRef(int columnIndex, Ref x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateRef(String columnName, Ref x) throws SQLException;
+
+ /**
+ * Updates the database with the new contents of the current row of this
+ * ResultSet object.
+ *
+ * @throws SQLException
+ */
+ public void updateRow() throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateShort(int columnIndex, short x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateShort(String columnName, short x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateString(int columnIndex, String x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a 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
+ */
+ public void updateString(String columnName, String x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a 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
+ */
+ public void updateTime(int columnIndex, Time x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column name with a Time value.
+ *
+ * @param columnName
+ * @param x
+ * the new value for the specified column
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void updateTime(String columnName, Time x) throws SQLException;
+
+ /**
+ * Updates a column specified by a column index with a Timestamp 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
+ */
+ public void updateTimestamp(int columnIndex, Timestamp x)
+ throws SQLException;
+
+ /**
+ * Updates a column specified by column name with a Timestamp value.
+ *
+ * @param columnName
+ * the name of the column to update
+ * @param x
+ * @throws SQLException
+ * if a database error happens
+ */
+ public void updateTimestamp(String columnName, Timestamp x)
+ throws SQLException;
+
+ /**
+ * Determines if the last column read from this ResultSet contained SQL
+ * NULL.
+ *
+ * @return true if the last column contained SQL NULL, false otherwise
+ * @throws SQLException
+ * if a database error happens
+ */
+ 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..d530d11
--- /dev/null
+++ b/sql/src/main/java/java/sql/ResultSetMetaData.java
@@ -0,0 +1,277 @@
+/*
+ * 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 in a ResultSet.
+ */
+public interface ResultSetMetaData {
+
+ /**
+ * Indicates that a column cannot contain NULL values
+ */
+ public static final int columnNoNulls = 0;
+
+ /**
+ * Indicates that a column can contain NULL values
+ */
+ public static final int columnNullable = 1;
+
+ /**
+ * Indicates that it is unknown whether a column can contain NULLs or not
+ */
+ public static final int columnNullableUnknown = 2;
+
+ /**
+ * Returns the title of indexed columns catalog
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return the catalog title
+ * @throws SQLException
+ * if there is a database error
+ */
+ public String getCatalogName(int column) throws SQLException;
+
+ /**
+ * Returns the fully-qualified type of the class that is produced when
+ * invoking ResultSet.getObject to recover this columns value.
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return the fully-qualified class name
+ * @throws SQLException
+ * if there is a database error
+ */
+ public String getColumnClassName(int column) throws SQLException;
+
+ /**
+ * Returns a count of the columns in this set of results.
+ *
+ * @return the column count
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ public String getColumnName(int column) throws SQLException;
+
+ /**
+ * Returns the type of the indexed column
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return the column type
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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
+ */
+ 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
+ */
+ public int getPrecision(int column) throws SQLException;
+
+ /**
+ * Returns the number of decimal places in the indexed column.
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return number of decimal places
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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
+ */
+ 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
+ */
+ public String getTableName(int column) throws SQLException;
+
+ /**
+ * Returns and indication of whether the indexed column has automatic
+ * numbering and is therefore read-only
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return true if it is automatically numbered, false otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean isAutoIncrement(int column) throws SQLException;
+
+ /**
+ * Returns an indicator of whether the case of the indexed column is
+ * important
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return true if case matters, false otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean isCaseSensitive(int column) throws SQLException;
+
+ /**
+ * Returns if the indexed column contains a monetary amount.
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return true if it is a monetary value, false otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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 true if the write is guaranteed, false otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean isDefinitelyWritable(int column) throws SQLException;
+
+ /**
+ * Returns whether the indexed column is nullable.
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return true if it is nullable, false otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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 true if the column is read-only, false otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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 true if the indexed column is searchable, false otherwise.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean isSearchable(int column) throws SQLException;
+
+ /**
+ * Returns an indicator of whether the values contained in the indexed
+ * column are signed.
+ *
+ * @param column
+ * the column index, starting at 1
+ * @return true if they are signed, false otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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 true if it is possible to write, false otherwise
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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..7b07835
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLData.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 java.sql;
+
+/**
+ * An interface for the custom mapping of an SQL User Defined Type (UDT) to a
+ * Java Class. The Java Class object will be added to the Connection's type map
+ * with the SQL Name of the UDT which it maps.
+ * <p>
+ * Usually within an implementation of SQLData, there is a corresponding field
+ * for every attribute of an SQL type, or only one field if the type is SQL
+ * DISTINCT. When the UDT is returned within a ResultSet, it is accessed with
+ * the ResultSet.getObject method and is returned as an Object which is an
+ * instance of the class defined by the SQLData mapping. The application can use
+ * this object just like any other Java object and can store changes back into
+ * the database using the PreparedStatement.setObject method which performs the
+ * reverse mapping into the SQL UDT.
+ * <p>
+ * It is standard for an implementation for a custom mapping to be generated by
+ * a tool. The tool usually requires the name of the SQL UDT, the name of the
+ * class which it is going to be mapped to, and the field names to which the UDT
+ * attributes will be mapped. The tool can then implement the SQLData readSQL
+ * and writeSQL methods. readSQL reads attributes from an SQLInput object, and
+ * writeSQL writes them. This is done via SQLInput and SQLOutput method calls
+ * respectively
+ * <p>
+ * Ordinarily a programmer would not call SQLData methods directly. Similarly
+ * SQLInput and SQLOutput methods are not usually called directly.
+ */
+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 SQLData object.
+ *
+ * @return a string with UDT type name for this object mapping, passed to
+ * readSQL when the object was created
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public String getSQLTypeName() throws SQLException;
+
+ /**
+ * Reads data from the database into this object. This method follows these
+ * steps:
+ * <ul>
+ * <li>Utilize the passed input stream to read the attributes or entries of
+ * the SQL type</li>
+ * <li>This is carried out by reading each entry from the input stream,
+ * ordered as the are the SQL definition.</li>
+ * <li>Assign the data to the appropriate fields or elements. This is done
+ * by calling the relevant reader method for the type involved (eg.
+ * SQLInput.readString, SQLInputreadBigDecimal). If the type is distinct,
+ * then read its only data entry. For structured types, read every entry.</li>
+ * </ul>
+ * The supplied input stream is typically initialized by the calling JDBC
+ * driver with the type map before readSQL is called.
+ *
+ * @param stream
+ * the 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
+ */
+ public void readSQL(SQLInput stream, String typeName) throws SQLException;
+
+ /**
+ * Writes the object to a supplied SQLOutput data stream, writing it out as
+ * an SQL value to the data source.
+ * <p>
+ * This method follows the following steps:
+ * <ul>
+ * <li>Write each attribute of the SQL type to the output stream.</li>
+ * <li>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
+ * SQLOutput methods (eg. writeInt, 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.</li>
+ * </ul>
+ *
+ * @param stream
+ * the SQLOutput stream to use to write out the data for the
+ * custom mapping
+ * @throws SQLException
+ * if a database error occurs
+ */
+ 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..07a4763
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLException.java
@@ -0,0 +1,153 @@
+/*
+ * 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 class that is used in conjunction with JDBC operations. It
+ * provides information about problems encountered with Database access and
+ * other problems related to JDBC
+ * <p>
+ * The SQLException class provides the following information:
+ * <ul>
+ * <li>A standard Java exception message, as a String
+ * <li>An SQLState string. This is an error description string which follows
+ * either the SQL 99 conventions or the XOPEN SQLstate conventions. The
+ * potential values of the SQLState string are described in each of the
+ * specifications. Which of the conventions is being used by the SQLState string
+ * can be discovered by using the getSQLStateType method of the DatabaseMetaData
+ * interface.
+ * <li>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.
+ * <li>A chain to a next Exception, if relevant, which can give access to
+ * additional error information.
+ * </ul>
+ */
+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 SQLException object. The Reason string is set to null, the
+ * SQLState string is set to null and the Error Code is set to 0.
+ */
+ public SQLException() {
+ super();
+ }
+
+ /**
+ * Creates an SQLException object. The Reason string is set to the given
+ * reason string, the SQLState string is set to 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 SQLException object. The Reason string is set to the given
+ * reason string, the SQLState string is set to the given 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 SQLState string
+ */
+ public SQLException(String theReason, String theSQLState) {
+ this(theReason, theSQLState, 0);
+ }
+
+ /**
+ * Creates an SQLException object. The Reason string is set to the given
+ * reason string, the SQLState string is set to the given 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 SQLState string
+ * @param theErrorCode
+ * the integer value for the error code
+ */
+ public SQLException(String theReason, String theSQLState, int theErrorCode) {
+ super(theReason);
+ SQLState = theSQLState;
+ vendorCode = theErrorCode;
+ }
+
+ /**
+ * Returns the integer error code for this SQLException
+ *
+ * @return The integer error code for this SQLException. The meaning of the
+ * code is specific to the vendor of the database.
+ */
+ public int getErrorCode() {
+ return vendorCode;
+ }
+
+ /**
+ * Retrieves the SQLException chained to this SQLException, if any.
+ *
+ * @return The SQLException chained to this SQLException. null if there is
+ * no SQLException chained to this SQLException.
+ */
+ public SQLException getNextException() {
+ return next;
+ }
+
+ /**
+ * Retrieves the SQLState description string for this SQLException object
+ *
+ * @return The SQLState string for this SQLException object. This is an
+ * error description string which follows either the SQL 99
+ * conventions or the XOPEN SQLstate conventions. The potential
+ * values of the SQLState string are described in each of the
+ * specifications. Which of the conventions is being used by the
+ * SQLState string can be discovered by using the getSQLStateType
+ * method of the DatabaseMetaData interface.
+ */
+ public String getSQLState() {
+ return SQLState;
+ }
+
+ /**
+ * Adds the SQLException to the end of this SQLException chain.
+ *
+ * @param ex
+ * the new SQLException to be added to the end of the chain
+ */
+ 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..d30da9f
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLInput.java
@@ -0,0 +1,280 @@
+/*
+ * 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 SQLInput interface defines operations which apply to a type of input
+ * stream which carries a series of values which represent an instance of an SQL
+ * structured type or SQL distinct type.
+ * <p>
+ * SQLInput interface is used for custom mapping of SQL User Defined Types
+ * (UDTs)to Java classes. It is used by JDBC drivers below the level of the
+ * public interfaces and application programs do not normally use the SQLInput
+ * methods directly. Reader methods such as readLong and readBytes provide means
+ * to read values from an SQLInput stream.
+ * <p>
+ * When the getObject method is called with an object which implements the
+ * SQLData interface, the JDBC driver determines the SQL type of the UDT being
+ * mapped by calling the SQLData.getSQLType method. The driver creates an
+ * instance of an SQLInput stream, filling the stream with the attributes of the
+ * UDT. The SQLInput stream is passed to the SQLData.readSQL method which then
+ * calls the SQLInput reader methods to read the attributes.
+ */
+public interface SQLInput {
+
+ /**
+ * Returns the next attribute in the stream in the form of a String.
+ *
+ * @return the next attribute as a String. null if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public String readString() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a boolean.
+ *
+ * @return the next attribute as a boolean. false if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean readBoolean() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a byte.
+ *
+ * @return the next attribute as a byte. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public byte readByte() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a short.
+ *
+ * @return the next attribute as a short. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public short readShort() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of an int.
+ *
+ * @return the next attribute as an int. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public int readInt() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a long.
+ *
+ * @return the next attribute as a long. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public long readLong() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a float.
+ *
+ * @return the next attribute as a float. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public float readFloat() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a double.
+ *
+ * @return the next attribute as a double. 0 if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public double readDouble() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a
+ * java.math.BigDecimal.
+ *
+ * @return the attribute as a java.math.BigDecimal. null if the read returns
+ * SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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. null if the read returns SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public byte[] readBytes() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a java.sql.Date.
+ *
+ * @return the next attribute as a java.sql.Date. null if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Date readDate() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a java.sql.Time.
+ *
+ * @return the attribute as a java.sql.Time. null if the read returns SQL
+ * NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Time readTime() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a
+ * java.sql.Timestamp.
+ *
+ * @return the attribute as a java.sql.Timestamp. null if the read returns
+ * SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Timestamp readTimestamp() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a Unicode
+ * character stream embodied as a java.io.Reader.
+ *
+ * @return the next attribute as a java.io.Reader. null if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Reader readCharacterStream() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of an ASCII
+ * character stream embodied as a java.io.InputStream.
+ *
+ * @return the next attribute as a java.io.InputStream. null if the value is
+ * SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public InputStream readAsciiStream() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a stream of bytes
+ * embodied as a java.io.InputStream.
+ *
+ * @return the next attribute as a java.io.InputStream. null if the value is
+ * SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public InputStream readBinaryStream() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a
+ * java.lang.Object.
+ * <p>
+ * The type of the Object returned is determined by the type mapping for
+ * this JDBC driver, including any customized mappings in force. A type map
+ * is given to the SQLInput by the JDBC driver before the SQLInput is given
+ * to the application.
+ * <p>
+ * If the attribute is an SQL structured or distinct type, its SQL type is
+ * determined. If the streams type map contains an element for that SQL
+ * type, the driver creates an object of relevant type and invokes the
+ * method 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. null if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Object readObject() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a java.sql.Ref.
+ *
+ * @return the next attribute as a java.sql.Ref. null if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Ref readRef() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a java.sql.Blob.
+ *
+ * @return the next attribute as a java.sql.Blob. null if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Blob readBlob() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a java.sql.Clob.
+ *
+ * @return the next attribute as a java.sql.Clob. null if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Clob readClob() throws SQLException;
+
+ /**
+ * Returns the next attribute in the stream in the form of a java.sql.Array.
+ *
+ * @return the next attribute as an Array. null if the value is SQL NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public Array readArray() throws SQLException;
+
+ /**
+ * Reports whether the last value read was SQL NULL.
+ *
+ * @return true if the last value read was SQL NULL, false otherwise.
+ * @throws SQLException
+ * if there is a database error
+ */
+ public boolean wasNull() throws SQLException;
+
+ /**
+ * Reads the next attribute in the stream (SQL DATALINK value) and returns
+ * it as a java.net.URL object.
+ *
+ * @return the next attribute as a java.net.URL. null if the value is SQL
+ * NULL.
+ * @throws SQLException
+ * if there is a database error
+ */
+ 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..287a5f6
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLOutput.java
@@ -0,0 +1,280 @@
+/*
+ * 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 to the database. This interface is used for custom mapping of
+ * types and is called by the JDBC driver. It is not expected that this
+ * interface is used by applications.
+ * <p>
+ * When an object which implements the SQLData interface is used as an argument
+ * to an SQL statement, the JDBC driver calls the method
+ * <code>SQLData.getSQLType</code> to establish the type of the SQL UDT that
+ * is being passed. The driver then creates an SQLOutput stream and passes it to
+ * the <code>SQLData.writeSQL</code> method, which in turn uses the
+ * appropriate SQLOutput writer methods to write the data from the SQLData
+ * object into the stream according to the defined mapping.
+ */
+public interface SQLOutput {
+
+ /**
+ * Write a String value into the output stream.
+ *
+ * @param theString
+ * the String to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeString(String theString) throws SQLException;
+
+ /**
+ * Write a boolean value into the output stream.
+ *
+ * @param theFlag
+ * the boolean value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeBoolean(boolean theFlag) throws SQLException;
+
+ /**
+ * Write a byte value into the output stream.
+ *
+ * @param theByte
+ * the byte value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeByte(byte theByte) throws SQLException;
+
+ /**
+ * Write a short value into the output stream.
+ *
+ * @param theShort
+ * the short value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeShort(short theShort) throws SQLException;
+
+ /**
+ * Write an int value into the output stream.
+ *
+ * @param theInt
+ * the int value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeInt(int theInt) throws SQLException;
+
+ /**
+ * Write a long value into the output stream.
+ *
+ * @param theLong
+ * the long value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeLong(long theLong) throws SQLException;
+
+ /**
+ * Write a float value into the output stream.
+ *
+ * @param theFloat
+ * the float value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeFloat(float theFloat) throws SQLException;
+
+ /**
+ * Write a double value into the output stream.
+ *
+ * @param theDouble
+ * the double value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeDouble(double theDouble) throws SQLException;
+
+ /**
+ * Write a java.math.BigDecimal value into the output stream.
+ *
+ * @param theBigDecimal
+ * the BigDecimal value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ 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
+ */
+ public void writeBytes(byte[] theBytes) throws SQLException;
+
+ /**
+ * Write a java.sql.Date value into the output stream.
+ *
+ * @param theDate
+ * the Date value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeDate(Date theDate) throws SQLException;
+
+ /**
+ * Write a java.sql.Time value into the output stream.
+ *
+ * @param theTime
+ * the Time value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeTime(Time theTime) throws SQLException;
+
+ /**
+ * Write a java.sql.Timestamp value into the output stream.
+ *
+ * @param theTimestamp
+ * the Timestamp value to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ 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 java.io.Reader
+ * object
+ * @throws SQLException
+ * if a database error occurs
+ */
+ 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
+ * java.io.InputStream object
+ * @throws SQLException
+ * if a database error occurs
+ */
+ 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 java.io.InputStream object
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeBinaryStream(InputStream theStream) throws SQLException;
+
+ /**
+ * Write an SQLData object into the output stream.
+ * <p>
+ * If the SQLData object is null, writes SQL NULL to the stream.
+ * <p>
+ * Otherwise, calls the <code>SQLData.writeSQL</code> 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 SQLData object to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeObject(SQLData theObject) throws SQLException;
+
+ /**
+ * Write an SQL Ref value into the output stream.
+ *
+ * @param theRef
+ * the java.sql.Ref object to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeRef(Ref theRef) throws SQLException;
+
+ /**
+ * Write an SQL Blob value into the output stream.
+ *
+ * @param theBlob
+ * the java.sql.Blob object to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeBlob(Blob theBlob) throws SQLException;
+
+ /**
+ * Write an SQL Clob value into the output stream.
+ *
+ * @param theClob
+ * the java.sql.Clob object to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeClob(Clob theClob) throws SQLException;
+
+ /**
+ * Write an SQL Struct value into the output stream.
+ *
+ * @param theStruct
+ * the java.sql.Struct object to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeStruct(Struct theStruct) throws SQLException;
+
+ /**
+ * Write an SQL Array value into the output stream.
+ *
+ * @param theArray
+ * the java.sql.Array object to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public void writeArray(Array theArray) throws SQLException;
+
+ /**
+ * Write an SQL DATALINK value into the output stream.
+ *
+ * @param theURL
+ * the Datalink value as a java.net.URL to write
+ * @throws SQLException
+ * if a database error occurs
+ */
+ 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..734f1f2
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLPermission.java
@@ -0,0 +1,60 @@
+/*
+ * 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;
+
+/**
+ * Permission relating to security access control in the java.sql package.
+ * <p>
+ * Currently, the only permission supported has the name "setLog". The setLog
+ * permission controls whether a Java application or applet can open a logging
+ * stream using the DriverManager.setLogWriter method or the
+ * DriverManager.setLogStream method. This is a potentially dangerous operation
+ * since the logging stream can contain usernames, passwords
+ */
+public final class SQLPermission extends BasicPermission implements Guard,
+ Serializable {
+
+ private static final long serialVersionUID = -1439323187199563495L;
+
+ /**
+ * Creates a new SQLPermission object with the specified name.
+ *
+ * @param name
+ * the name to use for this SQLPermission
+ */
+ public SQLPermission(String name) {
+ super(name);
+ }
+
+ /**
+ * Creates a new SQLPermission object with the specified name.
+ *
+ * @param name
+ * is the name of the SQLPermission. Currently only "setLog" is
+ * allowed.
+ * @param actions
+ * is currently unused and should be set to 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..efaf216
--- /dev/null
+++ b/sql/src/main/java/java/sql/SQLWarning.java
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+public class SQLWarning extends SQLException implements Serializable {
+
+ private static final long serialVersionUID = 3917336774604784856L;
+
+ /**
+ * Creates an SQLWarning object. The Reason string is set to null, the
+ * SQLState string is set to null and the Error Code is set to 0.
+ */
+ public SQLWarning() {
+ super();
+ }
+
+ /**
+ * Creates an SQLWarning object. The Reason string is set to the given
+ * reason string, the SQLState string is set to null and the Error Code is
+ * set to 0.
+ *
+ * @param theReason
+ */
+ public SQLWarning(String theReason) {
+ super(theReason);
+ }
+
+ /**
+ * Creates an SQLWarning object. The Reason string is set to the given
+ * reason string, the SQLState string is set to the given 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 SQLState string
+ */
+ public SQLWarning(String theReason, String theSQLState) {
+ super(theReason, theSQLState);
+ }
+
+ /**
+ * Creates an SQLWarning object. The Reason string is set to the given
+ * reason string, the SQLState string is set to the given SQLState string
+ * and the Error Code is set to the given ErrorCode value.
+ *
+ * @param theReason
+ * @param theSQLState
+ * @param theErrorCode
+ */
+ public SQLWarning(String theReason, String theSQLState, int theErrorCode) {
+ super(theReason, theSQLState, theErrorCode);
+ }
+
+ /**
+ * Gets the SQLWarning chained to this SQLWarning object.
+ *
+ * @return the SQLWarning chained to this SQLWarning. null if no SQLWarning
+ * is chained to this SQLWarning.
+ */
+ 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 SQLWarning to this SQLWarning.
+ *
+ * @param w
+ * the SQLWarning to chain to this SQLWarning.
+ */
+ 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..fd27877
--- /dev/null
+++ b/sql/src/main/java/java/sql/Savepoint.java
@@ -0,0 +1,43 @@
+/*
+ * 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 from the Connection.rollback method. Rolling back to a
+ * particular Savepoint means that all changes that occurred after that
+ * Savepoint are removed.
+ */
+public interface Savepoint {
+
+ /**
+ * Returns the constructed ID for this Savepoint.
+ *
+ * @return the ID for this Savepoint.
+ * @throws SQLException
+ */
+ public int getSavepointId() throws SQLException;
+
+ /**
+ * Returns the name for this Savepoint.
+ *
+ * @return the name of this Savepoint.
+ * @throws SQLException
+ */
+ 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..8896dbf
--- /dev/null
+++ b/sql/src/main/java/java/sql/Statement.java
@@ -0,0 +1,620 @@
+/*
+ * 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 and returning their
+ * results.
+ *
+ * By default, an object implementing the Statement interface can returns
+ * results as ResultSets. For any given Statement object, only one ResultSet can
+ * be open at one time. A call to any of the execution methods of Statement will
+ * cause any previously created ResultSet object for that Statement to be closed
+ * implicitly.
+ * <p>
+ * To have multiple ResultSet objects open concurrently, multiple Statement
+ * objects must be used.
+ */
+public interface Statement {
+
+ /**
+ * Passing this constant to getMoreResults implies that all ResultSet
+ * objects previously kept open should be closed.
+ */
+ public static final int CLOSE_ALL_RESULTS = 3;
+
+ /**
+ * Passing this constant to getMoreResults implies that the current
+ * ResultSet object should be closed
+ */
+ public static final int CLOSE_CURRENT_RESULT = 1;
+
+ /**
+ * Indicates that an error was encountered during execution of a batch
+ * statement.
+ */
+ public static final int EXECUTE_FAILED = -3;
+
+ /**
+ * Passing this constant to getMoreResults implies that the current
+ * ResultSet object should not be closed.
+ */
+ public static final int KEEP_CURRENT_RESULT = 2;
+
+ /**
+ * Indicates that generated keys should not be accessible for retrieval.
+ */
+ public static final int NO_GENERATED_KEYS = 2;
+
+ /**
+ * Indicates that generated keys should be accessible for retrieval.
+ */
+ 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.
+ */
+ public static final int SUCCESS_NO_INFO = -2;
+
+ /**
+ * Adds a specified SQL commands to the list of commands for this Statement.
+ * <p>
+ * The list of commands is executed by invoking the
+ * <code>executeBatch</code> method.
+ *
+ * @param sql
+ * the SQL command as a String. Typically an INSERT or UPDATE
+ * statement.
+ * @throws SQLException
+ * if an error occurs accessing the database or the database
+ * does not support batch updates
+ */
+ public void addBatch(String sql) throws SQLException;
+
+ /**
+ * Cancels this Statement 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 being executed on another thread.
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ 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
+ */
+ public void clearBatch() throws SQLException;
+
+ /**
+ * Clears all SQLWarnings from this Statement.
+ *
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public void clearWarnings() throws SQLException;
+
+ /**
+ * Releases this Statement's database and JDBC driver resources.
+ * <p>
+ * Using this method to release these resources as soon as possible is
+ * strongly recommended. It is not a good idea to rely on these resources
+ * being released when the Statement object is finalized during garbage
+ * collection. Doing so can result in unpredictable performance
+ * characteristics 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 ResultSets.
+ * <p>
+ * Use the <code>getResultSet</code> or <code>getUpdateCount</code>
+ * methods to get the first result and <code>getMoreResults</code> to get
+ * any subsequent results.
+ *
+ * @param sql
+ * the SQL statement to execute
+ * @return true if the first result is a ResultSet, false if the first
+ * result is an update count or if there is no result
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public boolean execute(String sql) throws SQLException;
+
+ /**
+ * Executes a supplied SQL statement. This may return multiple ResultSets.
+ * This method allows control of whether auto-generated Keys should be made
+ * available for retrieval, if the SQL statement is an INSERT statement.
+ * <p>
+ * Use the <code>getResultSet</code> or <code>getUpdateCount</code>
+ * methods to get the first result and <code>getMoreResults</code> 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
+ * Statement.NO_GENERATED_KEYS or Statement.RETURN_GENERATED_KEYS
+ * @return true if results exists and the first result is a ResultSet, false
+ * if the first result is an update count or if there is no result
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public boolean execute(String sql, int autoGeneratedKeys)
+ throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. This may return multiple ResultSets.
+ * This method allows retrieval of auto generated keys specified by the
+ * supplied array of column indexes, if the SQL statement is an INSERT
+ * statement.
+ * <p>
+ * Use the <code>getResultSet</code> or <code>getUpdateCount</code>
+ * methods to get the first result and <code>getMoreResults</code> 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</code> method.
+ * @return true if the first result is a ResultSet, false if the first
+ * result is an update count or if there is no result
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public boolean execute(String sql, int[] columnIndexes) throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. This may return multiple ResultSets.
+ * This method allows retrieval of auto generated keys specified by the
+ * supplied array of column indexes, if the SQL statement is an INSERT
+ * statement.
+ * <p>
+ * Use the <code>getResultSet</code> or <code>getUpdateCount</code>
+ * methods to get the first result and <code>getMoreResults</code> 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</code> method.
+ * @return true if the first result is a ResultSet, false if the first
+ * result is an update count or if there is no result
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ 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.
+ * <p>
+ * If one of the commands in the batch fails, this method can throw a
+ * BatchUpdateException and the JDBC driver may or may not process the
+ * remaining commands. The JDBC driver must behave consistently with the
+ * underlying database, either always continuing or never continuing. 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 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.
+ * <p>
+ * <ol>
+ * <li> If the value of an element is >=0, the corresponding command
+ * completed successfully and the value is the update count for that
+ * command, which is the number of rows in the database affected by
+ * the command.</li>
+ * <li> If the value is SUCCESS_NO_INFO, the command completed
+ * successfully but the number of rows affected is unknown.
+ * <li>
+ * <li> If the value is EXECUTE_FAILED, the command failed.
+ * </ol>
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public int[] executeBatch() throws SQLException;
+
+ /**
+ * Executes a supplied SQL statement. Returns a single ResultSet.
+ *
+ * @param sql
+ * an SQL statement to execute. Typically a SELECT statement
+ * @return a 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 ResultSet
+ */
+ public ResultSet executeQuery(String sql) throws SQLException;
+
+ /**
+ * Executes the supplied SQL statement. The statement may be an INSERT,
+ * UPDATE or DELETE statement or a statement which returns nothing.
+ *
+ * @param sql
+ * an SQL statement to execute - an SQL INSERT, UPDATE, 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 ResultSet
+ */
+ 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 INSERT, UPDATE, 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
+ * Statement.RETURN_GENERATED_KEYS or 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 ResultSet
+ */
+ 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 INSERT, UPDATE, 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</code> 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 ResultSet
+ */
+ 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 INSERT, UPDATE, 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</code> 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 ResultSet
+ */
+ public int executeUpdate(String sql, String[] columnNames)
+ throws SQLException;
+
+ /**
+ * Gets the Connection that produced this Statement.
+ *
+ * @return the Connection
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Gets the default direction for fetching rows for ResultSets generated
+ * from this Statement.
+ *
+ * @return an integer describing the default fetch direction, one of:
+ * ResultSet.FETCH_FORWARD, ResultSet.FETCH_REVERSE,
+ * ResultSet.FETCH_UNKNOWN
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public int getFetchDirection() throws SQLException;
+
+ /**
+ * Gets the default number of rows for a fetch for the ResultSet objects
+ * returned from this Statement.
+ *
+ * @return the default fetch size for ResultSets produced by this Statement
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public int getFetchSize() throws SQLException;
+
+ /**
+ * Returns auto generated keys created by executing this Statement.
+ *
+ * @return a ResultSet containing the auto generated keys - empty if no keys
+ * were generated by the Statement
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public ResultSet getGeneratedKeys() throws SQLException;
+
+ /**
+ * Gets the maximum number of bytes which can be returned for values from
+ * Character and Binary values in a ResultSet derived from this Statement.
+ * This limit applies to BINARY, VARBINARY, LONGVARBINARY, CHAR, VARCHAR,
+ * and LONGVARCHAR types. Any data exceeding the maximum size is abandoned
+ * without announcement.
+ *
+ * @return the current size limit, where 0 means that there is no limit
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public int getMaxFieldSize() throws SQLException;
+
+ /**
+ * Gets the maximum number of rows that a 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 0 means that there is no limit.
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public int getMaxRows() throws SQLException;
+
+ /**
+ * Moves to this Statement's next result. Returns true if it is a ResultSet.
+ * Any current ResultSet objects previously obtained with
+ * <code>getResultSet()</code> are closed implicitly.
+ *
+ * @return true if the next result is a ResultSet, false if the next result
+ * is not a ResultSet or if there are no more results. Note that if
+ * there is no more data, this method will return false and
+ * <code>getUpdateCount</code> will return -1.
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public boolean getMoreResults() throws SQLException;
+
+ /**
+ * Moves to this Statement's next result. Returns true if the next result is
+ * a ResultSet. Any current ResultSet objects previously obtained with
+ * <code>getResultSet()</code> are handled as indicated by a supplied Flag
+ * parameter.
+ *
+ * @param current
+ * a flag indicating what to do with existing ResultSets. This
+ * parameter must be one of Statement.CLOSE_ALL_RESULTS,
+ * Statement.CLOSE_CURRENT_RESULT or
+ * Statement.KEEP_CURRENT_RESULT.
+ * @return true if the next result exists and is a ResultSet, false if the
+ * next result is not a ResultSet or if there are no more results.
+ * Note that if there is no more data, this method will return false
+ * and <code>getUpdateCount</code> will return -1.
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public boolean getMoreResults(int current) throws SQLException;
+
+ /**
+ * Gets the timeout value for Statement execution. The JDBC driver will wait
+ * up to this value for the execution to complete - after the limit is
+ * exceeded an SQL Exception is thrown.
+ *
+ * @return the current Query Timeout value, where 0 indicates that there is
+ * no current timeout.
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public int getQueryTimeout() throws SQLException;
+
+ /**
+ * Gets the current result. Should only be called once per result.
+ *
+ * @return the ResultSet for the current result. null if the result is an
+ * update count or if there are no more results.
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public ResultSet getResultSet() throws SQLException;
+
+ /**
+ * Gets the concurrency setting for ResultSet objects generated by this
+ * Statement.
+ *
+ * @return ResultSet.CONCUR_READ_ONLY or ResultSet.CONCUR_UPDATABLE
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public int getResultSetConcurrency() throws SQLException;
+
+ /**
+ * Gets the cursor hold setting for ResultSet objects generated by this
+ * Statement.
+ *
+ * @return ResultSet.HOLD_CURSORS_OVER_COMMIT or
+ * ResultSet.CLOSE_CURSORS_AT_COMMIT
+ * @throws SQLException
+ * if there is an error while accessing the database
+ */
+ public int getResultSetHoldability() throws SQLException;
+
+ /**
+ * Gets the ResultSet type setting for ResultSets derived from this
+ * Statement.
+ *
+ * @return ResultSet.TYPE_FORWARD_ONLY for a ResultSet where the cursor can
+ * only move forward, ResultSet.TYPE_SCROLL_INSENSITIVE for a
+ * ResultSet which is Scrollable but is not sensitive to changes
+ * made by others, ResultSet.TYPE_SCROLL_SENSITIVE for a ResultSet
+ * which is Scrollable but is sensitive to changes made by others
+ * @throws SQLException
+ * if there is an error accessing the database
+ */
+ public int getResultSetType() throws SQLException;
+
+ /**
+ * Gets an update count for the current result if it is not a ResultSet.
+ *
+ * @return the current result as an update count. -1 if the current result
+ * is a ResultSet or if there are no more results
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public int getUpdateCount() throws SQLException;
+
+ /**
+ * Retrieves the first SQLWarning reported by calls on this Statement.
+ * <p>
+ * If there are multiple warnings, subsequent warnings are chained to the
+ * first one.
+ * <p>
+ * The chain or warnings is cleared each time the Statement is executed.
+ * <p>
+ * Warnings associated with reads from the ResultSet returned from executing
+ * a Statement will be attached to the ResultSet, not the Statement object.
+ *
+ * @return an SQLWarning, null if there are no warnings
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ public SQLWarning getWarnings() throws SQLException;
+
+ /**
+ * Sets the SQL cursor name. This name is used by subsequent Statement
+ * execute methods.
+ * <p>
+ * Cursor names must be unique within one Connection.
+ * <p>
+ * With the Cursor name set, it can then be utilized in SQL positioned
+ * update or delete statements to determine the current row in a 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
+ */
+ public void setCursorName(String name) throws SQLException;
+
+ /**
+ * Sets Escape Processing mode.
+ * <p>
+ * 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 PreparedStatements since they are processed when created, before this
+ * method can be called.
+ *
+ * @param enable
+ * true to set escape processing mode on, false to turn it off.
+ * @throws SQLException
+ * if an error occurs accessing the database
+ */
+ 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 ResultSets created by this Statement. The
+ * default fetch direction is FETCH_FORWARD.
+ *
+ * @param direction
+ * which fetch direction to use. This parameter should be one of
+ * ResultSet.FETCH_UNKNOWN, ResultSet.FETCH_FORWARD or
+ * 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. 0 tells the driver
+ * to ignore the hint. Should be less than
+ * <code>getMaxRows</code> 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.
+ */
+ public void setFetchSize(int rows) throws SQLException;
+
+ /**
+ * Sets the maximum number of bytes for ResultSet columns that contain
+ * character or binary values. This applies to BINARY, VARBINARY,
+ * LONGVARBINARY, CHAR, VARCHAR, and LONGVARCHAR fields. Any data exceeding
+ * the maximum size is abandoned without announcement.
+ *
+ * @param max
+ * the maximum field size in bytes. O means "no limit".
+ * @throws SQLException
+ * if an error occurs accessing the database or the max value is
+ * <0.
+ */
+ public void setMaxFieldSize(int max) throws SQLException;
+
+ /**
+ * Sets the maximum number of rows that any ResultSet can contain. If the
+ * number of rows exceeds this value, the additional rows are silently
+ * discarded.
+ *
+ * @param max
+ * the maximum number of rows. 0 means "no limit".
+ * @throws SQLException
+ * if an error occurs accessing the database or if max <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 SQLException.
+ *
+ * @param seconds
+ * timeout in seconds. 0 means no timeout ("wait forever")
+ * @throws SQLException
+ * if an error occurs accessing the database or if seconds <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..0404cb7
--- /dev/null
+++ b/sql/src/main/java/java/sql/Struct.java
@@ -0,0 +1,66 @@
+/*
+ * 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 mapping an SQL structured type to
+ * Java. The Struct object has a value for each attribute of the SQL structured
+ * type
+ */
+public interface Struct {
+
+ /**
+ * Gets the SQL Type name of the SQL structured type that this Struct
+ * represents
+ *
+ * @return the fully qualified name of SQL structured type
+ * @throws SQLException
+ * if a database error occurs
+ */
+ 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 Connection for customized
+ * type mappings. Where there is no entry in the Type Map which matches the
+ * this structured type, the JDBC driver uses the standard mapping.
+ *
+ * @return an Object array containing the attributes, in order
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public Object[] getAttributes() throws SQLException;
+
+ /**
+ * Gets the values of the attributes of this SQL structured type. This
+ * method uses the supplied type map for customized type mappings. Where
+ * there is no entry in the Type Map which matches the this structured type,
+ * the JDBC driver uses the default mapping. The 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 attributes, in order
+ * @throws SQLException
+ * if a database error occurs
+ */
+ public Object[] getAttributes(Map<String, Class<?>> 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..048259d
--- /dev/null
+++ b/sql/src/main/java/java/sql/Time.java
@@ -0,0 +1,221 @@
+/*
+ * 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 TIME value. Provides functions to aid
+ * generation and interpretation of JDBC escape format for time values.
+ *
+ */
+public class Time extends Date {
+
+ private static final long serialVersionUID = 8397324403548013681L;
+
+ /**
+ * @deprecated Please use the constructor {@link #Time(long)} Constructs a Time
+ * object using the supplied values for Hour, Minute and Second.
+ * The Year, Month and Day elements of the Time object are set
+ * to 1970, January, 1 reflecting the Epoch (Time in
+ * milliseconds = 0).
+ * <p>
+ * Any attempt to access the Year, Month or Day elements of a
+ * Time object will result in an IllegalArgumentException.
+ * <p>
+ * Result is undefined if any argument is out of bounds.
+ * @param theHour
+ * a value from 0 - 23
+ * @param theMinute
+ * a value from 0 - 59
+ * @param theSecond
+ * a value from 0 - 59
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ public Time(int theHour, int theMinute, int theSecond) {
+ super(70, 0, 1, theHour, theMinute, theSecond);
+ }
+
+ /**
+ * Constructs a Time object using a supplied time specified in milliseconds
+ *
+ * @param theTime
+ * a Time specified in milliseconds since the Epoch (January 1st
+ * 1970, 00:00:00.000)
+ */
+ public Time(long theTime) {
+ super(theTime);
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL Time
+ * object does not have a Date component.
+ * @return does not return
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getDate() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL Time
+ * object does not have a Day component.
+ * @return does not return
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getDay() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL Time
+ * object does not have a Month component.
+ * @return does not return
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getMonth() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL Time
+ * object does not have a Year component.
+ * @return does not return
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public int getYear() {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL Time
+ * object does not have a Date component.
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setDate(int i) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL Time
+ * object does not have a Month component.
+ * @throws IllegalArgumentException
+ * if this method is called
+ */
+ @SuppressWarnings("deprecation")
+ @Deprecated
+ @Override
+ public void setMonth(int i) {
+ throw new IllegalArgumentException();
+ }
+
+ /**
+ * @deprecated This method is deprecated and must not be used. An SQL 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 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
+ */
+ @Override
+ public void setTime(long time) {
+ super.setTime(time);
+ }
+
+ /**
+ * Formats the Time as a String in JDBC escape format: hh:mm:ss
+ *
+ * @return A String representing the Time value in JDBC escape format:
+ * HH:mm:ss
+ */
+ @Override
+ public String toString() {
+ SimpleDateFormat dateFormat = new SimpleDateFormat("HH:mm:ss"); //$NON-NLS-1$
+ return dateFormat.format(this);
+ }
+
+ /**
+ * Creates a Time object from a String holding a time represented in JDBC
+ * escape format: hh:mm:ss.
+ * <p>
+ * An exception occurs if the input string is not in the form of a time in
+ * JDBC escape format.
+ *
+ * @param timeString
+ * A String representing the time value in JDBC escape format:
+ * hh:mm:ss
+ * @return The Time object set to a time corresponding to the given time
+ * @throws IllegalArgumentException
+ * if the supplied time string is not in JDBC escape format.
+ */
+ 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..da8fa7a
--- /dev/null
+++ b/sql/src/main/java/java/sql/Timestamp.java
@@ -0,0 +1,478 @@
+/*
+ * 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 TIMESTAMP type. It provides the capability
+ * to represent the SQL TIMESTAMP nanosecond value, in addition to the regular
+ * date/time value which has millisecond resolution.
+ * <p>
+ * The 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.
+ * <p>
+ * The addition of the nanosecond value field to the Timestamp object makes it
+ * significantly different from the java.util.Date object which it extends.
+ * Users should be cautious in their use of Timestamp objects and should not
+ * assume that they are interchangeable with java.util.Date objects when used
+ * outside the confines of the java.sql package.
+ *
+ */
+public class Timestamp extends Date {
+
+ private static final long serialVersionUID = 2745179027874758501L;
+
+ // The nanoseconds time value of the Timestamp
+ private int nanos;
+
+ /**
+ * @deprecated Please use the constructor {@link #Timestamp(long)} Returns a
+ * Timestamp corresponding to the time specified by the supplied
+ * values for Year, Month, Date, Hour, Minutes, Seconds and
+ * Nanoseconds
+ * @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
+ */
+ @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 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)
+ */
+ 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 true if this timestamp object is later than the supplied
+ * timestamp, otherwise returns false.
+ *
+ * @param theTimestamp
+ * the timestamp to compare with this timestamp object
+ * @return true if this timestamp object is later than the supplied
+ * timestamp, false otherwise
+ */
+ 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 true if this timestamp object is earlier than the supplied
+ * timestamp, otherwise returns false.
+ *
+ * @param theTimestamp
+ * the timestamp to compare with this timestamp object
+ * @return true if this timestamp object is earlier than the supplied
+ * timestamp, false otherwise
+ */
+ 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 Timestamp object with a supplied Timestamp object
+ *
+ * @param theObject
+ * the timestamp to compare with this timestamp object, passed in
+ * as an Object
+ * @return 0 if the two Timestamp objects are equal in time, a value <0 if
+ * this Timestamp object is before the supplied Timestamp and a
+ * value >0 if this Timestamp object is after the supplied Timestamp
+ * @throws ClassCastException
+ * if the supplied object is not a Timestamp object
+ */
+ @Override
+ public int compareTo(Date theObject) throws ClassCastException {
+ return this.compareTo((Timestamp) theObject);
+ }
+
+ /**
+ * Compares this Timestamp object with a supplied Timestamp object
+ *
+ * @param theTimestamp
+ * the timestamp to compare with this timestamp object, passed in
+ * as a Timestamp
+ * @return 0 if the two Timestamp objects are equal in time, a value <0 if
+ * this Timestamp object is before the supplied Timestamp and a
+ * value >0 if this Timestamp object is after the supplied Timestamp
+ */
+ 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
+ * @return true if this Timestamp object is equal to the supplied Timestamp
+ * object false if the object is not a Timestamp object or if the
+ * object is a Timestamp but represents a different instant in time
+ */
+ @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 timestamp object, passed in
+ * as an Object
+ * @return true if this Timestamp object is equal to the supplied Timestamp
+ * object
+ */
+ public boolean equals(Timestamp theTimestamp) {
+ if (theTimestamp == null) {
+ return false;
+ }
+ return (this.getTime() == theTimestamp.getTime())
+ && (this.getNanos() == theTimestamp.getNanos());
+ }
+
+ /**
+ * Gets this Timestamp's nanosecond value
+ *
+ * @return The timestamp's nanosecond value, an integer between 0 and
+ * 999,999,999
+ */
+ public int getNanos() {
+ return nanos;
+ }
+
+ /**
+ * Returns the time represented by this Timestamp object, as a long value
+ * containing the number of milliseconds since the Epoch (January 1 1970,
+ * 00:00:00.000 GMT)
+ */
+ @Override
+ public long getTime() {
+ long theTime = super.getTime();
+ theTime = theTime + (nanos / 1000000);
+ return theTime;
+ }
+
+ /**
+ * Sets the nanosecond value for this timestamp
+ * @param n number of nanoseconds
+ * @throws IllegalArgumentException if number of nanoseconds smaller than 0
+ * or greater than 999999999
+ */
+ 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 Timestamp object to the supplied time,
+ * defined as the number of milliseconds since the Epoch (January 1 1970,
+ * 00:00:00.000 GMT)
+ */
+ @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 of the form "yyyy-mm-dd hh:mm:ss.nnnnnnnnn"
+ *
+ * @return A string representing the instant defined by the Timestamp, in
+ * JDBC Timestamp escape format
+ */
+ @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 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 of the form "yyyy-mm-dd hh:mm:ss.nnnnnnnnn"
+ *
+ * @param s
+ * the String containing a time in JDBC timestamp escape format
+ * @return A timestamp object with time value as defined by the supplied
+ * String
+ * @throws IllegalArgumentException if the provided String is null
+ */
+ 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..5e9aa4c
--- /dev/null
+++ b/sql/src/main/java/java/sql/Types.java
@@ -0,0 +1,184 @@
+/*
+ * 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 in XOPEN.
+ */
+public class Types {
+
+ /*
+ * Private constructor to prevent instantiation.
+ */
+ private Types() {
+ super();
+ }
+
+ /**
+ * The type code that identifies the SQL type ARRAY.
+ */
+ public static final int ARRAY = 2003;
+
+ /**
+ * The type code that identifies the SQL type BIGINT.
+ */
+ public static final int BIGINT = -5;
+
+ /**
+ * The type code that identifies the SQL type BINARY.
+ */
+ public static final int BINARY = -2;
+
+ /**
+ * The type code that identifies the SQL type BIT.
+ */
+ public static final int BIT = -7;
+
+ /**
+ * The type code that identifies the SQL type BLOB.
+ */
+ public static final int BLOB = 2004;
+
+ /**
+ * The type code that identifies the SQL type BOOLEAN.
+ */
+ public static final int BOOLEAN = 16;
+
+ /**
+ * The type code that identifies the SQL type CHAR.
+ */
+ public static final int CHAR = 1;
+
+ /**
+ * The type code that identifies the SQL type CLOB.
+ */
+ public static final int CLOB = 2005;
+
+ /**
+ * The type code that identifies the SQL type DATALINK.
+ */
+ public static final int DATALINK = 70;
+
+ /**
+ * The type code that identifies the SQL type DATE.
+ */
+ public static final int DATE = 91;
+
+ /**
+ * The type code that identifies the SQL type DECIMAL.
+ */
+ public static final int DECIMAL = 3;
+
+ /**
+ * The type code that identifies the SQL type DISTINCT.
+ */
+ public static final int DISTINCT = 2001;
+
+ /**
+ * The type code that identifies the SQL type DOUBLE.
+ */
+ public static final int DOUBLE = 8;
+
+ /**
+ * The type code that identifies the SQL type FLOAT.
+ */
+ public static final int FLOAT = 6;
+
+ /**
+ * The type code that identifies the SQL type INTEGER.
+ */
+ public static final int INTEGER = 4;
+
+ /**
+ * The type code that identifies the SQL type JAVA_OBJECT.
+ */
+ public static final int JAVA_OBJECT = 2000;
+
+ /**
+ * The type code that identifies the SQL type LONGVARBINARY.
+ */
+ public static final int LONGVARBINARY = -4;
+
+ /**
+ * The type code that identifies the SQL type LONGVARCHAR.
+ */
+ public static final int LONGVARCHAR = -1;
+
+ /**
+ * The type code that identifies the SQL type NULL.
+ */
+ public static final int NULL = 0;
+
+ /**
+ * The type code that identifies the SQL type NUMERIC.
+ */
+ 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</code> and <code>setObject</code>.
+ */
+ public static final int OTHER = 1111;
+
+ /**
+ * The type code that identifies the SQL type REAL.
+ */
+ public static final int REAL = 7;
+
+ /**
+ * The type code that identifies the SQL type REF.
+ */
+ public static final int REF = 2006;
+
+ /**
+ * The type code that identifies the SQL type SMALLINT.
+ */
+ public static final int SMALLINT = 5;
+
+ /**
+ * The type code that identifies the SQL type STRUCT.
+ */
+ public static final int STRUCT = 2002;
+
+ /**
+ * The type code that identifies the SQL type TIME.
+ */
+ public static final int TIME = 92;
+
+ /**
+ * The type code that identifies the SQL type TIMESTAMP.
+ */
+ public static final int TIMESTAMP = 93;
+
+ /**
+ * The type code that identifies the SQL type TINYINT.
+ */
+ public static final int TINYINT = -6;
+
+ /**
+ * The type code that identifies the SQL type VARBINARY.
+ */
+ public static final int VARBINARY = -3;
+
+ /**
+ * The type code that identifies the SQL type VARCHAR.
+ */
+ 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..e46f170
--- /dev/null
+++ b/sql/src/main/java/java/sql/package.html
@@ -0,0 +1,7 @@
+<html>
+ <body>
+ <p>
+ Provides a standard interface for accessing SQL-based databases.
+ <p>
+ </body>
+</html> \ 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..e8ec7c3
--- /dev/null
+++ b/sql/src/main/java/javax/sql/ConnectionEvent.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.EventObject;
+import java.sql.SQLException;
+import java.io.Serializable;
+
+/**
+ * An Event object which is sent when specific events happen on a
+ * PooledConnection object. The events involved are when the application closing
+ * the PooledConnection and when an error occurs in the PooledConnection.
+ */
+public class ConnectionEvent extends EventObject implements Serializable {
+
+ private static final long serialVersionUID = -4843217645290030002L;
+
+ private SQLException theSQLException;
+
+ /**
+ * Creates a connection event initialized with a supplied PooledConnection.
+ *
+ * @param theConnection
+ * the PooledConnection
+ */
+ public ConnectionEvent(PooledConnection theConnection) {
+ super(theConnection);
+ }
+
+ /**
+ * Creates a ConnectionEvent initialized with a supplied PooledConnection
+ * and with a supplied SQLException indicating that an error has occurred
+ * within the PooledConnection.
+ *
+ * @param theConnection
+ * the PooledConnection
+ * @param theException
+ * the SQLException holding information about the error that has
+ * occurred, which is about to be returned to the application.
+ */
+ public ConnectionEvent(PooledConnection theConnection,
+ SQLException theException) {
+ super(theConnection);
+ theSQLException = theException;
+ }
+
+ /**
+ * Gets the SQLException which holds information about the error which
+ * occurred in the PooledConnection.
+ *
+ * @return an SQLException containing information about the error. May be
+ * null if no error has occurred.
+ */
+ 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..7156558
--- /dev/null
+++ b/sql/src/main/java/javax/sql/ConnectionEventListener.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.util.EventListener;
+
+/**
+ * An interface used to receive events generated by a
+ * <code>PooledConnection</code>.
+ * <p>
+ * This interface would typically be implemented by a component which implements
+ * Connection Pooling (a Connection Pool Manager). A Connection will signal
+ * events to a ConnectionEventListener either when the application closes a
+ * Connection it has been using or when a significant error occurs while the
+ * Connection is being used, where the Connection should not be used again.
+ * <p>
+ * The Connection Pool Manager can return closed Connections to the Pool for
+ * later reuse. Connections experiencing an error should be discarded.
+ *
+ */
+public interface ConnectionEventListener extends EventListener {
+
+ /**
+ * Notifies the ConnectionEventListener that an application has called the
+ * <code>close</code> method on a pooled Connection.
+ *
+ * @param theEvent
+ * a ConnectionEvent containing detail about the source of the
+ * event.
+ */
+ public void connectionClosed(ConnectionEvent theEvent);
+
+ /**
+ * Notifies the ConnectionEventListener that an error has occurred while a
+ * PooledConnection was being used and that the PooledConnection can no
+ * longer be used for work. This notification is done just before the
+ * SQLException passed in the event message is thrown to the application.
+ *
+ * @param theEvent
+ * a ConnectionEvent containing detail about the source of the
+ * event and the SQLException that has occurred.
+ */
+ 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..5be75d9
--- /dev/null
+++ b/sql/src/main/java/javax/sql/ConnectionPoolDataSource.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.io.PrintWriter;
+
+/**
+ * An interface for the creation of PooledConnection objects. Used internally
+ * within the package.
+ * <p>
+ * A class which implements the ConnectionPoolDataSource interface is typically
+ * registered with a JNDI naming service directory and is retrieved from there
+ * by name.
+ */
+public interface ConnectionPoolDataSource {
+
+ /**
+ * Gets the Login Timeout value for this ConnectionPoolDataSource. The Login
+ * Timeout is the maximum time in seconds that the 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.
+ *
+ * @return the Login Timeout value in seconds.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public int getLoginTimeout() throws SQLException;
+
+ /**
+ * Gets the Log Writer for this ConnectionPoolDataSource.
+ * <p>
+ * The Log Writer is a stream to which all log and trace messages are sent
+ * from this ConnectionPoolDataSource. The Log Writer can be null, in which
+ * case, log and trace capture is disabled. The default value for the Log
+ * Writer when an ConnectionPoolDataSource is created is null. Note that the
+ * Log Writer for an ConnectionPoolDataSource is not the same as the Log
+ * Writer used by a <code>DriverManager</code>.
+ *
+ * @return a PrintWriter which is the Log Writer for this
+ * ConnectionPoolDataSource. Can be null, in which case log writing
+ * is disabled for this ConnectionPoolDataSource.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public PrintWriter getLogWriter() throws SQLException;
+
+ /**
+ * Create a connection to a database which can then be used as a pooled
+ * connection.
+ *
+ * @return a PooledConnection which represents the connection to the
+ * database
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public PooledConnection getPooledConnection() throws SQLException;
+
+ /**
+ * Create a connection to a database, using a supplied Username and
+ * Password, which can then be used as a pooled connection.
+ *
+ * @param theUser
+ * a String containing a User Name for the database
+ * @param thePassword
+ * a String containing the Password for the user identified by
+ * <code>theUser</code>
+ * @return a PooledConnection which represents the connection to the
+ * database
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public PooledConnection getPooledConnection(String theUser,
+ String thePassword) throws SQLException;
+
+ /**
+ * Sets the Login Timeout value for this ConnectionPoolDataSource. The Login
+ * Timeout is the maximum time in seconds that the 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.
+ */
+ public void setLoginTimeout(int theTimeout) throws SQLException;
+
+ /**
+ * Sets the Log Writer for this ConnectionPoolDataSource.
+ * <p>
+ * The Log Writer is a stream to which all log and trace messages are sent
+ * from this ConnectionPoolDataSource. The Log Writer can be null, in which
+ * case, log and trace capture is disabled. The default value for the Log
+ * Writer when an ConnectionPoolDataSource is created is null. Note that the
+ * Log Writer for an ConnectionPoolDataSource is not the same as the Log
+ * Writer used by a <code>DriverManager</code>.
+ *
+ * @param theWriter
+ * a PrintWriter to use as the Log Writer for this
+ * ConnectionPoolDataSource.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ 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..cd3e0a3
--- /dev/null
+++ b/sql/src/main/java/javax/sql/DataSource.java
@@ -0,0 +1,138 @@
+/*
+ * 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 Connection objects which represent a
+ * connection to a database. This interface is an alternative to the
+ * <code>java.sql.DriverManager</code>.
+ * <p>
+ * A class which implements the DataSource interface is typically registered
+ * with a JNDI naming service directory and is retrieved from there by name.
+ * <p>
+ * The DataSource interface is typically implemented by the writer of a JDBC
+ * driver. There are three variants of the DataSource interface, which produce
+ * Connections with differing characteristics:
+ * <ol>
+ * <li>Standard DataSource, which produces standard Connection objects with no
+ * special features.</li>
+ * <li>Connection Pool DataSource, which produces PooledConnection objects
+ * which are able to participate in connection pooling, typically involving a
+ * connection pooling manager as an intermediary between applications and the
+ * database.</li>
+ * <li>Distributed transaction DataSource ("XADataSource"), which produces
+ * XAConnection objects which can be used to handle distributed transactions and
+ * which typically involve a transaction manager component in the system.
+ * XAConnection objects also typically provide connection pooling capabilities
+ * as well as distributed transaction capabilities. </li>
+ * </ol>
+ * <p>
+ * Note that a JDBC driver which is accessed via the DataSource interface is
+ * loaded via a JNDI lookup process. A driver loaded in this way does not
+ * register itself with the <code>DriverManager</code>.
+ */
+public interface DataSource {
+
+ /**
+ * Creates a connection to the database represented by this DataSource.
+ *
+ * @return a Connection object which is a connection to the database.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Creates a connection to the database represented by this DataSource,
+ * using a supplied Username and Password,.
+ *
+ * @param theUsername
+ * a String containing a User Name for the database
+ * @param thePassword
+ * a String containing the Password for the user identified by
+ * <code>theUsername</code>
+ * @return a Connection object which is a connection to the database.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public Connection getConnection(String theUsername, String thePassword)
+ throws SQLException;
+
+ /**
+ * Gets the Login Timeout value for this DataSource. The Login Timeout is
+ * the maximum time in seconds that the 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.
+ */
+ public int getLoginTimeout() throws SQLException;
+
+ /**
+ * Gets the Log Writer for this DataSource.
+ * <p>
+ * The Log Writer is a stream to which all log and trace messages are sent
+ * from this DataSource. The Log Writer can be null, in which case, log and
+ * trace capture is disabled. The default value for the Log Writer when an
+ * DataSource is created is null. Note that the Log Writer for an DataSource
+ * is not the same as the Log Writer used by a <code>DriverManager</code>.
+ *
+ * @return a PrintWriter which is the Log Writer for this DataSource. Can be
+ * null, in which case log writing is disabled for this DataSource.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public PrintWriter getLogWriter() throws SQLException;
+
+ /**
+ * Sets the Login Timeout value for this DataSource. The Login Timeout is
+ * the maximum time in seconds that the 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.
+ */
+ public void setLoginTimeout(int theTimeout) throws SQLException;
+
+ /**
+ * Sets the Log Writer for this DataSource.
+ * <p>
+ * The Log Writer is a stream to which all log and trace messages are sent
+ * from this DataSource. The Log Writer can be null, in which case, log and
+ * trace capture is disabled. The default value for the Log Writer when an
+ * DataSource is created is null. Note that the Log Writer for an DataSource
+ * is not the same as the Log Writer used by a <code>DriverManager</code>.
+ *
+ * @param theWriter
+ * a PrintWriter to use as the Log Writer for this DataSource.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ 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..50f7ae9
--- /dev/null
+++ b/sql/src/main/java/javax/sql/PooledConnection.java
@@ -0,0 +1,111 @@
+/*
+ * 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.
+ * <p>
+ * Typically, a 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.
+ * <p>
+ * It is not intended that an application use the PooledConnection interface
+ * directly. The 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.
+ * <p>
+ * Applications obtain connections to the database by calling the
+ * <code>DataSource.getConnection</code> method. Under the covers, the
+ * Connection Pool Manager will get a PooledConnection object from its
+ * connection pool and passes back a Connection object that wraps or references
+ * the PooledConnection object. A new PooledConnection object will only be
+ * created if the pool is empty.
+ * <p>
+ * When the application is finished using a PooledConnection, the application
+ * calls the <code>Connection.close</code> method. The Connection Pool Manager
+ * is notified via a 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
+ * PooledConnection object from the Connection and returns it to the pool for
+ * reuse - the PooledConnection is thus recycled rather than being destroyed.
+ * <p>
+ * The connection to the database represented by the PooledConnection is kept
+ * open until the PooledConnection object itself is deactivated by the
+ * Connection Pool Manager, which calls the <code>PooledConnection.close</code>
+ * method. This is typically done if there are too many inactive connections in
+ * the pool, if the PooledConnection encounters a problem that makes it unusable
+ * or if the whole system is being shut down.
+ *
+ */
+public interface PooledConnection {
+
+ /**
+ * Registers the supplied ConnectionEventListener with this
+ * PooledConnection. Once registered, the ConnectionEventListener will
+ * receive ConnectionEvent events when they occur in the PooledConnection.
+ *
+ * @param theListener
+ * an object which implements the ConnectionEventListener
+ * interface.
+ */
+ public void addConnectionEventListener(ConnectionEventListener theListener);
+
+ /**
+ * Closes the connection to the database held by this PooledConnection. This
+ * method should not be called directly by application code - it is intended
+ * for use by the Connection Pool manager component.
+ *
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ 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</code> and there are no PooledConnection
+ * objects available in the connection pool.
+ *
+ * @return a Connection object that is a handle to this PooledConnection
+ * object.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Deregister the supplied ConnectionEventListener from this
+ * PooledConnection. Once deregistered, the ConnectionEventListener will not
+ * longer receive events occurring in the PooledConnection.
+ *
+ * @param theListener
+ * an object which implements the ConnectionEventListener
+ * interface. This object should have previously been registered
+ * with the PooledConnection using the
+ * <code>addConnectionEventListener</code> method.
+ */
+ 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..2794ff2
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSet.java
@@ -0,0 +1,856 @@
+/*
+ * 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;
+
+/**
+ * A RowSet is an interface which provides access to data being sent from/to a
+ * database and which extends the functionality of ResultSet into a form that
+ * can be used as a JavaBeans component, perhaps being used in a visual
+ * programming environment.
+ * <p>
+ * Facilities are provided for get/set of properties relating to the Database
+ * and the SQL Command and for getting/setting data within the Rows represented
+ * by the RowSet. The RowSet supports JavaBeans events so that other components
+ * in an application can be informed when various changes happen to the RowSet,
+ * such as changes in data values.
+ * <p>
+ * RowSet is implemented as a layer on top of the remainder of the JDBC API. A
+ * RowSet may be <i>connected</i> where it maintains a connection to the
+ * database throughout its lifecycle. A RowSet may be <i>disconnected</i> where
+ * it establishes a connection to the database, gets data and then closes the
+ * connection. Updates to a disconnected RowSet can be made and later send back
+ * the changes to the database, but this requires the RowSet to first reconnect
+ * to the database before the changes are sent back.
+ * <p>
+ * Disconnected RowSets may make use of RowSetReaders to populate the RowSet
+ * with data, possibly from a non-relational database source. Disconnected
+ * RowSets may also use RowSetWriters to send data back to the underlying data
+ * store. There is considerable freedom in the way that RowSetReaders and
+ * RowSetWriters are implemented to get and store data.
+ */
+public interface RowSet extends ResultSet {
+
+ /**
+ * Registers a supplied RowSetListener with this RowSet. Once registered,
+ * the RowSetListener is notified of events generated by the RowSet.
+ *
+ * @param theListener
+ * an object which implements the <code>rowSetListener</code>
+ * interface.
+ */
+ public void addRowSetListener(RowSetListener theListener);
+
+ /**
+ * Clears the parameters previously set for this RowSet.
+ * <p>
+ * Parameter values apply to repeated use of a RowSet object. Setting a new
+ * value for a parameter clears its previous value.
+ * <code>clearParameters</code> clears the values for all parameters with
+ * one method call.
+ *
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void clearParameters() throws SQLException;
+
+ /**
+ * Fetches data for this RowSet. If successful, any existing data for the
+ * RowSet is discarded and the metadata for the rowset is set.
+ * <p>
+ * Data is retrieved connects to the database and executes a Command. This
+ * requires some or all of the following properties to be set: url, data
+ * source 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.
+ * <p>
+ * The RowSet may use a RowSetReader to access the database - in this case a
+ * reader must be registered with the RowSet and the RowSet will then invoke
+ * the <code>readData</code> method on the reader to fetch the data.
+ *
+ * @throws SQLException
+ * if a problem occurs accessing the database or if the
+ * properties needed to access the database have not been set
+ */
+ public void execute() throws SQLException;
+
+ /**
+ * Gets the RowSet's Command property.
+ *
+ * @return a string containing the RowSet's Command property - this is an
+ * SQL Query which can be executed to fetch data into the RowSet.
+ */
+ public String getCommand();
+
+ /**
+ * Gets the name of the datasource for this RowSet.
+ *
+ * @return a String containing the name of the datasource.
+ */
+ public String getDataSourceName();
+
+ /**
+ * Reports if escape processing is enabled for this RowSet.
+ * <p>
+ * If <code>true</code> (the default) the driver will automatically
+ * perform escape code processing on SQL statements prior to them being sent
+ * to the database.
+ *
+ * @return true if escape processing is enabled, false otherwise.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public boolean getEscapeProcessing() throws SQLException;
+
+ /**
+ * Gets the maximum number of bytes that can be returned for column values
+ * which are of types BINARY, VARBINARY, LONGVARBINARYBINARY, CHAR, VARCHAR,
+ * or LONGVARCHAR. Excess data is silently discarded if the number is
+ * exceeded.
+ *
+ * @return the current maximum size in bytes. 0 means no limit
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public int getMaxFieldSize() throws SQLException;
+
+ /**
+ * Gets the maximum number of rows for this RowSet. Excess rows are
+ * discarded silently if the limit is exceeded.
+ *
+ * @return the previous maximum number of rows. 0 implies no limit.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public int getMaxRows() throws SQLException;
+
+ /**
+ * Gets the value of the password property for this RowSet. This property
+ * is used when making a connection to the database and should be set before
+ * invoking the <code>execute</code> method.
+ *
+ * @return a String containing the value of the password property.
+ */
+ public String getPassword();
+
+ /**
+ * Gets the Timeout for the driver when executing a Query operation.
+ * <p>
+ * If a Query takes longer than the Timeout, an exception is thrown.
+ *
+ * @return the Timeout value in seconds.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public int getQueryTimeout() throws SQLException;
+
+ /**
+ * Gets the transaction isolation property setting for this RowSet.
+ *
+ * @return an integer holding the current transaction isolation setting. One
+ * of: one of Connection.TRANSACTION_READ_UNCOMMITTED,
+ * Connection.TRANSACTION_READ_COMMITTED,
+ * Connection.TRANSACTION_REPEATABLE_READ,
+ * Connection.TRANSACTION_SERIALIZABLE
+ */
+ public int getTransactionIsolation();
+
+ /**
+ * Gets the custom mapping of SQL types for this RowSet, if any.
+ *
+ * @return a Map holding the custom mappings of SQL types to Java classes for
+ * this RowSet. By default, the Map is empty.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public Map<String, Class<?>> getTypeMap() throws SQLException;
+
+ /**
+ * Gets the URL property value for this RowSet. If there is no DataSource
+ * object specified, the RowSet uses the URL to establish a connection to
+ * the database. The default value for the URL is null.
+ *
+ * @return a String holding the value of the URL property.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public String getUrl() throws SQLException;
+
+ /**
+ * Gets the value of the Username property for this RowSet. The Username is
+ * used when establishing a connection to the database and should be set
+ * before the <code>execute</code> method is invoked.
+ *
+ * @return a String holing the value of the Username property.
+ */
+ public String getUsername();
+
+ /**
+ * Reports if this RowSet is read only.
+ *
+ * @return true if this RowSet is read only, false if it is updateable.
+ */
+ public boolean isReadOnly();
+
+ /**
+ * Removes a specified RowSetListener object from the set of listeners which
+ * will be notified of events by this RowSet.
+ *
+ * @param theListener
+ * the RowSetListener to remove from the set of listeners for
+ * this RowSet.
+ */
+ public void removeRowSetListener(RowSetListener theListener);
+
+ /**
+ * Sets the specified ARRAY parameter in the RowSet command with the
+ * supplied java.sql.Array value.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theArray
+ * the java.sql.Array value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setArray(int parameterIndex, Array theArray)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * ASCII data in the supplied java.io.InputStream value. Data is read from
+ * the InputStream until end-of-file is reached.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theInputStream
+ * an InputStream containing the ASCII data to set into the
+ * parameter value
+ * @param length
+ * the length of the data in bytes
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setAsciiStream(int parameterIndex, InputStream theInputStream,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of the specified SQL NUMERIC parameter in the RowSet
+ * command with the data in the supplied java.math.BigDecimal value.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theBigDecimal
+ * the BigDecimal containing the value
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setBigDecimal(int parameterIndex, BigDecimal theBigDecimal)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * binary data in the supplied java.io.InputStream value. Data is read from
+ * the InputStream until end-of-file is reached.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theInputStream
+ * an InputStream containing the binary data to set into the
+ * parameter value
+ * @param length
+ * the length of the data in bytes
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setBinaryStream(int parameterIndex, InputStream theInputStream,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * value of a supplied java.sql.Blob.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theBlob
+ * the Blob value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setBlob(int parameterIndex, Blob theBlob) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to the
+ * supplied boolean.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theBoolean
+ * the boolean value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setBoolean(int parameterIndex, boolean theBoolean)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to the
+ * supplied byte value.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theByte
+ * the byte value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setByte(int parameterIndex, byte theByte) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to the
+ * supplied byte array value.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theByteArray
+ * the array of bytes to set into the parameter.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setBytes(int parameterIndex, byte[] theByteArray)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to the
+ * sequence of Unicode characters carried by the supplied java.io.Reader.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theReader
+ * the Reader which contains the Unicode data to set into the
+ * parameter
+ * @param length
+ * the length of the data in the Reader in characters
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setCharacterStream(int parameterIndex, Reader theReader,
+ int length) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * value of a supplied java.sql.Clob.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theClob
+ * the Clob value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setClob(int parameterIndex, Clob theClob) throws SQLException;
+
+ /**
+ * Sets the Command property for this RowSet - the command is an SQL Query
+ * which runs when the <code>execute</code> method is invoked. This
+ * property is optional for datasources that do not support commands.
+ *
+ * @param cmd
+ * a String containing the SQL Query. Can be null.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setCommand(String cmd) throws SQLException;
+
+ /**
+ * Sets the concurrency property of this RowSet. The default value is
+ * ResultSet.CONCUR_READ_ONLY.
+ *
+ * @param concurrency
+ * the new concurrency value - one of: ResultSet.CONCUR_READ_ONLY
+ * or ResultSet.CONCUR_UPDATABLE
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setConcurrency(int concurrency) throws SQLException;
+
+ /**
+ * Sets the Data Source Name property for the RowSet.
+ * <p>
+ * The Data Source Name can be used to find a <code>DataSource</code>
+ * which has been registered with a naming service - the DataSource can then
+ * be used to create a connection to the database.
+ *
+ * @param name
+ * a String with the new Data Source Name.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setDataSourceName(String name) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * value of a supplied java.sql.Date.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theDate
+ * the Date to use
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setDate(int parameterIndex, Date theDate) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * value of a supplied java.sql.Date, where the conversion of the Date to an
+ * SQL DATE value is calculated using a supplied Calendar.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theDate
+ * the Date to use
+ * @param theCalendar
+ * the Calendar to use in converting the Date to an SQL DATE value
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setDate(int parameterIndex, Date theDate, Calendar theCalendar)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * supplied double.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theDouble
+ * the double value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setDouble(int parameterIndex, double theDouble)
+ throws SQLException;
+
+ /**
+ * Sets the Escape Processing status for this RowSet. If escape processing
+ * is on, the driver performs escape substitution before sending an SQL
+ * command to the database. The default value for escape processing is on.
+ *
+ * @param enable
+ * true to enable Escape Processing, false to turn it off.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setEscapeProcessing(boolean enable) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * supplied float.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theFloat
+ * the float value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setFloat(int parameterIndex, float theFloat)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * supplied integer.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theInteger
+ * the integer value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setInt(int parameterIndex, int theInteger) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command with the
+ * supplied long.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theLong
+ * the long value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ 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 BINARY, VARBINARY, LONGVARBINARYBINARY, CHAR,
+ * VARCHAR, or 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
+ * means unlimited.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setMaxFieldSize(int max) throws SQLException;
+
+ /**
+ * Sets the maximum number of rows which can be held by the RowSet. Any
+ * additional rows are silently discarded.
+ *
+ * @param max
+ * the maximum number of rows which can be held in the RowSet. 0
+ * means no limit.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setMaxRows(int max) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to SQL
+ * NULL.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param sqlType
+ * the type of the parameter, as defined by java.sql.Types.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setNull(int parameterIndex, int sqlType) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to SQL
+ * NULL. This form of the <code>setNull</code> method should be used for
+ * User Defined Types and REF parameters.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param sqlType
+ * the type of the parameter, as defined by 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 REF type.
+ * Ignored if the sqlType is not a UDT or REF type.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setNull(int parameterIndex, int sqlType, String typeName)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied Java object.
+ * <p>
+ * 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
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theObject
+ * the Java object containing the data value.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setObject(int parameterIndex, Object theObject)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied Java object.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theObject
+ * the Java object containing the data value.
+ * @param targetSqlType
+ * the SQL type to send to the database, as defined in
+ * java.sql.Types.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setObject(int parameterIndex, Object theObject,
+ int targetSqlType) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied Java object.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theObject
+ * the Java object containing the data value.
+ * @param targetSqlType
+ * the SQL type to send to the database, as defined in
+ * java.sql.Types.
+ * @param scale
+ * the number of digits after the decimal point, for
+ * java.sql.Types.DECIMAL and java.sql.Types.NUMERIC types.
+ * Ignored for all other types.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setObject(int parameterIndex, Object theObject,
+ int targetSqlType, int scale) throws SQLException;
+
+ /**
+ * Sets the database Password for this RowSet.
+ *
+ * @param password
+ * a string holding the new password
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setPassword(String password) throws SQLException;
+
+ /**
+ * Sets the Timeout value for this RowSet. The timeout is the maximum time
+ * that the driver will wait while executing a command - after this time, an
+ * SQLException is thrown.
+ *
+ * @param seconds
+ * the number of seconds for the Timeout.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setQueryTimeout(int seconds) throws SQLException;
+
+ /**
+ * Sets whether the RowSet is read only or is updateable.
+ *
+ * @param readOnly
+ * true to set the RowSet to readonly state, false to allow
+ * updates.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setReadOnly(boolean readOnly) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied java.sql.Ref. This is sent to the database as an SQL REF value.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theRef
+ * the Ref value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setRef(int parameterIndex, Ref theRef) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied short integer.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theShort
+ * the short value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setShort(int parameterIndex, short theShort)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied String. The String is placed into the database as a VARCHAR or
+ * LONGVARCHAR SQL value, depending on the database limits for the length of
+ * VARCHAR values.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theString
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setString(int parameterIndex, String theString)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied java.sql.Time, converting to an SQL TIME value using the system
+ * default Calendar.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theTime
+ * the Time value to set
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setTime(int parameterIndex, Time theTime) throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied java.sql.Time, converting to an SQL TIME value using a supplied
+ * Calendar.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theTime
+ * the Time value to set
+ * @param theCalendar
+ * the Calendar to use in the conversion operation
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setTime(int parameterIndex, Time theTime, Calendar theCalendar)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied java.sql.Timestamp, converting to an SQL TIMESTAMP value using
+ * the system default Calendar.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theTimestamp
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp)
+ throws SQLException;
+
+ /**
+ * Sets the value of the specified parameter in the RowSet command to a
+ * supplied java.sql.Timestamp converting to an SQL TIMESTAMP value using a
+ * supplied Calendar.
+ *
+ * @param parameterIndex
+ * index of the parameter to set, where the first parameter has
+ * index = 1.
+ * @param theTimestamp
+ * @param theCalendar
+ * the Calendar to use in the conversion operation
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setTimestamp(int parameterIndex, Timestamp theTimestamp,
+ Calendar theCalendar) throws SQLException;
+
+ /**
+ * Updates the target instance's transaction isolation level to one of a
+ * discrete set of possible values.
+ *
+ * @param level
+ * the new transaction isolation level. One of:
+ * Connection.TRANSACTION_READ_UNCOMMITTED,
+ * Connection.TRANSACTION_READ_COMMITTED,
+ * Connection.TRANSACTION_REPEATABLE_READ, or
+ * Connection.TRANSACTION_SERIALIZABLE
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setTransactionIsolation(int level) throws SQLException;
+
+ /**
+ * Sets the type of this RowSet. By default, the type is non-scrollable.
+ *
+ * @param type
+ * the new type for the RowSet. One of:
+ * ResultSet.TYPE_FORWARD_ONLY,
+ * ResultSet.TYPE_SCROLL_INSENSITIVE, or
+ * ResultSet.TYPE_SCROLL_SENSITIVE
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setType(int type) throws SQLException;
+
+ /**
+ * Sets the Map used to map SQL User Defined Types to Java classes.
+ *
+ * @param theTypeMap
+ * a Map which defines the names of SQL UDTs and the Java classes
+ * to which they are mapped.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setTypeMap(Map<String, Class<?>> theTypeMap)
+ throws SQLException;
+
+ /**
+ * Sets the URL used by this RowSet to access the database via a
+ * <code>DriverManager</code>. The URL is optional - an alternative is to
+ * use a Data Source Name to create a connection.
+ *
+ * @param theURL
+ * a String containing the URL for the database. Can be null.
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ public void setUrl(String theURL) throws SQLException;
+
+ /**
+ * Sets the Username property for the RowSet, used to authenticate a
+ * connection to the database.
+ *
+ * @param theUsername
+ * a String containing the User Name
+ * @throws SQLException
+ * if an error occurs accessing the database.
+ */
+ 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..8682957
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetEvent.java
@@ -0,0 +1,53 @@
+/*
+ * 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 RowSet object. The
+ * events are sent to inform registered listeners that changes have occurred to
+ * the RowSet. The events covered are:
+ * <ol>
+ * <li>A single row in the RowSet changes</li>
+ * <li>The whole set of data in the RowSet changes</li>
+ * <li>The RowSet cursor position changes</li>
+ * </ol>
+ * The event contains a reference to the RowSet object which generated the
+ * message so that the listeners can extract whatever information they need from
+ * that reference.
+ *
+ */
+public class RowSetEvent extends EventObject implements Serializable {
+
+ private static final long serialVersionUID = -1875450876546332005L;
+
+ /**
+ * Creates a RowSetEvent object containing a reference to the RowSet object
+ * that generated the event. Information about the changes that have
+ * occurred to the RowSet can be extracted from the RowSet using one or more
+ * of the query methods available on the RowSet.
+ *
+ * @param theSource
+ * the RowSet which generated the event
+ */
+ 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..f224a13
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetInternal.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 javax.sql;
+
+import java.sql.SQLException;
+import java.sql.Connection;
+import java.sql.ResultSet;
+
+/**
+ * An interface provided by a RowSet object to either a RowSetReader or a
+ * RowSetWriter, providing facilities to read and update the internal state of
+ * the RowSet.
+ */
+public interface RowSetInternal {
+
+ /**
+ * Gets the Connection associated with this RowSet object.
+ *
+ * @return the Connection
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public Connection getConnection() throws SQLException;
+
+ /**
+ * Gets the ResultSet that was the original (unmodified) content of the
+ * RowSet.
+ * <p>
+ * The ResultSet cursor is positioned before the first row of data
+ *
+ * @return the ResultSet that contained the original data value of the
+ * RowSet
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ 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 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 first, after last or
+ * pointing to the insert row).
+ */
+ public ResultSet getOriginalRow() throws SQLException;
+
+ /**
+ * Gets the parameter values that have been set for this RowSet's command.
+ *
+ * @return an Object array containing the values of parameters that have
+ * been set.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ public Object[] getParams() throws SQLException;
+
+ /**
+ * Sets RowSetMetaData for this RowSet. The RowSetMetaData is used by a
+ * RowSetReader to set values giving information about the RowSet's columns.
+ *
+ * @param theMetaData
+ * a RowSetMetaData holding the metadata about the RowSet's
+ * columns.
+ * @throws SQLException
+ * if there is a problem accessing the database.
+ */
+ 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..a482d2b
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetListener.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.util.EventListener;
+
+/**
+ * An interface used to send notification of events occurring in a RowSet. To
+ * receive the notification events, an object must implement the RowSetListener
+ * interface and then register itself with the RowSet of interest using the
+ * <code>RowSet.addRowSetListener</code> method.
+ */
+public interface RowSetListener extends EventListener {
+
+ /**
+ * Notifies the listener that one of the RowSet's rows has changed.
+ *
+ * @param theEvent
+ * a RowSetEvent that contains information about the RowSet
+ * involved. This information can be used to retrieve information
+ * about the change, such as the new cursor position.
+ */
+ public void cursorMoved(RowSetEvent theEvent);
+
+ /**
+ * Notifies the listener that the RowSet's cursor has moved.
+ *
+ * @param theEvent
+ * theEvent a RowSetEvent that contains information about the
+ * RowSet involved. This information can be used to retrieve
+ * information about the change, such as the updated data values.
+ */
+ public void rowChanged(RowSetEvent theEvent);
+
+ /**
+ * Notifies the listener that the RowSet's entire contents have been updated
+ * (an example is the execution of a command which retrieves new data from
+ * the database).
+ *
+ * @param theEvent
+ * theEvent a RowSetEvent that contains information about the
+ * RowSet involved. This information can be used to retrieve
+ * information about the change, such as the updated rows of
+ * data.
+ */
+ 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..89d6f7f
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetMetaData.java
@@ -0,0 +1,283 @@
+/*
+ * 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 RowSet.
+ * <p>
+ * RowSetMetaData extends ResultSetMetaData, adding new operations for carrying
+ * out value sets.
+ * <p>
+ * Application code would not normally call this interface directly. It would be
+ * called internally when <code>RowSet.execute</code> is called.
+ */
+public interface RowSetMetaData extends ResultSetMetaData {
+
+ /**
+ * Sets automatic numbering for a specified column in the RowSet. If
+ * automatic numbering is on, the column is read only. The default value is
+ * for automatic numbering to be off.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param autoIncrement
+ * true to set automatic numbering on, false to turn it off.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setAutoIncrement(int columnIndex, boolean autoIncrement)
+ throws SQLException;
+
+ /**
+ * Sets the case sensitive property for a specified column in the RowSet.
+ * The default is that the column is not case sensitive.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param caseSensitive
+ * true to make the column case sensitive, false to make it not
+ * case sensitive.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setCaseSensitive(int columnIndex, boolean caseSensitive)
+ throws SQLException;
+
+ /**
+ * Sets the Catalog Name for a specified column in the RowSet.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param catalogName
+ * a string containing the new Catalog Name
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setCatalogName(int columnIndex, String catalogName)
+ throws SQLException;
+
+ /**
+ * Sets the number of columns in the Row Set.
+ *
+ * @param columnCount
+ * an integer containing the number of columns in the RowSet.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setColumnCount(int columnCount) throws SQLException;
+
+ /**
+ * Sets the normal maximum width in characters for a specified column in the
+ * RowSet.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param displaySize
+ * an integer with the normal maximum column width in characters
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setColumnDisplaySize(int columnIndex, int displaySize)
+ throws SQLException;
+
+ /**
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param theLabel
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setColumnLabel(int columnIndex, String theLabel)
+ throws SQLException;
+
+ /**
+ * Sets the suggested column label for a specified column in the RowSet.
+ * This label is typically used in displaying or printing the column.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param theColumnName
+ * a string containing the column label
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setColumnName(int columnIndex, String theColumnName)
+ throws SQLException;
+
+ /**
+ * Sets the SQL type for a specified column in the RowSet
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param theSQLType
+ * an integer containing the SQL Type, as defined by
+ * java.sql.Types.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setColumnType(int columnIndex, int theSQLType)
+ throws SQLException;
+
+ /**
+ * Sets the Type Name for a specified column in the RowSet, where the data
+ * type is specific to the datasource.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param theTypeName
+ * a string containing the Type Name for the column
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setColumnTypeName(int columnIndex, String theTypeName)
+ throws SQLException;
+
+ /**
+ * Sets whether a specified column is a currency value.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param isCurrency
+ * true if the column should be treated as a currency value,
+ * false if it should not be treated as a currency value.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setCurrency(int columnIndex, boolean isCurrency)
+ throws SQLException;
+
+ /**
+ * Sets whether a specified column can contain SQL NULL values.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param nullability
+ * an integer which is one of the following values:
+ * ResultSetMetaData.columnNoNulls,
+ * ResultSetMetaData.columnNullable, or
+ * ResultSetMetaData.columnNullableUnknown
+ * <p>
+ * The default value is ResultSetMetaData.columnNullableUnknown
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setNullable(int columnIndex, int nullability)
+ throws SQLException;
+
+ /**
+ * Sets the number of decimal digits for a specified column in the RowSet.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param thePrecision
+ * an integer containing the number of decimal digits
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setPrecision(int columnIndex, int thePrecision)
+ throws SQLException;
+
+ /**
+ * For the column specified by <code>columnIndex</code> declares how many
+ * digits there should be after a decimal point.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param theScale
+ * an integer containing the number of digits after the decimal
+ * point
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setScale(int columnIndex, int theScale) throws SQLException;
+
+ /**
+ * Sets the Schema Name for a specified column in the RowSet
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param theSchemaName
+ * a String containing the schema name
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setSchemaName(int columnIndex, String theSchemaName)
+ throws SQLException;
+
+ /**
+ * Sets whether a specified column can be used in a search involving a WHERE
+ * clause. The default value is false.
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param isSearchable
+ * true of the column can be used in a WHERE clause search, false
+ * otherwise.
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ 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, where the first column has
+ * index 1.
+ * @param isSigned
+ * true if the column can contain signed numbers, false otherwise
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ public void setSigned(int columnIndex, boolean isSigned)
+ throws SQLException;
+
+ /**
+ * Sets the Table Name for a specified column in the RowSet
+ *
+ * @param columnIndex
+ * the index number for the column, where the first column has
+ * index 1.
+ * @param theTableName
+ * a String containing the Table Name for the column
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ 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..bc17ded
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetReader.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 javax.sql;
+
+import java.sql.SQLException;
+
+/**
+ * An interface which provides functionality for a disconnected RowSet to get
+ * data from a data source into its rows. The RowSet calls the RowSetReader
+ * interface when the RowSet's execute method is invoked - a RowSetReader must
+ * first be registered with the RowSet for this to work.
+ */
+public interface RowSetReader {
+
+ /**
+ * Reads new data into the RowSet. The calling RowSet object must itself
+ * implement the RowSetInternal interface and the RowSetReader must be
+ * registered as a Reader on the RowSet.
+ * <p>
+ * This method adds rows into the calling RowSet. The Reader may invoke any
+ * of the RowSet's methods except for the <code>execute</code> method
+ * (calling execute will cause an SQLException to be thrown). However, when
+ * the Reader calls the RowSet's methods, no events are sent to listeners -
+ * any listeners are informed by the calling RowSet's execute method once
+ * the Reader returns from the readData method.
+ *
+ * @param theCaller
+ * must be the calling RowSet object, which must have implemented
+ * the RowSetInternal interface.
+ * @throws SQLException
+ * if a problem occurs accessing the database or if the Reader
+ * calls the RowSet.execute method.
+ */
+ 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..ba95f59
--- /dev/null
+++ b/sql/src/main/java/javax/sql/RowSetWriter.java
@@ -0,0 +1,52 @@
+/*
+ * 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 RowSet to put
+ * data updates back to the data source from which the RowSet was originally
+ * populated. An object implementing this interface is called a Writer.
+ * <p>
+ * The Writer must establish a connection to the RowSet's data source before
+ * writing the data. The RowSet calling this interface must implement the
+ * RowSetInternal interface.
+ * <p>
+ * The Writer may encounter a situation where the updated data being written
+ * back to the data source has already been updated in the data source. How a
+ * conflict of this kind is handled is determined by the implementation of the
+ * Writer.
+ */
+public interface RowSetWriter {
+
+ /**
+ * Writes changes in the RowSet associated with this RowSetWriter back to
+ * its data source.
+ *
+ * @param theRowSet
+ * the RowSet object. This RowSet must a) Implement the
+ * RowSetInternal interface and b) have have this RowSetWriter
+ * registered with it and c) must call this method internally
+ * @return true if the modified data was written, false otherwise (which
+ * typically implies some form of conflict)
+ * @throws SQLException
+ * if a problem occurs accessing the database
+ */
+ 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..c5d5aee
--- /dev/null
+++ b/sql/src/main/java/javax/sql/package.html
@@ -0,0 +1,8 @@
+<html>
+ <body>
+ <p>
+ Provides extensions to the standard interface for accessing SQL-based
+ databases.
+ <p>
+ </body>
+</html> \ 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..77b669b
--- /dev/null
+++ b/sql/src/main/java/org/apache/harmony/sql/internal/nls/Messages.java
@@ -0,0 +1,124 @@
+/*
+ * 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.
+ */
+
+package org.apache.harmony.sql.internal.nls;
+
+import org.apache.harmony.luni.util.MsgHelp;
+
+/**
+ * This class retrieves strings from a resource bundle and returns them,
+ * formatting them with MessageFormat when required.
+ * <p>
+ * It is used by the system classes to provide national language support, by
+ * looking up messages in the <code>
+ * org.apache.harmony.sql.internal.nls.messages
+ * </code>
+ * 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 <em>KEY</em>
+ * should a reasonable human-readable (english) string.
+ *
+ */
+public class Messages {
+
+ private static final String sResource =
+ "org.apache.harmony.sql.internal.nls.messages"; //$NON-NLS-1$
+
+ /**
+ * 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) {
+ return MsgHelp.getString(sResource, msg);
+ }
+
+ /**
+ * 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) {
+ return MsgHelp.getString(sResource, msg, args);
+ }
+}
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 <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#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, "<init>", "([B)V");
+ M_java_lang_String_initBytes2 =
+ (*env)->GetMethodID(env, C_java_lang_String, "<init>",
+ "([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 <jni.h>
+/* 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/SQLite/JDBCDriverTest.java b/sql/src/test/java/SQLite/JDBCDriverTest.java
new file mode 100644
index 0000000..cc4d769
--- /dev/null
+++ b/sql/src/test/java/SQLite/JDBCDriverTest.java
@@ -0,0 +1,86 @@
+/*
+ * 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 SQLite;
+
+import tests.sql.AbstractSqlTest;
+
+import java.io.File;
+import java.sql.Connection;
+import java.sql.SQLException;
+
+
+
+/**
+ * Tests the SQLite.JDBCDriver.
+ */
+public class JDBCDriverTest extends AbstractSqlTest {
+
+
+
+ /**
+ * The SQLite db file.
+ */
+ private final File dbFile = new File("sqliteTest.db");
+
+ private final String connectionURL = "jdbc:sqlite:/" + dbFile.getName();
+
+ /**
+ * Creates a new instance of this class.
+ */
+ public JDBCDriverTest(String testName) {
+ super(testName);
+ }
+
+ /**
+ * Sets up an unit test by loading the SQLite.JDBCDriver, getting two
+ * connections and calling the setUp method of the super class.
+ */
+ @Override
+ protected void setUp() throws ClassNotFoundException, SQLException,
+ java.lang.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() {
+ return connectionURL;
+ }
+
+ @Override
+ protected String getDriverClassName() {
+ return "SQLite.JDBCDriver";
+ }
+
+ @Override
+ protected int getTransactionIsolation() {
+ return Connection.TRANSACTION_SERIALIZABLE;
+ }
+}
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..6dc7c84
--- /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 = new TestSuite("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..241888a
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.java
@@ -0,0 +1,384 @@
+/*
+ * 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.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;
+
+public class BatchUpdateExceptionTest extends TestCase {
+
+ /*
+ * ConstructorTest
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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.
+ */
+ public void testSerializationSelf() throws Exception {
+ BatchUpdateException object = new BatchUpdateException();
+ SerializationTest.verifySelf(object, BATCHUPDATEEXCEPTION_COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ 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..22409f7
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ConnectionTest.java
@@ -0,0 +1,89 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+public class ConnectionTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ public void testPublicStatics() {
+
+ HashMap<String, Integer> thePublicStatics = new HashMap<String, Integer>();
+ 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..624da41
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.java
@@ -0,0 +1,501 @@
+/*
+ * 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.Serializable;
+import java.sql.DataTruncation;
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import org.apache.harmony.testframework.serialization.SerializationTest.SerializableAssert;
+
+import junit.framework.TestCase;
+
+public class DataTruncationTest extends TestCase {
+
+ /*
+ * ConstructorTest
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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.
+ */
+ 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.
+ */
+ 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..c970c70
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DatabaseMetaDataTest.java
@@ -0,0 +1,119 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+public class DatabaseMetaDataTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ public void testPublicStatics() {
+
+ HashMap<String, Number> thePublicStatics = new HashMap<String, Number>();
+ 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..903b77f
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DateTest.java
@@ -0,0 +1,380 @@
+/*
+ * 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.Date;
+import java.util.Calendar;
+import java.util.TimeZone;
+
+import junit.framework.TestCase;
+
+/**
+ * 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
+ */
+ @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
+ */
+ 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
+ */
+ @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
+ */
+ @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
+ */
+ @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
+ */
+ @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
+ */
+ @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
+ */
+ @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.
+ */
+ 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.
+ */
+ 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
+ */
+ 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 )
+ */
+ 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..73b415b
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverManagerTest.java
@@ -0,0 +1,582 @@
+/*
+ * 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.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;
+
+/**
+ * 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
+ */
+ public void testDeregisterDriver() throws SQLException {
+ // 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 };
+ theMethod.invoke(null, args);
+ } catch (Exception e) {
+ System.out
+ .println("testDeregisterDriver: Got exception allocating TestHelper");
+ 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 };
+
+ 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)
+ */
+ 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)
+ */
+ 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)
+ */
+ 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";
+
+ 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()
+
+ public void testGetDrivers() {
+ // Load a driver manager
+ Enumeration<Driver> 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;
+
+ public void testGetLoginTimeout() {
+ DriverManager.setLoginTimeout(timeout1);
+ assertEquals(timeout1, DriverManager.getLoginTimeout());
+ } // end method testGetLoginTimeout()
+
+ @SuppressWarnings("deprecation")
+ public void testGetLogStream() {
+ assertNull(DriverManager.getLogStream());
+
+ DriverManager.setLogStream(testPrintStream);
+ assertTrue(DriverManager.getLogStream() == testPrintStream);
+
+ DriverManager.setLogStream(null);
+ } // end method testGetLogStream()
+
+ 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";
+
+ @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()
+
+ 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;
+
+ 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);
+
+ @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
+ */
+ 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..ec38988
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/DriverPropertyInfoTest.java
@@ -0,0 +1,107 @@
+/*
+ * 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.DriverPropertyInfo;
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+/**
+ * JUnit Testcase for the java.sql.DriverPropertyInfo class
+ *
+ */
+
+public class DriverPropertyInfoTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ public void testPublicStatics() {
+
+ } // end method testPublicStatics
+
+ /*
+ * Constructor test
+ */
+ public void testDriverPropertyInfoStringString() {
+
+ DriverPropertyInfo aDriverPropertyInfo = new DriverPropertyInfo(
+ validName, validValue);
+
+ assertNotNull(aDriverPropertyInfo);
+
+ aDriverPropertyInfo = new DriverPropertyInfo(null, null);
+
+ } // 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";
+
+ 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);
+
+ } // 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..d3e000d
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ParameterMetaDataTest.java
@@ -0,0 +1,94 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+public class ParameterMetaDataTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ public void testPublicStatics() {
+
+ HashMap<String, Integer> thePublicStatics = new HashMap<String, Integer>();
+ 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..07a25c2
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetMetaDataTest.java
@@ -0,0 +1,84 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+public class ResultSetMetaDataTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ public void testPublicStatics() {
+
+ HashMap<String, Integer> thePublicStatics = new HashMap<String, Integer>();
+ 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..26e61fe
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/ResultSetTest.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 java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+public class ResultSetTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ public void testPublicStatics() {
+
+ HashMap<String, Integer> thePublicStatics = new HashMap<String, Integer>();
+ 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..bb73343
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.java
@@ -0,0 +1,541 @@
+/*
+ * 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.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;
+
+public class SQLExceptionTest extends TestCase {
+
+ static long theFixedSUID = 2135244094396331484L;
+
+ /*
+ * SUID test
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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.
+ */
+ public void testSerializationSelf() throws Exception {
+ SQLException object = new SQLException();
+ SerializationTest.verifySelf(object, SQLEXCEPTION_COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ 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)
+ */
+ 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..0cf1d45
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLPermissionTest.java
@@ -0,0 +1,74 @@
+/*
+ * 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.SQLPermission;
+
+import junit.framework.TestCase;
+
+/**
+ * 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
+ */
+ 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
+ */
+ 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..d0998ce
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.java
@@ -0,0 +1,398 @@
+/*
+ * 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.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;
+
+public class SQLWarningTest extends TestCase {
+
+ /*
+ * ConstructorTest
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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)
+ */
+ 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.
+ */
+ public void testSerializationSelf() throws Exception {
+ SQLWarning object = new SQLWarning();
+ SerializationTest.verifySelf(object, SQLWARNING_COMPARATOR);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ 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..d0febeb
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/StatementTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+public class StatementTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ public void testPublicStatics() {
+
+ HashMap<String, Integer> thePublicStatics = new HashMap<String, Integer>();
+ 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
+ * <p>
+ * 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<String, Class<?>> 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<String, Class<?>> 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..299c33a
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TestHelper_DriverManager.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 java.sql.Driver;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+
+import junit.framework.TestCase;
+
+/**
+ * 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;
+ // System.out.println("TestHelper_DriverManager: Test Driver set!");
+
+ theHelper.checkDeregister();
+ } // end method setDriver( Driver )
+
+ public void checkDeregister() {
+
+ String baseURL = "jdbc:mikes1";
+
+ // System.out.println("Calling checkDeregister in
+ // TestHelper_DriverManager....");
+
+ Driver aDriver;
+
+ // System.out.println("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..a523b39
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimeTest.java
@@ -0,0 +1,304 @@
+/*
+ * 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.Time;
+import java.util.TimeZone;
+
+import junit.framework.TestCase;
+
+/**
+ * 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")
+ public void testTimeintintint() {
+ Time theTime = new Time(10, 45, 20);
+
+ // The date should have been created
+ assertNotNull(theTime);
+ } // end method testTimeintintint()
+
+ public void testTime() {
+ Time theTime = new Time(TIME_TEST1);
+
+ // The date should have been created
+ assertNotNull(theTime);
+ } // end method testTime()
+
+ 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
+ */
+ 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
+
+ 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()
+
+ @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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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")
+ 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 )
+ */
+ 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..7c5d7ab
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TimestampTest.java
@@ -0,0 +1,624 @@
+/*
+ * 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.Timestamp;
+import java.util.Date;
+import java.util.TimeZone;
+
+import org.apache.harmony.testframework.serialization.SerializationTest;
+import junit.framework.TestCase;
+
+/**
+ * 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
+ */
+ public void testTimestamplong() {
+ Timestamp theTimestamp = new Timestamp(TIME_TEST1);
+
+ // The Timestamp should have been created
+ assertNotNull(theTimestamp);
+ } // end method testTimestamplong
+
+ /*
+ * Constructor test
+ */
+ @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
+ */
+ 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
+ */
+ 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
+ */
+ @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
+ */
+ @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
+ */
+ @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
+ */
+ @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
+ */
+ @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
+ */
+ @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";
+
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ @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)
+ */
+ 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.
+ */
+ public void testSerializationSelf() throws Exception {
+ Timestamp object = new Timestamp(100L);
+ SerializationTest.verifySelf(object);
+ }
+
+ /**
+ * @tests serialization/deserialization compatibility with RI.
+ */
+ public void testSerializationCompatibility() throws Exception {
+ Timestamp object = new Timestamp(100L);
+ SerializationTest.verifyGolden(this, object);
+ }
+
+ /**
+ * @tests java.sql.Timestamp#toString()
+ */
+ 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..5ee8860
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/java/sql/TypesTest.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 java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashMap;
+
+import junit.framework.TestCase;
+
+public class TypesTest extends TestCase {
+
+ /*
+ * Public statics test
+ */
+ public void testPublicStatics() {
+
+ HashMap<String, Integer> thePublicStatics = new HashMap<String, Integer>();
+ 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..f1553f2
--- /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 = new TestSuite("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..a5d7617
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.java
@@ -0,0 +1,57 @@
+/*
+ * 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.SQLException;
+import javax.sql.ConnectionEvent;
+import junit.framework.TestCase;
+
+public class ConnectionEventTest extends TestCase {
+
+ 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());
+ }
+
+ 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());
+ }
+}
+
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<String, Class<?>> 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<String, Class<?>> 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<String, Class<?>> map) throws SQLException {
+ return null;
+ }
+
+ public Object getObject(int columnIndex) throws SQLException {
+ return null;
+ }
+
+ public Object getObject(String columnName, Map<String, Class<?>> 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..e78280b
--- /dev/null
+++ b/sql/src/test/java/org/apache/harmony/sql/tests/javax/sql/RowSetEventTest.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.javax.sql;
+
+import javax.sql.RowSetEvent;
+import junit.framework.TestCase;
+
+public class RowSetEventTest extends TestCase {
+
+ 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/java/sql/AllTests.java b/sql/src/test/java/tests/java/sql/AllTests.java
new file mode 100644
index 0000000..8ee9e9a
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/AllTests.java
@@ -0,0 +1,48 @@
+/*
+ * 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 = new TestSuite("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(InsertFunctionalityTest.suite());
+
+ // $JUnit-END$
+ return suite;
+ }
+}
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..42ae249
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/DatabaseMetaDataTest.java
@@ -0,0 +1,2191 @@
+/*
+ * 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 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.sql.Types;
+import java.util.Arrays;
+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;
+
+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;
+
+ private static Connection conn;
+
+ private static DatabaseMetaData meta;
+
+ private static Statement statement;
+
+ private static Statement statementForward;
+
+ private static int id = 1;
+
+ public static Test suite() {
+ TestSetup setup = new TestSetup(new TestSuite(
+ DatabaseMetaDataTest.class)) {
+ protected void setUp() throws Exception {
+ Support_SQL.loadDriver();
+ try {
+ conn = Support_SQL.getConnection();
+ statement = conn.createStatement();
+ statementForward = conn.createStatement(
+ ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_UPDATABLE);
+ meta = conn.getMetaData();
+ createTestTables();
+ } catch (SQLException e) {
+ fail("Unexpected SQLException " + e.toString());
+ }
+ }
+
+ protected void tearDown() throws Exception {
+ deleteTestTables();
+ statement.close();
+ statementForward.close();
+ conn.close();
+ }
+
+ 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);
+ } 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());
+ }
+ }
+ };
+ return setup;
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#allProceduresAreCallable()
+ */
+ public void test_allProceduresAreCallable() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#allTablesAreSelectable()
+ *
+ * // TODO GRANT and REVOKE are not supported
+ */
+/* 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()
+ */
+ public void test_dataDefinitionCausesTransactionCommit()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#dataDefinitionIgnoredInTransactions()
+ */
+ public void test_dataDefinitionIgnoredInTransactions() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#deletesAreDetected(int)
+ */
+ public void test_deletesAreDetectedI() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#doesMaxRowSizeIncludeBlobs()
+ */
+ public void test_doesMaxRowSizeIncludeBlobs() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getAttributes(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void test_getAttributesLjava_lang_StringLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getBestRowIdentifier(java.lang.String,
+ * java.lang.String, java.lang.String, int, boolean)
+ */
+ 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 do 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", "id", 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getCatalogSeparator()
+ */
+ public void test_getCatalogSeparator() throws SQLException {
+ assertTrue("Incorrect catalog separator", "".equals(meta
+ .getCatalogSeparator().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getCatalogTerm()
+ */
+ public void test_getCatalogTerm() throws SQLException {
+ assertTrue("Incorrect catalog term", "".equals(meta
+ .getCatalogSeparator().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getCatalogs()
+ */
+ public void test_getCatalogs() throws SQLException {
+ ResultSet rs = meta.getCatalogs();
+ // TODO 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 #getColumnPrivileges(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ *
+ * TODO GRANT is not supported
+ */
+/* 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 java.sql.DatabaseMetaData#getConnection()
+ */
+ public void test_getConnection() throws SQLException {
+ assertEquals("Incorrect connection value", conn, meta.getConnection());
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getCrossReference(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDatabaseMajorVersion()
+ */
+ public void test_getDatabaseMajorVersion() throws SQLException {
+ assertTrue("Incorrdct database major version", meta
+ .getDatabaseMajorVersion() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDatabaseMinorVersion()
+ */
+ public void test_getDatabaseMinorVersion() throws SQLException {
+ assertTrue("Incorrect database minor version", meta
+ .getDatabaseMinorVersion() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDatabaseProductName()
+ */
+ public void test_getDatabaseProductName() throws SQLException {
+ assertTrue("Incorrect database product name", !"".equals(meta
+ .getDatabaseProductName().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDatabaseProductVersion()
+ */
+ public void test_getDatabaseProductVersion() throws SQLException {
+ assertTrue("Incorrect database product version", !"".equals(meta
+ .getDatabaseProductVersion().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDefaultTransactionIsolation()
+ */
+ 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");
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDriverMajorVersion()
+ */
+ public void test_getDriverMajorVersion() {
+ assertTrue("Incorrect driver major version", meta
+ .getDriverMajorVersion() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDriverMinorVersion()
+ */
+ public void test_getDriverMinorVersion() {
+ assertTrue("Incorrect driver minor version", meta
+ .getDriverMinorVersion() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDriverName()
+ */
+ public void test_getDriverName() throws SQLException {
+ assertTrue("Incorrect driver name", !"".equals(meta.getDriverName()
+ .trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getDriverVersion()
+ */
+ public void test_getDriverVersion() throws SQLException {
+ assertTrue("Incorrect driver version", !"".equals(meta
+ .getDriverVersion().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getExportedKeys(java.lang.String,
+ * java.lang.String, java.lang.String)
+ *
+ * TODO getCatalog is not supported
+ */
+/* 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#getExtraNameCharacters()
+ */
+ public void test_getExtraNameCharacters() throws SQLException {
+ assertNotNull("Incorrect extra name characters", meta
+ .getExtraNameCharacters());
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getIdentifierQuoteString()
+ */
+ public void test_getIdentifierQuoteString() throws SQLException {
+ assertTrue("Incorrect identifier of quoted string", !"".equals(meta
+ .getIdentifierQuoteString().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getImportedKeys(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getIndexInfo(java.lang.String,
+ * java.lang.String, java.lang.String, boolean, boolean)
+ *
+ * TODO getCatalog is not supported
+ */
+/* 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 java.sql.DatabaseMetaData#getJDBCMajorVersion()
+ */
+ public void test_getJDBCMajorVersion() throws SQLException {
+ assertTrue("Incorrect JDBC major version",
+ meta.getJDBCMajorVersion() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getJDBCMinorVersion()
+ */
+ public void test_getJDBCMinorVersion() throws SQLException {
+ assertTrue("Incorrect JDBC minor version",
+ meta.getJDBCMinorVersion() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxBinaryLiteralLength()
+ */
+ public void test_getMaxBinaryLiteralLength() throws SQLException {
+ assertTrue("Incorrect binary literal length", meta
+ .getMaxBinaryLiteralLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxCatalogNameLength()
+ */
+ public void test_getMaxCatalogNameLength() throws SQLException {
+ assertTrue("Incorrect name length", meta.getMaxCatalogNameLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxCharLiteralLength()
+ */
+ public void test_getMaxCharLiteralLength() throws SQLException {
+ assertTrue("Incorrect char literal length", meta
+ .getMaxCharLiteralLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnNameLength()
+ */
+ public void test_getMaxColumnNameLength() throws SQLException {
+ assertTrue("Incorrect column name length", meta
+ .getMaxColumnNameLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInGroupBy()
+ */
+ public void test_getMaxColumnsInGroupBy() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInGroupBy() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInIndex()
+ */
+ public void test_getMaxColumnsInIndex() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInIndex() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInOrderBy()
+ */
+ public void test_getMaxColumnsInOrderBy() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInOrderBy() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInSelect()
+ */
+ public void test_getMaxColumnsInSelect() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInSelect() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxColumnsInTable()
+ */
+ public void test_getMaxColumnsInTable() throws SQLException {
+ assertTrue("Incorrect number of columns",
+ meta.getMaxColumnsInTable() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxConnections()
+ */
+ public void test_getMaxConnections() throws SQLException {
+ assertTrue("Incorrect number of connections",
+ meta.getMaxConnections() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxCursorNameLength()
+ */
+ 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#getMaxIndexLength()
+ */
+ public void test_getMaxIndexLength() throws SQLException {
+ assertTrue("Incorrect length of index", meta.getMaxIndexLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxProcedureNameLength()
+ */
+ public void test_getMaxProcedureNameLength() throws SQLException {
+ assertTrue("Incorrect length of procedure name", meta
+ .getMaxProcedureNameLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxRowSize()
+ */
+ public void test_getMaxRowSize() throws SQLException {
+ assertTrue("Incorrect size of row", meta.getMaxRowSize() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxSchemaNameLength()
+ */
+ public void test_getMaxSchemaNameLength() throws SQLException {
+ assertTrue("Incorrect length of schema name", meta
+ .getMaxSchemaNameLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxStatementLength()
+ */
+ public void test_getMaxStatementLength() throws SQLException {
+ assertTrue("Incorrect length of statement", meta
+ .getMaxStatementLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxStatements()
+ */
+ public void test_getMaxStatements() throws SQLException {
+ assertTrue("Incorrect number of statements",
+ meta.getMaxStatements() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxTableNameLength()
+ */
+ public void test_getMaxTableNameLength() throws SQLException {
+ assertTrue("Incorrect length of table name", meta
+ .getMaxTableNameLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxTablesInSelect()
+ */
+ public void test_getMaxTablesInSelect() throws SQLException {
+ assertTrue("Incorrect number of tables",
+ meta.getMaxTablesInSelect() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getMaxUserNameLength()
+ */
+ public void test_getMaxUserNameLength() throws SQLException {
+ assertTrue("Incorrect length of user name",
+ meta.getMaxUserNameLength() >= 0);
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getNumericFunctions()
+ */
+ public void test_getNumericFunctions() throws SQLException {
+ assertTrue("Incorrect list of math functions", "".equals(meta
+ .getNumericFunctions().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getPrimaryKeys(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ 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 do 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getProcedureColumns(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String)
+ */
+ public void test_getProcedureColumnsLjava_lang_StringLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getProcedureTerm()
+ */
+ public void test_getProcedureTerm() throws SQLException {
+ assertTrue("Incorrect procedure term", "".equals(meta
+ .getProcedureTerm().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getProcedures(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ public void test_getProceduresLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getResultSetHoldability()
+ */
+ 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));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSQLKeywords()
+ */
+ public void test_getSQLKeywords() throws SQLException {
+ assertTrue("Incorrect SQL keywords", !"".equals(meta.getSQLKeywords()
+ .trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSQLStateType()
+ */
+ 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");
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSchemaTerm()
+ */
+ public void test_getSchemaTerm() throws SQLException {
+ assertNotNull("Incorrect schema term", meta.getSchemaTerm());
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSchemas()
+ */
+ 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSearchStringEscape()
+ */
+ public void test_getSearchStringEscape() throws SQLException {
+ assertTrue("Incorrect search string escape", !"".equals(meta
+ .getSearchStringEscape().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getStringFunctions()
+ */
+ public void test_getStringFunctions() throws SQLException {
+ assertTrue("Incorrect string functions", "".equals(meta
+ .getStringFunctions().trim()));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getSuperTables(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ public void test_getSuperTablesLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getSuperTypes(java.lang.String,
+ * java.lang.String, java.lang.String)
+ */
+ public void test_getSuperTypesLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getSystemFunctions()
+ */
+ public void test_getSystemFunctions() throws SQLException {
+ assertTrue("No system function exist", meta.getSystemFunctions()
+ .trim().equals(""));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getTablePrivileges(java.lang.String,
+ * java.lang.String, java.lang.String)
+ *
+ * TODO GRANT is not supported
+ */
+/* 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<String> expectedPrivs = new HashSet<String>();
+ 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<String>();
+ 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#getTableTypes()
+ */
+ 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getTables(java.lang.String,
+ * java.lang.String, java.lang.String, java.lang.String[])
+ */
+ 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" };
+
+ // 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);
+ // 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();
+
+ // 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"));
+ 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getTimeDateFunctions()
+ */
+ public void test_getTimeDateFunctions() throws SQLException {
+ assertFalse("No time and data functions exist", !meta
+ .getTimeDateFunctions().trim().equals(""));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getTypeInfo()
+ */
+ 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData #getUDTs(java.lang.String,
+ * java.lang.String, java.lang.String, int[])
+ */
+ public void test_getUDTsLjava_lang_StringLjava_lang_StringLjava_lang_String$I()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getURL()
+ */
+ public void test_getURL() throws SQLException {
+ assertEquals("Wrong url", Support_SQL.sqlUrl, meta.getURL());
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#getUserName()
+ *
+ * TODO not supported
+ */
+/* public void test_getUserName() throws SQLException {
+ assertEquals("Wrong user name", Support_SQL.sqlLogin + "@"
+ + Support_SQL.sqlHost, meta.getUserName());
+ }
+*/
+ /**
+ * @tests java.sql.DatabaseMetaData #getVersionColumns(java.lang.String,
+ * java.lang.String, java.lang.String)
+ *
+ * TODO trigger is not supported
+ */
+/* public void test_getVersionColumnsLjava_lang_StringLjava_lang_StringLjava_lang_String()
+ throws SQLException {
+ 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#insertsAreDetected(int)
+ */
+ 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));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#isCatalogAtStart()
+ */
+ public void test_isCatalogAtStart() throws SQLException {
+ assertFalse(
+ "catalog doesn't appear at the start of a fully qualified table name",
+ meta.isCatalogAtStart());
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#isReadOnly()
+ */
+ public void test_isReadOnly() throws SQLException {
+ assertFalse("database is not read-only", meta.isReadOnly());
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#locatorsUpdateCopy()
+ */
+ public void test_locatorsUpdateCopy() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullPlusNonNullIsNull()
+ */
+ public void test_nullPlusNonNullIsNull() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullsAreSortedAtEnd()
+ */
+ public void test_nullsAreSortedAtEnd() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullsAreSortedAtStart()
+ */
+ public void test_nullsAreSortedAtStart() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullsAreSortedHigh()
+ */
+ public void test_nullsAreSortedHigh() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#nullsAreSortedLow()
+ */
+ public void test_nullsAreSortedLow() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#othersDeletesAreVisible(int)
+ */
+ 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));
+ assertFalse("deletes made by others are visible for unknown type", meta
+ .othersDeletesAreVisible(100));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#othersInsertsAreVisible(int)
+ */
+ 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));
+ assertFalse("inserts made by others are visible for unknown type", meta
+ .othersInsertsAreVisible(100));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#othersUpdatesAreVisible(int)
+ */
+ 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));
+ assertFalse("updates made by others are visible for unknown type", meta
+ .othersUpdatesAreVisible(100));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#ownDeletesAreVisible(int)
+ */
+ public void test_ownDeletesAreVisibleI() throws SQLException {
+ // TODO 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)
+ */
+ 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 java.sql.DatabaseMetaData#ownUpdatesAreVisible(int)
+ */
+ public void test_ownUpdatesAreVisibleI() throws SQLException {
+ // TODO 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()
+ */
+ public void test_storesLowerCaseIdentifiers() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesLowerCaseQuotedIdentifiers()
+ */
+ public void test_storesLowerCaseQuotedIdentifiers() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesMixedCaseIdentifiers()
+ */
+ public void test_storesMixedCaseIdentifiers() throws SQLException {
+ insertNewRecord();
+
+ String selectQuery = "SELECT fieLD1 FROM "
+ + DatabaseCreator.TEST_TABLE1;
+
+ try {
+ statement.executeQuery(selectQuery);
+ if (!meta.storesMixedCaseQuotedIdentifiers()) {
+ fail("mixed case are supported");
+ }
+ } catch (SQLException e) {
+ if (meta.storesMixedCaseQuotedIdentifiers()) {
+ fail("mixed case are not supported");
+ }
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesMixedCaseQuotedIdentifiers()
+ */
+ 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.storesMixedCaseQuotedIdentifiers()) {
+ fail("mixed case is supported");
+ }
+ } catch (SQLException e) {
+ if (meta.storesMixedCaseQuotedIdentifiers()) {
+ fail("mixed case is not supported");
+ }
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesUpperCaseIdentifiers()
+ */
+ public void test_storesUpperCaseIdentifiers() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#storesUpperCaseQuotedIdentifiers()
+ */
+ public void test_storesUpperCaseQuotedIdentifiers() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsANSI92EntryLevelSQL()
+ */
+ public void test_supportsANSI92EntryLevelSQL() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsANSI92FullSQL()
+ */
+ public void test_supportsANSI92FullSQL() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsANSI92IntermediateSQL()
+ */
+ public void test_supportsANSI92IntermediateSQL() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsAlterTableWithAddColumn()
+ */
+ public void test_supportsAlterTableWithAddColumn() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsAlterTableWithDropColumn()
+ */
+ public void test_supportsAlterTableWithDropColumn() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsBatchUpdates()
+ */
+ public void test_supportsBatchUpdates() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInDataManipulation()
+ */
+ public void test_supportsCatalogsInDataManipulation() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInIndexDefinitions()
+ */
+ public void test_supportsCatalogsInIndexDefinitions() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInPrivilegeDefinitions()
+ */
+ public void test_supportsCatalogsInPrivilegeDefinitions()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInProcedureCalls()
+ */
+ public void test_supportsCatalogsInProcedureCalls() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCatalogsInTableDefinitions()
+ */
+ public void test_supportsCatalogsInTableDefinitions() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsColumnAliasing()
+ */
+ 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();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsConvert()
+ */
+ public void test_supportsConvert() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsConvert(int, int)
+ */
+ public void test_supportsConvertII() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCoreSQLGrammar()
+ */
+ public void test_supportsCoreSQLGrammar() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsCorrelatedSubqueries()
+ */
+ public void test_supportsCorrelatedSubqueries() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsDataDefinitionAndDataManipulationTransactions()
+ */
+ public void test_supportsDataDefinitionAndDataManipulationTransactions()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsDataManipulationTransactionsOnly()
+ */
+ public void test_supportsDataManipulationTransactionsOnly()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsDifferentTableCorrelationNames()
+ */
+ public void test_supportsDifferentTableCorrelationNames()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsExpressionsInOrderBy()
+ */
+ 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");
+ }
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsExtendedSQLGrammar()
+ */
+ public void test_supportsExtendedSQLGrammar() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsFullOuterJoins()
+ */
+ public void test_supportsFullOuterJoins() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsGetGeneratedKeys()
+ */
+ public void test_supportsGetGeneratedKeys() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsGroupBy()
+ */
+ 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");
+ }
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsGroupByBeyondSelect()
+ */
+ public void test_supportsGroupByBeyondSelect() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsGroupByUnrelated()
+ */
+ 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");
+ }
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsIntegrityEnhancementFacility()
+ */
+ public void test_supportsIntegrityEnhancementFacility() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsLikeEscapeClause()
+ */
+ public void test_supportsLikeEscapeClause() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsLimitedOuterJoins()
+ */
+ public void test_supportsLimitedOuterJoins() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMinimumSQLGrammar()
+ */
+ public void test_supportsMinimumSQLGrammar() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMixedCaseIdentifiers()
+ */
+ public void test_supportsMixedCaseIdentifiers() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMixedCaseQuotedIdentifiers()
+ */
+ public void test_supportsMixedCaseQuotedIdentifiers() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMultipleOpenResults()
+ */
+ public void test_supportsMultipleOpenResults() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMultipleResultSets()
+ */
+ public void test_supportsMultipleResultSets() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsMultipleTransactions()
+ */
+ public void test_supportsMultipleTransactions() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsNamedParameters()
+ */
+ public void test_supportsNamedParameters() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsNonNullableColumns()
+ */
+ public void test_supportsNonNullableColumns() throws SQLException {
+ assertTrue(
+ "columns in this database may not be defined as non-nullable",
+ meta.supportsNonNullableColumns());
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOpenCursorsAcrossCommit()
+ */
+ public void test_supportsOpenCursorsAcrossCommit() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOpenCursorsAcrossRollback()
+ */
+ public void test_supportsOpenCursorsAcrossRollback() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOpenStatementsAcrossCommit()
+ */
+ public void test_supportsOpenStatementsAcrossCommit() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOpenStatementsAcrossRollback()
+ */
+ public void test_supportsOpenStatementsAcrossRollback() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOrderByUnrelated()
+ */
+ 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");
+ }
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsOuterJoins()
+ */
+ public void test_supportsOuterJoins() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsPositionedDelete()
+ */
+ public void test_supportsPositionedDelete() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsPositionedUpdate()
+ */
+ public void test_supportsPositionedUpdate() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsResultSetConcurrency(int, int)
+ */
+ public void test_supportsResultSetConcurrencyII() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsResultSetHoldability(int)
+ */
+ public void test_supportsResultSetHoldabilityI() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsResultSetType(int)
+ */
+ public void test_supportsResultSetTypeI() throws SQLException {
+ // TODO 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()
+ */
+ public void test_supportsSavepoints() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInDataManipulation()
+ */
+ public void test_supportsSchemasInDataManipulation() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInIndexDefinitions()
+ */
+ public void test_supportsSchemasInIndexDefinitions() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInPrivilegeDefinitions()
+ */
+ public void test_supportsSchemasInPrivilegeDefinitions()
+ throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInProcedureCalls()
+ */
+ public void test_supportsSchemasInProcedureCalls() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSchemasInTableDefinitions()
+ */
+ public void test_supportsSchemasInTableDefinitions() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSelectForUpdate()
+ */
+ 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");
+ }
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsStatementPooling()
+ */
+ public void test_supportsStatementPooling() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsStoredProcedures()
+ */
+ public void test_supportsStoredProcedures() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSubqueriesInComparisons()
+ */
+ public void test_supportsSubqueriesInComparisons() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSubqueriesInExists()
+ */
+ 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");
+ }
+ }
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSubqueriesInIns()
+ */
+ public void test_supportsSubqueriesInIns() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsSubqueriesInQuantifieds()
+ */
+ public void test_supportsSubqueriesInQuantifieds() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsTableCorrelationNames()
+ */
+ public void test_supportsTableCorrelationNames() throws SQLException {
+ insertNewRecord();
+
+ String corelationName = "TABLE_NAME";
+ String selectQuery = "SELECT * FROM " + DatabaseCreator.TEST_TABLE1
+ + " AS " + corelationName;
+ ResultSet rs = statement.executeQuery(selectQuery);
+ ResultSetMetaData rsmd = rs.getMetaData();
+ int numOfColumn = rsmd.getColumnCount();
+
+ for (int i = 0; i < numOfColumn; i++) {
+ if (meta.supportsTableCorrelationNames()) {
+ assertEquals("Corelation names is not supported",
+ corelationName, rsmd.getTableName(i + 1));
+ } else {
+ assertEquals("Corelation names is supported",
+ DatabaseCreator.TEST_TABLE1, rsmd.getTableName(i + 1));
+ }
+ }
+ rs.close();
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsTransactionIsolationLevel(int)
+ */
+ 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));
+ assertFalse("database supports unknown isolation level", meta
+ .supportsTransactionIsolationLevel(100));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsTransactions()
+ */
+ public void test_supportsTransactions() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsUnion()
+ */
+ public void test_supportsUnion() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#supportsUnionAll()
+ */
+ public void test_supportsUnionAll() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#updatesAreDetected(int)
+ */
+ 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));
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#usesLocalFilePerTable()
+ */
+ public void test_usesLocalFilePerTable() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ /**
+ * @tests java.sql.DatabaseMetaData#usesLocalFiles()
+ */
+ public void test_usesLocalFiles() throws SQLException {
+ // TODO: JDBC does not implement this functionality
+ }
+
+ private void insertNewRecord() throws SQLException {
+ String insertQuery = "INSERT INTO " + DatabaseCreator.TEST_TABLE1
+ + " (id, field1, field2, field3) VALUES(" + id + ", '"
+ + "value" + id + "', " + id + ", " + id + ")";
+ id++;
+ statement.execute(insertQuery);
+ }
+}
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..f00a7cf
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/DeleteFunctionalityTest.java
@@ -0,0 +1,219 @@
+/*
+ * 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 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;
+
+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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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(). Deletes rows using subquery
+ * in WHERE clause
+ * TODO Foreign key functionality is 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
+ */
+ 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..7ad2d3e
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/InsertFunctionalityTest.java
@@ -0,0 +1,250 @@
+/*
+ * 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 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;
+
+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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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..b88aa4e
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/MultiThreadAccessTest.java
@@ -0,0 +1,445 @@
+/*
+ * 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 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;
+
+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
+ */
+ 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
+ */
+ 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
+ */
+ 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", BigDecimal.valueOf(id2), result
+// .getBigDecimal("field2"));
+// assertEquals("Wrong value of field3", BigDecimal.valueOf(id2), result
+// .getBigDecimal("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", BigDecimal.valueOf(newID), result
+// .getBigDecimal("field2"));
+// assertEquals("Wrong value of field3", BigDecimal.valueOf(newID), result
+// .getBigDecimal("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
+ */
+ 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 ", BigDecimal
+ .valueOf(result.getInt("id")), result
+ .getBigDecimal("field2"));
+ assertEquals("Wrong value of field3 ", BigDecimal
+ .valueOf(result.getInt("id")), result
+ .getBigDecimal("field3"));
+ }
+ result.close();
+ } catch (Exception e) {
+ System.err.println(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(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(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(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(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(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(e.getMessage());
+ }
+ }
+ };
+ }
+}
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..a0ded6a
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/SelectFunctionalityTest.java
@@ -0,0 +1,542 @@
+/*
+ * 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 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;
+
+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
+ */
+ 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
+ */
+ 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
+ */
+ 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<Integer, String> value = new HashMap<Integer, String>();
+ 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
+ */
+ 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<Integer, Integer> value = new HashMap<Integer, Integer>();
+ 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
+ */
+ 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<Integer, String> value = new HashMap<Integer, String>();
+ 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
+ */
+ 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<Integer, Integer> value = new HashMap<Integer, Integer>();
+ 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
+ */
+/* 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<Integer, Integer> value = new HashMap<Integer, Integer>();
+ 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
+ */
+ 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<Integer, Integer> values = new HashMap<Integer, Integer>();
+ 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
+ */
+ public void test_SelectOrderBy() throws SQLException {
+ String selectQuery = "SELECT onum FROM " + DatabaseCreator.ORDERS_TABLE
+ + " ORDER BY onum";
+ ResultSet result = statement.executeQuery(selectQuery);
+
+ ArrayList<Integer> values = new ArrayList<Integer>();
+ 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
+ */
+ public void test_SelectDistinct() throws SQLException {
+ String selectQuery = "SELECT DISTINCT rating FROM "
+ + DatabaseCreator.CUSTOMERS_TABLE;
+ ResultSet result = statement.executeQuery(selectQuery);
+
+ HashSet<Integer> values = new HashSet<Integer>();
+ 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
+ */
+ 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) {
+ try {
+ ResultSet result = statement.executeQuery(query);
+ while (result.next()) {
+ assertEquals("wrong value of " + name + " field", expected,
+ result.getInt(name));
+ }
+ 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
+ */
+ 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<Double> values = new HashSet<Double>();
+ 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..fbafe82
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/StressTest.java
@@ -0,0 +1,310 @@
+/*
+ * 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 java.sql.Connection;
+import java.sql.DatabaseMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.Vector;
+
+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;
+
+public class StressTest extends TestCase {
+ Vector<Connection> vc = new Vector<Connection>();
+
+ 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.
+ */
+ 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.
+ */
+ 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.
+ */
+ public void testInsertOfManyRowsUsingOneThread() {
+ // TODO Crashes VM. Fix later.
+ /*
+ * int maxConnections = getConnectionNum();
+ * openConnections(maxConnections); int tasksPerConnection =
+ * Support_SQL.sqlMaxTasks / maxConnections; int pk = 1; for (int i = 0;
+ * i < vc.size(); ++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
+ */
+ public void testInsertOfManyRowsUsingManyThreads() {
+ // TODO Crashes VM. Fix later.
+ /*
+ * int numConnections = getConnectionNum();
+ *
+ * ThreadPool threadPool = new ThreadPool(numConnections);
+ *
+ * for (int i = 0; i < numConnections; ++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()); int tasksPerConnection = Support_SQL.sqlMaxTasks /
+ * numConnections; 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..b9761cd
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/UpdateFunctionalityTest.java
@@ -0,0 +1,365 @@
+/*
+ * 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 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;
+
+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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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
+ */
+ 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<BigDecimal> values = new HashSet<BigDecimal>();
+ // 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
+ */
+ 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
+ */
+ 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
+ */
+ 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..7bcbff6
--- /dev/null
+++ b/sql/src/test/java/tests/java/sql/UpdateFunctionalityTest2.java
@@ -0,0 +1,296 @@
+/*
+ * 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 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;
+
+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
+ */
+ 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
+ */
+/* public void testUpdate2() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ try {
+ statement.execute("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
+ */
+ 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
+ */
+/* public void testUpdate4() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ try {
+ statement.execute("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
+ */
+ public void testUpdate5() throws SQLException {
+ DatabaseCreator.fillFKCascadeTable(conn);
+ statement.execute("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
+ */
+ /* public void testUpdate6() throws SQLException {
+ DatabaseCreator.fillFKCascadeTable(conn);
+ try {
+ statement.execute("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
+ */
+/* public void testUpdate7() throws SQLException {
+ DatabaseCreator.fillFKStrictTable(conn);
+ statement.execute("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
+ */
+ public void testUpdate8() throws SQLException {
+ statement.execute("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
+ */
+ 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/sql/AbstractSqlTest.java b/sql/src/test/java/tests/sql/AbstractSqlTest.java
new file mode 100644
index 0000000..9d922db
--- /dev/null
+++ b/sql/src/test/java/tests/sql/AbstractSqlTest.java
@@ -0,0 +1,212 @@
+/*
+ * 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 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.
+ */
+public 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(String testName) {
+ super(testName);
+ 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
+ * @exception Exception may be thrown by subclasses
+ */
+ @Override
+ protected void setUp() throws 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);
+ }
+
+ 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
+ */
+ 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
+ */
+ 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/sql/AllTests.java b/sql/src/test/java/tests/sql/AllTests.java
new file mode 100644
index 0000000..afd9ba3
--- /dev/null
+++ b/sql/src/test/java/tests/sql/AllTests.java
@@ -0,0 +1,46 @@
+/* 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 = new TestSuite("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.addTestSuite(SQLite.JDBCDriverTest.class);
+ suite.addTestSuite(tests.sql.ConnectionTest.class);
+ suite.addTestSuite(tests.sql.PreparedStatementTest.class);
+ suite.addTestSuite(tests.sql.ResultSetMetaDataTest.class);
+ suite.addTestSuite(tests.sql.StatementTest.class);
+ // $JUnit-END$
+ return suite;
+ }
+}
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..ba6fff2
--- /dev/null
+++ b/sql/src/test/java/tests/sql/ConnectionTest.java
@@ -0,0 +1,1958 @@
+/*
+ * 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 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 junit.framework.Test;
+
+public class ConnectionTest extends SQLTest {
+
+ /**
+ * @test java.sql.Connection#createStatement()
+ */
+ public void testCreateStatement() {
+
+ Statement statement = null;
+ try {
+ statement = conn.createStatement();
+ statement.close();
+ } catch (SQLException sqle) {
+ fail("SQL Exception was thrown: " + sqle.getMessage());
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ }
+ try {
+ statement.executeQuery("select * from zoo");
+ fail("SQLException is not thrown after close");
+ } catch (SQLException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#createStatement(int resultSetType, int
+ * resultSetConcurrency)
+ */
+ public void testCreateStatement_int_int() {
+ Statement st = null;
+ ResultSet rs = null;
+ 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("Can 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) {
+ }
+ }
+
+ 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) {
+ }
+ }
+
+ try {
+ // exception is not specified for this case
+ conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, -1);
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ // exception is not specified for this case
+ conn.createStatement(Integer.MIN_VALUE, ResultSet.CONCUR_READ_ONLY);
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#createStatement(int resultSetType, int
+ * resultSetConcurrency, int resultSetHoldability)
+ */
+ public void testCreateStatement_int_int_int() {
+ Statement st = null;
+ try {
+ st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ st.execute("select id, name from zoo");
+ ResultSet 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 {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ /*
+ * ResultSet.CLOSE_CURSORS_AT_COMMIT is not supported
+ */
+/* try {
+ st = conn.createStatement(ResultSet.TYPE_FORWARD_ONLY,
+ ResultSet.CONCUR_READ_ONLY,
+ ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ 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 {
+ try {
+ 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) {
+ // expected
+ }
+
+ }
+
+ /**
+ * @test java.sql.Connection#getMetaData()
+ */
+ public void testGetMetaData() {
+ try {
+ DatabaseMetaData md = conn.getMetaData();
+ Connection con = md.getConnection();
+ assertEquals(conn, con);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#clearWarnings()
+ *
+ * TODO clearWarnings is not supported
+ */
+/* public void testClearWarnings() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute("select animals from zoo");
+ fail("SQLException was not thrown");
+ } catch (SQLException e) {
+ // expected
+ } 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) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ SQLWarning w = conn.getWarnings();
+ assertNotNull(w);
+ } catch (Exception e) {
+ fail("Unexpected Exception: " + e.getMessage());
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#getWarnings()
+ *
+ * TODO GetWarnings is not supported: returns null
+ */
+ /* public void testGetWarnings() {
+
+ 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();
+ 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) {
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#getAutoCommit()
+ */
+ 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)
+ */
+ public void testSetAutoCommit() {
+ 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');");
+ st.execute("select * from zoo");
+ rs = st.getResultSet();
+ assertEquals(3, getCount(rs));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } 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();
+ 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) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#isReadOnly()
+ */
+ public void testIsReadOnly() {
+ try {
+ conn.setReadOnly(true);
+ assertTrue(conn.isReadOnly());
+ conn.setReadOnly(false);
+ assertFalse(conn.isReadOnly());
+ conn.setReadOnly(true);
+ assertTrue(conn.isReadOnly());
+ conn.setReadOnly(false);
+ assertFalse(conn.isReadOnly());
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.getMessage());
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setReadOnly(boolean)
+ */
+ public void testSetReadOnly() {
+ 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) {
+ // 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) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#getHoldability()
+ *
+ * TODO ResultSet.CLOSE_CURSORS_AT_COMMIT is not supported
+ */
+ public void testGetHoldability() {
+ try {
+ // conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+ // assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, conn
+ // .getHoldability());
+ conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn
+ .getHoldability());
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.getMessage());
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setHoldability(int)
+ *
+ * TODO ResultSet.CLOSE_CURSORS_AT_COMMIT is not supported
+ */
+ public void testSetHoldability() {
+ Statement st = null;
+ try {
+// conn.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT);
+// assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, conn
+// .getHoldability());
+ st = conn.createStatement();
+ st.execute("select id, name from zoo");
+ ResultSet rs = st.getResultSet();
+ try {
+ rs.close();
+ } catch (SQLException sqle) {
+ fail("Unexpected exception was thrown during closing ResultSet");
+ }
+ conn.commit();
+ conn.setHoldability(ResultSet.HOLD_CURSORS_OVER_COMMIT);
+ assertEquals(ResultSet.HOLD_CURSORS_OVER_COMMIT, conn
+ .getHoldability());
+ } 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
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#getTransactionIsolation()
+ *
+ * TODO only Connection.TRANSACTION_SERIALIZABLE is supported
+ */
+ public void testGetTransactionIsolation() {
+ 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());
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setTransactionIsolation(int)
+ *
+ * TODO only Connection.TRANSACTION_SERIALIZABLE is supported
+ */
+ 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(-1);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setCatalog(String catalog)
+ *
+ * TODO setCatalog method does nothing
+ */
+/* public void testSetCatalog() {
+ String[] catalogs = { "test", "test1", "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
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#getCatalog()
+ *
+ * TODO getCatalog method returns ""
+ */
+ /* public void testGetCatalog() {
+ try {
+ assertEquals("test", conn.getCatalog());
+ } catch (SQLException sqle) {
+ fail("SQL Exception " + sqle.getMessage());
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#setTypeMap(Map<String,Class<?>> map)
+ *
+ * TODO setTypeMap is not supported
+ */
+/* 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) {
+ fail("SQL Exception " + sqle.getMessage());
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ }
+
+ try {
+ conn.setTypeMap(null);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#getTypeMap()
+ *
+ * TODO getTypeMap is not supported
+ */
+/* public void testGetTypeMap() {
+ 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) {
+ fail("SQL Exception " + sqle.getMessage());
+ } catch (Exception e) {
+ fail("Unexpected Exception " + e.getMessage());
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#nativeSQL(String sql)
+ *
+ * TODO nativeSQL is not supported
+ */
+/* public void testNativeSQL() {
+ 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;
+ try {
+ for (int i = 0; i < queries.length; i++) {
+ String nativeQuery = conn.nativeSQL(queries[i]);
+ assertEquals(native_queries[i], nativeQuery);
+ st = conn.createStatement();
+ st.execute(nativeQuery);
+ }
+ } catch (SQLException sqle) {
+ fail("SQL Exception " + sqle.getMessage());
+ } 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 {
+ String nativeQuery = conn.nativeSQL(inc_queries[i]);
+ assertEquals(inc_queries[i], nativeQuery);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#prepareCall(String sql)
+ *
+ * TODO prepareCall is not supported
+ */
+/* public void testPrepareCall() {
+ createProcedure();
+ 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) {
+ fail("SQLException was thrown");
+ } finally {
+ try {
+ st.close();
+ st1.close();
+ rs.close();
+ rs1.close();
+ cstmt.close();
+ } catch (SQLException 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
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#prepareCall(String sql, int resultSetType, int
+ * resultSetConcurrency)
+ *
+ * TODO prepareCall is not supported
+ */
+/* 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);
+ 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
+ */
+/* 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);
+ 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)
+ */
+ /*
+ * TODO Crashes VM. Fix later.
+ *
+ * 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) {
+ * //expected
+ * }
+ *
+ * try {
+ * conn.prepareStatement(null);
+ * fail("SQLException is not thrown");
+ * } catch (SQLException e) {
+ * // expected
+ * }
+ * }
+ */
+
+ /**
+ * @test java.sql.Connection#prepareStatement(String sql, int
+ * autoGeneratedKeys)
+ */
+// TODO Crashes VM. Fix later.
+/* 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 (?, ?, ?);";
+
+ // TODO Statement.RETURN_GENERATED_KEYS is not supported
+ prst = conn.prepareStatement(insert,
+ Statement.RETURN_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));
+
+ rs4 = prst.getGeneratedKeys();
+ assertEquals(0, getCount(rs4));
+
+
+ prst1 = conn.prepareStatement(insert, Statement.NO_GENERATED_KEYS);
+ prst1.setInt(1, 5);
+ prst1.setString(2, "Layka");
+ prst1.setString(3, "dog");
+
+ prst1.execute();
+
+// TODO getGeneratedKeys is not supported
+
+ 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();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#commit()
+ */
+ public void testCommit() {
+ Statement st = null;
+ Statement st1 = null;
+ Statement st2 = null;
+ Statement st3 = 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');");
+
+ if (!conn.getAutoCommit()) {
+ 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 {
+ conn.commit();
+ 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 {
+ try {
+ rs3.close();
+ st3.close();
+ } catch(SQLException ee) {}
+ }
+
+ } else {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ try {
+ conn.commit();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException was thrown: " + sqle.toString());
+ } finally {
+ try {
+ rs1.close();
+ st.close();
+ st1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#rollback()
+ */
+ public void testRollback() {
+ 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');");
+
+ 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));
+ 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 {
+ try {
+ rs2.close();
+ rs3.close();
+ st2.close();
+ st3.close();
+ } catch (SQLException ee) {
+ }
+ }
+ } else {
+ st1 = conn.createStatement();
+ st1.execute("select * from zoo");
+ rs1 = st1.getResultSet();
+ assertEquals(4, getCount(rs1));
+ try {
+ conn.rollback();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ } finally {
+ try {
+ st.close();
+ st1.close();
+ rs1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Connection#setSavepoint()
+ *
+ * TODO setSavepoint is not supported
+ */
+/* public void testSetSavepoint() {
+ 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();
+ 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();
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint();
+ 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();
+ st
+ .execute("insert into zoo (id, name, family) values (5, 'chayka', 'gull');");
+ Savepoint sp2 = conn.setSavepoint();
+ 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
+ */
+/* public void testSetSavepoint_String() {
+ 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
+ */
+/* public void testRollback_Savepoint() {
+ 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
+ */
+/* public void testReleaseSavepoint_Savepoint() {
+ 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
+ */
+/* public void testPrepareStatement_String_intArray() {
+ 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)
+ */
+// TODO Crashes VM. Fix later.
+/* 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 {
+ rs.close();
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ 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) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException was thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ 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
+ }
+ }
+*/
+ /**
+ * @test java.sql.Connection#prepareStatement(String sql, int resultSetType,
+ * int resultSetConcurrency, int resultSetHoldability)
+ */
+ // TODO Crashes VM. Fix later.
+/* 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 {
+ 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
+ */
+ /* 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 (?, ?, ?);";
+ 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) {
+ }
+ }
+
+ 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");
+ }
+ }
+*/
+}
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..1e6b124
--- /dev/null
+++ b/sql/src/test/java/tests/sql/PreparedStatementTest.java
@@ -0,0 +1,2473 @@
+/*
+ * 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 java.math.BigDecimal;
+import java.sql.ParameterMetaData;
+import java.sql.PreparedStatement;
+import java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Time;
+import java.sql.Timestamp;
+import java.sql.Types;
+import java.sql.Date;
+import java.util.Calendar;
+import java.util.Locale;
+import java.util.TimeZone;
+
+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 createTables() {
+ 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 clearTables() {
+ 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) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#addBatch()
+ */
+ 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");
+ } 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()
+ */
+
+ // TODO Crashes VM. Fix later.
+
+/* public void testExecute() {
+ Statement st = null;
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into zoo(id, family, name) values(?, ?, 'unknown animal')";
+ ps = conn.prepareStatement(query);
+ ps.setInt(1, 3);
+ ps.setString(2, "No name");
+ assertTrue(ps.execute());
+ st = conn.createStatement();
+ st.execute("select * from zoo");
+ assertEquals(3, getCount(st.getResultSet()));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ ps.close();
+ st.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);
+ assertTrue(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);
+ 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.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) {}
+ }
+ }
+*/
+ /*
+ * @test java.sql.PreparedStatement#executeQuery()
+ */
+
+ // TODO Crashes VM. Fix later.
+ /* 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) {}
+ }
+ }
+*/
+ /**
+ * @test java.sql.PreparedStatement#executeUpdate()
+ */
+
+ // TODO Crashes VM. Fix later.
+/* 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()
+ *
+ * TODO Doesn't pass on SQLite but according to Java docs:
+ * it is possible to invoke the method getMetaData on a
+ * PreparedStatement object rather than waiting to execute it.
+ */
+ public void testGetMetaData() {
+ PreparedStatement ps = null;
+ try {
+ String query = "update zoo set name='Masha', family='cat' where id=?;";
+ ps = conn.prepareStatement(query);
+ assertNull(ps.getMetaData());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ } catch (Exception e) {
+ fail("Exception is thrown: " + e.toString());
+ } 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));
+ assertEquals("id", rsmd.getColumnName(1));
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#getParameterMetaData()
+ * TODO not supported exception
+ */
+ /* public void testGetParameterMetaData() {
+ PreparedStatement ps = null;
+ try {
+ String query = "select * from zoo where id = ?";
+ ps = conn.prepareStatement(query);
+ ParameterMetaData rsmd = ps.getParameterMetaData();
+ assertNotNull(rsmd);
+ assertEquals(1, rsmd.getParameterCount());
+ ps.setInt(1, 2);
+ ps.execute();
+ ParameterMetaData rsmd1 = ps.getParameterMetaData();
+ assertNotNull(rsmd1);
+ assertEquals(1, rsmd1.getParameterCount());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.toString());
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ String query = "select * from zoo where id = ?";
+ ps = conn.prepareStatement(query);
+ ParameterMetaData rsmd = ps.getParameterMetaData();
+ assertNotNull(rsmd);
+ assertEquals(1, rsmd.getParameterCount());
+ ps.setInt(1, 2);
+ ps.execute();
+ ParameterMetaData rsmd1 = ps.getParameterMetaData();
+ assertNotNull(rsmd1);
+ assertEquals(1, rsmd1.getParameterCount());
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ String query = "select * from zoo where id = 1";
+ ps = conn.prepareStatement(query);
+ ParameterMetaData rsmd = ps.getParameterMetaData();
+ assertNotNull(rsmd);
+ assertEquals(0, rsmd.getParameterCount());
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.PreparedStatement#clearParameters()
+ */
+ /*
+ * TODO Crashes VM. Fix later.
+ * public void testClearParameters() {
+ * PreparedStatement ps = null;
+ * try {
+ * String query = "select * from zoo where id = ? and family=?";
+ * ps = conn.prepareStatement(query);
+ * 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)
+ */
+ public void testSetInt() throws SQLException {
+ createTables();
+ 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 {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ 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 {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ ps.setInt(2, Integer.MIN_VALUE);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setInt(-2, 0);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setLong(int parameterIndex, long x)
+ */
+ public void testSetLong() {
+ createTables();
+ 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) {
+ }
+ }
+
+ try {
+ ps.setLong(2, Long.MIN_VALUE);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setLong(-2, 0);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setFloat(int parameterIndex, float x)
+ */
+ public void testSetFloat() {
+ float value1 = 12345678.12345689f;
+ float value2 = -12345678.12345689f;
+ createTables();
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (FloatVal) values (?);";
+ ps = conn.prepareStatement(query);
+ 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) {
+ }
+ }
+
+ try {
+ ps.setFloat(2, Float.MIN_VALUE);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setFloat(-2, 0);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setDouble(int parameterIndex, double x)
+ */
+ public void testSetDouble() {
+ createTables();
+ PreparedStatement ps = null;
+ try {
+ String query = "insert into type (DoubleVal) values (?);";
+ ps = conn.prepareStatement(query);
+ 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) {
+ }
+ }
+
+ try {
+ ps.setDouble(2, Double.MIN_VALUE);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setDouble(-2, 0);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ public void testSetString_charField() {
+ createTables();
+ PreparedStatement ps = null;
+ try {
+ String str = "test^text$test%";
+ String query = "insert into type (charStr) values (?);";
+ ps = conn.prepareStatement(query);
+ 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(2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setString(-2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ 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());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ public void testSetString_tinyTextField() {
+ createTables();
+ 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(2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setString(-2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ 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());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ public void testSetString_textField() {
+ createTables();
+ 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 {
+ ps.setString(2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setString(-2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ 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());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ public void testSetString_mediumTextField() {
+ createTables();
+ 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(2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setString(-2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setString(1, null);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setString(int parameterIndex, String x)
+ */
+ public void testSetString_longTextField() {
+ createTables();
+ 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(2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setString(-2, "test text");
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setString(1, null);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setShort(int parameterIndex, short x)
+ */
+ public void testSetShort() {
+ createTables();
+ 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) {
+ }
+ }
+
+ try {
+ ps.setShort(2, Short.MAX_VALUE);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setShort(-2, Short.MIN_VALUE);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ String query1 = "insert type(Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+ try {
+ ps1.setShort(1, Short.MAX_VALUE);
+ ps1.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ 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 {
+ clearTables();
+ ps.close();
+ ps1.close();
+ ps2.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setBoolean(int parameterIndex, boolean
+ * x)
+ */
+ public void testSetBoolean() {
+ createTables();
+ 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) {
+ }
+ }
+
+ try {
+ ps.setBoolean(2, true);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setBoolean(-2, false);
+ ps.execute();
+ 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 {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setByte(int parameterIndex, byte x)
+ */
+ public void testSetByte() {
+ createTables();
+ 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);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setByte(-2, Byte.MIN_VALUE);
+ ps.execute();
+ 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 {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setBytes(int parameterIndex, byte[] x)
+ */
+ public void testSetBytes() {
+
+ byte[] bytesArray = {1, 0};
+ createTables();
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (LBlob) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ try {
+ ps.setBytes(1, bytesArray);
+ ps.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ ps.setBytes(2, bytesArray);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setBytes(-2, bytesArray);
+ ps.execute();
+ 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);
+ 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 {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setBigDecimal(int parameterIndex,
+ * BigDecimal x)
+ */
+ public void testSetBigDecimal() {
+
+ BigDecimal bd = new BigDecimal("50");
+ createTables();
+ 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);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where DecVal=" + bd);
+ 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.setBigDecimal(2, bd);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setBigDecimal(-2, bd);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ String query1 = "insert into type (Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setBigDecimal(1, bd);
+ ps1.execute();
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown");
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setDate(int parameterIndex, Date x)
+ */
+ public void testSetDate_int_Date() {
+
+ Date[] dates = { new Date(1799, 05, 26), new Date(Integer.MAX_VALUE),
+ new Date(123456789) };
+
+ createTables();
+ 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++) {
+ Statement st = null;
+ try {
+ ps.setDate(1, dates[i]);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where dateVal='"
+ + dates[i].toString() + "'");
+ 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.setDate(2, dates[0]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setDate(-2, dates[0]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ String query1 = "insert type(Tint) values (?);";
+ ps1 = conn.prepareStatement(query1);
+
+ try {
+ ps1.setDate(1, dates[0]);
+ ps1.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setDate(int parameterIndex, Date x,
+ * Calendar cal)
+ */
+ public void testSetDate_int_Date_Calendar() {
+
+ Calendar[] cals = { Calendar.getInstance(),
+ Calendar.getInstance(Locale.GERMANY),
+ Calendar.getInstance(TimeZone.getDefault()) };
+
+ Date[] dates = { new Date(1799, 05, 26), new Date(Integer.MAX_VALUE),
+ new Date(123456789) };
+
+ createTables();
+ 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++) {
+ Statement st = null;
+ try {
+ ps.setDate(1, dates[i], cals[i]);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where dateVal='"
+ + dates[i].toString() + "'");
+ 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.setDate(2, dates[0], cals[0]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setDate(-2, dates[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.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 {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setNull(int parameterIndex, int sqlType)
+ *
+ * this test doesn't passed on RI
+ */
+ public void testSetNull_int_int() {
+ createTables();
+ 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 {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, LongVal) values (true, ?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.BIGINT);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ //expected
+ } finally {
+ try {
+ st.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 {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, dateVal) values (true, ?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.DATE);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ //expected
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, BlobVal) values (true, ?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.BLOB);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ //expected
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ query = "insert into type (BoolVal, TextVal) values (true, ?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setNull(1, Types.CHAR);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ //expected
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setObject(int parameterIndex, Object x)
+ *
+ * this test doesn't pass on RI
+ */
+ public void testSetObject_int_Object() {
+ createTables();
+ 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 not thrown");
+ }
+
+ query = "insert into type (dateVal) values (?);";
+ ps = conn.prepareStatement(query);
+
+ try {
+ ps.setObject(1, new Date(123456789));
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where dateVal='"
+ + new Date(123456789) + "';");
+ 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 {
+ clearTables();
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setObject(int parameterIndex, Object x,
+ * int targetSqlType)
+ *
+ * this test doesn't pass on RI
+ */
+ public void testSetObject_int_Object_int() {
+ createTables();
+ 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);
+
+ try {
+ ps.setObject(1, new Date(123456789), Types.DATE);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where dateVal='"
+ + new Date(123456789) + "';");
+ 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 {
+ clearTables();
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setObject(int parameterIndex, Object x,
+ * int targetSqlType, int scale)
+ *
+ * this test doesn't pass on RI
+ */
+ public void testSetObject_int_Object_int_int() {
+ createTables();
+ 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);
+
+ try {
+ ps.setObject(1, new Date(123456789), Types.DATE, -1);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where dateVal='"
+ + new Date(123456789) + "';");
+ 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 {
+ clearTables();
+ ps.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setTime(int parameterIndex, Time x)
+ */
+ public void testSetTimeint_Time() {
+
+ Time[] times = { new Time(24, 25, 26), new Time(Integer.MAX_VALUE),
+ new Time(123456789) };
+
+ createTables();
+ 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].toString() + "'");
+ 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]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setTime(-2, times[0]);
+ ps.execute();
+ 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 {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setTime(int parameterIndex, Time x,
+ * Calendar cal)
+ */
+ 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) };
+
+ createTables();
+ 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]);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where timeVal='"
+ + times[i].toString() + "'");
+ 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], cals[0]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setTime(-2, times[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.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 {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.PreparedStatement#setTimestamp(int parameterIndex,
+ * Timestamp x)
+ */
+ public void testSetTimestamp_int_Timestamp() {
+
+ Timestamp[] timestamps = { new Timestamp(2007, 10, 17, 19, 06, 50, 23),
+ new Timestamp(123) };
+
+ createTables();
+ PreparedStatement ps = null;
+ PreparedStatement ps1 = null;
+ try {
+ String query = "insert into type (TS) values (?);";
+ ps = conn.prepareStatement(query);
+ Statement st = null;
+ for (int i = 0; i < timestamps.length; i++) {
+ try {
+ ps.setTimestamp(1, timestamps[i]);
+ ps.execute();
+ st = conn.createStatement();
+ st.execute("select * from type where TS='"
+ + timestamps[i].toString() + "'");
+ 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.setTimestamp(2, timestamps[0]);
+ ps.execute();
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ try {
+ ps.setTimestamp(-2, timestamps[0]);
+ 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]);
+ ps1.execute();
+
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ clearTables();
+ ps.close();
+ ps1.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+}
diff --git a/sql/src/test/java/tests/sql/ResultSetMetaDataTest.java b/sql/src/test/java/tests/sql/ResultSetMetaDataTest.java
new file mode 100755
index 0000000..1f9483b
--- /dev/null
+++ b/sql/src/test/java/tests/sql/ResultSetMetaDataTest.java
@@ -0,0 +1,252 @@
+/*
+ * 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 java.sql.ResultSet;
+import java.sql.ResultSetMetaData;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Types;
+
+public class ResultSetMetaDataTest extends SQLTest {
+
+ ResultSetMetaData rsmd = null;
+ Statement st = null;
+ ResultSet rs = null;
+
+ public void setUp() {
+ super.setUp();
+ try {
+ String query = "select * from zoo";
+ st = conn.createStatement();
+ st.execute(query);
+ rs = st.getResultSet();
+ rsmd = rs.getMetaData();
+ } catch (SQLException e) {
+ fail("Couldn't get ResultSetMetaData object");
+ }
+ }
+
+ public void tearDown() {
+ super.tearDown();
+ try {
+ rs.close();
+ st.close();
+ } catch (SQLException e) {
+ fail("Couldn't close Statement object");
+ }
+ }
+
+ /**
+ * @test java.sql.ResultSetMetaData#getCatalogName(int column)
+ */
+ public void testGetCatalogName() throws SQLException {
+ try {
+ assertNull(rsmd.getCatalogName(0));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+ }
+
+ /**
+ * @test java.sql.ResultSetMetaData#getColumnClassName(int column)
+ */
+ public void testGetColumnClassName() {
+ try {
+ assertNotNull(rsmd);
+ assertEquals(Short.class.getName(), rsmd.getColumnClassName(1));
+ assertEquals(String.class.getName(), rsmd.getColumnClassName(2));
+ assertEquals(String.class.getName(), rsmd.getColumnClassName(3));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+
+ try {
+ String name = rsmd.getColumnClassName(-1);
+ assertNull(name);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+
+ try {
+ String name = rsmd.getColumnClassName(4);
+ assertNull(name);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+ }
+
+ /**
+ * @test java.sql.ResultSetMetaData#getColumnCount()
+ */
+ public void testGetColumnCount() {
+ try {
+ assertEquals(3, rsmd.getColumnCount());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+ }
+
+ /**
+ * @test java.sql.ResultSetMetaData#getColumnLabel(int column)
+ */
+ public void testGetColumnLabel() {
+ String[] labels = { "zoo.id", "zoo.name", "zoo.family" };
+ try {
+ for (int i = 0; i < rsmd.getColumnCount(); i++) {
+ String label = rsmd.getColumnLabel(i + 1);
+ assertEquals(labels[i], label);
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+ }
+
+ /**
+ * @test java.sql.ResultSetMetaData#getColumnName(int column)
+ */
+ public void testGetColumnName() {
+ String[] labels = { "zoo.id", "zoo.name", "zoo.family" };
+ try {
+ for (int i = 0; i < rsmd.getColumnCount(); i++) {
+ String label = rsmd.getColumnLabel(i + 1);
+ assertEquals(labels[i], label);
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+
+ try {
+ String label = rsmd.getColumnLabel(-1);
+ assertNull(label);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+
+ try {
+ String label = rsmd.getColumnLabel(5);
+ assertNull(label);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+ }
+
+ /**
+ * @test java.sql.ResultSetMetaData#getColumnType(int column)
+ */
+ public void testGetColumnType() {
+ int[] types = { Types.SMALLINT, Types.VARCHAR, Types.VARCHAR};
+ try {
+ for (int i = 0; i < rsmd.getColumnCount(); i++) {
+ int type = rsmd.getColumnType(i + 1);
+ assertEquals(types[i], type);
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+
+ try {
+ rsmd.getColumnType(-1);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+ try {
+ rsmd.getColumnType(5);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.sql.ResultSetMetaData#getColumnTypeName(int column)
+ */
+ public void testGetColumnTypeName() {
+ try {
+ assertEquals("smallint", rsmd.getColumnTypeName(1));
+ assertEquals("varchar", rsmd.getColumnTypeName(2));
+ assertEquals("varchar", rsmd.getColumnTypeName(3));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+
+ try {
+ rsmd.getColumnTypeName(-1);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+ try {
+ rsmd.getColumnTypeName(5);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ }
+ }
+
+ /**
+ * @test java.sql.ResultSetMetaData#getTableName(int column)
+ */
+ public void testGetTableName() {
+ try {
+ assertEquals("zoo", rsmd.getTableName(1));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+ Statement st1 = null;
+ ResultSet rs1 = null;
+ try {
+ String[] queries = {
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "select name, animal_id from hutch, zoo where zoo.id = 1" };
+ st1 = conn.createStatement();
+ for (int i = 0; i < queries.length; i++) {
+ st1.execute(queries[i]);
+ }
+ rs1 = st1.getResultSet();
+ ResultSetMetaData rsmd1 = rs1.getMetaData();
+ assertEquals("zoo", rsmd1.getTableName(1));
+ assertEquals("hutch", rsmd1.getTableName(2));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs1.close();
+ st1.execute("drop table ifexists hutch");
+ st1.close();
+
+ } catch (SQLException sqle) {
+ }
+ }
+
+ try {
+ String name = rsmd.getTableName(-1);
+ assertNull(name);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+ try {
+ String name = rsmd.getTableName(5);
+ assertNull(name);
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+ }
+}
diff --git a/sql/src/test/java/tests/sql/SQLTest.java b/sql/src/test/java/tests/sql/SQLTest.java
new file mode 100755
index 0000000..08ae350
--- /dev/null
+++ b/sql/src/test/java/tests/sql/SQLTest.java
@@ -0,0 +1,123 @@
+/*
+ * 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 java.io.File;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.Statement;
+
+import tests.support.Support_SQL;
+
+import junit.extensions.TestSetup;
+import junit.framework.Test;
+import junit.framework.TestCase;
+import junit.framework.TestSuite;
+
+public class SQLTest extends TestCase {
+ static Connection conn;
+
+ public void setUp() {
+ getSQLiteConnection();
+ createZoo();
+ }
+
+ private final File dbFile = new File("sqliteTest2.db");
+
+ protected void getSQLiteConnection() {
+ try {
+ Class.forName("SQLite.JDBCDriver").newInstance();
+ if(dbFile.exists()) dbFile.delete();
+ conn = DriverManager.getConnection("jdbc:sqlite:/"
+ + dbFile.getName());
+ } catch (Exception e) {
+ fail("Exception: " + e.toString());
+ }
+ }
+
+ public void tearDown() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute("drop table if exists zoo");
+
+ } catch (SQLException e) {
+ fail("Couldn't drop table: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ conn.close();
+ } catch(SQLException ee) {}
+ }
+ }
+
+ public void createZoo() {
+
+ String[] queries = {
+ "create table zoo(id smallint, name varchar(10), family varchar(10))",
+ "insert into zoo values (1, 'Kesha', 'parrot')",
+ "insert into zoo values (2, 'Yasha', 'sparrow')" };
+
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ for (int i = 0; i < queries.length; i++) {
+ st.execute(queries[i]);
+ }
+ } catch (SQLException e) {
+ e.printStackTrace();
+ fail("Unexpected exception: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {}
+ }
+ }
+
+ public void createProcedure() {
+ String proc = "CREATE PROCEDURE welcomeAnimal (IN parameter1 integer, IN parameter2 char(20), IN parameter3 char(20)) "
+ + " BEGIN "
+ + " INSERT INTO zoo(id, name, family) VALUES (parameter1, parameter2, parameter3); "
+ + "SELECT * FROM zoo;" + " END;";
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute("DROP PROCEDURE IF EXISTS welcomeAnimal");
+ st.execute(proc);
+ } catch (SQLException e) {
+ fail("Unexpected exception: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {}
+ }
+ }
+
+ public int getCount(ResultSet rs) {
+ int count = 0;
+ try {
+ while (rs.next()) {
+ count++;
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ }
+ return count;
+ }
+}
diff --git a/sql/src/test/java/tests/sql/StatementTest.java b/sql/src/test/java/tests/sql/StatementTest.java
new file mode 100755
index 0000000..fd1002e
--- /dev/null
+++ b/sql/src/test/java/tests/sql/StatementTest.java
@@ -0,0 +1,955 @@
+/*
+ * 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 java.sql.BatchUpdateException;
+import java.sql.ResultSet;
+import java.sql.SQLException;
+import java.sql.SQLWarning;
+import java.sql.Statement;
+import java.util.Vector;
+
+public class StatementTest extends SQLTest {
+
+ /**
+ * @test java.sql.Statement#addBatch(String)
+ */
+ public void testAddBatch() throws SQLException {
+
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.addBatch("INSERT INTO zoo VALUES (3,'Tuzik','dog')");
+ st.addBatch("INSERT INTO zoo VALUES (4,'Mashka','cat')");
+
+ int[] updateCounts = st.executeBatch();
+ assertEquals(2, updateCounts.length);
+ assertEquals(1, updateCounts[0]);
+ assertEquals(1, updateCounts[1]);
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement();
+ st.addBatch("");
+ st.executeBatch();
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement();
+ st.addBatch(null);
+ st.executeBatch();
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#clearWarnings()
+ */
+ public void testClearWarnings() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute("select animals from zoo");
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ try {
+ st = conn.createStatement();
+ st.clearWarnings();
+ SQLWarning w = st.getWarnings();
+ assertNull(w);
+ } catch (Exception e) {
+ fail("Unexpected Exception: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#getWarnings()
+ *
+ * TODO getWarnings is not supported
+ */
+/* public void testGetWarnings() {
+
+ Statement st = null;
+ int errorCode1 = -1;
+ int errorCode2 = -1;
+
+ try {
+ st = conn.createStatement();
+ st.execute("select animals from zoooo");
+ } catch (SQLException e) {
+ // expected
+ errorCode1 = e.getErrorCode();
+ }
+ try {
+ SQLWarning wrs = st.getWarnings();
+ assertNull(wrs);
+ } 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 = st.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) {
+ }
+
+ }
+*/
+ /**
+ * @test java.sql.Statement#clearBatch(String)
+ */
+ public void testClearBatch() throws SQLException {
+
+ Statement st = null;
+
+ try {
+ st = conn.createStatement();
+ st.addBatch("INSERT INTO zoo VALUES (3,'Tuzik','dog'); ");
+ st.addBatch("INSERT INTO zoo VALUES (4,'Mashka','cat')");
+
+ int[] updateCounts = st.executeBatch();
+ assertEquals(2, updateCounts.length);
+ assertEquals(1, updateCounts[0]);
+ assertEquals(1, updateCounts[1]);
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement();
+ st.addBatch("");
+ st.executeBatch();
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement();
+ st.addBatch(null);
+ st.executeBatch();
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#execute(String sql)
+ *
+ * TODO not pass on SQLite and RI.
+ *
+ */
+ public void testExecute() throws SQLException {
+
+ String[] queries = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "drop table if exists hutch",
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "select animal_id, address from hutch where animal_id=1;",
+ "create view address as select address from hutch where animal_id=2",
+ "drop view address;", "drop table hutch;" };
+ boolean[] results = {true, true, true, true, true, true, true,
+ true, true};
+
+ for (int i = 0; i < queries.length; i++) {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ boolean res = st.execute(queries[i]);
+ assertEquals(results[i], res);
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ String[] inc_queries = {
+ "update zoo_zoo set name='Masha', family='cat' where id=5;",
+ "drop table hutchNO",
+ "insert into hutch (id, animal_id, address) values (1, 2, 10);",
+ "select animal_id, from hutch where animal_id=1;",
+ "drop view address;", "drop table hutch;", "", null };
+
+ for (int i = 0; i < inc_queries.length; i++) {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute(inc_queries[i]);
+ fail("SQLException is not thrown for query: " + inc_queries[i]);
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#execute(String sql, int autoGeneratedKeys)
+ * TODO not supported
+ */
+ /* public void testExecute_String_int() {
+ String[] queries = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "drop table if exists hutch",
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "select animal_id, address from hutch where animal_id=1;",
+ "create view address as select address from hutch where animal_id=2",
+ "drop view address;", "drop table hutch;" };
+
+ for (int i = 0; i < queries.length; i++) {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.execute(queries[i], Statement.NO_GENERATED_KEYS);
+ ResultSet rs = st.getGeneratedKeys();
+ assertFalse(rs.next());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#getConnection()
+ */
+ public void testGetConnection() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ assertSame(conn, st.getConnection());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#getFetchDirection()
+ */
+ public void testGetFetchDirection() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ assertEquals(ResultSet.FETCH_UNKNOWN, st.getFetchDirection());
+ } catch (SQLException e) {
+ fail("SQLException is thrown" + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#setFetchDirection()
+ * TODO not supported
+ */
+/* public void testSetFetchDirection() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ st.setFetchDirection(ResultSet.FETCH_FORWARD);
+ assertEquals(ResultSet.FETCH_FORWARD, st.getFetchDirection());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ try {
+ st = conn.createStatement();
+ st.setFetchDirection(-1);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement();
+ st.setFetchDirection(100);
+ fail("SQLException is not thrown");
+ } catch (SQLException e) {
+ // expected
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#getFetchSize()
+ */
+ public void testGetFetchSize() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ assertEquals(1, st.getFetchSize());
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#setFetchSize()
+ * TODO not supported
+ */
+/* public void testSetFetchSize() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ int rows = 100;
+ for (int i = 0; i < rows; i++) {
+ try {
+ st.setFetchSize(i);
+ assertEquals(i, st.getFetchSize());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.toString());
+ }
+ }
+ try {
+ st.setFetchSize(-1);
+ fail("SQLException is not thrown");
+ } catch (SQLException sqle) {
+ // expected
+ }
+
+ } catch (SQLException e) {
+ fail("SQLException is thrown");
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#setMaxFieldSize(int max)
+ * TODO not supported
+ */
+/* public void testSetMaxFieldSize() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ for (int i = 0; i < 300; i += 50) {
+ try {
+ st.setMaxFieldSize(i);
+ assertEquals(i, st.getMaxFieldSize());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ }
+ try {
+ st.setMaxFieldSize(-1);
+ fail("SQLException isn't thrown");
+ } catch (SQLException sqle) {
+ // expecteds
+ }
+ } catch (SQLException e) {
+ fail("Can't create statement, SQLException is thrown: "
+ + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#getMaxFieldSize()
+ * TODO not supported
+ */
+/* public void testGetMaxFieldSize() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ for (int i = 200; i < 500; i += 50) {
+ try {
+ st.setMaxFieldSize(i);
+ assertEquals(i, st.getMaxFieldSize());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ }
+ } catch (SQLException e) {
+ fail("Can't create statement, SQLException is thrown: "
+ + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#setMaxRows(int max)
+ * TODO not supported
+ */
+ /* public void testSetMaxRows() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ for (int i = 0; i < 300; i += 50) {
+ try {
+ st.setMaxRows(i);
+ assertEquals(i, st.getMaxRows());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ }
+ try {
+ st.setMaxRows(-1);
+ fail("SQLException isn't thrown");
+ } catch (SQLException sqle) {
+ // expecteds
+ }
+ } catch (SQLException e) {
+ fail("Can't create statement, SQLException is thrown: "
+ + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#getMaxRows()
+ * TODO not supported
+ */
+/* public void testGetMaxRows() {
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ for (int i = 200; i < 500; i += 50) {
+ try {
+ st.setMaxRows(i);
+ assertEquals(i, st.getMaxRows());
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown: " + sqle.getMessage());
+ }
+ }
+ } catch (SQLException e) {
+ fail("Can't create statement, SQLException is thrown: "
+ + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#close()
+ * TODO not passed but according to Java Docs
+ */
+ public void testClose() {
+ Statement st = null;
+ try {
+ String[] queries = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "insert into zoo (id, name, family) values (3, 'Vorobey', 'sparrow');",
+ "insert into zoo (id, name, family) values (4, 'Slon', 'elephant');",
+ "select * from zoo" };
+ st = conn.createStatement();
+ for (int i = 0; i < queries.length; i++) {
+ st.execute(queries[i]);
+ }
+ assertNotNull(st.getResultSet());
+ st.close();
+ assertNull(st.getResultSet());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#execute(String sql, int[] columnIndexes)
+ * TODO not supported
+ */
+/* public void testExecute_String_intArray() {
+ Statement st = null;
+ try {
+ String[] queries = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "insert zoo(id, name, family) values (3, 'Vorobey', 'sparrow');",
+ "insert zoo(id, name, family) values (4, 'Slon', 'elephant');",
+ "select * from zoo" };
+ Vector<int[]> array = new Vector<int[]>();
+ array.addElement(null);
+ array.addElement(new int[] { 1, 2, 3 });
+ array.addElement(new int[] { 1, 2, 10, 100 });
+ array.addElement(new int[] {});
+
+ st = conn.createStatement();
+ for (int i = 0; i < queries.length; i++) {
+ st.execute(queries[i], (int[]) array.elementAt(i));
+ }
+ assertNotNull(st.getResultSet());
+ st.close();
+ assertNull(st.getResultSet());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#execute(String sql, String[] columnNames)
+ */
+/* public void testExecute_String_StringArray() {
+ Statement st = null;
+ try {
+ String[] queries = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "insert zoo(id, name, family) values (3, 'Vorobey', 'sparrow');",
+ "insert zoo(id, name, family) values (4, 'Slon', 'elephant');",
+ "select * from zoo" };
+ Vector<String[]> array = new Vector<String[]>();
+ array.addElement(null);
+ array.addElement(new String[] { "", "", "", "", "", "", "", "" });
+ array.addElement(new String[] { "field 1", "", "field2" });
+ array.addElement(new String[] { "id", "family", "name" });
+
+ st = conn.createStatement();
+ for (int i = 0; i < queries.length; i++) {
+ st.execute(queries[i], (String[]) array.elementAt(i));
+ }
+ assertNotNull(st.getResultSet());
+ st.close();
+ assertNull(st.getResultSet());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#executeBatch()
+ */
+ public void testExecuteBatch() {
+
+ String[] queries = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "drop table if exists hutch",
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "create view address as select address from hutch where animal_id=2",
+ "drop view address;", "drop table hutch;" };
+
+ int[] result = { 1, 1, 1, 1, 1, 1, 1, 1 };
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ assertEquals(0, st.executeBatch().length);
+ for (int i = 0; i < queries.length; i++) {
+ st.addBatch(queries[i]);
+ }
+ int[] resArray = st.executeBatch();
+ assertTrue(java.util.Arrays.equals(result, resArray));
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement();
+ st.addBatch("select * from zoo");
+ st.executeBatch();
+ } catch (BatchUpdateException bue) {
+ fail("BatchUpdateException is thrown: " + bue.toString());
+ } catch (SQLException sqle) {
+ fail("Unknown SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#executeQuery(String sql)
+ */
+ public void testExecuteQuery_String() {
+
+ String[] queries1 = { "select * from zoo",
+ "select name, family from zoo where id = 1" };
+
+ String[] queries2 = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "drop table if exists hutch",
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "create view address as select address from hutch where animal_id=2",
+ "drop view address;", "drop table hutch;", "select from zoo" };
+
+ Statement st = null;
+
+ try {
+ st = conn.createStatement();
+ for (int i = 0; i < queries1.length; i++) {
+ try {
+ ResultSet rs = st.executeQuery(queries1[i]);
+ assertNotNull(rs);
+ } catch (SQLException sqle) {
+ fail("SQLException is thrown for query: " + queries1[i]);
+ }
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ try {
+ st = conn.createStatement();
+ for (int i = 0; i < queries2.length; i++) {
+ try {
+ st.executeQuery(queries2[i]);
+ fail("SQLException is not thrown for query: " + queries2[i]);
+ } catch (SQLException sqle) {
+ // expected
+ }
+ }
+ } catch (SQLException sqle) {
+ fail("Unknown SQLException is thrown: " + sqle.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+
+ }
+
+ /**
+ * @test java.sql.Statement#executeUpdate(String sql)
+ */
+ public void testExecuteUpdate_String() {
+
+ String[] queries1 = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "drop table if exists hutch",
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "create view address as select address from hutch where animal_id=2",
+ "drop view address;", "drop table hutch;" };
+
+ String[] queries2 = { "select * from zoo",
+ "select name, family from zoo where id = 1" };
+
+ Statement st = null;
+ try {
+ st = conn.createStatement();
+ for (int i = 0; i < queries1.length; i++) {
+ try {
+ st.executeUpdate(queries1[i]);
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ }
+ }
+
+ for (int i = 0; i < queries2.length; i++) {
+ try {
+ st.executeUpdate(queries2[i]);
+ fail("SQLException is not thrown for query: " + queries2[i]);
+ } catch (SQLException e) {
+ // expected
+ }
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+
+ /**
+ * @test java.sql.Statement#executeUpdate(String sql, int[] columnIndexes)
+ *
+ * TODO executeUpdate(String sql, int[] columnIndexes) is not supported
+ */
+/* public void testExecuteUpdate_String_intArray() {
+ Statement st = null;
+ try {
+ String[] queries1 = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "drop table if exists hutch",
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "create view address as select address from hutch where animal_id=2",
+ "drop view address;", "drop table hutch;" };
+
+ Vector<int[]> array = new Vector<int[]>();
+ array.addElement(null);
+ array.addElement(new int[] { 1, 2, 3 });
+ array.addElement(new int[] { 1, 2, 10, 100 });
+ array.addElement(new int[] {});
+ array.addElement(new int[] { 100, 200 });
+ array.addElement(new int[] { -1, 0 });
+ array.addElement(new int[] { 0, 0, 0, 1, 2, 3 });
+ array.addElement(new int[] { -100, -200 });
+
+ st = conn.createStatement();
+ for (int i = 0; i < queries1.length; i++) {
+ st.executeUpdate(queries1[i], (int[]) array.elementAt(i));
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#executeUpdate(String sql, int autoGeneratedKeys)
+ *
+ * TODO executeUpdate(String sql, int autoGeneratedKeys) is not supported
+ */
+/* public void testExecuteUpdate_String_int() {
+ String[] queries = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "drop table if exists hutch",
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "select animal_id, address from hutch where animal_id=1;",
+ "create view address as select address from hutch where animal_id=2",
+ "drop view address;", "drop table hutch;" };
+
+ for (int i = 0; i < queries.length; i++) {
+ Statement st = null;
+ ResultSet rs = null;
+ try {
+ st = conn.createStatement();
+ st.executeUpdate(queries[i], Statement.NO_GENERATED_KEYS);
+ rs = st.getGeneratedKeys();
+ assertFalse(rs.next());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ rs.close();
+ st.close();
+ } catch (Exception ee) {
+ }
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#executeUpdate(String sql, String[] columnNames)
+ *
+ * TODO executeUpdate(String sql, String[] columnNames) is not supported
+ */
+/* public void testExecuteUpdate_String_StringArray() {
+ Statement st = null;
+ try {
+ String[] queries = {
+ "update zoo set name='Masha', family='cat' where id=2;",
+ "drop table if exists hutch",
+ "create table hutch (id integer not null, animal_id integer, address char(20), primary key (id));",
+ "insert into hutch (id, animal_id, address) values (1, 2, 'Birds-house, 1');",
+ "insert into hutch (id, animal_id, address) values (2, 1, 'Horse-house, 5');",
+ "create view address as select address from hutch where animal_id=2",
+ "drop view address;", "drop table hutch;" };
+
+ Vector<String[]> array = new Vector<String[]>();
+ array.addElement(null);
+ array.addElement(new String[] { "", "", "", "", "", "", "", "" });
+ array.addElement(new String[] { "field 1", "", "field2" });
+ array.addElement(new String[] { "id", "family", "name" });
+ array
+ .addElement(new String[] { "id", null, "family", null,
+ "name" });
+ array.addElement(new String[] { "id", " ", "name" });
+ array.addElement(new String[] { null, null, null, null });
+ array.addElement(new String[] { " ", "123 21", "~!@#$%^&*()_+ ",
+ null });
+
+ st = conn.createStatement();
+ for (int i = 0; i < queries.length; i++) {
+ st.executeUpdate(queries[i], (String[]) array.elementAt(i));
+ }
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+*/
+ /**
+ * @test java.sql.Statement#getUpdateCount()
+ */
+ public void testGetUpdateCount() {
+ Statement st = null;
+ try {
+ String query = "update zoo set name='Masha', family='cat' where id=2;";
+ st = conn.createStatement();
+ assertEquals(0, st.getUpdateCount());
+ st.executeUpdate(query);
+ assertEquals(1, st.getUpdateCount());
+ query = "update zoo set name='Masha', family='cat' where id=5;";
+ st.executeUpdate(query);
+ assertEquals(0, st.getUpdateCount());
+ } catch (SQLException e) {
+ fail("SQLException is thrown: " + e.getMessage());
+ } finally {
+ try {
+ st.close();
+ } catch (SQLException ee) {
+ }
+ }
+ }
+}
diff --git a/sql/src/test/java/tests/support/DatabaseCreator.java b/sql/src/test/java/tests/support/DatabaseCreator.java
new file mode 100755
index 0000000..8d73c45
--- /dev/null
+++ b/sql/src/test/java/tests/support/DatabaseCreator.java
@@ -0,0 +1,401 @@
+/*
+ * 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.support;
+
+import java.sql.Connection;
+import java.sql.Date;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.sql.Time;
+
+public class DatabaseCreator {
+ public static final int defaultInt = 2;
+
+ public static final String defaultString = "string";
+
+ public static final String defaultCharacter = "chr";
+
+ public static final double defaultDouble = 0.1;
+
+ public static final String TEST_TABLE1 = "table1";
+
+ public static final String TEST_TABLE2 = "table2";
+
+ public static final String TEST_TABLE3 = "table3";
+
+ public static final String TEST_TABLE4 = "table4";
+
+ public static final String SALESPEOPLE_TABLE = "Salespeople";
+
+ public static final String CUSTOMERS_TABLE = "Customers";
+
+ public static final String ORDERS_TABLE = "Orders";
+
+ public static final String PARENT_TABLE = "test_names";
+
+ public static final String FKSTRICT_TABLE = "test_strict";
+
+ public static final String FKCASCADE_TABLE = "test_cascade";
+
+ public static final String TEST_TABLE5 = "test";
+
+ public static final String SIMPLE_TABLE1 = "simple_table1";
+
+ public static final String SIMPLE_TABLE2 = "simple_table2";
+
+ public static final String SIMPLE_TABLE3 = "simple_table3";
+
+ public static final String CREATE_TABLE1 = "CREATE TABLE " + TEST_TABLE1
+ + " (id INTEGER NOT NULL," + " field1 CHAR(100) DEFAULT NULL,"
+ + " field2 DECIMAL " //+ defaultInt
+ + " COMMENT 'field2_rem'," + " field3 DECIMAL," + " fkey INTEGER,"
+ + " PRIMARY KEY (id) FOREIGN KEY (fkey) REFERENCES "
+ + TEST_TABLE3 + "(fk))";
+
+ public static final String CREATE_TABLE2 = "CREATE TABLE " + TEST_TABLE2
+ + " ( " + "finteger integer NOT NULL, " + "ftext text, "
+ + "fcharacter character (5), " + "fdecimal decimal (5,1), "
+ + "fnumeric numeric (4,1), " + "fsmallint smallint, "
+ + "ffloat float, " + "freal real, " + "fdouble double, "
+ + "fdate date," + " ftime time, PRIMARY KEY (finteger))";
+
+ public static final String CREATE_TABLE3 = "CREATE TABLE " + TEST_TABLE3
+ + " (fk INTEGER NOT NULL," + "" + " PRIMARY KEY (fk))";
+
+ public static final String CREATE_TABLE4 = "CREATE TABLE " + TEST_TABLE4
+ + " (fk INTEGER NOT NULL," + " field1 CHAR(100) NOT NULL,"
+ + " PRIMARY KEY (fk))";
+
+ public static final String CREATE_TABLE5 = "CREATE TABLE " + TEST_TABLE5
+ + "( testId INTEGER NOT NULL, testValue CHAR(200))";
+
+ public static final String CREATE_TABLE_SALESPEOPLE = "CREATE TABLE "
+ + SALESPEOPLE_TABLE + " (snum integer, sname character (10),"
+ + " city character (10), comm real, PRIMARY KEY (snum))";
+
+ public static final String CREATE_TABLE_CUSTOMERS = "CREATE TABLE "
+ + CUSTOMERS_TABLE
+ + " (cnum integer, cname character (10), city character (10),"
+ + " rating integer, snum integer, PRIMARY KEY (cnum))";
+
+ public static final String CREATE_TABLE_ORDERS = "CREATE TABLE "
+ + ORDERS_TABLE
+ + " (onum integer, amt real, odate date, cnum integer,"
+ + " snum integer, PRIMARY KEY (onum))";
+
+ public static final String CREATE_TABLE_PARENT = "CREATE TABLE "
+ + PARENT_TABLE + "(id INTEGER NOT NULL, "
+ + "name CHAR(200), PRIMARY KEY(id))";
+
+ public static final String CREATE_TABLE_FKSTRICT = "CREATE TABLE "
+ + FKSTRICT_TABLE + "(id INTEGER NOT NULL," + "name_id INTEGER,"
+ + "value CHAR(200), PRIMARY KEY(id), "
+ + "CONSTRAINT fk1 FOREIGN KEY (name_id) " + "REFERENCES "
+ + PARENT_TABLE + " (id) " + "ON DELETE RESTRICT "
+ + "ON UPDATE RESTRICT)";
+
+ public static final String CREATE_TABLE_FKCASCADE = "CREATE TABLE "
+ + FKCASCADE_TABLE + "(id INTEGER NOT NULL," + "name_id INTEGER,"
+ + "value CHAR(200), PRIMARY KEY(id), "
+ + "CONSTRAINT fk2 FOREIGN KEY (name_id) " + "REFERENCES "
+ + PARENT_TABLE + " (id) " + "ON DELETE CASCADE "
+ + "ON UPDATE CASCADE)";
+
+ public static final String CREATE_TABLE_SIMPLE1 = "CREATE TABLE "
+ + SIMPLE_TABLE1 + "(id INTEGER NOT NULL," + "speed INTEGER,"
+ + "size INTEGER)";
+
+ public static final String CREATE_TABLE_SIMPLE2 = "CREATE TABLE "
+ + SIMPLE_TABLE2 + "(id INTEGER NOT NULL," + "speed INTEGER,"
+ + "size INTEGER)";
+
+ public static final String CREATE_TABLE_SIMPLE3 = "CREATE TABLE "
+ + SIMPLE_TABLE3 + "(id INTEGER NOT NULL," + "speed INTEGER)";
+
+ public static final String DROP_TABLE1 = "DROP TABLE " + TEST_TABLE1;
+
+ public static final String DROP_TABLE2 = "DROP TABLE " + TEST_TABLE2;
+
+ public static final String DROP_TABLE3 = "DROP TABLE " + TEST_TABLE3;
+
+ public static final String DROP_TABLE4 = "DROP TABLE " + TEST_TABLE4;
+
+ public static final String DROP_TABLE5 = "DROP TABLE " + TEST_TABLE5;
+
+ public static final String DROP_TABLE_CUSTOMERS = "DROP TABLE "
+ + CUSTOMERS_TABLE;
+
+ public static final String DROP_TABLE_ORDERS = "DROP TABLE " + ORDERS_TABLE;
+
+ public static final String DROP_TABLE_SALESPEOPLE = "DROP TABLE "
+ + SALESPEOPLE_TABLE;
+
+ public static final String DROP_TABLE_PARENT = "DROP TABLE " + PARENT_TABLE;
+
+ public static final String DROP_TABLE_FKSTRICT = "DROP TABLE "
+ + FKSTRICT_TABLE;
+
+ public static final String DROP_TABLE_FKCASCADE = "DROP TABLE "
+ + FKCASCADE_TABLE;
+
+ public static final String DROP_TABLE_SIMPLE1 = "DROP TABLE "
+ + SIMPLE_TABLE1;
+
+ public static final String DROP_TABLE_SIMPLE2 = "DROP TABLE "
+ + SIMPLE_TABLE2;
+
+ public static final String DROP_TABLE_SIMPLE3 = "DROP TABLE "
+ + SIMPLE_TABLE3;
+
+ public static final String INSERT_SALESPEOPLE1 = " INSERT INTO "
+ + SALESPEOPLE_TABLE + " (snum, sname, city, comm) "
+ + "VALUES (1001, 'Peel', 'London', .12)";
+
+ public static final String INSERT_SALESPEOPLE2 = " INSERT INTO "
+ + SALESPEOPLE_TABLE + " (snum, sname, city, comm) "
+ + "VALUES (1002, 'Serres', 'SanJose', .13)";
+
+ public static final String INSERT_SALESPEOPLE3 = " INSERT INTO "
+ + SALESPEOPLE_TABLE + " (snum, sname, city, comm) "
+ + "VALUES (1004, 'Motika', 'London', .11)";
+
+ public static final String INSERT_SALESPEOPLE4 = " INSERT INTO "
+ + SALESPEOPLE_TABLE + " (snum, sname, city, comm) "
+ + "VALUES (1007, 'Rifkin', 'Barcelona', .15)";
+
+ public static final String INSERT_SALESPEOPLE5 = " INSERT INTO "
+ + SALESPEOPLE_TABLE + " (snum, sname, city, comm) "
+ + "VALUES (1003, 'Axelrod', 'NewYork', .10)";
+
+ public static final String INSERT_SALESPEOPLE6 = " INSERT INTO "
+ + SALESPEOPLE_TABLE + " (snum, sname, city, comm) "
+ + "VALUES (1013, 'Simpson', 'Kasan', .25)";
+
+ public static final String INSERT_CUSTOMERS1 = " INSERT INTO "
+ + CUSTOMERS_TABLE + " (cnum, cname, city, rating, snum)"
+ + " VALUES (2001, 'Hoffman', 'London', 100, 1001)";
+
+ public static final String INSERT_CUSTOMERS2 = " INSERT INTO "
+ + CUSTOMERS_TABLE + " (cnum, cname, city, rating, snum) "
+ + "VALUES (2002, 'Giovanni', 'Rome', 200, 1003)";
+
+ public static final String INSERT_CUSTOMERS3 = " INSERT INTO "
+ + CUSTOMERS_TABLE + " (cnum, cname, city, rating, snum) "
+ + "VALUES (2003, 'Liu', 'SanJose', 200, 1002)";
+
+ public static final String INSERT_CUSTOMERS4 = " INSERT INTO "
+ + CUSTOMERS_TABLE + " (cnum, cname, city, rating, snum) "
+ + "VALUES (2004, 'Grass', 'Berlin', 300, 1002)";
+
+ public static final String INSERT_CUSTOMERS5 = " INSERT INTO "
+ + CUSTOMERS_TABLE + " (cnum, cname, city, rating, snum) "
+ + "VALUES (2006, 'Clemens', 'London', 100, 1001)";
+
+ public static final String INSERT_CUSTOMERS6 = " INSERT INTO "
+ + CUSTOMERS_TABLE + " (cnum, cname, city, rating, snum) "
+ + "VALUES (2008, 'Cisneros', 'SanJose', 300, 1007)";
+
+ public static final String INSERT_CUSTOMERS7 = " INSERT INTO "
+ + CUSTOMERS_TABLE + " (cnum, cname, city, rating, snum) "
+ + "VALUES (2007, 'Pereira', 'Rome', 100, 1004)";
+
+ public static final String INSERT_ORDERS1 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3001, 18.69, 10/03/1990, 2008, 1007)";
+
+ public static final String INSERT_ORDERS2 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3003, 767.19, 10/03/1990, 2001, 1001)";
+
+ public static final String INSERT_ORDERS3 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3002, 1900.10, 10/03/1990, 2007, 1004)";
+
+ public static final String INSERT_ORDERS4 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3005, 5160.45, 10/03/1990, 2003, 1002)";
+
+ public static final String INSERT_ORDERS5 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3006, 1098.16, 10/03/1990, 2008, 1007)";
+
+ public static final String INSERT_ORDERS6 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3009, 1713.23, 10/04/1990, 2002, 1003)";
+
+ public static final String INSERT_ORDERS7 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3007, 75.75, 10/04/1990, 2004, 1002)";
+
+ public static final String INSERT_ORDERS8 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3008, 4723.01, 10/05/1990, 2006, 1001)";
+
+ public static final String INSERT_ORDERS9 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3010, 1309.95, 10/06/1990, 2004, 1002)";
+
+ public static final String INSERT_ORDERS10 = " INSERT INTO " + ORDERS_TABLE
+ + " (onum, amt, odate, cnum, snum) "
+ + "VALUES (3011, 9891.88, 10/06/1990, 2006, 1001)";
+
+ public static void fillParentTable(Connection conn) throws SQLException {
+ Statement statement = conn.createStatement();
+ statement
+ .execute("INSERT INTO " + PARENT_TABLE + " VALUES(1, 'test1')");
+ statement.execute("INSERT INTO " + PARENT_TABLE + " VALUES(2,'test2')");
+ statement
+ .execute("INSERT INTO " + PARENT_TABLE + " VALUES(3, 'test3')");
+ }
+
+ public static void fillFKStrictTable(Connection conn) throws SQLException {
+ Statement statement = conn.createStatement();
+ statement.execute("INSERT INTO " + FKSTRICT_TABLE
+ + " VALUES(1, 1, '1')");
+ statement.execute("INSERT INTO " + FKSTRICT_TABLE
+ + " VALUES(2, 2, '2')");
+ statement.execute("INSERT INTO " + FKSTRICT_TABLE
+ + " VALUES(3, 1, '3')");
+ }
+
+ public static void fillFKCascadeTable(Connection conn) throws SQLException {
+ Statement statement = conn.createStatement();
+ statement.execute("INSERT INTO " + FKCASCADE_TABLE
+ + " VALUES(1, 1, '1')");
+ statement.execute("INSERT INTO " + FKCASCADE_TABLE
+ + " VALUES(2, 2, '2')");
+ statement.execute("INSERT INTO " + FKCASCADE_TABLE
+ + " VALUES(3, 1, '3')");
+ }
+
+ public static void fillSimpleTable1(Connection conn) throws SQLException {
+ Statement statement = conn.createStatement();
+ statement
+ .execute("INSERT INTO " + SIMPLE_TABLE1 + " VALUES(1, 10, 20)");
+ statement.execute("INSERT INTO " + SIMPLE_TABLE1 + " VALUES(2, 5, 7)");
+ }
+
+ public static void fillSimpleTable3(Connection conn) throws SQLException {
+ Statement statement = conn.createStatement();
+ statement.execute("INSERT INTO " + SIMPLE_TABLE3 + " VALUES(1, 8)");
+ statement.execute("INSERT INTO " + SIMPLE_TABLE3 + " VALUES(2, 6)");
+ statement.execute("INSERT INTO " + SIMPLE_TABLE3 + " VALUES(3, 4)");
+ }
+
+ public static void fillSalesPeopleTable(Connection conn)
+ throws SQLException {
+ Statement statement = conn.createStatement();
+
+ statement.execute(DatabaseCreator.INSERT_SALESPEOPLE1);
+ statement.execute(DatabaseCreator.INSERT_SALESPEOPLE2);
+ statement.execute(DatabaseCreator.INSERT_SALESPEOPLE3);
+ statement.execute(DatabaseCreator.INSERT_SALESPEOPLE4);
+ statement.execute(DatabaseCreator.INSERT_SALESPEOPLE5);
+ statement.execute(DatabaseCreator.INSERT_SALESPEOPLE6);
+ }
+
+ public static void fillCustomersTable(Connection conn) throws SQLException {
+ Statement statement = conn.createStatement();
+
+ statement.execute(DatabaseCreator.INSERT_CUSTOMERS1);
+ statement.execute(DatabaseCreator.INSERT_CUSTOMERS2);
+ statement.execute(DatabaseCreator.INSERT_CUSTOMERS3);
+ statement.execute(DatabaseCreator.INSERT_CUSTOMERS4);
+ statement.execute(DatabaseCreator.INSERT_CUSTOMERS5);
+ statement.execute(DatabaseCreator.INSERT_CUSTOMERS6);
+ statement.execute(DatabaseCreator.INSERT_CUSTOMERS7);
+ }
+
+ public static void fillOrdersTable(Connection conn) throws SQLException {
+ Statement statement = conn.createStatement();
+
+ statement.execute(DatabaseCreator.INSERT_ORDERS1);
+ statement.execute(DatabaseCreator.INSERT_ORDERS2);
+ statement.execute(DatabaseCreator.INSERT_ORDERS3);
+ statement.execute(DatabaseCreator.INSERT_ORDERS4);
+ statement.execute(DatabaseCreator.INSERT_ORDERS5);
+ statement.execute(DatabaseCreator.INSERT_ORDERS6);
+ statement.execute(DatabaseCreator.INSERT_ORDERS7);
+ statement.execute(DatabaseCreator.INSERT_ORDERS8);
+ statement.execute(DatabaseCreator.INSERT_ORDERS9);
+ statement.execute(DatabaseCreator.INSERT_ORDERS10);
+ }
+
+ public static void fillTestTable1(Connection conn, int numberOfRecords)
+ throws SQLException {
+ Statement statement = conn.createStatement();
+ for (int id = 0; id < numberOfRecords; id++) {
+ String value = DatabaseCreator.defaultString + id;
+ String insertQuery = "INSERT INTO " + DatabaseCreator.TEST_TABLE1
+ + " (id, field1, field2, field3) VALUES(" + id + ", '"
+ + value + "', " + id + ", " + id + ")";
+ statement.execute(insertQuery);
+ }
+ }
+
+ public static void fillTestTable2(Connection conn, int startID, int endID,
+ long time) throws SQLException {
+ Statement statement = conn.createStatement();
+ for (int id = startID; id <= endID; id++) {
+ double value = id + DatabaseCreator.defaultDouble;
+ String insertQuery = "INSERT INTO " + DatabaseCreator.TEST_TABLE2
+ + " (finteger, ftext, fcharacter, fdecimal, fnumeric,"
+ + " fsmallint, ffloat, freal, fdouble, fdate, ftime)"
+ + " VALUES (" + id + ", '" + DatabaseCreator.defaultString
+ + id + "'," + " '" + DatabaseCreator.defaultCharacter + id
+ + "', " + value + ", " + value + "," + value + ", " + value
+ + ", " + value + "," + value + ", '"
+ + new Date(time).toString() + "'," + " '"
+ + new Time(time).toString() + "')";
+ statement.execute(insertQuery);
+ }
+ }
+
+ public static void fillTestTable2(Connection conn, int numberOfRecords)
+ throws SQLException {
+ Statement statement = conn.createStatement();
+ for (int id = 0; id < numberOfRecords; id++) {
+ double value = id + DatabaseCreator.defaultDouble;
+ String insertQuery = "INSERT INTO " + DatabaseCreator.TEST_TABLE2
+ + " (finteger, ftext, fcharacter, fdecimal, fnumeric,"
+ + " fsmallint, ffloat, freal, fdouble)" + " VALUES (" + id
+ + ", '" + DatabaseCreator.defaultString + id + "'," + " '"
+ + DatabaseCreator.defaultCharacter + id + "', " + value
+ + ", " + value + "," + value + ", " + value + ", " + value
+ + "," + value + ")";
+ statement.execute(insertQuery);
+ }
+ }
+
+ public static void fillTestTable4(Connection conn, int numberOfRecords)
+ throws SQLException {
+ Statement statement = conn.createStatement();
+ for (int id = 0; id < numberOfRecords; id++) {
+ String insertQuery = "INSERT INTO " + DatabaseCreator.TEST_TABLE4
+ + " (fk, field1) VALUES(" + id + ", \""
+ + DatabaseCreator.defaultString + id + "\")";
+ statement.execute(insertQuery);
+ }
+ }
+
+ public static void fillTestTable5(Connection conn) throws SQLException {
+ Statement statement = conn.createStatement();
+ statement.execute("INSERT INTO " + TEST_TABLE5 + " VALUES(1, '0')");
+ statement.execute("INSERT INTO " + TEST_TABLE5 + " VALUES(2, '3')");
+ statement.execute("INSERT INTO " + TEST_TABLE5 + " VALUES(3, '4')");
+ }
+}
diff --git a/sql/src/test/java/tests/support/Support_SQL.java b/sql/src/test/java/tests/support/Support_SQL.java
new file mode 100644
index 0000000..7c42163
--- /dev/null
+++ b/sql/src/test/java/tests/support/Support_SQL.java
@@ -0,0 +1,90 @@
+/*
+ * 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.support;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.util.Properties;
+
+public class Support_SQL {
+
+ public static String sqlDriver = null;
+
+ public static String sqlLogin = null;
+
+ public static String sqlCatalog = null;
+
+ public static String sqlHost = null;
+
+ public static String sqlUrl = null;
+
+ public static String sqlPassword = null;
+
+ public static String sqlUser = null;
+
+ public static int sqlMaxConnections = 1;
+
+ public static int sqlMaxTasks = 0;
+
+ public static void loadDriver() {
+ try {
+ loadProperties(Class.forName("tests.support.Support_SQL")
+ .getResourceAsStream("/connection.properties"));
+ Class.forName(sqlDriver).newInstance();
+ } catch (Exception ex) {
+ System.err.println("Unexpected exception " + ex.toString());
+ }
+ }
+
+ public static Connection getConnection() throws SQLException {
+ return DriverManager.getConnection(Support_SQL.sqlUrl,
+ Support_SQL.sqlLogin, Support_SQL.sqlPassword);
+ }
+
+ public static Connection getConnection(String url, String login,
+ String password) throws SQLException {
+
+ return DriverManager.getConnection(url, login, password);
+ }
+
+ public static boolean isEqual(byte[] b1, int off1, byte[] b2, int off2,
+ int len) {
+ for (int i = 0; i < len; ++i)
+ if (b1[i + off1] != b2[i + off2])
+ return false;
+ return true;
+ }
+
+ private static void loadProperties(InputStream fileName) throws IOException {
+ Properties properties = new Properties();
+ properties.load(fileName);
+ sqlDriver = properties.getProperty("sqlDriver");
+ sqlLogin = properties.getProperty("sqlLogin");
+ sqlCatalog = properties.getProperty("sqlCatalog");
+ sqlHost = properties.getProperty("sqlHost");
+ sqlUrl = properties.getProperty("sqlUrlPrefix") + sqlHost + "/"
+ + sqlCatalog;
+ sqlPassword = properties.getProperty("sqlPassword");
+ sqlUser = properties.getProperty("sqlUser");
+ sqlMaxConnections = Integer.parseInt(properties
+ .getProperty("sqlMaxConnections"));
+ sqlMaxTasks = Integer.parseInt(properties.getProperty("sqlMaxTasks"));
+ }
+}
diff --git a/sql/src/test/java/tests/support/ThreadPool.java b/sql/src/test/java/tests/support/ThreadPool.java
new file mode 100644
index 0000000..84f22a9
--- /dev/null
+++ b/sql/src/test/java/tests/support/ThreadPool.java
@@ -0,0 +1,116 @@
+/*
+ * 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.support;
+
+import java.util.LinkedList;
+
+public class ThreadPool extends ThreadGroup {
+
+ private boolean isAlive;
+
+ private LinkedList<Runnable> taskQueue;
+
+ private int threadID;
+
+ private static int threadPoolID;
+
+ public ThreadPool(int numThreads) {
+ super("ThreadPool-" + (threadPoolID++));
+ setDaemon(true);
+
+ isAlive = true;
+
+ taskQueue = new LinkedList<Runnable>();
+ for (int i = 0; i < numThreads; i++) {
+ new PooledThread().start();
+ }
+ }
+
+ public synchronized void runTask(Runnable task) {
+ if (!isAlive) {
+ throw new IllegalStateException();
+ }
+ if (task != null) {
+ taskQueue.add(task);
+ notify();
+ }
+ }
+
+ protected synchronized Runnable getTask() throws InterruptedException {
+ while (taskQueue.size() == 0) {
+ if (!isAlive) {
+ return null;
+ }
+ wait();
+ }
+ return (Runnable) taskQueue.removeFirst();
+ }
+
+ public synchronized void close() {
+ if (isAlive) {
+ isAlive = false;
+ taskQueue.clear();
+ interrupt();
+ }
+ }
+
+ public void join() {
+ synchronized (this) {
+ isAlive = false;
+ notifyAll();
+ }
+
+ Thread[] threads = new Thread[activeCount()];
+ int count = enumerate(threads);
+ for (int i = 0; i < count; i++) {
+ try {
+ threads[i].join();
+ } catch (InterruptedException ex) {
+ System.err.println(ex.getMessage());
+ }
+ }
+ }
+
+ private class PooledThread extends Thread {
+
+ public PooledThread() {
+ super(ThreadPool.this, "PooledThread-" + (threadID++));
+ }
+
+ public void run() {
+ while (!isInterrupted()) {
+
+ Runnable task = null;
+ try {
+ task = getTask();
+ } catch (InterruptedException ex) {
+ System.err.println(ex.getMessage());
+ }
+
+ if (task == null) {
+ return;
+ }
+
+ try {
+ task.run();
+ } catch (Throwable t) {
+ System.err.println(t.getMessage());
+ }
+ }
+ }
+ }
+}
diff --git a/sql/src/test/resources/connection.properties b/sql/src/test/resources/connection.properties
new file mode 100644
index 0000000..2e49346
--- /dev/null
+++ b/sql/src/test/resources/connection.properties
@@ -0,0 +1,9 @@
+sqlDriver = SQLite.JDBCDriver
+sqlLogin =
+sqlCatalog =sqliteTest.db
+sqlHost =
+sqlUrlPrefix = jdbc:sqlite:
+sqlPassword =
+sqlUser =
+sqlMaxConnections = 30
+sqlMaxTasks = 10000
diff --git a/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.golden.ser b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.golden.ser
new file mode 100644
index 0000000..d20eed1
--- /dev/null
+++ b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/BatchUpdateExceptionTest.golden.ser
Binary files differ
diff --git a/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.golden.ser b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.golden.ser
new file mode 100644
index 0000000..9ecd6e1
--- /dev/null
+++ b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/DataTruncationTest.golden.ser
Binary files differ
diff --git a/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.golden.ser b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.golden.ser
new file mode 100644
index 0000000..6e58660
--- /dev/null
+++ b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/SQLExceptionTest.golden.ser
Binary files differ
diff --git a/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.golden.ser b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.golden.ser
new file mode 100644
index 0000000..be37cb8
--- /dev/null
+++ b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/SQLWarningTest.golden.ser
Binary files differ
diff --git a/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/TimestampTest.golden.ser b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/TimestampTest.golden.ser
new file mode 100644
index 0000000..4e51a0a
--- /dev/null
+++ b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/java/sql/TimestampTest.golden.ser
Binary files differ
diff --git a/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.golden.ser b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.golden.ser
new file mode 100644
index 0000000..642e2fc
--- /dev/null
+++ b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/ConnectionEventTest.golden.ser
Binary files differ
diff --git a/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/rowset/RowSetMetaDataImplTest.golden.ser b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/rowset/RowSetMetaDataImplTest.golden.ser
new file mode 100644
index 0000000..edd8bee
--- /dev/null
+++ b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/rowset/RowSetMetaDataImplTest.golden.ser
Binary files differ
diff --git a/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/rowset/serial/SerialExceptionTest.golden.ser b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/rowset/serial/SerialExceptionTest.golden.ser
new file mode 100644
index 0000000..71ed471
--- /dev/null
+++ b/sql/src/test/resources/serialization/org/apache/harmony/sql/tests/javax/sql/rowset/serial/SerialExceptionTest.golden.ser
Binary files differ