提交 d04b4cb7 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Add support for IN(UNNEST(?)

上级 21036320
...@@ -490,7 +490,7 @@ Instead, use a prepared statement with arrays as in the following example: ...@@ -490,7 +490,7 @@ Instead, use a prepared statement with arrays as in the following example:
</p> </p>
<pre> <pre>
PreparedStatement prep = conn.prepareStatement( PreparedStatement prep = conn.prepareStatement(
"SELECT * FROM TEST WHERE ID = ANY(?)"); "SELECT * FROM TEST WHERE ID IN(UNNEST(?))");
prep.setObject(1, new Object[] { "1", "2" }); prep.setObject(1, new Object[] { "1", "2" });
ResultSet rs = prep.executeQuery(); ResultSet rs = prep.executeQuery();
</pre> </pre>
......
...@@ -8,6 +8,8 @@ package org.h2.expression; ...@@ -8,6 +8,8 @@ package org.h2.expression;
import java.util.ArrayList; import java.util.ArrayList;
import org.h2.engine.Database; import org.h2.engine.Database;
import org.h2.engine.Session; import org.h2.engine.Session;
import org.h2.expression.function.Function;
import org.h2.expression.function.TableFunction;
import org.h2.index.IndexCondition; import org.h2.index.IndexCondition;
import org.h2.table.ColumnResolver; import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter; import org.h2.table.TableFilter;
...@@ -103,6 +105,18 @@ public class ConditionIn extends Condition { ...@@ -103,6 +105,18 @@ public class ConditionIn extends Condition {
} }
if (size == 1) { if (size == 1) {
Expression right = valueList.get(0); Expression right = valueList.get(0);
if (right instanceof TableFunction) {
TableFunction tf = (TableFunction) right;
if (tf.getFunctionType() == Function.UNNEST) {
Expression[] args = tf.getArgs();
if (args.length == 1) {
Expression arg = args[0];
if (arg instanceof Parameter) {
return new ConditionInParameter(database, left, (Parameter) arg);
}
}
}
}
Expression expr = new Comparison(session, Comparison.EQUAL, left, right); Expression expr = new Comparison(session, Comparison.EQUAL, left, right);
expr = expr.optimize(session); expr = expr.optimize(session);
return expr; return expr;
......
...@@ -18,7 +18,7 @@ import org.h2.value.ValueBoolean; ...@@ -18,7 +18,7 @@ import org.h2.value.ValueBoolean;
import org.h2.value.ValueNull; import org.h2.value.ValueNull;
/** /**
* A condition with parameter as {@code = ANY(?)}. * A condition with parameter as {@code IN(UNNEST(?))}.
*/ */
public class ConditionInParameter extends Condition { public class ConditionInParameter extends Condition {
private static final class ParameterList extends AbstractList<Expression> { private static final class ParameterList extends AbstractList<Expression> {
...@@ -60,12 +60,12 @@ public class ConditionInParameter extends Condition { ...@@ -60,12 +60,12 @@ public class ConditionInParameter extends Condition {
private final Parameter parameter; private final Parameter parameter;
/** /**
* Create a new {@code = ANY(?)} condition. * Create a new {@code IN(UNNEST(?))} condition.
* *
* @param database * @param database
* the database * the database
* @param left * @param left
* the expression before {@code = ANY(?)} * the expression before {@code IN(UNNEST(?))}
* @param parameter * @param parameter
* parameter * parameter
*/ */
...@@ -84,8 +84,10 @@ public class ConditionInParameter extends Condition { ...@@ -84,8 +84,10 @@ public class ConditionInParameter extends Condition {
boolean result = false; boolean result = false;
boolean hasNull = false; boolean hasNull = false;
Value value = parameter.getValue(session); Value value = parameter.getValue(session);
if (value instanceof ValueArray) { if (value == ValueNull.INSTANCE) {
for (Value r : ((ValueArray) value).getList()) { hasNull = true;
} else {
for (Value r : ((ValueArray) value.convertTo(Value.ARRAY)).getList()) {
if (r == ValueNull.INSTANCE) { if (r == ValueNull.INSTANCE) {
hasNull = true; hasNull = true;
} else { } else {
...@@ -95,12 +97,6 @@ public class ConditionInParameter extends Condition { ...@@ -95,12 +97,6 @@ public class ConditionInParameter extends Condition {
} }
} }
} }
} else {
if (value == ValueNull.INSTANCE) {
hasNull = true;
} else {
result = Comparison.compareNotNull(database, l, value, Comparison.EQUAL);
}
} }
if (!result && hasNull) { if (!result && hasNull) {
return ValueNull.INSTANCE; return ValueNull.INSTANCE;
...@@ -142,8 +138,8 @@ public class ConditionInParameter extends Condition { ...@@ -142,8 +138,8 @@ public class ConditionInParameter extends Condition {
@Override @Override
public StringBuilder getSQL(StringBuilder builder) { public StringBuilder getSQL(StringBuilder builder) {
builder.append('('); builder.append('(');
left.getSQL(builder).append(" = ANY("); left.getSQL(builder).append(" IN(UNNEST(");
return parameter.getSQL(builder).append("))"); return parameter.getSQL(builder).append(")))");
} }
@Override @Override
......
...@@ -1635,6 +1635,12 @@ public class TestPreparedStatement extends TestDb { ...@@ -1635,6 +1635,12 @@ public class TestPreparedStatement extends TestDb {
anyParameterCheck(ps, values, expected); anyParameterCheck(ps, values, expected);
ps = conn.prepareStatement("SELECT ID FROM TEST INNER JOIN TABLE(X INT=?) T ON TEST.VALUE = T.X"); ps = conn.prepareStatement("SELECT ID FROM TEST INNER JOIN TABLE(X INT=?) T ON TEST.VALUE = T.X");
anyParameterCheck(ps, values, expected); anyParameterCheck(ps, values, expected);
// Test expression IN(UNNEST(?))
ps = conn.prepareStatement("SELECT ID FROM TEST WHERE VALUE IN(UNNEST(?))");
assertThrows(ErrorCode.PARAMETER_NOT_SET_1, ps).executeQuery();
anyParameterCheck(ps, values, expected);
anyParameterCheck(ps, 300, new int[] {30});
anyParameterCheck(ps, -5, new int[0]);
// Test expression = ANY(?) // Test expression = ANY(?)
ps = conn.prepareStatement("SELECT ID FROM TEST WHERE VALUE = ANY(?)"); ps = conn.prepareStatement("SELECT ID FROM TEST WHERE VALUE = ANY(?)");
assertThrows(ErrorCode.PARAMETER_NOT_SET_1, ps).executeQuery(); assertThrows(ErrorCode.PARAMETER_NOT_SET_1, ps).executeQuery();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论