Search in sources :

Example 1 with JdbcCallParameterRegistration

use of org.hibernate.sql.exec.spi.JdbcCallParameterRegistration in project hibernate-orm by hibernate.

the class ProcedureCallImpl method buildOutputs.

private ProcedureOutputsImpl buildOutputs() {
    // todo : going to need a very specialized Loader for this.
    // or, might be a good time to look at splitting Loader up into:
    // 1) building statement objects
    // 2) executing statement objects
    // 3) processing result sets
    // for now assume there are no resultClasses nor mappings defined..
    // TOTAL PROOF-OF-CONCEPT!!!!!!
    // todo : how to identify calls which should be in the form `{? = call procName...}` ??? (note leading param marker)
    // more than likely this will need to be a method on the native API.  I can see this as a trigger to
    // both: (1) add the `? = ` part and also (2) register a REFCURSOR parameter for DBs (Oracle, PGSQL) that
    // need it.
    final CallableStatementSupport callableStatementSupport = getSession().getJdbcServices().getJdbcEnvironment().getDialect().getCallableStatementSupport();
    this.call = callableStatementSupport.interpretCall(this);
    final Map<ProcedureParameter<?>, JdbcCallParameterRegistration> parameterRegistrations = new IdentityHashMap<>();
    final List<JdbcCallRefCursorExtractor> refCursorExtractors = new ArrayList<>();
    if (call.getFunctionReturn() != null) {
        parameterRegistrations.put(functionReturn, call.getFunctionReturn());
        final JdbcCallRefCursorExtractorImpl refCursorExtractor = call.getFunctionReturn().getRefCursorExtractor();
        if (refCursorExtractor != null) {
            refCursorExtractors.add(refCursorExtractor);
        }
    }
    final List<? extends ProcedureParameterImplementor<?>> registrations = getParameterMetadata().getRegistrationsAsList();
    final List<JdbcCallParameterRegistration> jdbcParameters = call.getParameterRegistrations();
    for (int i = 0; i < registrations.size(); i++) {
        final JdbcCallParameterRegistration jdbcCallParameterRegistration = jdbcParameters.get(i);
        parameterRegistrations.put(registrations.get(i), jdbcCallParameterRegistration);
        final JdbcCallRefCursorExtractorImpl refCursorExtractor = jdbcCallParameterRegistration.getRefCursorExtractor();
        if (refCursorExtractor != null) {
            refCursorExtractors.add(refCursorExtractor);
        }
    }
    LOG.debugf("Preparing procedure call : %s", call);
    final CallableStatement statement = (CallableStatement) getSession().getJdbcCoordinator().getStatementPreparer().prepareStatement(call.getSql(), true);
    // Register the parameter mode and type
    callableStatementSupport.registerParameters(procedureName, call, statement, parameterMetadata, getSession());
    // Apply the parameter bindings
    final JdbcParameterBindings jdbcParameterBindings = new JdbcParameterBindingsImpl(parameterRegistrations.size());
    for (Map.Entry<ProcedureParameter<?>, JdbcCallParameterRegistration> entry : parameterRegistrations.entrySet()) {
        final JdbcCallParameterRegistration registration = entry.getValue();
        if (registration.getParameterBinder() != null) {
            final ProcedureParameter<?> parameter = entry.getKey();
            final QueryParameterBinding<?> binding = getParameterBindings().getBinding(parameter);
            if (!binding.isBound()) {
                if (parameter.getPosition() == null) {
                    throw new IllegalArgumentException("The parameter named [" + parameter + "] was not set! You need to call the setParameter method.");
                } else {
                    throw new IllegalArgumentException("The parameter at position [" + parameter + "] was not set! You need to call the setParameter method.");
                }
            }
            jdbcParameterBindings.addBinding((JdbcParameter) registration.getParameterBinder(), new JdbcParameterBindingImpl((JdbcMapping) registration.getParameterType(), binding.getBindValue()));
        }
    }
    final JdbcCallRefCursorExtractor[] extractors = refCursorExtractors.toArray(new JdbcCallRefCursorExtractor[0]);
    final ExecutionContext executionContext = new ExecutionContext() {

        private final Callback callback = new CallbackImpl();

        @Override
        public SharedSessionContractImplementor getSession() {
            return ProcedureCallImpl.this.getSession();
        }

        @Override
        public QueryOptions getQueryOptions() {
            return new QueryOptionsAdapter() {

                @Override
                public Boolean isReadOnly() {
                    return false;
                }
            };
        }

        @Override
        public String getQueryIdentifier(String sql) {
            return sql;
        }

        @Override
        public QueryParameterBindings getQueryParameterBindings() {
            return QueryParameterBindings.NO_PARAM_BINDINGS;
        }

        @Override
        public Callback getCallback() {
            return callback;
        }
    };
    try {
        int paramBindingPosition = call.getFunctionReturn() == null ? 1 : 2;
        for (JdbcParameterBinder parameterBinder : call.getParameterBinders()) {
            parameterBinder.bindParameterValue(statement, paramBindingPosition, jdbcParameterBindings, executionContext);
            paramBindingPosition++;
        }
    } catch (SQLException e) {
        throw getSession().getJdbcServices().getSqlExceptionHelper().convert(e, "Error registering CallableStatement parameters", procedureName);
    }
    return new ProcedureOutputsImpl(this, parameterRegistrations, extractors, statement);
}
Also used : ProcedureParameter(org.hibernate.query.procedure.ProcedureParameter) JdbcCallRefCursorExtractorImpl(org.hibernate.sql.exec.internal.JdbcCallRefCursorExtractorImpl) CallbackImpl(org.hibernate.sql.exec.internal.CallbackImpl) JdbcMapping(org.hibernate.metamodel.mapping.JdbcMapping) SQLException(java.sql.SQLException) IdentityHashMap(java.util.IdentityHashMap) ArrayList(java.util.ArrayList) JdbcCallRefCursorExtractor(org.hibernate.sql.exec.spi.JdbcCallRefCursorExtractor) CallableStatement(java.sql.CallableStatement) JdbcParameterBinder(org.hibernate.sql.exec.spi.JdbcParameterBinder) JdbcParameterBindingsImpl(org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl) JdbcParameterBindingImpl(org.hibernate.sql.exec.internal.JdbcParameterBindingImpl) CallableStatementSupport(org.hibernate.procedure.spi.CallableStatementSupport) ExecutionContext(org.hibernate.sql.exec.spi.ExecutionContext) Callback(org.hibernate.sql.exec.spi.Callback) JdbcCallParameterRegistration(org.hibernate.sql.exec.spi.JdbcCallParameterRegistration) QueryOptionsAdapter(org.hibernate.query.spi.QueryOptionsAdapter) Map(java.util.Map) IdentityHashMap(java.util.IdentityHashMap) JdbcParameterBindings(org.hibernate.sql.exec.spi.JdbcParameterBindings)

Example 2 with JdbcCallParameterRegistration

use of org.hibernate.sql.exec.spi.JdbcCallParameterRegistration in project hibernate-orm by hibernate.

the class StandardCallableStatementSupport method interpretCall.

@Override
public JdbcCall interpretCall(ProcedureCallImplementor<?> procedureCall) {
    final String procedureName = procedureCall.getProcedureName();
    final FunctionReturnImplementor functionReturn = procedureCall.getFunctionReturn();
    final ProcedureParameterMetadataImplementor parameterMetadata = procedureCall.getParameterMetadata();
    final SharedSessionContractImplementor session = procedureCall.getSession();
    final List<? extends ProcedureParameterImplementor<?>> registrations = parameterMetadata.getRegistrationsAsList();
    final ParameterStrategy parameterStrategy = functionReturn == null && parameterMetadata.hasNamedParameters() ? ParameterStrategy.NAMED : ParameterStrategy.POSITIONAL;
    final JdbcCallImpl.Builder builder = new JdbcCallImpl.Builder(parameterStrategy);
    final StringBuilder buffer;
    final int offset;
    if (functionReturn != null && !implicitReturn) {
        offset = 2;
        buffer = new StringBuilder(11 + procedureName.length() + registrations.size() * 2).append("{?=call ");
        builder.setFunctionReturn(functionReturn.toJdbcFunctionReturn(session));
    } else {
        offset = 1;
        buffer = new StringBuilder(9 + procedureName.length() + registrations.size() * 2).append("{call ");
    }
    buffer.append(procedureName).append("(");
    String sep = "";
    for (int i = 0; i < registrations.size(); i++) {
        final ProcedureParameterImplementor<?> parameter = registrations.get(i);
        if (parameter.getMode() == ParameterMode.REF_CURSOR) {
            verifyRefCursorSupport(session.getJdbcServices().getJdbcEnvironment().getDialect());
        }
        buffer.append(sep);
        final JdbcCallParameterRegistration registration = parameter.toJdbcParameterRegistration(i + offset, procedureCall);
        if (registration.getName() != null) {
            buffer.append(':').append(registration.getName());
        } else {
            buffer.append("?");
        }
        sep = ",";
        builder.addParameterRegistration(registration);
    }
    buffer.append(")}");
    builder.setCallableName(buffer.toString());
    return builder.buildJdbcCall();
}
Also used : SharedSessionContractImplementor(org.hibernate.engine.spi.SharedSessionContractImplementor) ParameterStrategy(org.hibernate.procedure.spi.ParameterStrategy) JdbcCallImpl(org.hibernate.sql.exec.internal.JdbcCallImpl) JdbcCallParameterRegistration(org.hibernate.sql.exec.spi.JdbcCallParameterRegistration) ProcedureParameterMetadataImplementor(org.hibernate.query.spi.ProcedureParameterMetadataImplementor) FunctionReturnImplementor(org.hibernate.procedure.spi.FunctionReturnImplementor)

