org.firebirdsql.jdbc.GeneratedKeysSupport Maven / Gradle / Ivy
Show all versions of jaybird Show documentation
/*
* Firebird Open Source JDBC Driver
*
* Distributable under LGPL license.
* You may obtain a copy of the License at http://www.gnu.org/copyleft/lgpl.html
*
* This program 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
* LGPL License for more details.
*
* This file was created by members of the firebird development team.
* All individual contributions remain the Copyright (C) of those
* individuals. Contributors to this file are either listed here or
* can be obtained from a source control history command.
*
* All rights reserved.
*/
package org.firebirdsql.jdbc;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.EnumSet;
import java.util.Set;
/**
* Provides support for generated keys depending on the level configured and the availability of the parser.
*
* @author Mark Rotteveel
* @since 4.0
*/
interface GeneratedKeysSupport {
/**
* Process SQL statement text according to {@code autoGeneratedKeys} value.
*
* For {@code Statement.NO_GENERATED_KEYS} the statement will not be processed, for
* {@code Statement.RETURN_GENERATED_KEYS} it will be processed depending on configuration and feature support.
*
*
* The query will only be modified if 1) it is capable of returning keys, 2) does not already contain a RETURNING
* clause and 3) availability and configured support for generated keys.
*
*
* @param sql
* SQL query string
* @param autoGeneratedKeys
* Generated keys option ({@link Statement#NO_GENERATED_KEYS} or {@link Statement#RETURN_GENERATED_KEYS})
* @return Query object
* @throws SQLException
* If generated keys support is not available or for database access errors
*/
Query buildQuery(String sql, int autoGeneratedKeys) throws SQLException;
/**
* Process SQL statement for adding generated key columns by their ordinal position.
*
* The query will only be modified if 1) it is capable of returning keys, 2) does not already contain a RETURNING
* clause and 3) availability and configured support for generated keys.
*
*
* The columns are added in order of indexes in the {@code columnIndexes} array. The values of columnIndexes are
* taken as the {@code ORDINAL_POSITION} returned by {@link java.sql.DatabaseMetaData#getColumns(String, String,
* String, String)}.
* When a column index does not exist for the table of the query, a {@link SQLException} will be thrown.
*
*
* @param sql
* SQL query string
* @param columnIndexes
* Array of ORDINAL_POSITION values of the columns to return as generated key
* @return Query object
* @throws SQLException
* If generated keys support is not available or for database access errors
*/
Query buildQuery(String sql, int[] columnIndexes) throws SQLException;
/**
* Process SQL statement for adding generated key columns by name.
*
* The query will only be modified if 1) it is capable of returning keys, 2) does not already contain a RETURNING
* clause and 3) availability and configured support for generated keys.
*
*
* The {@code columnNames} passed are taken as is and included in a new returning clause. There is no check for
* actual existence of these columns, nor are they quoted (this is subject to change).
*
*
* @param sql
* SQL query string
* @param columnNames
* Array of column names to return as generated key
* @return Query object
* @throws SQLException
* If generated keys support is not available or for database access errors
*/
Query buildQuery(String sql, String[] columnNames) throws SQLException;
/**
* @return Unmodifiable set of supported query types (intended for testing)
*/
Set supportedQueryTypes();
/**
* @return {@code true} if generated keys support is enabled for at least one query type
*/
boolean supportsGetGeneratedKeys();
/**
* Query types that can be used for generated keys retrieval
*/
enum QueryType {
INSERT(2, 0, "insert"),
UPDATE(2, 1, "update"),
DELETE(2, 1, "delete"),
MERGE(3, 0, "merge"),
UPDATE_OR_INSERT(2, 1, "update_or_insert"),
/**
* Marks unsupported query types (used as a 'null-object')
*/
UNSUPPORTED(Integer.MAX_VALUE, Integer.MAX_VALUE, "unsupported");
private final int sinceMajor;
private final int sinceMinor;
private final String configName;
/**
* Creates QueryType.
*
* @param sinceMajor
* Major version that introduced {@code RETURNING} support
* @param sinceMinor
* Minor version (of {@code sinceMajor}) that introduced {@code RETURNING} support
* @param configName
* Name for this query type in config options (should be lowercase, but not enforced)
*/
QueryType(int sinceMajor, int sinceMinor, String configName) {
this.sinceMajor = sinceMajor;
this.sinceMinor = sinceMinor;
this.configName = configName;
}
/**
* Does the {@code configName} of this {@code QueryType} match the specified name (case-sensitive!).
*
* Should only be used from {@link GeneratedKeysSupportFactory}.
*
*
* @param name
* Name to match
* @return {@code true} if {@code name} is equal to the {@code configName} of this enum value, {@code false}
* otherwise.
*/
boolean matches(String name) {
return configName.equals(name);
}
/**
* A set of query types supported for the specified version.
*
* @param major
* Major version
* @param minor
* Minor version of {@code major}
* @return Set of available query types with {@code RETURNING} support; can be empty
*/
static Set returningSupportForVersion(int major, int minor) {
EnumSet supportedQueryTypes = EnumSet.noneOf(QueryType.class);
for (QueryType queryType : values()) {
if (major > queryType.sinceMajor
|| major == queryType.sinceMajor && minor >= queryType.sinceMinor) {
supportedQueryTypes.add(queryType);
}
}
return supportedQueryTypes;
}
}
/**
* Parsed and possibly enhanced query for generated keys.
*/
final class Query {
private final boolean generatesKeys;
private final String queryString;
Query(boolean generatesKeys, String queryString) {
this.generatesKeys = generatesKeys;
this.queryString = queryString;
}
/**
* @return {@code true} if this query generates keys (ie: has a {@code RETURNING} clause)
*/
boolean generatesKeys() {
return generatesKeys;
}
/**
* @return Query string
*/
String getQueryString() {
return queryString;
}
}
}