    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}