/*
 * Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package java.sql;

import java.util.regex.Pattern;
import static java.util.stream.Collectors.joining;

/**
 * <P>The object used for executing a static SQL statement
 * and returning the results it produces.
 * <P>
 * By default, only one {@code ResultSet} object per {@code Statement}
 * object can be open at the same time. Therefore, if the reading of one
 * {@code ResultSet} object is interleaved
 * with the reading of another, each must have been generated by
 * different {@code Statement} objects. All execution methods in the
 * {@code Statement} interface implicitly close a current
 * {@code ResultSet} object of the statement if an open one exists.
 *
 * @see Connection#createStatement
 * @see ResultSet
 * @since 1.1
 */
public interface Statement extends Wrapper, AutoCloseable {

    /**
     * Executes the given SQL statement, which returns a single
     * {@code ResultSet} object.
     *<p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql an SQL statement to be sent to the database, typically a
     *        static SQL {@code SELECT} statement
     * @return a {@code ResultSet} object that contains the data produced
     *         by the given query; never {@code null}
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the given
     *            SQL statement produces anything other than a single
     *            {@code ResultSet} object, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     */
    ResultSet executeQuery(String sql) throws SQLException;

    /**
     * Executes the given SQL statement, which may be an {@code INSERT},
     * {@code UPDATE}, or {@code DELETE} statement or an
     * SQL statement that returns nothing, such as an SQL DDL statement.
     *<p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql an SQL Data Manipulation Language (DML) statement, such as {@code INSERT}, {@code UPDATE} or
     * {@code DELETE}; or an SQL statement that returns nothing,
     * such as a DDL statement.
     *
     * @return either (1) the row count for SQL Data Manipulation Language (DML) statements
     *         or (2) 0 for SQL statements that return nothing
     *
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the given
     * SQL statement produces a {@code ResultSet} object, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     */
    int executeUpdate(String sql) throws SQLException;

    /**
     * Releases this {@code Statement} object's database
     * and JDBC resources immediately instead of waiting for
     * this to happen when it is automatically closed.
     * It is generally good practice to release resources as soon as
     * you are finished with them to avoid tying up database
     * resources.
     * <P>
     * Calling the method {@code close} on a {@code Statement}
     * object that is already closed has no effect.
     * <P>
     * <B>Note:</B>When a {@code Statement} object is
     * closed, its current {@code ResultSet} object, if one exists, is
     * also closed.
     *
     * @throws SQLException if a database access error occurs
     */
    void close() throws SQLException;

    //----------------------------------------------------------------------

    /**
     * Retrieves the maximum number of bytes that can be
     * returned for character and binary column values in a {@code ResultSet}
     * object produced by this {@code Statement} object.
     * This limit applies only to  {@code BINARY}, {@code VARBINARY},
     * {@code LONGVARBINARY}, {@code CHAR}, {@code VARCHAR},
     * {@code NCHAR}, {@code NVARCHAR}, {@code LONGNVARCHAR}
     * and {@code LONGVARCHAR} columns.  If the limit is exceeded, the
     * excess data is silently discarded.
     *
     * @return the current column size limit for columns storing character and
     *         binary values; zero means there is no limit
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @see #setMaxFieldSize
     */
    int getMaxFieldSize() throws SQLException;

    /**
     * Sets the limit for the maximum number of bytes that can be returned for
     * character and binary column values in a {@code ResultSet}
     * object produced by this {@code Statement} object.
     *
     * This limit applies
     * only to {@code BINARY}, {@code VARBINARY},
     * {@code LONGVARBINARY}, {@code CHAR}, {@code VARCHAR},
     * {@code NCHAR}, {@code NVARCHAR}, {@code LONGNVARCHAR} and
     * {@code LONGVARCHAR} fields.  If the limit is exceeded, the excess data
     * is silently discarded. For maximum portability, use values
     * greater than 256.
     *
     * @param max the new column size limit in bytes; zero means there is no limit
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}
     *            or the condition {@code max >= 0} is not satisfied
     * @see #getMaxFieldSize
     */
    void setMaxFieldSize(int max) throws SQLException;

    /**
     * Retrieves the maximum number of rows that a
     * {@code ResultSet} object produced by this
     * {@code Statement} object can contain.  If this limit is exceeded,
     * the excess rows are silently dropped.
     *
     * @return the current maximum number of rows for a {@code ResultSet}
     *         object produced by this {@code Statement} object;
     *         zero means there is no limit
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @see #setMaxRows
     */
    int getMaxRows() throws SQLException;

    /**
     * Sets the limit for the maximum number of rows that any
     * {@code ResultSet} object  generated by this {@code Statement}
     * object can contain to the given number.
     * If the limit is exceeded, the excess
     * rows are silently dropped.
     *
     * @param max the new max rows limit; zero means there is no limit
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}
     *            or the condition {@code max >= 0} is not satisfied
     * @see #getMaxRows
     */
    void setMaxRows(int max) throws SQLException;

    /**
     * Sets escape processing on or off.
     * If escape scanning is on (the default), the driver will do
     * escape substitution before sending the SQL statement to the database.
     *<p>
     * The {@code Connection} and {@code DataSource} property
     * {@code escapeProcessing} may be used to change the default escape processing
     * behavior.  A value of true (the default) enables escape Processing for
     * all {@code Statement} objects. A value of false disables escape processing
     * for all {@code Statement} objects.  The {@code setEscapeProcessing}
     * method may be used to specify the escape processing behavior for an
     * individual {@code Statement} object.
     * <p>
     * Note: Since prepared statements have usually been parsed prior
     * to making this call, disabling escape processing for
     * {@code PreparedStatements} objects will have no effect.
     *
     * @param enable {@code true} to enable escape processing;
     *       {@code false} to disable it
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     */
    void setEscapeProcessing(boolean enable) throws SQLException;

    /**
     * Retrieves the number of seconds the driver will
     * wait for a {@code Statement} object to execute.
     * If the limit is exceeded, a
     * {@code SQLException} is thrown.
     *
     * @return the current query timeout limit in seconds; zero means there is
     *         no limit
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @see #setQueryTimeout
     */
    int getQueryTimeout() throws SQLException;

    /**
     * Sets the number of seconds the driver will wait for a
     * {@code Statement} object to execute to the given number of seconds.
     *By default there is no limit on the amount of time allowed for a running
     * statement to complete. If the limit is exceeded, an
     * {@code SQLTimeoutException} is thrown.
     * A JDBC driver must apply this limit to the {@code execute},
     * {@code executeQuery} and {@code executeUpdate} methods.
     * <p>
     * <strong>Note:</strong> JDBC driver implementations may also apply this
     * limit to {@code ResultSet} methods
     * (consult your driver vendor documentation for details).
     * <p>
     * <strong>Note:</strong> In the case of {@code Statement} batching, it is
     * implementation defined as to whether the time-out is applied to
     * individual SQL commands added via the {@code addBatch} method or to
     * the entire batch of SQL commands invoked by the {@code executeBatch}
     * method (consult your driver vendor documentation for details).
     *
     * @param seconds the new query timeout limit in seconds; zero means
     *        there is no limit
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}
     *            or the condition {@code seconds >= 0} is not satisfied
     * @see #getQueryTimeout
     */
    void setQueryTimeout(int seconds) throws SQLException;

    /**
     * Cancels this {@code Statement} object if both the DBMS and
     * driver support aborting an SQL statement.
     * This method can be used by one thread to cancel a statement that
     * is being executed by another thread.
     *
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method
     */
    void cancel() throws SQLException;

    /**
     * Retrieves the first warning reported by calls on this {@code Statement} object.
     * Subsequent {@code Statement} object warnings will be chained to this
     * {@code SQLWarning} object.
     *
     * <p>The warning chain is automatically cleared each time
     * a statement is (re)executed. This method may not be called on a closed
     * {@code Statement} object; doing so will cause an {@code SQLException}
     * to be thrown.
     *
     * <P><B>Note:</B> If you are processing a {@code ResultSet} object, any
     * warnings associated with reads on that {@code ResultSet} object
     * will be chained on it rather than on the {@code Statement}
     * object that produced it.
     *
     * @return the first {@code SQLWarning} object or {@code null}
     *         if there are no warnings
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     */
    SQLWarning getWarnings() throws SQLException;

    /**
     * Clears all the warnings reported on this {@code Statement}
     * object. After a call to this method,
     * the method {@code getWarnings} will return
     * {@code null} until a new warning is reported for this
     * {@code Statement} object.
     *
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     */
    void clearWarnings() throws SQLException;

    /**
     * Sets the SQL cursor name to the given {@code String}, which
     * will be used by subsequent {@code Statement} object
     * {@code execute} methods. This name can then be
     * used in SQL positioned update or delete statements to identify the
     * current row in the {@code ResultSet} object generated by this
     * statement.  If the database does not support positioned update/delete,
     * this method is a noop.  To insure that a cursor has the proper isolation
     * level to support updates, the cursor's {@code SELECT} statement
     * should have the form {@code SELECT FOR UPDATE}.  If
     * {@code FOR UPDATE} is not present, positioned updates may fail.
     *
     * <P><B>Note:</B> By definition, the execution of positioned updates and
     * deletes must be done by a different {@code Statement} object than
     * the one that generated the {@code ResultSet} object being used for
     * positioning. Also, cursor names must be unique within a connection.
     *
     * @param name the new cursor name, which must be unique within
     *             a connection
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     */
    void setCursorName(String name) throws SQLException;

    //----------------------- Multiple Results --------------------------

    /**
     * Executes the given SQL statement, which may return multiple results.
     * In some (uncommon) situations, a single SQL statement may return
     * multiple result sets and/or update counts.  Normally you can ignore
     * this unless you are (1) executing a stored procedure that you know may
     * return multiple results or (2) you are dynamically executing an
     * unknown SQL string.
     * <P>
     * The {@code execute} method executes an SQL statement and indicates the
     * form of the first result.  You must then use the methods
     * {@code getResultSet} or {@code getUpdateCount}
     * to retrieve the result, and {@code getMoreResults} to
     * move to any subsequent result(s).
     * <p>
     *<strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql any SQL statement
     * @return {@code true} if the first result is a {@code ResultSet}
     *         object; {@code false} if it is an update count or there are
     *         no results
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement},
     * the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @see #getResultSet
     * @see #getUpdateCount
     * @see #getMoreResults
     */
    boolean execute(String sql) throws SQLException;

    /**
     *  Retrieves the current result as a {@code ResultSet} object.
     *  This method should be called only once per result.
     *
     * @return the current result as a {@code ResultSet} object or
     * {@code null} if the result is an update count or there are no more results
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @see #execute
     */
    ResultSet getResultSet() throws SQLException;

    /**
     *  Retrieves the current result as an update count;
     *  if the result is a {@code ResultSet} object or there are no more results, -1
     *  is returned. This method should be called only once per result.
     *
     * @return the current result as an update count; -1 if the current result is a
     * {@code ResultSet} object or there are no more results
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @see #execute
     */
    int getUpdateCount() throws SQLException;

    /**
     * Moves to this {@code Statement} object's next result, returns
     * {@code true} if it is a {@code ResultSet} object, and
     * implicitly closes any current {@code ResultSet}
     * object(s) obtained with the method {@code getResultSet}.
     *
     * <P>There are no more results when the following is true:
     * <PRE>{@code
     *     // stmt is a Statement object
     *     ((stmt.getMoreResults() == false) && (stmt.getUpdateCount() == -1))
     * }</PRE>
     *
     * @return {@code true} if the next result is a {@code ResultSet}
     *         object; {@code false} if it is an update count or there are
     *         no more results
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @see #execute
     */
    boolean getMoreResults() throws SQLException;


    //--------------------------JDBC 2.0-----------------------------


    /**
     * Gives the driver a hint as to the direction in which
     * rows will be processed in {@code ResultSet}
     * objects created using this {@code Statement} object.  The
     * default value is {@code ResultSet.FETCH_FORWARD}.
     * <P>
     * Note that this method sets the default fetch direction for
     * result sets generated by this {@code Statement} object.
     * Each result set has its own methods for getting and setting
     * its own fetch direction.
     *
     * @param direction the initial direction for processing rows
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}
     * or the given direction
     * is not one of {@code ResultSet.FETCH_FORWARD},
     * {@code ResultSet.FETCH_REVERSE}, or {@code ResultSet.FETCH_UNKNOWN}
     * @since 1.2
     * @see #getFetchDirection
     */
    void setFetchDirection(int direction) throws SQLException;

    /**
     * Retrieves the direction for fetching rows from
     * database tables that is the default for result sets
     * generated from this {@code Statement} object.
     * If this {@code Statement} object has not set
     * a fetch direction by calling the method {@code setFetchDirection},
     * the return value is implementation-specific.
     *
     * @return the default fetch direction for result sets generated
     *          from this {@code Statement} object
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @since 1.2
     * @see #setFetchDirection
     */
    int getFetchDirection() throws SQLException;

