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);
}
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();
}
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();
}
Aggregations