From e3ec046490886bea7cbdbd0592f948adc25c2de4 Mon Sep 17 00:00:00 2001 From: Lukas Eder Date: Fri, 15 Feb 2013 20:49:03 +0100 Subject: [PATCH] [#2202] Add Mock JDBC objects for unit testing with jOOQ --- .../src/org/jooq/test/jOOQAbstractTest.java | 70 + .../main/java/org/jooq/impl/ResultImpl.java | 3 +- .../java/org/jooq/impl/ResultSetImpl.java | 1351 ----------------- .../org/jooq/tools/jdbc/MockConnection.java | 406 +++++ .../org/jooq/tools/jdbc/MockDataProvider.java | 140 ++ .../jooq/tools/jdbc/MockExecuteContext.java | 214 +++ .../java/org/jooq/tools/jdbc/MockResult.java | 93 ++ .../org/jooq/tools/jdbc/MockResultSet.java | 1157 ++++++++++++++ .../tools/jdbc/MockResultSetMetaData.java | 271 ++++ .../org/jooq/tools/jdbc/MockStatement.java | 1322 ++++++++++++++++ 10 files changed, 3675 insertions(+), 1352 deletions(-) delete mode 100644 jOOQ/src/main/java/org/jooq/impl/ResultSetImpl.java create mode 100644 jOOQ/src/main/java/org/jooq/tools/jdbc/MockConnection.java create mode 100644 jOOQ/src/main/java/org/jooq/tools/jdbc/MockDataProvider.java create mode 100644 jOOQ/src/main/java/org/jooq/tools/jdbc/MockExecuteContext.java create mode 100644 jOOQ/src/main/java/org/jooq/tools/jdbc/MockResult.java create mode 100644 jOOQ/src/main/java/org/jooq/tools/jdbc/MockResultSet.java create mode 100644 jOOQ/src/main/java/org/jooq/tools/jdbc/MockResultSetMetaData.java create mode 100644 jOOQ/src/main/java/org/jooq/tools/jdbc/MockStatement.java diff --git a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java index 55d6d36720..42f9d66dd7 100644 --- a/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java +++ b/jOOQ-test/src/org/jooq/test/jOOQAbstractTest.java @@ -51,6 +51,7 @@ import java.sql.SQLException; import java.sql.SQLSyntaxErrorException; import java.sql.Statement; import java.sql.Timestamp; +import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; import java.util.List; @@ -60,12 +61,15 @@ import java.util.UUID; import javax.swing.UIManager; +import junit.framework.Assert; + import org.jooq.ArrayRecord; import org.jooq.DAO; import org.jooq.DataType; import org.jooq.ExecuteType; import org.jooq.Field; import org.jooq.ForeignKey; +import org.jooq.Query; import org.jooq.Record; import org.jooq.Record1; import org.jooq.Record2; @@ -132,6 +136,10 @@ import org.jooq.test._.testcases.ValuesConstructorTests; import org.jooq.tools.JooqLogger; import org.jooq.tools.StopWatch; import org.jooq.tools.StringUtils; +import org.jooq.tools.jdbc.MockConnection; +import org.jooq.tools.jdbc.MockDataProvider; +import org.jooq.tools.jdbc.MockExecuteContext; +import org.jooq.tools.jdbc.MockResult; import org.jooq.tools.reflect.ReflectException; import org.jooq.types.UByte; import org.jooq.types.UInteger; @@ -452,6 +460,68 @@ public abstract class jOOQAbstractTest< if (!connectionInitialised) { connectionInitialised = true; connection = getConnection0(null, null); + final Connection c = connection; + + // Reactivate this, to enable mock connections + if (false) + connection = new MockConnection(new MockDataProvider() { + + @Override + public MockResult[] execute(MockExecuteContext context) throws SQLException { + Executor executor = new Executor(c, getDialect()); + + if (context.isSingleBatch()) { + Query query = executor.query(context.getSQL(), new Object[context.getBatchBindings()[0].length]); + int[] result = + executor.batch(query) + .bind(context.getBatchBindings()) + .execute(); + + MockResult[] r = new MockResult[result.length]; + for (int i = 0; i < r.length; i++) { + r[i] = new MockResult(result[i], null); + } + + return r; + } + else if (context.isMultiBatch()) { + List queries = new ArrayList(); + + for (String sql : context.getBatchSQL()) { + queries.add(executor.query(sql)); + } + + int[] result = + executor.batch(queries) + .execute(); + + MockResult[] r = new MockResult[result.length]; + for (int i = 0; i < r.length; i++) { + r[i] = new MockResult(result[i], null); + } + + return r; + } + else if (context.getSQL().toLowerCase().matches("(?s:\\W*(select|with).*)")) { + List> result = executor.fetchMany(context.getSQL(), context.getBindings()); + MockResult[] r = new MockResult[result.size()]; + + for (int i = 0; i < result.size(); i++) { + r[i] = new MockResult(result.get(i).size(), result.get(i)); + } + + return r; + } + else { + int result = executor.execute(context.getSQL(), context.getBindings()); + + MockResult[] r = new MockResult[1]; + r[0] = new MockResult(result, null); + + return r; + } + } + }); if (RUN_CONSOLE_IN_PROCESS) { try { diff --git a/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java b/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java index 11360e1811..13007140c1 100644 --- a/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java +++ b/jOOQ/src/main/java/org/jooq/impl/ResultImpl.java @@ -73,6 +73,7 @@ import org.jooq.Table; import org.jooq.exception.InvalidResultException; import org.jooq.tools.Convert; import org.jooq.tools.StringUtils; +import org.jooq.tools.jdbc.MockResultSet; import org.jooq.tools.json.JSONObject; import org.w3c.dom.Document; @@ -1020,7 +1021,7 @@ class ResultImpl implements Result, AttachableInternal { @Override public final ResultSet intoResultSet() { - return new ResultSetImpl(this); + return new MockResultSet(this); } @Override diff --git a/jOOQ/src/main/java/org/jooq/impl/ResultSetImpl.java b/jOOQ/src/main/java/org/jooq/impl/ResultSetImpl.java deleted file mode 100644 index 6b23244c83..0000000000 --- a/jOOQ/src/main/java/org/jooq/impl/ResultSetImpl.java +++ /dev/null @@ -1,1351 +0,0 @@ -/** - * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com - * All rights reserved. - * - * This software is licensed to you under the Apache License, Version 2.0 - * (the "License"); You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * - * . Redistributions of source code must retain the above copyright notice, this - * list of conditions and the following disclaimer. - * - * . Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation - * and/or other materials provided with the distribution. - * - * . Neither the name "jOOQ" nor the names of its contributors may be - * used to endorse or promote products derived from this software without - * specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ -package org.jooq.impl; - -import java.io.ByteArrayInputStream; -import java.io.InputStream; -import java.io.Reader; -import java.io.Serializable; -import java.io.StringReader; -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.NClob; -import java.sql.Ref; -import java.sql.ResultSet; -import java.sql.ResultSetMetaData; -import java.sql.RowId; -import java.sql.SQLException; -import java.sql.SQLFeatureNotSupportedException; -import java.sql.SQLWarning; -import java.sql.SQLXML; -import java.sql.Statement; -import java.sql.Time; -import java.sql.Timestamp; -import java.util.Calendar; -import java.util.Map; - -import org.jooq.AttachableInternal; -import org.jooq.Configuration; -import org.jooq.Field; -import org.jooq.Record; -import org.jooq.Result; -import org.jooq.Schema; -import org.jooq.Table; -import org.jooq.TableField; -import org.jooq.tools.jdbc.JDBC41ResultSet; -import org.jooq.types.UNumber; - -/** - * @author Lukas Eder - */ -class ResultSetImpl extends JDBC41ResultSet implements ResultSet, Serializable { - - /** - * Generated UID - */ - private static final long serialVersionUID = -2292216936424437750L; - - private Result result; - private transient int index; - private transient boolean wasNull; - - ResultSetImpl(Result result) { - this.result = result; - } - - // ------------------------------------------------------------------------- - // XXX: Unsupported implementations - // ------------------------------------------------------------------------- - - @Override - public final T unwrap(Class iface) throws SQLException { - return null; - } - - @Override - public final boolean isWrapperFor(Class iface) throws SQLException { - return false; - } - - // ------------------------------------------------------------------------- - // XXX: ResultSet operations - // ------------------------------------------------------------------------- - - private final void checkNotClosed() throws SQLException { - if (result == null) { - throw new SQLException("ResultSet is already closed"); - } - } - - private final void checkInRange() throws SQLException { - checkNotClosed(); - - if (index <= 0 || index > result.size()) { - throw new SQLException("ResultSet index is at an illegal position : " + index); - } - } - - private final void checkField(String columnLabel) throws SQLException { - if (result.field(columnLabel) == null) { - throw new SQLException("Unknown column label : " + columnLabel); - } - } - - private final void checkField(int columnIndex) throws SQLException { - if (result.field(columnIndex - 1) == null) { - throw new SQLException("Unknown column index : " + columnIndex); - } - } - - @Override - public final boolean next() throws SQLException { - return relative(1); - } - - @Override - public final boolean previous() throws SQLException { - return relative(-1); - } - - @Override - public final boolean absolute(int row) throws SQLException { - if (result.size() > 0) { - if (row > 0) { - if (row <= result.size()) { - index = row; - return true; - } - else { - afterLast(); - return false; - } - } - else if (row == 0) { - beforeFirst(); - return false; - } - else { - if (-row <= result.size()) { - index = result.size() + 1 + row; - return true; - } - else { - beforeFirst(); - return false; - } - } - } - else { - return false; - } - } - - @Override - public final boolean relative(int rows) throws SQLException { - checkNotClosed(); - - index += rows; - try { - return (index > 0 && index <= result.size()); - } - - // Be sure we don't go out of bounds - finally { - index = Math.max(index, 0); - index = Math.min(index, result.size() + 1); - } - } - - @Override - public final int getRow() throws SQLException { - return (index > result.size()) ? 0 : index; - } - - @Override - public final void beforeFirst() throws SQLException { - checkNotClosed(); - index = 0; - } - - @Override - public final void afterLast() throws SQLException { - checkNotClosed(); - index = result.size() + 1; - } - - @Override - public final boolean first() throws SQLException { - return absolute(1); - } - - @Override - public final boolean last() throws SQLException { - checkNotClosed(); - return absolute(result.size()); - } - - @Override - public final boolean isFirst() throws SQLException { - checkNotClosed(); - - return (result.size() > 0 && index == 1); - } - - @Override - public final boolean isBeforeFirst() throws SQLException { - checkNotClosed(); - - return (result.size() > 0 && index == 0); - } - - @Override - public final boolean isLast() throws SQLException { - checkNotClosed(); - - return (result.size() > 0 && index == result.size()); - } - - @Override - public final boolean isAfterLast() throws SQLException { - checkNotClosed(); - - return (result.size() > 0 && index > result.size()); - } - - @Override - public final void close() throws SQLException { - checkNotClosed(); - - result = null; - index = 0; - } - - @Override - public final boolean isClosed() throws SQLException { - return result == null; - } - - @Override - public final SQLWarning getWarnings() throws SQLException { - // Warnings are not supported - return null; - } - - @Override - public final void clearWarnings() throws SQLException { - // Warnings are not supported - } - - @Override - public final String getCursorName() throws SQLException { - throw new SQLFeatureNotSupportedException("jOOQ ResultSets don't have a cursor name"); - } - - @Override - public final int findColumn(String columnLabel) throws SQLException { - checkNotClosed(); - - Field field = result.field(columnLabel); - if (field == null) { - throw new SQLException("No such column : " + columnLabel); - } - - return result.fieldsRow().indexOf(field) + 1; - } - - @Override - public final void setFetchDirection(int direction) throws SQLException { - - // Fetch direction is not supported - if (direction != ResultSet.FETCH_FORWARD) { - throw new SQLException("Fetch direction can only be FETCH_FORWARD"); - } - } - - @Override - public final int getFetchDirection() throws SQLException { - - // Fetch direction is not supported - return ResultSet.FETCH_FORWARD; - } - - @Override - public final void setFetchSize(int rows) throws SQLException { - // Fetch size is not supported - } - - @Override - public final int getFetchSize() throws SQLException { - return 0; - } - - @Override - public final int getType() throws SQLException { - return ResultSet.TYPE_SCROLL_INSENSITIVE; - } - - @Override - public final int getConcurrency() throws SQLException { - return ResultSet.CONCUR_READ_ONLY; - } - - @Override - public final int getHoldability() throws SQLException { - return ResultSet.CLOSE_CURSORS_AT_COMMIT; - } - - // ------------------------------------------------------------------------- - // XXX: Getters - // ------------------------------------------------------------------------- - - @Override - public final boolean wasNull() throws SQLException { - checkNotClosed(); - - return wasNull; - } - - @Override - public final ResultSetMetaData getMetaData() throws SQLException { - return new MetaData(); - } - - @Override - public final Statement getStatement() throws SQLException { - return null; - } - - private final T getValue(String columnLabel, Class type) throws SQLException { - checkInRange(); - checkField(columnLabel); - - T value = result.get(index - 1).getValue(columnLabel, type); - wasNull = (value == null); - return value; - } - - private final T getValue(int columnIndex, Class type) throws SQLException { - checkInRange(); - checkField(columnIndex); - - T value = result.get(index - 1).getValue(columnIndex - 1, type); - wasNull = (value == null); - return value; - } - - @Override - public final String getString(int columnIndex) throws SQLException { - return getValue(columnIndex, String.class); - } - - @Override - public final String getString(String columnLabel) throws SQLException { - return getValue(columnLabel, String.class); - } - - @Override - public final String getNString(int columnIndex) throws SQLException { - return getString(columnIndex); - } - - @Override - public final String getNString(String columnLabel) throws SQLException { - return getString(columnLabel); - } - - @Override - public final boolean getBoolean(int columnIndex) throws SQLException { - Boolean value = getValue(columnIndex, Boolean.class); - return wasNull ? false : value; - } - - @Override - public final boolean getBoolean(String columnLabel) throws SQLException { - Boolean value = getValue(columnLabel, Boolean.class); - return wasNull ? false : value; - } - - @Override - public final byte getByte(int columnIndex) throws SQLException { - Byte value = getValue(columnIndex, Byte.class); - return wasNull ? (byte) 0 : value; - } - - @Override - public final byte getByte(String columnLabel) throws SQLException { - Byte value = getValue(columnLabel, Byte.class); - return wasNull ? (byte) 0 : value; - } - - @Override - public final short getShort(int columnIndex) throws SQLException { - Short value = getValue(columnIndex, Short.class); - return wasNull ? (short) 0 : value; - } - - @Override - public final short getShort(String columnLabel) throws SQLException { - Short value = getValue(columnLabel, Short.class); - return wasNull ? (short) 0 : value; - } - - @Override - public final int getInt(int columnIndex) throws SQLException { - Integer value = getValue(columnIndex, Integer.class); - return wasNull ? 0 : value; - } - - @Override - public final int getInt(String columnLabel) throws SQLException { - Integer value = getValue(columnLabel, Integer.class); - return wasNull ? 0 : value; - } - - @Override - public final long getLong(int columnIndex) throws SQLException { - Long value = getValue(columnIndex, Long.class); - return wasNull ? 0L : value; - } - - @Override - public final long getLong(String columnLabel) throws SQLException { - Long value = getValue(columnLabel, Long.class); - return wasNull ? 0L : value; - } - - @Override - public final float getFloat(int columnIndex) throws SQLException { - Float value = getValue(columnIndex, Float.class); - return wasNull ? 0.0f : value; - } - - @Override - public final float getFloat(String columnLabel) throws SQLException { - Float value = getValue(columnLabel, Float.class); - return wasNull ? 0.0f : value; - } - - @Override - public final double getDouble(int columnIndex) throws SQLException { - Double value = getValue(columnIndex, Double.class); - return wasNull ? 0.0 : value; - } - - @Override - public final double getDouble(String columnLabel) throws SQLException { - Double value = getValue(columnLabel, Double.class); - return wasNull ? 0.0 : value; - } - - @Override - public final BigDecimal getBigDecimal(int columnIndex) throws SQLException { - return getValue(columnIndex, BigDecimal.class); - } - - @Override - @Deprecated - public final BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { - return getValue(columnIndex, BigDecimal.class); - } - - @Override - public final BigDecimal getBigDecimal(String columnLabel) throws SQLException { - return getValue(columnLabel, BigDecimal.class); - } - - @Override - @Deprecated - public final BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { - return getValue(columnLabel, BigDecimal.class); - } - - @Override - public final byte[] getBytes(int columnIndex) throws SQLException { - return getValue(columnIndex, byte[].class); - } - - @Override - public final byte[] getBytes(String columnLabel) throws SQLException { - return getValue(columnLabel, byte[].class); - } - - @Override - public final Date getDate(int columnIndex) throws SQLException { - return getValue(columnIndex, Date.class); - } - - @Override - public final Date getDate(int columnIndex, Calendar cal) throws SQLException { - return getValue(columnIndex, Date.class); - } - - @Override - public final Date getDate(String columnLabel) throws SQLException { - return getValue(columnLabel, Date.class); - } - - @Override - public final Date getDate(String columnLabel, Calendar cal) throws SQLException { - return getValue(columnLabel, Date.class); - } - - @Override - public final Time getTime(int columnIndex) throws SQLException { - return getValue(columnIndex, Time.class); - } - - @Override - public final Time getTime(int columnIndex, Calendar cal) throws SQLException { - return getValue(columnIndex, Time.class); - } - - @Override - public final Time getTime(String columnLabel) throws SQLException { - return getValue(columnLabel, Time.class); - } - - @Override - public final Time getTime(String columnLabel, Calendar cal) throws SQLException { - return getValue(columnLabel, Time.class); - } - - @Override - public final Timestamp getTimestamp(int columnIndex) throws SQLException { - return getValue(columnIndex, Timestamp.class); - } - - @Override - public final Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { - return getValue(columnIndex, Timestamp.class); - } - - @Override - public final Timestamp getTimestamp(String columnLabel) throws SQLException { - return getValue(columnLabel, Timestamp.class); - } - - @Override - public final Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { - return getValue(columnLabel, Timestamp.class); - } - - @Override - public final InputStream getAsciiStream(int columnIndex) throws SQLException { - byte[] bytes = getBytes(columnIndex); - return wasNull ? null : new ByteArrayInputStream(bytes); - } - - @Override - public final InputStream getAsciiStream(String columnLabel) throws SQLException { - byte[] bytes = getBytes(columnLabel); - return wasNull ? null : new ByteArrayInputStream(bytes); - } - - @Override - @Deprecated - public final InputStream getUnicodeStream(int columnIndex) throws SQLException { - String string = getString(columnIndex); - return wasNull ? null : new ByteArrayInputStream(string.getBytes()); - } - - @Override - @Deprecated - public final InputStream getUnicodeStream(String columnLabel) throws SQLException { - String string = getString(columnLabel); - return wasNull ? null : new ByteArrayInputStream(string.getBytes()); - } - - @Override - public final Reader getCharacterStream(int columnIndex) throws SQLException { - String string = getString(columnIndex); - return wasNull ? null : new StringReader(string); - } - - @Override - public final Reader getCharacterStream(String columnLabel) throws SQLException { - String string = getString(columnLabel); - return wasNull ? null : new StringReader(string); - } - - @Override - public final Reader getNCharacterStream(int columnIndex) throws SQLException { - return getCharacterStream(columnIndex); - } - - @Override - public final Reader getNCharacterStream(String columnLabel) throws SQLException { - return getCharacterStream(columnLabel); - } - - @Override - public final InputStream getBinaryStream(int columnIndex) throws SQLException { - byte[] bytes = getBytes(columnIndex); - return wasNull ? null : new ByteArrayInputStream(bytes); - } - - @Override - public final InputStream getBinaryStream(String columnLabel) throws SQLException { - byte[] bytes = getBytes(columnLabel); - return wasNull ? null : new ByteArrayInputStream(bytes); - } - - @Override - public final Ref getRef(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type"); - } - - @Override - public final Ref getRef(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type"); - } - - @Override - public final RowId getRowId(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type"); - } - - @Override - public final RowId getRowId(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type"); - } - - @Override - public final SQLXML getSQLXML(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type"); - } - - @Override - public final SQLXML getSQLXML(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type"); - } - - @Override - public final Blob getBlob(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type. Use getBytes() instead"); - } - - @Override - public final Blob getBlob(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type. Use getBytes() instead"); - } - - @Override - public final Clob getClob(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type. Use getString() instead"); - } - - @Override - public final Clob getClob(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type. Use getString() instead"); - } - - @Override - public final NClob getNClob(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type. Use getString() instead"); - } - - @Override - public final NClob getNClob(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type. Use getString() instead"); - } - - @Override - public final Array getArray(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type. Use getObject() instead"); - } - - @Override - public final Array getArray(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("Unsupported data type. Use getObject() instead"); - } - - @Override - public final URL getURL(int columnIndex) throws SQLException { - return getValue(columnIndex, URL.class); - } - - @Override - public final URL getURL(String columnLabel) throws SQLException { - return getValue(columnLabel, URL.class); - } - - @Override - public final Object getObject(int columnIndex) throws SQLException { - return getValue(columnIndex, Object.class); - } - - @Override - public final Object getObject(int columnIndex, Map> map) throws SQLException { - return getValue(columnIndex, Object.class); - } - - @Override - public final Object getObject(String columnLabel) throws SQLException { - return getValue(columnLabel, Object.class); - } - - @Override - public final Object getObject(String columnLabel, Map> map) throws SQLException { - return getValue(columnLabel, Object.class); - } - - // ------------------------------------------------------------------------- - // XXX: Setters and row update methods - // ------------------------------------------------------------------------- - - @Override - public final boolean rowUpdated() throws SQLException { - return false; - } - - @Override - public final boolean rowInserted() throws SQLException { - return false; - } - - @Override - public final boolean rowDeleted() throws SQLException { - return false; - } - - @Override - public final void updateNull(int columnIndex) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBoolean(int columnIndex, boolean x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateByte(int columnIndex, byte x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateShort(int columnIndex, short x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateInt(int columnIndex, int x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateLong(int columnIndex, long x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateFloat(int columnIndex, float x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateDouble(int columnIndex, double x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateString(int columnIndex, String x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBytes(int columnIndex, byte[] x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateDate(int columnIndex, Date x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateTime(int columnIndex, Time x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateObject(int columnIndex, Object x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateNull(String columnLabel) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBoolean(String columnLabel, boolean x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateByte(String columnLabel, byte x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateShort(String columnLabel, short x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateInt(String columnLabel, int x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateLong(String columnLabel, long x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateFloat(String columnLabel, float x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateDouble(String columnLabel, double x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateString(String columnLabel, String x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBytes(String columnLabel, byte[] x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateDate(String columnLabel, Date x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateTime(String columnLabel, Time x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateRef(int columnIndex, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateRef(String columnLabel, Ref x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateRowId(int columnIndex, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateRowId(String columnLabel, RowId x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBlob(int columnIndex, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateBlob(String columnLabel, Blob x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateClob(int columnIndex, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateClob(String columnLabel, Clob x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateArray(int columnIndex, Array x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateArray(String columnLabel, Array x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateNString(int columnIndex, String nString) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateNString(String columnLabel, String nString) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateNClob(int columnIndex, NClob nClob) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateNClob(String columnLabel, NClob nClob) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateClob(int columnIndex, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateClob(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateCharacterStream(int columnIndex, Reader x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateClob(int columnIndex, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateClob(String columnLabel, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateNClob(int columnIndex, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } - - @Override - public final void updateNClob(String columnLabel, Reader reader) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateObject(String columnLabel, Object x) throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void insertRow() throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void updateRow() throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void deleteRow() throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void refreshRow() throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void cancelRowUpdates() throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void moveToInsertRow() throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - @Override - public final void moveToCurrentRow() throws SQLException { - throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); - } - - private class MetaData implements ResultSetMetaData, Serializable { - - /** - * Generated UID - */ - private static final long serialVersionUID = -6859273409631070434L; - - @Override - public final T unwrap(Class iface) throws SQLException { - return null; - } - - @Override - public final boolean isWrapperFor(Class iface) throws SQLException { - return false; - } - - @Override - public final int getColumnCount() throws SQLException { - checkNotClosed(); - - return result.fieldsRow().size(); - } - - @Override - public final boolean isAutoIncrement(int column) throws SQLException { - checkNotClosed(); - - return false; - } - - @Override - public final boolean isCaseSensitive(int column) throws SQLException { - checkNotClosed(); - - return true; - } - - @Override - public final boolean isSearchable(int column) throws SQLException { - checkNotClosed(); - - return true; - } - - @Override - public final boolean isCurrency(int column) throws SQLException { - checkNotClosed(); - - return false; - } - - @Override - public final int isNullable(int column) throws SQLException { - checkNotClosed(); - - // TODO: Check generated JSR-303 or JPA annotations for nullability - return ResultSetMetaData.columnNullableUnknown; - } - - @Override - public final boolean isSigned(int column) throws SQLException { - checkNotClosed(); - - Field field = result.field(column - 1); - Class type = field.getType(); - - return Number.class.isAssignableFrom(type) && !UNumber.class.isAssignableFrom(type); - } - - @Override - public final int getColumnDisplaySize(int column) throws SQLException { - return 0; - } - - @Override - public final String getColumnLabel(int column) throws SQLException { - return getColumnName(column); - } - - @Override - public final String getColumnName(int column) throws SQLException { - checkNotClosed(); - - return result.field(column - 1).getName(); - } - - @Override - public final String getSchemaName(int column) throws SQLException { - checkNotClosed(); - - Field field = result.field(column - 1); - if (field instanceof TableField) { - Table table = ((TableField) field).getTable(); - - if (table != null) { - Schema schema = table.getSchema(); - - if (schema != null) { - Configuration configuration = ((AttachableInternal) result).getConfiguration(); - Schema mapped = null; - - if (configuration != null) { - mapped = Utils.getMappedSchema(configuration, schema); - } - - if (mapped != null) { - return mapped.getName(); - } - else { - return schema.getName(); - } - } - } - } - - // By default, no schema is available - return ""; - } - - @Override - public final int getPrecision(int column) throws SQLException { - checkNotClosed(); - - // TODO: Check generated JSR-303 or JPA annotations for precision - return 0; - } - - @Override - public final int getScale(int column) throws SQLException { - checkNotClosed(); - - // TODO: Check generated JSR-303 or JPA annotations for scale - return 0; - } - - @Override - public final String getTableName(int column) throws SQLException { - checkNotClosed(); - - Field field = result.field(column - 1); - if (field instanceof TableField) { - Table table = ((TableField) field).getTable(); - - if (table != null) { - return table.getName(); - } - } - - // By default, no table is available - return ""; - } - - @Override - public final String getCatalogName(int column) throws SQLException { - checkNotClosed(); - - // jOOQ doesn't support catalogs yet - return ""; - } - - @Override - public final int getColumnType(int column) throws SQLException { - checkNotClosed(); - - return result.field(column - 1).getDataType().getSQLType(); - } - - @Override - public final String getColumnTypeName(int column) throws SQLException { - checkNotClosed(); - - return result.field(column - 1).getDataType().getTypeName(); - } - - @Override - public final boolean isReadOnly(int column) throws SQLException { - checkNotClosed(); - - return true; - } - - @Override - public final boolean isWritable(int column) throws SQLException { - checkNotClosed(); - - return false; - } - - @Override - public final boolean isDefinitelyWritable(int column) throws SQLException { - checkNotClosed(); - - return false; - } - - @Override - public final String getColumnClassName(int column) throws SQLException { - checkNotClosed(); - - return result.field(column - 1).getType().getName(); - } - } - - // ------------------------------------------------------------------------- - // XXX: Object API - // ------------------------------------------------------------------------- - - @Override - public String toString() { - return result == null ? "null" : result.toString(); - } -} diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/MockConnection.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockConnection.java new file mode 100644 index 0000000000..9fde006fdf --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockConnection.java @@ -0,0 +1,406 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.tools.jdbc; + +import java.sql.Array; +import java.sql.Blob; +import java.sql.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.NClob; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLClientInfoException; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Savepoint; +import java.sql.Statement; +import java.sql.Struct; +import java.util.Map; +import java.util.Properties; + +/** + * A mock connection. + *

+ * Mock connections can be used to supply jOOQ with unit test data, avoiding the + * round-trip of using an actual in-memory test database, such as Derby, H2 or + * HSQLDB. A usage example: + *

+ *

+ * MockDataProvider provider = new MockDataProvider() {
+ *     public MockResult[] execute(MockExecuteContext context) throws SQLException {
+ *         Result<MyTableRecord> result = executor.newResult(MY_TABLE);
+ *         result.add(executor.newRecord(MY_TABLE));
+ *
+ *         return new MockResult[] {
+ *             new MockResult(1, result);
+ *         };
+ *     }
+ * };
+ * Connection connection = new MockConnection(provider);
+ * Executor create = new Executor(connection, dialect);
+ * assertEquals(1, create.selectOne().fetch().size());
+ * 

+ * While this MockConnection can be used independently of jOOQ, it + * has been optimised for usage with jOOQ. JDBC features that are not used by + * jOOQ (e.g. procedure bind value access by parameter name) are not supported + * in this mock framework + * + * @author Lukas Eder + */ +public class MockConnection extends JDBC41Connection implements Connection { + + private final MockDataProvider data; + private boolean isClosed; + + public MockConnection(MockDataProvider data) { + this.data = data; + } + + // ------------------------------------------------------------------------- + // XXX: Utilities + // ------------------------------------------------------------------------- + + private void checkNotClosed() throws SQLException { + if (isClosed) { + throw new SQLException("Connection is already closed"); + } + } + + // ------------------------------------------------------------------------- + // XXX: Creating statements + // ------------------------------------------------------------------------- + + @Override + public Statement createStatement() throws SQLException { + return createStatement(ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { + return createStatement(resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT); + } + + @Override + public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) + throws SQLException { + checkNotClosed(); + + MockStatement result = new MockStatement(this, data); + result.resultSetType = resultSetType; + result.resultSetConcurrency = resultSetConcurrency; + result.resultSetHoldability = resultSetHoldability; + return result; + } + + @Override + public PreparedStatement prepareStatement(String sql) throws SQLException { + return prepareStatement(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT); + } + + @Override + public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + checkNotClosed(); + + MockStatement result = new MockStatement(this, data, sql); + result.resultSetType = resultSetType; + result.resultSetConcurrency = resultSetConcurrency; + result.resultSetHoldability = resultSetHoldability; + return result; + } + + @Override + public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { + checkNotClosed(); + + MockStatement result = new MockStatement(this, data, sql); + result.autoGeneratedKeys = autoGeneratedKeys; + return result; + } + + @Override + public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { + checkNotClosed(); + + MockStatement result = new MockStatement(this, data, sql); + result.autoGeneratedKeys = Statement.RETURN_GENERATED_KEYS; + result.columnIndexes = columnIndexes; + return result; + } + + @Override + public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { + checkNotClosed(); + + MockStatement result = new MockStatement(this, data, sql); + result.autoGeneratedKeys = Statement.RETURN_GENERATED_KEYS; + result.columnNames = columnNames; + return result; + } + + @Override + public CallableStatement prepareCall(String sql) throws SQLException { + return prepareCall(sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY, ResultSet.CLOSE_CURSORS_AT_COMMIT); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { + return prepareCall(sql, resultSetType, resultSetConcurrency, ResultSet.CLOSE_CURSORS_AT_COMMIT); + } + + @Override + public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, + int resultSetHoldability) throws SQLException { + checkNotClosed(); + + MockStatement result = new MockStatement(this, data, sql); + result.resultSetType = resultSetType; + result.resultSetConcurrency = resultSetConcurrency; + result.resultSetHoldability = resultSetHoldability; + return result; + } + + // ------------------------------------------------------------------------- + // XXX: Ignored operations + // ------------------------------------------------------------------------- + + @Override + public void commit() throws SQLException { + checkNotClosed(); + } + + @Override + public void rollback() throws SQLException { + checkNotClosed(); + } + + @Override + public void rollback(Savepoint savepoint) throws SQLException { + checkNotClosed(); + } + + @Override + public void close() throws SQLException { + isClosed = true; + } + + @Override + public Savepoint setSavepoint() throws SQLException { + checkNotClosed(); + return null; + } + + @Override + public Savepoint setSavepoint(String name) throws SQLException { + checkNotClosed(); + return null; + } + + @Override + public void releaseSavepoint(Savepoint savepoint) throws SQLException { + checkNotClosed(); + } + + @Override + public boolean isClosed() throws SQLException { + return isClosed; + } + + @Override + public void setAutoCommit(boolean autoCommit) throws SQLException { + checkNotClosed(); + } + + @Override + public boolean getAutoCommit() throws SQLException { + checkNotClosed(); + return false; + } + + @Override + public void setReadOnly(boolean readOnly) throws SQLException { + checkNotClosed(); + } + + @Override + public boolean isReadOnly() throws SQLException { + checkNotClosed(); + return false; + } + + @Override + public void setCatalog(String catalog) throws SQLException { + checkNotClosed();} + + @Override + public String getCatalog() throws SQLException { + checkNotClosed(); + return null; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + checkNotClosed(); + return null; + } + + @Override + public void clearWarnings() throws SQLException { + checkNotClosed(); + } + + @Override + public void setTransactionIsolation(int level) throws SQLException { + checkNotClosed(); + } + + @Override + public int getTransactionIsolation() throws SQLException { + checkNotClosed(); + return 0; + } + + @Override + public void setTypeMap(Map> map) throws SQLException { + checkNotClosed(); + } + + @Override + public Map> getTypeMap() throws SQLException { + checkNotClosed(); + return null; + } + + @Override + public void setHoldability(int holdability) throws SQLException { + checkNotClosed(); + } + + @Override + public int getHoldability() throws SQLException { + checkNotClosed(); + return 0; + } + + @Override + public boolean isValid(int timeout) throws SQLException { + checkNotClosed(); + return false; + } + + @Override + public void setClientInfo(String name, String value) throws SQLClientInfoException { + } + + @Override + public void setClientInfo(Properties properties) throws SQLClientInfoException { + } + + @Override + public String getClientInfo(String name) throws SQLException { + checkNotClosed(); + return null; + } + + @Override + public Properties getClientInfo() throws SQLException { + checkNotClosed(); + return null; + } + + // ------------------------------------------------------------------------- + // XXX: Unsupported operations + // ------------------------------------------------------------------------- + + @Override + public DatabaseMetaData getMetaData() throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public T unwrap(Class iface) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public String nativeSQL(String sql) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Clob createClob() throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Blob createBlob() throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public NClob createNClob() throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public SQLXML createSQLXML() throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Array createArrayOf(String typeName, Object[] elements) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Struct createStruct(String typeName, Object[] attributes) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } +} diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/MockDataProvider.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockDataProvider.java new file mode 100644 index 0000000000..156c438f37 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockDataProvider.java @@ -0,0 +1,140 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.tools.jdbc; + +import java.sql.PreparedStatement; +import java.sql.SQLException; +import java.sql.Statement; + +import org.jooq.Query; +import org.jooq.ResultQuery; +import org.jooq.impl.Executor; + +/** + * A data provider for mock query executions. + *

+ * Supply this data provider to your {@link MockConnection} in order to globally + * provide data for SQL statements. + *

+ * See {@link #execute(MockExecuteContext)} for details. + * + * @author Lukas Eder + * @see MockConnection + */ +public interface MockDataProvider { + + /** + * Execution callback for a JDBC query execution. + *

+ * This callback will be called by {@link MockStatement} upon the various + * statement execution methods. These include: + *

+ *

    + *
  • {@link Statement#execute(String)}
  • + *
  • {@link Statement#execute(String, int)}
  • + *
  • {@link Statement#execute(String, int[])}
  • + *
  • {@link Statement#execute(String, String[])}
  • + *
  • {@link Statement#executeBatch()}
  • + *
  • {@link Statement#executeQuery(String)}
  • + *
  • {@link Statement#executeUpdate(String)}
  • + *
  • {@link Statement#executeUpdate(String, int)}
  • + *
  • {@link Statement#executeUpdate(String, int[])}
  • + *
  • {@link Statement#executeUpdate(String, String[])}
  • + *
  • {@link PreparedStatement#execute()}
  • + *
  • {@link PreparedStatement#executeQuery()}
  • + *
  • {@link PreparedStatement#executeUpdate()}
  • + *
+ *

+ * The various execution modes are unified into this simple method. + * Implementations should adhere to this contract: + *

+ *

    + *
  • MockStatement does not distinguish between "static" and + * "prepared" statements. However, a non-empty + * {@link MockExecuteContext#getBindings()} is a strong indicator for a + * {@link PreparedStatement}.
  • + *
  • MockStatement does not distinguish between "batch" and + * "single" statements. However... + *
      + *
    • A {@link MockExecuteContext#getBatchSQL()} with more than one SQL + * string is a strong indicator for a "multi-batch statement", as understood + * by jOOQ's {@link Executor#batch(Query...)}.
    • + *
    • A {@link MockExecuteContext#getBatchBindings()} with more than one + * bind variable array is a strong indicator for a "single-batch statement", + * as understood by jOOQ's {@link Executor#batch(Query)}.
    • + *
    + *
  • + *
  • It is recommended to return as many MockResult objects + * as batch executions. In other words, you should guarantee that: + *

    + *

    +     * int multiSize = context.getBatchSQL().length;
    +     * int singleSize = context.getBatchBindings().length;
    +     * assertEquals(result.length, Math.max(multiSize, singleSize))
    +     * 
    + *

    + * This holds true also for non-batch executions (where both sizes are equal + * to 1)

  • + *
  • You may also return more than one result for non-batch executions. + * This is useful for procedure calls with several result sets. + *
      + *
    • In JDBC, such additional result sets can be obtained with + * {@link Statement#getMoreResults()}.
    • + *
    • In jOOQ, such additional result sets can be obtained with + * {@link ResultQuery#fetchMany()}
    • + *
    + *
  • + *
  • If generated keys ({@link Statement#RETURN_GENERATED_KEYS}) are + * requested from this execution, you can also add {@link MockResult#data} + * to your result, in addition to the affected {@link MockResult#rows}. The + * relevant flag is passed from MockStatement to any of these + * properties: + *
      + *
    • {@link MockExecuteContext#getAutoGeneratedKeys()}
    • + *
    • {@link MockExecuteContext#getColumnIndexes()}
    • + *
    • {@link MockExecuteContext#getColumnNames()}
    • + *
    + *
  • + *
+ * + * @param context The execution context. + * @return The execution results. This should be non-null and non-empty, as + * every execution is expected to return at least one result. + * @throws SQLException A SQLException that is passed through + * to jOOQ. + */ + MockResult[] execute(MockExecuteContext context) throws SQLException; +} diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/MockExecuteContext.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockExecuteContext.java new file mode 100644 index 0000000000..942e8febf9 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockExecuteContext.java @@ -0,0 +1,214 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.tools.jdbc; + +import java.sql.Statement; + +import org.jooq.Query; +import org.jooq.impl.Executor; + +/** + * A mock execution context. + *

+ * This context is passed to + * {@link MockDataProvider#execute(MockExecuteContext)}, as a context object + * containing all relevant information about a given query execution. + * + * @author Lukas Eder + * @see MockDataProvider + */ +public class MockExecuteContext { + + private final String[] sql; + private final Object[][] bindings; + + private final int autoGeneratedKeys; + private final int[] columnIndexes; + private final String[] columnNames; + + /** + * Create a new mock execution context. + * + * @param sql The SQL statement(s) + * @param bindings The bind variable(s) + */ + public MockExecuteContext(String[] sql, Object[][] bindings) { + this(sql, bindings, Statement.NO_GENERATED_KEYS, null, null); + } + + /** + * Create a new mock execution context. + * + * @param sql The SQL statement(s) + * @param bindings The bind variable(s) + * @param autoGeneratedKeys The corresponding value from + * MockStatement + */ + public MockExecuteContext(String[] sql, Object[][] bindings, int autoGeneratedKeys) { + this(sql, bindings, autoGeneratedKeys, null, null); + } + + /** + * Create a new mock execution context. + *

+ * + * @param sql The SQL statement(s) + * @param bindings The bind variable(s) + * @param columnIndexes The corresponding value from + * MockStatement + */ + public MockExecuteContext(String[] sql, Object[][] bindings, int[] columnIndexes) { + this(sql, bindings, Statement.RETURN_GENERATED_KEYS, columnIndexes, null); + } + + /** + * Create a new mock execution context. + *

+ * + * @param sql The SQL statement(s) + * @param bindings The bind variable(s) + * @param columnNames The corresponding value from + * MockStatement + */ + public MockExecuteContext(String[] sql, Object[][] bindings, String[] columnNames) { + this(sql, bindings, Statement.RETURN_GENERATED_KEYS, null, columnNames); + } + + MockExecuteContext(String[] sql, Object[][] bindings, int autoGeneratedKeys, int[] columnIndexes, + String[] columnNames) { + this.sql = sql; + this.bindings = bindings; + this.autoGeneratedKeys = autoGeneratedKeys; + this.columnIndexes = columnIndexes; + this.columnNames = columnNames; + } + + /** + * Whether this execution context is a from a batch statement. + * + * @return Whether this execution context is a from a batch statement. + */ + public boolean isBatch() { + return isSingleBatch() || isMultiBatch(); + } + + /** + * Whether this execution context is from a "single batch" statement. + * + * @return Whether this execution context is from a "single batch" + * statement. + * @see Executor#batch(Query) + */ + public boolean isSingleBatch() { + return bindings.length > 1; + } + + /** + * Whether this execution context is from a "multi batch" statement. + * + * @return Whether this execution context is from a "multi batch" statement. + * @see Executor#batch(Query...) + */ + public boolean isMultiBatch() { + return sql.length > 1; + } + + /** + * Get all batch SQL statements of a "multi batch" statement. + * + * @return All batch SQL statements of a "multi batch" statement, or an + * array of length 1 with the single statement. + */ + public String[] getBatchSQL() { + return sql; + } + + /** + * Get all bind variables of a "single batch" statement. + * + * @return All bind variables of a "single batch" statment, or an array of + * length 1 with the bind variables of a single + * statement. + */ + public Object[][] getBatchBindings() { + return bindings; + } + + /** + * Get the single (or first "multi batch") SQL statement. + * + * @return The single (or first "multi batch") SQL statement. + */ + public String getSQL() { + return sql[0]; + } + + /** + * Get the single (or first "single batch") set of bind variables. + * + * @return The single (or first "single batch") set of bind variables. + */ + public Object[] getBindings() { + return bindings[0]; + } + + /** + * The corresponding value from MockStatement. + * + * @return The corresponding value from MockStatement. + */ + public int getAutoGeneratedKeys() { + return autoGeneratedKeys; + } + + /** + * The corresponding value from MockStatement. + * + * @return The corresponding value from MockStatement. + */ + public int[] getColumnIndexes() { + return columnIndexes; + } + + /** + * The corresponding value from MockStatement. + * + * @return The corresponding value from MockStatement. + */ + public String[] getColumnNames() { + return columnNames; + } +} diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResult.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResult.java new file mode 100644 index 0000000000..ccefd68b28 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResult.java @@ -0,0 +1,93 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.tools.jdbc; + +import java.sql.Statement; + +import org.jooq.Result; + +/** + * A mock result. + *

+ * This type is used to wrap unified results of DDL and DML query executions. + * JDBC execution results can be summarised to two properties: + *

    + *
  • {@link Statement#getUpdateCount()}: The number of affected rows
  • + *
  • {@link Statement#getResultSet()}: The result set
  • + *
+ *

+ * See {@link MockDataProvider#execute(MockExecuteContext)} for more details + * + * @author Lukas Eder + * @see MockDataProvider + */ +public class MockResult { + + /** + * The number of affected rows for this execution result. + *

+ * This number corresponds to the value of + * {@link Statement#getUpdateCount()}. The following values are possible: + *

    + *
  • Positive numbers: the number of affected rows by a given query + * execution
  • + *
  • 0: no rows were affected by a given query execution
  • + *
  • -1: the row count is not applicable
  • + *
+ */ + public final int rows; + + /** + * The result data associated with this execution result. + *

+ * This object describes the result data (including meta data). If the given + * query execution did not provide any results, this may be + * null. Note, that this can also be used to provide a result + * for {@link Statement#getGeneratedKeys()} + */ + public final Result data; + + /** + * Create a new MockResult. + * + * @param rows The number of affected rows + * @param data The result data + */ + public MockResult(int rows, Result data) { + this.rows = rows; + this.data = data; + } +} diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResultSet.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResultSet.java new file mode 100644 index 0000000000..9b5abfeff6 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResultSet.java @@ -0,0 +1,1157 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.tools.jdbc; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.io.Reader; +import java.io.Serializable; +import java.io.StringReader; +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.NClob; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.Calendar; +import java.util.Map; + +import org.jooq.Field; +import org.jooq.Result; + +/** + * A mock result set. + * + * @author Lukas Eder + * @see MockConnection + */ +public class MockResultSet extends JDBC41ResultSet implements ResultSet, Serializable { + + /** + * Generated UID + */ + private static final long serialVersionUID = -2292216936424437750L; + + private final int maxRows; + Result result; + private transient int index; + private transient boolean wasNull; + + public MockResultSet(Result result) { + this(result, 0); + } + + public MockResultSet(Result result, int maxRows) { + this.result = result; + this.maxRows = maxRows; + } + + // ------------------------------------------------------------------------- + // XXX: Unsupported implementations + // ------------------------------------------------------------------------- + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } + + // ------------------------------------------------------------------------- + // XXX: ResultSet operations + // ------------------------------------------------------------------------- + + private int size() { + if (maxRows == 0) { + return result.size(); + } + else { + return Math.min(maxRows, result.size()); + } + } + + void checkNotClosed() throws SQLException { + if (result == null) { + throw new SQLException("ResultSet is already closed"); + } + } + + private void checkInRange() throws SQLException { + checkNotClosed(); + + if (index <= 0 || index > result.size()) { + throw new SQLException("ResultSet index is at an illegal position : " + index); + } + } + + private void checkField(String columnLabel) throws SQLException { + if (result.field(columnLabel) == null) { + throw new SQLException("Unknown column label : " + columnLabel); + } + } + + private void checkField(int columnIndex) throws SQLException { + if (result.field(columnIndex - 1) == null) { + throw new SQLException("Unknown column index : " + columnIndex); + } + } + + @Override + public boolean next() throws SQLException { + return relative(1); + } + + @Override + public boolean previous() throws SQLException { + return relative(-1); + } + + @Override + public boolean absolute(int row) throws SQLException { + if (size() > 0) { + if (row > 0) { + if (row <= size()) { + index = row; + return true; + } + else { + afterLast(); + return false; + } + } + else if (row == 0) { + beforeFirst(); + return false; + } + else { + if (-row <= size()) { + index = size() + 1 + row; + return true; + } + else { + beforeFirst(); + return false; + } + } + } + else { + return false; + } + } + + @Override + public boolean relative(int rows) throws SQLException { + checkNotClosed(); + + index += rows; + try { + return (index > 0 && index <= size()); + } + + // Be sure we don't go out of bounds + finally { + index = Math.max(index, 0); + index = Math.min(index, size() + 1); + } + } + + @Override + public int getRow() throws SQLException { + return (index > size()) ? 0 : index; + } + + @Override + public void beforeFirst() throws SQLException { + checkNotClosed(); + index = 0; + } + + @Override + public void afterLast() throws SQLException { + checkNotClosed(); + index = size() + 1; + } + + @Override + public boolean first() throws SQLException { + return absolute(1); + } + + @Override + public boolean last() throws SQLException { + checkNotClosed(); + return absolute(size()); + } + + @Override + public boolean isFirst() throws SQLException { + checkNotClosed(); + + return (size() > 0 && index == 1); + } + + @Override + public boolean isBeforeFirst() throws SQLException { + checkNotClosed(); + + return (size() > 0 && index == 0); + } + + @Override + public boolean isLast() throws SQLException { + checkNotClosed(); + + return (size() > 0 && index == size()); + } + + @Override + public boolean isAfterLast() throws SQLException { + checkNotClosed(); + + return (size() > 0 && index > size()); + } + + @Override + public void close() throws SQLException { + checkNotClosed(); + + result = null; + index = 0; + } + + @Override + public boolean isClosed() throws SQLException { + return result == null; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + // Warnings are not supported + return null; + } + + @Override + public void clearWarnings() throws SQLException { + // Warnings are not supported + } + + @Override + public String getCursorName() throws SQLException { + throw new SQLFeatureNotSupportedException("jOOQ ResultSets don't have a cursor name"); + } + + @Override + public int findColumn(String columnLabel) throws SQLException { + checkNotClosed(); + + Field field = result.field(columnLabel); + if (field == null) { + throw new SQLException("No such column : " + columnLabel); + } + + return result.fieldsRow().indexOf(field) + 1; + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + + // Fetch direction is not supported + if (direction != ResultSet.FETCH_FORWARD) { + throw new SQLException("Fetch direction can only be FETCH_FORWARD"); + } + } + + @Override + public int getFetchDirection() throws SQLException { + + // Fetch direction is not supported + return ResultSet.FETCH_FORWARD; + } + + @Override + public void setFetchSize(int rows) throws SQLException { + // Fetch size is not supported + } + + @Override + public int getFetchSize() throws SQLException { + return 0; + } + + @Override + public int getType() throws SQLException { + return ResultSet.TYPE_SCROLL_INSENSITIVE; + } + + @Override + public int getConcurrency() throws SQLException { + return ResultSet.CONCUR_READ_ONLY; + } + + @Override + public int getHoldability() throws SQLException { + return ResultSet.CLOSE_CURSORS_AT_COMMIT; + } + + // ------------------------------------------------------------------------- + // XXX: Getters + // ------------------------------------------------------------------------- + + @Override + public boolean wasNull() throws SQLException { + checkNotClosed(); + + return wasNull; + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return new MockResultSetMetaData(this); + } + + @Override + public Statement getStatement() throws SQLException { + return null; + } + + private T getValue(String columnLabel, Class type) throws SQLException { + checkInRange(); + checkField(columnLabel); + + T value = result.get(index - 1).getValue(columnLabel, type); + wasNull = (value == null); + return value; + } + + private T getValue(int columnIndex, Class type) throws SQLException { + checkInRange(); + checkField(columnIndex); + + T value = result.get(index - 1).getValue(columnIndex - 1, type); + wasNull = (value == null); + return value; + } + + @Override + public String getString(int columnIndex) throws SQLException { + return getValue(columnIndex, String.class); + } + + @Override + public String getString(String columnLabel) throws SQLException { + return getValue(columnLabel, String.class); + } + + @Override + public String getNString(int columnIndex) throws SQLException { + return getString(columnIndex); + } + + @Override + public String getNString(String columnLabel) throws SQLException { + return getString(columnLabel); + } + + @Override + public boolean getBoolean(int columnIndex) throws SQLException { + Boolean value = getValue(columnIndex, Boolean.class); + return wasNull ? false : value; + } + + @Override + public boolean getBoolean(String columnLabel) throws SQLException { + Boolean value = getValue(columnLabel, Boolean.class); + return wasNull ? false : value; + } + + @Override + public byte getByte(int columnIndex) throws SQLException { + Byte value = getValue(columnIndex, Byte.class); + return wasNull ? (byte) 0 : value; + } + + @Override + public byte getByte(String columnLabel) throws SQLException { + Byte value = getValue(columnLabel, Byte.class); + return wasNull ? (byte) 0 : value; + } + + @Override + public short getShort(int columnIndex) throws SQLException { + Short value = getValue(columnIndex, Short.class); + return wasNull ? (short) 0 : value; + } + + @Override + public short getShort(String columnLabel) throws SQLException { + Short value = getValue(columnLabel, Short.class); + return wasNull ? (short) 0 : value; + } + + @Override + public int getInt(int columnIndex) throws SQLException { + Integer value = getValue(columnIndex, Integer.class); + return wasNull ? 0 : value; + } + + @Override + public int getInt(String columnLabel) throws SQLException { + Integer value = getValue(columnLabel, Integer.class); + return wasNull ? 0 : value; + } + + @Override + public long getLong(int columnIndex) throws SQLException { + Long value = getValue(columnIndex, Long.class); + return wasNull ? 0L : value; + } + + @Override + public long getLong(String columnLabel) throws SQLException { + Long value = getValue(columnLabel, Long.class); + return wasNull ? 0L : value; + } + + @Override + public float getFloat(int columnIndex) throws SQLException { + Float value = getValue(columnIndex, Float.class); + return wasNull ? 0.0f : value; + } + + @Override + public float getFloat(String columnLabel) throws SQLException { + Float value = getValue(columnLabel, Float.class); + return wasNull ? 0.0f : value; + } + + @Override + public double getDouble(int columnIndex) throws SQLException { + Double value = getValue(columnIndex, Double.class); + return wasNull ? 0.0 : value; + } + + @Override + public double getDouble(String columnLabel) throws SQLException { + Double value = getValue(columnLabel, Double.class); + return wasNull ? 0.0 : value; + } + + @Override + public BigDecimal getBigDecimal(int columnIndex) throws SQLException { + return getValue(columnIndex, BigDecimal.class); + } + + @Override + @Deprecated + public BigDecimal getBigDecimal(int columnIndex, int scale) throws SQLException { + return getValue(columnIndex, BigDecimal.class); + } + + @Override + public BigDecimal getBigDecimal(String columnLabel) throws SQLException { + return getValue(columnLabel, BigDecimal.class); + } + + @Override + @Deprecated + public BigDecimal getBigDecimal(String columnLabel, int scale) throws SQLException { + return getValue(columnLabel, BigDecimal.class); + } + + @Override + public byte[] getBytes(int columnIndex) throws SQLException { + return getValue(columnIndex, byte[].class); + } + + @Override + public byte[] getBytes(String columnLabel) throws SQLException { + return getValue(columnLabel, byte[].class); + } + + @Override + public Date getDate(int columnIndex) throws SQLException { + return getValue(columnIndex, Date.class); + } + + @Override + public Date getDate(int columnIndex, Calendar cal) throws SQLException { + return getValue(columnIndex, Date.class); + } + + @Override + public Date getDate(String columnLabel) throws SQLException { + return getValue(columnLabel, Date.class); + } + + @Override + public Date getDate(String columnLabel, Calendar cal) throws SQLException { + return getValue(columnLabel, Date.class); + } + + @Override + public Time getTime(int columnIndex) throws SQLException { + return getValue(columnIndex, Time.class); + } + + @Override + public Time getTime(int columnIndex, Calendar cal) throws SQLException { + return getValue(columnIndex, Time.class); + } + + @Override + public Time getTime(String columnLabel) throws SQLException { + return getValue(columnLabel, Time.class); + } + + @Override + public Time getTime(String columnLabel, Calendar cal) throws SQLException { + return getValue(columnLabel, Time.class); + } + + @Override + public Timestamp getTimestamp(int columnIndex) throws SQLException { + return getValue(columnIndex, Timestamp.class); + } + + @Override + public Timestamp getTimestamp(int columnIndex, Calendar cal) throws SQLException { + return getValue(columnIndex, Timestamp.class); + } + + @Override + public Timestamp getTimestamp(String columnLabel) throws SQLException { + return getValue(columnLabel, Timestamp.class); + } + + @Override + public Timestamp getTimestamp(String columnLabel, Calendar cal) throws SQLException { + return getValue(columnLabel, Timestamp.class); + } + + @Override + public InputStream getAsciiStream(int columnIndex) throws SQLException { + byte[] bytes = getBytes(columnIndex); + return wasNull ? null : new ByteArrayInputStream(bytes); + } + + @Override + public InputStream getAsciiStream(String columnLabel) throws SQLException { + byte[] bytes = getBytes(columnLabel); + return wasNull ? null : new ByteArrayInputStream(bytes); + } + + @Override + @Deprecated + public InputStream getUnicodeStream(int columnIndex) throws SQLException { + String string = getString(columnIndex); + return wasNull ? null : new ByteArrayInputStream(string.getBytes()); + } + + @Override + @Deprecated + public InputStream getUnicodeStream(String columnLabel) throws SQLException { + String string = getString(columnLabel); + return wasNull ? null : new ByteArrayInputStream(string.getBytes()); + } + + @Override + public Reader getCharacterStream(int columnIndex) throws SQLException { + String string = getString(columnIndex); + return wasNull ? null : new StringReader(string); + } + + @Override + public Reader getCharacterStream(String columnLabel) throws SQLException { + String string = getString(columnLabel); + return wasNull ? null : new StringReader(string); + } + + @Override + public Reader getNCharacterStream(int columnIndex) throws SQLException { + return getCharacterStream(columnIndex); + } + + @Override + public Reader getNCharacterStream(String columnLabel) throws SQLException { + return getCharacterStream(columnLabel); + } + + @Override + public InputStream getBinaryStream(int columnIndex) throws SQLException { + byte[] bytes = getBytes(columnIndex); + return wasNull ? null : new ByteArrayInputStream(bytes); + } + + @Override + public InputStream getBinaryStream(String columnLabel) throws SQLException { + byte[] bytes = getBytes(columnLabel); + return wasNull ? null : new ByteArrayInputStream(bytes); + } + + @Override + public Ref getRef(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type"); + } + + @Override + public Ref getRef(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type"); + } + + @Override + public RowId getRowId(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type"); + } + + @Override + public RowId getRowId(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type"); + } + + @Override + public SQLXML getSQLXML(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type"); + } + + @Override + public SQLXML getSQLXML(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type"); + } + + @Override + public Blob getBlob(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type. Use getBytes() instead"); + } + + @Override + public Blob getBlob(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type. Use getBytes() instead"); + } + + @Override + public Clob getClob(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type. Use getString() instead"); + } + + @Override + public Clob getClob(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type. Use getString() instead"); + } + + @Override + public NClob getNClob(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type. Use getString() instead"); + } + + @Override + public NClob getNClob(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type. Use getString() instead"); + } + + @Override + public Array getArray(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type. Use getObject() instead"); + } + + @Override + public Array getArray(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported data type. Use getObject() instead"); + } + + @Override + public URL getURL(int columnIndex) throws SQLException { + return getValue(columnIndex, URL.class); + } + + @Override + public URL getURL(String columnLabel) throws SQLException { + return getValue(columnLabel, URL.class); + } + + @Override + public Object getObject(int columnIndex) throws SQLException { + return getValue(columnIndex, Object.class); + } + + @Override + public Object getObject(int columnIndex, Map> map) throws SQLException { + return getValue(columnIndex, Object.class); + } + + @Override + public Object getObject(String columnLabel) throws SQLException { + return getValue(columnLabel, Object.class); + } + + @Override + public Object getObject(String columnLabel, Map> map) throws SQLException { + return getValue(columnLabel, Object.class); + } + + // ------------------------------------------------------------------------- + // XXX: Setters and row update methods + // ------------------------------------------------------------------------- + + @Override + public boolean rowUpdated() throws SQLException { + return false; + } + + @Override + public boolean rowInserted() throws SQLException { + return false; + } + + @Override + public boolean rowDeleted() throws SQLException { + return false; + } + + @Override + public void updateNull(int columnIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBoolean(int columnIndex, boolean x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateByte(int columnIndex, byte x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateShort(int columnIndex, short x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateInt(int columnIndex, int x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateLong(int columnIndex, long x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateFloat(int columnIndex, float x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateDouble(int columnIndex, double x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBigDecimal(int columnIndex, BigDecimal x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateString(int columnIndex, String x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBytes(int columnIndex, byte[] x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateDate(int columnIndex, Date x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateTime(int columnIndex, Time x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateTimestamp(int columnIndex, Timestamp x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateObject(int columnIndex, Object x, int scaleOrLength) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateObject(int columnIndex, Object x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateNull(String columnLabel) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBoolean(String columnLabel, boolean x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateByte(String columnLabel, byte x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateShort(String columnLabel, short x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateInt(String columnLabel, int x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateLong(String columnLabel, long x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateFloat(String columnLabel, float x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateDouble(String columnLabel, double x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBigDecimal(String columnLabel, BigDecimal x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateString(String columnLabel, String x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBytes(String columnLabel, byte[] x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateDate(String columnLabel, Date x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateTime(String columnLabel, Time x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateTimestamp(String columnLabel, Timestamp x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateRef(int columnIndex, Ref x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateRef(String columnLabel, Ref x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateRowId(int columnIndex, RowId x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateRowId(String columnLabel, RowId x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBlob(int columnIndex, Blob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateBlob(String columnLabel, Blob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateClob(int columnIndex, Clob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateClob(String columnLabel, Clob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateArray(int columnIndex, Array x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateArray(String columnLabel, Array x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateNString(int columnIndex, String nString) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateNString(String columnLabel, String nString) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateNClob(int columnIndex, NClob nClob) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateNClob(String columnLabel, NClob nClob) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateSQLXML(int columnIndex, SQLXML xmlObject) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateSQLXML(String columnLabel, SQLXML xmlObject) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateCharacterStream(int columnIndex, Reader x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateClob(int columnIndex, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateClob(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateNClob(int columnIndex, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateNClob(String columnLabel, Reader reader, long length) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateNCharacterStream(int columnIndex, Reader x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateNCharacterStream(String columnLabel, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateAsciiStream(int columnIndex, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateBinaryStream(int columnIndex, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateCharacterStream(int columnIndex, Reader x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateAsciiStream(String columnLabel, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateBinaryStream(String columnLabel, InputStream x) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateCharacterStream(String columnLabel, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateBlob(int columnIndex, InputStream inputStream) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateBlob(String columnLabel, InputStream inputStream) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateClob(int columnIndex, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateClob(String columnLabel, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateNClob(int columnIndex, Reader reader) throws SQLException { throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); } + + @Override + public void updateNClob(String columnLabel, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateObject(String columnLabel, Object x, int scaleOrLength) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateObject(String columnLabel, Object x) throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void insertRow() throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void updateRow() throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void deleteRow() throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void refreshRow() throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void cancelRowUpdates() throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void moveToInsertRow() throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + @Override + public void moveToCurrentRow() throws SQLException { + throw new SQLFeatureNotSupportedException("Cannot update ResultSet"); + } + + // ------------------------------------------------------------------------- + // XXX: Object API + // ------------------------------------------------------------------------- + + @Override + public String toString() { + return result == null ? "null" : result.toString(); + } +} diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResultSetMetaData.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResultSetMetaData.java new file mode 100644 index 0000000000..a72706a094 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockResultSetMetaData.java @@ -0,0 +1,271 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.tools.jdbc; + +import java.io.Serializable; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; + +import org.jooq.AttachableInternal; +import org.jooq.Configuration; +import org.jooq.Field; +import org.jooq.Schema; +import org.jooq.Table; +import org.jooq.TableField; +import org.jooq.impl.Executor; +import org.jooq.types.UNumber; + +/** + * A mock result set meta data object. + * + * @author Lukas Eder + * @see MockConnection + */ +public class MockResultSetMetaData implements ResultSetMetaData, Serializable { + + /** + * Generated UID + */ + private static final long serialVersionUID = -6859273409631070434L; + + /** + * The result set reference. + */ + private final MockResultSet rs; + + /** + * Create a new mock result set meta data object + */ + public MockResultSetMetaData(MockResultSet rs) { + this.rs = rs; + } + + @Override + public T unwrap(Class iface) throws SQLException { + return null; + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return false; + } + + @Override + public int getColumnCount() throws SQLException { + rs.checkNotClosed(); + + return rs.result.fieldsRow().size(); + } + + @Override + public boolean isAutoIncrement(int column) throws SQLException { + rs.checkNotClosed(); + + return false; + } + + @Override + public boolean isCaseSensitive(int column) throws SQLException { + rs.checkNotClosed(); + + return true; + } + + @Override + public boolean isSearchable(int column) throws SQLException { + rs.checkNotClosed(); + + return true; + } + + @Override + public boolean isCurrency(int column) throws SQLException { + rs.checkNotClosed(); + + return false; + } + + @Override + public int isNullable(int column) throws SQLException { + rs.checkNotClosed(); + + // TODO: Check generated JSR-303 or JPA annotations for nullability + return ResultSetMetaData.columnNullableUnknown; + } + + @Override + public boolean isSigned(int column) throws SQLException { + rs.checkNotClosed(); + + Field field = rs.result.field(column - 1); + Class type = field.getType(); + + return Number.class.isAssignableFrom(type) && !UNumber.class.isAssignableFrom(type); + } + + @Override + public int getColumnDisplaySize(int column) throws SQLException { + return 0; + } + + @Override + public String getColumnLabel(int column) throws SQLException { + return getColumnName(column); + } + + @Override + public String getColumnName(int column) throws SQLException { + rs.checkNotClosed(); + + return rs.result.field(column - 1).getName(); + } + + @Override + public String getSchemaName(int column) throws SQLException { + rs.checkNotClosed(); + + Field field = rs.result.field(column - 1); + if (field instanceof TableField) { + Table table = ((TableField) field).getTable(); + + if (table != null) { + Schema schema = table.getSchema(); + + if (schema != null) { + Configuration configuration = ((AttachableInternal) rs.result).getConfiguration(); + Schema mapped = null; + + if (configuration != null) { + mapped = new Executor(configuration).map(schema); + } + + if (mapped != null) { + return mapped.getName(); + } + else { + return schema.getName(); + } + } + } + } + + // By default, no schema is available + return ""; + } + + @Override + public int getPrecision(int column) throws SQLException { + rs.checkNotClosed(); + + // TODO: Check generated JSR-303 or JPA annotations for precision + return 0; + } + + @Override + public int getScale(int column) throws SQLException { + rs.checkNotClosed(); + + // TODO: Check generated JSR-303 or JPA annotations for scale + return 0; + } + + @Override + public String getTableName(int column) throws SQLException { + rs.checkNotClosed(); + + Field field = rs.result.field(column - 1); + if (field instanceof TableField) { + Table table = ((TableField) field).getTable(); + + if (table != null) { + return table.getName(); + } + } + + // By default, no table is available + return ""; + } + + @Override + public String getCatalogName(int column) throws SQLException { + rs.checkNotClosed(); + + // jOOQ doesn't support catalogs yet + return ""; + } + + @Override + public int getColumnType(int column) throws SQLException { + rs.checkNotClosed(); + + return rs.result.field(column - 1).getDataType().getSQLType(); + } + + @Override + public String getColumnTypeName(int column) throws SQLException { + rs.checkNotClosed(); + + return rs.result.field(column - 1).getDataType().getTypeName(); + } + + @Override + public boolean isReadOnly(int column) throws SQLException { + rs.checkNotClosed(); + + return true; + } + + @Override + public boolean isWritable(int column) throws SQLException { + rs.checkNotClosed(); + + return false; + } + + @Override + public boolean isDefinitelyWritable(int column) throws SQLException { + rs.checkNotClosed(); + + return false; + } + + @Override + public String getColumnClassName(int column) throws SQLException { + rs.checkNotClosed(); + + return rs.result.field(column - 1).getType().getName(); + } +} \ No newline at end of file diff --git a/jOOQ/src/main/java/org/jooq/tools/jdbc/MockStatement.java b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockStatement.java new file mode 100644 index 0000000000..6c14cc29f6 --- /dev/null +++ b/jOOQ/src/main/java/org/jooq/tools/jdbc/MockStatement.java @@ -0,0 +1,1322 @@ +/** + * Copyright (c) 2009-2013, Lukas Eder, lukas.eder@gmail.com + * All rights reserved. + * + * This software is licensed to you under the Apache License, Version 2.0 + * (the "License"); You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * . Redistributions of source code must retain the above copyright notice, this + * list of conditions and the following disclaimer. + * + * . Redistributions in binary form must reproduce the above copyright notice, + * this list of conditions and the following disclaimer in the documentation + * and/or other materials provided with the distribution. + * + * . Neither the name "jOOQ" nor the names of its contributors may be + * used to endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE + * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ +package org.jooq.tools.jdbc; + +import static java.util.Collections.nCopies; + +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.CallableStatement; +import java.sql.Clob; +import java.sql.Connection; +import java.sql.Date; +import java.sql.NClob; +import java.sql.ParameterMetaData; +import java.sql.PreparedStatement; +import java.sql.Ref; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.RowId; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; +import java.sql.SQLXML; +import java.sql.Statement; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Calendar; +import java.util.List; +import java.util.Map; + +/** + * A mock statement. + *

+ * This statement can be used to mock any of these: + *

    + *
  • {@link Statement}
  • + *
  • {@link PreparedStatement}
  • + *
  • {@link CallableStatement}
  • + *
+ * + * @author Lukas Eder + * @see MockConnection + */ +public class MockStatement extends JDBC41Statement implements CallableStatement { + + private final MockConnection connection; + + private final MockDataProvider data; + private final List sql; + private final List> bindings; + private MockResult[] result; + private int resultIndex; + private boolean isClosed; + + // Execution parameters + int resultSetType = ResultSet.TYPE_FORWARD_ONLY; + int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY; + int resultSetHoldability = ResultSet.CLOSE_CURSORS_AT_COMMIT; + int autoGeneratedKeys = Statement.NO_GENERATED_KEYS; + int[] columnIndexes; + String[] columnNames; + + // Statement properties + private int queryTimeout; + private int maxRows; + + public MockStatement(MockConnection connection, MockDataProvider data) { + this(connection, data, null); + } + + public MockStatement(MockConnection connection, MockDataProvider data, String sql) { + this.connection = connection; + this.data = data; + this.sql = new ArrayList(); + this.bindings = new ArrayList>(); + + if (sql != null) { + this.sql.add(sql); + } + + this.bindings.add(new ArrayList()); + } + + // ------------------------------------------------------------------------- + // XXX: Utilities + // ------------------------------------------------------------------------- + + private List bindings() { + return bindings.get(bindings.size() - 1); + } + + private void ensureBindingsCapacity(int index) { + List b = bindings(); + + if (b.size() < index) { + b.addAll(nCopies(index - b.size(), null)); + } + } + + private void checkNotClosed() throws SQLException { + if (isClosed) { + throw new SQLException("Connection is already closed"); + } + } + + @Override + public Connection getConnection() throws SQLException { + return connection; + } + + // ------------------------------------------------------------------------- + // XXX: Executing queries + // ------------------------------------------------------------------------- + + @SuppressWarnings("unused") + private boolean execute0( + String localSql, + int localResultSetType, + int localResultSetConcurrency, + int localResultSetHoldability, + int localAutoGeneratedKeys, + int[] localColumnIndexes, + String[] localColumnNames) throws SQLException { + + checkNotClosed(); + + MockExecuteContext context = new MockExecuteContext( + new String[] { localSql }, + new Object[][] { bindings().toArray() }, + localAutoGeneratedKeys, + localColumnIndexes, + localColumnNames + ); + + MockStatement.this.result = data.execute(context); + return result != null && result.length > 0 && result[resultIndex].data != null; + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return getResultSet(); + } + + @Override + public boolean getMoreResults() throws SQLException { + return getMoreResults(CLOSE_CURRENT_RESULT); + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return (result != null && ++resultIndex < result.length); + } + + @SuppressWarnings("resource") + @Override + public ResultSet getResultSet() throws SQLException { + checkNotClosed(); + return (result != null && resultIndex < result.length && result[resultIndex].data != null) + ? new MockResultSet(result[resultIndex].data, maxRows) + : null; + } + + @Override + public int getUpdateCount() throws SQLException { + checkNotClosed(); + return (result != null && result.length > 0) ? result[resultIndex].rows : 0; + } + + @Override + public ResultSet executeQuery() throws SQLException { + return executeQuery(sql.get(0)); + } + + @Override + public ResultSet executeQuery(String localSql) throws SQLException { + execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, autoGeneratedKeys, columnIndexes, columnNames); + return getResultSet(); + } + + @Override + public boolean execute() throws SQLException { + return execute(sql.get(0)); + } + + @Override + public boolean execute(String localSql) throws SQLException { + return execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, autoGeneratedKeys, columnIndexes, columnNames); + } + + @Override + public boolean execute(String localSql, int localAutoGeneratedKeys) throws SQLException { + return execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, localAutoGeneratedKeys, null, null); + } + + @Override + public boolean execute(String localSql, int[] localColumnIndexes) throws SQLException { + return execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, Statement.RETURN_GENERATED_KEYS, localColumnIndexes, null); + } + + @Override + public boolean execute(String localSql, String[] localColumnNames) throws SQLException { + return execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, Statement.RETURN_GENERATED_KEYS, null, localColumnNames); + } + + @Override + public int executeUpdate() throws SQLException { + return executeUpdate(sql.get(0)); + } + + @Override + public int executeUpdate(String localSql) throws SQLException { + execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, autoGeneratedKeys, columnIndexes, columnNames); + return getUpdateCount(); + } + + @Override + public int executeUpdate(String localSql, int localAutoGeneratedKeys) throws SQLException { + execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, localAutoGeneratedKeys, null, null); + return getUpdateCount(); + } + + @Override + public int executeUpdate(String localSql, int[] localColumnIndexes) throws SQLException { + execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, Statement.RETURN_GENERATED_KEYS, localColumnIndexes, null); + return getUpdateCount(); + } + + @Override + public int executeUpdate(String localSql, String[] localColumnNames) throws SQLException { + execute0(localSql, resultSetType, resultSetConcurrency, resultSetHoldability, Statement.RETURN_GENERATED_KEYS, null, localColumnNames); + return getUpdateCount(); + } + + // ------------------------------------------------------------------------- + // XXX: Batch processing + // ------------------------------------------------------------------------- + + @Override + public void addBatch() throws SQLException { + checkNotClosed(); + bindings.add(new ArrayList()); + } + + @Override + public void addBatch(String localSql) throws SQLException { + checkNotClosed(); + sql.add(localSql); + } + + @Override + public void clearBatch() throws SQLException { + checkNotClosed(); + sql.clear(); + bindings.clear(); + bindings.add(new ArrayList()); + } + + @Override + public int[] executeBatch() throws SQLException { + checkNotClosed(); + + Object[][] matrix = new Object[bindings.size() - 1][]; + for (int i = 0; i < bindings.size() - 1; i++) { + matrix[i] = bindings.get(i).toArray(); + } + + result = data.execute(new MockExecuteContext(sql.toArray(new String[sql.size()]), matrix)); + + int[] rows = new int[result.length]; + for (int i = 0; i < result.length; i++) { + rows[i] = result[i].rows; + } + + return rows; + } + + // ------------------------------------------------------------------------- + // XXX: Bind variables + // ------------------------------------------------------------------------- + + @Override + public void clearParameters() throws SQLException { + checkNotClosed(); + List b = bindings(); + + for (int i = 0; i < b.size(); i++) { + b.set(i, null); + } + } + + @Override + public void setNull(int parameterIndex, int sqlType) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, null); + } + + @Override + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, null); + } + + @Override + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setByte(int parameterIndex, byte x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setShort(int parameterIndex, short x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setInt(int parameterIndex, int x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setLong(int parameterIndex, long x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setFloat(int parameterIndex, float x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setDouble(int parameterIndex, double x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setString(int parameterIndex, String x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setNString(int parameterIndex, String value) throws SQLException { + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, value); + } + + @Override + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setDate(int parameterIndex, Date x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setTime(int parameterIndex, Time x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setObject(int parameterIndex, Object x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setURL(int parameterIndex, URL x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x); + } + + @Override + public void setArray(int parameterIndex, Array x) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + bindings().set(parameterIndex - 1, x.getArray()); + } + + // ------------------------------------------------------------------------- + // XXX: Bind variables from CallableStatement + // ------------------------------------------------------------------------- + + @Override + public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException { + checkNotClosed(); + ensureBindingsCapacity(parameterIndex); + } + + @Override + public boolean wasNull() throws SQLException { + return false; + } + + @Override + public String getString(int parameterIndex) throws SQLException { + return null; + } + + @Override + public String getNString(int parameterIndex) throws SQLException { + return null; + } + + @Override + public boolean getBoolean(int parameterIndex) throws SQLException { + return false; + } + + @Override + public byte getByte(int parameterIndex) throws SQLException { + return 0; + } + + @Override + public short getShort(int parameterIndex) throws SQLException { + return 0; + } + + @Override + public int getInt(int parameterIndex) throws SQLException { + return 0; + } + + @Override + public long getLong(int parameterIndex) throws SQLException { + return 0; + } + + @Override + public float getFloat(int parameterIndex) throws SQLException { + return 0; + } + + @Override + public double getDouble(int parameterIndex) throws SQLException { + return 0; + } + + @Override + public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException { + return null; + } + + @Override + public byte[] getBytes(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Date getDate(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Time getTime(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Timestamp getTimestamp(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Object getObject(int parameterIndex) throws SQLException { + return null; + } + + @Override + public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Object getObject(int parameterIndex, Map> map) throws SQLException { + return null; + } + + @Override + public Array getArray(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Date getDate(int parameterIndex, Calendar cal) throws SQLException { + return null; + } + + @Override + public Time getTime(int parameterIndex, Calendar cal) throws SQLException { + return null; + } + + @Override + public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException { + return null; + } + + @Override + public URL getURL(int parameterIndex) throws SQLException { + return null; + } + + // ------------------------------------------------------------------------- + // XXX: Ignored operations + // ------------------------------------------------------------------------- + + @Override + public boolean isClosed() throws SQLException { + return isClosed; + } + + @Override + public void close() throws SQLException { + isClosed = true; + } + + @Override + public void cancel() throws SQLException { + isClosed = true; + } + + @Override + public int getMaxFieldSize() throws SQLException { + checkNotClosed(); + return 0; + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + checkNotClosed(); + } + + @Override + public int getMaxRows() throws SQLException { + checkNotClosed(); + return maxRows; + } + + @Override + public void setMaxRows(int max) throws SQLException { + checkNotClosed(); + this.maxRows = max; + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + checkNotClosed(); + } + + @Override + public int getQueryTimeout() throws SQLException { + checkNotClosed(); + return queryTimeout; + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + checkNotClosed(); + this.queryTimeout = seconds; + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + checkNotClosed(); + } + + @Override + public int getFetchDirection() throws SQLException { + checkNotClosed(); + return 0; + } + + @Override + public void setFetchSize(int rows) throws SQLException { + checkNotClosed(); + } + + @Override + public int getFetchSize() throws SQLException { + checkNotClosed(); + return 0; + } + + @Override + public int getResultSetConcurrency() throws SQLException { + checkNotClosed(); + return 0; + } + + @Override + public int getResultSetType() throws SQLException { + checkNotClosed(); + return 0; + } + + @Override + public int getResultSetHoldability() throws SQLException { + checkNotClosed(); + return 0; + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + checkNotClosed(); + } + + @Override + public boolean isPoolable() throws SQLException { + checkNotClosed(); + return false; + } + + @Override + public SQLWarning getWarnings() throws SQLException { + checkNotClosed(); + return null; + } + + @Override + public void clearWarnings() throws SQLException { + checkNotClosed(); + } + + @Override + public void setCursorName(String name) throws SQLException { + checkNotClosed(); + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + checkNotClosed(); + throw new SQLException("Can this be ignored?"); + } + + // ------------------------------------------------------------------------- + // XXX: Unsupported operations + // ------------------------------------------------------------------------- + + @Override + public T unwrap(Class iface) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public ParameterMetaData getParameterMetaData() throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNCharacterStream(String parameterName, Reader value) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setRef(int parameterIndex, Ref x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBlob(int parameterIndex, Blob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBlob(String parameterName, Blob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBlob(String parameterName, InputStream inputStream) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setClob(int parameterIndex, Clob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setClob(int parameterIndex, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setClob(String parameterName, Clob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setClob(String parameterName, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setClob(String parameterName, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNClob(int parameterIndex, NClob value) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNClob(String parameterName, NClob value) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNClob(String parameterName, Reader reader, long length) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNClob(String parameterName, Reader reader) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNString(String parameterName, String value) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setRowId(int parameterIndex, RowId x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setRowId(String parameterName, RowId x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setDate(String parameterName, Date x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setDate(String parameterName, Date x, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setTime(String parameterName, Time x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setTime(String parameterName, Time x, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setTimestamp(String parameterName, Timestamp x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setURL(String parameterName, URL val) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNull(String parameterName, int sqlType) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setNull(String parameterName, int sqlType, String typeName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBoolean(String parameterName, boolean x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setByte(String parameterName, byte x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setShort(String parameterName, short x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setInt(String parameterName, int x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setLong(String parameterName, long x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setFloat(String parameterName, float x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setDouble(String parameterName, double x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setString(String parameterName, String x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setBytes(String parameterName, byte[] x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void setObject(String parameterName, Object x) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public String getString(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public boolean getBoolean(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public byte getByte(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public short getShort(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public int getInt(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public long getLong(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public float getFloat(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public double getDouble(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public byte[] getBytes(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Date getDate(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Time getTime(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Timestamp getTimestamp(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Object getObject(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public BigDecimal getBigDecimal(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Object getObject(String parameterName, Map> map) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Ref getRef(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Ref getRef(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Blob getBlob(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Blob getBlob(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Clob getClob(int parameterIndex) throws SQLException { + return null; + } + + @Override + public Clob getClob(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public NClob getNClob(int parameterIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public NClob getNClob(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public String getNString(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Reader getNCharacterStream(int parameterIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Reader getNCharacterStream(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Reader getCharacterStream(int parameterIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Reader getCharacterStream(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Array getArray(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Date getDate(String parameterName, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Time getTime(String parameterName, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public URL getURL(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public RowId getRowId(int parameterIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public RowId getRowId(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public SQLXML getSQLXML(int parameterIndex) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } + + @Override + public SQLXML getSQLXML(String parameterName) throws SQLException { + throw new SQLFeatureNotSupportedException("Unsupported Operation"); + } +}