    /**
     * Gives the JDBC driver a hint as to the number of rows that should
     * be fetched from the database when more rows are needed for
     * {@code ResultSet} objects generated by this {@code Statement}.
     * If the value specified is zero, then the hint is ignored.
     * The default value is zero.
     *
     * @param rows the number of rows to fetch
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement} or the
     *        condition {@code rows >= 0} is not satisfied.
     * @since 1.2
     * @see #getFetchSize
     */
    void setFetchSize(int rows) throws SQLException;

    /**
     * Retrieves the number of result set rows that is the default
     * fetch size for {@code ResultSet} objects
     * generated from this {@code Statement} object.
     * If this {@code Statement} object has not set
     * a fetch size by calling the method {@code setFetchSize},
     * the return value is implementation-specific.
     *
     * @return the default fetch size for result sets generated
     *          from this {@code Statement} object
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @since 1.2
     * @see #setFetchSize
     */
    int getFetchSize() throws SQLException;

    /**
     * Retrieves the result set concurrency for {@code ResultSet} objects
     * generated by this {@code Statement} object.
     *
     * @return either {@code ResultSet.CONCUR_READ_ONLY} or
     * {@code ResultSet.CONCUR_UPDATABLE}
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @since 1.2
     */
    int getResultSetConcurrency() throws SQLException;

    /**
     * Retrieves the result set type for {@code ResultSet} objects
     * generated by this {@code Statement} object.
     *
     * @return one of {@code ResultSet.TYPE_FORWARD_ONLY},
     * {@code ResultSet.TYPE_SCROLL_INSENSITIVE}, or
     * {@code ResultSet.TYPE_SCROLL_SENSITIVE}
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @since 1.2
     */
    int getResultSetType()  throws SQLException;

    /**
     * Adds the given SQL command to the current list of commands for this
     * {@code Statement} object. The commands in this list can be
     * executed as a batch by calling the method {@code executeBatch}.
     * <P>
     *<strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql typically this is a SQL {@code INSERT} or
     * {@code UPDATE} statement
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the
     * driver does not support batch updates, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @see #executeBatch
     * @see DatabaseMetaData#supportsBatchUpdates
     * @since 1.2
     */
    void addBatch( String sql ) throws SQLException;

    /**
     * Empties this {@code Statement} object's current list of
     * SQL commands.
     *
     * @throws SQLException if a database access error occurs,
     *  this method is called on a closed {@code Statement} or the
     * driver does not support batch updates
     * @see #addBatch
     * @see DatabaseMetaData#supportsBatchUpdates
     * @since 1.2
     */
    void clearBatch() throws SQLException;

    /**
     * Submits a batch of commands to the database for execution and
     * if all commands execute successfully, returns an array of update counts.
     * The {@code int} elements of the array that is returned are ordered
     * to correspond to the commands in the batch, which are ordered
     * according to the order in which they were added to the batch.
     * The elements in the array returned by the method {@code executeBatch}
     * may be one of the following:
     * <OL>
     * <LI>A number greater than or equal to zero -- indicates that the
     * command was processed successfully and is an update count giving the
     * number of rows in the database that were affected by the command's
     * execution
     * <LI>A value of {@code SUCCESS_NO_INFO} -- indicates that the command was
     * processed successfully but that the number of rows affected is
     * unknown
     * <P>
     * If one of the commands in a batch update fails to execute properly,
     * this method throws a {@code BatchUpdateException}, and a JDBC
     * driver may or may not continue to process the remaining commands in
     * the batch.  However, the driver's behavior must be consistent with a
     * particular DBMS, either always continuing to process commands or never
     * continuing to process commands.  If the driver continues processing
     * after a failure, the array returned by the method
     * {@code BatchUpdateException.getUpdateCounts}
     * will contain as many elements as there are commands in the batch, and
     * at least one of the elements will be the following:
     *
     * <LI>A value of {@code EXECUTE_FAILED} -- indicates that the command failed
     * to execute successfully and occurs only if a driver continues to
     * process commands after a command fails
     * </OL>
     * <P>
     * The possible implementations and return values have been modified in
     * the Java 2 SDK, Standard Edition, version 1.3 to
     * accommodate the option of continuing to process commands in a batch
     * update after a {@code BatchUpdateException} object has been thrown.
     *
     * @return an array of update counts containing one element for each
     * command in the batch.  The elements of the array are ordered according
     * to the order in which commands were added to the batch.
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement} or the
     * driver does not support batch statements. Throws {@link BatchUpdateException}
     * (a subclass of {@code SQLException}) if one of the commands sent to the
     * database fails to execute properly or attempts to return a result set.
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     *
     * @see #addBatch
     * @see DatabaseMetaData#supportsBatchUpdates
     * @since 1.2
     */
    int[] executeBatch() throws SQLException;

    /**
     * Retrieves the {@code Connection} object
     * that produced this {@code Statement} object.
     * @return the connection that produced this statement
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @since 1.2
     */
    Connection getConnection()  throws SQLException;

  //--------------------------JDBC 3.0-----------------------------

    /**
     * The constant indicating that the current {@code ResultSet} object
     * should be closed when calling {@code getMoreResults}.
     *
     * @since 1.4
     */
    int CLOSE_CURRENT_RESULT = 1;

    /**
     * The constant indicating that the current {@code ResultSet} object
     * should not be closed when calling {@code getMoreResults}.
     *
     * @since 1.4
     */
    int KEEP_CURRENT_RESULT = 2;

    /**
     * The constant indicating that all {@code ResultSet} objects that
     * have previously been kept open should be closed when calling
     * {@code getMoreResults}.
     *
     * @since 1.4
     */
    int CLOSE_ALL_RESULTS = 3;

    /**
     * The constant indicating that a batch statement executed successfully
     * but that no count of the number of rows it affected is available.
     *
     * @since 1.4
     */
    int SUCCESS_NO_INFO = -2;

    /**
     * The constant indicating that an error occurred while executing a
     * batch statement.
     *
     * @since 1.4
     */
    int EXECUTE_FAILED = -3;

    /**
     * The constant indicating that generated keys should be made
     * available for retrieval.
     *
     * @since 1.4
     */
    int RETURN_GENERATED_KEYS = 1;

    /**
     * The constant indicating that generated keys should not be made
     * available for retrieval.
     *
     * @since 1.4
     */
    int NO_GENERATED_KEYS = 2;

