提交 18f439c9 authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov

Fix quantified comparison predicates with multi-column values

上级 a8db85bd
......@@ -2168,7 +2168,7 @@ ALL predicate returns FALSE if at least one such comparison returns FALSE.
Otherwise it returns NULL.
Quantified comparison predicates ANY and SOME return TRUE if specified comparison operation between
left size of condition and at least one value from a subquery returns TRUE.
left size of condition and at least one row from a subquery returns TRUE.
ANY and SOME predicates return FALSE if all such comparisons return FALSE.
Otherwise it returns NULL.
Note that these predicates have priority over ANY and SOME aggregate functions with subquery on the right side.
......
......@@ -5,7 +5,6 @@
*/
package org.h2.expression.condition;
import org.h2.api.ErrorCode;
import org.h2.command.dml.Query;
import org.h2.engine.Database;
import org.h2.engine.Session;
......@@ -13,13 +12,13 @@ import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.expression.ExpressionVisitor;
import org.h2.index.IndexCondition;
import org.h2.message.DbException;
import org.h2.result.LocalResult;
import org.h2.result.ResultInterface;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.util.StringUtils;
import org.h2.value.Value;
import org.h2.value.ValueArray;
import org.h2.value.ValueBoolean;
import org.h2.value.ValueNull;
......@@ -63,16 +62,25 @@ public class ConditionInSelect extends Condition {
compareType != Comparison.EQUAL_NULL_SAFE)) {
return getValueSlow(rows, l);
}
int dataType = rows.getColumnType(0);
if (dataType == Value.NULL) {
return ValueBoolean.FALSE;
}
l = l.convertTo(dataType, database.getMode());
if (rows.containsDistinct(new Value[] { l })) {
return ValueBoolean.TRUE;
}
if (rows.containsDistinct(new Value[] { ValueNull.INSTANCE })) {
return ValueNull.INSTANCE;
int columnCount = query.getColumnCount();
if (columnCount != 1) {
l = l.convertTo(Value.ARRAY);
Value[] leftValue = ((ValueArray) l).getList();
if (columnCount == leftValue.length && rows.containsDistinct(leftValue)) {
return ValueBoolean.TRUE;
}
} else {
int dataType = rows.getColumnType(0);
if (dataType == Value.NULL) {
return ValueBoolean.FALSE;
}
l = l.convertTo(dataType, database.getMode());
if (rows.containsDistinct(new Value[] { l })) {
return ValueBoolean.TRUE;
}
if (rows.containsDistinct(new Value[] { ValueNull.INSTANCE })) {
return ValueNull.INSTANCE;
}
}
return ValueBoolean.FALSE;
}
......@@ -84,7 +92,8 @@ public class ConditionInSelect extends Condition {
boolean result = all;
while (rows.next()) {
boolean value;
Value r = rows.currentRow()[0];
Value[] currentRow = rows.currentRow();
Value r = query.getColumnCount() == 1 ? currentRow[0] : org.h2.value.ValueArray.get(currentRow);
if (r == ValueNull.INSTANCE) {
value = false;
hasNull = true;
......@@ -116,9 +125,6 @@ public class ConditionInSelect extends Condition {
left = left.optimize(session);
query.setRandomAccessResult(true);
session.optimizeQueryExpression(query);
if (query.getColumnCount() != 1) {
throw DbException.get(ErrorCode.SUBQUERY_IS_NOT_SINGLE_COLUMN);
}
// Can not optimize: the data may change
return this;
}
......@@ -172,6 +178,9 @@ public class ConditionInSelect extends Condition {
if (compareType != Comparison.EQUAL) {
return;
}
if (query.getColumnCount() != 1) {
return;
}
if (!(left instanceof ExpressionColumn)) {
return;
}
......
......@@ -440,14 +440,26 @@ SELECT 1 FROM TEST HAVING TRUE FOR UPDATE;
DROP TABLE TEST;
> ok
CREATE TABLE TEST(ID INT PRIMARY KEY) AS SELECT X FROM SYSTEM_RANGE(1, 3);
CREATE TABLE TEST(ID INT PRIMARY KEY, V INT) AS SELECT X, X + 1 FROM SYSTEM_RANGE(1, 3);
> ok
SELECT * FROM TEST WHERE ID != ALL (SELECT ID FROM TEST WHERE ID IN(1, 3));
SELECT ID FROM TEST WHERE ID != ALL (SELECT ID FROM TEST WHERE ID IN(1, 3));
> ID
> --
> 2
> rows: 1
SELECT (1, 3) > ANY (SELECT ID, V FROM TEST);
>> TRUE
SELECT (1, 2) > ANY (SELECT ID, V FROM TEST);
>> FALSE
SELECT (2, 3) = ANY (SELECT ID, V FROM TEST);
>> TRUE
SELECT (3, 4) > ALL (SELECT ID, V FROM TEST);
>> FALSE
DROP TABLE TEST;
> ok
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论