/* * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.jdbi.v3.core.statement; import java.sql.CallableStatement; import java.sql.PreparedStatement; import java.sql.SQLException; import java.sql.Types; import java.util.ArrayList; import java.util.List; import org.jdbi.v3.core.Handle; import org.jdbi.v3.core.argument.Argument; /** * Used for invoking stored procedures. */ public class Call extends SqlStatement<Call> { private final List<OutParamArgument> params = new ArrayList<>(); public Call(Handle handle, String sql) { super(handle, sql); } /** * Register a positional output parameter * @param position the parameter position (zero-based) * @param sqlType an SQL type constant as defined by {@link java.sql.Types} or by the JDBC vendor. * @return self */ public Call registerOutParameter(int position, int sqlType) { return registerOutParameter(position, sqlType, null); } /** * Register a positional output parameter * @param position the parameter position (zero-based) * @param sqlType an SQL type constant as defined by {@link java.sql.Types} or by the JDBC vendor. * @param mapper a mapper which converts the {@link CallableStatement} to a desired output type. * @return self */ public Call registerOutParameter(int position, int sqlType, CallableStatementMapper mapper) { getBinding().addPositional(position, new OutParamArgument(sqlType, mapper, null)); return this; } /** * Register a named output parameter * @param name the parameter name * @param sqlType an SQL type constant as defined by {@link java.sql.Types} or by the JDBC vendor. * @return self */ public Call registerOutParameter(String name, int sqlType) { return registerOutParameter(name, sqlType, null); } /** * Register a named output parameter * @param name the parameter name * @param sqlType an SQL type constant as defined by {@link java.sql.Types} or by the JDBC vendor. * @param mapper a mapper which converts the {@link CallableStatement} to a desired output type. * @return self */ public Call registerOutParameter(String name, int sqlType, CallableStatementMapper mapper) { getBinding().addNamed(name, new OutParamArgument(sqlType, mapper, name)); return this; } /** * Invoke the callable statement * @return the output parameters resulting from the invocation. */ public OutParameters invoke() { try { final PreparedStatement stmt = this.internalExecute(); OutParameters out = new OutParameters(); for ( OutParamArgument param : params ) { Object obj = param.map((CallableStatement)stmt); // convert from JDBC 1-based position to Jdbi's 0-based int index = param.position - 1; out.getMap().put(index, obj); if ( param.name != null ) { out.getMap().put(param.name, obj); } } return out; } finally { close(); } } private class OutParamArgument implements Argument { private final int sqlType; private final CallableStatementMapper mapper; private final String name; private int position ; OutParamArgument(int sqlType, CallableStatementMapper mapper, String name) { this.sqlType = sqlType; this.mapper = mapper; this.name = name; params.add(this); } @Override public void apply(int position, PreparedStatement statement, StatementContext ctx) throws SQLException { ((CallableStatement)statement).registerOutParameter(position, sqlType); this.position = position; } public Object map(CallableStatement stmt) { try { if ( mapper != null ) { return mapper.map(position, stmt); } switch ( sqlType ) { case Types.CLOB : case Types.VARCHAR : case Types.LONGNVARCHAR : case Types.LONGVARCHAR : case Types.NCLOB : case Types.NVARCHAR : return stmt.getString(position) ; case Types.BLOB : case Types.VARBINARY : return stmt.getBytes(position) ; case Types.SMALLINT : return stmt.getShort(position); case Types.INTEGER : return stmt.getInt(position); case Types.BIGINT : return stmt.getLong(position); case Types.TIMESTAMP : case Types.TIME : return stmt.getTimestamp(position) ; case Types.DATE : return stmt.getDate(position) ; case Types.FLOAT : return stmt.getFloat(position); case Types.DECIMAL : case Types.DOUBLE : return stmt.getDouble(position); default : return stmt.getObject(position); } } catch (SQLException e) { throw new UnableToExecuteStatementException("Could not get OUT parameter from statement", e, getContext()); } } } }