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.sql.Connection;
019 import java.sql.ResultSet;
020 import java.sql.SQLException;
021 import java.sql.SQLWarning;
022 import java.sql.Statement;
023 import java.util.List;
024 import java.util.ArrayList;
025
026 /**
027 * Wraps a Statement and reports method calls, returns and exceptions.
028 *
029 * @author Arthur Blake
030 */
031 public class StatementSpy implements Statement, Spy
032 {
033 private final SpyLogDelegator log;
034
035 /**
036 * The Connection that created this Statement.
037 */
038 protected ConnectionSpy connectionSpy;
039
040 /**
041 * The real statement that this StatementSpy wraps.
042 */
043 protected Statement realStatement;
044
045 /**
046 * Create a StatementSpy that wraps another Statement, for the purpose of logging all method calls, sql,
047 * exceptions and return values.
048 *
049 * @param connectionSpy Connection that created this Statement.
050 * @param realStatement real underlying Statement that this StatementSpy wraps.
051 */
052 public StatementSpy(ConnectionSpy connectionSpy, Statement realStatement)
053 {
054 if (realStatement == null)
055 {
056 throw new IllegalArgumentException("Must pass in a non null real Statement");
057 }
058 if (connectionSpy == null)
059 {
060 throw new IllegalArgumentException("Must pass in a non null ConnectionSpy");
061 }
062 this.realStatement = realStatement;
063 this.connectionSpy = connectionSpy;
064
065 log = SpyLogFactory.getSpyLogDelegator();
066 }
067
068 public String getClassType()
069 {
070 return "Statement";
071 }
072
073 public int getConnectionNumber()
074 {
075 return connectionSpy.getConnectionNumber();
076 }
077
078 /**
079 * Report an exception to be logged which includes timing data on a sql failure.
080 * @param methodCall description of method call and arguments passed to it that generated the exception.
081 * @param exception exception that was generated
082 * @param sql SQL associated with the call.
083 * @param execTime amount of time that the jdbc driver was chugging on the SQL before it threw an exception.
084 */
085 protected void reportException(String methodCall, SQLException exception, String sql, long execTime)
086 {
087 log.exceptionOccured(this, methodCall, exception, sql, execTime);
088 }
089
090 /**
091 * Report an exception to be logged.
092 * @param methodCall description of method call and arguments passed to it that generated the exception.
093 * @param exception exception that was generated
094 * @param sql SQL associated with the call.
095 */
096 protected void reportException(String methodCall, SQLException exception, String sql)
097 {
098 log.exceptionOccured(this, methodCall, exception, sql, -1L);
099 }
100
101 /**
102 * Report an exception to be logged.
103 *
104 * @param methodCall description of method call and arguments passed to it that generated the exception.
105 * @param exception exception that was generated
106 */
107 protected void reportException(String methodCall, SQLException exception)
108 {
109 log.exceptionOccured(this, methodCall, exception, null, -1L);
110 }
111
112 /**
113 * Report (for logging) that a method returned. All the other reportReturn methods are conveniance methods that call this method.
114 *
115 * @param methodCall description of method call and arguments passed to it that returned.
116 * @param msg description of what the return value that was returned. may be an empty String for void return types.
117 */
118 protected void reportAllReturns(String methodCall, String msg)
119 {
120 log.methodReturned(this, methodCall, msg);
121 }
122
123 /**
124 * Conveniance method to report (for logging) that a method returned a boolean value.
125 *
126 * @param methodCall description of method call and arguments passed to it that returned.
127 * @param value boolean return value.
128 * @return the boolean return value as passed in.
129 */
130 protected boolean reportReturn(String methodCall, boolean value)
131 {
132 reportAllReturns(methodCall, "" + value);
133 return value;
134 }
135
136 /**
137 * Conveniance method to report (for logging) that a method returned a byte value.
138 *
139 * @param methodCall description of method call and arguments passed to it that returned.
140 * @param value byte return value.
141 * @return the byte return value as passed in.
142 */
143 protected byte reportReturn(String methodCall, byte value)
144 {
145 reportAllReturns(methodCall, "" + value);
146 return value;
147 }
148
149 /**
150 * Conveniance method to report (for logging) that a method returned a int value.
151 *
152 * @param methodCall description of method call and arguments passed to it that returned.
153 * @param value int return value.
154 * @return the int return value as passed in.
155 */
156 protected int reportReturn(String methodCall, int value)
157 {
158 reportAllReturns(methodCall, "" + value);
159 return value;
160 }
161
162 /**
163 * Conveniance method to report (for logging) that a method returned a double value.
164 *
165 * @param methodCall description of method call and arguments passed to it that returned.
166 * @param value double return value.
167 * @return the double return value as passed in.
168 */
169 protected double reportReturn(String methodCall, double value)
170 {
171 reportAllReturns(methodCall, "" + value);
172 return value;
173 }
174
175 /**
176 * Conveniance method to report (for logging) that a method returned a short value.
177 *
178 * @param methodCall description of method call and arguments passed to it that returned.
179 * @param value short return value.
180 * @return the short return value as passed in.
181 */
182 protected short reportReturn(String methodCall, short value)
183 {
184 reportAllReturns(methodCall, "" + value);
185 return value;
186 }
187
188 /**
189 * Conveniance method to report (for logging) that a method returned a long value.
190 *
191 * @param methodCall description of method call and arguments passed to it that returned.
192 * @param value long return value.
193 * @return the long return value as passed in.
194 */
195 protected long reportReturn(String methodCall, long value)
196 {
197 reportAllReturns(methodCall, "" + value);
198 return value;
199 }
200
201 /**
202 * Conveniance method to report (for logging) that a method returned a float value.
203 *
204 * @param methodCall description of method call and arguments passed to it that returned.
205 * @param value float return value.
206 * @return the float return value as passed in.
207 */
208 protected float reportReturn(String methodCall, float value)
209 {
210 reportAllReturns(methodCall, "" + value);
211 return value;
212 }
213
214 /**
215 * Conveniance method to report (for logging) that a method returned an Object.
216 *
217 * @param methodCall description of method call and arguments passed to it that returned.
218 * @param value return Object.
219 * @return the return Object as passed in.
220 */
221 protected Object reportReturn(String methodCall, Object value)
222 {
223 reportAllReturns(methodCall, "" + value);
224 return value;
225 }
226
227 /**
228 * Conveniance method to report (for logging) that a method returned (void return type).
229 *
230 * @param methodCall description of method call and arguments passed to it that returned.
231 */
232 protected void reportReturn(String methodCall)
233 {
234 reportAllReturns(methodCall, "");
235 }
236
237 /**
238 * Running one-off statement sql is generally inefficient and a bad idea for various reasons,
239 * so give a warning when this is done.
240 */
241 private static final String StatementSqlWarning = "{WARNING: Statement used to run SQL} ";
242
243 /**
244 * Report SQL for logging with a warning that it was generated from a statement.
245 *
246 * @param sql the SQL being run
247 * @param methodCall the name of the method that was running the SQL
248 */
249 protected void reportStatementSql(String sql, String methodCall)
250 {
251 // redirect to one more method call ONLY so that stack trace search is consistent
252 // with the reportReturn calls
253 _reportSql(StatementSqlWarning + sql, methodCall);
254 }
255
256 /**
257 * Report SQL for logging with a warning that it was generated from a statement.
258 *
259 * @param execTime execution time in msec.
260 * @param sql the SQL being run
261 * @param methodCall the name of the method that was running the SQL
262 */
263 protected void reportStatementSqlTiming(long execTime, String sql, String methodCall)
264 {
265 // redirect to one more method call ONLY so that stack trace search is consistent
266 // with the reportReturn calls
267 _reportSqlTiming(execTime, StatementSqlWarning + sql, methodCall);
268 }
269
270 /**
271 * Report SQL for logging.
272 *
273 * @param execTime execution time in msec.
274 * @param sql the SQL being run
275 * @param methodCall the name of the method that was running the SQL
276 */
277 protected void reportSqlTiming(long execTime, String sql, String methodCall)
278 {
279 // redirect to one more method call ONLY so that stack trace search is consistent
280 // with the reportReturn calls
281 _reportSqlTiming(execTime, sql, methodCall);
282 }
283
284 /**
285 * Report SQL for logging.
286 *
287 * @param sql the SQL being run
288 * @param methodCall the name of the method that was running the SQL
289 */
290 protected void reportSql(String sql, String methodCall)
291 {
292 // redirect to one more method call ONLY so that stack trace search is consistent
293 // with the reportReturn calls
294 _reportSql(sql, methodCall);
295 }
296
297 private void _reportSql(String sql, String methodCall)
298 {
299 log.sqlOccured(this, methodCall, sql);
300 }
301
302 private void _reportSqlTiming(long execTime, String sql, String methodCall)
303 {
304 log.sqlTimingOccured(this, execTime, methodCall, sql);
305 }
306
307 // implementation of interface methods
308 public SQLWarning getWarnings() throws SQLException
309 {
310 String methodCall = "getWarnings()";
311 try
312 {
313 return (SQLWarning) reportReturn(methodCall, realStatement.getWarnings());
314 }
315 catch (SQLException s)
316 {
317 reportException(methodCall, s);
318 throw s;
319 }
320 }
321
322 public int executeUpdate(String sql, String[] columnNames) throws SQLException
323 {
324 String methodCall = "executeUpdate(" + sql + ", " + columnNames + ")";
325 reportStatementSql(sql, methodCall);
326 long tstart = System.currentTimeMillis();
327 try
328 {
329 int result = realStatement.executeUpdate(sql, columnNames);
330 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
331 return reportReturn(methodCall, result);
332 }
333 catch (SQLException s)
334 {
335 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
336 throw s;
337 }
338 }
339
340 public boolean execute(String sql, String[] columnNames) throws SQLException
341 {
342 String methodCall = "execute(" + sql + ", " + columnNames + ")";
343 reportStatementSql(sql, methodCall);
344 long tstart = System.currentTimeMillis();
345 try
346 {
347 boolean result = realStatement.execute(sql, columnNames);
348 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
349 return reportReturn(methodCall, result);
350 }
351 catch (SQLException s)
352 {
353 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
354 throw s;
355 }
356 }
357
358 public void setMaxRows(int max) throws SQLException
359 {
360 String methodCall = "setMaxRows(" + max + ")";
361 try
362 {
363 realStatement.setMaxRows(max);
364 }
365 catch (SQLException s)
366 {
367 reportException(methodCall, s);
368 throw s;
369 }
370 reportReturn(methodCall);
371 }
372
373 public boolean getMoreResults() throws SQLException
374 {
375 String methodCall = "getMoreResults()";
376
377 try
378 {
379 return reportReturn(methodCall, realStatement.getMoreResults());
380 }
381 catch (SQLException s)
382 {
383 reportException(methodCall, s);
384 throw s;
385 }
386 }
387
388 public void clearWarnings() throws SQLException
389 {
390 String methodCall = "clearWarnings()";
391 try
392 {
393 realStatement.clearWarnings();
394 }
395 catch (SQLException s)
396 {
397 reportException(methodCall, s);
398 throw s;
399 }
400 reportReturn(methodCall);
401 }
402
403 /**
404 * Tracking of current batch (see addBatch, clearBatch and executeBatch)
405 * //todo: should access to this List be synchronized?
406 */
407 protected List currentBatch = new ArrayList();
408
409 public void addBatch(String sql) throws SQLException
410 {
411 String methodCall = "addBatch(" + sql + ")";
412
413 currentBatch.add(StatementSqlWarning + sql);
414 try
415 {
416 realStatement.addBatch(sql);
417 }
418 catch (SQLException s)
419 {
420 reportException(methodCall,s);
421 throw s;
422 }
423 reportReturn(methodCall);
424 }
425
426 public int getResultSetType() throws SQLException
427 {
428 String methodCall = "getResultSetType()";
429 try
430 {
431 return reportReturn(methodCall, realStatement.getResultSetType());
432 }
433 catch (SQLException s)
434 {
435 reportException(methodCall, s);
436 throw s;
437 }
438 }
439
440 public void clearBatch() throws SQLException
441 {
442 String methodCall = "clearBatch()";
443 try
444 {
445 realStatement.clearBatch();
446 }
447 catch (SQLException s)
448 {
449 reportException(methodCall, s);
450 throw s;
451 }
452 currentBatch.clear();
453 reportReturn(methodCall);
454 }
455
456 public void setFetchDirection(int direction) throws SQLException
457 {
458 String methodCall = "setFetchDirection(" + direction + ")";
459 try
460 {
461 realStatement.setFetchDirection(direction);
462 }
463 catch (SQLException s)
464 {
465 reportException(methodCall, s);
466 throw s;
467 }
468 reportReturn(methodCall);
469 }
470
471 public int[] executeBatch() throws SQLException
472 {
473 String methodCall = "executeBatch()";
474
475 int j=currentBatch.size();
476 StringBuffer batchReport = new StringBuffer("batching " + j + " statements:");
477
478 int fieldSize = (""+j).length();
479
480 String sql;
481 for (int i=0; i < j;)
482 {
483 sql = (String) currentBatch.get(i);
484 batchReport.append("\n");
485 batchReport.append(Utilities.rightJustify(fieldSize,""+(++i)));
486 batchReport.append(": ");
487 batchReport.append(sql);
488 }
489
490 sql = batchReport.toString();
491 reportSql(sql, methodCall);
492 long tstart = System.currentTimeMillis();
493
494 int[] updateResults;
495 try
496 {
497 updateResults = realStatement.executeBatch();
498 reportSqlTiming(System.currentTimeMillis()-tstart, sql, methodCall);
499 }
500 catch (SQLException s)
501 {
502 reportException(methodCall, s, sql, System.currentTimeMillis()-tstart);
503 throw s;
504 }
505 return (int[])reportReturn(methodCall,updateResults);
506 }
507
508 public void setFetchSize(int rows) throws SQLException
509 {
510 String methodCall = "setFetchSize(" + rows + ")";
511 try
512 {
513 realStatement.setFetchSize(rows);
514 }
515 catch (SQLException s)
516 {
517 reportException(methodCall, s);
518 throw s;
519 }
520 reportReturn(methodCall);
521 }
522
523 public int getQueryTimeout() throws SQLException
524 {
525 String methodCall = "getQueryTimeout()";
526 try
527 {
528 return reportReturn(methodCall, realStatement.getQueryTimeout());
529 }
530 catch (SQLException s)
531 {
532 reportException(methodCall, s);
533 throw s;
534 }
535 }
536
537 public Connection getConnection() throws SQLException
538 {
539 String methodCall = "getConnection()";
540 return (Connection) reportReturn(methodCall, connectionSpy);
541 }
542
543 public ResultSet getGeneratedKeys() throws SQLException
544 {
545 String methodCall = "getGeneratedKeys()";
546 try
547 {
548 ResultSet r = realStatement.getGeneratedKeys();
549 if (r == null)
550 {
551 return (ResultSet) reportReturn(methodCall, r);
552 }
553 else
554 {
555 return (ResultSet) reportReturn(methodCall, new ResultSetSpy(this, r));
556 }
557 }
558 catch (SQLException s)
559 {
560 reportException(methodCall, s);
561 throw s;
562 }
563 }
564
565 public void setEscapeProcessing(boolean enable) throws SQLException
566 {
567 String methodCall = "setEscapeProcessing(" + enable + ")";
568 try
569 {
570 realStatement.setEscapeProcessing(enable);
571 }
572 catch (SQLException s)
573 {
574 reportException(methodCall, s);
575 throw s;
576 }
577 reportReturn(methodCall);
578 }
579
580 public int getFetchDirection() throws SQLException
581 {
582 String methodCall = "getFetchDirection()";
583 try
584 {
585 return reportReturn(methodCall, realStatement.getFetchDirection());
586 }
587 catch (SQLException s)
588 {
589 reportException(methodCall, s);
590 throw s;
591 }
592 }
593
594 public void setQueryTimeout(int seconds) throws SQLException
595 {
596 String methodCall = "setQueryTimeout(" + seconds + ")";
597 try
598 {
599 realStatement.setQueryTimeout(seconds);
600 }
601 catch (SQLException s)
602 {
603 reportException(methodCall, s);
604 throw s;
605 }
606 reportReturn(methodCall);
607 }
608
609 public boolean getMoreResults(int current) throws SQLException
610 {
611 String methodCall = "getMoreResults(" + current + ")";
612
613 try
614 {
615 return reportReturn(methodCall, realStatement.getMoreResults(current));
616 }
617 catch (SQLException s)
618 {
619 reportException(methodCall, s);
620 throw s;
621 }
622 }
623
624 public ResultSet executeQuery(String sql) throws SQLException
625 {
626 String methodCall = "executeQuery(" + sql + ")";
627 reportStatementSql(sql, methodCall);
628 long tstart = System.currentTimeMillis();
629 try
630 {
631 ResultSet result = realStatement.executeQuery(sql);
632 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
633 ResultSetSpy r = new ResultSetSpy(this, result);
634 return (ResultSet) reportReturn(methodCall, r);
635 }
636 catch (SQLException s)
637 {
638 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
639 throw s;
640 }
641 }
642
643 public int getMaxFieldSize() throws SQLException
644 {
645 String methodCall = "getMaxFieldSize()";
646 try
647 {
648 return reportReturn(methodCall, realStatement.getMaxFieldSize());
649 }
650 catch (SQLException s)
651 {
652 reportException(methodCall, s);
653 throw s;
654 }
655 }
656
657 public int executeUpdate(String sql) throws SQLException
658 {
659 String methodCall = "executeUpdate(" + sql + ")";
660 reportStatementSql(sql, methodCall);
661 long tstart = System.currentTimeMillis();
662 try
663 {
664 int result = realStatement.executeUpdate(sql);
665 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
666 return reportReturn(methodCall, result);
667 }
668 catch (SQLException s)
669 {
670 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
671 throw s;
672 }
673 }
674
675 public void cancel() throws SQLException
676 {
677 String methodCall = "cancel()";
678 try
679 {
680 realStatement.cancel();
681 }
682 catch (SQLException s)
683 {
684 reportException(methodCall, s);
685 throw s;
686 }
687 reportReturn(methodCall);
688 }
689
690 public void setCursorName(String name) throws SQLException
691 {
692 String methodCall = "setCursorName(" + name + ")";
693 try
694 {
695 realStatement.setCursorName(name);
696 }
697 catch (SQLException s)
698 {
699 reportException(methodCall, s);
700 throw s;
701 }
702 reportReturn(methodCall);
703 }
704
705 public int getFetchSize() throws SQLException
706 {
707 String methodCall = "getFetchSize()";
708 try
709 {
710 return reportReturn(methodCall, realStatement.getFetchSize());
711 }
712 catch (SQLException s)
713 {
714 reportException(methodCall, s);
715 throw s;
716 }
717 }
718
719 public int getResultSetConcurrency() throws SQLException
720 {
721 String methodCall = "getResultSetConcurrency()";
722 try
723 {
724 return reportReturn(methodCall, realStatement.getResultSetConcurrency());
725 }
726 catch (SQLException s)
727 {
728 reportException(methodCall, s);
729 throw s;
730 }
731 }
732
733 public int getResultSetHoldability() throws SQLException
734 {
735 String methodCall = "getResultSetHoldability()";
736 try
737 {
738 return reportReturn(methodCall, realStatement.getResultSetHoldability());
739 }
740 catch (SQLException s)
741 {
742 reportException(methodCall, s);
743 throw s;
744 }
745 }
746
747 public void setMaxFieldSize(int max) throws SQLException
748 {
749 String methodCall = "setMaxFieldSize(" + max + ")";
750 try
751 {
752 realStatement.setMaxFieldSize(max);
753 }
754 catch (SQLException s)
755 {
756 reportException(methodCall, s);
757 throw s;
758 }
759 reportReturn(methodCall);
760 }
761
762 public boolean execute(String sql) throws SQLException
763 {
764 String methodCall = "execute(" + sql + ")";
765 reportStatementSql(sql, methodCall);
766 long tstart = System.currentTimeMillis();
767 try
768 {
769 boolean result = realStatement.execute(sql);
770 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
771 return reportReturn(methodCall, result);
772 }
773 catch (SQLException s)
774 {
775 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
776 throw s;
777 }
778 }
779
780 public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException
781 {
782 String methodCall = "executeUpdate(" + sql + ", " + autoGeneratedKeys + ")";
783 reportStatementSql(sql, methodCall);
784 long tstart = System.currentTimeMillis();
785 try
786 {
787 int result = realStatement.executeUpdate(sql, autoGeneratedKeys);
788 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
789 return reportReturn(methodCall, result);
790 }
791 catch (SQLException s)
792 {
793 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
794 throw s;
795 }
796 }
797
798 public boolean execute(String sql, int autoGeneratedKeys) throws SQLException
799 {
800 String methodCall = "execute(" + sql + ", " + autoGeneratedKeys + ")";
801 reportStatementSql(sql, methodCall);
802 long tstart = System.currentTimeMillis();
803 try
804 {
805 boolean result = realStatement.execute(sql, autoGeneratedKeys);
806 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
807 return reportReturn(methodCall, result);
808 }
809 catch (SQLException s)
810 {
811 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
812 throw s;
813 }
814 }
815
816 public int executeUpdate(String sql, int[] columnIndexes) throws SQLException
817 {
818 String methodCall = "executeUpdate(" + sql + ", " + columnIndexes + ")";
819 reportStatementSql(sql, methodCall);
820 long tstart = System.currentTimeMillis();
821 try
822 {
823 int result = realStatement.executeUpdate(sql, columnIndexes);
824 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
825 return reportReturn(methodCall, result);
826 }
827 catch (SQLException s)
828 {
829 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
830 throw s;
831 }
832 }
833
834 public boolean execute(String sql, int[] columnIndexes) throws SQLException
835 {
836 String methodCall = "execute(" + sql + ", " + columnIndexes + ")";
837 reportStatementSql(sql, methodCall);
838 long tstart = System.currentTimeMillis();
839 try
840 {
841 boolean result = realStatement.execute(sql, columnIndexes);
842 reportStatementSqlTiming(System.currentTimeMillis() - tstart, sql, methodCall);
843 return reportReturn(methodCall, result);
844 }
845 catch (SQLException s)
846 {
847 reportException(methodCall, s, sql, System.currentTimeMillis() - tstart);
848 throw s;
849 }
850 }
851
852 public ResultSet getResultSet() throws SQLException
853 {
854 String methodCall = "getResultSet()";
855 try
856 {
857 ResultSet r = realStatement.getResultSet();
858 if (r == null)
859 {
860 return (ResultSet) reportReturn(methodCall, r);
861 }
862 else
863 {
864 return (ResultSet) reportReturn(methodCall, new ResultSetSpy(this, r));
865 }
866 }
867 catch (SQLException s)
868 {
869 reportException(methodCall, s);
870 throw s;
871 }
872 }
873
874 public int getMaxRows() throws SQLException
875 {
876 String methodCall = "getMaxRows()";
877 try
878 {
879 return reportReturn(methodCall, realStatement.getMaxRows());
880 }
881 catch (SQLException s)
882 {
883 reportException(methodCall, s);
884 throw s;
885 }
886 }
887
888 public void close() throws SQLException
889 {
890 String methodCall = "close()";
891 try
892 {
893 realStatement.close();
894 }
895 catch (SQLException s)
896 {
897 reportException(methodCall, s);
898 throw s;
899 }
900 reportReturn(methodCall);
901 }
902
903 public int getUpdateCount() throws SQLException
904 {
905 String methodCall = "getUpdateCount()";
906 try
907 {
908 return reportReturn(methodCall, realStatement.getUpdateCount());
909 }
910 catch (SQLException s)
911 {
912 reportException(methodCall, s);
913 throw s;
914 }
915 }
916 }