/*
 * GRAL: GRAphing Library for Java(R)
 *
 * (C) Copyright 2009-2015 Erich Seifert <dev[at]erichseifert.de>,
 * Michael Seifert <mseifert[at]error-reports.org>
 *
 * This file is part of GRAL.
 *
 * GRAL is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * GRAL is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with GRAL.  If not, see <http://www.gnu.org/licenses/>.
 */
package de.erichseifert.gral;

import java.io.InputStream;
import java.io.Reader;
import java.math.BigDecimal;
import java.net.MalformedURLException;
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.DatabaseMetaData;
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.SQLClientInfoException;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.SQLXML;
import java.sql.Savepoint;
import java.sql.Statement;
import java.sql.Struct;
import java.sql.Time;
import java.sql.Timestamp;
import java.sql.Types;
import java.util.Calendar;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.Executor;

import de.erichseifert.gral.data.DataSource;
import de.erichseifert.gral.data.DummyData;

public class DummyJdbc implements Connection {
	private final DataSource data;
	private boolean closed;

	public DummyJdbc(DataSource data) {
		this.data = data;
		this.closed = false;
	}

	public void clearWarnings() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void close() throws SQLException {
		closed = true;
	}

	public void commit() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Statement createStatement() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Statement createStatement(int resultSetType, int resultSetConcurrency)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Statement createStatement(int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws SQLException {
		throw new UnsupportedOperationException();
	}


	public boolean getAutoCommit() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String getCatalog() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getHoldability() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public DatabaseMetaData getMetaData() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getTransactionIsolation() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Map<String, Class<?>> getTypeMap() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public SQLWarning getWarnings() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isClosed() throws SQLException {
		return closed;
	}

	public boolean isReadOnly() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String nativeSQL(String sql) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public CallableStatement prepareCall(String sql) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public CallableStatement prepareCall(String sql, int resultSetType,
			int resultSetConcurrency) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public CallableStatement prepareCall(String sql, int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public PreparedStatement prepareStatement(String sql) throws SQLException {
		return new DummyPreparedStatement(this, data);
	}

	public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
			throws SQLException {
		return new DummyPreparedStatement(this, data);
	}

	public PreparedStatement prepareStatement(String sql, int[] columnIndexes)
			throws SQLException {
		return new DummyPreparedStatement(this, data);
	}

	public PreparedStatement prepareStatement(String sql, String[] columnNames)
			throws SQLException {
		return new DummyPreparedStatement(this, data);
	}

	public PreparedStatement prepareStatement(String sql, int resultSetType,
			int resultSetConcurrency) throws SQLException {
		return prepareStatement(sql, resultSetType, resultSetConcurrency, ResultSet.HOLD_CURSORS_OVER_COMMIT);
	}

	public PreparedStatement prepareStatement(String sql, int resultSetType,
			int resultSetConcurrency, int resultSetHoldability)
			throws SQLException {
		if (sql.toUpperCase().startsWith("SELECT COUNT(*) FROM ")) {
			return new DummyPreparedStatement(this,
					new DummyData(1, 1, data.getRowCount()));
		}
		return new DummyPreparedStatement(this, data);
	}

	public void releaseSavepoint(Savepoint savepoint) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void rollback() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void rollback(Savepoint savepoint) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setAutoCommit(boolean autoCommit) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setCatalog(String catalog) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setHoldability(int holdability) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setReadOnly(boolean readOnly) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Savepoint setSavepoint() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Savepoint setSavepoint(String name) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setTransactionIsolation(int level) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setTypeMap(Map<String, Class<?>> map) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public <T> T unwrap(Class<T> iface) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Array createArrayOf(String typeName, Object[] elements)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Blob createBlob() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Clob createClob() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public NClob createNClob() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public SQLXML createSQLXML() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Struct createStruct(String typeName, Object[] attributes)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Properties getClientInfo() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public String getClientInfo(String name) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public boolean isValid(int timeout) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setClientInfo(Properties properties)
			throws SQLClientInfoException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setClientInfo(String name, String value)
			throws SQLClientInfoException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public void abort(Executor executor) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public int getNetworkTimeout() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public String getSchema() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public void setNetworkTimeout(Executor executor, int milliseconds) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public void setSchema(String schema) throws SQLException {
		throw new UnsupportedOperationException();
	}
}

class DummyResultSet implements ResultSet {
	private final DataSource data;
	private int rowIndex = -1;
	private boolean closed;

	public DummyResultSet(DataSource data) {
		this.data = data;
	}

	public boolean absolute(int row) throws SQLException {
		rowIndex = row - 1;
		return !isBeforeFirst() && !isAfterLast();
	}

	public void afterLast() throws SQLException {
		rowIndex = data.getRowCount();
	}

	public void beforeFirst() throws SQLException {
		rowIndex = -1;
	}

	public void cancelRowUpdates() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void clearWarnings() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void close() throws SQLException {
		closed = true;
	}

	public void deleteRow() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int findColumn(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean first() throws SQLException {
		rowIndex = 0;
		return !isBeforeFirst() && !isAfterLast();
	}

	public Array getArray(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Array getArray(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public BigDecimal getBigDecimal(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public BigDecimal getBigDecimal(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public BigDecimal getBigDecimal(int columnIndex, int scale)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public BigDecimal getBigDecimal(String columnLabel, int scale)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Blob getBlob(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Blob getBlob(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean getBoolean(int columnIndex) throws SQLException {
		return (Boolean) data.get(columnIndex - 1, rowIndex);
	}

	public boolean getBoolean(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public byte getByte(int columnIndex) throws SQLException {
		return ((Number) data.get(columnIndex - 1, rowIndex)).byteValue();
	}

	public byte getByte(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public byte[] getBytes(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public byte[] getBytes(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Clob getClob(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Clob getClob(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getConcurrency() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String getCursorName() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Date getDate(int columnIndex) throws SQLException {
		return (Date) data.get(columnIndex - 1, rowIndex);
	}

	public Date getDate(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Date getDate(int columnIndex, Calendar cal) throws SQLException {
		// TODO Use calendar
		return (Date) data.get(columnIndex - 1, rowIndex);
	}

	public Date getDate(String columnLabel, Calendar cal) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public double getDouble(int columnIndex) throws SQLException {
		return ((Number) data.get(columnIndex - 1, rowIndex)).doubleValue();
	}

	public double getDouble(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getFetchDirection() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getFetchSize() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public float getFloat(int columnIndex) throws SQLException {
		return ((Number) data.get(columnIndex - 1, rowIndex)).floatValue();
	}

	public float getFloat(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getInt(int columnIndex) throws SQLException {
		return ((Number) data.get(columnIndex - 1, rowIndex)).intValue();
	}

	public int getInt(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public long getLong(int columnIndex) throws SQLException {
		return ((Number) data.get(columnIndex - 1, rowIndex)).longValue();
	}

	public long getLong(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public ResultSetMetaData getMetaData() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Object getObject(int columnIndex) throws SQLException {
		return data.get(columnIndex - 1, rowIndex);
	}

	public Object getObject(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Object getObject(int columnIndex, Map<String, Class<?>> map)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Object getObject(String columnLabel, Map<String, Class<?>> map)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Ref getRef(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Ref getRef(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getRow() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public short getShort(int columnIndex) throws SQLException {
		return ((Number) data.get(columnIndex - 1, rowIndex)).shortValue();
	}

	public short getShort(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Statement getStatement() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String getString(int columnIndex) throws SQLException {
		return String.valueOf(data.get(columnIndex - 1, rowIndex));
	}

	public String getString(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Time getTime(int columnIndex) throws SQLException {
		return (Time) data.get(columnIndex - 1, rowIndex);
	}

	public Time getTime(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Time getTime(int columnIndex, Calendar cal) throws SQLException {
		// TODO Use calendar
		return (Time) data.get(columnIndex - 1, rowIndex);
	}

	public Time getTime(String columnLabel, Calendar cal) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Timestamp getTimestamp(int columnIndex) throws SQLException {
		return (Timestamp) data.get(columnIndex - 1, rowIndex);
	}

	public Timestamp getTimestamp(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Timestamp getTimestamp(int columnIndex, Calendar cal)
			throws SQLException {
		// TODO Use calendar
		return (Timestamp) data.get(columnIndex - 1, rowIndex);
	}

	public Timestamp getTimestamp(String columnLabel, Calendar cal)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getType() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public URL getURL(int columnIndex) throws SQLException {
		Object obj = getObject(columnIndex);
		if (obj == null) {
			return null;
		}
		try {
			return new URL(obj.toString());
		} catch (MalformedURLException e) {
			throw new SQLException(e);
		}
	}

	public URL getURL(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public InputStream getUnicodeStream(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public InputStream getUnicodeStream(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public SQLWarning getWarnings() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void insertRow() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isAfterLast() throws SQLException {
		return rowIndex >= data.getRowCount();
	}

	public boolean isBeforeFirst() throws SQLException {
		return rowIndex < 0;
	}

	public boolean isFirst() throws SQLException {
		return rowIndex == 0;
	}

	public boolean isLast() throws SQLException {
		return rowIndex == data.getRowCount() - 1;
	}

	public boolean last() throws SQLException {
		rowIndex = data.getRowCount() - 1;
		return rowIndex >= 0 && rowIndex < data.getRowCount();
	}

	public void moveToCurrentRow() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void moveToInsertRow() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean next() throws SQLException {
		rowIndex++;
		if (rowIndex > data.getRowCount()) {
			rowIndex = data.getRowCount();
		}
		return !isBeforeFirst() && !isAfterLast();
	}

	public boolean previous() throws SQLException {
		rowIndex--;
		if (rowIndex < 0) {
			rowIndex = -1;
		}
		return !isBeforeFirst() && !isAfterLast();
	}

	public void refreshRow() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean relative(int rows) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean rowDeleted() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean rowInserted() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean rowUpdated() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setFetchDirection(int direction) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setFetchSize(int rows) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateArray(int columnIndex, Array x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateArray(String columnLabel, Array x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBigDecimal(int columnIndex, BigDecimal x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBigDecimal(String columnLabel, BigDecimal x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBlob(int columnIndex, Blob x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBlob(String columnLabel, Blob x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBlob(int columnIndex, InputStream inputStream)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBlob(String columnLabel, InputStream inputStream)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBlob(int columnIndex, InputStream inputStream, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBlob(String columnLabel, InputStream inputStream,
			long length) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBoolean(int columnIndex, boolean x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBoolean(String columnLabel, boolean x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateByte(int columnIndex, byte x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateByte(String columnLabel, byte x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBytes(int columnIndex, byte[] x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateBytes(String columnLabel, byte[] x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateClob(int columnIndex, Clob x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateClob(String columnLabel, Clob x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateClob(int columnIndex, Reader reader) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateClob(String columnLabel, Reader reader)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateClob(int columnIndex, Reader reader, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateClob(String columnLabel, Reader reader, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateDate(int columnIndex, Date x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateDate(String columnLabel, Date x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateDouble(int columnIndex, double x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateDouble(String columnLabel, double x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateFloat(int columnIndex, float x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateFloat(String columnLabel, float x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateInt(int columnIndex, int x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateInt(String columnLabel, int x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateLong(int columnIndex, long x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateLong(String columnLabel, long x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateNull(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateNull(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateObject(int columnIndex, Object x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateObject(String columnLabel, Object x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateObject(int columnIndex, Object x, int scaleOrLength)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateObject(String columnLabel, Object x, int scaleOrLength)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateRef(int columnIndex, Ref x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateRef(String columnLabel, Ref x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateRow() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateShort(int columnIndex, short x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateShort(String columnLabel, short x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateString(int columnIndex, String x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateString(String columnLabel, String x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateTime(int columnIndex, Time x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateTime(String columnLabel, Time x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateTimestamp(int columnIndex, Timestamp x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void updateTimestamp(String columnLabel, Timestamp x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean wasNull() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public <T> T unwrap(Class<T> iface) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public InputStream getAsciiStream(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public InputStream getAsciiStream(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public InputStream getBinaryStream(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public InputStream getBinaryStream(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Reader getCharacterStream(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Reader getCharacterStream(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public int getHoldability() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Reader getNCharacterStream(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public Reader getNCharacterStream(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public NClob getNClob(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public NClob getNClob(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public String getNString(int columnIndex) throws SQLException {
		return getString(columnIndex);
	}

	// Java 1.6
	public String getNString(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public RowId getRowId(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public RowId getRowId(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public SQLXML getSQLXML(int columnIndex) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public SQLXML getSQLXML(String columnLabel) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public boolean isClosed() throws SQLException {
		return closed;
	}

	// Java 1.6
	public void updateAsciiStream(int columnIndex, InputStream x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateAsciiStream(String columnLabel, InputStream x)
			throws SQLException {
	}

	// Java 1.6
	public void updateAsciiStream(int columnIndex, InputStream x, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateAsciiStream(String columnLabel, InputStream x, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateAsciiStream(int columnIndex, InputStream x, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateAsciiStream(String columnLabel, InputStream x, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateBinaryStream(int columnIndex, InputStream x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateBinaryStream(String columnLabel, InputStream x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateBinaryStream(int columnIndex, InputStream x, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateBinaryStream(String columnLabel, InputStream x, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateBinaryStream(int columnIndex, InputStream x, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateBinaryStream(String columnLabel, InputStream x,
			long length) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateCharacterStream(int columnIndex, Reader x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateCharacterStream(String columnLabel, Reader reader)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateCharacterStream(int columnIndex, Reader x, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateCharacterStream(String columnLabel, Reader reader,
			int length) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateCharacterStream(int columnIndex, Reader x, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateCharacterStream(String columnLabel, Reader reader,
			long length) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNCharacterStream(int columnIndex, Reader x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNCharacterStream(String columnLabel, Reader reader)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNCharacterStream(int columnIndex, Reader x, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNCharacterStream(String columnLabel, Reader reader,
			long length) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNClob(int columnIndex, NClob nClob) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNClob(String columnLabel, NClob nClob)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNClob(int columnIndex, Reader reader) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNClob(String columnLabel, Reader reader)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNClob(int columnIndex, Reader reader, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNClob(String columnLabel, Reader reader, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNString(int columnIndex, String nString)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateNString(String columnLabel, String nString)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateRowId(int columnIndex, RowId x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateRowId(String columnLabel, RowId x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateSQLXML(int columnIndex, SQLXML xmlObject)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void updateSQLXML(String columnLabel, SQLXML xmlObject)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public <T> T getObject(int columnIndex, Class<T> type)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public <T> T getObject(String columnLabel, Class<T> type)
			throws SQLException {
		throw new UnsupportedOperationException();
	}
}

class DummyResultSetMetaData implements ResultSetMetaData {
	private final DataSource data;

	public DummyResultSetMetaData(DataSource data) {
		this.data = data;
	}

	public String getCatalogName(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String getColumnClassName(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getColumnCount() throws SQLException {
		return data.getColumnCount();
	}

	public int getColumnDisplaySize(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String getColumnLabel(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String getColumnName(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getColumnType(int column) throws SQLException {
		return getJdbcColumnType(column);
	}

	private int getJdbcColumnType(int column) {
		Class<? extends Comparable<?>> javaType = data.getColumnTypes()[column - 1];
		if (Byte.class.equals(javaType)) {
			return Types.TINYINT;
		} else if (Short.class.equals(javaType)) {
			return Types.SMALLINT;
		} else if (Integer.class.equals(javaType)) {
			return Types.INTEGER;
		} else if (Long.class.equals(javaType)) {
			return Types.BIGINT;
		} else if (Byte.class.equals(javaType)) {
			return Types.TINYINT;
		} else if (Float.class.equals(javaType)) {
			return Types.REAL;
		} else if (Double.class.equals(javaType)) {
			return Types.FLOAT;
		} else if (Date.class.equals(javaType)) {
			return Types.DATE;
		} else if (Time.class.equals(javaType)) {
			return Types.TIME;
		} else if (Timestamp.class.equals(javaType)) {
			return Types.TIMESTAMP;
		} else if (String.class.equals(javaType)) {
			return Types.VARCHAR;
		}

		throw new IllegalArgumentException(String.format("Unkown java data type: %s", javaType.getName()));
	}

	public String getColumnTypeName(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getPrecision(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getScale(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String getSchemaName(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public String getTableName(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isAutoIncrement(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isCaseSensitive(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isCurrency(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isDefinitelyWritable(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int isNullable(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isReadOnly(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isSearchable(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isSigned(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isWritable(int column) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public <T> T unwrap(Class<T> iface) throws SQLException {
		throw new UnsupportedOperationException();
	}
}

class DummyPreparedStatement implements PreparedStatement {
	private final Connection connection;
	private final DataSource data;

	public DummyPreparedStatement(Connection connection, DataSource data) {
		this.connection = connection;
		this.data = data;
	}

	public void addBatch() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void clearParameters() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean execute() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public ResultSet executeQuery() throws SQLException {
		return new DummyResultSet(data);
	}

	public int executeUpdate() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public ResultSetMetaData getMetaData() throws SQLException {
		return new DummyResultSetMetaData(data);
	}

	public ParameterMetaData getParameterMetaData() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setArray(int parameterIndex, Array x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setAsciiStream(int parameterIndex, InputStream x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setAsciiStream(int parameterIndex, InputStream x, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setAsciiStream(int parameterIndex, InputStream x, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setBigDecimal(int parameterIndex, BigDecimal x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setBinaryStream(int parameterIndex, InputStream x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setBinaryStream(int parameterIndex, InputStream x, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setBinaryStream(int parameterIndex, InputStream x, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setBlob(int parameterIndex, Blob x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setBlob(int parameterIndex, InputStream inputStream)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setBlob(int parameterIndex, InputStream inputStream, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setBoolean(int parameterIndex, boolean x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setByte(int parameterIndex, byte x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setBytes(int parameterIndex, byte[] x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setCharacterStream(int parameterIndex, Reader reader)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setCharacterStream(int parameterIndex, Reader reader, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setCharacterStream(int parameterIndex, Reader reader,
			long length) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setClob(int parameterIndex, Clob x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setClob(int parameterIndex, Reader reader) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setClob(int parameterIndex, Reader reader, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setDate(int parameterIndex, Date x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setDate(int parameterIndex, Date x, Calendar cal)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setDouble(int parameterIndex, double x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setFloat(int parameterIndex, float x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setInt(int parameterIndex, int x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setLong(int parameterIndex, long x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setNCharacterStream(int parameterIndex, Reader value)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setNCharacterStream(int parameterIndex, Reader value,
			long length) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setNClob(int parameterIndex, NClob value) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setNClob(int parameterIndex, Reader reader) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setNClob(int parameterIndex, Reader reader, long length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setNString(int parameterIndex, String value)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setNull(int parameterIndex, int sqlType) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setNull(int parameterIndex, int sqlType, String typeName)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setObject(int parameterIndex, Object x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setObject(int parameterIndex, Object x, int targetSqlType)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setObject(int parameterIndex, Object x, int targetSqlType,
			int scaleOrLength) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setRef(int parameterIndex, Ref x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setRowId(int parameterIndex, RowId x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.6
	public void setSQLXML(int parameterIndex, SQLXML xmlObject)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setShort(int parameterIndex, short x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setString(int parameterIndex, String x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setTime(int parameterIndex, Time x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setTime(int parameterIndex, Time x, Calendar cal)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setTimestamp(int parameterIndex, Timestamp x)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setURL(int parameterIndex, URL x) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setUnicodeStream(int parameterIndex, InputStream x, int length)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void addBatch(String sql) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void cancel() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void clearBatch() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void clearWarnings() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void close() throws SQLException {
		connection.close();
	}

	public boolean execute(String sql) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean execute(String sql, int autoGeneratedKeys)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean execute(String sql, int[] columnIndexes) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean execute(String sql, String[] columnNames)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int[] executeBatch() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public ResultSet executeQuery(String sql) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int executeUpdate(String sql) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int executeUpdate(String sql, int autoGeneratedKeys)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int executeUpdate(String sql, int[] columnIndexes)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int executeUpdate(String sql, String[] columnNames)
			throws SQLException {
		throw new UnsupportedOperationException();
	}

	public Connection getConnection() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getFetchDirection() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getFetchSize() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public ResultSet getGeneratedKeys() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getMaxFieldSize() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getMaxRows() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean getMoreResults() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean getMoreResults(int current) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getQueryTimeout() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public ResultSet getResultSet() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getResultSetConcurrency() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getResultSetHoldability() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getResultSetType() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public int getUpdateCount() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public SQLWarning getWarnings() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isClosed() throws SQLException {
		return connection.isClosed();
	}

	public boolean isPoolable() throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setCursorName(String name) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setEscapeProcessing(boolean enable) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setFetchDirection(int direction) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setFetchSize(int rows) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setMaxFieldSize(int max) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setMaxRows(int max) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setPoolable(boolean poolable) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public void setQueryTimeout(int seconds) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public boolean isWrapperFor(Class<?> iface) throws SQLException {
		throw new UnsupportedOperationException();
	}

	public <T> T unwrap(Class<T> iface) throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public void closeOnCompletion() throws SQLException {
		throw new UnsupportedOperationException();
	}

	// Java 1.7
	public boolean isCloseOnCompletion() throws SQLException {
		throw new UnsupportedOperationException();
	}
}