    /**
     * Moves to this {@code Statement} object's next result, deals with
     * any current {@code ResultSet} object(s) according  to the instructions
     * specified by the given flag, and returns
     * {@code true} if the next result is a {@code ResultSet} object.
     *
     * <P>There are no more results when the following is true:
     * <PRE>{@code
     *     // stmt is a Statement object
     *     ((stmt.getMoreResults(current) == false) && (stmt.getUpdateCount() == -1))
     * }</PRE>
     *
     * @param current one of the following {@code Statement}
     *        constants indicating what should happen to current
     *        {@code ResultSet} objects obtained using the method
     *        {@code getResultSet}:
     *        {@code Statement.CLOSE_CURRENT_RESULT},
     *        {@code Statement.KEEP_CURRENT_RESULT}, or
     *        {@code Statement.CLOSE_ALL_RESULTS}
     * @return {@code true} if the next result is a {@code ResultSet}
     *         object; {@code false} if it is an update count or there are no
     *         more results
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement} or the argument
     *         supplied is not one of the following:
     *        {@code Statement.CLOSE_CURRENT_RESULT},
     *        {@code Statement.KEEP_CURRENT_RESULT} or
     *        {@code Statement.CLOSE_ALL_RESULTS}
     *@throws SQLFeatureNotSupportedException if
     * {@code DatabaseMetaData.supportsMultipleOpenResults} returns
     * {@code false} and either
     *        {@code Statement.KEEP_CURRENT_RESULT} or
     *        {@code Statement.CLOSE_ALL_RESULTS} are supplied as
     * the argument.
     * @since 1.4
     * @see #execute
     */
    boolean getMoreResults(int current) throws SQLException;

    /**
     * Retrieves any auto-generated keys created as a result of executing this
     * {@code Statement} object. If this {@code Statement} object did
     * not generate any keys, an empty {@code ResultSet}
     * object is returned.
     *
     *<p><B>Note:</B>If the columns which represent the auto-generated keys were not specified,
     * the JDBC driver implementation will determine the columns which best represent the auto-generated keys.
     *
     * @return a {@code ResultSet} object containing the auto-generated key(s)
     *         generated by the execution of this {@code Statement} object
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     * @since 1.4
     */
    ResultSet getGeneratedKeys() throws SQLException;

    /**
     * Executes the given SQL statement and signals the driver with the
     * given flag about whether the
     * auto-generated keys produced by this {@code Statement} object
     * should be made available for retrieval.  The driver will ignore the
     * flag if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     *<p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql an SQL Data Manipulation Language (DML) statement, such as {@code INSERT}, {@code UPDATE} or
     * {@code DELETE}; or an SQL statement that returns nothing,
     * such as a DDL statement.
     *
     * @param autoGeneratedKeys a flag indicating whether auto-generated keys
     *        should be made available for retrieval;
     *         one of the following constants:
     *         {@code Statement.RETURN_GENERATED_KEYS}
     *         {@code Statement.NO_GENERATED_KEYS}
     * @return either (1) the row count for SQL Data Manipulation Language (DML) statements
     *         or (2) 0 for SQL statements that return nothing
     *
     * @throws SQLException if a database access error occurs,
     *  this method is called on a closed {@code Statement}, the given
     *            SQL statement returns a {@code ResultSet} object,
     *            the given constant is not one of those allowed, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method with a constant of Statement.RETURN_GENERATED_KEYS
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @since 1.4
     */
    int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException;

    /**
     * Executes the given SQL statement and signals the driver that the
     * auto-generated keys indicated in the given array should be made available
     * for retrieval.   This array contains the indexes of the columns in the
     * target table that contain the auto-generated keys that should be made
     * available. The driver will ignore the array if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     *<p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql an SQL Data Manipulation Language (DML) statement, such as {@code INSERT}, {@code UPDATE} or
     * {@code DELETE}; or an SQL statement that returns nothing,
     * such as a DDL statement.
     *
     * @param columnIndexes an array of column indexes indicating the columns
     *        that should be returned from the inserted row
     * @return either (1) the row count for SQL Data Manipulation Language (DML) statements
     *         or (2) 0 for SQL statements that return nothing
     *
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the SQL
     * statement returns a {@code ResultSet} object, the second argument
     * supplied to this method is not an
     * {@code int} array whose elements are valid column indexes, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @since 1.4
     */
    int executeUpdate(String sql, int columnIndexes[]) throws SQLException;

    /**
     * Executes the given SQL statement and signals the driver that the
     * auto-generated keys indicated in the given array should be made available
     * for retrieval.   This array contains the names of the columns in the
     * target table that contain the auto-generated keys that should be made
     * available. The driver will ignore the array if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     *<p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql an SQL Data Manipulation Language (DML) statement, such as {@code INSERT}, {@code UPDATE} or
     * {@code DELETE}; or an SQL statement that returns nothing,
     * such as a DDL statement.
     * @param columnNames an array of the names of the columns that should be
     *        returned from the inserted row
     * @return either the row count for {@code INSERT}, {@code UPDATE},
     *         or {@code DELETE} statements, or 0 for SQL statements
     *         that return nothing
     * @throws SQLException if a database access error occurs,
     *  this method is called on a closed {@code Statement}, the SQL
     *            statement returns a {@code ResultSet} object, the
     *            second argument supplied to this method is not a {@code String} array
     *            whose elements are valid column names, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @since 1.4
     */
    int executeUpdate(String sql, String columnNames[]) throws SQLException;

    /**
     * Executes the given SQL statement, which may return multiple results,
     * and signals the driver that any
     * auto-generated keys should be made available
     * for retrieval.  The driver will ignore this signal if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     * <P>
     * In some (uncommon) situations, a single SQL statement may return
     * multiple result sets and/or update counts.  Normally you can ignore
     * this unless you are (1) executing a stored procedure that you know may
     * return multiple results or (2) you are dynamically executing an
     * unknown SQL string.
     * <P>
     * The {@code execute} method executes an SQL statement and indicates the
     * form of the first result.  You must then use the methods
     * {@code getResultSet} or {@code getUpdateCount}
     * to retrieve the result, and {@code getMoreResults} to
     * move to any subsequent result(s).
     *<p>
     *<strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql any SQL statement
     * @param autoGeneratedKeys a constant indicating whether auto-generated
     *        keys should be made available for retrieval using the method
     *        {@code getGeneratedKeys}; one of the following constants:
     *        {@code Statement.RETURN_GENERATED_KEYS} or
     *        {@code Statement.NO_GENERATED_KEYS}
     * @return {@code true} if the first result is a {@code ResultSet}
     *         object; {@code false} if it is an update count or there are
     *         no results
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the second
     *         parameter supplied to this method is not
     *         {@code Statement.RETURN_GENERATED_KEYS} or
     *         {@code Statement.NO_GENERATED_KEYS},
     * the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method with a constant of Statement.RETURN_GENERATED_KEYS
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @see #getResultSet
     * @see #getUpdateCount
     * @see #getMoreResults
     * @see #getGeneratedKeys
     *
     * @since 1.4
     */
    boolean execute(String sql, int autoGeneratedKeys) throws SQLException;