Example 3 with JdbcCallParameterRegistration

use of org.hibernate.sql.exec.spi.JdbcCallParameterRegistration in project hibernate-orm by hibernate.

the class PostgresCallableStatementSupport method interpretCall.

@Override
public JdbcCall interpretCall(ProcedureCallImplementor<?> procedureCall) {
    final String procedureName = procedureCall.getProcedureName();
    final FunctionReturnImplementor functionReturn = procedureCall.getFunctionReturn();
    final ProcedureParameterMetadataImplementor parameterMetadata = procedureCall.getParameterMetadata();
    final SharedSessionContractImplementor session = procedureCall.getSession();
    final boolean firstParamIsRefCursor = parameterMetadata.getParameterCount() != 0 && isFirstParameterModeRefCursor(parameterMetadata);
    if (firstParamIsRefCursor || functionReturn != null) {
        // validate that the parameter strategy is positional (cannot mix, and REF_CURSOR is inherently positional)
        if (parameterMetadata.hasNamedParameters()) {
            throw new HibernateException("Cannot mix named parameters and REF_CURSOR parameter on PostgreSQL");
        }
    }
    final List<? extends ProcedureParameterImplementor<?>> registrations = parameterMetadata.getRegistrationsAsList();
    final ParameterStrategy parameterStrategy = parameterMetadata.hasNamedParameters() ? ParameterStrategy.NAMED : ParameterStrategy.POSITIONAL;
    final JdbcCallImpl.Builder builder = new JdbcCallImpl.Builder(parameterStrategy);
    final StringBuilder buffer;
    final int offset;
    final int startIndex;
    if (functionReturn != null) {
        offset = 2;
        startIndex = 0;
        buffer = new StringBuilder(11 + procedureName.length() + registrations.size() * 2).append("{?=call ");
        builder.setFunctionReturn(functionReturn.toJdbcFunctionReturn(session));
    } else if (firstParamIsRefCursor) {
        offset = 1;
        startIndex = 1;
        buffer = new StringBuilder(11 + procedureName.length() + registrations.size() * 2).append("{?=call ");
        builder.addParameterRegistration(registrations.get(0).toJdbcParameterRegistration(1, procedureCall));
    } else {
        offset = 1;
        startIndex = 0;
        buffer = new StringBuilder(9 + procedureName.length() + registrations.size() * 2).append("{call ");
    }
    buffer.append(procedureName).append("(");
    String sep = "";
    for (int i = startIndex; i < registrations.size(); i++) {
        final ProcedureParameterImplementor<?> parameter = registrations.get(i);
        if (parameter.getMode() == ParameterMode.REF_CURSOR) {
            throw new HibernateException("PostgreSQL supports only one REF_CURSOR parameter, but multiple were registered");
        }
        buffer.append(sep);
        final JdbcCallParameterRegistration registration = parameter.toJdbcParameterRegistration(i + offset, procedureCall);
        if (registration.getName() != null) {
            buffer.append(':').append(registration.getName());
        } else {
            buffer.append("?");
        }
        sep = ",";
        builder.addParameterRegistration(registration);
    }
    buffer.append(")}");
    builder.setCallableName(buffer.toString());
    return builder.buildJdbcCall();
}
Also used : HibernateException(org.hibernate.HibernateException) SharedSessionContractImplementor(org.hibernate.engine.spi.SharedSessionContractImplementor) ParameterStrategy(org.hibernate.procedure.spi.ParameterStrategy) JdbcCallImpl(org.hibernate.sql.exec.internal.JdbcCallImpl) JdbcCallParameterRegistration(org.hibernate.sql.exec.spi.JdbcCallParameterRegistration) ProcedureParameterMetadataImplementor(org.hibernate.query.spi.ProcedureParameterMetadataImplementor) FunctionReturnImplementor(org.hibernate.procedure.spi.FunctionReturnImplementor)

