package net.sourceforge.mayfly.jdbc; import net.sourceforge.mayfly.MayflyConnection; import net.sourceforge.mayfly.MayflyException; import net.sourceforge.mayfly.UnimplementedException; import net.sourceforge.mayfly.datastore.TimestampCell; import net.sourceforge.mayfly.evaluation.command.Command; import net.sourceforge.mayfly.parser.Lexer; import net.sourceforge.mayfly.parser.Parser; import net.sourceforge.mayfly.parser.Substitutor; import net.sourceforge.mayfly.util.ImmutableByteArray; import org.joda.time.LocalDate; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.io.StringWriter; import java.math.BigDecimal; import java.net.URL; import java.sql.Array; import java.sql.Blob; import java.sql.Clob; import java.sql.Connection; 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.SQLWarning; import java.sql.SQLXML; import java.sql.Time; import java.sql.Timestamp; import java.util.BitSet; import java.util.Calendar; import java.util.List; import java.util.Vector; public class JdbcPreparedStatement implements PreparedStatement { private final MayflyConnection mayflyConnection; private final String sql; private Vector parameters; private final int parameterCount; private BitSet parameterSpecified; JdbcPreparedStatement(String sql, MayflyConnection mayflyConnection) throws SQLException { this.mayflyConnection = mayflyConnection; try { this.sql = sql; this.parameters = new Vector(); List tokens = new Lexer(sql).tokens(); parameterCount = Substitutor.parameterCount(tokens); new Parser(tokens, true).parse(); parameters.setSize(parameterCount); parameterSpecified = new BitSet(parameterCount); } catch (MayflyException e) { throw e.asSqlException(); } } public ResultSet executeQuery() throws SQLException { try { Command select = fromTokens(); return mayflyConnection.query(select); } catch (MayflyException e) { throw e.asSqlException(); } } public int executeUpdate() throws SQLException { try { Command command = fromTokens(); return mayflyConnection.executeUpdate(command); } catch (MayflyException e) { throw e.asSqlException(); } } private Command fromTokens() throws SQLException { return Command.fromTokens(substitutedTokens(), mayflyConnection.options()); } private List substitutedTokens() throws SQLException { // This didn't work for me. Perhaps a bug in which libgcj // was returning an answer past the length of the bitset, but // I didn't investigate enough to be sure. // int firstUnspecifiedParameter = parameterSpecified.nextClearBit(0); // if (firstUnspecifiedParameter != -1) { // int oneBased = firstUnspecifiedParameter + 1; // throw new MayflyException("Parameter " + oneBased + " missing"); // } for (int i = 0; i < parameterCount; ++i) { if (!parameterSpecified.get(i)) { int oneBased = i + 1; throw new MayflyException("Parameter " + oneBased + " missing"); } } return Substitutor.substitute(new Lexer(sql).tokens(), parameters); } public void setNull(int oneBased, int sqlType) throws SQLException { setParameter(oneBased, null); } public void setBoolean(int parameterIndex, boolean value) throws SQLException { throw new UnimplementedException(); } public void setByte(int oneBased, byte value) throws SQLException { setParameter(oneBased, new Long(value)); } public void setShort(int oneBased, short value) throws SQLException { setParameter(oneBased, new Long(value)); } public void setInt(int oneBased, int value) throws SQLException { setParameter(oneBased, new Long(value)); } public void setLong(int oneBased, long value) throws SQLException { setParameter(oneBased, new Long(value)); } private void setParameter(int oneBased, Object value) throws SQLException { int zeroBased = oneBased - 1; if (zeroBased < 0) { throw new SQLException("Parameter index " + oneBased + " is out of bounds"); } if (zeroBased >= parameterCount) { throw new SQLException("Parameter index " + oneBased + " is out of bounds"); } parameters.set(zeroBased, value); parameterSpecified.set(zeroBased); } public void setFloat(int parameterIndex, float value) throws SQLException { throw new UnimplementedException(); } public void setDouble(int parameterIndex, double value) throws SQLException { /* What's the difference between the BigDecimal constructor that takes a double and the one that takes a string? */ setParameter(parameterIndex, new BigDecimal(String.valueOf(value))); } public void setBigDecimal(int parameterIndex, BigDecimal value) throws SQLException { setParameter(parameterIndex, value); } public void setString(int parameterIndex, String value) throws SQLException { setParameter(parameterIndex, value); } public void setBytes(int parameterIndex, byte[] value) throws SQLException { setParameter(parameterIndex, new ImmutableByteArray(value)); } public void setDate(int parameterIndex, java.sql.Date value) throws SQLException { long time = value.getTime(); String string = new LocalDate(time).toString(); setParameter(parameterIndex, string); } public void setTime(int parameterIndex, Time value) throws SQLException { throw new UnimplementedException(); } public void setTimestamp(int parameterIndex, Timestamp value) throws SQLException { long time = value.getTime(); String string = TimestampCell.FORMATTER.print(time); setParameter(parameterIndex, string); } public void setAsciiStream(int parameterIndex, InputStream value, int length) throws SQLException { throw new UnimplementedException("We recommend setCharacterStream instead"); } /** * @deprecated */ public void setUnicodeStream(int parameterIndex, InputStream value, int length) throws SQLException { throw new UnimplementedException("We recommend setCharacterStream instead"); } public void setBinaryStream(int parameterIndex, InputStream stream, int length) throws SQLException { try { try { setParameter(parameterIndex, new ImmutableByteArray(stream)); } finally { stream.close(); } } catch (IOException e) { throw (SQLException) new SQLException("Cannot read parameter") .initCause(e); } } public void clearParameters() throws SQLException { throw new UnimplementedException(); } public void setObject(int parameterIndex, Object value, int targetSqlType, int scale) throws SQLException { throw new UnimplementedException(); } public void setObject(int parameterIndex, Object value, int targetSqlType) throws SQLException { setParameter(parameterIndex, value); } public void setObject(int parameterIndex, Object value) throws SQLException { setParameter(parameterIndex, value); } public boolean execute() throws SQLException { throw new UnimplementedException(); } public void addBatch() throws SQLException { throw new UnimplementedException(); } public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { try { setString(parameterIndex, readString(reader)); } catch (IOException e) { throw (SQLException) new SQLException("Cannot read parameter") .initCause(e); } } private String readString(Reader reader) throws IOException { StringWriter writer = new StringWriter(); char[] buffer = new char[8192]; int n = 0; while (-1 != (n = reader.read(buffer))) { writer.write(buffer, 0, n); } return writer.toString(); } public void setRef(int i, Ref value) throws SQLException { throw new UnimplementedException(); } public void setBlob(int i, Blob value) throws SQLException { throw new UnimplementedException(); } public void setClob(int i, Clob value) throws SQLException { throw new UnimplementedException(); } public void setArray(int i, Array value) throws SQLException { throw new UnimplementedException(); } public ResultSetMetaData getMetaData() throws SQLException { throw new UnimplementedException(); } public void setDate(int parameterIndex, java.sql.Date value, Calendar cal) throws SQLException { throw new UnimplementedException(); } public void setTime(int parameterIndex, Time value, Calendar cal) throws SQLException { throw new UnimplementedException(); } public void setTimestamp(int parameterIndex, Timestamp value, Calendar cal) throws SQLException { throw new UnimplementedException(); } public void setNull(int oneBased, int sqlType, String typeName) throws SQLException { setNull(oneBased, sqlType); } public void setURL(int parameterIndex, URL value) throws SQLException { throw new UnimplementedException(); } public ParameterMetaData getParameterMetaData() throws SQLException { throw new UnimplementedException(); } public ResultSet executeQuery(String sql) throws SQLException { throw new UnimplementedException(); } public int executeUpdate(String sql) throws SQLException { throw new UnimplementedException(); } public void close() throws SQLException { } public int getMaxFieldSize() throws SQLException { throw new UnimplementedException(); } public void setMaxFieldSize(int max) throws SQLException { throw new UnimplementedException(); } public int getMaxRows() throws SQLException { return 0; } public void setMaxRows(int max) throws SQLException { throw new UnimplementedException(); } public void setEscapeProcessing(boolean enable) throws SQLException { throw new UnimplementedException(); } public int getQueryTimeout() throws SQLException { return 0; } public void setQueryTimeout(int seconds) throws SQLException { throw new UnimplementedException(); } public void cancel() throws SQLException { throw new UnimplementedException(); } public SQLWarning getWarnings() throws SQLException { throw new UnimplementedException(); } public void clearWarnings() throws SQLException { throw new UnimplementedException(); } public void setCursorName(String name) throws SQLException { throw new UnimplementedException(); } public boolean execute(String sql) throws SQLException { throw new UnimplementedException(); } public ResultSet getResultSet() throws SQLException { throw new UnimplementedException(); } public int getUpdateCount() throws SQLException { throw new UnimplementedException(); } public boolean getMoreResults() throws SQLException { throw new UnimplementedException(); } public void setFetchDirection(int direction) throws SQLException { throw new UnimplementedException(); } public int getFetchDirection() throws SQLException { throw new UnimplementedException(); } public void setFetchSize(int rows) throws SQLException { throw new UnimplementedException(); } public int getFetchSize() throws SQLException { throw new UnimplementedException(); } public int getResultSetConcurrency() throws SQLException { throw new UnimplementedException(); } public int getResultSetType() throws SQLException { throw new UnimplementedException(); } public void addBatch(String sql) throws SQLException { throw new UnimplementedException(); } public void clearBatch() throws SQLException { throw new UnimplementedException(); } public int[] executeBatch() throws SQLException { throw new UnimplementedException(); } public Connection getConnection() throws SQLException { throw new UnimplementedException(); } public boolean getMoreResults(int current) throws SQLException { throw new UnimplementedException(); } public ResultSet getGeneratedKeys() throws SQLException { throw new UnimplementedException(); } public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { throw new UnimplementedException(); } public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { throw new UnimplementedException(); } public int executeUpdate(String sql, String[] columnNames) throws SQLException { throw new UnimplementedException(); } public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { throw new UnimplementedException(); } public boolean execute(String sql, int[] columnIndexes) throws SQLException { throw new UnimplementedException(); } public boolean execute(String sql, String[] columnNames) throws SQLException { throw new UnimplementedException(); } public int getResultSetHoldability() throws SQLException { throw new UnimplementedException(); } public void setAsciiStream(int arg0, InputStream arg1) throws SQLException { throw new UnimplementedException(); } public void setAsciiStream(int arg0, InputStream arg1, long arg2) throws SQLException { throw new UnimplementedException(); } public void setBinaryStream(int arg0, InputStream arg1) throws SQLException { throw new UnimplementedException(); } public void setBinaryStream(int arg0, InputStream arg1, long arg2) throws SQLException { throw new UnimplementedException(); } public void setBlob(int arg0, InputStream arg1) throws SQLException { throw new UnimplementedException(); } public void setBlob(int arg0, InputStream arg1, long arg2) throws SQLException { throw new UnimplementedException(); } public void setCharacterStream(int arg0, Reader arg1) throws SQLException { throw new UnimplementedException(); } public void setCharacterStream(int arg0, Reader arg1, long arg2) throws SQLException { throw new UnimplementedException(); } public void setClob(int arg0, Reader arg1) throws SQLException { throw new UnimplementedException(); } public void setClob(int arg0, Reader arg1, long arg2) throws SQLException { throw new UnimplementedException(); } public void setNCharacterStream(int arg0, Reader arg1) throws SQLException { throw new UnimplementedException(); } public void setNCharacterStream(int arg0, Reader arg1, long arg2) throws SQLException { throw new UnimplementedException(); } public void setNClob(int arg0, NClob arg1) throws SQLException { throw new UnimplementedException(); } public void setNClob(int arg0, Reader arg1) throws SQLException { throw new UnimplementedException(); } public void setNClob(int arg0, Reader arg1, long arg2) throws SQLException { throw new UnimplementedException(); } public void setNString(int arg0, String arg1) throws SQLException { throw new UnimplementedException(); } public void setRowId(int arg0, RowId arg1) throws SQLException { throw new UnimplementedException(); } public void setSQLXML(int arg0, SQLXML arg1) throws SQLException { throw new UnimplementedException(); } public boolean isClosed() throws SQLException { throw new UnimplementedException(); } public boolean isPoolable() throws SQLException { throw new UnimplementedException(); } public void setPoolable(boolean arg0) throws SQLException { throw new UnimplementedException(); } public boolean isWrapperFor(Class<?> iface) throws SQLException { throw new UnimplementedException(); } public <T> T unwrap(Class<T> iface) throws SQLException { throw new UnimplementedException(); } }