001 /**
002 * Copyright 2007-2008 Arthur Blake
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016 package net.sf.log4jdbc;
017
018 import java.io.InputStream;
019 import java.io.Reader;
020 import java.math.BigDecimal;
021 import java.net.URL;
022 import java.sql.Array;
023 import java.sql.Blob;
024 import java.sql.Clob;
025 import java.sql.Date;
026 import java.sql.NClob;
027 import java.sql.ParameterMetaData;
028 import java.sql.PreparedStatement;
029 import java.sql.Ref;
030 import java.sql.RowId;
031 import java.sql.ResultSet;
032 import java.sql.ResultSetMetaData;
033 import java.sql.SQLException;
034 import java.sql.SQLXML;
035 import java.sql.Statement;
036 import java.sql.Time;
037 import java.sql.Timestamp;
038 import java.util.ArrayList;
039 import java.util.Calendar;
040 import java.util.List;
041
042 /**
043 * Wraps a PreparedStatement and reports method calls, returns and exceptions.
044 *
045 * @author Arthur Blake
046 */
047 public class PreparedStatementSpy extends StatementSpy implements PreparedStatement
048 {
049
050 /**
051 * holds list of bind variables for tracing
052 */
053 protected final List argTrace = new ArrayList();
054
055 // a way to turn on and off type help...
056 // todo: make this a configurable parameter
057 // todo, debug arrays and streams in a more useful manner.... if possible
058 private static final boolean showTypeHelp = false;
059
060 /**
061 * Store an argument (bind variable) into the argTrace list (above) for later dumping.
062 *
063 * @param i index of argument being set.
064 * @param typeHelper optional additional info about the type that is being set in the arg
065 * @param arg argument being bound.
066 */
067 protected void argTraceSet(int i, String typeHelper, Object arg)
068 {
069 String tracedArg = rdbmsSpecifics.formatParameterObject(arg);
070
071 i--; // make the index 0 based
072 synchronized (argTrace)
073 {
074 // if an object is being inserted out of sequence, fill up missing values with null...
075 while (i >= argTrace.size())
076 {
077 argTrace.add(argTrace.size(), null);
078 }
079 if (!showTypeHelp || typeHelper == null)
080 {
081 argTrace.set(i, tracedArg);
082 }
083 else
084 {
085 argTrace.set(i, typeHelper + tracedArg);
086 }
087 }
088 }
089
090 private String sql;
091
092 protected String dumpedSql()
093 {
094 StringBuffer dumpSql = new StringBuffer();
095 int lastPos = 0;
096 int Qpos = sql.indexOf('?', lastPos); // find position of first question mark
097 int argIdx = 0;
098 String arg;
099
100 while (Qpos != -1)
101 {
102 // get stored argument
103 synchronized (argTrace)
104 {
105 try
106 {
107 arg = (String) argTrace.get(argIdx);
108 }
109 catch (IndexOutOfBoundsException e)
110 {
111 arg = "?";
112 }
113 }
114 if (arg == null)
115 {
116 arg = "?";
117 }
118
119 argIdx++;
120
121 dumpSql.append(sql.substring(lastPos, Qpos)); // dump segment of sql up to question mark.
122 lastPos = Qpos + 1;
123 Qpos = sql.indexOf('?', lastPos);
124 dumpSql.append(arg);
125 }
126 if (lastPos < sql.length())
127 {
128 dumpSql.append(sql.substring(lastPos, sql.length())); // dump last segment
129 }
130
131 return dumpSql.toString();
132 }
133
134 protected void reportAllReturns(String methodCall, String msg)
135 {
136 log.methodReturned(this, methodCall, msg);
137 }
138
139 /**
140 * The real PreparedStatement that this PreparedStatementSpy wraps.
141 */
142 protected PreparedStatement realPreparedStatement;
143
144 /**
145 * RdbmsSpecifics for formatting SQL for the given RDBMS.
146 */
147 protected RdbmsSpecifics rdbmsSpecifics;
148
149 /**
150 * Create a PreparedStatementSpy (JDBC 4 version) for logging activity of another PreparedStatement.
151 *
152 * @param sql SQL for the prepared statement that is being spied upon.
153 * @param connectionSpy ConnectionSpy that was called to produce this PreparedStatement.
154 * @param realPreparedStatement The actual PreparedStatement that is being spied upon.
155 */
156 public PreparedStatementSpy(String sql, ConnectionSpy connectionSpy, PreparedStatement realPreparedStatement)
157 {
158 super(connectionSpy, realPreparedStatement); // does null check for us
159 this.sql = sql;
160 this.realPreparedStatement = realPreparedStatement;
161 rdbmsSpecifics = connectionSpy.getRdbmsSpecifics();
162 }
163
164 public String getClassType()
165 {
166 return "PreparedStatement";
167 }
168
169 // forwarding methods
170
171 public void setTime(int parameterIndex, Time x) throws SQLException
172 {
173 String methodCall = "setTime(" + parameterIndex + ", " + x + ")";
174 argTraceSet(parameterIndex, "(Time)", x);
175 try
176 {
177 realPreparedStatement.setTime(parameterIndex, x);
178 }
179 catch (SQLException s)
180 {
181 reportException(methodCall, s);
182 throw s;
183 }
184 reportReturn(methodCall);
185 }
186
187 public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException
188 {
189 String methodCall = "setTime(" + parameterIndex + ", " + x + ", " + cal + ")";
190 argTraceSet(parameterIndex, "(Time)", x);
191 try
192 {
193 realPreparedStatement.setTime(parameterIndex, x, cal);
194 }
195 catch (SQLException s)
196 {
197 reportException(methodCall, s);
198 throw s;
199 }
200 reportReturn(methodCall);
201 }
202
203 public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException
204 {
205 String methodCall = "setCharacterStream(" + parameterIndex + ", " + reader + ", " + length + ")";
206 argTraceSet(parameterIndex, "(Reader)", "<Reader of length " + length + ">");
207 try
208 {
209 realPreparedStatement.setCharacterStream(parameterIndex, reader, length);
210 }
211 catch (SQLException s)
212 {
213 reportException(methodCall, s);
214 throw s;
215 }
216 reportReturn(methodCall);
217 }
218
219 public void setNull(int parameterIndex, int sqlType) throws SQLException
220 {
221 String methodCall = "setNull(" + parameterIndex + ", " + sqlType + ")";
222 argTraceSet(parameterIndex, null, null);
223 try
224 {
225 realPreparedStatement.setNull(parameterIndex, sqlType);
226 }
227 catch (SQLException s)
228 {
229 reportException(methodCall, s);
230 throw s;
231 }
232 reportReturn(methodCall);
233 }
234
235 public void setNull(int paramIndex, int sqlType, String typeName) throws SQLException
236 {
237 String methodCall = "setNull(" + paramIndex + ", " + sqlType + ", " + typeName + ")";
238 argTraceSet(paramIndex, null, null);
239 try
240 {
241 realPreparedStatement.setNull(paramIndex, sqlType, typeName);
242 }
243 catch (SQLException s)
244 {
245 reportException(methodCall, s);
246 throw s;
247 }
248 reportReturn(methodCall);
249 }
250
251 public void setRef(int i, Ref x) throws SQLException
252 {
253 String methodCall = "setRef(" + i + ", " + x + ")";
254 argTraceSet(i, "(Ref)", x);
255 try
256 {
257 realPreparedStatement.setRef(i, x);
258 }
259 catch (SQLException s)
260 {
261 reportException(methodCall, s);
262 throw s;
263 }
264 reportReturn(methodCall);
265 }
266
267 public void setBoolean(int parameterIndex, boolean x) throws SQLException
268 {
269 String methodCall = "setBoolean(" + parameterIndex + ", " + x + ")";
270 argTraceSet(parameterIndex, "(boolean)", x?Boolean.TRUE:Boolean.FALSE);
271 try
272 {
273 realPreparedStatement.setBoolean(parameterIndex, x);
274 }
275 catch (SQLException s)
276 {
277 reportException(methodCall, s);
278 throw s;
279 }
280 reportReturn(methodCall);
281 }
282
283 public void setBlob(int i, Blob x) throws SQLException
284 {
285 String methodCall = "setBlob(" + i + ", " + x + ")";
286 argTraceSet(i, "(Blob)", "<Blob of size " + x.length() + ">");
287 try
288 {
289 realPreparedStatement.setBlob(i, x);
290 }
291 catch (SQLException s)
292 {
293 reportException(methodCall, s);
294 throw s;
295 }
296 reportReturn(methodCall);
297 }
298
299 public void setClob(int i, Clob x) throws SQLException
300 {
301 String methodCall = "setClob(" + i + ", " + x + ")";
302 argTraceSet(i, "(Clob)", "<Clob of size " + x.length() + ">");
303 try
304 {
305 realPreparedStatement.setClob(i, x);
306 }
307 catch (SQLException s)
308 {
309 reportException(methodCall, s);
310 throw s;
311 }
312 reportReturn(methodCall);
313 }
314
315 public void setArray(int i, Array x) throws SQLException
316 {
317 String methodCall = "setArray(" + i + ", " + x + ")";
318 argTraceSet(i, "(Array)", "<Array>");
319 try
320 {
321 realPreparedStatement.setArray(i, x);
322 }
323 catch (SQLException s)
324 {
325 reportException(methodCall, s);
326 throw s;
327 }
328 reportReturn(methodCall);
329 }
330
331 public void setByte(int parameterIndex, byte x) throws SQLException
332 {
333 String methodCall = "setByte(" + parameterIndex + ", " + x + ")";
334 argTraceSet(parameterIndex, "(byte)", new Byte(x));
335 try
336 {
337 realPreparedStatement.setByte(parameterIndex, x);
338 }
339 catch (SQLException s)
340 {
341 reportException(methodCall, s);
342 throw s;
343 }
344 reportReturn(methodCall);
345 }
346
347 /**
348 * @deprecated
349 */
350 public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException
351 {
352 String methodCall = "setUnicodeStream(" + parameterIndex + ", " + x + ", " + length + ")";
353 argTraceSet(parameterIndex, "(Unicode InputStream)", "<Unicode InputStream of length " + length + ">");
354 try
355 {
356 realPreparedStatement.setUnicodeStream(parameterIndex, x, length);
357 }
358 catch (SQLException s)
359 {
360 reportException(methodCall, s);
361 throw s;
362 }
363 reportReturn(methodCall);
364 }
365
366 public void setShort(int parameterIndex, short x) throws SQLException
367 {
368 String methodCall = "setShort(" + parameterIndex + ", " + x + ")";
369 argTraceSet(parameterIndex, "(short)", new Short(x));
370 try
371 {
372 realPreparedStatement.setShort(parameterIndex, x);
373 }
374 catch (SQLException s)
375 {
376 reportException(methodCall, s);
377 throw s;
378 }
379 reportReturn(methodCall);
380 }
381
382 public boolean execute() throws SQLException
383 {
384 String methodCall = "execute()";
385 String dumpedSql = dumpedSql();
386 reportSql(dumpedSql, methodCall);
387 long tstart = System.currentTimeMillis();
388 try
389 {
390 boolean result = realPreparedStatement.execute();
391 reportSqlTiming(System.currentTimeMillis() - tstart, dumpedSql, methodCall);
392 return reportReturn(methodCall, result);
393 }
394 catch (SQLException s)
395 {
396 reportException(methodCall, s, dumpedSql, System.currentTimeMillis() - tstart);
397 throw s;
398 }
399 }
400
401 public void setInt(int parameterIndex, int x) throws SQLException
402 {
403 String methodCall = "setInt(" + parameterIndex + ", " + x + ")";
404 argTraceSet(parameterIndex, "(int)", new Integer(x));
405 try
406 {
407 realPreparedStatement.setInt(parameterIndex, x);
408 }
409 catch (SQLException s)
410 {
411 reportException(methodCall, s);
412 throw s;
413 }
414 reportReturn(methodCall);
415 }
416
417 public void setLong(int parameterIndex, long x) throws SQLException
418 {
419 String methodCall = "setLong(" + parameterIndex + ", " + x + ")";
420 argTraceSet(parameterIndex, "(long)", new Long(x));
421 try
422 {
423 realPreparedStatement.setLong(parameterIndex, x);
424 }
425 catch (SQLException s)
426 {
427 reportException(methodCall, s);
428 throw s;
429 }
430 reportReturn(methodCall);
431 }
432
433 public void setFloat(int parameterIndex, float x) throws SQLException
434 {
435 String methodCall = "setFloat(" + parameterIndex + ", " + x + ")";
436 argTraceSet(parameterIndex, "(float)", new Float(x));
437 try
438 {
439 realPreparedStatement.setFloat(parameterIndex, x);
440 }
441 catch (SQLException s)
442 {
443 reportException(methodCall, s);
444 throw s;
445 }
446 reportReturn(methodCall);
447 }
448
449 public void setDouble(int parameterIndex, double x) throws SQLException
450 {
451 String methodCall = "setDouble(" + parameterIndex + ", " + x + ")";
452 argTraceSet(parameterIndex, "(double)", new Double(x));
453 try
454 {
455 realPreparedStatement.setDouble(parameterIndex, x);
456 }
457 catch (SQLException s)
458 {
459 reportException(methodCall, s);
460 throw s;
461 }
462 reportReturn(methodCall);
463 }
464
465 public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException
466 {
467 String methodCall = "setBigDecimal(" + parameterIndex + ", " + x + ")";
468 argTraceSet(parameterIndex, "(BigDecimal)", x);
469 try
470 {
471 realPreparedStatement.setBigDecimal(parameterIndex, x);
472 }
473 catch (SQLException s)
474 {
475 reportException(methodCall, s);
476 throw s;
477 }
478 reportReturn(methodCall);
479 }
480
481 public void setURL(int parameterIndex, URL x) throws SQLException
482 {
483 String methodCall = "setURL(" + parameterIndex + ", " + x + ")";
484 argTraceSet(parameterIndex, "(URL)", x);
485
486 try
487 {
488 realPreparedStatement.setURL(parameterIndex, x);
489 }
490 catch (SQLException s)
491 {
492 reportException(methodCall, s);
493 throw s;
494 }
495 reportReturn(methodCall);
496 }
497
498 public void setString(int parameterIndex, String x) throws SQLException
499 {
500 String methodCall = "setString(" + parameterIndex + ", \"" + x + "\")";
501 argTraceSet(parameterIndex, "(String)", x);
502
503 try
504 {
505 realPreparedStatement.setString(parameterIndex, x);
506 }
507 catch (SQLException s)
508 {
509 reportException(methodCall, s);
510 throw s;
511 }
512 reportReturn(methodCall);
513 }
514
515 public void setBytes(int parameterIndex, byte[] x) throws SQLException
516 {
517 //todo: dump array?
518 String methodCall = "setBytes(" + parameterIndex + ", " + x + ")";
519 argTraceSet(parameterIndex, "(byte[])", "<byte[]>");
520 try
521 {
522 realPreparedStatement.setBytes(parameterIndex, x);
523 }
524 catch (SQLException s)
525 {
526 reportException(methodCall, s);
527 throw s;
528 }
529 reportReturn(methodCall);
530 }
531
532 public void setDate(int parameterIndex, Date x) throws SQLException
533 {
534 String methodCall = "setDate(" + parameterIndex + ", " + x + ")";
535 argTraceSet(parameterIndex, "(Date)", x);
536 try
537 {
538 realPreparedStatement.setDate(parameterIndex, x);
539 }
540 catch (SQLException s)
541 {
542 reportException(methodCall, s);
543 throw s;
544 }
545 reportReturn(methodCall);
546 }
547
548 public ParameterMetaData getParameterMetaData() throws SQLException
549 {
550 String methodCall = "getParameterMetaData()";
551 try
552 {
553 return (ParameterMetaData) reportReturn(methodCall, realPreparedStatement.getParameterMetaData());
554 }
555 catch (SQLException s)
556 {
557 reportException(methodCall, s);
558 throw s;
559 }
560 }
561
562 public void setRowId(int parameterIndex, RowId x) throws SQLException {
563 String methodCall = "setRowId(" + parameterIndex + ", " + x + ")";
564 argTraceSet(parameterIndex, "(RowId)", x);
565 try
566 {
567 realPreparedStatement.setRowId(parameterIndex, x);
568 }
569 catch (SQLException s)
570 {
571 reportException(methodCall, s);
572 throw s;
573 }
574 reportReturn(methodCall);
575 }
576
577 public void setNString(int parameterIndex, String value) throws SQLException {
578 String methodCall = "setNString(" + parameterIndex + ", " + value + ")";
579 argTraceSet(parameterIndex, "(String)", value);
580 try
581 {
582 realPreparedStatement.setNString(parameterIndex, value);
583 }
584 catch (SQLException s)
585 {
586 reportException(methodCall, s);
587 throw s;
588 }
589 reportReturn(methodCall);
590 }
591
592 public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException {
593 String methodCall = "setNCharacterStream(" + parameterIndex + ", " + value + ", " + length + ")";
594 argTraceSet(parameterIndex, "(Reader)", "<Reader of length " + length + ">");
595 try
596 {
597 realPreparedStatement.setNCharacterStream(parameterIndex, value, length);
598 }
599 catch (SQLException s)
600 {
601 reportException(methodCall, s);
602 throw s;
603 }
604 reportReturn(methodCall);
605 }
606
607 public void setNClob(int parameterIndex, NClob value) throws SQLException {
608 String methodCall = "setNClob(" + parameterIndex + ", " + value + ")";
609 argTraceSet(parameterIndex, "(NClob)", "<NClob>");
610 try
611 {
612 realPreparedStatement.setNClob(parameterIndex, value);
613 }
614 catch (SQLException s)
615 {
616 reportException(methodCall, s);
617 throw s;
618 }
619 reportReturn(methodCall);
620 }
621
622 public void setClob(int parameterIndex, Reader reader, long length) throws SQLException {
623 String methodCall = "setClob(" + parameterIndex + ", " + reader + ", " + length + ")";
624 argTraceSet(parameterIndex, "(Reader)", "<Reader of length " + length + ">");
625 try
626 {
627 realPreparedStatement.setClob(parameterIndex, reader, length);
628 }
629 catch (SQLException s)
630 {
631 reportException(methodCall, s);
632 throw s;
633 }
634 reportReturn(methodCall);
635 }
636
637 public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException {
638 String methodCall = "setBlob(" + parameterIndex + ", " + inputStream + ", " + length + ")";
639 argTraceSet(parameterIndex, "(InputStream)", "<InputStream of length " + length + ">");
640 try
641 {
642 realPreparedStatement.setBlob(parameterIndex, inputStream, length);
643 }
644 catch (SQLException s)
645 {
646 reportException(methodCall, s);
647 throw s;
648 }
649 reportReturn(methodCall);
650 }
651
652 public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException {
653 String methodCall = "setNClob(" + parameterIndex + ", " + reader + ", " + length + ")";
654 argTraceSet(parameterIndex, "(Reader)", "<Reader of length " + length + ">");
655 try
656 {
657 realPreparedStatement.setNClob(parameterIndex, reader, length);
658 }
659 catch (SQLException s)
660 {
661 reportException(methodCall, s);
662 throw s;
663 }
664 reportReturn(methodCall);
665 }
666
667 public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException {
668 String methodCall = "setSQLXML(" + parameterIndex + ", " + xmlObject + ")";
669 argTraceSet(parameterIndex, "(SQLXML)", xmlObject);
670 try
671 {
672 realPreparedStatement.setSQLXML(parameterIndex, xmlObject);
673 }
674 catch (SQLException s)
675 {
676 reportException(methodCall, s);
677 throw s;
678 }
679 reportReturn(methodCall);
680 }
681
682 public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException
683 {
684 String methodCall = "setDate(" + parameterIndex + ", " + x + ", " + cal + ")";
685 argTraceSet(parameterIndex, "(Date)", x);
686
687 try
688 {
689 realPreparedStatement.setDate(parameterIndex, x, cal);
690 }
691 catch (SQLException s)
692 {
693 reportException(methodCall, s);
694 throw s;
695 }
696 reportReturn(methodCall);
697 }
698
699 public ResultSet executeQuery() throws SQLException
700 {
701 String methodCall = "executeQuery()";
702 String dumpedSql = dumpedSql();
703 reportSql(dumpedSql, methodCall);
704 long tstart = System.currentTimeMillis();
705 try
706 {
707 ResultSet r = realPreparedStatement.executeQuery();
708 reportSqlTiming(System.currentTimeMillis() - tstart, dumpedSql, methodCall);
709 ResultSetSpy rsp = new ResultSetSpy(this, r);
710 return (ResultSet) reportReturn(methodCall, rsp);
711 }
712 catch (SQLException s)
713 {
714 reportException(methodCall, s, dumpedSql, System.currentTimeMillis() - tstart);
715 throw s;
716 }
717 }
718
719 private String getTypeHelp(Object x)
720 {
721 if (x==null)
722 {
723 return "(null)";
724 }
725 else
726 {
727 return "(" + x.getClass().getName() + ")";
728 }
729 }
730
731 public void setObject(int parameterIndex, Object x, int targetSqlType, int scale) throws SQLException
732 {
733 String methodCall = "setObject(" + parameterIndex + ", " + x + ", " + targetSqlType + ", " + scale + ")";
734 argTraceSet(parameterIndex, getTypeHelp(x), x);
735
736 try
737 {
738 realPreparedStatement.setObject(parameterIndex, x, targetSqlType, scale);
739 }
740 catch (SQLException s)
741 {
742 reportException(methodCall, s);
743 throw s;
744 }
745 reportReturn(methodCall);
746 }
747
748 /**
749 * Sets the designated parameter to the given input stream, which will have
750 * the specified number of bytes.
751 * When a very large ASCII value is input to a <code>LONGVARCHAR</code>
752 * parameter, it may be more practical to send it via a
753 * <code>java.io.InputStream</code>. Data will be read from the stream
754 * as needed until end-of-file is reached. The JDBC driver will
755 * do any necessary conversion from ASCII to the database char format.
756 * <p/>
757 * <P><B>Note:</B> This stream object can either be a standard
758 * Java stream object or your own subclass that implements the
759 * standard interface.
760 *
761 * @param parameterIndex the first parameter is 1, the second is 2, ...
762 * @param x the Java input stream that contains the ASCII parameter value
763 * @param length the number of bytes in the stream
764 * @throws java.sql.SQLException if parameterIndex does not correspond to a parameter
765 * marker in the SQL statement; if a database access error occurs or
766 * this method is called on a closed <code>PreparedStatement</code>
767 * @since 1.6
768 */
769 public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException {
770 String methodCall = "setAsciiStream(" + parameterIndex + ", " + x + ", " + length + ")";
771 argTraceSet(parameterIndex, "(Ascii InputStream)", "<Ascii InputStream of length " + length + ">");
772 try
773 {
774 realPreparedStatement.setAsciiStream(parameterIndex, x, length);
775 }
776 catch (SQLException s)
777 {
778 reportException(methodCall, s);
779 throw s;
780 }
781 reportReturn(methodCall);
782 }
783
784 public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException {
785 String methodCall = "setBinaryStream(" + parameterIndex + ", " + x + ", " + length + ")";
786 argTraceSet(parameterIndex, "(Binary InputStream)", "<Binary InputStream of length " + length + ">");
787 try
788 {
789 realPreparedStatement.setBinaryStream(parameterIndex, x, length);
790 }
791 catch (SQLException s)
792 {
793 reportException(methodCall, s);
794 throw s;
795 }
796 reportReturn(methodCall);
797 }
798
799 public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException {
800 String methodCall = "setCharacterStream(" + parameterIndex + ", " + reader + ", " + length + ")";
801 argTraceSet(parameterIndex, "(Reader)", "<Reader of length " + length + ">");
802 try
803 {
804 realPreparedStatement.setCharacterStream(parameterIndex, reader, length);
805 }
806 catch (SQLException s)
807 {
808 reportException(methodCall, s);
809 throw s;
810 }
811 reportReturn(methodCall);
812
813 }
814
815 public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException {
816 String methodCall = "setAsciiStream(" + parameterIndex + ", " + x + ")";
817 argTraceSet(parameterIndex, "(Ascii InputStream)", "<Ascii InputStream>");
818 try
819 {
820 realPreparedStatement.setAsciiStream(parameterIndex, x);
821 }
822 catch (SQLException s)
823 {
824 reportException(methodCall, s);
825 throw s;
826 }
827 reportReturn(methodCall);
828 }
829
830 public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException {
831 String methodCall = "setBinaryStream(" + parameterIndex + ", " + x + ")";
832 argTraceSet(parameterIndex, "(Binary InputStream)", "<Binary InputStream>");
833 try
834 {
835 realPreparedStatement.setBinaryStream(parameterIndex, x);
836 }
837 catch (SQLException s)
838 {
839 reportException(methodCall, s);
840 throw s;
841 }
842 reportReturn(methodCall);
843
844 }
845
846 public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException {
847 String methodCall = "setCharacterStream(" + parameterIndex + ", " + reader + ")";
848 argTraceSet(parameterIndex, "(Reader)", "<Reader>");
849 try
850 {
851 realPreparedStatement.setCharacterStream(parameterIndex, reader);
852 }
853 catch (SQLException s)
854 {
855 reportException(methodCall, s);
856 throw s;
857 }
858 reportReturn(methodCall);
859 }
860
861 public void setNCharacterStream(int parameterIndex, Reader reader) throws SQLException {
862 String methodCall = "setNCharacterStream(" + parameterIndex + ", " + reader + ")";
863 argTraceSet(parameterIndex, "(Reader)", "<Reader>");
864 try
865 {
866 realPreparedStatement.setNCharacterStream(parameterIndex, reader);
867 }
868 catch (SQLException s)
869 {
870 reportException(methodCall, s);
871 throw s;
872 }
873 reportReturn(methodCall);
874 }
875
876 public void setClob(int parameterIndex, Reader reader) throws SQLException {
877 String methodCall = "setClob(" + parameterIndex + ", " + reader + ")";
878 argTraceSet(parameterIndex, "(Reader)", "<Reader>");
879 try
880 {
881 realPreparedStatement.setClob(parameterIndex, reader);
882 }
883 catch (SQLException s)
884 {
885 reportException(methodCall, s);
886 throw s;
887 }
888 reportReturn(methodCall);
889 }
890
891 public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException {
892 String methodCall = "setBlob(" + parameterIndex + ", " + inputStream + ")";
893 argTraceSet(parameterIndex, "(InputStream)", "<InputStream>");
894 try
895 {
896 realPreparedStatement.setBlob(parameterIndex, inputStream);
897 }
898 catch (SQLException s)
899 {
900 reportException(methodCall, s);
901 throw s;
902 }
903 reportReturn(methodCall);
904 }
905
906 public void setNClob(int parameterIndex, Reader reader) throws SQLException {
907 String methodCall = "setNClob(" + parameterIndex + ", " + reader + ")";
908 argTraceSet(parameterIndex, "(Reader)", "<Reader>");
909 try
910 {
911 realPreparedStatement.setNClob(parameterIndex, reader);
912 }
913 catch (SQLException s)
914 {
915 reportException(methodCall, s);
916 throw s;
917 }
918 reportReturn(methodCall);
919
920 }
921
922 public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException
923 {
924 String methodCall = "setObject(" + parameterIndex + ", " + x + ", " + targetSqlType + ")";
925 argTraceSet(parameterIndex, getTypeHelp(x), x);
926 try
927 {
928 realPreparedStatement.setObject(parameterIndex, x, targetSqlType);
929 }
930 catch (SQLException s)
931 {
932 reportException(methodCall, s);
933 throw s;
934 }
935 reportReturn(methodCall);
936 }
937
938 public void setObject(int parameterIndex, Object x) throws SQLException
939 {
940 String methodCall = "setObject(" + parameterIndex + ", " + x + ")";
941 argTraceSet(parameterIndex, getTypeHelp(x), x);
942 try
943 {
944 realPreparedStatement.setObject(parameterIndex, x);
945 }
946 catch (SQLException s)
947 {
948 reportException(methodCall, s);
949 throw s;
950 }
951 reportReturn(methodCall);
952 }
953
954 public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException
955 {
956 String methodCall = "setTimestamp(" + parameterIndex + ", " + x + ")";
957 argTraceSet(parameterIndex, "(Date)", x);
958 try
959 {
960 realPreparedStatement.setTimestamp(parameterIndex, x);
961 }
962 catch (SQLException s)
963 {
964 reportException(methodCall, s);
965 throw s;
966 }
967 reportReturn(methodCall);
968 }
969
970 public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException
971 {
972 String methodCall = "setTimestamp(" + parameterIndex + ", " + x + ", " + cal + ")";
973 argTraceSet(parameterIndex, "(Timestamp)", x);
974 try
975 {
976 realPreparedStatement.setTimestamp(parameterIndex, x, cal);
977 }
978 catch (SQLException s)
979 {
980 reportException(methodCall, s);
981 throw s;
982 }
983 reportReturn(methodCall);
984 }
985
986 public int executeUpdate() throws SQLException
987 {
988 String methodCall = "executeUpdate()";
989 String dumpedSql = dumpedSql();
990 reportSql(dumpedSql, methodCall);
991 long tstart = System.currentTimeMillis();
992 try
993 {
994 int result = realPreparedStatement.executeUpdate();
995 reportSqlTiming(System.currentTimeMillis() - tstart, dumpedSql, methodCall);
996 return reportReturn(methodCall, result);
997 }
998 catch (SQLException s)
999 {
1000 reportException(methodCall, s, dumpedSql, System.currentTimeMillis() - tstart);
1001 throw s;
1002 }
1003 }
1004
1005 public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException
1006 {
1007 String methodCall = "setAsciiStream(" + parameterIndex + ", " + x + ", " + length + ")";
1008 argTraceSet(parameterIndex, "(Ascii InputStream)", "<Ascii InputStream of length " + length + ">");
1009 try
1010 {
1011 realPreparedStatement.setAsciiStream(parameterIndex, x, length);
1012 }
1013 catch (SQLException s)
1014 {
1015 reportException(methodCall, s);
1016 throw s;
1017 }
1018 reportReturn(methodCall);
1019 }
1020
1021 public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException
1022 {
1023 String methodCall = "setBinaryStream(" + parameterIndex + ", " + x + ", " + length + ")";
1024 argTraceSet(parameterIndex, "(Binary InputStream)", "<Binary InputStream of length " + length + ">");
1025 try
1026 {
1027 realPreparedStatement.setBinaryStream(parameterIndex, x, length);
1028 }
1029 catch (SQLException s)
1030 {
1031 reportException(methodCall, s);
1032 throw s;
1033 }
1034 reportReturn(methodCall);
1035 }
1036
1037 public void clearParameters() throws SQLException
1038 {
1039 String methodCall = "clearParameters()";
1040
1041 synchronized (argTrace)
1042 {
1043 argTrace.clear();
1044 }
1045
1046 try
1047 {
1048 realPreparedStatement.clearParameters();
1049 }
1050 catch (SQLException s)
1051 {
1052 reportException(methodCall, s);
1053 throw s;
1054 }
1055 reportReturn(methodCall);
1056 }
1057
1058 public ResultSetMetaData getMetaData() throws SQLException
1059 {
1060 String methodCall = "getMetaData()";
1061 try
1062 {
1063 return (ResultSetMetaData) reportReturn(methodCall, realPreparedStatement.getMetaData());
1064 }
1065 catch (SQLException s)
1066 {
1067 reportException(methodCall, s);
1068 throw s;
1069 }
1070 }
1071
1072 public void addBatch() throws SQLException
1073 {
1074 String methodCall = "addBatch()";
1075 currentBatch.add(dumpedSql());
1076 try
1077 {
1078 realPreparedStatement.addBatch();
1079 }
1080 catch (SQLException s)
1081 {
1082 reportException(methodCall, s);
1083 throw s;
1084 }
1085 reportReturn(methodCall);
1086 }
1087
1088 public <T> T unwrap(Class<T> iface) throws SQLException {
1089 String methodCall = "unwrap(" + (iface==null?"null":iface.getName()) + ")";
1090 try
1091 {
1092 //todo: double check this logic
1093 //NOTE: could call super.isWrapperFor to simplify this logic, but it would result in extra log output
1094 //because the super classes would be invoked, thus executing their logging methods too...
1095 return (T)reportReturn(methodCall,
1096 (iface != null && (iface==PreparedStatement.class||iface==Statement.class||iface==Spy.class))?
1097 (T)this:
1098 realPreparedStatement.unwrap(iface));
1099 }
1100 catch (SQLException s)
1101 {
1102 reportException(methodCall,s);
1103 throw s;
1104 }
1105 }
1106
1107 public boolean isWrapperFor(Class<?> iface) throws SQLException
1108 {
1109 String methodCall = "isWrapperFor(" + (iface==null?"null":iface.getName()) + ")";
1110 try
1111 {
1112 //NOTE: could call super.isWrapperFor to simplify this logic, but it would result in extra log output
1113 //when the super classes would be invoked..
1114 return reportReturn(methodCall,
1115 (iface != null && (iface==PreparedStatement.class||iface==Statement.class||iface==Spy.class)) ||
1116 realPreparedStatement.isWrapperFor(iface));
1117 }
1118 catch (SQLException s)
1119 {
1120 reportException(methodCall,s);
1121 throw s;
1122 }
1123 }
1124
1125 }