Unverified 提交 291b541c authored 作者: Evgenij Ryazanov's avatar Evgenij Ryazanov 提交者: GitHub

Merge pull request #1607 from katzyn/misc

Fixes for quantified comparison predicates and other changes
......@@ -2152,7 +2152,7 @@ ID<>2
"
"Other Grammar","Condition Right Hand Side","
compare { { ALL ( select ) } | operand }
compare { { { ALL | ANY | SOME } ( select ) } | operand }
| IS [ NOT ] NULL
| IS [ NOT ] [ DISTINCT FROM ] operand
| BETWEEN operand AND operand
......@@ -2162,6 +2162,18 @@ compare { { ALL ( select ) } | operand }
","
The right hand side of a condition.
Quantified comparison predicate ALL returns TRUE if specified comparison operation between
left size of condition and each row from a subquery returns TRUE, including case when there are no rows.
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 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.
Use parentheses around aggregate function.
The conditions ""IS [ NOT ]"" and ""IS [ NOT ] DISTINCT FROM"" are null-safe, meaning
NULL is considered the same as NULL, and the condition never evaluates to NULL.
......@@ -2179,6 +2191,8 @@ ILIKE does a case-insensitive compare.
When comparing with REGEXP, regular expression matching is used.
See Java ""Matcher.find"" for details.
","
VALUE > 10
A IS NOT DISTINCT FROM B
LIKE 'Jo%'
"
......@@ -3469,8 +3483,13 @@ EVERY(ID>10)
Returns true if any expression is true.
If no rows are selected, the result is NULL.
Aggregates are only allowed in select statements.
Note that if ANY or SOME aggregate function is placed on the right side of comparison operation
and argument of this function is a subquery additional parentheses around aggregate function are required,
otherwise it will be parsed as quantified comparison predicate.
","
ANY(NAME LIKE 'W%')
A = (ANY((SELECT B FROM T)))
"
"Functions (Aggregate)","COUNT","
......
......@@ -21,6 +21,12 @@ Change Log
<h2>Next Version (unreleased)</h2>
<ul>
<li>Issue #1606: Quantified comparison predicate doesn't work correctly on primary key column
</li>
<li>Issue #1057: Very slow execution with subquery and connection parameter LAZY_QUERY_EXECUTION=1
</li>
<li>Issue #1072: Very slow execution with join and connection parameter LAZY_QUERY_EXECUTION=1
</li>
<li>PR #1601: Return BIGINT from ROWNUM(), ROW_NUMBER() and rank functions
</li>
<li>PR #1599: cleanup StringUtils.cache
......
......@@ -959,7 +959,6 @@ or the SQL statement <code>SET MODE PostgreSQL</code>.
</li><li>Fixed-width strings are padded with spaces.
</li><li>MONEY data type is treated like NUMERIC(19, 2) data type.
</li><li>Datetime value functions return the same value within a transaction.
</li><li>ANY and SOME after comparison operators are parsed as array comparison operators.
</li></ul>
<h3>Ignite Compatibility Mode</h3>
......
......@@ -12,6 +12,9 @@ import static org.h2.util.ParserUtil.ALL;
import static org.h2.util.ParserUtil.CHECK;
import static org.h2.util.ParserUtil.CONSTRAINT;
import static org.h2.util.ParserUtil.CROSS;
import static org.h2.util.ParserUtil.CURRENT_DATE;
import static org.h2.util.ParserUtil.CURRENT_TIME;
import static org.h2.util.ParserUtil.CURRENT_TIMESTAMP;
import static org.h2.util.ParserUtil.DISTINCT;
import static org.h2.util.ParserUtil.EXCEPT;
import static org.h2.util.ParserUtil.EXISTS;
......@@ -30,6 +33,8 @@ import static org.h2.util.ParserUtil.IS;
import static org.h2.util.ParserUtil.JOIN;
import static org.h2.util.ParserUtil.LIKE;
import static org.h2.util.ParserUtil.LIMIT;
import static org.h2.util.ParserUtil.LOCALTIME;
import static org.h2.util.ParserUtil.LOCALTIMESTAMP;
import static org.h2.util.ParserUtil.MINUS;
import static org.h2.util.ParserUtil.NATURAL;
import static org.h2.util.ParserUtil.NOT;
......@@ -457,6 +462,10 @@ public class Parser {
"LIKE",
// LIMIT
"LIMIT",
// LOCALTIME
"LOCALTIME",
// LOCALTIMESTAMP
"LOCALTIMESTAMP",
// MINUS
"MINUS",
// NATURAL
......@@ -1408,7 +1417,6 @@ public class Parser {
return select;
}
private Prepared parseMerge() {
int start = lastParseIndex;
read("INTO");
......@@ -2853,23 +2861,33 @@ public class Parser {
break;
}
read();
int start = lastParseIndex;
if (readIf(ALL)) {
read(OPEN_PAREN);
Query query = parseSelect();
r = new ConditionInSelect(database, r, query, true,
compareType);
read(CLOSE_PAREN);
} else if (database.getMode().anyAndSomeAreComparisons && (readIf("ANY") || readIf("SOME"))) {
if (isSelect()) {
Query query = parseSelect();
r = new ConditionInSelect(database, r, query, true, compareType);
read(CLOSE_PAREN);
} else {
parseIndex = start;
read();
r = new Comparison(session, compareType, r, readConcat());
}
} else if (readIf("ANY") || readIf("SOME")) {
read(OPEN_PAREN);
if (currentTokenType == PARAMETER && compareType == 0) {
Parameter p = readParameter();
r = new ConditionInParameter(database, r, p);
} else {
read(CLOSE_PAREN);
} else if (isSelect()) {
Query query = parseSelect();
r = new ConditionInSelect(database, r, query, false,
compareType);
r = new ConditionInSelect(database, r, query, false, compareType);
read(CLOSE_PAREN);
} else {
parseIndex = start;
read();
r = new Comparison(session, compareType, r, readConcat());
}
read(CLOSE_PAREN);
} else {
r = new Comparison(session, compareType, r, readConcat());
}
......@@ -3523,6 +3541,14 @@ public class Parser {
}
}
private Expression readKeywordFunction(String name) {
if (readIf(OPEN_PAREN)) {
return readFunction(null, name);
} else {
return readFunctionWithoutParameters(name);
}
}
private Expression readFunctionWithoutParameters(String name) {
if (database.isAllowBuiltinAliasOverride()) {
FunctionAlias functionAlias = database.getSchema(session.getCurrentSchemaName()).findFunction(name);
......@@ -3806,6 +3832,26 @@ public class Parser {
r = ValueExpression.get(currentValue);
read();
break;
case CURRENT_DATE:
read();
r = readKeywordFunction("CURRENT_DATE");
break;
case CURRENT_TIME:
read();
r = readKeywordFunction("CURRENT_TIME");
break;
case CURRENT_TIMESTAMP:
read();
r = readKeywordFunction("CURRENT_TIMESTAMP");
break;
case LOCALTIME:
read();
r = readKeywordFunction("LOCALTIME");
break;
case LOCALTIMESTAMP:
read();
r = readKeywordFunction("LOCALTIMESTAMP");
break;
default:
throw getSyntaxError();
}
......@@ -3844,9 +3890,15 @@ public class Parser {
private Expression readTermWithIdentifier(String name) {
// Unquoted identifier is never empty
char ch = name.charAt(0);
if (!identifiersToUpper) {
/*
* Convert a-z to A-Z. This method is safe, because only A-Z
* characters are considered below.
*/
ch &= 0xffdf;
}
switch (ch) {
case 'A':
case 'a':
if (equalsToken("ARRAY", name)) {
read(OPEN_BRACKET);
ArrayList<Expression> list = Utils.newSmallArrayList();
......@@ -3861,21 +3913,13 @@ public class Parser {
}
break;
case 'C':
case 'c':
if (equalsToken("CURRENT_DATE", name)) {
return readFunctionWithoutParameters("CURRENT_DATE");
} else if (equalsToken("CURRENT_TIME", name)) {
return readFunctionWithoutParameters("CURRENT_TIME");
} else if (equalsToken("CURRENT_TIMESTAMP", name)) {
return readFunctionWithoutParameters("CURRENT_TIMESTAMP");
} else if (equalsToken("CURRENT_USER", name)) {
if (equalsToken("CURRENT_USER", name)) {
return readFunctionWithoutParameters("USER");
} else if (database.getMode().getEnum() == ModeEnum.DB2 && equalsToken("CURRENT", name)) {
return parseDB2SpecialRegisters(name);
}
break;
case 'D':
case 'd':
if (currentTokenType == VALUE && currentValue.getType() == Value.STRING &&
(equalsToken("DATE", name) || equalsToken("D", name))) {
String date = currentValue.getString();
......@@ -3884,7 +3928,6 @@ public class Parser {
}
break;
case 'E':
case 'e':
if (currentTokenType == VALUE && currentValue.getType() == Value.STRING && equalsToken("E", name)) {
String text = currentValue.getString();
// the PostgreSQL ODBC driver uses
......@@ -3897,21 +3940,11 @@ public class Parser {
}
break;
case 'I':
case 'i':
if (equalsToken("INTERVAL", name)) {
return readInterval();
}
break;
case 'L':
case 'l':
if (equalsToken("LOCALTIME", name)) {
return readFunctionWithoutParameters("LOCALTIME");
} else if (equalsToken("LOCALTIMESTAMP", name)) {
return readFunctionWithoutParameters("LOCALTIMESTAMP");
}
break;
case 'N':
case 'n':
if (equalsToken("NEXT", name) && readIf("VALUE")) {
read(FOR);
return new SequenceValue(readSequence());
......@@ -3923,7 +3956,6 @@ public class Parser {
}
break;
case 'S':
case 's':
if (equalsToken("SYSDATE", name)) {
return readFunctionWithoutParameters("CURRENT_TIMESTAMP");
} else if (equalsToken("SYSTIME", name)) {
......@@ -3933,7 +3965,6 @@ public class Parser {
}
break;
case 'T':
case 't':
if (equalsToken("TIME", name)) {
boolean without = readIf("WITHOUT");
if (without) {
......@@ -3986,7 +4017,6 @@ public class Parser {
}
break;
case 'X':
case 'x':
if (currentTokenType == VALUE && currentValue.getType() == Value.STRING && equalsToken("X", name)) {
byte[] buffer = StringUtils.convertHexToBytes(currentValue.getString());
read();
......@@ -4061,10 +4091,11 @@ public class Parser {
if (readIf(WITH)) {
read("TIME");
read("ZONE");
return readFunctionWithoutParameters("CURRENT_TIMESTAMP");
return readKeywordFunction("CURRENT_TIMESTAMP");
}
return readFunctionWithoutParameters("LOCALTIMESTAMP");
return readKeywordFunction("LOCALTIMESTAMP");
} else if (readIf("TIME")) {
// Time with fractional seconds is not supported by DB2
return readFunctionWithoutParameters("CURRENT_TIME");
} else if (readIf("DATE")) {
return readFunctionWithoutParameters("CURRENT_DATE");
......@@ -5978,7 +6009,14 @@ public class Parser {
private CreateFunctionAlias parseCreateFunctionAlias(boolean force) {
boolean ifNotExists = readIfNotExists();
String aliasName = readIdentifierWithSchema();
String aliasName;
if (currentTokenType != IDENTIFIER) {
aliasName = currentToken;
read();
schemaName = session.getCurrentSchemaName();
} else {
aliasName = readIdentifierWithSchema();
}
final boolean newAliasSameNameAsBuiltin = Function.getFunction(database, aliasName) != null;
if (database.isAllowBuiltinAliasOverride() && newAliasSameNameAsBuiltin) {
// fine
......
......@@ -209,12 +209,6 @@ public class Mode {
*/
public boolean dateTimeValueWithinTransaction;
/**
* If {@code true}, ANY and SOME after comparison operators are parsed as
* array comparison operators.
*/
public boolean anyAndSomeAreComparisons;
/**
* An optional Set of hidden/disallowed column types.
* Certain DBMSs don't support all column types provided by H2, such as
......@@ -360,7 +354,6 @@ public class Mode {
dt.name = "MONEY";
mode.typeByNameMap.put("MONEY", dt);
mode.dateTimeValueWithinTransaction = true;
mode.anyAndSomeAreComparisons = true;
add(mode);
mode = new Mode(ModeEnum.Ignite);
......
......@@ -19,6 +19,7 @@ import org.h2.engine.Session;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Subquery;
import org.h2.expression.analysis.Window;
import org.h2.index.Cursor;
import org.h2.index.Index;
......@@ -265,6 +266,15 @@ public class Aggregate extends AbstractAggregate {
this.groupConcatSeparator = separator;
}
/**
* Returns the type of this aggregate.
*
* @return the type of this aggregate
*/
public AggregateType getAggregateType() {
return type;
}
private void sortWithOrderBy(Value[] array) {
final SortOrder sortOrder = orderBySort;
if (sortOrder != null) {
......@@ -812,7 +822,12 @@ public class Aggregate extends AbstractAggregate {
on.getSQL(builder).append(')');
} else {
builder.append('(');
on.getUnenclosedSQL(builder).append(')');
if (on instanceof Subquery) {
on.getSQL(builder);
} else {
on.getUnenclosedSQL(builder);
}
builder.append(')');
}
return appendTailConditions(builder);
}
......
......@@ -14,6 +14,8 @@ import org.h2.expression.ExpressionColumn;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Parameter;
import org.h2.expression.ValueExpression;
import org.h2.expression.aggregate.Aggregate;
import org.h2.expression.aggregate.Aggregate.AggregateType;
import org.h2.index.IndexCondition;
import org.h2.message.DbException;
import org.h2.table.Column;
......@@ -130,6 +132,7 @@ public class Comparison extends Condition {
@Override
public StringBuilder getSQL(StringBuilder builder) {
boolean encloseRight = false;
builder.append('(');
switch (compareType) {
case IS_NULL:
......@@ -143,9 +146,25 @@ public class Comparison extends Condition {
left.getSQL(builder).append(", ");
right.getSQL(builder).append(')');
break;
case EQUAL:
case BIGGER_EQUAL:
case BIGGER:
case SMALLER_EQUAL:
case SMALLER:
case NOT_EQUAL:
if (right instanceof Aggregate && ((Aggregate) right).getAggregateType() == AggregateType.ANY) {
encloseRight = true;
}
//$FALL-THROUGH$
default:
left.getSQL(builder).append(' ').append(getCompareOperator(compareType)).append(' ');
if (encloseRight) {
builder.append('(');
}
right.getSQL(builder);
if (encloseRight) {
builder.append(')');
}
}
return builder.append(')');
}
......
......@@ -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;
}
......@@ -169,6 +175,12 @@ public class ConditionInSelect extends Condition {
if (!session.getDatabase().getSettings().optimizeInList) {
return;
}
if (compareType != Comparison.EQUAL) {
return;
}
if (query.getColumnCount() != 1) {
return;
}
if (!(left instanceof ExpressionColumn)) {
return;
}
......
......@@ -6,6 +6,7 @@
package org.h2.expression.function;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DateFormatSymbols;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;
......@@ -233,7 +234,7 @@ public class ToChar {
int separator = findDecimalSeparator(format);
int formatScale = calculateScale(format, separator);
if (formatScale < number.scale()) {
number = number.setScale(formatScale, BigDecimal.ROUND_HALF_UP);
number = number.setScale(formatScale, RoundingMode.HALF_UP);
}
// any 9s to the left of the decimal separator but to the right of a
......@@ -461,7 +462,7 @@ public class ToChar {
}
}
int i = number.setScale(0, BigDecimal.ROUND_HALF_UP).intValue();
int i = number.setScale(0, RoundingMode.HALF_UP).intValue();
String hex = Integer.toHexString(i);
if (digits < hex.length()) {
hex = StringUtils.pad("", digits + 1, "#", true);
......
......@@ -1056,7 +1056,7 @@ public class MVMap<K, V> extends AbstractMap<K, V>
return getVersion(getRoot());
}
private long getVersion(RootReference rootReference) {
private static long getVersion(RootReference rootReference) {
RootReference previous = rootReference.previous;
return previous == null || previous.root != rootReference.root ||
previous.appendCounter != rootReference.appendCounter ?
......
......@@ -905,6 +905,7 @@ public class MVStore implements AutoCloseable {
/**
* Close the file and the store. Unsaved changes are written to disk first.
*/
@Override
public void close() {
if (closed) {
return;
......
......@@ -1236,10 +1236,12 @@ public abstract class Page implements Cloneable
}
}
@Override
public boolean isComplete() {
return complete;
}
@Override
public void setComplete() {
recalculateTotalCount();
complete = true;
......
......@@ -279,10 +279,6 @@ public class Column {
return precision;
}
public void setPrecision(long p) {
precision = p;
}
public int getDisplaySize() {
return displaySize;
}
......@@ -299,10 +295,6 @@ public class Column {
return extTypeInfo;
}
public void setExtTypeInfo(ExtTypeInfo extTypeInfo) {
this.extTypeInfo = extTypeInfo;
}
public boolean getVisible() {
return visible;
}
......
......@@ -137,10 +137,20 @@ public class ParserUtil {
*/
public static final int LIMIT = LIKE + 1;
/**
* The token "LOCALTIME".
*/
public static final int LOCALTIME = LIMIT + 1;
/**
* The token "LOCALTIMESTAMP".
*/
public static final int LOCALTIMESTAMP = LOCALTIME + 1;
/**
* The token "MINUS".
*/
public static final int MINUS = LIMIT + 1;
public static final int MINUS = LOCALTIMESTAMP + 1;
/**
* The token "NATURAL".
......@@ -311,12 +321,12 @@ public class ParserUtil {
return CONSTRAINT;
} else if (eq("CROSS", s, ignoreCase, start, end)) {
return CROSS;
}
if (additionalKeywords) {
if (eq("CURRENT_DATE", s, ignoreCase, start, end) || eq("CURRENT_TIME", s, ignoreCase, start, end)
|| eq("CURRENT_TIMESTAMP", s, ignoreCase, start, end)) {
return KEYWORD;
}
} else if (eq("CURRENT_DATE", s, ignoreCase, start, end)) {
return CURRENT_DATE;
} else if (eq("CURRENT_TIME", s, ignoreCase, start, end)) {
return CURRENT_TIME;
} else if (eq("CURRENT_TIMESTAMP", s, ignoreCase, start, end)) {
return CURRENT_TIMESTAMP;
}
return IDENTIFIER;
case 'D':
......@@ -380,11 +390,10 @@ public class ParserUtil {
return LIMIT;
} else if (eq("LIKE", s, ignoreCase, start, end)) {
return LIKE;
}
if (additionalKeywords) {
if (eq("LOCALTIME", s, ignoreCase, start, end) || eq("LOCALTIMESTAMP", s, ignoreCase, start, end)) {
return KEYWORD;
}
} else if (eq("LOCALTIME", s, ignoreCase, start, end)) {
return LOCALTIME;
} else if (eq("LOCALTIMESTAMP", s, ignoreCase, start, end)) {
return LOCALTIMESTAMP;
}
return IDENTIFIER;
case 'M':
......
......@@ -11,6 +11,7 @@ import java.io.Reader;
import java.io.StringReader;
import java.lang.ref.SoftReference;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.nio.charset.StandardCharsets;
import java.sql.Date;
import java.sql.PreparedStatement;
......@@ -1431,7 +1432,7 @@ public abstract class Value {
throw DbException.get(
ErrorCode.NUMERIC_VALUE_OUT_OF_RANGE_2, x.toString(), getColumnName(column));
}
return x.setScale(0, BigDecimal.ROUND_HALF_UP).longValue();
return x.setScale(0, RoundingMode.HALF_UP).longValue();
}
private static String getColumnName(Object column) {
......
......@@ -6,6 +6,7 @@
package org.h2.value;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.PreparedStatement;
import java.sql.SQLException;
......@@ -95,7 +96,7 @@ public class ValueDecimal extends Value {
}
BigDecimal bd = value.divide(dec.value,
value.scale() + DIVIDE_SCALE_ADD,
BigDecimal.ROUND_HALF_DOWN);
RoundingMode.HALF_DOWN);
if (bd.signum() == 0) {
bd = BigDecimal.ZERO;
} else if (bd.scale() > 0) {
......@@ -265,7 +266,7 @@ public class ValueDecimal extends Value {
if (scale > BIG_DECIMAL_SCALE_MAX || scale < -BIG_DECIMAL_SCALE_MAX) {
throw DbException.getInvalidValueException("scale", scale);
}
return bd.setScale(scale, BigDecimal.ROUND_HALF_UP);
return bd.setScale(scale, RoundingMode.HALF_UP);
}
}
......@@ -6,6 +6,7 @@
package org.h2.test.bench;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
......@@ -214,7 +215,7 @@ public class BenchCThread {
BigDecimal olAmount = new BigDecimal(olQuantity).multiply(
price).multiply(ONE.add(wTax).add(tax)).multiply(
ONE.subtract(discount));
olAmount = olAmount.setScale(2, BigDecimal.ROUND_HALF_UP);
olAmount = olAmount.setScale(2, RoundingMode.HALF_UP);
amt[number - 1] = olAmount;
total = total.add(olAmount);
prep = prepare("INSERT INTO ORDER_LINE (OL_O_ID, OL_D_ID, OL_W_ID, OL_NUMBER, "
......
......@@ -102,7 +102,7 @@ public class TestLIRSMemoryConsumption extends TestDb {
return 2560;
}
private long getMemUsedKb() {
private static long getMemUsedKb() {
Runtime rt = Runtime.getRuntime();
long memory = Long.MAX_VALUE;
for (int i = 0; i < 8; i++) {
......
......@@ -42,7 +42,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
String[] expectedRowData = new String[]{"|meat|null", "|fruit|3", "|veg|2"};
String[] expectedColumnTypes = new String[]{"VARCHAR", numericName};
String[] expectedColumnNames = new String[]{"VAL",
"SUM(SELECT\n" +
"SUM((SELECT\n" +
" X\n" +
"FROM PUBLIC.\"\" BB\n" +
" /* SELECT\n" +
......@@ -61,7 +61,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
" GROUP BY A: A IS A.VAL\n" +
" */\n" +
" /* scanCount: 1 */\n" +
"WHERE BB.A IS A.VAL)"};
"WHERE BB.A IS A.VAL))"};
String setupSQL =
"DROP TABLE IF EXISTS A; "
......@@ -92,7 +92,7 @@ public class TestPersistentCommonTableExpressions extends AbstractBaseForCommonT
"GROUP BY a) \n" +
"SELECT \n" +
"A.val, \n" +
"sum(SELECT X FROM BB WHERE BB.a IS A.val)\n" +
"sum((SELECT X FROM BB WHERE BB.a IS A.val))\n" +
"FROM A \n" + "GROUP BY A.val";
int maxRetries = 3;
int expectedNumberOfRows = expectedRowData.length;
......
......@@ -1681,7 +1681,6 @@ public class TestPreparedStatement extends TestDb {
anyParameterCheck(ps, 300, new int[] {30});
anyParameterCheck(ps, -5, new int[0]);
// Test expression = ANY(?)
conn.createStatement().execute("SET MODE PostgreSQL");
ps = conn.prepareStatement("SELECT ID FROM TEST WHERE VALUE = ANY(?)");
assertThrows(ErrorCode.PARAMETER_NOT_SET_1, ps).executeQuery();
anyParameterCheck(ps, values, expected);
......
......@@ -439,3 +439,27 @@ SELECT 1 FROM TEST HAVING TRUE FOR UPDATE;
DROP TABLE TEST;
> ok
CREATE TABLE TEST(ID INT PRIMARY KEY, V INT) AS SELECT X, X + 1 FROM SYSTEM_RANGE(1, 3);
> ok
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
......@@ -19,3 +19,15 @@ SELECT A, ANY(B < 2), SOME(B > 3), BOOL_OR(B = 1), ANY(B = 1) FILTER (WHERE A =
DROP TABLE TEST;
> ok
SELECT TRUE = (ANY((SELECT TRUE)));
> TRUE = (ANY((SELECT TRUE FROM SYSTEM_RANGE(1, 1) /* PUBLIC.RANGE_INDEX */ /* scanCount: 2 */)))
> -----------------------------------------------------------------------------------------------
> TRUE
> rows: 1
SELECT TRUE = (ANY((SELECT FALSE)));
> TRUE = (ANY((SELECT FALSE FROM SYSTEM_RANGE(1, 1) /* PUBLIC.RANGE_INDEX */ /* scanCount: 2 */)))
> ------------------------------------------------------------------------------------------------
> FALSE
> rows: 1
......@@ -6513,9 +6513,6 @@ SELECT * FROM CUSTOMER WHERE NAME NOT IN(SELECT NAME FROM CUSTOMER);
> -- ----
> rows: 0
SET MODE PostgreSQL;
> ok
SELECT * FROM CUSTOMER WHERE NAME = ANY(SELECT NAME FROM CUSTOMER);
> ID NAME
> -- -------
......@@ -6548,9 +6545,6 @@ SELECT * FROM CUSTOMER WHERE NAME < ANY(SELECT NAME FROM CUSTOMER);
> 2 Meier
> rows: 2
SET MODE Regular;
> ok
DROP TABLE INVOICE;
> ok
......
......@@ -135,8 +135,8 @@ public class TestSubqueryPerformanceOnLazyExecutionMode extends TestDb {
}
if (failCnt > successCnt) {
fail("Lazy execution too slow. Avg lazy time: "
+ (totalLazy / FAIL_REPEATS) + ", avg not lazy time: " + (totalNotLazy / FAIL_REPEATS));
fail("Lazy execution too slow. Avg lazy time: "
+ (totalLazy / FAIL_REPEATS) + ", avg not lazy time: " + (totalNotLazy / FAIL_REPEATS));
}
}
......
......@@ -804,4 +804,4 @@ qualification opportunity jumping exploited unacceptable vrs duplicated
queryparser tokenized freeze factorings recompilation unenclosed rfe dsync
econd irst bcef ordinality nord unnest
analyst occupation distributive josaph aor engineer sajeewa isuru randil kevin doctor businessman artist ashan
corrupts splitted disruption unintentional octets preconditions
corrupts splitted disruption unintentional octets preconditions predicates subq
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论