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