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