http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java new file mode 100644 index 0000000..0b1cad8 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinPreparedStatement.java @@ -0,0 +1,461 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.jdbc.thin; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.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.SQLXML; +import java.sql.Time; +import java.sql.Timestamp; +import java.util.ArrayList; +import java.util.Calendar; +import org.apache.ignite.internal.processors.odbc.SqlListenerUtils; + +/** + * JDBC prepared statement implementation. + */ +public class JdbcThinPreparedStatement extends JdbcThinStatement implements PreparedStatement { + /** SQL query. */ + private final String sql; + + /** + * Creates new prepared statement. + * + * @param conn Connection. + * @param sql SQL query. + */ + JdbcThinPreparedStatement(JdbcThinConnection conn, String sql) { + super(conn); + + this.sql = sql; + } + + /** {@inheritDoc} */ + @Override public ResultSet executeQuery() throws SQLException { + ResultSet rs = super.executeQuery(sql); + + args = null; + + return rs; + } + + /** {@inheritDoc} */ + @Override public ResultSet executeQuery(String sql) throws SQLException { + throw new SQLException("The method 'executeQuery(String)' is called on PreparedStatement instance."); + } + + /** {@inheritDoc} */ + @Override public int executeUpdate() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public int executeUpdate(String sql) throws SQLException { + throw new SQLException("The method 'executeUpdate(String)' is called on PreparedStatement instance."); + } + + /** {@inheritDoc} */ + @Override public void setNull(int paramIdx, int sqlType) throws SQLException { + setArgument(paramIdx, null); + } + + /** {@inheritDoc} */ + @Override public void setBoolean(int paramIdx, boolean x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setByte(int paramIdx, byte x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setShort(int paramIdx, short x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setInt(int paramIdx, int x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setLong(int paramIdx, long x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setFloat(int paramIdx, float x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setDouble(int paramIdx, double x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setBigDecimal(int paramIdx, BigDecimal x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setString(int paramIdx, String x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setBytes(int paramIdx, byte[] x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setDate(int paramIdx, Date x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setTime(int paramIdx, Time x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setTimestamp(int paramIdx, Timestamp x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setAsciiStream(int paramIdx, InputStream x, int length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setUnicodeStream(int paramIdx, InputStream x, int length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setBinaryStream(int paramIdx, InputStream x, int length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void clearParameters() throws SQLException { + ensureNotClosed(); + + args = null; + } + + /** {@inheritDoc} */ + @Override public void setObject(int paramIdx, Object x, int targetSqlType) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setObject(int paramIdx, Object x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public boolean execute() throws SQLException { + return super.execute(sql); + } + + /** {@inheritDoc} */ + @Override public boolean execute(String sql) throws SQLException { + throw new SQLException("The method 'execute(String)' is called on PreparedStatement instance."); + } + + /** {@inheritDoc} */ + @Override public void addBatch() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setCharacterStream(int paramIdx, Reader x, int length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setRef(int paramIdx, Ref x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setBlob(int paramIdx, Blob x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setClob(int paramIdx, Clob x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setArray(int paramIdx, Array x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public ResultSetMetaData getMetaData() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Meta data for prepared statement is not supported."); + } + + /** {@inheritDoc} */ + @Override public void setDate(int paramIdx, Date x, Calendar cal) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setTime(int paramIdx, Time x, Calendar cal) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setTimestamp(int paramIdx, Timestamp x, Calendar cal) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setNull(int paramIdx, int sqlType, String typeName) throws SQLException { + if (!JdbcThinUtils.isPlainJdbcType(sqlType)) { + throw new SQLFeatureNotSupportedException("The SQL type is unsupported. [type=" + sqlType + "typeName=" + + typeName + ']'); + } + + setNull(paramIdx, sqlType); + } + + /** {@inheritDoc} */ + @Override public void setURL(int paramIdx, URL x) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public ParameterMetaData getParameterMetaData() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Meta data for prepared statement is not supported."); + } + + /** {@inheritDoc} */ + @Override public void setRowId(int paramIdx, RowId x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setNString(int paramIdx, String val) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setNCharacterStream(int paramIdx, Reader val, long length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setNClob(int paramIdx, NClob val) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setClob(int paramIdx, Reader reader, long length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setBlob(int paramIdx, InputStream inputStream, long length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setNClob(int paramIdx, Reader reader, long length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setSQLXML(int paramIdx, SQLXML xmlObj) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setObject(int paramIdx, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + setArgument(paramIdx, x); + } + + /** {@inheritDoc} */ + @Override public void setAsciiStream(int paramIdx, InputStream x, long length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setBinaryStream(int paramIdx, InputStream x, long length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setCharacterStream(int paramIdx, Reader x, long length) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setAsciiStream(int paramIdx, InputStream x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setBinaryStream(int paramIdx, InputStream x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setCharacterStream(int paramIdx, Reader x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setNCharacterStream(int paramIdx, Reader val) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setClob(int paramIdx, Reader reader) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setBlob(int paramIdx, InputStream inputStream) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void setNClob(int paramIdx, Reader reader) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public <T> T unwrap(Class<T> iface) throws SQLException { + if (!isWrapperFor(iface)) + throw new SQLException("Prepared statement is not a wrapper for " + iface.getName()); + + return (T)this; + } + + /** {@inheritDoc} */ + @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { + return iface != null && iface.isAssignableFrom(JdbcThinPreparedStatement.class); + } + + /** + * Sets query argument value. + * + * @param paramIdx Index. + * @param val Value. + * @throws SQLException If index is invalid. + */ + private void setArgument(int paramIdx, Object val) throws SQLException { + ensureNotClosed(); + + if (val != null && !SqlListenerUtils.isPlainType(val.getClass())) + throw new SQLException("Parameter type is unsupported. [cls=" + val.getClass() + ']'); + + if (paramIdx < 1) + throw new SQLException("Parameter index is invalid: " + paramIdx); + + if (args == null) + args = new ArrayList<>(paramIdx); + + while (args.size() < paramIdx) + args.add(null); + + args.set(paramIdx - 1, val); + } +} \ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java new file mode 100644 index 0000000..f4ab444 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSet.java @@ -0,0 +1,1698 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.jdbc.thin; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.Array; +import java.sql.Blob; +import java.sql.Clob; +import java.sql.Date; +import java.sql.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.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryFetchResult; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryMetadataResult; + +/** + * JDBC result set implementation. + */ +public class JdbcThinResultSet implements ResultSet { + /** Statement. */ + private final JdbcThinStatement stmt; + + /** Query ID. */ + private final Long qryId; + + /** Metadata. */ + private List<JdbcColumnMeta> meta; + + /** Column order map. */ + private Map<String, Integer> colOrder; + + /** Metadata initialization flag. */ + private boolean metaInit; + + /** Rows. */ + private List<List<Object>> rows; + + /** Rows iterator. */ + private Iterator<List<Object>> rowsIter; + + /** Current row. */ + private List<Object> curRow; + + /** Current position. */ + private int curPos; + + /** Finished flag. */ + private boolean finished; + + /** Closed flag. */ + private boolean closed; + + /** Was {@code NULL} flag. */ + private boolean wasNull; + + /** Fetch size. */ + private int fetchSize; + + /** Is query flag. */ + private boolean isQuery; + + /** Update count. */ + private long updCnt; + + /** + * Creates new result set. + * + * @param stmt Statement. + * @param qryId Query ID. + * @param fetchSize Fetch size. + * @param finished Finished flag. + * @param rows Rows. + * @param isQuery Is Result ser for Select query + */ + @SuppressWarnings("OverlyStrongTypeCast") JdbcThinResultSet(JdbcThinStatement stmt, long qryId, int fetchSize, boolean finished, + List<List<Object>> rows, boolean isQuery) { + assert stmt != null; + assert fetchSize > 0; + + this.stmt = stmt; + this.qryId = qryId; + this.fetchSize = fetchSize; + this.rows = rows; + this.finished = finished; + + rowsIter = rows.iterator(); + + this.isQuery = isQuery; + } + + /** {@inheritDoc} */ + @SuppressWarnings("unchecked") + @Override public boolean next() throws SQLException { + ensureNotClosed(); + + if (rowsIter == null && !finished) { + try { + JdbcQueryFetchResult res = stmt.connection().cliIo().queryFetch(qryId, fetchSize); + + rows = res.items(); + finished = res.last(); + + rowsIter = rows.iterator(); + } + catch (IOException e) { + stmt.connection().close(); + + throw new SQLException("Failed to query Ignite.", e); + } + catch (IgniteCheckedException e) { + throw new SQLException("Failed to query Ignite.", e); + } + } + + if (rowsIter != null) { + if (rowsIter.hasNext()) { + curRow = rowsIter.next(); + + curPos++; + + return true; + } + else { + rowsIter = null; + curRow = null; + + return false; + } + } + else + return false; + } + + /** {@inheritDoc} */ + @Override public void close() throws SQLException { + if (closed || stmt.connection().isClosed()) + return; + + try { + stmt.connection().cliIo().queryClose(qryId); + + closed = true; + } + catch (IOException e) { + stmt.connection().close(); + + throw new SQLException("Failed to close Ignite query.", e); + } + catch (IgniteCheckedException e) { + throw new SQLException("Failed to close Ignite query.", e); + } + } + + /** {@inheritDoc} */ + @Override public boolean wasNull() throws SQLException { + return wasNull; + } + + /** {@inheritDoc} */ + @Override public String getString(int colIdx) throws SQLException { + ensureNotClosed(); + ensureHasCurrentRow(); + + try { + Object val = curRow.get(colIdx - 1); + + wasNull = val == null; + + if (val == null) + return null; + else + return String.valueOf(val); + } + catch (IndexOutOfBoundsException e) { + throw new SQLException("Invalid column index: " + colIdx, e); + } + } + + /** {@inheritDoc} */ + @Override public boolean getBoolean(int colIdx) throws SQLException { + try { + Object val = curRow.get(colIdx - 1); + + wasNull = val == null; + + if (val == null) + return false; + else if (val.getClass() == Boolean.class) + return (Boolean)val; + else { + if (val.getClass() == Byte.class + || val.getClass() == Short.class + || val.getClass() == Integer.class + || val.getClass() == Long.class) + return castToBoolean((Number)val); + else if (val.getClass() == Character.class + || val.getClass() == String.class) + return castToBoolean(val.toString()); + else + throw new ClassCastException("Cannot cast " + val.getClass().getName() + " to boolean"); + } + } + catch (IndexOutOfBoundsException e) { + throw new SQLException("Invalid column index: " + colIdx, e); + } + catch (ClassCastException e) { + throw new SQLException("Value is an not instance of " + Boolean.class.getName(), e); + } + } + + /** {@inheritDoc} */ + @Override public byte getByte(int colIdx) throws SQLException { + Byte val = getTypedValue(colIdx, Byte.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public short getShort(int colIdx) throws SQLException { + Short val = getTypedValue(colIdx, Short.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public int getInt(int colIdx) throws SQLException { + Integer val = getTypedValue(colIdx, Integer.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public long getLong(int colIdx) throws SQLException { + Long val = getTypedValue(colIdx, Long.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public float getFloat(int colIdx) throws SQLException { + Float val = getTypedValue(colIdx, Float.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public double getDouble(int colIdx) throws SQLException { + Double val = getTypedValue(colIdx, Double.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public BigDecimal getBigDecimal(int colIdx, int scale) throws SQLException { + return getTypedValue(colIdx, BigDecimal.class); + } + + /** {@inheritDoc} */ + @Override public byte[] getBytes(int colIdx) throws SQLException { + return getTypedValue(colIdx, byte[].class); + } + + /** {@inheritDoc} */ + @Override public Date getDate(int colIdx) throws SQLException { + ensureNotClosed(); + ensureHasCurrentRow(); + + try { + Object val = curRow.get(colIdx - 1); + + wasNull = val == null; + + if (val == null) + return null; + else if (val.getClass() == java.util.Date.class) + return new java.sql.Date(((java.util.Date)val).getTime()); + else + return (Date)val; + } + catch (IndexOutOfBoundsException e) { + throw new SQLException("Invalid column index: " + colIdx, e); + } + catch (ClassCastException e) { + throw new SQLException("Value is an not instance of Date", e); + } + } + + /** {@inheritDoc} */ + @Override public Time getTime(int colIdx) throws SQLException { + return getTypedValue(colIdx, Time.class); + } + + /** {@inheritDoc} */ + @Override public Timestamp getTimestamp(int colIdx) throws SQLException { + return getTypedValue(colIdx, Timestamp.class); + } + + /** {@inheritDoc} */ + @Override public InputStream getAsciiStream(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public InputStream getUnicodeStream(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public InputStream getBinaryStream(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Stream are not supported."); + } + + /** {@inheritDoc} */ + @Override public String getString(String colLb) throws SQLException { + int colIdx = findColumn(colLb); + + assert colIdx > 0; + + return getString(colIdx); + } + + /** {@inheritDoc} */ + @Override public boolean getBoolean(String colLb) throws SQLException { + int colIdx = findColumn(colLb); + + assert colIdx > 0; + + return getBoolean(colIdx); + } + + /** {@inheritDoc} */ + @Override public byte getByte(String colLb) throws SQLException { + Byte val = getTypedValue(colLb, Byte.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public short getShort(String colLb) throws SQLException { + Short val = getTypedValue(colLb, Short.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public int getInt(String colLb) throws SQLException { + Integer val = getTypedValue(colLb, Integer.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public long getLong(String colLb) throws SQLException { + Long val = getTypedValue(colLb, Long.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public float getFloat(String colLb) throws SQLException { + Float val = getTypedValue(colLb, Float.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public double getDouble(String colLb) throws SQLException { + Double val = getTypedValue(colLb, Double.class); + + return val != null ? val : 0; + } + + /** {@inheritDoc} */ + @Override public BigDecimal getBigDecimal(String colLb, int scale) throws SQLException { + return getTypedValue(colLb, BigDecimal.class); + } + + /** {@inheritDoc} */ + @Override public byte[] getBytes(String colLb) throws SQLException { + return getTypedValue(colLb, byte[].class); + } + + /** {@inheritDoc} */ + @Override public Date getDate(String colLb) throws SQLException { + int colIdx = findColumn(colLb); + + assert colIdx > 0; + + return getDate(colIdx); + } + + /** {@inheritDoc} */ + @Override public Time getTime(String colLb) throws SQLException { + return getTypedValue(colLb, Time.class); + } + + /** {@inheritDoc} */ + @Override public Timestamp getTimestamp(String colLb) throws SQLException { + return getTypedValue(colLb, Timestamp.class); + } + + /** {@inheritDoc} */ + @Override public InputStream getAsciiStream(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public InputStream getUnicodeStream(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public InputStream getBinaryStream(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public SQLWarning getWarnings() throws SQLException { + ensureNotClosed(); + + return null; + } + + /** {@inheritDoc} */ + @Override public void clearWarnings() throws SQLException { + ensureNotClosed(); + } + + /** {@inheritDoc} */ + @Override public String getCursorName() throws SQLException { + ensureNotClosed(); + + return null; + } + + /** {@inheritDoc} */ + @Override public ResultSetMetaData getMetaData() throws SQLException { + ensureNotClosed(); + + return new JdbcThinResultSetMetadata(meta()); + } + + /** {@inheritDoc} */ + @Override public Object getObject(int colIdx) throws SQLException { + return getTypedValue(colIdx, Object.class); + } + + /** {@inheritDoc} */ + @Override public Object getObject(String colLb) throws SQLException { + return getTypedValue(colLb, Object.class); + } + + /** {@inheritDoc} */ + @Override public int findColumn(final String colLb) throws SQLException { + ensureNotClosed(); + + Integer order = columnOrder().get(colLb.toUpperCase()); + + if (order == null) + throw new SQLException("Column not found: " + colLb); + + return order + 1; + } + + /** {@inheritDoc} */ + @Override public Reader getCharacterStream(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public Reader getCharacterStream(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Streams are not supported."); + } + + /** {@inheritDoc} */ + @Override public BigDecimal getBigDecimal(int colIdx) throws SQLException { + return getTypedValue(colIdx, BigDecimal.class); + } + + /** {@inheritDoc} */ + @Override public BigDecimal getBigDecimal(String colLb) throws SQLException { + return getTypedValue(colLb, BigDecimal.class); + } + + /** {@inheritDoc} */ + @Override public boolean isBeforeFirst() throws SQLException { + ensureNotClosed(); + + return curPos == 0 && rowsIter != null && rowsIter.hasNext(); + } + + /** {@inheritDoc} */ + @Override public boolean isAfterLast() throws SQLException { + ensureNotClosed(); + + return finished && rowsIter == null && curRow == null; + } + + /** {@inheritDoc} */ + @Override public boolean isFirst() throws SQLException { + ensureNotClosed(); + + return curPos == 1; + } + + /** {@inheritDoc} */ + @Override public boolean isLast() throws SQLException { + ensureNotClosed(); + + return finished && rowsIter != null && !rowsIter.hasNext() && curRow != null; + } + + /** {@inheritDoc} */ + @Override public void beforeFirst() throws SQLException { + ensureNotClosed(); + + throw new SQLException("Result set is forward-only."); + } + + /** {@inheritDoc} */ + @Override public void afterLast() throws SQLException { + ensureNotClosed(); + + throw new SQLException("Result set is forward-only."); + } + + /** {@inheritDoc} */ + @Override public boolean first() throws SQLException { + ensureNotClosed(); + + throw new SQLException("Result set is forward-only."); + } + + /** {@inheritDoc} */ + @Override public boolean last() throws SQLException { + ensureNotClosed(); + + throw new SQLException("Result set is forward-only."); + } + + /** {@inheritDoc} */ + @Override public int getRow() throws SQLException { + ensureNotClosed(); + + return isAfterLast() ? 0 : curPos; + } + + /** {@inheritDoc} */ + @Override public boolean absolute(int row) throws SQLException { + ensureNotClosed(); + + throw new SQLException("Result set is forward-only."); + } + + /** {@inheritDoc} */ + @Override public boolean relative(int rows) throws SQLException { + ensureNotClosed(); + + throw new SQLException("Result set is forward-only."); + } + + /** {@inheritDoc} */ + @Override public boolean previous() throws SQLException { + ensureNotClosed(); + + throw new SQLException("Result set is forward-only."); + } + + /** {@inheritDoc} */ + @Override public void setFetchDirection(int direction) throws SQLException { + ensureNotClosed(); + + if (direction != FETCH_FORWARD) + throw new SQLFeatureNotSupportedException("Only forward direction is supported"); + } + + /** {@inheritDoc} */ + @Override public int getFetchDirection() throws SQLException { + ensureNotClosed(); + + return FETCH_FORWARD; + } + + /** {@inheritDoc} */ + @Override public void setFetchSize(int fetchSize) throws SQLException { + ensureNotClosed(); + + if (fetchSize <= 0) + throw new SQLException("Fetch size must be greater than zero."); + + this.fetchSize = fetchSize; + } + + /** {@inheritDoc} */ + @Override public int getFetchSize() throws SQLException { + ensureNotClosed(); + + return fetchSize; + } + + /** {@inheritDoc} */ + @Override public int getType() throws SQLException { + ensureNotClosed(); + + return stmt.getResultSetType(); + } + + /** {@inheritDoc} */ + @Override public int getConcurrency() throws SQLException { + ensureNotClosed(); + + return CONCUR_READ_ONLY; + } + + /** {@inheritDoc} */ + @Override public boolean rowUpdated() throws SQLException { + ensureNotClosed(); + + return false; + } + + /** {@inheritDoc} */ + @Override public boolean rowInserted() throws SQLException { + ensureNotClosed(); + + return false; + } + + /** {@inheritDoc} */ + @Override public boolean rowDeleted() throws SQLException { + ensureNotClosed(); + + return false; + } + + /** {@inheritDoc} */ + @Override public void updateNull(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBoolean(int colIdx, boolean x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateByte(int colIdx, byte x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateShort(int colIdx, short x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateInt(int colIdx, int x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateLong(int colIdx, long x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateFloat(int colIdx, float x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateDouble(int colIdx, double x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBigDecimal(int colIdx, BigDecimal x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateString(int colIdx, String x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBytes(int colIdx, byte[] x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateDate(int colIdx, Date x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateTime(int colIdx, Time x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateTimestamp(int colIdx, Timestamp x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateAsciiStream(int colIdx, InputStream x, int len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBinaryStream(int colIdx, InputStream x, int len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateCharacterStream(int colIdx, Reader x, int len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateObject(int colIdx, Object x, int scaleOrLen) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateObject(int colIdx, Object x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNull(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBoolean(String colLb, boolean x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateByte(String colLb, byte x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateShort(String colLb, short x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateInt(String colLb, int x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateLong(String colLb, long x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateFloat(String colLb, float x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateDouble(String colLb, double x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBigDecimal(String colLb, BigDecimal x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateString(String colLb, String x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBytes(String colLb, byte[] x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateDate(String colLb, Date x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateTime(String colLb, Time x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateTimestamp(String colLb, Timestamp x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateAsciiStream(String colLb, InputStream x, int len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBinaryStream(String colLb, InputStream x, int len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateCharacterStream(String colLb, Reader reader, int len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateObject(String colLb, Object x, int scaleOrLen) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateObject(String colLb, Object x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void insertRow() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateRow() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void deleteRow() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void refreshRow() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Row refreshing is not supported."); + } + + /** {@inheritDoc} */ + @Override public void cancelRowUpdates() throws SQLException { + ensureNotClosed(); + + if (getConcurrency() == CONCUR_READ_ONLY) + throw new SQLException("The result set concurrency is CONCUR_READ_ONLY"); + } + + /** {@inheritDoc} */ + @Override public void moveToInsertRow() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void moveToCurrentRow() throws SQLException { + ensureNotClosed(); + + if (getConcurrency() == CONCUR_READ_ONLY) + throw new SQLException("The result set concurrency is CONCUR_READ_ONLY"); + } + + /** {@inheritDoc} */ + @Override public Statement getStatement() throws SQLException { + ensureNotClosed(); + + return stmt; + } + + /** {@inheritDoc} */ + @Override public Object getObject(int colIdx, Map<String, Class<?>> map) throws SQLException { + throw new SQLFeatureNotSupportedException("SQL structured type are not supported."); + } + + /** {@inheritDoc} */ + @Override public Ref getRef(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Blob getBlob(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Clob getClob(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Array getArray(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Object getObject(String colLb, Map<String, Class<?>> map) throws SQLException { + throw new SQLFeatureNotSupportedException("SQL structured type are not supported."); + } + + /** {@inheritDoc} */ + @Override public Ref getRef(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Blob getBlob(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Clob getClob(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Array getArray(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Date getDate(int colIdx, Calendar cal) throws SQLException { + ensureNotClosed(); + ensureHasCurrentRow(); + + try { + Object val = curRow.get(colIdx - 1); + + wasNull = val == null; + + if (val == null) + return null; + else if (val.getClass() == java.util.Date.class) + return new Date(((java.util.Date)val).getTime()); + else + return (Date)val; + } + catch (IndexOutOfBoundsException e) { + throw new SQLException("Invalid column index: " + colIdx, e); + } + catch (ClassCastException e) { + throw new SQLException("Value is an not instance of Date", e); + } + } + + /** {@inheritDoc} */ + @Override public Date getDate(String colLb, Calendar cal) throws SQLException { + int colIdx = findColumn(colLb); + + assert colIdx > 0; + + return getDate(colIdx, cal); + } + + /** {@inheritDoc} */ + @Override public Time getTime(int colIdx, Calendar cal) throws SQLException { + return getTypedValue(colIdx, Time.class); + } + + /** {@inheritDoc} */ + @Override public Time getTime(String colLb, Calendar cal) throws SQLException { + return getTypedValue(colLb, Time.class); + } + + /** {@inheritDoc} */ + @Override public Timestamp getTimestamp(int colIdx, Calendar cal) throws SQLException { + return getTypedValue(colIdx, Timestamp.class); + } + + /** {@inheritDoc} */ + @Override public Timestamp getTimestamp(String colLb, Calendar cal) throws SQLException { + return getTypedValue(colLb, Timestamp.class); + } + + /** {@inheritDoc} */ + @Override public URL getURL(int colIdx) throws SQLException { + return getTypedValue(colIdx, URL.class); + } + + /** {@inheritDoc} */ + @Override public URL getURL(String colLb) throws SQLException { + return getTypedValue(colLb, URL.class); + } + + /** {@inheritDoc} */ + @Override public void updateRef(int colIdx, Ref x) throws SQLException { + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateRef(String colLb, Ref x) throws SQLException { + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBlob(int colIdx, Blob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBlob(String colLb, Blob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateClob(int colIdx, Clob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateClob(String colLb, Clob x) throws SQLException { + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateArray(int colIdx, Array x) throws SQLException { + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateArray(String colLb, Array x) throws SQLException { + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public RowId getRowId(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public RowId getRowId(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateRowId(int colIdx, RowId x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateRowId(String colLb, RowId x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public int getHoldability() throws SQLException { + ensureNotClosed(); + + return HOLD_CURSORS_OVER_COMMIT; + } + + /** {@inheritDoc} */ + @Override public boolean isClosed() throws SQLException { + return stmt.isClosed() || closed; + } + + /** {@inheritDoc} */ + @Override public void updateNString(int colIdx, String nStr) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNString(String colLb, String nStr) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNClob(int colIdx, NClob nClob) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNClob(String colLb, NClob nClob) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public NClob getNClob(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public NClob getNClob(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public SQLXML getSQLXML(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public SQLXML getSQLXML(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateSQLXML(int colIdx, SQLXML xmlObj) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateSQLXML(String colLb, SQLXML xmlObj) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public String getNString(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public String getNString(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Reader getNCharacterStream(int colIdx) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public Reader getNCharacterStream(String colLb) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("SQL-specific types are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNCharacterStream(int colIdx, Reader x, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNCharacterStream(String colLb, Reader reader, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateAsciiStream(int colIdx, InputStream x, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBinaryStream(int colIdx, InputStream x, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateCharacterStream(int colIdx, Reader x, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateAsciiStream(String colLb, InputStream x, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBinaryStream(String colLb, InputStream x, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateCharacterStream(String colLb, Reader reader, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBlob(int colIdx, InputStream inputStream, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBlob(String colLb, InputStream inputStream, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateClob(int colIdx, Reader reader, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateClob(String colLb, Reader reader, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNClob(int colIdx, Reader reader, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNClob(String colLb, Reader reader, long len) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNCharacterStream(int colIdx, Reader x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNCharacterStream(String colLb, Reader reader) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateAsciiStream(int colIdx, InputStream x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBinaryStream(int colIdx, InputStream x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateCharacterStream(int colIdx, Reader x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateAsciiStream(String colLb, InputStream x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBinaryStream(String colLb, InputStream x) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateCharacterStream(String colLb, Reader reader) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBlob(int colIdx, InputStream inputStream) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateBlob(String colLb, InputStream inputStream) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateClob(int colIdx, Reader reader) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateClob(String colLb, Reader reader) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNClob(int colIdx, Reader reader) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void updateNClob(String colLb, Reader reader) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public <T> T unwrap(Class<T> iface) throws SQLException { + if (!isWrapperFor(iface)) + throw new SQLException("Result set is not a wrapper for " + iface.getName()); + + return (T)this; + } + + /** {@inheritDoc} */ + @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { + return iface != null && iface.isAssignableFrom(JdbcThinResultSet.class); + } + + /** {@inheritDoc} */ + @Override public <T> T getObject(int colIdx, Class<T> type) throws SQLException { + return getTypedValue(colIdx, type); + } + + /** {@inheritDoc} */ + @Override public <T> T getObject(String colLb, Class<T> type) throws SQLException { + return getTypedValue(colLb, type); + } + + /** + * Gets casted field value by label. + * + * @param colLb Column label. + * @param cls Value class. + * @return Casted field value. + * @throws SQLException In case of error. + */ + private <T> T getTypedValue(String colLb, Class<T> cls) throws SQLException { + ensureNotClosed(); + ensureHasCurrentRow(); + + int colIdx = findColumn(colLb); + + assert colIdx > 0; + + return getTypedValue(colIdx, cls); + } + + /** + * Gets casted field value by index. + * + * @param colIdx Column index. + * @param cls Value class. + * @return Casted field value. + * @throws SQLException In case of error. + */ + @SuppressWarnings("unchecked") + private <T> T getTypedValue(int colIdx, Class<T> cls) throws SQLException { + ensureNotClosed(); + ensureHasCurrentRow(); + + try { + Object val = curRow.get(colIdx - 1); + + wasNull = val == null; + + if (val == null) + return null; + else + return (T)val; + } + catch (IndexOutOfBoundsException e) { + throw new SQLException("Invalid column index: " + colIdx, e); + } + catch (ClassCastException e) { + throw new SQLException("Value is an not instance of " + cls.getName(), e); + } + } + + /** + * Ensures that result set is not closed. + * + * @throws SQLException If result set is closed. + */ + private void ensureNotClosed() throws SQLException { + if (closed) + throw new SQLException("Result set is closed."); + } + + /** + * Ensures that result set is positioned on a row. + * + * @throws SQLException If result set is not positioned on a row. + */ + private void ensureHasCurrentRow() throws SQLException { + if (curRow == null) + throw new SQLException("Result set is not positioned on a row."); + } + + /** + * @return Results metadata. + * @throws SQLException On error. + */ + private List<JdbcColumnMeta> meta() throws SQLException { + if (!metaInit) { + try { + JdbcQueryMetadataResult res = stmt.connection().cliIo().queryMeta(qryId); + + meta = res.meta(); + + metaInit = true; + } + catch (IOException e) { + stmt.connection().close(); + + throw new SQLException("Failed to get query metadata.", e); + } + catch (IgniteCheckedException e) { + throw new SQLException("Failed to get query metadata.", e); + } + } + + return meta; + } + + /** + * Init column order map. + * @throws SQLException On error. + * @return Column order map. + */ + private Map<String, Integer> columnOrder() throws SQLException { + if(colOrder != null) + return colOrder; + + if(!metaInit) + meta(); + + colOrder = new HashMap<>(meta.size()); + + for (int i = 0; i < meta.size(); ++i) { + String colName = meta.get(i).columnName().toUpperCase(); + + if(!colOrder.containsKey(colName)) + colOrder.put(colName, i); + } + + return colOrder; + } + + /** + * @return Is query flag. + */ + boolean isQuery() { + return isQuery; + } + + /** + * @return Update count for no-SELECT queries. + */ + long updatedCount() { + return updCnt; + } + + /** + * @param val Number value. + * @return Boolean value. + */ + private static boolean castToBoolean(Number val) { + if (val.intValue() == 1) + return true; + else if (val.intValue() == 0) + return false; + else + throw new ClassCastException("Cannot cast " + val.getClass().getName() + + " [val=" + val +"] to boolean"); + } + + /** + * @param str String value. + * @return Boolean value. + */ + private static boolean castToBoolean(String str) { + try { + return castToBoolean(Integer.parseInt(str)); + } + catch (NumberFormatException e) { + throw new ClassCastException("Cannot cast [val=" + str +"] to boolean"); + } + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java new file mode 100644 index 0000000..4c560bc --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinResultSetMetadata.java @@ -0,0 +1,161 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.jdbc.thin; + +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.util.List; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcColumnMeta; + +/** + * JDBC result set metadata implementation. + */ +public class JdbcThinResultSetMetadata implements ResultSetMetaData { + /** Column width. */ + private static final int COL_WIDTH = 30; + + /** Table names. */ + private final List<JdbcColumnMeta> meta; + + /** + * @param meta Metadata. + */ + JdbcThinResultSetMetadata(List<JdbcColumnMeta> meta) { + assert meta != null; + + this.meta = meta; + } + + /** {@inheritDoc} */ + @Override public int getColumnCount() throws SQLException { + return meta.size(); + } + + /** {@inheritDoc} */ + @Override public boolean isAutoIncrement(int col) throws SQLException { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isCaseSensitive(int col) throws SQLException { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isSearchable(int col) throws SQLException { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isCurrency(int col) throws SQLException { + return false; + } + + /** {@inheritDoc} */ + @Override public int isNullable(int col) throws SQLException { + return columnNullable; + } + + /** {@inheritDoc} */ + @Override public boolean isSigned(int col) throws SQLException { + return true; + } + + /** {@inheritDoc} */ + @Override public int getColumnDisplaySize(int col) throws SQLException { + return COL_WIDTH; + } + + /** {@inheritDoc} */ + @Override public String getColumnLabel(int col) throws SQLException { + return meta.get(col - 1).columnName(); + } + + /** {@inheritDoc} */ + @Override public String getColumnName(int col) throws SQLException { + return meta.get(col - 1).columnName(); + } + + /** {@inheritDoc} */ + @Override public String getSchemaName(int col) throws SQLException { + return meta.get(col - 1).schemaName(); + } + + /** {@inheritDoc} */ + @Override public int getPrecision(int col) throws SQLException { + return 0; + } + + /** {@inheritDoc} */ + @Override public int getScale(int col) throws SQLException { + return 0; + } + + /** {@inheritDoc} */ + @Override public String getTableName(int col) throws SQLException { + return meta.get(col - 1).tableName(); + } + + /** {@inheritDoc} */ + @Override public String getCatalogName(int col) throws SQLException { + return ""; + } + + /** {@inheritDoc} */ + @Override public int getColumnType(int col) throws SQLException { + return meta.get(col - 1).dataType(); + } + + /** {@inheritDoc} */ + @Override public String getColumnTypeName(int col) throws SQLException { + return meta.get(col - 1).dataTypeName(); + } + + /** {@inheritDoc} */ + @Override public boolean isReadOnly(int col) throws SQLException { + return true; + } + + /** {@inheritDoc} */ + @Override public boolean isWritable(int col) throws SQLException { + return false; + } + + /** {@inheritDoc} */ + @Override public boolean isDefinitelyWritable(int col) throws SQLException { + return false; + } + + /** {@inheritDoc} */ + @Override public String getColumnClassName(int col) throws SQLException { + return meta.get(col - 1).dataTypeClass(); + } + + /** {@inheritDoc} */ + @Override public <T> T unwrap(Class<T> iface) throws SQLException { + if (!isWrapperFor(iface)) + throw new SQLException("Result set meta data is not a wrapper for " + iface.getName()); + + return (T)this; + } + + /** {@inheritDoc} */ + @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { + return iface != null && iface.isAssignableFrom(JdbcThinResultSetMetadata.class); + } +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/ignite/blob/e92707b6/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java ---------------------------------------------------------------------- diff --git a/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java new file mode 100644 index 0000000..2bcd4d1 --- /dev/null +++ b/modules/core/src/main/java/org/apache/ignite/internal/jdbc/thin/JdbcThinStatement.java @@ -0,0 +1,475 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.apache.ignite.internal.jdbc.thin; + +import java.io.IOException; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.SQLFeatureNotSupportedException; +import java.sql.SQLWarning; +import java.sql.Statement; +import java.util.ArrayList; +import org.apache.ignite.IgniteCheckedException; +import org.apache.ignite.cache.query.SqlQuery; +import org.apache.ignite.internal.processors.odbc.jdbc.JdbcQueryExecuteResult; + +import static java.sql.ResultSet.CONCUR_READ_ONLY; +import static java.sql.ResultSet.FETCH_FORWARD; +import static java.sql.ResultSet.HOLD_CURSORS_OVER_COMMIT; +import static java.sql.ResultSet.TYPE_FORWARD_ONLY; + +/** + * JDBC statement implementation. + */ +public class JdbcThinStatement implements Statement { + /** Default queryPage size. */ + private static final int DFLT_PAGE_SIZE = SqlQuery.DFLT_PAGE_SIZE; + + /** Ignite endpoint and I/O protocol implementation. */ + private JdbcThinConnection conn; + + /** Closed flag. */ + private boolean closed; + + /** Rows limit. */ + private int maxRows; + + /** Query timeout. */ + private int timeout; + + /** Current result set. */ + private JdbcThinResultSet rs; + + /** Query arguments. */ + protected ArrayList<Object> args; + + /** Fetch size. */ + private int pageSize = DFLT_PAGE_SIZE; + + private boolean alreadyRead; + + /** + * Creates new statement. + * + * @param conn JDBC connection. + */ + JdbcThinStatement(JdbcThinConnection conn) { + assert conn != null; + + this.conn = conn; + } + + /** {@inheritDoc} */ + @Override public ResultSet executeQuery(String sql) throws SQLException { + JdbcThinResultSet rs = execute0(sql); + + if (!rs.isQuery()) + throw new SQLException("The query isn't SELECT query: [sql=" + sql +']'); + + return rs; + } + + /** + * @param sql Sql query. + * @return Result set. + * @throws SQLException Onj error. + */ + protected JdbcThinResultSet execute0(String sql) throws SQLException { + ensureNotClosed(); + + if (rs != null) { + rs.close(); + + rs = null; + } + + alreadyRead = false; + + if (sql == null || sql.isEmpty()) + throw new SQLException("SQL query is empty."); + + try { + JdbcQueryExecuteResult res = conn.cliIo().queryExecute(conn.getSchema(), pageSize, maxRows, + sql, args); + + assert res != null; + + rs = new JdbcThinResultSet(this, res.getQueryId(), pageSize, res.last(), res.items(), res.isQuery()); + + return rs; + } + catch (IOException e) { + conn.close(); + + throw new SQLException("Failed to query Ignite.", e); + } + catch (IgniteCheckedException e) { + throw new SQLException("Failed to query Ignite.", e); + } + } + + /** {@inheritDoc} */ + @Override public int executeUpdate(String sql) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void close() throws SQLException { + if (isClosed()) + return; + + if (rs != null) + rs.close(); + + closed = true; + } + + /** {@inheritDoc} */ + @Override public int getMaxFieldSize() throws SQLException { + ensureNotClosed(); + + return 0; + } + + /** {@inheritDoc} */ + @Override public void setMaxFieldSize(int max) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Field size limitation is not supported."); + } + + /** {@inheritDoc} */ + @Override public int getMaxRows() throws SQLException { + ensureNotClosed(); + + return maxRows; + } + + /** {@inheritDoc} */ + @Override public void setMaxRows(int maxRows) throws SQLException { + ensureNotClosed(); + + this.maxRows = maxRows; + } + + /** {@inheritDoc} */ + @Override public void setEscapeProcessing(boolean enable) throws SQLException { + ensureNotClosed(); + } + + /** {@inheritDoc} */ + @Override public int getQueryTimeout() throws SQLException { + ensureNotClosed(); + + return timeout / 1000; + } + + /** {@inheritDoc} */ + @Override public void setQueryTimeout(int timeout) throws SQLException { + ensureNotClosed(); + + this.timeout = timeout * 1000; + } + + /** {@inheritDoc} */ + @Override public void cancel() throws SQLException { + ensureNotClosed(); + } + + /** {@inheritDoc} */ + @Override public SQLWarning getWarnings() throws SQLException { + ensureNotClosed(); + + return null; + } + + /** {@inheritDoc} */ + @Override public void clearWarnings() throws SQLException { + ensureNotClosed(); + } + + /** {@inheritDoc} */ + @Override public void setCursorName(String name) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public boolean execute(String sql) throws SQLException { + ensureNotClosed(); + + rs = execute0(sql); + + return rs.isQuery(); + } + + /** {@inheritDoc} */ + @Override public ResultSet getResultSet() throws SQLException { + ensureNotClosed(); + + if (rs == null || !rs.isQuery() || alreadyRead) + return null; + + alreadyRead = true; + + return rs; + } + + /** {@inheritDoc} */ + @Override public int getUpdateCount() throws SQLException { + ensureNotClosed(); + + if (rs == null || rs.isQuery() || alreadyRead) + return -1; + + alreadyRead = true; + + return (int)rs.updatedCount(); + } + + /** {@inheritDoc} */ + @Override public boolean getMoreResults() throws SQLException { + ensureNotClosed(); + + return false; + } + + /** {@inheritDoc} */ + @Override public void setFetchDirection(int direction) throws SQLException { + ensureNotClosed(); + + if (direction != FETCH_FORWARD) + throw new SQLFeatureNotSupportedException("Only forward direction is supported"); + } + + /** {@inheritDoc} */ + @Override public int getFetchDirection() throws SQLException { + ensureNotClosed(); + + return FETCH_FORWARD; + } + + /** {@inheritDoc} */ + @Override public void setFetchSize(int fetchSize) throws SQLException { + ensureNotClosed(); + + if (fetchSize <= 0) + throw new SQLException("Fetch size must be greater than zero."); + + this.pageSize = fetchSize; + } + + /** {@inheritDoc} */ + @Override public int getFetchSize() throws SQLException { + ensureNotClosed(); + + return pageSize; + } + + /** {@inheritDoc} */ + @Override public int getResultSetConcurrency() throws SQLException { + ensureNotClosed(); + + return CONCUR_READ_ONLY; + } + + /** {@inheritDoc} */ + @Override public int getResultSetType() throws SQLException { + ensureNotClosed(); + + return TYPE_FORWARD_ONLY; + } + + /** {@inheritDoc} */ + @Override public void addBatch(String sql) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public void clearBatch() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public int[] executeBatch() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public Connection getConnection() throws SQLException { + ensureNotClosed(); + + return conn; + } + + /** {@inheritDoc} */ + @Override public boolean getMoreResults(int curr) throws SQLException { + ensureNotClosed(); + + if (curr == KEEP_CURRENT_RESULT || curr == CLOSE_ALL_RESULTS) + throw new SQLFeatureNotSupportedException("Multiple open results are not supported."); + + return false; + } + + /** {@inheritDoc} */ + @Override public ResultSet getGeneratedKeys() throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public int executeUpdate(String sql, int[] colIndexes) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public int executeUpdate(String sql, String[] colNames) throws SQLException { + ensureNotClosed(); + + throw new SQLFeatureNotSupportedException("Updates are not supported."); + } + + /** {@inheritDoc} */ + @Override public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + ensureNotClosed(); + + if (autoGeneratedKeys == RETURN_GENERATED_KEYS) + throw new SQLFeatureNotSupportedException("Updates are not supported."); + + return execute(sql); + } + + /** {@inheritDoc} */ + @Override public boolean execute(String sql, int[] colIndexes) throws SQLException { + ensureNotClosed(); + + if (colIndexes != null && colIndexes.length > 0) + throw new SQLFeatureNotSupportedException("Updates are not supported."); + + return execute(sql); + } + + /** {@inheritDoc} */ + @Override public boolean execute(String sql, String[] colNames) throws SQLException { + ensureNotClosed(); + + if (colNames != null && colNames.length > 0) + throw new SQLFeatureNotSupportedException("Updates are not supported."); + + return execute(sql); + } + + /** {@inheritDoc} */ + @Override public int getResultSetHoldability() throws SQLException { + ensureNotClosed(); + + return HOLD_CURSORS_OVER_COMMIT; + } + + /** {@inheritDoc} */ + @Override public boolean isClosed() throws SQLException { + return conn.isClosed() || closed; + } + + /** {@inheritDoc} */ + @Override public void setPoolable(boolean poolable) throws SQLException { + ensureNotClosed(); + + if (poolable) + throw new SQLFeatureNotSupportedException("Pooling is not supported."); + } + + /** {@inheritDoc} */ + @Override public boolean isPoolable() throws SQLException { + ensureNotClosed(); + + return false; + } + + /** {@inheritDoc} */ + @Override public <T> T unwrap(Class<T> iface) throws SQLException { + if (!isWrapperFor(iface)) + throw new SQLException("Statement is not a wrapper for " + iface.getName()); + + return (T)this; + } + + /** {@inheritDoc} */ + @Override public boolean isWrapperFor(Class<?> iface) throws SQLException { + return iface != null && iface.isAssignableFrom(JdbcThinStatement.class); + } + + /** {@inheritDoc} */ + @Override public void closeOnCompletion() throws SQLException { + throw new SQLFeatureNotSupportedException("closeOnCompletion is not supported."); + } + + /** {@inheritDoc} */ + @Override public boolean isCloseOnCompletion() throws SQLException { + ensureNotClosed(); + + return false; + } + + /** + * Sets timeout in milliseconds. + * + * @param timeout Timeout. + */ + void timeout(int timeout) { + this.timeout = timeout; + } + + /** + * @return Connection. + */ + JdbcThinConnection connection() { + return conn; + } + + /** + * Ensures that statement is not closed. + * + * @throws SQLException If statement is closed. + */ + protected void ensureNotClosed() throws SQLException { + if (isClosed()) + throw new SQLException("Statement is closed."); + } +}