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 * https://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.Time; 036import java.sql.Timestamp; 037import java.util.ArrayList; 038import java.util.Calendar; 039import java.util.List; 040import java.util.Objects; 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 /** 171 * Prepares internal states before calling {@link #passivate()}. 172 * 173 * @throws SQLException Thrown closing a traced resource or calling {@link #passivate()}. 174 */ 175 protected void prepareToReturn() throws SQLException { 176 setClosedInternal(true); 177 removeThisTrace(getConnectionInternal()); 178 // The JDBC spec requires that a statement close any open 179 // ResultSet's when it is closed. 180 // FIXME The PreparedStatement we're wrapping should handle this for us. 181 // See DBCP-10 for what could happen when ResultSets are closed twice. 182 final List<AbandonedTrace> traceList = getTrace(); 183 if (traceList != null) { 184 final List<Exception> thrownList = new ArrayList<>(); 185 traceList.forEach(trace -> trace.close(thrownList::add)); 186 clearTrace(); 187 if (!thrownList.isEmpty()) { 188 throw new SQLExceptionList(thrownList); 189 } 190 } 191 super.passivate(); 192 } 193 194 @Override 195 public void setArray(final int i, final Array x) throws SQLException { 196 checkOpen(); 197 try { 198 getDelegatePreparedStatement().setArray(i, x); 199 } catch (final SQLException e) { 200 handleException(e); 201 } 202 } 203 204 @Override 205 public void setAsciiStream(final int parameterIndex, final InputStream inputStream) throws SQLException { 206 checkOpen(); 207 try { 208 getDelegatePreparedStatement().setAsciiStream(parameterIndex, inputStream); 209 } catch (final SQLException e) { 210 handleException(e); 211 } 212 } 213 214 @Override 215 public void setAsciiStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { 216 checkOpen(); 217 try { 218 getDelegatePreparedStatement().setAsciiStream(parameterIndex, x, length); 219 } catch (final SQLException e) { 220 handleException(e); 221 } 222 } 223 224 @Override 225 public void setAsciiStream(final int parameterIndex, final InputStream inputStream, final long length) 226 throws SQLException { 227 checkOpen(); 228 try { 229 getDelegatePreparedStatement().setAsciiStream(parameterIndex, inputStream, length); 230 } catch (final SQLException e) { 231 handleException(e); 232 } 233 } 234 235 @Override 236 public void setBigDecimal(final int parameterIndex, final BigDecimal x) throws SQLException { 237 checkOpen(); 238 try { 239 getDelegatePreparedStatement().setBigDecimal(parameterIndex, x); 240 } catch (final SQLException e) { 241 handleException(e); 242 } 243 } 244 245 @Override 246 public void setBinaryStream(final int parameterIndex, final InputStream inputStream) throws SQLException { 247 checkOpen(); 248 try { 249 getDelegatePreparedStatement().setBinaryStream(parameterIndex, inputStream); 250 } catch (final SQLException e) { 251 handleException(e); 252 } 253 } 254 255 @Override 256 public void setBinaryStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { 257 checkOpen(); 258 try { 259 getDelegatePreparedStatement().setBinaryStream(parameterIndex, x, length); 260 } catch (final SQLException e) { 261 handleException(e); 262 } 263 } 264 265 @Override 266 public void setBinaryStream(final int parameterIndex, final InputStream inputStream, final long length) 267 throws SQLException { 268 checkOpen(); 269 try { 270 getDelegatePreparedStatement().setBinaryStream(parameterIndex, inputStream, length); 271 } catch (final SQLException e) { 272 handleException(e); 273 } 274 } 275 276 @Override 277 public void setBlob(final int i, final Blob x) throws SQLException { 278 checkOpen(); 279 try { 280 getDelegatePreparedStatement().setBlob(i, x); 281 } catch (final SQLException e) { 282 handleException(e); 283 } 284 } 285 286 @Override 287 public void setBlob(final int parameterIndex, final InputStream inputStream) throws SQLException { 288 checkOpen(); 289 try { 290 getDelegatePreparedStatement().setBlob(parameterIndex, inputStream); 291 } catch (final SQLException e) { 292 handleException(e); 293 } 294 } 295 296 @Override 297 public void setBlob(final int parameterIndex, final InputStream inputStream, final long length) 298 throws SQLException { 299 checkOpen(); 300 try { 301 getDelegatePreparedStatement().setBlob(parameterIndex, inputStream, length); 302 } catch (final SQLException e) { 303 handleException(e); 304 } 305 } 306 307 @Override 308 public void setBoolean(final int parameterIndex, final boolean x) throws SQLException { 309 checkOpen(); 310 try { 311 getDelegatePreparedStatement().setBoolean(parameterIndex, x); 312 } catch (final SQLException e) { 313 handleException(e); 314 } 315 } 316 317 @Override 318 public void setByte(final int parameterIndex, final byte x) throws SQLException { 319 checkOpen(); 320 try { 321 getDelegatePreparedStatement().setByte(parameterIndex, x); 322 } catch (final SQLException e) { 323 handleException(e); 324 } 325 } 326 327 @Override 328 public void setBytes(final int parameterIndex, final byte[] x) throws SQLException { 329 checkOpen(); 330 try { 331 getDelegatePreparedStatement().setBytes(parameterIndex, x); 332 } catch (final SQLException e) { 333 handleException(e); 334 } 335 } 336 337 @Override 338 public void setCharacterStream(final int parameterIndex, final Reader reader) throws SQLException { 339 checkOpen(); 340 try { 341 getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader); 342 } catch (final SQLException e) { 343 handleException(e); 344 } 345 } 346 347 @Override 348 public void setCharacterStream(final int parameterIndex, final Reader reader, final int length) 349 throws SQLException { 350 checkOpen(); 351 try { 352 getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader, length); 353 } catch (final SQLException e) { 354 handleException(e); 355 } 356 } 357 358 @Override 359 public void setCharacterStream(final int parameterIndex, final Reader reader, final long length) 360 throws SQLException { 361 checkOpen(); 362 try { 363 getDelegatePreparedStatement().setCharacterStream(parameterIndex, reader, length); 364 } catch (final SQLException e) { 365 handleException(e); 366 } 367 } 368 369 @Override 370 public void setClob(final int i, final Clob x) throws SQLException { 371 checkOpen(); 372 try { 373 getDelegatePreparedStatement().setClob(i, x); 374 } catch (final SQLException e) { 375 handleException(e); 376 } 377 } 378 379 @Override 380 public void setClob(final int parameterIndex, final Reader reader) throws SQLException { 381 checkOpen(); 382 try { 383 getDelegatePreparedStatement().setClob(parameterIndex, reader); 384 } catch (final SQLException e) { 385 handleException(e); 386 } 387 } 388 389 @Override 390 public void setClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { 391 checkOpen(); 392 try { 393 getDelegatePreparedStatement().setClob(parameterIndex, reader, length); 394 } catch (final SQLException e) { 395 handleException(e); 396 } 397 } 398 399 @Override 400 public void setDate(final int parameterIndex, final Date x) throws SQLException { 401 checkOpen(); 402 try { 403 getDelegatePreparedStatement().setDate(parameterIndex, x); 404 } catch (final SQLException e) { 405 handleException(e); 406 } 407 } 408 409 @Override 410 public void setDate(final int parameterIndex, final Date x, final Calendar cal) throws SQLException { 411 checkOpen(); 412 try { 413 getDelegatePreparedStatement().setDate(parameterIndex, x, cal); 414 } catch (final SQLException e) { 415 handleException(e); 416 } 417 } 418 419 @Override 420 public void setDouble(final int parameterIndex, final double x) throws SQLException { 421 checkOpen(); 422 try { 423 getDelegatePreparedStatement().setDouble(parameterIndex, x); 424 } catch (final SQLException e) { 425 handleException(e); 426 } 427 } 428 429 @Override 430 public void setFloat(final int parameterIndex, final float x) throws SQLException { 431 checkOpen(); 432 try { 433 getDelegatePreparedStatement().setFloat(parameterIndex, x); 434 } catch (final SQLException e) { 435 handleException(e); 436 } 437 } 438 439 @Override 440 public void setInt(final int parameterIndex, final int x) throws SQLException { 441 checkOpen(); 442 try { 443 getDelegatePreparedStatement().setInt(parameterIndex, x); 444 } catch (final SQLException e) { 445 handleException(e); 446 } 447 } 448 449 @Override 450 public void setLong(final int parameterIndex, final long x) throws SQLException { 451 checkOpen(); 452 try { 453 getDelegatePreparedStatement().setLong(parameterIndex, x); 454 } catch (final SQLException e) { 455 handleException(e); 456 } 457 } 458 459 @Override 460 public void setNCharacterStream(final int parameterIndex, final Reader reader) throws SQLException { 461 checkOpen(); 462 try { 463 getDelegatePreparedStatement().setNCharacterStream(parameterIndex, reader); 464 } catch (final SQLException e) { 465 handleException(e); 466 } 467 } 468 469 @Override 470 public void setNCharacterStream(final int parameterIndex, final Reader value, final long length) 471 throws SQLException { 472 checkOpen(); 473 try { 474 getDelegatePreparedStatement().setNCharacterStream(parameterIndex, value, length); 475 } catch (final SQLException e) { 476 handleException(e); 477 } 478 } 479 480 @Override 481 public void setNClob(final int parameterIndex, final NClob value) throws SQLException { 482 checkOpen(); 483 try { 484 getDelegatePreparedStatement().setNClob(parameterIndex, value); 485 } catch (final SQLException e) { 486 handleException(e); 487 } 488 } 489 490 @Override 491 public void setNClob(final int parameterIndex, final Reader reader) throws SQLException { 492 checkOpen(); 493 try { 494 getDelegatePreparedStatement().setNClob(parameterIndex, reader); 495 } catch (final SQLException e) { 496 handleException(e); 497 } 498 } 499 500 @Override 501 public void setNClob(final int parameterIndex, final Reader reader, final long length) throws SQLException { 502 checkOpen(); 503 try { 504 getDelegatePreparedStatement().setNClob(parameterIndex, reader, length); 505 } catch (final SQLException e) { 506 handleException(e); 507 } 508 } 509 510 @Override 511 public void setNString(final int parameterIndex, final String value) throws SQLException { 512 checkOpen(); 513 try { 514 getDelegatePreparedStatement().setNString(parameterIndex, value); 515 } catch (final SQLException e) { 516 handleException(e); 517 } 518 } 519 520 @Override 521 public void setNull(final int parameterIndex, final int sqlType) throws SQLException { 522 checkOpen(); 523 try { 524 getDelegatePreparedStatement().setNull(parameterIndex, sqlType); 525 } catch (final SQLException e) { 526 handleException(e); 527 } 528 } 529 530 @Override 531 public void setNull(final int paramIndex, final int sqlType, final String typeName) throws SQLException { 532 checkOpen(); 533 try { 534 getDelegatePreparedStatement().setNull(paramIndex, sqlType, typeName); 535 } catch (final SQLException e) { 536 handleException(e); 537 } 538 } 539 540 @Override 541 public void setObject(final int parameterIndex, final Object x) throws SQLException { 542 checkOpen(); 543 try { 544 getDelegatePreparedStatement().setObject(parameterIndex, x); 545 } catch (final SQLException e) { 546 handleException(e); 547 } 548 } 549 550 @Override 551 public void setObject(final int parameterIndex, final Object x, final int targetSqlType) throws SQLException { 552 checkOpen(); 553 try { 554 getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType); 555 } catch (final SQLException e) { 556 handleException(e); 557 } 558 } 559 560 @Override 561 public void setObject(final int parameterIndex, final Object x, final int targetSqlType, final int scale) 562 throws SQLException { 563 checkOpen(); 564 try { 565 getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType, scale); 566 } catch (final SQLException e) { 567 handleException(e); 568 } 569 } 570 571 /** 572 * @since 2.5.0 573 */ 574 @Override 575 public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType) throws SQLException { 576 checkOpen(); 577 try { 578 getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType); 579 } catch (final SQLException e) { 580 handleException(e); 581 } 582 } 583 584 /** 585 * @since 2.5.0 586 */ 587 @Override 588 public void setObject(final int parameterIndex, final Object x, final SQLType targetSqlType, final int scaleOrLength) throws SQLException { 589 checkOpen(); 590 try { 591 getDelegatePreparedStatement().setObject(parameterIndex, x, targetSqlType, scaleOrLength); 592 } catch (final SQLException e) { 593 handleException(e); 594 } 595 } 596 597 @Override 598 public void setRef(final int i, final Ref x) throws SQLException { 599 checkOpen(); 600 try { 601 getDelegatePreparedStatement().setRef(i, x); 602 } catch (final SQLException e) { 603 handleException(e); 604 } 605 } 606 607 @Override 608 public void setRowId(final int parameterIndex, final RowId value) throws SQLException { 609 checkOpen(); 610 try { 611 getDelegatePreparedStatement().setRowId(parameterIndex, value); 612 } catch (final SQLException e) { 613 handleException(e); 614 } 615 } 616 617 @Override 618 public void setShort(final int parameterIndex, final short x) throws SQLException { 619 checkOpen(); 620 try { 621 getDelegatePreparedStatement().setShort(parameterIndex, x); 622 } catch (final SQLException e) { 623 handleException(e); 624 } 625 } 626 627 @Override 628 public void setSQLXML(final int parameterIndex, final SQLXML value) throws SQLException { 629 checkOpen(); 630 try { 631 getDelegatePreparedStatement().setSQLXML(parameterIndex, value); 632 } catch (final SQLException e) { 633 handleException(e); 634 } 635 } 636 637 @Override 638 public void setString(final int parameterIndex, final String x) throws SQLException { 639 checkOpen(); 640 try { 641 getDelegatePreparedStatement().setString(parameterIndex, x); 642 } catch (final SQLException e) { 643 handleException(e); 644 } 645 } 646 647 @Override 648 public void setTime(final int parameterIndex, final Time x) throws SQLException { 649 checkOpen(); 650 try { 651 getDelegatePreparedStatement().setTime(parameterIndex, x); 652 } catch (final SQLException e) { 653 handleException(e); 654 } 655 } 656 657 @Override 658 public void setTime(final int parameterIndex, final Time x, final Calendar cal) throws SQLException { 659 checkOpen(); 660 try { 661 getDelegatePreparedStatement().setTime(parameterIndex, x, cal); 662 } catch (final SQLException e) { 663 handleException(e); 664 } 665 } 666 667 @Override 668 public void setTimestamp(final int parameterIndex, final Timestamp x) throws SQLException { 669 checkOpen(); 670 try { 671 getDelegatePreparedStatement().setTimestamp(parameterIndex, x); 672 } catch (final SQLException e) { 673 handleException(e); 674 } 675 } 676 677 @Override 678 public void setTimestamp(final int parameterIndex, final Timestamp x, final Calendar cal) throws SQLException { 679 checkOpen(); 680 try { 681 getDelegatePreparedStatement().setTimestamp(parameterIndex, x, cal); 682 } catch (final SQLException e) { 683 handleException(e); 684 } 685 } 686 687 /** @deprecated Use setAsciiStream(), setCharacterStream() or setNCharacterStream() */ 688 @Deprecated 689 @Override 690 public void setUnicodeStream(final int parameterIndex, final InputStream x, final int length) throws SQLException { 691 checkOpen(); 692 try { 693 getDelegatePreparedStatement().setUnicodeStream(parameterIndex, x, length); 694 } catch (final SQLException e) { 695 handleException(e); 696 } 697 } 698 699 @Override 700 public void setURL(final int parameterIndex, final java.net.URL x) throws SQLException { 701 checkOpen(); 702 try { 703 getDelegatePreparedStatement().setURL(parameterIndex, x); 704 } catch (final SQLException e) { 705 handleException(e); 706 } 707 } 708 709 /** 710 * Returns a String representation of this object. 711 * 712 * @return String 713 */ 714 @SuppressWarnings("resource") 715 @Override 716 public synchronized String toString() { 717 return Objects.toString(getDelegate(), "NULL"); 718 } 719}