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 | * SSPreparedStatement.java |
29 | * --------------- |
30 | * Author: Volker Berlin |
31 | * |
32 | */ |
33 | package smallsql.database; |
34 | |
35 | import java.sql.*; |
36 | import java.math.*; |
37 | import java.io.*; |
38 | import java.util.ArrayList; |
39 | import java.util.Calendar; |
40 | import java.net.URL; |
41 | |
42 | |
43 | class SSPreparedStatement extends SSStatement implements PreparedStatement { |
44 | |
45 | final private String sql; |
46 | private ArrayList batches; |
47 | private final int top; // value of an optional top expression |
48 | |
49 | SSPreparedStatement( SSConnection con, String sql ) throws SQLException { |
50 | this( con, sql, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY ); |
51 | } |
52 | |
53 | SSPreparedStatement( SSConnection con, String sql, int rsType, int rsConcurrency ) throws SQLException { |
54 | super( con, rsType, rsConcurrency ); |
55 | this.sql = sql; |
56 | con.log.println(sql); |
57 | SQLParser parser = new SQLParser(); |
58 | cmd = parser.parse( con, sql ); |
59 | top = cmd.getMaxRows(); |
60 | } |
61 | |
62 | public ResultSet executeQuery() throws SQLException { |
63 | executeImp(); |
64 | return cmd.getQueryResult(); |
65 | } |
66 | |
67 | public int executeUpdate() throws SQLException { |
68 | executeImp(); |
69 | return cmd.getUpdateCount(); |
70 | } |
71 | |
72 | final private void executeImp() throws SQLException { |
73 | cmd.verifyParams(); |
74 | if(getMaxRows() != 0 && (top == 0 || top > getMaxRows())) |
75 | cmd.setMaxRows(getMaxRows()); |
76 | cmd.execute( con, this); |
77 | } |
78 | |
79 | public void setNull(int parameterIndex, int sqlType) throws SQLException { |
80 | cmd.setParamValue( parameterIndex, null, SQLTokenizer.NULL); |
81 | } |
82 | |
83 | |
84 | public void setBoolean(int parameterIndex, boolean x) throws SQLException { |
85 | cmd.setParamValue( parameterIndex, x ? Boolean.TRUE : Boolean.FALSE, SQLTokenizer.BOOLEAN); |
86 | } |
87 | |
88 | |
89 | public void setByte(int parameterIndex, byte x) throws SQLException { |
90 | cmd.setParamValue( parameterIndex, new Integer(x), SQLTokenizer.TINYINT); |
91 | } |
92 | |
93 | |
94 | public void setShort(int parameterIndex, short x) throws SQLException { |
95 | cmd.setParamValue( parameterIndex, new Integer(x), SQLTokenizer.SMALLINT); |
96 | } |
97 | |
98 | |
99 | public void setInt(int parameterIndex, int x) throws SQLException { |
100 | cmd.setParamValue( parameterIndex, new Integer(x), SQLTokenizer.INT); |
101 | } |
102 | |
103 | |
104 | public void setLong(int parameterIndex, long x) throws SQLException { |
105 | cmd.setParamValue( parameterIndex, new Long(x), SQLTokenizer.BIGINT); |
106 | } |
107 | |
108 | |
109 | public void setFloat(int parameterIndex, float x) throws SQLException { |
110 | cmd.setParamValue( parameterIndex, new Float(x), SQLTokenizer.REAL); |
111 | } |
112 | |
113 | |
114 | public void setDouble(int parameterIndex, double x) throws SQLException { |
115 | cmd.setParamValue( parameterIndex, new Double(x), SQLTokenizer.DOUBLE); |
116 | } |
117 | |
118 | |
119 | public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { |
120 | cmd.setParamValue( parameterIndex, x, SQLTokenizer.DECIMAL); |
121 | } |
122 | |
123 | |
124 | public void setString(int parameterIndex, String x) throws SQLException { |
125 | cmd.setParamValue( parameterIndex, x, SQLTokenizer.VARCHAR); |
126 | } |
127 | |
128 | |
129 | public void setBytes(int parameterIndex, byte[] x) throws SQLException { |
130 | cmd.setParamValue( parameterIndex, x, SQLTokenizer.BINARY); |
131 | } |
132 | |
133 | |
134 | public void setDate(int parameterIndex, Date x) throws SQLException { |
135 | cmd.setParamValue( parameterIndex, DateTime.valueOf(x), SQLTokenizer.DATE); |
136 | } |
137 | |
138 | |
139 | public void setTime(int parameterIndex, Time x) throws SQLException { |
140 | cmd.setParamValue( parameterIndex, DateTime.valueOf(x), SQLTokenizer.TIME); |
141 | } |
142 | |
143 | |
144 | public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { |
145 | cmd.setParamValue( parameterIndex, DateTime.valueOf(x), SQLTokenizer.TIMESTAMP); |
146 | } |
147 | |
148 | |
149 | public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { |
150 | cmd.setParamValue( parameterIndex, x, SQLTokenizer.LONGVARCHAR, length); |
151 | } |
152 | |
153 | |
154 | public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { |
155 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
156 | throw new java.lang.UnsupportedOperationException("Method setUnicodeStream() not yet implemented."); |
157 | } |
158 | |
159 | |
160 | public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { |
161 | cmd.setParamValue( parameterIndex, x, SQLTokenizer.LONGVARBINARY, length); |
162 | } |
163 | |
164 | |
165 | public void clearParameters() throws SQLException { |
166 | cmd.clearParams(); |
167 | } |
168 | |
169 | |
170 | public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException { |
171 | //FIXME Scale berücksichtigen |
172 | cmd.setParamValue( parameterIndex, x, -1); |
173 | } |
174 | |
175 | |
176 | public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { |
177 | cmd.setParamValue( parameterIndex, x, -1); |
178 | } |
179 | |
180 | |
181 | public void setObject(int parameterIndex, Object x) throws SQLException { |
182 | cmd.setParamValue( parameterIndex, x, -1); |
183 | } |
184 | |
185 | |
186 | public boolean execute() throws SQLException { |
187 | executeImp(); |
188 | return cmd.getResultSet() != null; |
189 | } |
190 | |
191 | |
192 | public void addBatch() throws SQLException { |
193 | try{ |
194 | final Expressions params = cmd.params; |
195 | final int size = params.size(); |
196 | ExpressionValue[] values = new ExpressionValue[size]; |
197 | for(int i=0; i<size; i++){ |
198 | values[i] = (ExpressionValue)params.get(i).clone(); |
199 | } |
200 | if(batches == null) batches = new ArrayList(); |
201 | batches.add(values); |
202 | }catch(Exception e){ |
203 | throw Utils.createSQLException(e); |
204 | } |
205 | } |
206 | |
207 | |
208 | public void clearBatch() { |
209 | if(batches != null) batches.clear(); |
210 | } |
211 | |
212 | |
213 | public int[] executeBatch() throws BatchUpdateException { |
214 | if(batches == null || batches.size() == 0) return new int[0]; |
215 | int[] result = new int[batches.size()]; |
216 | BatchUpdateException failed = null; |
217 | for(int b=0; b<batches.size(); b++){ |
218 | try{ |
219 | ExpressionValue[] values = (ExpressionValue[])batches.get(b); |
220 | for(int i=0; i<values.length; i++){ |
221 | ((ExpressionValue)cmd.params.get(i)).set( values[i] ); |
222 | } |
223 | result[b] = executeUpdate(); |
224 | } catch (SQLException ex) { |
225 | result[b] = EXECUTE_FAILED; |
226 | if(failed == null){ |
227 | failed = new BatchUpdateException(ex.getMessage(), ex.getSQLState(), ex.getErrorCode(), result); |
228 | failed.initCause(ex); |
229 | } |
230 | failed.setNextException(ex); |
231 | } |
232 | } |
233 | batches.clear(); |
234 | if(failed != null) |
235 | throw failed; |
236 | return result; |
237 | } |
238 | |
239 | |
240 | public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { |
241 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
242 | throw new java.lang.UnsupportedOperationException("Method setCharacterStream() not yet implemented."); |
243 | } |
244 | |
245 | |
246 | public void setRef(int i, Ref x) throws SQLException { |
247 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
248 | throw new java.lang.UnsupportedOperationException("Method setRef() not yet implemented."); |
249 | } |
250 | public void setBlob(int i, Blob x) throws SQLException { |
251 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
252 | throw new java.lang.UnsupportedOperationException("Method setBlob() not yet implemented."); |
253 | } |
254 | public void setClob(int i, Clob x) throws SQLException { |
255 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
256 | throw new java.lang.UnsupportedOperationException("Method setClob() not yet implemented."); |
257 | } |
258 | public void setArray(int i, Array x) throws SQLException { |
259 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
260 | throw new java.lang.UnsupportedOperationException("Method setArray() not yet implemented."); |
261 | } |
262 | |
263 | |
264 | public ResultSetMetaData getMetaData() throws SQLException { |
265 | if(cmd instanceof CommandSelect){ |
266 | try{ |
267 | ((CommandSelect)cmd).compile(con); |
268 | SSResultSetMetaData metaData = new SSResultSetMetaData(); |
269 | metaData.columns = cmd.columnExpressions; |
270 | return metaData; |
271 | }catch(Exception e){ |
272 | Utils.createSQLException(e); |
273 | } |
274 | } |
275 | return null; |
276 | } |
277 | |
278 | |
279 | public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { |
280 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
281 | throw new java.lang.UnsupportedOperationException("Method setDate() not yet implemented."); |
282 | } |
283 | public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { |
284 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
285 | throw new java.lang.UnsupportedOperationException("Method setTime() not yet implemented."); |
286 | } |
287 | public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { |
288 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
289 | throw new java.lang.UnsupportedOperationException("Method setTimestamp() not yet implemented."); |
290 | } |
291 | public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException { |
292 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
293 | throw new java.lang.UnsupportedOperationException("Method setNull() not yet implemented."); |
294 | } |
295 | public void setURL(int parameterIndex, URL x) throws SQLException { |
296 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
297 | throw new java.lang.UnsupportedOperationException("Method setURL() not yet implemented."); |
298 | } |
299 | public ParameterMetaData getParameterMetaData() throws SQLException { |
300 | /**@todo: Implement this java.sql.PreparedStatement method*/ |
301 | throw new java.lang.UnsupportedOperationException("Method getParameterMetaData() not yet implemented."); |
302 | } |
303 | } |