    /**
     * Executes the given SQL statement, which may return multiple results,
     * and signals the driver that the
     * auto-generated keys indicated in the given array should be made available
     * for retrieval.  This array contains the indexes of the columns in the
     * target table that contain the auto-generated keys that should be made
     * available.  The driver will ignore the array if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     * <P>
     * Under some (uncommon) situations, a single SQL statement may return
     * multiple result sets and/or update counts.  Normally you can ignore
     * this unless you are (1) executing a stored procedure that you know may
     * return multiple results or (2) you are dynamically executing an
     * unknown SQL string.
     * <P>
     * The {@code execute} method executes an SQL statement and indicates the
     * form of the first result.  You must then use the methods
     * {@code getResultSet} or {@code getUpdateCount}
     * to retrieve the result, and {@code getMoreResults} to
     * move to any subsequent result(s).
     *<p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql any SQL statement
     * @param columnIndexes an array of the indexes of the columns in the
     *        inserted row that should be  made available for retrieval by a
     *        call to the method {@code getGeneratedKeys}
     * @return {@code true} if the first result is a {@code ResultSet}
     *         object; {@code false} if it is an update count or there
     *         are no results
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the
     *            elements in the {@code int} array passed to this method
     *            are not valid column indexes, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @see #getResultSet
     * @see #getUpdateCount
     * @see #getMoreResults
     *
     * @since 1.4
     */
    boolean execute(String sql, int columnIndexes[]) throws SQLException;

    /**
     * Executes the given SQL statement, which may return multiple results,
     * and signals the driver that the
     * auto-generated keys indicated in the given array should be made available
     * for retrieval. This array contains the names of the columns in the
     * target table that contain the auto-generated keys that should be made
     * available.  The driver will ignore the array if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     * <P>
     * In some (uncommon) situations, a single SQL statement may return
     * multiple result sets and/or update counts.  Normally you can ignore
     * this unless you are (1) executing a stored procedure that you know may
     * return multiple results or (2) you are dynamically executing an
     * unknown SQL string.
     * <P>
     * The {@code execute} method executes an SQL statement and indicates the
     * form of the first result.  You must then use the methods
     * {@code getResultSet} or {@code getUpdateCount}
     * to retrieve the result, and {@code getMoreResults} to
     * move to any subsequent result(s).
     *<p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     * @param sql any SQL statement
     * @param columnNames an array of the names of the columns in the inserted
     *        row that should be made available for retrieval by a call to the
     *        method {@code getGeneratedKeys}
     * @return {@code true} if the next result is a {@code ResultSet}
     *         object; {@code false} if it is an update count or there
     *         are no more results
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the
     *          elements of the {@code String} array passed to this
     *          method are not valid column names, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @see #getResultSet
     * @see #getUpdateCount
     * @see #getMoreResults
     * @see #getGeneratedKeys
     *
     * @since 1.4
     */
    boolean execute(String sql, String columnNames[]) throws SQLException;

   /**
     * Retrieves the result set holdability for {@code ResultSet} objects
     * generated by this {@code Statement} object.
     *
     * @return either {@code ResultSet.HOLD_CURSORS_OVER_COMMIT} or
     *         {@code ResultSet.CLOSE_CURSORS_AT_COMMIT}
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     *
     * @since 1.4
     */
    int getResultSetHoldability() throws SQLException;

    /**
     * Retrieves whether this {@code Statement} object has been closed. A {@code Statement} is closed if the
     * method close has been called on it, or if it is automatically closed.
     * @return true if this {@code Statement} object is closed; false if it is still open
     * @throws SQLException if a database access error occurs
     * @since 1.6
     */
    boolean isClosed() throws SQLException;

        /**
         * Requests that a {@code Statement} be pooled or not pooled.  The value
         * specified is a hint to the statement pool implementation indicating
         * whether the application wants the statement to be pooled.  It is up to
         * the statement pool manager as to whether the hint is used.
         * <p>
         * The poolable value of a statement is applicable to both internal
         * statement caches implemented by the driver and external statement caches
         * implemented by application servers and other applications.
         * <p>
         * By default, a {@code Statement} is not poolable when created, and
         * a {@code PreparedStatement} and {@code CallableStatement}
         * are poolable when created.
         *
         * @param poolable              requests that the statement be pooled if true and
         *                                              that the statement not be pooled if false
         *
         * @throws SQLException if this method is called on a closed
         * {@code Statement}
         *
         * @since 1.6
         */
        void setPoolable(boolean poolable)
                throws SQLException;

        /**
         * Returns a  value indicating whether the {@code Statement}
         * is poolable or not.
         *
         * @return              {@code true} if the {@code Statement}
         * is poolable; {@code false} otherwise
         *
         * @throws SQLException if this method is called on a closed
         * {@code Statement}
         *
         * @since 1.6
         *
         * @see java.sql.Statement#setPoolable(boolean) setPoolable(boolean)
         */
        boolean isPoolable()
                throws SQLException;

    //--------------------------JDBC 4.1 -----------------------------

    /**
     * Specifies that this {@code Statement} will be closed when all its
     * dependent result sets are closed. If execution of the {@code Statement}
     * does not produce any result sets, this method has no effect.
     * <p>
     * <strong>Note:</strong> Multiple calls to {@code closeOnCompletion} do
     * not toggle the effect on this {@code Statement}. However, a call to
     * {@code closeOnCompletion} does effect both the subsequent execution of
     * statements, and statements that currently have open, dependent,
     * result sets.
     *
     * @throws SQLException if this method is called on a closed
     * {@code Statement}
     * @since 1.7
     */
    public void closeOnCompletion() throws SQLException;

    /**
     * Returns a value indicating whether this {@code Statement} will be
     * closed when all its dependent result sets are closed.
     * @return {@code true} if the {@code Statement} will be closed when all
     * of its dependent result sets are closed; {@code false} otherwise
     * @throws SQLException if this method is called on a closed
     * {@code Statement}
     * @since 1.7
     */
    public boolean isCloseOnCompletion() throws SQLException;


    //--------------------------JDBC 4.2 -----------------------------

