    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}