
org.jooq.Binding Maven / Gradle / Ivy
/*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Other licenses:
* -----------------------------------------------------------------------------
* Commercial licenses for this work are available. These replace the above
* Apache-2.0 license and offer limited warranties, support, maintenance, and
* commercial database integrations.
*
* For more information, please visit: http://www.jooq.org/licenses
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*
*/
package org.jooq;
import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLInput;
import java.sql.SQLOutput;
import java.sql.Timestamp;
import java.util.function.Consumer;
import org.jooq.exception.DataAccessException;
import org.jooq.impl.DefaultBinding;
import org.jooq.impl.SQLDataType;
import org.jetbrains.annotations.NotNull;
/**
* An SPI (Service Provider Interface) that exposes all low-level interactions
* with JDBC bind variables.
*
* This SPI is used by jOOQ users to implement support for custom data types
* that would otherwise not be supported by jOOQ and/or JDBC. All of jOOQ's
* internal support for bind variable types is implemented in
* {@link DefaultBinding}.
*
*
Creating user defined {@link DataType}s
*
* jOOQ provides built in data types through {@link SQLDataType}. Users can
* define their own data types programmatically by calling
* {@link DataType#asConvertedDataType(Converter)} or
* {@link DataType#asConvertedDataType(Binding)}, for example. Custom data types
* can also be defined on generated code using the
* <forcedType/>
configuration, see the manual for more details
*
* @param The database type - i.e. any type available from
* {@link SQLDataType}
* @param The user type
* @author Lukas Eder
*/
public interface Binding extends Serializable {
/**
* A converter that can convert between the database type and the custom
* type.
*
* While the {@link Converter} property of a binding is not optional
* ({@link Converter#fromType()} and {@link Converter#toType()} are needed
* by jOOQ's internals), the conversion implementation (i.e.
* {@link Converter#from(Object)} and {@link Converter#to(Object)}) isn't
* strictly required if implementations don't rely on it.
*/
@NotNull
Converter converter();
/**
* Generate SQL code for the bind variable.
*
* Implementations should generate SQL code onto
* {@link BindingSQLContext#render()}, given the context's bind variable
* located at {@link BindingSQLContext#value()}. Examples of such SQL code
* are:
*
* "?"
: Default implementations can simply generate a
* question mark.
*
*
* "123"
: Implementations may choose to inline bind
* variables to influence execution plan generation.
*
* {@link RenderContext#paramType()} contains information whether inlined
* bind variables are expected in the current context.
*
*
* "CAST(? AS DATE)"
: Cast a database to a more specific
* type. This can be useful in databases like Oracle, which map both
* DATE
and TIMESTAMP
SQL types to
* {@link Timestamp}.
*
* {@link RenderContext#castMode()} may contain some hints about whether
* casting is suggested in the current context.
*
*
* "?::json"
: Vendor-specific bind variables can be
* supported, e.g. {@link SQLDialect#POSTGRES}'s JSON data type.
*
*
* Implementations must provide consistent behaviour between
* {@link #sql(BindingSQLContext)} and
* {@link #set(BindingSetStatementContext)}, i.e. when bind variables are
* inlined, then they must not be bound to the {@link PreparedStatement} in
* {@link #set(BindingSetStatementContext)}
*
* @param ctx The context object containing all argument objects.
* @throws SQLException Implementations are allowed to pass on all
* {@link SQLException}s to the caller to be wrapped in
* {@link DataAccessException}s.
*/
void sql(BindingSQLContext ctx) throws SQLException;
/**
* Register a {@link CallableStatement}'s OUT
parameter.
*
* @param ctx The context object containing all argument objects.
* @throws SQLException Implementations are allowed to pass on all
* {@link SQLException}s to the caller to be wrapped in
* {@link DataAccessException}s.
*/
void register(BindingRegisterContext ctx) throws SQLException;
/**
* Set a {@link PreparedStatement}'s IN
parameter.
*
* @param ctx The context object containing all argument objects.
* @throws SQLException Implementations are allowed to pass on all
* {@link SQLException}s to the caller to be wrapped in
* {@link DataAccessException}s.
*/
void set(BindingSetStatementContext ctx) throws SQLException;
/**
* Set a {@link SQLOutput}'s IN
parameter.
*
* @param ctx The context object containing all argument objects.
* @throws SQLException Implementations are allowed to pass on all
* {@link SQLException}s to the caller to be wrapped in
* {@link DataAccessException}s.
*/
void set(BindingSetSQLOutputContext ctx) throws SQLException;
/**
* Get a {@link ResultSet}'s OUT
value.
*
* Implementations are expected to produce a value by calling
* {@link BindingGetResultSetContext#value(Object)}, passing the resulting
* value to the method.
*
* @param ctx The context object containing all argument objects.
* @throws SQLException Implementations are allowed to pass on all
* {@link SQLException}s to the caller to be wrapped in
* {@link DataAccessException}s.
*/
void get(BindingGetResultSetContext ctx) throws SQLException;
/**
* Get a {@link CallableStatement}'s OUT
value.
*
* Implementations are expected to produce a value by calling
* {@link BindingGetStatementContext#value(Object)}, passing the resulting
* value to the method.
*
* @param ctx The context object containing all argument objects.
* @throws SQLException Implementations are allowed to pass on all
* {@link SQLException}s to the caller to be wrapped in
* {@link DataAccessException}s.
*/
void get(BindingGetStatementContext ctx) throws SQLException;
/**
* Get a {@link SQLInput}'s OUT
value.
*
* Implementations are expected to produce a value by calling
* {@link BindingGetSQLInputContext#value(Object)}, passing the resulting
* value to the method.
*
* @param ctx The context object containing all argument objects.
* @throws SQLException Implementations are allowed to pass on all
* {@link SQLException}s to the caller to be wrapped in
* {@link DataAccessException}s.
*/
void get(BindingGetSQLInputContext ctx) throws SQLException;
/**
* Construct a binding from functions.
*/
@NotNull
static Binding of(
Converter converter,
Consumer super BindingSQLContext> sqlContext,
Consumer super BindingGetResultSetContext> getResultSetContext,
Consumer super BindingSetStatementContext> setStatementContext
) {
return of(
converter,
sqlContext,
getResultSetContext,
setStatementContext,
ctx -> { throw new UnsupportedOperationException(); },
ctx -> { throw new UnsupportedOperationException(); },
ctx -> { throw new UnsupportedOperationException(); },
ctx -> { throw new UnsupportedOperationException(); }
);
}
/**
* Construct a binding from functions.
*/
@NotNull
static Binding of(
Converter converter,
Consumer super BindingSQLContext> sqlContext,
Consumer super BindingGetResultSetContext> getResultSetContext,
Consumer super BindingSetStatementContext> setStatementContext,
Consumer super BindingRegisterContext> registerContext,
Consumer super BindingGetStatementContext> getStatementContext
) {
return of(
converter,
sqlContext,
getResultSetContext,
setStatementContext,
registerContext,
getStatementContext,
ctx -> { throw new UnsupportedOperationException(); },
ctx -> { throw new UnsupportedOperationException(); }
);
}
/**
* Construct a binding from functions.
*/
@NotNull
static Binding of(
Converter converter,
Consumer super BindingSQLContext> sqlContext,
Consumer super BindingGetResultSetContext> getResultSetContext,
Consumer super BindingSetStatementContext> setStatementContext,
Consumer super BindingRegisterContext> registerContext,
Consumer super BindingGetStatementContext> getStatementContext,
Consumer super BindingGetSQLInputContext> getSqlInputContext,
Consumer super BindingSetSQLOutputContext> setSqlOutputContext
) {
return new Binding() {
@Override
public final Converter converter() {
return converter;
}
@Override
public final void sql(BindingSQLContext ctx) throws SQLException {
sqlContext.accept(ctx);
}
@Override
public final void register(BindingRegisterContext ctx) throws SQLException {
registerContext.accept(ctx);
}
@Override
public final void set(BindingSetStatementContext ctx) throws SQLException {
setStatementContext.accept(ctx);
}
@Override
public final void set(BindingSetSQLOutputContext ctx) throws SQLException {
setSqlOutputContext.accept(ctx);
}
@Override
public final void get(BindingGetResultSetContext ctx) throws SQLException {
getResultSetContext.accept(ctx);
}
@Override
public final void get(BindingGetStatementContext ctx) throws SQLException {
getStatementContext.accept(ctx);
}
@Override
public final void get(BindingGetSQLInputContext ctx) throws SQLException {
getSqlInputContext.accept(ctx);
}
};
}
}