Skip to content

Commit

Permalink
Bug 558283: Missing parameter markers from DB2 Stored Procedures
Browse files Browse the repository at this point in the history
Signed-off-by: Will Dazey <[email protected]>
  • Loading branch information
dazey3 committed Jan 7, 2020
1 parent bb27b2e commit 09e8c4c
Show file tree
Hide file tree
Showing 11 changed files with 230 additions and 137 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,7 @@ public AbstractRecord buildOutputRow(CallableStatement statement, DatabaseAccess
if (parameter instanceof OutputParameterForCallableStatement) {
OutputParameterForCallableStatement outParameter = (OutputParameterForCallableStatement)parameter;
if (!outParameter.isCursor() || !isCursorOutputProcedure()) {
Object value = getObject(statement, index);
Object value = getOutputParameterValue(statement, index, session);
DatabaseField field = outParameter.getOutputField();
if (value instanceof Struct){
ClassDescriptor descriptor = session.getDescriptor(field.getType());
Expand Down Expand Up @@ -1387,11 +1387,26 @@ public void setHasAllocatedConnection(boolean hasAllocatedConnection) {
}

/**
* Get the return object from the statement. Use the index to determine what return object to get.
*
* INTERNAL:
*
* Get the return object from the statement. Use the parameter index to determine what return object to get.
* @param index - 0-based index in the argument list
* @return
*/
public Object getOutputParameterValue(CallableStatement statement, int index, AbstractSession session) throws SQLException {
return session.getPlatform().getParameterValueFromDatabaseCall(statement, index + 1, session);
}

/**
*
* INTERNAL:
*
* Get the return object from the statement. Use the parameter name to determine what return object to get.
* @param index - 0-based index in the argument list
* @return
*/
protected Object getObject(CallableStatement statement, int index) throws SQLException {
return statement.getObject(index + 1);
public Object getOutputParameterValue(CallableStatement statement, String name, AbstractSession session) throws SQLException {
return session.getPlatform().getParameterValueFromDatabaseCall(statement, name, session);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2487,7 +2487,7 @@ public Object executeStoredProcedure(DatabaseCall dbCall, PreparedStatement stat
if (dbCall.isCursorOutputProcedure()) {
result = accessor.executeNoSelect(dbCall, statement, session);
int index = dbCall.getCursorOutIndex();
resultSet = (ResultSet)dbCall.getObject((CallableStatement)statement, index - 1);
resultSet = (ResultSet)dbCall.getOutputParameterValue((CallableStatement)statement, index - 1, session);
} else {
accessor.executeDirectNoSelect(statement, dbCall, session);

Expand Down Expand Up @@ -2782,6 +2782,23 @@ protected void setNullFromDatabaseField(DatabaseField databaseField, CallableSta
}
}

/**
* INTERNAL
* Get the parameter from the JDBC statement with the given index.
* @param index - 1-based index in the argument list
*/
public Object getParameterValueFromDatabaseCall(CallableStatement statement, int index, AbstractSession session) throws SQLException {
return statement.getObject(index);
}

/**
* INTERNAL
* Get the parameter from the JDBC statement with the given name.
*/
public Object getParameterValueFromDatabaseCall(CallableStatement statement, String name, AbstractSession session) throws SQLException {
return statement.getObject(name);
}

public boolean usesBatchWriting() {
return usesBatchWriting;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -425,13 +425,14 @@ public String getProcedureAsString() {
}

/**
* INTERNAL:
* Should the variable name of a stored procedure call be printed as part of the procedure call
* e.g. EXECUTE PROCEDURE MyStoredProc(myvariable = ?)
* Obtain the platform specific argument string
*/
@Override
public boolean shouldPrintStoredProcedureArgumentNameInCall() {
return false;
public String getProcedureArgument(String name, Object parameter, Integer parameterType, StoredProcedureCall call, AbstractSession session) {
if (name != null && shouldPrintStoredProcedureArgumentNameInCall()) {
return getProcedureArgumentString() + name + " => " + "?";
}
return "?";
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
import java.io.ByteArrayInputStream;
import java.io.CharArrayReader;
import java.io.StringWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
Expand Down Expand Up @@ -93,7 +92,7 @@ public String getProcedureArgument(String name, Object parameter, Integer parame
if (name != null && shouldPrintStoredProcedureArgumentNameInCall()) {
return ":" + name;
}
return "";
return "?";
}

/**
Expand Down Expand Up @@ -186,7 +185,7 @@ public void registerOutputParameter(CallableStatement statement, String name, in
Object o = statement.unwrap(clazz);
PrivilegedAccessHelper.invokeMethod(method, o, parameters);
}
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
} catch (ReflectiveOperationException e) {
AbstractSessionLog.getLog().logThrowable(SessionLog.WARNING, null, e);
//Didn't work, fall back. This most likely still won't work, but the driver exception from there will be helpful.
super.registerOutputParameter(statement, name, jdbcType);
Expand Down Expand Up @@ -225,7 +224,7 @@ public void registerOutputParameter(CallableStatement statement, String name, in
Object o = statement.unwrap(clazz);
PrivilegedAccessHelper.invokeMethod(method, o, parameters);
}
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
} catch (ReflectiveOperationException e) {
AbstractSessionLog.getLog().logThrowable(SessionLog.WARNING, null, e);
//Didn't work, fall back. This most likely still won't work, but the driver exception from there will be helpful.
super.registerOutputParameter(statement, name, jdbcType, typeName);
Expand Down Expand Up @@ -423,7 +422,7 @@ else if (parameter instanceof Calendar) {
Object o = statement.unwrap(clazz);
PrivilegedAccessHelper.invokeMethod(method, o, parameters);
}
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
} catch (ReflectiveOperationException e) {
AbstractSessionLog.getLog().logThrowable(SessionLog.WARNING, null, e);
//Didn't work, fall back. This most likely still won't work, but the driver exception from there will be helpful.
super.setParameterValueInDatabaseCall(parameter, statement, name, session);
Expand Down Expand Up @@ -471,10 +470,53 @@ protected void setNullFromDatabaseField(DatabaseField databaseField, CallableSta
Object o = statement.unwrap(clazz);
PrivilegedAccessHelper.invokeMethod(method, o, parameters);
}
} catch (ClassNotFoundException | NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
} catch (ReflectiveOperationException e) {
AbstractSessionLog.getLog().logThrowable(SessionLog.WARNING, null, e);
//Didn't work, fall back. This most likely still won't work, but the driver exception from there will be helpful.
super.setNullFromDatabaseField(databaseField, statement, name);
}
}

@Override
public Object getParameterValueFromDatabaseCall(CallableStatement statement, String name, AbstractSession session)
throws SQLException {
String methodName = null;
Class[] methodArgs = null;
Object[] parameters = null;

methodName = "getJccObjectAtName";
methodArgs = new Class[] {String.class};
parameters = new Object[] {name};

if(methodName != null) {
try {
Class clazz = null;
Method method = null;
if (PrivilegedAccessHelper.shouldUsePrivilegedAccess()) {
try {
ClassLoader cl = AccessController.doPrivileged(new PrivilegedGetContextClassLoader(Thread.currentThread()));
clazz = AccessController.doPrivileged(new PrivilegedClassForName(DB2_CALLABLESTATEMENT_CLASS, true, cl));
method = AccessController.doPrivileged(new PrivilegedGetMethod(clazz, methodName, methodArgs, true));
Object o = statement.unwrap(clazz);
return AccessController.doPrivileged(new PrivilegedMethodInvoker(method, o, parameters));
} catch (PrivilegedActionException ex) {
if (ex.getCause() instanceof ClassNotFoundException) {
throw (ClassNotFoundException) ex.getCause();
}
throw (RuntimeException) ex.getCause();
}
} else {
ClassLoader cl = PrivilegedAccessHelper.getContextClassLoader(Thread.currentThread());
clazz = PrivilegedAccessHelper.getClassForName(DB2_CALLABLESTATEMENT_CLASS, true, cl);
method = PrivilegedAccessHelper.getMethod(clazz, methodName, methodArgs, true);
Object o = statement.unwrap(clazz);
return PrivilegedAccessHelper.invokeMethod(method, o, parameters);
}
} catch (ReflectiveOperationException e) {
AbstractSessionLog.getLog().logThrowable(SessionLog.WARNING, null, e);
}
}
//Didn't work, fall back. This most likely still won't work, but the driver exception from there will be helpful.
return super.getParameterValueFromDatabaseCall(statement, name, session);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -1302,8 +1302,8 @@ public String getPl2SQLName(ComplexDatabaseType type) {
}

@Override
protected Object getObject(CallableStatement statement, int index) throws SQLException {
return statement.getObject(index + 1);
public Object getOutputParameterValue(CallableStatement statement, int index, AbstractSession session) throws SQLException {
return session.getPlatform().getParameterValueFromDatabaseCall(statement, index + 1, session);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1044,20 +1044,15 @@ public void setOptionalArguments(List<DatabaseField> optionalArguments) {
this.optionalArguments = optionalArguments;
}

/**
* Get the return object from the statement. Use the index to determine what return object to get.
* @param index - 0-based index in the argument list
* @return
*/
@Override
protected Object getObject(CallableStatement statement, int index) throws SQLException {
public Object getOutputParameterValue(CallableStatement statement, int index, AbstractSession session) throws SQLException {
List<String> procedureArgs = getProcedureArgumentNames();
if(procedureArgs.size() == 0 || procedureArgs.get(0) == null) {
return super.getObject(statement, index);
return super.getOutputParameterValue(statement, index, session);
}

String name = procedureArgs.get(index);
return statement.getObject(name);
return getOutputParameterValue(statement, name, session);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ public void testLeftOuterJoinWithNullResult() {
}
}

private DatabasePlatform getPlatform(EntityManagerFactory emf) {
private static DatabasePlatform getPlatform(EntityManagerFactory emf) {
return ((EntityManagerFactoryImpl)emf).getServerSession().getPlatform();
}
}
Loading

0 comments on commit 09e8c4c

Please sign in to comment.