001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.dbcp2; 018 019import java.io.InputStream; 020import java.io.Reader; 021import java.math.BigDecimal; 022import java.sql.Array; 023import java.sql.Blob; 024import java.sql.Clob; 025import java.sql.Date; 026import java.sql.NClob; 027import java.sql.PreparedStatement; 028import java.sql.Ref; 029import java.sql.ResultSet; 030import java.sql.ResultSetMetaData; 031import java.sql.RowId; 032import java.sql.SQLException; 033import java.sql.SQLType; 034import java.sql.SQLXML; 035import java.sql.Statement; 036import java.sql.Time; 037import java.sql.Timestamp; 038import java.util.ArrayList; 039import java.util.Calendar; 040import java.util.List; 041 042/** 043 * A base delegating implementation of {@link PreparedStatement}. 044 * <p> 045 * All of the methods from the {@link PreparedStatement} interface simply check to see that the 046 * {@link PreparedStatement} is active, and call the corresponding method on the "delegate" provided in my constructor. 047 * <p> 048 * Extends AbandonedTrace to implement Statement tracking and logging of code which created the Statement. Tracking the 049 * Statement ensures that the Connection which created it can close any open Statement's on Connection close. 050 * 051 * @since 2.0 052 */ 053public class DelegatingPreparedStatement extends DelegatingStatement implements PreparedStatement { 054 055 /** 056 * Create a wrapper for the Statement which traces this Statement to the Connection which created it and the code 057 * which created it. 058 * 059 * @param statement 060 * the {@link PreparedStatement} to delegate all calls to. 061 * @param connection 062 * the {@link DelegatingConnection} that created this statement. 063 */ 064 public DelegatingPreparedStatement(final DelegatingConnection<?> connection, final PreparedStatement statement) { 065 super(connection, statement); 066 } 067 068 @Override 069 public void addBatch() throws SQLException { 070 checkOpen(); 071 try { 072 getDelegatePreparedStatement().addBatch(); 073 } catch (final SQLException e) { 074 handleException(e); 075 } 076 } 077 078 @Override 079 public void clearParameters() throws SQLException { 080 checkOpen(); 081 try { 082 getDelegatePreparedStatement().clearParameters(); 083 } catch (final SQLException e) { 084 handleException(e); 085 } 086 } 087 088 @Override 089 public boolean execute() throws SQLException { 090 checkOpen(); 091 if (getConnectionInternal() != null) { 092 getConnectionInternal().setLastUsed(); 093 } 094 try { 095 return getDelegatePreparedStatement().execute(); 096 } catch (final SQLException e) { 097 handleException(e); 098 return false; 099 } 100 } 101 102 /** 103 * @since 2.5.0 104 */ 105 @Override 106 public long executeLargeUpdate() throws SQLException { 107 checkOpen(); 108 try { 109 return getDelegatePreparedStatement().executeLargeUpdate(); 110 } catch (final SQLException e) { 111 handleException(e); 112 return 0; 113 } 114 } 115 116 @Override 117 public ResultSet executeQuery() throws SQLException { 118 checkOpen(); 119 if (getConnectionInternal() != null) { 120 getConnectionInternal().setLastUsed(); 121 } 122 try { 123 return DelegatingResultSet.wrapResultSet(this, getDelegatePreparedStatement().executeQuery()); 124 } catch (final SQLException e) { 125 handleException(e); 126 throw new AssertionError(); 127 } 128 } 129 130 @Override 131 public int executeUpdate() throws SQLException { 132 checkOpen(); 133 if (getConnectionInternal() != null) { 134 getConnectionInternal().setLastUsed(); 135 } 136 try { 137 return getDelegatePreparedStatement().executeUpdate(); 138 } catch (final SQLException e) { 139 handleException(e); 140 return 0; 141 } 142 } 143 144 private PreparedStatement getDelegatePreparedStatement() { 145 return (PreparedStatement) getDelegate(); 146 } 147 148 @Override 149 public ResultSetMetaData getMetaData() throws SQLException { 150 checkOpen(); 151 try { 152 return getDelegatePreparedStatement().getMetaData(); 153 } catch (final SQLException e) { 154 handleException(e); 155 throw new AssertionError(); 156 } 157 } 158 159 @Override 160 public java.sql.ParameterMetaData getParameterMetaData() throws SQLException { 161 checkOpen(); 162 try { 163 return getDelegatePreparedStatement().getParameterMetaData(); 164 } catch (final SQLException e) { 165 handleException(e); 166 throw new AssertionError(); 167 } 168 } 169 170 protected void prepareToReturn() throws SQLException { 171 setClosedInternal(true); 172 removeThisTrace(getConnectionInternal()); 173 174 // The JDBC spec requires that a statement close any open 175 // ResultSet's when it is closed. 176 // FIXME The PreparedStatement we're wrapping should handle this for us. 177 // See DBCP-10 for what could happen when ResultSets are closed twice. 178 final List<AbandonedTrace> traceList = getTrace(); 179 if (traceList != null) { 180 final List<Exception> thrownList = new ArrayList<>(); 181 traceList.forEach(trace -> trace.close(thrownList::add)); 182 clearTrace(); 183 if (!thrownList.isEmpty()) { 184 throw new SQLExceptionList(thrownList); 185 } 186 } 187 188 super.passivate(); 189 } 190 191 @Override 192 public void setArray(final int i, final Array x) throws SQLException { 193 checkOpen(); 194 try { 195 getDelegatePreparedStatement().setArray(i, x); 196 } catch (final SQLException e) { 197 handleException(e); 198 } 199 } 200 201 @Override 202 public void setAsciiStream(final int parameterIndex, final InputStream inputStream) throws SQLException { 203 checkOpen(); 204 try { 205 getDelegatePreparedStatement().setAsciiStream(parameterIndex, inputStream); 206 } catch (final SQLException e) { 207 handleException(e); 208 } 209 } 210 211 @Override 212 public void setAsciiStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { 213 checkOpen(); 214 try { 215 getDelegatePreparedStatement().setAsciiStream(parameterIndex, x, length); 216 } catch (final SQLException e) { 217 handleException(e); 218 } 219 } 220 221 @Override 222 public void setAsciiStream(final int parameterIndex, final InputStream inputStream, final long length) 223 throws SQLException { 224 checkOpen(); 225 try { 226 getDelegatePreparedStatement().setAsciiStream(parameterIndex, inputStream, length); 227 } catch (final SQLException e) { 228 handleException(e); 229 } 230 } 231 232 @Override 233 public void setBigDecimal(final int parameterIndex, final BigDecimal x) throws SQLException { 234 checkOpen(); 235 try { 236 getDelegatePreparedStatement().setBigDecimal(parameterIndex, x); 237 } catch (final SQLException e) { 238 handleException(e); 239 } 240 } 241 242 @Override 243 public void setBinaryStream(final int parameterIndex, final InputStream inputStream) throws SQLException { 244 checkOpen(); 245 try { 246 getDelegatePreparedStatement().setBinaryStream(parameterIndex, inputStream); 247 } catch (final SQLException e) { 248 handleException(e); 249 } 250 } 251 252 @Override 253 public void setBinaryStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { 254 checkOpen(); 255 try { 256 getDelegatePreparedStatement().setBinaryStream(parameterIndex, x, length); 257 } catch (final SQLException e) { 258 handleException(e); 259 } 260 } 261 262 @Override 263 public void setBinaryStream(final int parameterIndex, final InputStream inputStream, final long length) 264 throws SQLException { 265 checkOpen(); 266 try { 267 getDelegatePreparedStatement().setBinaryStream(parameterIndex, inputStream, length); 268 } catch (final SQLException e) { 269 handleException(e); 270 } 271 } 272 273 @Override 274 public void setBlob(final int i, final Blob x) throws SQLException { 275 checkOpen(); 276 try { 277 getDelegatePreparedStatement().setBlob(i, x); 278 } catch (final SQLException e) { 279 handleException(e); 280 } 281 } 282 283 @Override 284 public void setBlob(final int parameterIndex, final InputStream inputStream) throws SQLException { 285 checkOpen(); 286 try { 287 getDelegatePreparedStatement().setBlob(parameterIndex, inputStream); 288 } catch (final SQLException e) { 289 handleException(e); 290 } 291 } 292 293 @Override 294 public void setBlob(final int parameterIndex, final InputStream inputStream, final long length) 295 throws SQLException { 296 checkOpen(); 297 try { 298 getDelegatePreparedStatement().setBlob(parameterIndex, inputStream, length); 299 } catch (final SQLException e) { 300 handleException(e); 301 } 302 } 303 304 @Override 305 public void setBoolean(final int parameterIndex, final boolean x) throws SQLException { 306 checkOpen(); 307 try { 308 getDelegatePreparedStatement().setBoolean(parameterIndex, x); 309 } catch (final SQLException e) { 310 handleException(e); 311 } 312 } 313 314 @Override 315 public void setByte(final int parameterIndex, final byte x) throws SQLException { 316 checkOpen(); 317 try { 318 getDelegatePreparedStatement().setByte(parameterIndex, x); 319 } catch (final SQLException e) { 320 handleException(e); 321 } 322 } 323 324 @Override 325 public void setBytes(final int parameterIndex, final byte[] x) throws SQLException { 326 checkOpen(); 327 try { 328 getDelegatePreparedStatement().setBytes(parameterIndex, x); 329 } catch (final SQLException e) { 330 handleException(e); 331 } 332 } 333 334 @Override 335 public void setCharacterStream(final int parameterIndex, final Reader reader) throws SQLException { 336 checkOpen(); 337 try { 338 getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader); 339 } catch (final SQLException e) { 340 handleException(e); 341 } 342 } 343 344 @Override 345 public void setCharacterStream(final int parameterIndex, final Reader reader, final int length) 346 throws SQLException { 347 checkOpen(); 348 try { 349 getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader, length); 350 } catch (final SQLException e) { 351 handleException(e); 352 } 353 } 354 355 @Override 356 public void setCharacterStream(final int parameterIndex, final Reader reader, final long length) 357 throws SQLException { 358 checkOpen(); 359 try { 360 getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader, length); 361 } catch (final SQLException e) { 362 handleException(e); 363 } 364 } 365 366 @Override 367 public void setClob(final int i, final Clob x) throws SQLException { 368 checkOpen(); 369 try { 370 getDelegatePreparedStatement().setClob(i, x); 371 } catch (final SQLException e) { 372 handleException(e); 373 } 374 } 375 376 @Override 377 public void setClob(final int parameterIndex, final Reader reader) throws SQLException { 378 checkOpen(); 379 try { 380 getDelegatePreparedStatement().setClob(parameterIndex, reader); 381 } catch (final SQLException e) { 382 handleException(e); 383 } 384 } 385 386 @Override 387 public void setClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { 388 checkOpen(); 389 try { 390 getDelegatePreparedStatement().setClob(parameterIndex, reader, length); 391 } catch (final SQLException e) { 392 handleException(e); 393 } 394 } 395 396 @Override 397 public void setDate(final int parameterIndex, final Date x) throws SQLException { 398 checkOpen(); 399 try { 400 getDelegatePreparedStatement().setDate(parameterIndex, x); 401 } catch (final SQLException e) { 402 handleException(e); 403 } 404 } 405 406 @Override 407 public void setDate(final int parameterIndex, final Date x, final Calendar cal) throws SQLException { 408 checkOpen(); 409 try { 410 getDelegatePreparedStatement().setDate(parameterIndex, x, cal); 411 } catch (final SQLException e) { 412 handleException(e); 413 } 414 } 415 416 @Override 417 public void setDouble(final int parameterIndex, final double x) throws SQLException { 418 checkOpen(); 419 try { 420 getDelegatePreparedStatement().setDouble(parameterIndex, x); 421 } catch (final SQLException e) { 422 handleException(e); 423 } 424 } 425 426 @Override 427 public void setFloat(final int parameterIndex, final float x) throws SQLException { 428 checkOpen(); 429 try { 430 getDelegatePreparedStatement().setFloat(parameterIndex, x); 431 } catch (final SQLException e) { 432 handleException(e); 433 } 434 } 435 436 @Override 437 public void setInt(final int parameterIndex, final int x) throws SQLException { 438 checkOpen(); 439 try { 440 getDelegatePreparedStatement().setInt(parameterIndex, x); 441 } catch (final SQLException e) { 442 handleException(e); 443 } 444 } 445 446 @Override 447 public void setLong(final int parameterIndex, final long x) throws SQLException { 448 checkOpen(); 449 try { 450 getDelegatePreparedStatement().setLong(parameterIndex, x); 451 } catch (final SQLException e) { 452 handleException(e); 453 } 454 } 455 456 @Override 457 public void setNCharacterStream(final int parameterIndex, final Reader reader) throws SQLException { 458 checkOpen(); 459 try { 460 getDelegatePreparedStatement().setNCharacterStream(parameterIndex, reader); 461 } catch (final SQLException e) { 462 handleException(e); 463 } 464 } 465 466 @Override 467 public void setNCharacterStream(final int parameterIndex, final Reader value, final long length) 468 throws SQLException { 469 checkOpen(); 470 try { 471 getDelegatePreparedStatement().setNCharacterStream(parameterIndex, value, length); 472 } catch (final SQLException e) { 473 handleException(e); 474 } 475 } 476 477 @Override 478 public void setNClob(final int parameterIndex, final NClob value) throws SQLException { 479 checkOpen(); 480 try { 481 getDelegatePreparedStatement().setNClob(parameterIndex, value); 482 } catch (final SQLException e) { 483 handleException(e); 484 } 485 } 486 487 @Override 488 public void setNClob(final int parameterIndex, final Reader reader) throws SQLException { 489 checkOpen(); 490 try { 491 getDelegatePreparedStatement().setNClob(parameterIndex, reader); 492 } catch (final SQLException e) { 493 handleException(e); 494 } 495 } 496 497 @Override 498 public void setNClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { 499 checkOpen(); 500 try { 501 getDelegatePreparedStatement().setNClob(parameterIndex, reader, length); 502 } catch (final SQLException e) { 503 handleException(e); 504 } 505 } 506 507 @Override 508 public void setNString(final int parameterIndex, final String value) throws SQLException { 509 checkOpen(); 510 try { 511 getDelegatePreparedStatement().setNString(parameterIndex, value); 512 } catch (final SQLException e) { 513 handleException(e); 514 } 515 } 516 517 @Override 518 public void setNull(final int parameterIndex, final int sqlType) throws SQLException { 519 checkOpen(); 520 try { 521 getDelegatePreparedStatement().setNull(parameterIndex, sqlType); 522 } catch (final SQLException e) { 523 handleException(e); 524 } 525 } 526 527 @Override 528 public void setNull(final int paramIndex, final int sqlType, final String typeName) throws SQLException { 529 checkOpen(); 530 try { 531 getDelegatePreparedStatement().setNull(paramIndex, sqlType, typeName); 532 } catch (final SQLException e) { 533 handleException(e); 534 } 535 } 536 537 @Override 538 public void setObject(final int parameterIndex, final Object x) throws SQLException { 539 checkOpen(); 540 try { 541 getDelegatePreparedStatement().setObject(parameterIndex, x); 542 } catch (final SQLException e) { 543 handleException(e); 544 } 545 } 546 547 @Override 548 public void setObject(final int parameterIndex, final Object x, final int targetSqlType) throws SQLException { 549 checkOpen(); 550 try { 551 getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType); 552 } catch (final SQLException e) { 553 handleException(e); 554 } 555 } 556 557 @Override 558 public void setObject(final int parameterIndex, final Object x, final int targetSqlType, final int scale) 559 throws SQLException { 560 checkOpen(); 561 try { 562 getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType, scale); 563 } catch (final SQLException e) { 564 handleException(e); 565 } 566 } 567 568 /** 569 * @since 2.5.0 570 */ 571 @Override 572 public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType) throws SQLException { 573 checkOpen(); 574 try { 575 getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType); 576 } catch (final SQLException e) { 577 handleException(e); 578 } 579 } 580 581 /** 582 * @since 2.5.0 583 */ 584 @Override 585 public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { 586 checkOpen(); 587 try { 588 getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType, scaleOrLength); 589 } catch (final SQLException e) { 590 handleException(e); 591 } 592 } 593 594 @Override 595 public void setRef(final int i, final Ref x) throws SQLException { 596 checkOpen(); 597 try { 598 getDelegatePreparedStatement().setRef(i, x); 599 } catch (final SQLException e) { 600 handleException(e); 601 } 602 } 603 604 @Override 605 public void setRowId(final int parameterIndex, final RowId value) throws SQLException { 606 checkOpen(); 607 try { 608 getDelegatePreparedStatement().setRowId(parameterIndex, value); 609 } catch (final SQLException e) { 610 handleException(e); 611 } 612 } 613 614 @Override 615 public void setShort(final int parameterIndex, final short x) throws SQLException { 616 checkOpen(); 617 try { 618 getDelegatePreparedStatement().setShort(parameterIndex, x); 619 } catch (final SQLException e) { 620 handleException(e); 621 } 622 } 623 624 @Override 625 public void setSQLXML(final int parameterIndex, final SQLXML value) throws SQLException { 626 checkOpen(); 627 try { 628 getDelegatePreparedStatement().setSQLXML(parameterIndex, value); 629 } catch (final SQLException e) { 630 handleException(e); 631 } 632 } 633 634 @Override 635 public void setString(final int parameterIndex, final String x) throws SQLException { 636 checkOpen(); 637 try { 638 getDelegatePreparedStatement().setString(parameterIndex, x); 639 } catch (final SQLException e) { 640 handleException(e); 641 } 642 } 643 644 @Override 645 public void setTime(final int parameterIndex, final Time x) throws SQLException { 646 checkOpen(); 647 try { 648 getDelegatePreparedStatement().setTime(parameterIndex, x); 649 } catch (final SQLException e) { 650 handleException(e); 651 } 652 } 653 654 @Override 655 public void setTime(final int parameterIndex, final Time x, final Calendar cal) throws SQLException { 656 checkOpen(); 657 try { 658 getDelegatePreparedStatement().setTime(parameterIndex, x, cal); 659 } catch (final SQLException e) { 660 handleException(e); 661 } 662 } 663 664 @Override 665 public void setTimestamp(final int parameterIndex, final Timestamp x) throws SQLException { 666 checkOpen(); 667 try { 668 getDelegatePreparedStatement().setTimestamp(parameterIndex, x); 669 } catch (final SQLException e) { 670 handleException(e); 671 } 672 } 673 674 @Override 675 public void setTimestamp(final int parameterIndex, final Timestamp x, final Calendar cal) throws SQLException { 676 checkOpen(); 677 try { 678 getDelegatePreparedStatement().setTimestamp(parameterIndex, x, cal); 679 } catch (final SQLException e) { 680 handleException(e); 681 } 682 } 683 684 /** @deprecated Use setAsciiStream(), setCharacterStream() or setNCharacterStream() */ 685 @Deprecated 686 @Override 687 public void setUnicodeStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { 688 checkOpen(); 689 try { 690 getDelegatePreparedStatement().setUnicodeStream(parameterIndex, x, length); 691 } catch (final SQLException e) { 692 handleException(e); 693 } 694 } 695 696 @Override 697 public void setURL(final int parameterIndex, final java.net.URL x) throws SQLException { 698 checkOpen(); 699 try { 700 getDelegatePreparedStatement().setURL(parameterIndex, x); 701 } catch (final SQLException e) { 702 handleException(e); 703 } 704 } 705 706 /** 707 * Returns a String representation of this object. 708 * 709 * @return String 710 */ 711 @SuppressWarnings("resource") 712 @Override 713 public synchronized String toString() { 714 final Statement statement = getDelegate(); 715 return statement == null ? "NULL" : statement.toString(); 716 } 717}