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}