    /**
     *  Retrieves the current result as an update count; if the result
     * is a {@code ResultSet} object or there are no more results, -1
     *  is returned. This method should be called only once per result.
     * <p>
     * This method should be used when the returned row count may exceed
     * {@link Integer#MAX_VALUE}.
     *<p>
     * The default implementation will throw {@code UnsupportedOperationException}
     *
     * @return the current result as an update count; -1 if the current result
     * is a {@code ResultSet} object or there are no more results
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @see #execute
     * @since 1.8
     */
    default long getLargeUpdateCount() throws SQLException {
        throw new UnsupportedOperationException("getLargeUpdateCount not implemented");
    }

    /**
     * Sets the limit for the maximum number of rows that any
     * {@code ResultSet} object  generated by this {@code Statement}
     * object can contain to the given number.
     * If the limit is exceeded, the excess
     * rows are silently dropped.
     * <p>
     * This method should be used when the row limit may exceed
     * {@link Integer#MAX_VALUE}.
     *<p>
     * The default implementation will throw {@code UnsupportedOperationException}
     *
     * @param max the new max rows limit; zero means there is no limit
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}
     *            or the condition {@code max >= 0} is not satisfied
     * @see #getMaxRows
     * @since 1.8
     */
    default void setLargeMaxRows(long max) throws SQLException {
        throw new UnsupportedOperationException("setLargeMaxRows not implemented");
    }

    /**
     * Retrieves the maximum number of rows that a
     * {@code ResultSet} object produced by this
     * {@code Statement} object can contain.  If this limit is exceeded,
     * the excess rows are silently dropped.
     * <p>
     * This method should be used when the returned row limit may exceed
     * {@link Integer#MAX_VALUE}.
     *<p>
     * The default implementation will return {@code 0}
     *
     * @return the current maximum number of rows for a {@code ResultSet}
     *         object produced by this {@code Statement} object;
     *         zero means there is no limit
     * @throws SQLException if a database access error occurs or
     * this method is called on a closed {@code Statement}
     * @see #setMaxRows
     * @since 1.8
     */
    default long getLargeMaxRows() throws SQLException {
        return 0;
    }

    /**
     * Submits a batch of commands to the database for execution and
     * if all commands execute successfully, returns an array of update counts.
     * The {@code long} elements of the array that is returned are ordered
     * to correspond to the commands in the batch, which are ordered
     * according to the order in which they were added to the batch.
     * The elements in the array returned by the method {@code executeLargeBatch}
     * may be one of the following:
     * <OL>
     * <LI>A number greater than or equal to zero -- indicates that the
     * command was processed successfully and is an update count giving the
     * number of rows in the database that were affected by the command's
     * execution
     * <LI>A value of {@code SUCCESS_NO_INFO} -- indicates that the command was
     * processed successfully but that the number of rows affected is
     * unknown
     * <P>
     * If one of the commands in a batch update fails to execute properly,
     * this method throws a {@code BatchUpdateException}, and a JDBC
     * driver may or may not continue to process the remaining commands in
     * the batch.  However, the driver's behavior must be consistent with a
     * particular DBMS, either always continuing to process commands or never
     * continuing to process commands.  If the driver continues processing
     * after a failure, the array returned by the method
     * {@code BatchUpdateException.getLargeUpdateCounts}
     * will contain as many elements as there are commands in the batch, and
     * at least one of the elements will be the following:
     *
     * <LI>A value of {@code EXECUTE_FAILED} -- indicates that the command failed
     * to execute successfully and occurs only if a driver continues to
     * process commands after a command fails
     * </OL>
     * <p>
     * This method should be used when the returned row count may exceed
     * {@link Integer#MAX_VALUE}.
     *<p>
     * The default implementation will throw {@code UnsupportedOperationException}
     *
     * @return an array of update counts containing one element for each
     * command in the batch.  The elements of the array are ordered according
     * to the order in which commands were added to the batch.
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement} or the
     * driver does not support batch statements. Throws {@link BatchUpdateException}
     * (a subclass of {@code SQLException}) if one of the commands sent to the
     * database fails to execute properly or attempts to return a result set.
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     *
     * @see #addBatch
     * @see DatabaseMetaData#supportsBatchUpdates
     * @since 1.8
     */
    default long[] executeLargeBatch() throws SQLException {
        throw new UnsupportedOperationException("executeLargeBatch not implemented");
    }

    /**
     * Executes the given SQL statement, which may be an {@code INSERT},
     * {@code UPDATE}, or {@code DELETE} statement or an
     * SQL statement that returns nothing, such as an SQL DDL statement.
     * <p>
     * This method should be used when the returned row count may exceed
     * {@link Integer#MAX_VALUE}.
     * <p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     *<p>
     * The default implementation will throw {@code UnsupportedOperationException}
     *
     * @param sql an SQL Data Manipulation Language (DML) statement,
     * such as {@code INSERT}, {@code UPDATE} or
     * {@code DELETE}; or an SQL statement that returns nothing,
     * such as a DDL statement.
     *
     * @return either (1) the row count for SQL Data Manipulation Language
     * (DML) statements or (2) 0 for SQL statements that return nothing
     *
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the given
     * SQL statement produces a {@code ResultSet} object, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @since 1.8
     */
    default long executeLargeUpdate(String sql) throws SQLException {
        throw new UnsupportedOperationException("executeLargeUpdate not implemented");
    }

    /**
     * Executes the given SQL statement and signals the driver with the
     * given flag about whether the
     * auto-generated keys produced by this {@code Statement} object
     * should be made available for retrieval.  The driver will ignore the
     * flag if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     * <p>
     * This method should be used when the returned row count may exceed
     * {@link Integer#MAX_VALUE}.
     * <p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     *<p>
     * The default implementation will throw {@code SQLFeatureNotSupportedException}
     *
     * @param sql an SQL Data Manipulation Language (DML) statement,
     * such as {@code INSERT}, {@code UPDATE} or
     * {@code DELETE}; or an SQL statement that returns nothing,
     * such as a DDL statement.
     *
     * @param autoGeneratedKeys a flag indicating whether auto-generated keys
     *        should be made available for retrieval;
     *         one of the following constants:
     *         {@code Statement.RETURN_GENERATED_KEYS}
     *         {@code Statement.NO_GENERATED_KEYS}
     * @return either (1) the row count for SQL Data Manipulation Language (DML) statements
     *         or (2) 0 for SQL statements that return nothing
     *
     * @throws SQLException if a database access error occurs,
     *  this method is called on a closed {@code Statement}, the given
     *            SQL statement returns a {@code ResultSet} object,
     *            the given constant is not one of those allowed, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException if the JDBC driver does not support
     * this method with a constant of Statement.RETURN_GENERATED_KEYS
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @since 1.8
     */
    default long executeLargeUpdate(String sql, int autoGeneratedKeys)
            throws SQLException {
        throw new SQLFeatureNotSupportedException("executeLargeUpdate not implemented");
    }