Aggregations

JdbcCallParameterRegistration (org.hibernate.sql.exec.spi.JdbcCallParameterRegistration)3 SharedSessionContractImplementor (org.hibernate.engine.spi.SharedSessionContractImplementor)2 FunctionReturnImplementor (org.hibernate.procedure.spi.FunctionReturnImplementor)2 ParameterStrategy (org.hibernate.procedure.spi.ParameterStrategy)2 ProcedureParameterMetadataImplementor (org.hibernate.query.spi.ProcedureParameterMetadataImplementor)2 JdbcCallImpl (org.hibernate.sql.exec.internal.JdbcCallImpl)2 CallableStatement (java.sql.CallableStatement)1 SQLException (java.sql.SQLException)1 ArrayList (java.util.ArrayList)1 IdentityHashMap (java.util.IdentityHashMap)1 Map (java.util.Map)1 HibernateException (org.hibernate.HibernateException)1 JdbcMapping (org.hibernate.metamodel.mapping.JdbcMapping)1 CallableStatementSupport (org.hibernate.procedure.spi.CallableStatementSupport)1 ProcedureParameter (org.hibernate.query.procedure.ProcedureParameter)1 QueryOptionsAdapter (org.hibernate.query.spi.QueryOptionsAdapter)1 CallbackImpl (org.hibernate.sql.exec.internal.CallbackImpl)1 JdbcCallRefCursorExtractorImpl (org.hibernate.sql.exec.internal.JdbcCallRefCursorExtractorImpl)1 JdbcParameterBindingImpl (org.hibernate.sql.exec.internal.JdbcParameterBindingImpl)1 JdbcParameterBindingsImpl (org.hibernate.sql.exec.internal.JdbcParameterBindingsImpl)1