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 }