    /**
     * Executes the given SQL statement and signals the driver that the
     * auto-generated keys indicated in the given array should be made available
     * for retrieval.   This array contains the indexes of the columns in the
     * target table that contain the auto-generated keys that should be made
     * available. The driver will ignore the array if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     * <p>
     * This method should be used when the returned row count may exceed
     * {@link Integer#MAX_VALUE}.
     * <p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     *<p>
     * The default implementation will throw {@code SQLFeatureNotSupportedException}
     *
     * @param sql an SQL Data Manipulation Language (DML) statement,
     * such as {@code INSERT}, {@code UPDATE} or
     * {@code DELETE}; or an SQL statement that returns nothing,
     * such as a DDL statement.
     *
     * @param columnIndexes an array of column indexes indicating the columns
     *        that should be returned from the inserted row
     * @return either (1) the row count for SQL Data Manipulation Language (DML) statements
     *         or (2) 0 for SQL statements that return nothing
     *
     * @throws SQLException if a database access error occurs,
     * this method is called on a closed {@code Statement}, the SQL
     * statement returns a {@code ResultSet} object,the second argument
     * supplied to this method is not an
     * {@code int} array whose elements are valid column indexes, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @since 1.8
     */
    default long executeLargeUpdate(String sql, int columnIndexes[]) throws SQLException {
        throw new SQLFeatureNotSupportedException("executeLargeUpdate not implemented");
    }

    /**
     * Executes the given SQL statement and signals the driver that the
     * auto-generated keys indicated in the given array should be made available
     * for retrieval.   This array contains the names of the columns in the
     * target table that contain the auto-generated keys that should be made
     * available. The driver will ignore the array if the SQL statement
     * is not an {@code INSERT} statement, or an SQL statement able to return
     * auto-generated keys (the list of such statements is vendor-specific).
     * <p>
     * This method should be used when the returned row count may exceed
     * {@link Integer#MAX_VALUE}.
     * <p>
     * <strong>Note:</strong>This method cannot be called on a
     * {@code PreparedStatement} or {@code CallableStatement}.
     *<p>
     * The default implementation will throw {@code SQLFeatureNotSupportedException}
     *
     * @param sql an SQL Data Manipulation Language (DML) statement,
     * such as {@code INSERT}, {@code UPDATE} or
     * {@code DELETE}; or an SQL statement that returns nothing,
     * such as a DDL statement.
     * @param columnNames an array of the names of the columns that should be
     *        returned from the inserted row
     * @return either the row count for {@code INSERT}, {@code UPDATE},
     *         or {@code DELETE} statements, or 0 for SQL statements
     *         that return nothing
     * @throws SQLException if a database access error occurs,
     *  this method is called on a closed {@code Statement}, the SQL
     *            statement returns a {@code ResultSet} object, the
     *            second argument supplied to this method is not a {@code String} array
     *            whose elements are valid column names, the method is called on a
     * {@code PreparedStatement} or {@code CallableStatement}
     * @throws SQLFeatureNotSupportedException  if the JDBC driver does not support this method
     * @throws SQLTimeoutException when the driver has determined that the
     * timeout value that was specified by the {@code setQueryTimeout}
     * method has been exceeded and has at least attempted to cancel
     * the currently running {@code Statement}
     * @since 1.8
     */
    default long executeLargeUpdate(String sql, String columnNames[])
            throws SQLException {
        throw new SQLFeatureNotSupportedException("executeLargeUpdate not implemented");
    }

    // JDBC 4.3

    /**
     * Returns a {@code String} enclosed in single quotes. Any occurrence of a
     * single quote within the string will be replaced by two single quotes.
     *
     * <blockquote>
     * <table class="striped">
     * <caption>Examples of the conversion:</caption>
     * <thead>
     * <tr><th scope="col">Value</th><th scope="col">Result</th></tr>
     * </thead>
     * <tbody style="text-align:center">
     * <tr> <th scope="row">Hello</th> <td>'Hello'</td> </tr>
     * <tr> <th scope="row">G'Day</th> <td>'G''Day'</td> </tr>
     * <tr> <th scope="row">'G''Day'</th>
     * <td>'''G''''Day'''</td> </tr>
     * <tr> <th scope="row">I'''M</th> <td>'I''''''M'</td>
     * </tr>
     *
     * </tbody>
     * </table>
     * </blockquote>
     * @implNote
     * JDBC driver implementations may need to provide their own implementation
     * of this method in order to meet the requirements of the underlying
     * datasource.
     * @param val a character string
     * @return A string enclosed by single quotes with every single quote
     * converted to two single quotes
     * @throws NullPointerException if val is {@code null}
     * @throws SQLException if a database access error occurs
     *
     * @since 9
     */
     default String enquoteLiteral(String val)  throws SQLException {
         return "'" + val.replace("'", "''") +  "'";
    }


     /**
     * Returns a SQL identifier. If {@code identifier} is a simple SQL identifier:
     * <ul>
     * <li>Return the original value if {@code alwaysQuote} is
     * {@code false}</li>
     * <li>Return a delimited identifier if {@code alwaysQuote} is
     * {@code true}</li>
     * </ul>
     *
     * If {@code identifier} is not a simple SQL identifier, {@code identifier} will be
     * enclosed in double quotes if not already present. If the datasource does
     * not support double quotes for delimited identifiers, the
     * identifier should be enclosed by the string returned from
     * {@link DatabaseMetaData#getIdentifierQuoteString}.  If the datasource
     * does not support delimited identifiers, a
     * {@code SQLFeatureNotSupportedException} should be thrown.
     * <p>
     * A {@code SQLException} will be thrown if {@code identifier} contains any
     * characters invalid in a delimited identifier or the identifier length is
     * invalid for the datasource.
     *
     * @implSpec
     * The default implementation uses the following criteria to
     * determine a valid simple SQL identifier:
     * <ul>
     * <li>The string is not enclosed in double quotes</li>
     * <li>The first character is an alphabetic character from a through z, or
     * from A through Z</li>
     * <li>The name only contains alphanumeric characters or the character "_"</li>
     * </ul>
     *
     * The default implementation will throw a {@code SQLException} if:
     * <ul>
     * <li>{@code identifier} contains a {@code null} character or double quote and is not
     * a simple SQL identifier.</li>
     * <li>The length of {@code identifier} is less than 1 or greater than 128 characters
     * </ul>
     * <blockquote>
     * <table class="striped" >
     * <caption>Examples of the conversion:</caption>
     * <thead>
     * <tr>
     * <th scope="col">identifier</th>
     * <th scope="col">alwaysQuote</th>
     * <th scope="col">Result</th></tr>
     * </thead>
     * <tbody>
     * <tr>
     * <th scope="row">Hello</th>
     * <td>false</td>
     * <td>Hello</td>
     * </tr>
     * <tr>
     * <th scope="row">Hello</th>
     * <td>true</td>
     * <td>"Hello"</td>
     * </tr>
     * <tr>
     * <th scope="row">G'Day</th>
     * <td>false</td>
     * <td>"G'Day"</td>
     * </tr>
     * <tr>
     * <th scope="row">"Bruce Wayne"</th>
     * <td>false</td>
     * <td>"Bruce Wayne"</td>
     * </tr>
     * <tr>
     * <th scope="row">"Bruce Wayne"</th>
     * <td>true</td>
     * <td>"Bruce Wayne"</td>
     * </tr>
     * <tr>
     * <th scope="row">GoodDay$</th>
     * <td>false</td>
     * <td>"GoodDay$"</td>
     * </tr>
     * <tr>
     * <th scope="row">Hello"World</th>
     * <td>false</td>
     * <td>SQLException</td>
     * </tr>
     * <tr>
     * <th scope="row">"Hello"World"</th>
     * <td>false</td>
     * <td>SQLException</td>
     * </tr>
     * </tbody>
     * </table>
     * </blockquote>
     * @implNote
     * JDBC driver implementations may need to provide their own implementation
     * of this method in order to meet the requirements of the underlying
     * datasource.
     * @param identifier a SQL identifier
     * @param alwaysQuote indicates if a simple SQL identifier should be
     * returned as a quoted identifier
     * @return A simple SQL identifier or a delimited identifier
     * @throws SQLException if identifier is not a valid identifier
     * @throws SQLFeatureNotSupportedException if the datasource does not support
     * delimited identifiers
     * @throws NullPointerException if identifier is {@code null}
     *
     * @since 9
     */
    default String enquoteIdentifier(String identifier, boolean alwaysQuote) throws SQLException {
        int len = identifier.length();
        if (len < 1 || len > 128) {
            throw new SQLException("Invalid name");
        }
        if (Pattern.compile("[\\p{Alpha}][\\p{Alnum}_]*").matcher(identifier).matches()) {
            return alwaysQuote ?  "\"" + identifier + "\"" : identifier;
        }
        if (identifier.matches("^\".+\"$")) {
            identifier = identifier.substring(1, len - 1);
        }
        if (Pattern.compile("[^\u0000\"]+").matcher(identifier).matches()) {
            return "\"" + identifier + "\"";
        } else {
            throw new SQLException("Invalid name");
        }
    }

    /**
     * Retrieves whether {@code identifier} is a simple SQL identifier.
     *
     * @implSpec The default implementation uses the following criteria to
     * determine a valid simple SQL identifier:
     * <ul>
     * <li>The string is not enclosed in double quotes</li>
     * <li>The first character is an alphabetic character from a through z, or
     * from A through Z</li>
     * <li>The string only contains alphanumeric characters or the character
     * "_"</li>
     * <li>The string is between 1 and 128 characters in length inclusive</li>
     * </ul>
     *
     * <blockquote>
     * <table class="striped" >
     * <caption>Examples of the conversion:</caption>
     * <thead>
     * <tr>
     * <th scope="col">identifier</th>
     * <th scope="col">Simple Identifier</th>
     * </thead>
     *
     * <tbody>
     * <tr>
     * <th scope="row">Hello</th>
     * <td>true</td>
     * </tr>
     * <tr>
     * <th scope="row">G'Day</th>
     * <td>false</td>
     * </tr>
     * <tr>
     * <th scope="row">"Bruce Wayne"</th>
     * <td>false</td>
     * </tr>
     * <tr>
     * <th scope="row">GoodDay$</th>
     * <td>false</td>
     * </tr>
     * <tr>
     * <th scope="row">Hello"World</th>
     * <td>false</td>
     * </tr>
     * <tr>
     * <th scope="row">"Hello"World"</th>
     * <td>false</td>
     * </tr>
     * </tbody>
     * </table>
     * </blockquote>
     * @implNote JDBC driver implementations may need to provide their own
     * implementation of this method in order to meet the requirements of the
     * underlying datasource.
     * @param identifier a SQL identifier
     * @return  true if  a simple SQL identifier, false otherwise
     * @throws NullPointerException if identifier is {@code null}
     * @throws SQLException if a database access error occurs
     *
     * @since 9
     */
    default boolean isSimpleIdentifier(String identifier) throws SQLException {
        int len = identifier.length();
        return len >= 1 && len <= 128
                && Pattern.compile("[\\p{Alpha}][\\p{Alnum}_]*").matcher(identifier).matches();
    }

    /**
    * Returns a {@code String} representing a National Character Set Literal
    * enclosed in single quotes and prefixed with a upper case letter N.
    * Any occurrence of a single quote within the string will be replaced
    * by two single quotes.
    *
    * <blockquote>
    * <table class="striped">
    * <caption>Examples of the conversion:</caption>
    * <thead>
    * <tr>
    * <th scope="col">Value</th>
    * <th scope="col">Result</th>
    * </tr>
    * </thead>
    * <tbody>
    * <tr> <th scope="row">Hello</th> <td>N'Hello'</td> </tr>
    * <tr> <th scope="row">G'Day</th> <td>N'G''Day'</td> </tr>
    * <tr> <th scope="row">'G''Day'</th>
    * <td>N'''G''''Day'''</td> </tr>
    * <tr> <th scope="row">I'''M</th> <td>N'I''''''M'</td>
    * <tr> <th scope="row">N'Hello'</th> <td>N'N''Hello'''</td> </tr>
    *
    * </tbody>
    * </table>
    * </blockquote>
    * @implNote
    * JDBC driver implementations may need to provide their own implementation
    * of this method in order to meet the requirements of the underlying
    * datasource. An implementation of enquoteNCharLiteral may accept a different
    * set of characters than that accepted by the same drivers implementation of
    * enquoteLiteral.
    * @param val a character string
    * @return the result of replacing every single quote character in the
    * argument by two single quote characters where this entire result is
    * then prefixed with 'N'.
    * @throws NullPointerException if val is {@code null}
    * @throws SQLException if a database access error occurs
    *
    * @since 9
    */
    default String enquoteNCharLiteral(String val)  throws SQLException {
        return "N'" + val.replace("'", "''") +  "'";
   }
}
