001: /*
002: * $Id: AxionPreparedStatement.java,v 1.34 2007/11/13 19:04:01 rwald Exp $
003: * =======================================================================
004: * Copyright (c) 2002-2003 Axion Development Team. All rights reserved.
005: *
006: * Redistribution and use in source and binary forms, with or without
007: * modification, are permitted provided that the following conditions
008: * are met:
009: *
010: * 1. Redistributions of source code must retain the above
011: * copyright notice, this list of conditions and the following
012: * disclaimer.
013: *
014: * 2. Redistributions in binary form must reproduce the above copyright
015: * notice, this list of conditions and the following disclaimer in
016: * the documentation and/or other materials provided with the
017: * distribution.
018: *
019: * 3. The names "Tigris", "Axion", nor the names of its contributors may
020: * not be used to endorse or promote products derived from this
021: * software without specific prior written permission.
022: *
023: * 4. Products derived from this software may not be called "Axion", nor
024: * may "Tigris" or "Axion" appear in their names without specific prior
025: * written permission.
026: *
027: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
028: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
029: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
030: * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
031: * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
032: * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
033: * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
034: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
035: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
036: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
037: * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
038: * =======================================================================
039: */
040:
041: package org.axiondb.jdbc;
042:
043: import java.io.BufferedReader;
044: import java.io.ByteArrayOutputStream;
045: import java.io.IOException;
046: import java.io.InputStream;
047: import java.io.InputStreamReader;
048: import java.io.Reader;
049: import java.io.UnsupportedEncodingException;
050: import java.math.BigDecimal;
051: import java.net.URL;
052: import java.sql.Array;
053: import java.sql.BatchUpdateException;
054: import java.sql.Blob;
055: import java.sql.Clob;
056: import java.sql.Date;
057: import java.sql.NClob;
058: import java.sql.ParameterMetaData;
059: import java.sql.PreparedStatement;
060: import java.sql.Ref;
061: import java.sql.ResultSet;
062: import java.sql.ResultSetMetaData;
063: import java.sql.RowId;
064: import java.sql.SQLException;
065: import java.sql.SQLWarning;
066: import java.sql.SQLXML;
067: import java.sql.Statement;
068: import java.sql.Time;
069: import java.sql.Timestamp;
070: import java.util.Arrays;
071: import java.util.Calendar;
072: import java.util.Iterator;
073:
074: import org.axiondb.AxionCommand;
075: import org.axiondb.AxionException;
076: import org.axiondb.types.ByteArrayBlob;
077: import org.axiondb.util.ExceptionConverter;
078: import org.axiondb.util.ValuePool;
079:
080: /**
081: * A {@link PreparedStatement} implementation.
082: *
083: * @TODO Support currently unsupported JDBC 3 methods.
084: * @version $Revision: 1.34 $ $Date: 2007/11/13 19:04:01 $
085: * @author Chuck Burdick
086: * @author Rod Waldhoff
087: * @author Ahimanikya Satapathy
088: */
089: public class AxionPreparedStatement extends AxionStatement implements
090: Statement, PreparedStatement {
091: protected AxionPreparedStatement(AxionConnection conn, String sql)
092: throws SQLException {
093: super (conn);
094: initStatement(sql);
095: }
096:
097: protected AxionPreparedStatement(AxionConnection conn, String sql,
098: int resultSetType, int resultSetConcurrency)
099: throws SQLException {
100: super (conn, resultSetType, resultSetConcurrency);
101: initStatement(sql);
102: }
103:
104: private void initStatement(String sql) throws SQLException {
105: _cmd = parseCommand(sql);
106: _params = new Parameters(_cmd.getBindVariables().size());
107: }
108:
109: private void setParameter(int i, Object value) throws SQLException {
110: assertOpen();
111: _params.set(i, value);
112: }
113:
114: private void bindVariables(Parameters params) throws SQLException {
115: try {
116: params.assertBindVariablesSet();
117: _cmd.bindAll(params.getValues());
118: } catch (AxionException e) {
119: throw ExceptionConverter.convert(e);
120: }
121: }
122:
123: // ============= PREPARED STATEMENT METHODS =============
124:
125: public void close() throws SQLException {
126: _cmd = null;
127: super .close();
128: }
129:
130: public boolean execute(String sql) throws SQLException {
131: throw new SQLException(
132: "execute(String) not valid for PreparedStatements");
133: }
134:
135: public ResultSet executeQuery(String sql) throws SQLException {
136: throw new SQLException(
137: "executeQuery(String) not valid for PreparedStatements");
138: }
139:
140: public int executeUpdate(String sql) throws SQLException {
141: throw new SQLException(
142: "executeUpdate(String) not valid for PreparedStatements");
143: }
144:
145: public void addBatch(String sql) throws SQLException {
146: throw new SQLException(
147: "addBatch(String) not valid for PreparedStatements");
148: }
149:
150: public void addBatch() throws SQLException {
151: closeCurrentResultSet(); // if still open
152: addToBatchContext(_params);
153: _params = new Parameters(_params.size());
154: }
155:
156: public void setEscapeProcessing(boolean enable) throws SQLException {
157: // "Since prepared statements have usually been parsed prior to making this call,
158: // disabling escape processing for prepared statements will have no effect"
159: }
160:
161: public void clearParameters() throws SQLException {
162: try {
163: _cmd.clearBindings();
164: _params.clearBindings();
165: } catch (AxionException e) {
166: throw ExceptionConverter.convert(e);
167: }
168: }
169:
170: public int[] executeBatch() throws SQLException {
171: SQLException exception = null;
172: int[] results = new int[getBatchCount()];
173: int i = 0;
174: for (Iterator iter = getBatchContext(); iter.hasNext(); i++) {
175: Parameters params = (Parameters) iter.next();
176: try {
177: bindVariables(params);
178: results[i] = executeUpdate(_cmd);
179: clearParameters();
180: } catch (SQLWarning w) {
181: addWarning(w);
182: } catch (SQLException e) {
183: exception = e;
184: results[i] = EXECUTE_FAILED;
185: }
186: }
187: clearBatchContext();
188: if (null != exception) {
189: throw new BatchUpdateException(exception.getMessage(),
190: results);
191: }
192: return results;
193: }
194:
195: public boolean execute() throws SQLException {
196: clearCurrentResult();
197: bindVariables(_params);
198: return execute(_cmd);
199: }
200:
201: public ResultSet executeQuery() throws SQLException {
202: clearCurrentResult();
203: bindVariables(_params);
204: return executeQuery(_cmd);
205: }
206:
207: public int executeUpdate() throws SQLException {
208: clearCurrentResult();
209: bindVariables(_params);
210: return executeUpdate(_cmd);
211: }
212:
213: public ResultSetMetaData getMetaData() throws SQLException {
214: if (hasCurrentResultSet()) {
215: return getCurrentResultSet().getMetaData();
216: }
217: throw new SQLException("No current ResultSet");
218: }
219:
220: public void setArray(int i, Array arr) throws SQLException {
221: setParameter(i, arr);
222: }
223:
224: public void setAsciiStream(int n, InputStream in, int length)
225: throws SQLException {
226: try {
227: setCharacterStream(n, new InputStreamReader(in, "ASCII"),
228: length);
229: } catch (UnsupportedEncodingException e) {
230: throw ExceptionConverter.convert(e);
231: }
232: }
233:
234: public void setBigDecimal(int i, BigDecimal big)
235: throws SQLException {
236: setParameter(i, big);
237: }
238:
239: public void setBinaryStream(int n, InputStream in, int length)
240: throws SQLException {
241: ByteArrayOutputStream buffer = new ByteArrayOutputStream(length);
242: try {
243: for (int i = 0, b = in.read(); i < length && b != -1; i++, b = in
244: .read()) {
245: buffer.write(b);
246: }
247: } catch (IOException e) {
248: throw ExceptionConverter.convert(e);
249: }
250: setBlob(n, new ByteArrayBlob(buffer.toByteArray()));
251: }
252:
253: public void setBlob(int i, Blob blob) throws SQLException {
254: setParameter(i, blob);
255: }
256:
257: public void setBoolean(int i, boolean bool) throws SQLException {
258: setParameter(i, ValuePool.getBoolean(bool));
259: }
260:
261: public void setByte(int i, byte b) throws SQLException {
262: setParameter(i, new Byte(b));
263: }
264:
265: public void setBytes(int i, byte[] bytes) throws SQLException {
266: setParameter(i, bytes);
267: }
268:
269: public void setCharacterStream(int n, Reader reader, int length)
270: throws SQLException {
271: StringBuffer buf = new StringBuffer(length);
272: try {
273: reader = new BufferedReader(reader);
274: for (int i = 0, c = reader.read(); i < length && c != -1; c = reader
275: .read(), i++) {
276: buf.append((char) c);
277: }
278: } catch (IOException e) {
279: throw ExceptionConverter.convert(e);
280: }
281: setString(n, buf.toString());
282: }
283:
284: public void setClob(int i, Clob clob) throws SQLException {
285: setParameter(i, clob);
286: }
287:
288: public void setDate(int i, Date date) throws SQLException {
289: setParameter(i, date);
290: }
291:
292: public void setDate(int i, Date date, Calendar cal)
293: throws SQLException {
294: throw new UnsupportedOperationException();
295: }
296:
297: public void setDouble(int i, double d) throws SQLException {
298: setParameter(i, new Double(d));
299: }
300:
301: public void setFloat(int i, float f) throws SQLException {
302: setParameter(i, new Float(f));
303: }
304:
305: public void setInt(int i, int value) throws SQLException {
306: setParameter(i, new Integer(value));
307: }
308:
309: public void setLong(int i, long l) throws SQLException {
310: setParameter(i, new Long(l));
311: }
312:
313: public void setNull(int i, int sqlType) throws SQLException {
314: setParameter(i, null);
315: }
316:
317: public void setNull(int i, int sqlType, String typeName)
318: throws SQLException {
319: setParameter(i, null);
320: }
321:
322: public void setObject(int i, Object o) throws SQLException {
323: setParameter(i, o);
324: }
325:
326: public void setObject(int i, Object o, int targetSqlType)
327: throws SQLException {
328: setParameter(i, o);
329: }
330:
331: public void setObject(int i, Object o, int targetSqlType, int scale)
332: throws SQLException {
333: setParameter(i, o);
334: }
335:
336: public void setRef(int i, Ref ref) throws SQLException {
337: throw new SQLException("setRef is currently not supported");
338: }
339:
340: public void setShort(int i, short s) throws SQLException {
341: setParameter(i, new Short(s));
342: }
343:
344: public void setString(int i, String str) throws SQLException {
345: setParameter(i, str);
346: }
347:
348: public void setTime(int i, Time time) throws SQLException {
349: setParameter(i, time);
350: }
351:
352: public void setTime(int i, Time time, Calendar cal)
353: throws SQLException {
354: throw new SQLException(
355: "setTime(int,Time,Calendar) is currently not supported");
356: }
357:
358: public void setTimestamp(int i, Timestamp timestamp)
359: throws SQLException {
360: setParameter(i, timestamp);
361: }
362:
363: public void setTimestamp(int i, Timestamp timestamp, Calendar cal)
364: throws SQLException {
365: throw new SQLException(
366: "setTimestamp(int,Timestamp,Calendar) is currently not supported");
367: }
368:
369: public void setURL(int i, URL url) throws SQLException {
370: setParameter(i, url);
371: }
372:
373: /** @deprecated See {@link java.sql.PreparedStatement#setUnicodeStream} */
374: public void setUnicodeStream(int n, InputStream in, int length)
375: throws SQLException {
376: try {
377: setCharacterStream(n, new InputStreamReader(in,
378: "UnicodeBig"), length / 2);
379: } catch (UnsupportedEncodingException e) {
380: throw ExceptionConverter.convert(e);
381: }
382: }
383:
384: /** Currently unsupported. */
385: public ParameterMetaData getParameterMetaData() throws SQLException {
386: throw new SQLException(
387: "getParameterMetaData is currently not supported");
388: }
389:
390: protected class Parameters {
391: public Parameters(int size) {
392: _vals = new Object[size];
393: Arrays.fill(_vals, UNBOUND);
394: }
395:
396: /**
397: * Get the value of parameter <i>i</i>.
398: * Note that the index is zero-based.
399: */
400: public Object get(int i) {
401: return _vals[i];
402: }
403:
404: /**
405: * Set the value of parameter <i>i</i> to
406: * <i>val</i>.
407: *
408: * Note that the index is zero-based.
409: */
410: public void set(int i, Object val) throws SQLException {
411: if (i < 1 || i > _vals.length) {
412: throw new SQLException("Invalid index for Parameter");
413: }
414: _vals[i - 1] = val;
415: }
416:
417: public void assertBindVariablesSet() throws SQLException {
418: for (int i = 0, I = _vals.length; i < I; i++) {
419: if (_vals[i] == UNBOUND) {
420: throw new SQLException("Unbound variable found.");
421: }
422: }
423: }
424:
425: public final void clearBindings() {
426: Arrays.fill(_vals, UNBOUND);
427: }
428:
429: /**
430: * Return the number of parameters I contain.
431: */
432: public int size() {
433: return _vals.length;
434: }
435:
436: public Object[] getValues() {
437: return _vals;
438: }
439:
440: private Object[] _vals;
441: }
442:
443: private AxionCommand _cmd;
444: private Parameters _params;
445: private final static Object UNBOUND = new Object();
446:
447: @Override
448: public void setAsciiStream(int arg0, InputStream arg1)
449: throws SQLException {
450: throw new SQLException("Not supported");
451: }
452:
453: @Override
454: public void setAsciiStream(int arg0, InputStream arg1, long arg2)
455: throws SQLException {
456: throw new SQLException("Not supported");
457: }
458:
459: @Override
460: public void setBinaryStream(int arg0, InputStream arg1)
461: throws SQLException {
462: throw new SQLException("Not supported");
463: }
464:
465: @Override
466: public void setBinaryStream(int arg0, InputStream arg1, long arg2)
467: throws SQLException {
468: throw new SQLException("Not supported");
469: }
470:
471: @Override
472: public void setBlob(int arg0, InputStream arg1) throws SQLException {
473: throw new SQLException("Not supported");
474: }
475:
476: @Override
477: public void setBlob(int arg0, InputStream arg1, long arg2)
478: throws SQLException {
479: throw new SQLException("Not supported");
480: }
481:
482: @Override
483: public void setCharacterStream(int arg0, Reader arg1)
484: throws SQLException {
485: throw new SQLException("Not supported");
486: }
487:
488: @Override
489: public void setCharacterStream(int arg0, Reader arg1, long arg2)
490: throws SQLException {
491: throw new SQLException("Not supported");
492: }
493:
494: @Override
495: public void setClob(int arg0, Reader arg1) throws SQLException {
496: throw new SQLException("Not supported");
497: }
498:
499: @Override
500: public void setClob(int arg0, Reader arg1, long arg2)
501: throws SQLException {
502: throw new SQLException("Not supported");
503: }
504:
505: @Override
506: public void setNCharacterStream(int arg0, Reader arg1)
507: throws SQLException {
508: throw new SQLException("Not supported");
509: }
510:
511: @Override
512: public void setNCharacterStream(int arg0, Reader arg1, long arg2)
513: throws SQLException {
514: throw new SQLException("Not supported");
515: }
516:
517: @Override
518: public void setNClob(int arg0, NClob arg1) throws SQLException {
519: throw new SQLException("Not supported");
520: }
521:
522: @Override
523: public void setNClob(int arg0, Reader arg1) throws SQLException {
524: throw new SQLException("Not supported");
525: }
526:
527: @Override
528: public void setNClob(int arg0, Reader arg1, long arg2)
529: throws SQLException {
530: throw new SQLException("Not supported");
531: }
532:
533: @Override
534: public void setNString(int arg0, String arg1) throws SQLException {
535: throw new SQLException("Not supported");
536: }
537:
538: @Override
539: public void setRowId(int arg0, RowId arg1) throws SQLException {
540: throw new SQLException("Not supported");
541: }
542:
543: @Override
544: public void setSQLXML(int arg0, SQLXML arg1) throws SQLException {
545: throw new SQLException("Not supported");
546: }
547:
548: }
|