1 package com.firstworks.sql; 2 3 import java.sql.*; 4 import java.util.List; 5 import java.util.ArrayList; 6 7 import com.firstworks.sqlrelay.*; 8 9 public class SQLRelayStatement implements Statement { 10 11 private Connection connection; 12 private SQLRConnection sqlrcon; 13 protected SQLRCursor sqlrcur; 14 private List<String> batch; 15 private boolean closeoncompletion; 16 protected SQLRelayResultSet resultset; 17 private int fetchdirection; 18 private int maxfieldsize; 19 private int maxrows; 20 private boolean poolable; 21 protected int updatecount; 22 private boolean escapeprocessing; 23 SQLRelayStatement()24 public SQLRelayStatement() { 25 reset(); 26 } 27 reset()28 private void reset() { 29 connection=null; 30 sqlrcon=null; 31 sqlrcur=null; 32 batch=new ArrayList<String>(); 33 closeoncompletion=false; 34 resultset=null; 35 fetchdirection=ResultSet.FETCH_FORWARD; 36 maxfieldsize=0; 37 maxrows=0; 38 poolable=false; 39 updatecount=-1; 40 escapeprocessing=true; 41 } 42 setConnection(Connection connection)43 public void setConnection(Connection connection) { 44 this.connection=connection; 45 } 46 setSQLRConnection(SQLRConnection sqlrcon)47 public void setSQLRConnection(SQLRConnection sqlrcon) { 48 this.sqlrcon=sqlrcon; 49 } 50 setSQLRCursor(SQLRCursor sqlrcur)51 public void setSQLRCursor(SQLRCursor sqlrcur) { 52 this.sqlrcur=sqlrcur; 53 } 54 addBatch(String sql)55 public void addBatch(String sql) throws SQLException { 56 throwExceptionIfClosed(); 57 batch.add(sql); 58 } 59 cancel()60 public void cancel() throws SQLException { 61 throwExceptionIfClosed(); 62 throwNotSupportedException(); 63 // FIXME: maybe we can support this somehow? 64 } 65 clearBatch()66 public void clearBatch() throws SQLException { 67 throwExceptionIfClosed(); 68 batch.clear(); 69 } 70 clearWarnings()71 public void clearWarnings() throws SQLException { 72 throwExceptionIfClosed(); 73 } 74 close()75 public void close() throws SQLException { 76 if (resultset!=null) { 77 resultset.close(); 78 } 79 reset(); 80 } 81 closeOnCompletion()82 public void closeOnCompletion() throws SQLException { 83 throwExceptionIfClosed(); 84 closeoncompletion=true; 85 } 86 execute(String sql)87 public boolean execute(String sql) throws SQLException { 88 throwExceptionIfClosed(); 89 // FIXME: handle timeout 90 resultset=null; 91 updatecount=-1; 92 boolean result=sqlrcur.sendQuery(sql); 93 if (result) { 94 if (sqlrcur.affectedRows()==0 && sqlrcur.colCount()>0) { 95 resultset=new SQLRelayResultSet(); 96 resultset.setStatement(this); 97 resultset.setSQLRCursor(sqlrcur); 98 } else { 99 sqlrcur.closeResultSet(); 100 result=false; 101 } 102 } else { 103 throwErrorMessageException(); 104 } 105 return result; 106 } 107 execute(String sql, int autoGeneratedKeys)108 public boolean execute(String sql, int autoGeneratedKeys) 109 throws SQLException { 110 throwExceptionIfClosed(); 111 throwNotSupportedException(); 112 return false; 113 } 114 execute(String sql, int[] columnIndexes)115 public boolean execute(String sql, int[] columnIndexes) 116 throws SQLException { 117 throwExceptionIfClosed(); 118 throwNotSupportedException(); 119 return false; 120 } 121 execute(String sql, String[] columnNames)122 public boolean execute(String sql, String[] columnNames) 123 throws SQLException { 124 throwExceptionIfClosed(); 125 throwNotSupportedException(); 126 return false; 127 } 128 executeBatch()129 public int[] executeBatch() throws SQLException { 130 throwExceptionIfClosed(); 131 // FIXME: handle timeout 132 int[] results=new int[batch.size()]; 133 int count=0; 134 for (String sql: batch) { 135 results[count++]=executeUpdate(sql); 136 } 137 return results; 138 } 139 executeQuery(String sql)140 public ResultSet executeQuery(String sql) throws SQLException { 141 throwExceptionIfClosed(); 142 // FIXME: handle timeout 143 resultset=null; 144 updatecount=-1; 145 if (sqlrcur.sendQuery(sql)) { 146 resultset=new SQLRelayResultSet(); 147 resultset.setStatement(this); 148 resultset.setSQLRCursor(sqlrcur); 149 } else { 150 throw new SQLException(sqlrcur.errorMessage()); 151 } 152 return resultset; 153 } 154 executeUpdate(String sql)155 public int executeUpdate(String sql) throws SQLException { 156 throwExceptionIfClosed(); 157 // FIXME: handle timeout 158 resultset=null; 159 updatecount=-1; 160 if (sqlrcur.sendQuery(sql)) { 161 updatecount=(int)sqlrcur.affectedRows(); 162 } else { 163 throwErrorMessageException(); 164 } 165 return updatecount; 166 } 167 executeUpdate(String sql, int autoGeneratedKeys)168 public int executeUpdate(String sql, int autoGeneratedKeys) 169 throws SQLException { 170 throwExceptionIfClosed(); 171 throwNotSupportedException(); 172 return 0; 173 } 174 executeUpdate(String sql, int[] columnIndexes)175 public int executeUpdate(String sql, int[] columnIndexes) 176 throws SQLException { 177 throwExceptionIfClosed(); 178 throwNotSupportedException(); 179 return 0; 180 } 181 executeUpdate(String sql, String[] columnNames)182 public int executeUpdate(String sql, String[] columnNames) 183 throws SQLException { 184 throwExceptionIfClosed(); 185 throwNotSupportedException(); 186 return 0; 187 } 188 getConnection()189 public Connection getConnection() throws SQLException { 190 throwExceptionIfClosed(); 191 return connection; 192 } 193 getFetchDirection()194 public int getFetchDirection() throws SQLException { 195 throwExceptionIfClosed(); 196 return fetchdirection; 197 } 198 getFetchSize()199 public int getFetchSize() throws SQLException { 200 throwExceptionIfClosed(); 201 return (int)sqlrcur.getResultSetBufferSize(); 202 } 203 getGeneratedKeys()204 public ResultSet getGeneratedKeys() throws SQLException { 205 throwExceptionIfClosed(); 206 throwNotSupportedException(); 207 // FIXME: maybe we can support this somehow? 208 return null; 209 } 210 getMaxFieldSize()211 public int getMaxFieldSize() throws SQLException { 212 throwExceptionIfClosed(); 213 return maxfieldsize; 214 } 215 getMaxRows()216 public int getMaxRows() throws SQLException { 217 throwExceptionIfClosed(); 218 return maxrows; 219 } 220 getMoreResults()221 public boolean getMoreResults() throws SQLException { 222 return getMoreResults(Statement.CLOSE_CURRENT_RESULT); 223 } 224 getMoreResults(int current)225 public boolean getMoreResults(int current) throws SQLException { 226 throwExceptionIfClosed(); 227 switch (current) { 228 case Statement.CLOSE_CURRENT_RESULT: 229 if (resultset!=null) { 230 resultset.close(); 231 resultset=null; 232 updatecount=-1; 233 } 234 // FIXME: we could support this... 235 return false; 236 case Statement.KEEP_CURRENT_RESULT: 237 throwNotSupportedException(); 238 return false; 239 case Statement.CLOSE_ALL_RESULTS: 240 throwNotSupportedException(); 241 return false; 242 default: 243 throwNotSupportedException(); 244 return false; 245 } 246 } 247 getQueryTimeout()248 public int getQueryTimeout() throws SQLException { 249 throwExceptionIfClosed(); 250 throwNotSupportedException(); 251 // FIXME: this can be supported 252 //return sqlrcon.getResponseTimeout(); 253 return 0; 254 } 255 getResultSet()256 public ResultSet getResultSet() throws SQLException { 257 throwExceptionIfClosed(); 258 return resultset; 259 } 260 getResultSetConcurrency()261 public int getResultSetConcurrency() throws SQLException { 262 throwExceptionIfClosed(); 263 // FIXME: is this correct? 264 return ResultSet.CONCUR_READ_ONLY; 265 } 266 getResultSetHoldability()267 public int getResultSetHoldability() throws SQLException { 268 throwExceptionIfClosed(); 269 // FIXME: is this correct? 270 return ResultSet.CLOSE_CURSORS_AT_COMMIT; 271 } 272 getResultSetType()273 public int getResultSetType() throws SQLException { 274 throwExceptionIfClosed(); 275 return ResultSet.TYPE_FORWARD_ONLY; 276 } 277 getUpdateCount()278 public int getUpdateCount() throws SQLException { 279 throwExceptionIfClosed(); 280 return updatecount; 281 } 282 getWarnings()283 public SQLWarning getWarnings() throws SQLException { 284 throwExceptionIfClosed(); 285 return null; 286 } 287 isClosed()288 public boolean isClosed() throws SQLException { 289 return sqlrcur==null; 290 } 291 isCloseOnCompletion()292 public boolean isCloseOnCompletion() throws SQLException { 293 throwExceptionIfClosed(); 294 return false; 295 } 296 isPoolable()297 public boolean isPoolable() throws SQLException { 298 throwExceptionIfClosed(); 299 return poolable; 300 } 301 setCursorName(String name)302 public void setCursorName(String name) throws SQLException { 303 throwExceptionIfClosed(); 304 throwNotSupportedException(); 305 } 306 setEscapeProcessing(boolean enable)307 public void setEscapeProcessing(boolean enable) 308 throws SQLException { 309 throwExceptionIfClosed(); 310 escapeprocessing=enable; 311 // FIXME: do something with this... 312 } 313 setFetchDirection(int direction)314 public void setFetchDirection(int direction) throws SQLException { 315 throwExceptionIfClosed(); 316 fetchdirection=direction; 317 } 318 setFetchSize(int rows)319 public void setFetchSize(int rows) throws SQLException { 320 throwExceptionIfClosed(); 321 sqlrcur.setResultSetBufferSize(rows); 322 } 323 setMaxFieldSize(int max)324 public void setMaxFieldSize(int max) throws SQLException { 325 throwExceptionIfClosed(); 326 maxfieldsize=max; 327 } 328 setMaxRows(int max)329 public void setMaxRows(int max) throws SQLException { 330 throwExceptionIfClosed(); 331 maxrows=max; 332 } 333 setPoolable(boolean poolable)334 public void setPoolable(boolean poolable) throws SQLException { 335 throwExceptionIfClosed(); 336 this.poolable=poolable; 337 } 338 setQueryTimeout(int seconds)339 public void setQueryTimeout(int seconds) throws SQLException { 340 throwExceptionIfClosed(); 341 // FIXME: hmm... this is at the connection level 342 sqlrcon.setResponseTimeout(seconds,0); 343 } 344 isWrapperFor(Class<?> iface)345 public boolean isWrapperFor(Class<?> iface) throws SQLException { 346 // FIXME: implement this for SQLRCursor and SQLRConnection 347 return false; 348 } 349 unwrap(Class<T> iface)350 public <T> T unwrap(Class<T> iface) throws SQLException { 351 // FIXME: implement this for SQLRCursor and SQLRConnection 352 return null; 353 } 354 throwExceptionIfClosed()355 protected void throwExceptionIfClosed() throws SQLException { 356 if (sqlrcur==null) { 357 throw new SQLException("FIXME: Statement is closed"); 358 } 359 } 360 throwErrorMessageException()361 protected void throwErrorMessageException() throws SQLException { 362 throw new SQLException(sqlrcur.errorMessage()); 363 } 364 throwNotSupportedException()365 protected void throwNotSupportedException() throws SQLException { 366 throw new SQLFeatureNotSupportedException(); 367 } 368 }; 369