Implementing ProcedureParamBindings

This commit is contained in:
Andrea Boriero 2021-09-27 08:08:32 +02:00 committed by Christian Beikov
parent d4007c5071
commit 6931635c4f
4 changed files with 105 additions and 97 deletions

View File

@ -31,48 +31,47 @@ public class PostgresCallableStatementSupport implements CallableStatementSuppor
ParameterMetadataImplementor parameterMetadata, ParameterMetadataImplementor parameterMetadata,
ProcedureParamBindings paramBindings, ProcedureParamBindings paramBindings,
SharedSessionContractImplementor session) { SharedSessionContractImplementor session) {
throw new NotYetImplementedFor6Exception( getClass() );
// // if there are any parameters, see if the first is REF_CURSOR // if there are any parameters, see if the first is REF_CURSOR
// final boolean firstParamIsRefCursor = ! parameterRegistrations.isEmpty() final boolean firstParamIsRefCursor = parameterMetadata.getParameterCount() != 0
// && parameterRegistrations.get( 0 ).getMode() == ParameterMode.REF_CURSOR; && paramBindings..getMode() == ParameterMode.REF_CURSOR;
//
// if ( firstParamIsRefCursor ) { if ( firstParamIsRefCursor ) {
// // validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional) // validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional)
// if ( parameterStrategy == ParameterStrategy.NAMED ) { if ( parameterStrategy == ParameterStrategy.NAMED ) {
// throw new HibernateException( "Cannot mix named parameters and REF_CURSOR parameter on PostgreSQL" ); throw new HibernateException( "Cannot mix named parameters and REF_CURSOR parameter on PostgreSQL" );
// } }
// } }
//
// final StringBuilder buffer; final StringBuilder buffer;
// if ( firstParamIsRefCursor ) { if ( firstParamIsRefCursor ) {
// buffer = new StringBuilder().append( "{? = call " ); buffer = new StringBuilder().append( "{? = call " );
// } }
// else { else {
// buffer = new StringBuilder().append( "{call " ); buffer = new StringBuilder().append( "{call " );
// } }
//
// buffer.append( procedureName ).append( "(" ); buffer.append( procedureName ).append( "(" );
//
// String sep = ""; String sep = "";
//
// // skip the first registration if it was a REF_CURSOR // skip the first registration if it was a REF_CURSOR
// final int startIndex = firstParamIsRefCursor ? 1 : 0; final int startIndex = firstParamIsRefCursor ? 1 : 0;
// for ( int i = startIndex; i < parameterRegistrations.size(); i++ ) { for ( int i = startIndex; i < parameterRegistrations.size(); i++ ) {
// final ParameterRegistrationImplementor parameter = parameterRegistrations.get( i ); final ParameterRegistrationImplementor parameter = parameterRegistrations.get( i );
//
// // any additional REF_CURSOR parameter registrations are an error // any additional REF_CURSOR parameter registrations are an error
// if ( parameter.getMode() == ParameterMode.REF_CURSOR ) { if ( parameter.getMode() == ParameterMode.REF_CURSOR ) {
// throw new HibernateException( "PostgreSQL supports only one REF_CURSOR parameter, but multiple were registered" ); throw new HibernateException( "PostgreSQL supports only one REF_CURSOR parameter, but multiple were registered" );
// } }
//
// for ( int ignored : parameter.getSqlTypes() ) { for ( int ignored : parameter.getSqlTypes() ) {
// buffer.append( sep ).append( "?" ); buffer.append( sep ).append( "?" );
// sep = ","; sep = ",";
// } }
// } }
//
// return buffer.append( ")}" ).toString(); return buffer.append( ")}" ).toString();
} }
@Override @Override

View File

@ -6,6 +6,8 @@
*/ */
package org.hibernate.procedure.internal; package org.hibernate.procedure.internal;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Calendar; import java.util.Calendar;
@ -14,6 +16,7 @@ import java.util.Date;
import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream; import java.util.stream.Stream;
import jakarta.persistence.FlushModeType; import jakarta.persistence.FlushModeType;
import jakarta.persistence.LockModeType; import jakarta.persistence.LockModeType;
@ -27,7 +30,6 @@ import jakarta.persistence.TransactionRequiredException;
import org.hibernate.HibernateException; import org.hibernate.HibernateException;
import org.hibernate.LockMode; import org.hibernate.LockMode;
import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.ScrollMode; import org.hibernate.ScrollMode;
import org.hibernate.engine.spi.SessionFactoryImplementor; import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.engine.spi.SharedSessionContractImplementor;
@ -62,8 +64,11 @@ import org.hibernate.result.Output;
import org.hibernate.result.ResultSetOutput; import org.hibernate.result.ResultSetOutput;
import org.hibernate.result.UpdateCountOutput; import org.hibernate.result.UpdateCountOutput;
import org.hibernate.result.spi.ResultContext; import org.hibernate.result.spi.ResultContext;
import org.hibernate.sql.exec.spi.JdbcCall;
import org.hibernate.sql.results.NoMoreOutputsException; import org.hibernate.sql.results.NoMoreOutputsException;
import org.jboss.logging.Logger;
/** /**
* Standard implementation of {@link ProcedureCall} * Standard implementation of {@link ProcedureCall}
* *
@ -72,6 +77,7 @@ import org.hibernate.sql.results.NoMoreOutputsException;
public class ProcedureCallImpl<R> public class ProcedureCallImpl<R>
extends AbstractQuery<R> extends AbstractQuery<R>
implements ProcedureCallImplementor<R>, ResultContext { implements ProcedureCallImplementor<R>, ResultContext {
private static final Logger LOG = Logger.getLogger( ProcedureCallImpl.class );
private final String procedureName; private final String procedureName;
@ -432,51 +438,51 @@ public class ProcedureCallImpl<R>
// both: (1) add the `? = ` part and also (2) register a REFCURSOR parameter for DBs (Oracle, PGSQL) that // both: (1) add the `? = ` part and also (2) register a REFCURSOR parameter for DBs (Oracle, PGSQL) that
// need it. // need it.
// final String call = getSession().getJdbcServices().getJdbcEnvironment().getDialect().getCallableStatementSupport().renderCallableStatement( final JdbcCall call = getSession().getJdbcServices().getJdbcEnvironment().getDialect().getCallableStatementSupport().interpretCall(
// procedureName, procedureName,
// getParameterMetadata(), functionReturn,
// paramBindings, getParameterMetadata(),
// getSession() paramBindings,
// ); getSession()
// );
// LOG.debugf( "Preparing procedure call : %s", call );
// final CallableStatement statement = (CallableStatement) getSession() LOG.debugf( "Preparing procedure call : %s", call );
// .getJdbcCoordinator() final CallableStatement statement = (CallableStatement) getSession()
// .getStatementPreparer() .getJdbcCoordinator()
// .prepareStatement( call, true ); .getStatementPreparer()
// .prepareStatement( call.getSql(), true );
//
// // prepare parameters
// // prepare parameters
// getParameterMetadata().visitRegistrations(
// new Consumer<QueryParameter<?>>() { getParameterMetadata().visitRegistrations(
// int i = 1; new Consumer<QueryParameter<?>>() {
// int i = 1;
// @Override
// public void accept(QueryParameter queryParameter) { @Override
// try { public void accept(QueryParameter queryParameter) {
// final ProcedureParameterImplementor registration = (ProcedureParameterImplementor) queryParameter; try {
// registration.prepare( statement, i, ProcedureCallImpl.this ); final ProcedureParameterImplementor registration = (ProcedureParameterImplementor) queryParameter;
registration.prepare( statement, i, ProcedureCallImpl.this );
// if ( registration.getMode() == ParameterMode.REF_CURSOR ) { // if ( registration.getMode() == ParameterMode.REF_CURSOR ) {
// i++; i++;
// } // }
// else { // else {
// i += registration.getSqlTypes().length; // i += registration.getSqlTypes().length;
// } // }
// } }
// catch (SQLException e) { catch (SQLException e) {
// throw getSession().getJdbcServices().getSqlExceptionHelper().convert( throw getSession().getJdbcServices().getSqlExceptionHelper().convert(
// e, e,
// "Error preparing registered callable parameter", "Error preparing registered callable parameter",
// getProcedureName() getProcedureName()
// ); );
// } }
// } }
// } }
// ); );
//
// return new ProcedureOutputsImpl( this, statement ); return new ProcedureOutputsImpl( this, statement );
throw new NotYetImplementedFor6Exception( getClass() );
} }
@Override @Override

View File

@ -13,7 +13,6 @@ import org.hibernate.NotYetImplementedFor6Exception;
import org.hibernate.procedure.spi.ProcedureParameterBindingImplementor; import org.hibernate.procedure.spi.ProcedureParameterBindingImplementor;
import org.hibernate.procedure.spi.ProcedureParameterImplementor; import org.hibernate.procedure.spi.ProcedureParameterImplementor;
import org.hibernate.query.procedure.ProcedureParameterBinding; import org.hibernate.query.procedure.ProcedureParameterBinding;
import org.hibernate.query.spi.QueryParameterBinding;
import org.hibernate.query.spi.QueryParameterBindingTypeResolver; import org.hibernate.query.spi.QueryParameterBindingTypeResolver;
import org.hibernate.query.spi.QueryParameterBindings; import org.hibernate.query.spi.QueryParameterBindings;
import org.hibernate.query.spi.QueryParameterImplementor; import org.hibernate.query.spi.QueryParameterImplementor;
@ -45,17 +44,16 @@ public class ProcedureParamBindings implements QueryParameterBindings {
} }
@Override @Override
public <P> QueryParameterBinding<P> getBinding(QueryParameterImplementor<P> parameter) { public <P> ProcedureParameterBinding<P> getBinding(QueryParameterImplementor<P> parameter) {
// return getBinding( parameterMetadata.resolve( parameter ) ); return getQueryParamerBinding( (ProcedureParameterImplementor) parameter );
throw new NotYetImplementedFor6Exception( getClass() );
} }
public ProcedureParameterBindingImplementor<?> getBinding(ProcedureParameterImplementor<?> parameter) { public <P> ProcedureParameterBinding<P> getQueryParamerBinding(ProcedureParameterImplementor<P> parameter) {
final ProcedureParameterImplementor procParam = parameterMetadata.resolve( parameter ); final ProcedureParameterImplementor procParam = parameterMetadata.resolve( parameter );
ProcedureParameterBindingImplementor binding = bindingMap.get( procParam ); ProcedureParameterBindingImplementor binding = bindingMap.get( procParam );
if ( binding == null ) { if ( binding == null ) {
if ( ! parameterMetadata.containsReference( parameter ) ) { if ( !parameterMetadata.containsReference( parameter ) ) {
throw new IllegalArgumentException( "Passed parameter is not registered with this query" ); throw new IllegalArgumentException( "Passed parameter is not registered with this query" );
} }
@ -68,15 +66,23 @@ public class ProcedureParamBindings implements QueryParameterBindings {
} }
@Override @Override
public ProcedureParameterBinding<?> getBinding(String name) { public <P> ProcedureParameterBinding<P> getBinding(String name) {
// return (ProcedureParameterBinding<?>) getBinding( parameterMetadata.getQueryParameter( name ) ); final ProcedureParameterImplementor<P> parameter = (ProcedureParameterImplementor<P>) parameterMetadata
throw new NotYetImplementedFor6Exception( getClass() ); .getQueryParameter( name );
if ( parameter == null ) {
throw new IllegalArgumentException( "Parameter does not exist: " + name );
}
return getQueryParamerBinding( parameter );
} }
@Override @Override
public ProcedureParameterBinding getBinding(int position) { public <P> ProcedureParameterBinding<P> getBinding(int position) {
// return getBinding( parameterMetadata.getQueryParameter( position ) ); final ProcedureParameterImplementor<P> parameter = (ProcedureParameterImplementor<P>) parameterMetadata
throw new NotYetImplementedFor6Exception( getClass() ); .getQueryParameter( position );
if ( parameter == null ) {
throw new IllegalArgumentException( "Parameter at position " + position + "does not exist" );
}
return getQueryParamerBinding( parameter );
} }
@Override @Override
@ -101,5 +107,4 @@ public class ProcedureParamBindings implements QueryParameterBindings {
return false; return false;
} }
} }

View File

@ -63,7 +63,6 @@ import org.hibernate.type.YesNoType;
import org.hibernate.testing.TestForIssue; import org.hibernate.testing.TestForIssue;
import org.hibernate.testing.orm.junit.DomainModel; import org.hibernate.testing.orm.junit.DomainModel;
import org.hibernate.testing.orm.junit.NotImplementedYet;
import org.hibernate.testing.orm.junit.SessionFactory; import org.hibernate.testing.orm.junit.SessionFactory;
import org.hibernate.testing.orm.junit.SessionFactoryScope; import org.hibernate.testing.orm.junit.SessionFactoryScope;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -74,7 +73,6 @@ import static org.junit.jupiter.api.Assertions.fail;
/** /**
* @author Vlad Mihalcea * @author Vlad Mihalcea
*/ */
@NotImplementedYet
@DomainModel @DomainModel
@SessionFactory @SessionFactory
public class StoredProcedureParameterTypeTest { public class StoredProcedureParameterTypeTest {