1 | /* ============================================================= |
2 | * SmallSQL : a free Java DBMS library for the Java(tm) platform |
3 | * ============================================================= |
4 | * |
5 | * (C) Copyright 2004-2006, by Volker Berlin. |
6 | * |
7 | * Project Info: http://www.smallsql.de/ |
8 | * |
9 | * This library is free software; you can redistribute it and/or modify it |
10 | * under the terms of the GNU Lesser General Public License as published by |
11 | * the Free Software Foundation; either version 2.1 of the License, or |
12 | * (at your option) any later version. |
13 | * |
14 | * This library is distributed in the hope that it will be useful, but |
15 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY |
16 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public |
17 | * License for more details. |
18 | * |
19 | * You should have received a copy of the GNU Lesser General Public |
20 | * License along with this library; if not, write to the Free Software |
21 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, |
22 | * USA. |
23 | * |
24 | * [Java is a trademark or registered trademark of Sun Microsystems, Inc. |
25 | * in the United States and other countries.] |
26 | * |
27 | * --------------- |
28 | * SSStatement.java |
29 | * --------------- |
30 | * Author: Volker Berlin |
31 | * |
32 | */ |
33 | package smallsql.database; |
34 | |
35 | import java.sql.*; |
36 | import java.util.ArrayList; |
37 | |
38 | |
39 | class SSStatement implements Statement { |
40 | |
41 | final SSConnection con; |
42 | Command cmd; |
43 | int rsType; |
44 | int rsConcurrency; |
45 | private int fetchDirection; |
46 | private int fetchSize; |
47 | private int queryTimeout; |
48 | private int maxRows; |
49 | private int maxFieldSize; |
50 | private ArrayList batches; |
51 | private boolean needGeneratedKeys; |
52 | private ResultSet generatedKeys; |
53 | private int[] generatedKeyIndexes; |
54 | private String[] generatedKeyNames; |
55 | |
56 | |
57 | SSStatement( SSConnection con ) throws SQLException{ |
58 | this( con, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY ); |
59 | } |
60 | |
61 | SSStatement( SSConnection con, int rsType, int rsConcurrency ) throws SQLException{ |
62 | this.con = con; |
63 | this.rsType = rsType; |
64 | this.rsConcurrency = rsConcurrency; |
65 | con.testClosedConnection(); |
66 | } |
67 | |
68 | final public ResultSet executeQuery(String sql) throws SQLException { |
69 | executeImpl(sql); |
70 | return cmd.getQueryResult(); |
71 | } |
72 | final public int executeUpdate(String sql) throws SQLException { |
73 | executeImpl(sql); |
74 | return cmd.getUpdateCount(); |
75 | } |
76 | final public boolean execute(String sql) throws SQLException { |
77 | executeImpl(sql); |
78 | return cmd.getResultSet() != null; |
79 | } |
80 | |
81 | final private void executeImpl(String sql) throws SQLException { |
82 | generatedKeys = null; |
83 | try{ |
84 | con.log.println(sql); |
85 | SQLParser parser = new SQLParser(); |
86 | cmd = parser.parse( con, sql ); |
87 | if(maxRows != 0 && (cmd.getMaxRows() == 0 || cmd.getMaxRows() > maxRows)) |
88 | cmd.setMaxRows(maxRows); |
89 | cmd.execute( con, this); |
90 | }catch(Exception e){ |
91 | throw Utils.createSQLException(e); |
92 | } |
93 | needGeneratedKeys = false; |
94 | generatedKeyIndexes = null; |
95 | generatedKeyNames = null; |
96 | } |
97 | |
98 | final public void close() throws SQLException { |
99 | } |
100 | final public int getMaxFieldSize() throws SQLException { |
101 | return maxFieldSize; |
102 | } |
103 | final public void setMaxFieldSize(int max) throws SQLException { |
104 | maxFieldSize = max; |
105 | } |
106 | final public int getMaxRows(){ |
107 | return maxRows; |
108 | } |
109 | |
110 | |
111 | final public void setMaxRows(int max) throws SQLException{ |
112 | if(max<0) |
113 | throw Utils.createSQLException("Wrong max rows value:"+max); |
114 | maxRows = max; |
115 | } |
116 | |
117 | |
118 | final public void setEscapeProcessing(boolean enable) throws SQLException { |
119 | } |
120 | |
121 | |
122 | final public int getQueryTimeout() throws SQLException { |
123 | return queryTimeout; |
124 | } |
125 | final public void setQueryTimeout(int seconds) throws SQLException { |
126 | queryTimeout = seconds; |
127 | } |
128 | final public void cancel() throws SQLException { |
129 | } |
130 | final public SQLWarning getWarnings() throws SQLException { |
131 | return null; |
132 | } |
133 | final public void clearWarnings() throws SQLException { |
134 | } |
135 | final public void setCursorName(String name) throws SQLException { |
136 | /**@todo: Implement this java.sql.Statement method*/ |
137 | throw new java.lang.UnsupportedOperationException("Method setCursorName() not yet implemented."); |
138 | } |
139 | final public ResultSet getResultSet() throws SQLException { |
140 | return cmd.getResultSet(); |
141 | } |
142 | |
143 | |
144 | final public int getUpdateCount() throws SQLException { |
145 | return cmd.getUpdateCount(); |
146 | } |
147 | |
148 | |
149 | final public boolean getMoreResults() throws SQLException { |
150 | return getMoreResults(CLOSE_CURRENT_RESULT); |
151 | } |
152 | |
153 | |
154 | final public void setFetchDirection(int direction) throws SQLException { |
155 | fetchDirection = direction; |
156 | } |
157 | final public int getFetchDirection() throws SQLException { |
158 | return fetchDirection; |
159 | } |
160 | final public void setFetchSize(int rows) throws SQLException { |
161 | fetchSize = rows; |
162 | } |
163 | final public int getFetchSize() throws SQLException { |
164 | return fetchSize; |
165 | } |
166 | final public int getResultSetConcurrency() throws SQLException { |
167 | return rsConcurrency; |
168 | } |
169 | final public int getResultSetType() throws SQLException { |
170 | return rsType; |
171 | } |
172 | |
173 | |
174 | final public void addBatch(String sql){ |
175 | if(batches == null) batches = new ArrayList(); |
176 | batches.add(sql); |
177 | } |
178 | |
179 | |
180 | public void clearBatch(){ |
181 | if(batches == null) return; |
182 | batches.clear(); |
183 | } |
184 | |
185 | |
186 | public int[] executeBatch() throws BatchUpdateException { |
187 | if(batches == null) return new int[0]; |
188 | final int[] result = new int[batches.size()]; |
189 | BatchUpdateException failed = null; |
190 | for(int i=0; i<result.length; i++){ |
191 | try { |
192 | result[i] = executeUpdate((String)batches.get(i)); |
193 | } catch (SQLException ex) { |
194 | result[i] = EXECUTE_FAILED; |
195 | if(failed == null){ |
196 | failed = new BatchUpdateException(ex.getMessage(), ex.getSQLState(), ex.getErrorCode(), result); |
197 | failed.initCause(ex); |
198 | } |
199 | failed.setNextException(ex); |
200 | } |
201 | } |
202 | batches.clear(); |
203 | if(failed != null) |
204 | throw failed; |
205 | return result; |
206 | } |
207 | |
208 | |
209 | final public Connection getConnection(){ |
210 | return con; |
211 | } |
212 | |
213 | |
214 | final public boolean getMoreResults(int current) throws SQLException { |
215 | switch(current){ |
216 | case CLOSE_ALL_RESULTS: |
217 | //currently there exists only one ResultSet |
218 | case CLOSE_CURRENT_RESULT: |
219 | ResultSet rs = cmd.getResultSet(); |
220 | cmd.rs = null; |
221 | if(rs != null) rs.close(); |
222 | break; |
223 | case KEEP_CURRENT_RESULT: |
224 | break; |
225 | default: |
226 | throw Utils.createSQLException("Invalid flag value in method getMoreResults:"+current); |
227 | } |
228 | return false; |
229 | } |
230 | |
231 | |
232 | final void setNeedGeneratedKeys(int autoGeneratedKeys) throws SQLException{ |
233 | switch(autoGeneratedKeys){ |
234 | case NO_GENERATED_KEYS: |
235 | break; |
236 | case RETURN_GENERATED_KEYS: |
237 | needGeneratedKeys = true; |
238 | break; |
239 | default: |
240 | throw Utils.createSQLException("Invalid argument:"+autoGeneratedKeys); |
241 | } |
242 | } |
243 | |
244 | |
245 | final void setNeedGeneratedKeys(int[] columnIndexes) throws SQLException{ |
246 | needGeneratedKeys = columnIndexes != null; |
247 | generatedKeyIndexes = columnIndexes; |
248 | } |
249 | |
250 | |
251 | final void setNeedGeneratedKeys(String[] columnNames) throws SQLException{ |
252 | needGeneratedKeys = columnNames != null; |
253 | generatedKeyNames = columnNames; |
254 | } |
255 | |
256 | |
257 | final boolean needGeneratedKeys(){ |
258 | return needGeneratedKeys; |
259 | } |
260 | |
261 | |
262 | final int[] getGeneratedKeyIndexes(){ |
263 | return generatedKeyIndexes; |
264 | } |
265 | |
266 | |
267 | final String[] getGeneratedKeyNames(){ |
268 | return generatedKeyNames; |
269 | } |
270 | |
271 | |
272 | /** |
273 | * Set on execution the result with the genrated keys. |
274 | * @param rs |
275 | */ |
276 | final void setGeneratedKeys(ResultSet rs){ |
277 | generatedKeys = rs; |
278 | } |
279 | |
280 | |
281 | final public ResultSet getGeneratedKeys() throws SQLException { |
282 | if(generatedKeys == null) |
283 | throw Utils.createSQLException("GeneratedKeys not requested"); |
284 | return generatedKeys; |
285 | } |
286 | |
287 | |
288 | final public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { |
289 | setNeedGeneratedKeys(autoGeneratedKeys); |
290 | return executeUpdate(sql); |
291 | } |
292 | |
293 | |
294 | final public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { |
295 | setNeedGeneratedKeys(columnIndexes); |
296 | return executeUpdate(sql); |
297 | } |
298 | |
299 | |
300 | final public int executeUpdate(String sql, String[] columnNames) throws SQLException { |
301 | setNeedGeneratedKeys(columnNames); |
302 | return executeUpdate(sql); |
303 | } |
304 | |
305 | |
306 | final public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { |
307 | setNeedGeneratedKeys(autoGeneratedKeys); |
308 | return execute(sql); |
309 | } |
310 | |
311 | |
312 | final public boolean execute(String sql, int[] columnIndexes) throws SQLException { |
313 | setNeedGeneratedKeys(columnIndexes); |
314 | return execute(sql); |
315 | } |
316 | |
317 | |
318 | final public boolean execute(String sql, String[] columnNames) throws SQLException { |
319 | setNeedGeneratedKeys(columnNames); |
320 | return execute(sql); |
321 | } |
322 | |
323 | |
324 | final public int getResultSetHoldability() throws SQLException { |
325 | /**@todo: Implement this java.sql.Statement method*/ |
326 | throw new java.lang.UnsupportedOperationException("Method getResultSetHoldability() not yet implemented."); |
327 | } |
328 | } |