[#4155] Add support for PL/SQL BOOLEAN types

This commit is contained in:
lukaseder 2016-02-25 15:29:24 +01:00
parent dde5d91bb4
commit 5e7255b31c
2 changed files with 164 additions and 50 deletions

View File

@ -125,13 +125,14 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
private Parameter<T> returnParameter;
private ResultsImpl results;
private boolean overloaded;
private boolean hasDefaultedParameters;
private boolean hasUnnamedParameters;
// ------------------------------------------------------------------------
// Call-data attributes (call-specific)
// ------------------------------------------------------------------------
@ -143,7 +144,7 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
private Configuration configuration;
private final Map<Parameter<?>, Object> outValues;
private final Map<Parameter<?>, Integer> parameterIndexes;
private final Map<Parameter<?>, Integer> resultIndexes;
// ------------------------------------------------------------------------
// Constructors
@ -188,7 +189,7 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
@SuppressWarnings({ "unchecked", "rawtypes" })
protected <X, Y> AbstractRoutine(String name, Schema schema, Package pkg, DataType<X> type, Converter<Y, T> converter, Binding<X, Y> binding) {
this.parameterIndexes = new HashMap<Parameter<?>, Integer>();
this.resultIndexes = new HashMap<Parameter<?>, Integer>();
this.schema = schema;
this.pkg = pkg;
@ -496,56 +497,101 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
}
final void bind0(BindContext context) {
for (Parameter<?> parameter : getParameters()) {
// [#1183] [#3533] Skip defaulted parameters
if (getInParameters().contains(parameter) && inValuesDefaulted.contains(parameter)) {
if (getInParameters().contains(parameter) && inValuesDefaulted.contains(parameter))
continue;
}
int index = context.peekIndex();
parameterIndexes.put(parameter, index);
bind1(context, parameter, getInValues().get(parameter) != null, resultParameter(parameter));
}
}
if (getInValues().get(parameter) != null) {
context.visit(getInValues().get(parameter));
private final void bind1(BindContext context, Parameter<?> parameter, boolean bindAsIn, boolean bindAsOut) {
int index = context.peekIndex();
// [#391] This happens when null literals are used as IN/OUT
// parameters. They're not bound as in value, but they need to
// be registered as OUT parameter
if (index == context.peekIndex() && getOutParameters().contains(parameter)) {
context.nextIndex();
}
}
if (bindAsOut)
resultIndexes.put(parameter, index);
// Skip one index for OUT parameters
else {
if (bindAsIn) {
context.visit(getInValues().get(parameter));
// [#391] This happens when null literals are used as IN/OUT
// parameters. They're not bound as in value, but they need to
// be registered as OUT parameter
if (index == context.peekIndex() && bindAsOut)
context.nextIndex();
}
}
// Skip one index for OUT parameters
else {
context.nextIndex();
}
}
final void toSQL0(RenderContext context) {
toSQLDeclare(context);
toSQLBegin(context);
if (getReturnParameter() != null) {
if (getReturnParameter() != null)
toSQLAssign(context);
}
toSQLCall(context);
context.sql('(');
String separator = "";
for (Parameter<?> parameter : getParameters()) {
List<Parameter<?>> parameters = getParameters();
for (int i = 0; i < parameters.size(); i++) {
Parameter<?> parameter = parameters.get(i);
// The return value has already been written
if (parameter.equals(getReturnParameter())) {
if (parameter.equals(getReturnParameter()))
continue;
}
// OUT and IN OUT parameters are always written as a '?' bind variable
else if (getOutParameters().contains(parameter)) {
if (getOutParameters().contains(parameter)) {
context.sql(separator);
toSQLOutParam(context, parameter);
toSQLOutParam(context, parameter, i);
}
// [#1183] [#3533] Omit defaulted parameters
@ -556,7 +602,7 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
// IN parameters are rendered normally
else {
context.sql(separator);
toSQLInParam(context, parameter, getInValues().get(parameter));
toSQLInParam(context, parameter, i, getInValues().get(parameter));
}
separator = ", ";
@ -576,9 +622,52 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
{
context.sql(" }");
}
}
private final void toSQLDeclare(RenderContext context) {
}
private final void toSQLBegin(RenderContext context) {
@ -602,6 +691,9 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
{
context.sql("? = ");
}
@ -620,7 +712,10 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
toSQLQualifiedName(context);
}
private final void toSQLOutParam(RenderContext context, Parameter<?> parameter) {
private final void toSQLOutParam(RenderContext context, Parameter<?> parameter, int index) {
@ -631,7 +726,10 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
context.sql('?');
}
private final void toSQLInParam(RenderContext context, Parameter<?> parameter, Field<?> value) {
private final void toSQLInParam(RenderContext context, Parameter<?> parameter, int index, Field<?> value) {
@ -669,13 +767,9 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
}
private final void fetchOutParameters(ExecuteContext ctx) throws SQLException {
for (Parameter<?> parameter : getParameters()) {
if (parameter.equals(getReturnParameter()) ||
getOutParameters().contains(parameter)) {
for (Parameter<?> parameter : getParameters())
if (resultParameter(parameter))
fetchOutParameter(ctx, parameter);
}
}
}
private final <U> void fetchOutParameter(ExecuteContext ctx, Parameter<U> parameter) throws SQLException {
@ -683,7 +777,7 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
ctx.configuration(),
ctx.data(),
(CallableStatement) ctx.statement(),
parameterIndexes.get(parameter)
resultIndexes.get(parameter)
);
parameter.getBinding().get(out);
@ -697,17 +791,13 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
// Register all out / inout parameters according to their position
// Note that some RDBMS do not support binding by name very well
for (Parameter<?> parameter : getParameters()) {
if (parameter.equals(getReturnParameter()) ||
getOutParameters().contains(parameter)) {
for (Parameter<?> parameter : getParameters())
if (resultParameter(parameter))
registerOutParameter(c, data, statement, parameter);
}
}
}
private final <U> void registerOutParameter(Configuration c, Map<Object, Object> data, CallableStatement statement, Parameter<U> parameter) throws SQLException {
parameter.getBinding().register(new DefaultBindingRegisterContext<U>(c, data, statement, parameterIndexes.get(parameter)));
parameter.getBinding().register(new DefaultBindingRegisterContext<U>(c, data, statement, resultIndexes.get(parameter)));
}
// ------------------------------------------------------------------------
@ -716,9 +806,8 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
@Override
public final T getReturnValue() {
if (returnParameter != null) {
if (returnParameter != null)
return getValue(returnParameter);
}
return null;
}
@ -800,9 +889,18 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
private final boolean hasDefaultedParameters() {
return hasDefaultedParameters && !inValuesDefaulted.isEmpty();
}
private final boolean hasUnnamedParameters() {
return hasUnnamedParameters;
@ -810,8 +908,16 @@ public abstract class AbstractRoutine<T> extends AbstractQueryPart implements Ro
private final void addParameter(Parameter<?> parameter) {
allParameters.add(parameter);
hasDefaultedParameters |= parameter.isDefaulted();
hasUnnamedParameters |= parameter.isUnnamed();
}
private final boolean resultParameter(Parameter<?> parameter) {
return parameter.equals(getReturnParameter()) || getOutParameters().contains(parameter);
}
protected final void addInParameter(Parameter<?> parameter) {

View File

@ -780,7 +780,13 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
Configuration configuration = ctx.configuration();
int sqlType = DefaultDataType.getDataType(ctx.dialect(), type).getSQLType();
switch (configuration.dialect().family()) {
switch (configuration.family()) {
@ -919,6 +925,8 @@ public class DefaultBinding<T, U> implements Binding<T, U> {
ctx.statement().setBoolean(ctx.index(), (Boolean) value);
}
else if (actualType == BigDecimal.class) {