HHH-7387 - Integrate Draft 6 of the JPA 2.1 spec : REF_CURSOR param handling
This commit is contained in:
parent
cb13cea1ac
commit
219707df1d
|
@ -27,6 +27,7 @@ import javax.persistence.ParameterMode;
|
|||
import javax.persistence.TemporalType;
|
||||
import java.util.List;
|
||||
|
||||
import org.hibernate.internal.StoredProcedureCallImpl;
|
||||
import org.hibernate.type.Type;
|
||||
|
||||
/**
|
||||
|
|
|
@ -1466,14 +1466,16 @@ public abstract class Dialect implements ConversionContext {
|
|||
// callable statement support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
* Registers an OUT parameter which will be returning a
|
||||
* {@link java.sql.ResultSet}. How this is accomplished varies greatly
|
||||
* from DB to DB, hence its inclusion (along with {@link #getResultSet}) here.
|
||||
* Registers a parameter (either OUT, or the new REF_CURSOR param type available in Java 8) capable of
|
||||
* returning {@link java.sql.ResultSet} *by position*. Pre-Java 8, registering such ResultSet-returning
|
||||
* parameters varied greatly across database and drivers; hence its inclusion as part of the Dialect contract.
|
||||
*
|
||||
* @param statement The callable statement.
|
||||
* @param position The bind position at which to register the OUT param.
|
||||
* @param position The bind position at which to register the output param.
|
||||
*
|
||||
* @return The number of (contiguous) bind positions used.
|
||||
* @throws SQLException Indicates problems registering the OUT param.
|
||||
*
|
||||
* @throws SQLException Indicates problems registering the param.
|
||||
*/
|
||||
public int registerResultSetOutParameter(CallableStatement statement, int position) throws SQLException {
|
||||
throw new UnsupportedOperationException(
|
||||
|
@ -1482,6 +1484,25 @@ public abstract class Dialect implements ConversionContext {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers a parameter (either OUT, or the new REF_CURSOR param type available in Java 8) capable of
|
||||
* returning {@link java.sql.ResultSet} *by name*. Pre-Java 8, registering such ResultSet-returning
|
||||
* parameters varied greatly across database and drivers; hence its inclusion as part of the Dialect contract.
|
||||
*
|
||||
* @param statement The callable statement.
|
||||
* @param name The parameter name (for drivers which support named parameters).
|
||||
*
|
||||
* @return The number of (contiguous) bind positions used.
|
||||
*
|
||||
* @throws SQLException Indicates problems registering the param.
|
||||
*/
|
||||
public int registerResultSetOutParameter(CallableStatement statement, String name) throws SQLException {
|
||||
throw new UnsupportedOperationException(
|
||||
getClass().getName() +
|
||||
" does not support resultsets via stored procedures"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a callable statement previously processed by {@link #registerResultSetOutParameter},
|
||||
* extract the {@link java.sql.ResultSet} from the OUT parameter.
|
||||
|
@ -1497,6 +1518,42 @@ public abstract class Dialect implements ConversionContext {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a callable statement previously processed by {@link #registerResultSetOutParameter},
|
||||
* extract the {@link java.sql.ResultSet}.
|
||||
*
|
||||
* @param statement The callable statement.
|
||||
* @param position The bind position at which to register the output param.
|
||||
*
|
||||
* @return The extracted result set.
|
||||
*
|
||||
* @throws SQLException Indicates problems extracting the result set.
|
||||
*/
|
||||
public ResultSet getResultSet(CallableStatement statement, int position) throws SQLException {
|
||||
throw new UnsupportedOperationException(
|
||||
getClass().getName() +
|
||||
" does not support resultsets via stored procedures"
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a callable statement previously processed by {@link #registerResultSetOutParameter},
|
||||
* extract the {@link java.sql.ResultSet} from the OUT parameter.
|
||||
*
|
||||
* @param statement The callable statement.
|
||||
* @param name The parameter name (for drivers which support named parameters).
|
||||
*
|
||||
* @return The extracted result set.
|
||||
*
|
||||
* @throws SQLException Indicates problems extracting the result set.
|
||||
*/
|
||||
public ResultSet getResultSet(CallableStatement statement, String name) throws SQLException {
|
||||
throw new UnsupportedOperationException(
|
||||
getClass().getName() +
|
||||
" does not support resultsets via stored procedures"
|
||||
);
|
||||
}
|
||||
|
||||
// current timestamp support ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
/**
|
||||
|
|
|
@ -57,6 +57,7 @@ import org.hibernate.internal.util.ReflectHelper;
|
|||
import org.hibernate.internal.util.config.ConfigurationHelper;
|
||||
import org.hibernate.service.jdbc.connections.spi.ConnectionProvider;
|
||||
import org.hibernate.service.jdbc.connections.spi.MultiTenantConnectionProvider;
|
||||
import org.hibernate.service.jdbc.cursor.internal.StandardRefCursorSupport;
|
||||
import org.hibernate.service.jdbc.dialect.spi.DialectFactory;
|
||||
import org.hibernate.service.spi.Configurable;
|
||||
import org.hibernate.service.spi.ServiceRegistryAwareService;
|
||||
|
@ -92,6 +93,8 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
Dialect dialect = null;
|
||||
LobCreatorBuilder lobCreatorBuilder = null;
|
||||
|
||||
boolean metaSupportsRefCursors = false;
|
||||
boolean metaSupportsNamedParams = false;
|
||||
boolean metaSupportsScrollable = false;
|
||||
boolean metaSupportsGetGeneratedKeys = false;
|
||||
boolean metaSupportsBatchUpdates = false;
|
||||
|
@ -133,6 +136,8 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
LOG.debugf( "JDBC version : %s.%s", meta.getJDBCMajorVersion(), meta.getJDBCMinorVersion() );
|
||||
}
|
||||
|
||||
metaSupportsRefCursors = StandardRefCursorSupport.supportsRefCursors( meta );
|
||||
metaSupportsNamedParams = meta.supportsNamedParameters();
|
||||
metaSupportsScrollable = meta.supportsResultSetType( ResultSet.TYPE_SCROLL_INSENSITIVE );
|
||||
metaSupportsBatchUpdates = meta.supportsBatchUpdates();
|
||||
metaReportsDDLCausesTxnCommit = meta.dataDefinitionCausesTransactionCommit();
|
||||
|
@ -191,6 +196,8 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
this.sqlStatementLogger = new SqlStatementLogger( showSQL, formatSQL );
|
||||
|
||||
this.extractedMetaDataSupport = new ExtractedDatabaseMetaDataImpl(
|
||||
metaSupportsRefCursors,
|
||||
metaSupportsNamedParams,
|
||||
metaSupportsScrollable,
|
||||
metaSupportsGetGeneratedKeys,
|
||||
metaSupportsBatchUpdates,
|
||||
|
@ -316,6 +323,8 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
}
|
||||
|
||||
private static class ExtractedDatabaseMetaDataImpl implements ExtractedDatabaseMetaData {
|
||||
private final boolean supportsRefCursors;
|
||||
private final boolean supportsNamedParameters;
|
||||
private final boolean supportsScrollableResults;
|
||||
private final boolean supportsGetGeneratedKeys;
|
||||
private final boolean supportsBatchUpdates;
|
||||
|
@ -329,6 +338,8 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
private final LinkedHashSet<TypeInfo> typeInfoSet;
|
||||
|
||||
private ExtractedDatabaseMetaDataImpl(
|
||||
boolean supportsRefCursors,
|
||||
boolean supportsNamedParameters,
|
||||
boolean supportsScrollableResults,
|
||||
boolean supportsGetGeneratedKeys,
|
||||
boolean supportsBatchUpdates,
|
||||
|
@ -340,6 +351,8 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
String connectionSchemaName,
|
||||
String connectionCatalogName,
|
||||
LinkedHashSet<TypeInfo> typeInfoSet) {
|
||||
this.supportsRefCursors = supportsRefCursors;
|
||||
this.supportsNamedParameters = supportsNamedParameters;
|
||||
this.supportsScrollableResults = supportsScrollableResults;
|
||||
this.supportsGetGeneratedKeys = supportsGetGeneratedKeys;
|
||||
this.supportsBatchUpdates = supportsBatchUpdates;
|
||||
|
@ -353,6 +366,16 @@ public class JdbcServicesImpl implements JdbcServices, ServiceRegistryAwareServi
|
|||
this.typeInfoSet = typeInfoSet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsRefCursors() {
|
||||
return supportsRefCursors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNamedParameters() {
|
||||
return supportsNamedParameters;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsScrollableResults() {
|
||||
return supportsScrollableResults;
|
||||
|
|
|
@ -44,6 +44,22 @@ public interface ExtractedDatabaseMetaData {
|
|||
UNKOWN
|
||||
}
|
||||
|
||||
/**
|
||||
* Does the driver report supporting named parameters?
|
||||
*
|
||||
* @return {@code true} indicates the driver reported true; {@code false} indicates the driver reported false
|
||||
* or that the driver could not be asked.
|
||||
*/
|
||||
public boolean supportsNamedParameters();
|
||||
|
||||
/**
|
||||
* Does the driver report supporting REF_CURSORs?
|
||||
*
|
||||
* @return {@code true} indicates the driver reported true; {@code false} indicates the driver reported false
|
||||
* or that the driver could not be asked.
|
||||
*/
|
||||
public boolean supportsRefCursors();
|
||||
|
||||
/**
|
||||
* Did the driver report to supporting scrollable result sets?
|
||||
*
|
||||
|
|
|
@ -47,12 +47,14 @@ import org.hibernate.StoredProcedureCall;
|
|||
import org.hibernate.StoredProcedureOutputs;
|
||||
import org.hibernate.cfg.NotYetImplementedException;
|
||||
import org.hibernate.engine.ResultSetMappingDefinition;
|
||||
import org.hibernate.engine.jdbc.spi.ExtractedDatabaseMetaData;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryReturn;
|
||||
import org.hibernate.engine.query.spi.sql.NativeSQLQueryRootReturn;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.util.StringHelper;
|
||||
import org.hibernate.persister.entity.EntityPersister;
|
||||
import org.hibernate.service.jdbc.cursor.spi.RefCursorSupport;
|
||||
import org.hibernate.type.DateType;
|
||||
import org.hibernate.type.ProcedureParameterExtractionAware;
|
||||
import org.hibernate.type.Type;
|
||||
|
@ -156,22 +158,42 @@ public class StoredProcedureCallImpl extends AbstractBasicQueryContractImpl impl
|
|||
|
||||
private void registerParameter(StoredProcedureParameterImplementor parameter) {
|
||||
if ( StringHelper.isNotEmpty( parameter.getName() ) ) {
|
||||
if ( typeOfParameters == TypeOfParameter.POSITIONAL ) {
|
||||
throw new QueryException( "Cannot mix named and positional parameters" );
|
||||
}
|
||||
typeOfParameters = TypeOfParameter.NAMED;
|
||||
registeredParameters.add( parameter );
|
||||
prepareForNamedParameters();
|
||||
}
|
||||
else if ( parameter.getPosition() != null ) {
|
||||
if ( typeOfParameters == TypeOfParameter.NAMED ) {
|
||||
throw new QueryException( "Cannot mix named and positional parameters" );
|
||||
}
|
||||
typeOfParameters = TypeOfParameter.POSITIONAL;
|
||||
registeredParameters.add( parameter.getPosition(), parameter );
|
||||
prepareForPositionalParameters();
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException( "Given parameter did not define name nor position [" + parameter + "]" );
|
||||
}
|
||||
registeredParameters.add( parameter );
|
||||
}
|
||||
|
||||
private void prepareForPositionalParameters() {
|
||||
if ( typeOfParameters == TypeOfParameter.NAMED ) {
|
||||
throw new QueryException( "Cannot mix named and positional parameters" );
|
||||
}
|
||||
typeOfParameters = TypeOfParameter.POSITIONAL;
|
||||
}
|
||||
|
||||
private void prepareForNamedParameters() {
|
||||
if ( typeOfParameters == TypeOfParameter.POSITIONAL ) {
|
||||
throw new QueryException( "Cannot mix named and positional parameters" );
|
||||
}
|
||||
if ( typeOfParameters == null ) {
|
||||
// protect to only do this check once
|
||||
final ExtractedDatabaseMetaData databaseMetaData = session().getTransactionCoordinator()
|
||||
.getJdbcCoordinator()
|
||||
.getLogicalConnection()
|
||||
.getJdbcServices()
|
||||
.getExtractedMetaDataSupport();
|
||||
if ( ! databaseMetaData.supportsNamedParameters() ) {
|
||||
throw new QueryException(
|
||||
"Named stored procedure parameters used, but JDBC driver does not support named parameters"
|
||||
);
|
||||
}
|
||||
typeOfParameters = TypeOfParameter.NAMED;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -183,8 +205,8 @@ public class StoredProcedureCallImpl extends AbstractBasicQueryContractImpl impl
|
|||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public List getRegisteredParameters() {
|
||||
return registeredParameters;
|
||||
public List<StoredProcedureParameter> getRegisteredParameters() {
|
||||
return new ArrayList<StoredProcedureParameter>( registeredParameters );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -197,7 +219,8 @@ public class StoredProcedureCallImpl extends AbstractBasicQueryContractImpl impl
|
|||
return parameter;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException( "Could not locate parameter registered under that name [" + name + "]" ); }
|
||||
throw new IllegalArgumentException( "Could not locate parameter registered under that name [" + name + "]" );
|
||||
}
|
||||
|
||||
@Override
|
||||
public StoredProcedureParameterImplementor getRegisteredParameter(int position) {
|
||||
|
@ -320,6 +343,16 @@ public class StoredProcedureCallImpl extends AbstractBasicQueryContractImpl impl
|
|||
return qp;
|
||||
}
|
||||
|
||||
public StoredProcedureParameterImplementor[] collectRefCursorParameters() {
|
||||
List<StoredProcedureParameterImplementor> refCursorParams = new ArrayList<StoredProcedureParameterImplementor>();
|
||||
for ( StoredProcedureParameterImplementor param : registeredParameters ) {
|
||||
if ( param.getMode() == ParameterMode.REF_CURSOR ) {
|
||||
refCursorParams.add( param );
|
||||
}
|
||||
}
|
||||
return refCursorParams.toArray( new StoredProcedureParameterImplementor[refCursorParams.size()] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Ternary logic enum
|
||||
*/
|
||||
|
@ -442,6 +475,19 @@ public class StoredProcedureCallImpl extends AbstractBasicQueryContractImpl impl
|
|||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// we have a REF_CURSOR type param
|
||||
if ( procedureCall.typeOfParameters == TypeOfParameter.NAMED ) {
|
||||
session().getFactory().getServiceRegistry()
|
||||
.getService( RefCursorSupport.class )
|
||||
.registerRefCursorParameter( statement, getName() );
|
||||
}
|
||||
else {
|
||||
session().getFactory().getServiceRegistry()
|
||||
.getService( RefCursorSupport.class )
|
||||
.registerRefCursorParameter( statement, getPosition() );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public int[] getSqlTypes() {
|
||||
|
@ -476,6 +522,13 @@ public class StoredProcedureCallImpl extends AbstractBasicQueryContractImpl impl
|
|||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public T extract(CallableStatement statement) {
|
||||
if ( mode == ParameterMode.IN ) {
|
||||
throw new QueryException( "IN parameter not valid for output extraction" );
|
||||
}
|
||||
else if ( mode == ParameterMode.REF_CURSOR ) {
|
||||
throw new QueryException( "REF_CURSOR parameters should be accessed via results" );
|
||||
}
|
||||
|
||||
try {
|
||||
if ( ProcedureParameterExtractionAware.class.isInstance( hibernateType ) ) {
|
||||
return (T) ( (ProcedureParameterExtractionAware) hibernateType ).extract( statement, startIndex, session() );
|
||||
|
|
|
@ -23,24 +23,29 @@
|
|||
*/
|
||||
package org.hibernate.internal;
|
||||
|
||||
import javax.persistence.ParameterMode;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.hibernate.JDBCException;
|
||||
import org.hibernate.StoredProcedureCall.StoredProcedureParameter;
|
||||
import org.hibernate.StoredProcedureOutputs;
|
||||
import org.hibernate.StoredProcedureResultSetReturn;
|
||||
import org.hibernate.StoredProcedureReturn;
|
||||
import org.hibernate.StoredProcedureUpdateCountReturn;
|
||||
import org.hibernate.engine.spi.QueryParameters;
|
||||
import org.hibernate.engine.spi.SessionImplementor;
|
||||
import org.hibernate.internal.StoredProcedureCallImpl.StoredProcedureParameterImplementor;
|
||||
import org.hibernate.loader.custom.CustomLoader;
|
||||
import org.hibernate.loader.custom.CustomQuery;
|
||||
import org.hibernate.loader.custom.Return;
|
||||
import org.hibernate.loader.custom.sql.SQLQueryReturnProcessor;
|
||||
import org.hibernate.service.jdbc.cursor.spi.RefCursorSupport;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
|
@ -49,15 +54,19 @@ public class StoredProcedureOutputsImpl implements StoredProcedureOutputs {
|
|||
private final StoredProcedureCallImpl procedureCall;
|
||||
private final CallableStatement callableStatement;
|
||||
|
||||
private final StoredProcedureParameterImplementor[] refCursorParameters;
|
||||
private final CustomLoaderExtension loader;
|
||||
|
||||
private CurrentReturnDescriptor currentReturnDescriptor;
|
||||
|
||||
private boolean executed = false;
|
||||
private int refCursorParamIndex = 0;
|
||||
|
||||
StoredProcedureOutputsImpl(StoredProcedureCallImpl procedureCall, CallableStatement callableStatement) {
|
||||
this.procedureCall = procedureCall;
|
||||
this.callableStatement = callableStatement;
|
||||
|
||||
this.refCursorParameters = procedureCall.collectRefCursorParameters();
|
||||
// For now...
|
||||
this.loader = buildSpecializedCustomLoader( procedureCall );
|
||||
}
|
||||
|
@ -105,14 +114,16 @@ public class StoredProcedureOutputsImpl implements StoredProcedureOutputs {
|
|||
}
|
||||
}
|
||||
|
||||
currentReturnDescriptor = new CurrentReturnDescriptor( isResultSet, updateCount );
|
||||
currentReturnDescriptor = new CurrentReturnDescriptor( isResultSet, updateCount, refCursorParamIndex );
|
||||
}
|
||||
|
||||
return hasMoreResults( currentReturnDescriptor );
|
||||
}
|
||||
|
||||
private boolean hasMoreResults(CurrentReturnDescriptor descriptor) {
|
||||
return currentReturnDescriptor.isResultSet || currentReturnDescriptor.updateCount >= 0;
|
||||
return descriptor.isResultSet
|
||||
|| descriptor.updateCount >= 0
|
||||
|| descriptor.refCursorParamIndex < refCursorParameters.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -141,22 +152,45 @@ public class StoredProcedureOutputsImpl implements StoredProcedureOutputs {
|
|||
throw convert( e, "Error calling CallableStatement.getResultSet" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
else if ( copyReturnDescriptor.updateCount >= 0 ) {
|
||||
return new UpdateCountReturn( this, copyReturnDescriptor.updateCount );
|
||||
}
|
||||
else {
|
||||
this.refCursorParamIndex++;
|
||||
ResultSet resultSet;
|
||||
int refCursorParamIndex = copyReturnDescriptor.refCursorParamIndex;
|
||||
StoredProcedureParameterImplementor refCursorParam = refCursorParameters[refCursorParamIndex];
|
||||
if ( refCursorParam.getName() != null ) {
|
||||
resultSet = procedureCall.session().getFactory().getServiceRegistry()
|
||||
.getService( RefCursorSupport.class )
|
||||
.getResultSet( callableStatement, refCursorParam.getName() );
|
||||
}
|
||||
else {
|
||||
resultSet = procedureCall.session().getFactory().getServiceRegistry()
|
||||
.getService( RefCursorSupport.class )
|
||||
.getResultSet( callableStatement, refCursorParam.getPosition() );
|
||||
}
|
||||
return new ResultSetReturn( this, resultSet );
|
||||
}
|
||||
}
|
||||
|
||||
protected JDBCException convert(SQLException e, String message) {
|
||||
return procedureCall.session().getFactory().getSQLExceptionHelper().convert( e, message, procedureCall.getProcedureName() );
|
||||
return procedureCall.session().getFactory().getSQLExceptionHelper().convert(
|
||||
e,
|
||||
message,
|
||||
procedureCall.getProcedureName()
|
||||
);
|
||||
}
|
||||
|
||||
private static class CurrentReturnDescriptor {
|
||||
private final boolean isResultSet;
|
||||
private final int updateCount;
|
||||
private final int refCursorParamIndex;
|
||||
|
||||
private CurrentReturnDescriptor(boolean resultSet, int updateCount) {
|
||||
isResultSet = resultSet;
|
||||
private CurrentReturnDescriptor(boolean isResultSet, int updateCount, int refCursorParamIndex) {
|
||||
this.isResultSet = isResultSet;
|
||||
this.updateCount = updateCount;
|
||||
this.refCursorParamIndex = refCursorParamIndex;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -501,6 +501,12 @@ public class SimpleValue implements KeyValue {
|
|||
throws SQLException {
|
||||
return (X) converter.convertToEntityAttribute( realExtractor.extract( statement, index, options ) );
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return (X) converter.convertToEntityAttribute( realExtractor.extract( statement, new String[] {name}, options ) );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -38,6 +38,7 @@ import org.hibernate.service.config.internal.ConfigurationServiceInitiator;
|
|||
import org.hibernate.service.internal.SessionFactoryServiceRegistryFactoryInitiator;
|
||||
import org.hibernate.service.jdbc.connections.internal.ConnectionProviderInitiator;
|
||||
import org.hibernate.service.jdbc.connections.internal.MultiTenantConnectionProviderInitiator;
|
||||
import org.hibernate.service.jdbc.cursor.internal.RefCursorSupportInitiator;
|
||||
import org.hibernate.service.jdbc.dialect.internal.DialectFactoryInitiator;
|
||||
import org.hibernate.service.jdbc.dialect.internal.DialectResolverInitiator;
|
||||
import org.hibernate.service.jmx.internal.JmxServiceInitiator;
|
||||
|
@ -72,6 +73,7 @@ public class StandardServiceInitiators {
|
|||
serviceInitiators.add( DialectFactoryInitiator.INSTANCE );
|
||||
serviceInitiators.add( BatchBuilderInitiator.INSTANCE );
|
||||
serviceInitiators.add( JdbcServicesInitiator.INSTANCE );
|
||||
serviceInitiators.add( RefCursorSupportInitiator.INSTANCE );
|
||||
|
||||
serviceInitiators.add( MutableIdentifierGeneratorFactoryInitiator.INSTANCE);
|
||||
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.service.jdbc.cursor.internal;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.hibernate.service.jdbc.cursor.spi.RefCursorSupport;
|
||||
import org.hibernate.service.spi.BasicServiceInitiator;
|
||||
import org.hibernate.service.spi.ServiceRegistryImplementor;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class RefCursorSupportInitiator implements BasicServiceInitiator<RefCursorSupport> {
|
||||
public static final RefCursorSupportInitiator INSTANCE = new RefCursorSupportInitiator();
|
||||
|
||||
@Override
|
||||
public RefCursorSupport initiateService(Map configurationValues, ServiceRegistryImplementor registry) {
|
||||
return new StandardRefCursorSupport();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<RefCursorSupport> getServiceInitiated() {
|
||||
return RefCursorSupport.class;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,233 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.service.jdbc.cursor.internal;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.DatabaseMetaData;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.sql.Types;
|
||||
|
||||
import org.jboss.logging.Logger;
|
||||
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.engine.jdbc.spi.JdbcServices;
|
||||
import org.hibernate.service.jdbc.cursor.spi.RefCursorSupport;
|
||||
import org.hibernate.service.spi.InjectService;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public class StandardRefCursorSupport implements RefCursorSupport {
|
||||
private static final Logger log = Logger.getLogger( StandardRefCursorSupport.class );
|
||||
|
||||
private JdbcServices jdbcServices;
|
||||
|
||||
@InjectService
|
||||
@SuppressWarnings("UnusedDeclaration")
|
||||
public void injectJdbcServices(JdbcServices jdbcServices) {
|
||||
this.jdbcServices = jdbcServices;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRefCursorParameter(CallableStatement statement, int position) {
|
||||
if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) {
|
||||
try {
|
||||
statement.registerOutParameter( position, refCursorTypeCode() );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering REF_CURSOR parameter [" + position + "]" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
jdbcServices.getDialect().registerResultSetOutParameter( statement, position );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error asking dialect to register ref cursor parameter [" + position + "]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerRefCursorParameter(CallableStatement statement, String name) {
|
||||
if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) {
|
||||
try {
|
||||
statement.registerOutParameter( name, refCursorTypeCode() );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error registering REF_CURSOR parameter [" + name + "]" );
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
jdbcServices.getDialect().registerResultSetOutParameter( statement, name );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert( e, "Error asking dialect to register ref cursor parameter [" + name + "]" );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet getResultSet(CallableStatement statement, int position) {
|
||||
if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) {
|
||||
try {
|
||||
return (ResultSet) getResultSetByPositionMethod().invoke( statement, position, ResultSet.class );
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
if ( e.getTargetException() instanceof SQLException ) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert(
|
||||
(SQLException) e.getTargetException(),
|
||||
"Error extracting REF_CURSOR parameter [" + position + "]"
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + position + "]", e.getTargetException() );
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + position + "]", e );
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return jdbcServices.getDialect().getResultSet( statement, position );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert(
|
||||
e,
|
||||
"Error asking dialect to extract ResultSet from CallableStatement parameter [" + position + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public ResultSet getResultSet(CallableStatement statement, String name) {
|
||||
if ( jdbcServices.getExtractedMetaDataSupport().supportsRefCursors() ) {
|
||||
try {
|
||||
return (ResultSet) getResultSetByNameMethod().invoke( statement, name, ResultSet.class );
|
||||
}
|
||||
catch (InvocationTargetException e) {
|
||||
if ( e.getTargetException() instanceof SQLException ) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert(
|
||||
(SQLException) e.getTargetException(),
|
||||
"Error extracting REF_CURSOR parameter [" + name + "]"
|
||||
);
|
||||
}
|
||||
else {
|
||||
throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + name + "]", e.getTargetException() );
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unexpected error extracting REF_CURSOR parameter [" + name + "]", e );
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
return jdbcServices.getDialect().getResultSet( statement, name );
|
||||
}
|
||||
catch (SQLException e) {
|
||||
throw jdbcServices.getSqlExceptionHelper().convert(
|
||||
e,
|
||||
"Error asking dialect to extract ResultSet from CallableStatement parameter [" + name + "]"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
public static boolean supportsRefCursors(DatabaseMetaData meta) {
|
||||
// Standard JDBC REF_CURSOR support was not added until Java 8, so we need to use reflection to attempt to
|
||||
// access these fields/methods...
|
||||
try {
|
||||
return ( (Boolean) meta.getClass().getMethod( "supportsRefCursors" ).invoke( null ) ).booleanValue();
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
log.trace( "JDBC DatabaseMetaData class does not define supportsRefCursors method..." );
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.debug( "Unexpected error trying to gauge level of JDBC REF_CURSOR support : " + e.getMessage() );
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
private static Integer refCursorTypeCode;
|
||||
|
||||
@SuppressWarnings("UnnecessaryUnboxing")
|
||||
private int refCursorTypeCode() {
|
||||
if ( refCursorTypeCode == null ) {
|
||||
try {
|
||||
refCursorTypeCode = (Integer) Types.class.getField( "REF_CURSOR" ).get( null );
|
||||
}
|
||||
catch (NoSuchFieldException e) {
|
||||
throw new HibernateException( "java.sql.Types class does not define REF_CURSOR field..." );
|
||||
}
|
||||
catch (IllegalAccessException e) {
|
||||
throw new HibernateException( "Unexpected error trying to determine REF_CURSOR field value : " + e.getMessage() );
|
||||
}
|
||||
}
|
||||
return refCursorTypeCode.intValue();
|
||||
}
|
||||
|
||||
|
||||
private static Method getResultSetByPositionMethod;
|
||||
|
||||
private Method getResultSetByPositionMethod() {
|
||||
if ( getResultSetByPositionMethod == null ) {
|
||||
try {
|
||||
getResultSetByPositionMethod = CallableStatement.class.getMethod( "getObject", int.class, Class.class );
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new HibernateException( "CallableStatement class does not define getObject(int,Class) method" );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unexpected error trying to access CallableStatement#getObject(int,Class)" );
|
||||
}
|
||||
}
|
||||
return getResultSetByPositionMethod;
|
||||
}
|
||||
|
||||
|
||||
private static Method getResultSetByNameMethod;
|
||||
|
||||
private Method getResultSetByNameMethod() {
|
||||
if ( getResultSetByNameMethod == null ) {
|
||||
try {
|
||||
getResultSetByNameMethod = CallableStatement.class.getMethod( "getObject", String.class, Class.class );
|
||||
}
|
||||
catch (NoSuchMethodException e) {
|
||||
throw new HibernateException( "CallableStatement class does not define getObject(String,Class) method" );
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new HibernateException( "Unexpected error trying to access CallableStatement#getObject(String,Class)" );
|
||||
}
|
||||
}
|
||||
return getResultSetByNameMethod;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,73 @@
|
|||
/*
|
||||
* Hibernate, Relational Persistence for Idiomatic Java
|
||||
*
|
||||
* Copyright (c) 2012, Red Hat Inc. or third-party contributors as
|
||||
* indicated by the @author tags or express copyright attribution
|
||||
* statements applied by the authors. All third-party contributions are
|
||||
* distributed under license by Red Hat Inc.
|
||||
*
|
||||
* This copyrighted material is made available to anyone wishing to use, modify,
|
||||
* copy, or redistribute it subject to the terms and conditions of the GNU
|
||||
* Lesser General Public License, as published by the Free Software Foundation.
|
||||
*
|
||||
* 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 GNU Lesser General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with this distribution; if not, write to:
|
||||
* Free Software Foundation, Inc.
|
||||
* 51 Franklin Street, Fifth Floor
|
||||
* Boston, MA 02110-1301 USA
|
||||
*/
|
||||
package org.hibernate.service.jdbc.cursor.spi;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.ResultSet;
|
||||
|
||||
import org.hibernate.service.Service;
|
||||
|
||||
/**
|
||||
* @author Steve Ebersole
|
||||
*/
|
||||
public interface RefCursorSupport extends Service {
|
||||
/**
|
||||
* Register a parameter capable of returning a {@link java.sql.ResultSet} *by position*.
|
||||
*
|
||||
* @param statement The callable statement.
|
||||
* @param position The bind position at which to register the output param.
|
||||
*/
|
||||
public void registerRefCursorParameter(CallableStatement statement, int position);
|
||||
|
||||
/**
|
||||
* Register a parameter capable of returning a {@link java.sql.ResultSet} *by name*.
|
||||
*
|
||||
* @param statement The callable statement.
|
||||
* @param name The parameter name (for drivers which support named parameters).
|
||||
*/
|
||||
public void registerRefCursorParameter(CallableStatement statement, String name);
|
||||
|
||||
/**
|
||||
* Given a callable statement previously processed by {@link #registerRefCursorParameter(java.sql.CallableStatement, int)},
|
||||
* extract the {@link java.sql.ResultSet}.
|
||||
*
|
||||
*
|
||||
* @param statement The callable statement.
|
||||
* @param position The bind position at which to register the output param.
|
||||
*
|
||||
* @return The extracted result set.
|
||||
*/
|
||||
public ResultSet getResultSet(CallableStatement statement, int position);
|
||||
|
||||
/**
|
||||
* Given a callable statement previously processed by {@link #registerRefCursorParameter(java.sql.CallableStatement, String)},
|
||||
* extract the {@link java.sql.ResultSet}.
|
||||
*
|
||||
* @param statement The callable statement.
|
||||
* @param name The parameter name (for drivers which support named parameters).
|
||||
*
|
||||
* @return The extracted result set.
|
||||
*/
|
||||
public ResultSet getResultSet(CallableStatement statement, String name);
|
||||
}
|
|
@ -413,6 +413,33 @@ public abstract class AbstractStandardBasicType<T>
|
|||
}
|
||||
};
|
||||
|
||||
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract( statement, startIndex, options );
|
||||
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract(
|
||||
statement,
|
||||
startIndex,
|
||||
options
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public T extract(CallableStatement statement, String[] paramNames, final SessionImplementor session) throws SQLException {
|
||||
// todo : have SessionImplementor extend WrapperOptions
|
||||
final WrapperOptions options = new WrapperOptions() {
|
||||
public boolean useStreamForLobBinding() {
|
||||
return Environment.useStreamsForBinary();
|
||||
}
|
||||
|
||||
public LobCreator getLobCreator() {
|
||||
return Hibernate.getLobCreator( session );
|
||||
}
|
||||
|
||||
public SqlTypeDescriptor remapSqlTypeDescriptor(SqlTypeDescriptor sqlTypeDescriptor) {
|
||||
final SqlTypeDescriptor remapped = sqlTypeDescriptor.canBeRemapped()
|
||||
? session.getFactory().getDialect().remapSqlTypeDescriptor( sqlTypeDescriptor )
|
||||
: sqlTypeDescriptor;
|
||||
return remapped == null ? sqlTypeDescriptor : remapped;
|
||||
}
|
||||
};
|
||||
|
||||
return remapSqlTypeDescriptor( options ).getExtractor( javaTypeDescriptor ).extract( statement, paramNames, options );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -772,4 +772,34 @@ public class ComponentType extends AbstractType implements CompositeType, Proced
|
|||
|
||||
return resolve( values, session, null );
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object extract(CallableStatement statement, String[] paramNames, SessionImplementor session) throws SQLException {
|
||||
// for this form to work all sub-property spans must be one (1)...
|
||||
|
||||
Object[] values = new Object[propertySpan];
|
||||
|
||||
int indx = 0;
|
||||
boolean notNull = false;
|
||||
for ( String paramName : paramNames ) {
|
||||
// we know this cast is safe from canDoExtraction
|
||||
final ProcedureParameterExtractionAware propertyType = (ProcedureParameterExtractionAware) propertyTypes[indx];
|
||||
final Object value = propertyType.extract( statement, new String[] { paramName }, session );
|
||||
if ( value == null ) {
|
||||
if ( isKey ) {
|
||||
return null; //different nullability rules for pk/fk
|
||||
}
|
||||
}
|
||||
else {
|
||||
notNull = true;
|
||||
}
|
||||
values[indx] = value;
|
||||
}
|
||||
|
||||
if ( ! notNull ) {
|
||||
values = null;
|
||||
}
|
||||
|
||||
return resolve( values, session, null );
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,6 +90,11 @@ public class PostgresUUIDType extends AbstractSingleColumnStandardBasicType<UUID
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getObject( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getObject( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -55,4 +55,18 @@ public interface ProcedureParameterExtractionAware<T> extends Type {
|
|||
* @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction}
|
||||
*/
|
||||
public T extract(CallableStatement statement, int startIndex, SessionImplementor session) throws SQLException;
|
||||
|
||||
/**
|
||||
* Perform the extraction
|
||||
*
|
||||
* @param statement The CallableStatement from which to extract the parameter value(s).
|
||||
* @param paramNames The parameter names.
|
||||
* @param session The originating session
|
||||
*
|
||||
* @return The extracted value.
|
||||
*
|
||||
* @throws SQLException Indicates an issue calling into the CallableStatement
|
||||
* @throws IllegalStateException Thrown if this method is called on instances that return {@code false} for {@link #canDoExtraction}
|
||||
*/
|
||||
public T extract(CallableStatement statement, String[] paramNames, SessionImplementor session) throws SQLException;
|
||||
}
|
||||
|
|
|
@ -47,4 +47,6 @@ public interface ValueExtractor<X> {
|
|||
public X extract(ResultSet rs, String name, WrapperOptions options) throws SQLException;
|
||||
|
||||
public X extract(CallableStatement rs, int index, WrapperOptions options) throws SQLException;
|
||||
|
||||
public X extract(CallableStatement statement, String[] paramNames, WrapperOptions options) throws SQLException;
|
||||
}
|
||||
|
|
|
@ -120,4 +120,39 @@ public abstract class BasicExtractor<J> implements ValueExtractor<J> {
|
|||
* @throws SQLException Indicates a problem accessing the parameter value
|
||||
*/
|
||||
protected abstract J doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException;
|
||||
|
||||
@Override
|
||||
public J extract(CallableStatement statement, String[] paramNames, WrapperOptions options) throws SQLException {
|
||||
if ( paramNames.length > 1 ) {
|
||||
throw new IllegalArgumentException( "Basic value extraction cannot handle multiple output parameters" );
|
||||
}
|
||||
final String paramName = paramNames[0];
|
||||
final J value = doExtract( statement, paramName, options );
|
||||
if ( value == null || statement.wasNull() ) {
|
||||
LOG.tracev( "Found [null] as procedure output parameter [{0}]", paramName );
|
||||
return null;
|
||||
}
|
||||
else {
|
||||
if ( LOG.isTraceEnabled() ) {
|
||||
LOG.tracev( "Found [{0}] as procedure output parameter [{1}]", getJavaDescriptor().extractLoggableRepresentation( value ), paramName );
|
||||
}
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform the extraction.
|
||||
* <p/>
|
||||
* Called from {@link #extract}. Null checking of the value (as well as consulting {@link ResultSet#wasNull}) is
|
||||
* done there.
|
||||
*
|
||||
* @param statement The callable statement containing the output parameter
|
||||
* @param name The output parameter name
|
||||
* @param options The binding options
|
||||
*
|
||||
* @return The extracted value.
|
||||
*
|
||||
* @throws SQLException Indicates a problem accessing the parameter value
|
||||
*/
|
||||
protected abstract J doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException;
|
||||
}
|
||||
|
|
|
@ -78,6 +78,11 @@ public class BigIntTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getLong( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getLong( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -80,6 +80,11 @@ public class BitTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBoolean( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBoolean( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -68,6 +68,11 @@ public abstract class BlobTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBlob( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBlob( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -75,6 +75,11 @@ public class BooleanTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBoolean( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBoolean( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,11 @@ public abstract class ClobTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getClob( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getClob( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -79,6 +79,11 @@ public class DateTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getDate( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getDate( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,11 @@ public class DecimalTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBigDecimal( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBigDecimal( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,11 @@ public class DoubleTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getDouble( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getDouble( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,11 @@ public class IntegerTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getInt( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getInt( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,11 @@ public abstract class NClobTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getNClob( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getNClob( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -78,6 +78,11 @@ public class NVarcharTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getNString( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getNString( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,11 @@ public class RealTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getFloat( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getFloat( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,11 @@ public class SmallIntTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getShort( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getShort( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -142,10 +142,14 @@ public class SqlTypeDescriptorRegistry {
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Object doExtract(CallableStatement statement, int index, WrapperOptions options)
|
||||
throws SQLException {
|
||||
protected Object doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return statement.getObject( index );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return statement.getObject( name );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,11 @@ public class TimeTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getTime( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getTime( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -79,6 +79,11 @@ public class TimestampTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getTimestamp( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getTimestamp( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
|
@ -81,6 +81,11 @@ public class TinyIntTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getByte( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getByte( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -75,6 +75,11 @@ public class VarbinaryTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBytes( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getBytes( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,6 +78,11 @@ public class VarcharTypeDescriptor implements SqlTypeDescriptor {
|
|||
protected X doExtract(CallableStatement statement, int index, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getString( index ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
return javaTypeDescriptor.wrap( statement.getString( name ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
|
@ -106,6 +106,16 @@ public class BasicTestingJdbcServiceImpl implements JdbcServices {
|
|||
}
|
||||
|
||||
private static class MetaDataSupportImpl implements ExtractedDatabaseMetaData {
|
||||
@Override
|
||||
public boolean supportsRefCursors() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsNamedParameters() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean supportsScrollableResults() {
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -84,6 +84,15 @@ public class StoredPrefixedStringType
|
|||
}
|
||||
return javaTypeDescriptor.wrap( stringValue.substring( PREFIX.length() ), options );
|
||||
}
|
||||
|
||||
@Override
|
||||
protected X doExtract(CallableStatement statement, String name, WrapperOptions options) throws SQLException {
|
||||
String stringValue = statement.getString( name );
|
||||
if ( ! stringValue.startsWith( PREFIX ) ) {
|
||||
throw new AssertionFailure( "Value read from procedure output param does not have prefix." );
|
||||
}
|
||||
return javaTypeDescriptor.wrap( stringValue.substring( PREFIX.length() ), options );
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue