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