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