001    package com.mockrunner.mock.jdbc;
002    
003    import java.sql.BatchUpdateException;
004    import java.sql.Connection;
005    import java.sql.ResultSet;
006    import java.sql.SQLException;
007    import java.sql.SQLWarning;
008    import java.sql.Statement;
009    import java.util.ArrayList;
010    import java.util.List;
011    
012    import com.mockrunner.base.NestedApplicationException;
013    import com.mockrunner.jdbc.AbstractResultSetHandler;
014    import com.mockrunner.jdbc.SQLUtil;
015    
016    /**
017     * Mock implementation of <code>Statement</code>.
018     */
019    public class MockStatement implements Statement
020    {
021        private AbstractResultSetHandler resultSetHandler;
022        private ResultSet nextResultSet = null;
023        private int nextUpdateCount = -1;
024        private List batches = new ArrayList();
025        private String cursorName = "";
026        private int querySeconds = 0;
027        private int maxRows = 0;
028        private int maxFieldSize = 0;
029        private int fetchDirection = ResultSet.FETCH_FORWARD;
030        private int fetchSize = 0;
031        private int resultSetType = ResultSet.TYPE_FORWARD_ONLY;
032        private int resultSetConcurrency = ResultSet.CONCUR_READ_ONLY;
033        private int resultSetHoldability = ResultSet.HOLD_CURSORS_OVER_COMMIT;
034        private boolean closed = false;
035        private Connection connection;
036        
037        public MockStatement(Connection connection)
038        {
039            this.connection = connection;
040            this.resultSetType = ResultSet.TYPE_FORWARD_ONLY;
041            this.resultSetConcurrency = ResultSet.CONCUR_READ_ONLY;
042            try
043            {
044                this.resultSetHoldability = connection.getMetaData().getResultSetHoldability();
045            }
046            catch(SQLException exc)
047            {
048                throw new NestedApplicationException(exc);
049            }
050        }
051        
052        public MockStatement(Connection connection, int resultSetType, int resultSetConcurrency)
053        {
054            this.connection = connection;
055            this.resultSetType = resultSetType;
056            this.resultSetConcurrency = resultSetConcurrency;
057            try
058            {
059                this.resultSetHoldability = connection.getMetaData().getResultSetHoldability();
060            }
061            catch(SQLException exc)
062            {
063                throw new NestedApplicationException(exc);
064            } 
065        }
066        
067        public MockStatement(Connection connection, int resultSetType, int resultSetConcurrency, int resultSetHoldability)
068        {
069            this.connection = connection;
070            this.resultSetType = resultSetType;
071            this.resultSetConcurrency = resultSetConcurrency;
072            this.resultSetHoldability = resultSetHoldability;
073        }
074        
075        public boolean isClosed()
076        {
077            return closed;
078        }
079        
080        public void setResultSetHandler(AbstractResultSetHandler resultSetHandler)
081        {
082            this.resultSetHandler = resultSetHandler;
083        }
084        
085        protected void setNextResultSet(ResultSet resultSet)
086        {
087            this.nextResultSet = resultSet;
088        }
089        
090        protected void setNextUpdateCount(int updateCount)
091        {
092            this.nextUpdateCount = updateCount;
093        }
094        
095        public String getCursorName()
096        {
097            return cursorName;
098        }
099        
100        public ResultSet executeQuery(String sql) throws SQLException
101        {
102            if(resultSetHandler.getThrowsSQLException(sql))
103            {
104                throw new SQLException("Statement " + sql + " was specified to throw an exception");
105            }
106            resultSetHandler.addExecutedStatement(sql);
107            MockResultSet result = resultSetHandler.getResultSet(sql);
108            if(null != result)
109            {
110                result = cloneResultSet(result);
111                resultSetHandler.addReturnedResultSet(result);
112                setNextResultSet(result);
113                return result;
114            }
115            result = cloneResultSet(resultSetHandler.getGlobalResultSet());
116            resultSetHandler.addReturnedResultSet(result);
117            setNextResultSet(result);
118            return result;
119        }
120    
121        public int executeUpdate(String sql) throws SQLException
122        {
123            if(resultSetHandler.getThrowsSQLException(sql))
124            {
125                throw new SQLException("Statement " + sql + " was specified to throw an exception");
126            }
127            resultSetHandler.addExecutedStatement(sql);
128            Integer returnValue = resultSetHandler.getUpdateCount(sql);
129            if(null != returnValue)
130            {
131                int updateCount = returnValue.intValue();
132                setNextUpdateCount(updateCount);
133                return updateCount;
134            }
135            int updateCount = resultSetHandler.getGlobalUpdateCount();
136            setNextUpdateCount(updateCount);
137            return updateCount;
138        }
139    
140        public void close() throws SQLException
141        {
142            closed = true;
143        }
144    
145        public int getMaxFieldSize() throws SQLException
146        {
147            return maxFieldSize;
148        }
149    
150        public void setMaxFieldSize(int maxFieldSize) throws SQLException
151        {
152            this.maxFieldSize = maxFieldSize;
153        }
154    
155        public int getMaxRows() throws SQLException
156        {
157            return maxRows;
158        }
159    
160        public void setMaxRows(int maxRows) throws SQLException
161        {
162            this.maxRows = maxRows;
163        }
164    
165        public void setEscapeProcessing(boolean enable) throws SQLException
166        {
167    
168        }
169    
170        public int getQueryTimeout() throws SQLException
171        {
172            return querySeconds;
173        }
174    
175        public void setQueryTimeout(int querySeconds) throws SQLException
176        {
177            this.querySeconds = querySeconds;
178        }
179    
180        public void cancel() throws SQLException
181        {
182    
183        }
184    
185        public SQLWarning getWarnings() throws SQLException
186        {
187            return null;
188        }
189    
190        public void clearWarnings() throws SQLException
191        {
192    
193        }
194    
195        public void setCursorName(String cursorName) throws SQLException
196        {
197            this.cursorName = cursorName;
198        }
199    
200        public boolean execute(String sql) throws SQLException
201        {
202            boolean callExecuteQuery = isQuery(sql);
203            if(callExecuteQuery)
204            {
205                executeQuery(sql);
206            }
207            else
208            {
209                executeUpdate(sql);
210            }
211            return callExecuteQuery;
212        }
213        
214        protected boolean isQuery(String sql)
215        {
216            boolean isQuery;
217            Boolean returnsResultSet = resultSetHandler.getReturnsResultSet(sql);
218            if(null != returnsResultSet)
219            {
220                isQuery = returnsResultSet.booleanValue();
221            }
222            else
223            {
224                isQuery = SQLUtil.isSelect(sql);
225            }
226            return isQuery;
227        }
228    
229        public ResultSet getResultSet() throws SQLException
230        {
231            ResultSet tempResultSet = nextResultSet;
232            nextResultSet = null;
233            return tempResultSet;
234        }
235    
236        public int getUpdateCount() throws SQLException
237        {
238            int tempUpdateCount = nextUpdateCount;
239            nextUpdateCount = -1;
240            return tempUpdateCount;
241        }
242    
243        public boolean getMoreResults() throws SQLException
244        {
245            if(null != nextResultSet) return true;
246            return false;
247        }
248    
249        public void setFetchDirection(int fetchDirection) throws SQLException
250        {
251            this.fetchDirection = fetchDirection;
252        }
253    
254        public int getFetchDirection() throws SQLException
255        {
256            return fetchDirection;
257        }
258    
259        public void setFetchSize(int fetchSize) throws SQLException
260        {   
261            this.fetchSize = fetchSize;
262        }
263    
264        public int getFetchSize() throws SQLException
265        {
266            return fetchSize;
267        }
268    
269        public void addBatch(String sql) throws SQLException
270        {
271            batches.add(sql);
272        }
273    
274        public void clearBatch() throws SQLException
275        {
276            batches.clear();
277        }
278    
279        public int[] executeBatch() throws SQLException
280        {
281            int[] results = new int[batches.size()];
282            for(int ii = 0; ii < results.length; ii++)
283            {
284                String nextSQL = (String)batches.get(ii);
285                if(isQuery(nextSQL))
286                {
287                    throw new BatchUpdateException("SQL " + batches.get(ii) + " in the list of batches returned a ResultSet.", null);
288                }
289                results[ii] = executeUpdate(nextSQL);
290            }
291            return results;
292        }
293    
294        public Connection getConnection() throws SQLException
295        {
296            return connection;
297        }
298    
299        public boolean getMoreResults(int current) throws SQLException
300        {
301            return getMoreResults();
302        }
303    
304        public ResultSet getGeneratedKeys() throws SQLException
305        {
306            return null;
307        }
308    
309        public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
310        {
311            return executeUpdate(sql);
312        }
313    
314        public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
315        {
316            return executeUpdate(sql);
317        }
318    
319        public int executeUpdate(String sql, String[] columnNames) throws SQLException
320        {
321            return executeUpdate(sql);
322        }
323    
324        public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
325        {
326            return execute(sql);
327        }
328    
329        public boolean execute(String sql, int[] columnIndexes) throws SQLException
330        {
331            return execute(sql);
332        }
333    
334        public boolean execute(String sql, String[] columnNames) throws SQLException
335        {
336            return execute(sql);
337        }
338        
339        public int getResultSetType() throws SQLException
340        {
341            return resultSetType;
342        }
343        
344        public int getResultSetConcurrency() throws SQLException
345        {
346            return resultSetConcurrency;
347        }
348        
349        public int getResultSetHoldability() throws SQLException
350        {
351            return resultSetHoldability;
352        }
353        
354        protected MockResultSet cloneResultSet(MockResultSet resultSet) throws SQLException
355        {
356            if(null == resultSet) return null;
357            MockResultSet clone = (MockResultSet)resultSet.clone();
358            clone.setStatement(this);
359            return clone;
360        }
361    }