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

Merge pull request #1388 from katzyn/operation

Extract UnaryOperation from Operation and other changes
......@@ -79,7 +79,7 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Console: add accesskey to most important commands (A, AREA, BUTTON, INPUT, LABEL, LEGEND, TEXTAREA).
</li><li>Test performance again with SQL Server, Oracle, DB2.
</li><li>Test with Spatial DB in a box / JTS: http://www.opengeospatial.org/standards/sfs - OpenGIS Implementation Specification.
</li><li>Write more tests and documentation for MVCC (Multi Version Concurrency Control).
</li><li>Improve documentation of MVCC (Multi Version Concurrency Control).
</li><li>Find a tool to view large text file (larger than 100 MB), with find, page up and down (like less), truncate before / after.
</li><li>Implement, test, document XAConnection and so on.
</li><li>Pluggable data type (for streaming, hashing, compression, validation, conversion, encryption).
......@@ -219,7 +219,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Integrate spatial functions from http://geosysin.iict.ch/irstv-trac/wiki/H2spatial/Download
</li><li>Cluster: hot deploy (adding a node at runtime).
</li><li>Support DatabaseMetaData.insertsAreDetected: updatable result sets should detect inserts.
</li><li>Oracle: support DECODE method (convert to CASE WHEN).
</li><li>Native search: support "phrase search", wildcard search (* and ?), case-insensitive search, boolean operators, and grouping
</li><li>Improve documentation of access rights.
</li><li>Support opening a database that is in the classpath, maybe using a new file system. Workaround: detect jar file using getClass().getProtectionDomain().getCodeSource().getLocation().
......@@ -256,7 +255,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>MySQL compatibility: real SQL statement for DESCRIBE TEST
</li><li>Use a default delay of 1 second before closing a database.
</li><li>Write (log) to system table before adding to internal data structures.
</li><li>Support direct lookup for MIN and MAX when using WHERE (see todo.txt / Direct Lookup).
</li><li>Support other array types (String[], double[]) in PreparedStatement.setObject(int, Object) (with test case).
</li><li>Oracle compatibility: support NLS_DATE_FORMAT.
</li><li>Support for Thread.interrupt to cancel running statements.
......@@ -322,7 +320,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Doclet: convert tests in javadocs to a java class.
</li><li>Doclet: format fields like methods, but support sorting by name and value.
</li><li>Doclet: shrink the html files.
</li><li>MySQL compatibility: support SET NAMES 'latin1' - See also http://code.google.com/p/h2database/issues/detail?id=56
</li><li>Allow to scan index backwards starting with a value (to better support ORDER BY DESC).
</li><li>Java Service Wrapper: try http://yajsw.sourceforge.net/
</li><li>Batch parameter for INSERT, UPDATE, and DELETE, and commit after each batch. See also MySQL DELETE.
......@@ -334,7 +331,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Sybase/DB2/Oracle compatibility: support out parameters in stored procedures - See http://code.google.com/p/h2database/issues/detail?id=83
</li><li>Combine Server and Console tool (only keep Server).
</li><li>Store the Lucene index in the database itself.
</li><li>Oracle compatibility: support DECODE(x, ...).
</li><li>MVCC: compare concurrent update behavior with PostgreSQL and Oracle.
</li><li>HSQLDB compatibility: CREATE FUNCTION (maybe using a Function interface).
</li><li>HSQLDB compatibility: support CALL "java.lang.Math.sqrt"(2.0)
......@@ -346,7 +342,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Support =ANY(array) as in PostgreSQL. See also http://www.postgresql.org/docs/8.0/interactive/arrays.html
</li><li>IBM DB2 compatibility: support PREVIOUS VALUE FOR sequence.
</li><li>Compatibility: use different LIKE ESCAPE characters depending on the mode (disable for Derby, HSQLDB, DB2, Oracle, MSSQLServer).
</li><li>Oracle compatibility: support CREATE SYNONYM table FOR schema.table.
</li><li>FTP: document the server, including -ftpTask option to execute / kill remote processes
</li><li>FTP: problems with multithreading?
</li><li>FTP: implement SFTP / FTPS
......@@ -410,7 +405,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Issue 178: Optimizer: index usage when both ascending and descending indexes are available.
</li><li>Issue 179: Related subqueries in HAVING clause.
</li><li>IBM DB2 compatibility: NOT NULL WITH DEFAULT. Similar to MySQL Mode.convertInsertNullToZero.
</li><li>Creating primary key: always create a constraint.
</li><li>Maybe use a different page layout: keep the data at the head of the page, and ignore the tail
(don't store / read it). This may increase write / read performance depending on the file system.
</li><li>Indexes of temporary tables are currently kept in-memory. Is this how it should be?
......@@ -501,10 +495,10 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>PostgreSQL compatibility: UPDATE with FROM.
</li><li>Issue 297: Oracle compatibility for "at time zone".
</li><li>IBM DB2 compatibility: IDENTITY_VAL_LOCAL().
</li><li>Support SQL/XML.
</li><li>Support SQL/XML data type.
</li><li>Support concurrent opening of databases.
</li><li>Improved error message and diagnostics in case of network configuration problems.
</li><li>TRUNCATE should reset the identity columns as in MySQL and MS SQL Server (and possibly other databases).
</li><li>TRUNCATE should reset the identity columns by default in MySQL and MS SQL Server compatibility modes (and possibly other).
</li><li>Adding a primary key should make the columns 'not null' unless if there is a row with null
(compatibility with MySQL, PostgreSQL, HSQLDB; not Derby).
</li><li>ARRAY data type: support Integer[] and so on in Java functions (currently only Object[] is supported).
......@@ -526,7 +520,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
</li><li>Support [INNER | OUTER] JOIN USING(column [,...]).
</li><li>Support NATURAL [ { LEFT | RIGHT } [ OUTER ] | INNER ] JOIN (Derby, Oracle)
</li><li>GROUP BY columnNumber (similar to ORDER BY columnNumber) (MySQL, PostgreSQL, SQLite; not by HSQLDB and Derby).
</li><li>Sybase / MS SQL Server compatibility: CONVERT(..) parameters are swapped.
</li><li>Index conditions: WHERE AGE>1 should not scan through all rows with AGE=1.
</li><li>PHP support: H2 should support PDO, or test with PostgreSQL PDO.
</li><li>Outer joins: if no column of the outer join table is referenced, the outer join table could be removed from the query.
......@@ -539,7 +532,6 @@ See also <a href="build.html#providing_patches">Providing Patches</a>.
Keep an pointer to the data area and the column id that is already read.
</li><li>Long running transactions: log session id when detected.
</li><li>Optimization: "select id from test" should use the index on id even without "order by".
</li><li>Issue 362: LIMIT support for UPDATE statements (MySQL compatibility).
</li><li>Sybase SQL Anywhere compatibility: SELECT TOP ... START AT ...
</li><li>Use Java 6 SQLException subclasses.
</li><li>Issue 390: RUNSCRIPT FROM '...' CONTINUE_ON_ERROR
......
......@@ -148,6 +148,8 @@ import org.h2.engine.UserDataType;
import org.h2.expression.Aggregate;
import org.h2.expression.Aggregate.AggregateType;
import org.h2.expression.Alias;
import org.h2.expression.BinaryOperation;
import org.h2.expression.BinaryOperation.OpType;
import org.h2.expression.CompareLike;
import org.h2.expression.Comparison;
import org.h2.expression.ConditionAndOr;
......@@ -163,13 +165,12 @@ import org.h2.expression.Function;
import org.h2.expression.FunctionCall;
import org.h2.expression.JavaAggregate;
import org.h2.expression.JavaFunction;
import org.h2.expression.Operation;
import org.h2.expression.Operation.OpType;
import org.h2.expression.Parameter;
import org.h2.expression.Rownum;
import org.h2.expression.SequenceValue;
import org.h2.expression.Subquery;
import org.h2.expression.TableFunction;
import org.h2.expression.UnaryOperation;
import org.h2.expression.ValueExpression;
import org.h2.expression.Variable;
import org.h2.expression.Wildcard;
......@@ -1797,9 +1798,6 @@ public class Parser {
}
private IndexHints parseIndexHints(Table table) {
if (table == null) {
throw getSyntaxError();
}
read(OPEN_PAREN);
LinkedHashSet<String> indexNames = new LinkedHashSet<>();
if (!readIf(CLOSE_PAREN)) {
......@@ -2858,7 +2856,7 @@ public class Parser {
Expression r = readSum();
while (true) {
if (readIf(STRING_CONCAT)) {
r = new Operation(OpType.CONCAT, r, readSum());
r = new BinaryOperation(OpType.CONCAT, r, readSum());
} else if (readIf(TILDE)) {
if (readIf(ASTERISK)) {
Function function = Function.getFunction(database, "CAST");
......@@ -2888,9 +2886,9 @@ public class Parser {
Expression r = readFactor();
while (true) {
if (readIf(PLUS_SIGN)) {
r = new Operation(OpType.PLUS, r, readFactor());
r = new BinaryOperation(OpType.PLUS, r, readFactor());
} else if (readIf(MINUS_SIGN)) {
r = new Operation(OpType.MINUS, r, readFactor());
r = new BinaryOperation(OpType.MINUS, r, readFactor());
} else {
return r;
}
......@@ -2901,11 +2899,11 @@ public class Parser {
Expression r = readTerm();
while (true) {
if (readIf(ASTERISK)) {
r = new Operation(OpType.MULTIPLY, r, readTerm());
r = new BinaryOperation(OpType.MULTIPLY, r, readTerm());
} else if (readIf(SLASH)) {
r = new Operation(OpType.DIVIDE, r, readTerm());
r = new BinaryOperation(OpType.DIVIDE, r, readTerm());
} else if (readIf(PERCENT)) {
r = new Operation(OpType.MODULUS, r, readTerm());
r = new BinaryOperation(OpType.MODULUS, r, readTerm());
} else {
return r;
}
......@@ -3551,7 +3549,7 @@ public class Parser {
}
read();
} else {
r = new Operation(OpType.NEGATE, readTerm(), null);
r = new UnaryOperation(readTerm());
}
break;
case PLUS_SIGN:
......@@ -3610,7 +3608,7 @@ public class Parser {
Function function = Function.getFunction(database, "ARRAY_GET");
function.setParameter(0, r);
r = readExpression();
r = new Operation(OpType.PLUS, r, ValueExpression.get(ValueInt
r = new BinaryOperation(OpType.PLUS, r, ValueExpression.get(ValueInt
.get(1)));
function.setParameter(1, r);
r = function;
......
......@@ -12,17 +12,13 @@ import java.util.List;
import org.h2.api.ErrorCode;
import org.h2.command.Prepared;
import org.h2.engine.Database;
import org.h2.engine.Session;
import org.h2.engine.Mode.ModeEnum;
import org.h2.engine.Session;
import org.h2.expression.Alias;
import org.h2.expression.Comparison;
import org.h2.expression.ConditionAndOr;
import org.h2.expression.ConditionNot;
import org.h2.expression.Expression;
import org.h2.expression.ExpressionColumn;
import org.h2.expression.ExpressionVisitor;
import org.h2.expression.Function;
import org.h2.expression.Operation;
import org.h2.expression.Parameter;
import org.h2.expression.ValueExpression;
import org.h2.message.DbException;
......@@ -529,6 +525,7 @@ public abstract class Query extends Prepared {
*/
private static boolean checkOrderOther(Session session, Expression expr, ArrayList<String> expressionSQL) {
if (expr.isConstant()) {
// ValueExpression or other
return true;
}
String exprSQL = expr.getSQL();
......@@ -537,38 +534,22 @@ public abstract class Query extends Prepared {
return true;
}
}
int count = expr.getSubexpressionCount();
if (expr instanceof Function) {
Function function = (Function) expr;
if (!function.isDeterministic()) {
if (!((Function) expr).isDeterministic()) {
return false;
}
for (Expression e : function.getArgs()) {
if (!checkOrderOther(session, e, expressionSQL)) {
return false;
}
}
return true;
}
if (expr instanceof Operation) {
Operation operation = (Operation) expr;
Expression right = operation.getRightSubExpression();
return checkOrderOther(session, operation.getLeftSubExpression(), expressionSQL)
&& (right == null || checkOrderOther(session, right, expressionSQL));
}
if (expr instanceof ConditionAndOr) {
ConditionAndOr condition = (ConditionAndOr) expr;
return checkOrderOther(session, condition.getLeftSubExpression(), expressionSQL)
&& checkOrderOther(session, condition.getRightSubExpression(), expressionSQL);
}
if (expr instanceof ConditionNot) {
return checkOrderOther(session, ((ConditionNot) expr).getSubCondition(), expressionSQL);
} else if (count <= 0) {
// Expression is an ExpressionColumn, Parameter, SequenceValue or
// has other unsupported type without subexpressions
return false;
}
if (expr instanceof Comparison) {
Comparison condition = (Comparison) expr;
return checkOrderOther(session, condition.getLeftSubExpression(), expressionSQL)
&& checkOrderOther(session, condition.getRightSubExpression(), expressionSQL);
for (int i = 0; i < count; i++) {
if (!checkOrderOther(session, expr.getSubexpression(i), expressionSQL)) {
return false;
}
}
return false;
return true;
}
/**
......
......@@ -21,7 +21,7 @@ import org.h2.value.ValueString;
/**
* A mathematical expression, or string concatenation.
*/
public class Operation extends Expression {
public class BinaryOperation extends Expression {
public enum OpType {
/**
......@@ -50,11 +50,6 @@ public class Operation extends Expression {
*/
DIVIDE,
/**
* This operation represents a negation as in - ID.
*/
NEGATE,
/**
* This operation represents a modulus as in 5 % 2.
*/
......@@ -66,7 +61,7 @@ public class Operation extends Expression {
private int dataType;
private boolean convertRight = true;
public Operation(OpType opType, Expression left, Expression right) {
public BinaryOperation(OpType opType, Expression left, Expression right) {
this.opType = opType;
this.left = left;
this.right = right;
......@@ -74,23 +69,13 @@ public class Operation extends Expression {
@Override
public String getSQL() {
String sql;
if (opType == OpType.NEGATE) {
// don't remove the space, otherwise it might end up some thing like
// --1 which is a line remark
sql = "- " + left.getSQL();
} else {
// don't remove the space, otherwise it might end up some thing like
// --1 which is a line remark
sql = left.getSQL() + " " + getOperationToken() + " " + right.getSQL();
}
return "(" + sql + ")";
// don't remove the space, otherwise it might end up some thing like
// --1 which is a line remark
return '(' + left.getSQL() + ' ' + getOperationToken() + ' ' + right.getSQL() + ')';
}
private String getOperationToken() {
switch (opType) {
case NEGATE:
return "-";
case CONCAT:
return "||";
case PLUS:
......@@ -112,18 +97,11 @@ public class Operation extends Expression {
public Value getValue(Session session) {
Mode mode = session.getDatabase().getMode();
Value l = left.getValue(session).convertTo(dataType, mode);
Value r;
if (right == null) {
r = null;
} else {
r = right.getValue(session);
if (convertRight) {
r = r.convertTo(dataType, mode);
}
Value r = right.getValue(session);
if (convertRight) {
r = r.convertTo(dataType, mode);
}
switch (opType) {
case NEGATE:
return l == ValueNull.INSTANCE ? l : l.negate();
case CONCAT: {
if (l == ValueNull.INSTANCE) {
if (mode.nullConcatIsNull) {
......@@ -174,36 +152,22 @@ public class Operation extends Expression {
@Override
public void mapColumns(ColumnResolver resolver, int level) {
left.mapColumns(resolver, level);
if (right != null) {
right.mapColumns(resolver, level);
}
right.mapColumns(resolver, level);
}
@Override
public Expression optimize(Session session) {
left = left.optimize(session);
right = right.optimize(session);
switch (opType) {
case NEGATE:
dataType = left.getType();
if (dataType == Value.UNKNOWN) {
dataType = Value.DECIMAL;
} else if (dataType == Value.ENUM) {
dataType = Value.INT;
}
break;
case CONCAT:
right = right.optimize(session);
dataType = Value.STRING;
if (left.isConstant() && right.isConstant()) {
return ValueExpression.get(getValue(session));
}
break;
case PLUS:
case MINUS:
case MULTIPLY:
case DIVIDE:
case MODULUS:
right = right.optimize(session);
int l = left.getType();
int r = right.getType();
if ((l == Value.NULL && r == Value.NULL) ||
......@@ -234,7 +198,7 @@ public class Operation extends Expression {
default:
DbException.throwInternalError("type=" + opType);
}
if (left.isConstant() && (right == null || right.isConstant())) {
if (left.isConstant() && right.isConstant()) {
return ValueExpression.get(getValue(session));
}
return this;
......@@ -334,7 +298,7 @@ public class Operation extends Expression {
// Oracle date add
Function f = Function.getFunction(session.getDatabase(), "DATEADD");
f.setParameter(0, ValueExpression.get(ValueString.get("SECOND")));
left = new Operation(OpType.MULTIPLY, ValueExpression.get(ValueInt
left = new BinaryOperation(OpType.MULTIPLY, ValueExpression.get(ValueInt
.get(60 * 60 * 24)), left);
f.setParameter(1, left);
f.setParameter(2, right);
......@@ -361,7 +325,7 @@ public class Operation extends Expression {
// Oracle date subtract
Function f = Function.getFunction(session.getDatabase(), "DATEADD");
f.setParameter(0, ValueExpression.get(ValueString.get("DAY")));
right = new Operation(OpType.NEGATE, right, null);
right = new UnaryOperation(right);
right = right.optimize(session);
f.setParameter(1, right);
f.setParameter(2, left);
......@@ -374,9 +338,9 @@ public class Operation extends Expression {
// Oracle date subtract
Function f = Function.getFunction(session.getDatabase(), "DATEADD");
f.setParameter(0, ValueExpression.get(ValueString.get("SECOND")));
right = new Operation(OpType.MULTIPLY, ValueExpression.get(ValueInt
right = new BinaryOperation(OpType.MULTIPLY, ValueExpression.get(ValueInt
.get(60 * 60 * 24)), right);
right = new Operation(OpType.NEGATE, right, null);
right = new UnaryOperation(right);
right = right.optimize(session);
f.setParameter(1, right);
f.setParameter(2, left);
......@@ -437,9 +401,7 @@ public class Operation extends Expression {
@Override
public void setEvaluatable(TableFilter tableFilter, boolean b) {
left.setEvaluatable(tableFilter, b);
if (right != null) {
right.setEvaluatable(tableFilter, b);
}
right.setEvaluatable(tableFilter, b);
}
@Override
......@@ -449,74 +411,61 @@ public class Operation extends Expression {
@Override
public long getPrecision() {
if (right != null) {
switch (opType) {
case CONCAT:
return left.getPrecision() + right.getPrecision();
default:
return Math.max(left.getPrecision(), right.getPrecision());
}
switch (opType) {
case CONCAT:
return left.getPrecision() + right.getPrecision();
default:
return Math.max(left.getPrecision(), right.getPrecision());
}
return left.getPrecision();
}
@Override
public int getDisplaySize() {
if (right != null) {
switch (opType) {
case CONCAT:
return MathUtils.convertLongToInt((long) left.getDisplaySize() +
(long) right.getDisplaySize());
default:
return Math.max(left.getDisplaySize(), right.getDisplaySize());
}
switch (opType) {
case CONCAT:
return MathUtils.convertLongToInt((long) left.getDisplaySize() +
(long) right.getDisplaySize());
default:
return Math.max(left.getDisplaySize(), right.getDisplaySize());
}
return left.getDisplaySize();
}
@Override
public int getScale() {
if (right != null) {
return Math.max(left.getScale(), right.getScale());
}
return left.getScale();
return Math.max(left.getScale(), right.getScale());
}
@Override
public void updateAggregate(Session session) {
left.updateAggregate(session);
if (right != null) {
right.updateAggregate(session);
}
right.updateAggregate(session);
}
@Override
public boolean isEverything(ExpressionVisitor visitor) {
return left.isEverything(visitor) &&
(right == null || right.isEverything(visitor));
return left.isEverything(visitor) && right.isEverything(visitor);
}
@Override
public int getCost() {
return left.getCost() + 1 + (right == null ? 0 : right.getCost());
return left.getCost() + right.getCost() + 1;
}
/**
* Get the left sub-expression of this operation.
*
* @return the left sub-expression
*/
public Expression getLeftSubExpression() {
return left;
@Override
public int getSubexpressionCount() {
return 2;
}
/**
* Get the right sub-expression of this operation.
*
* @return the right sub-expression
*/
public Expression getRightSubExpression() {
return right;
@Override
public Expression getSubexpression(int index) {
switch (index) {
case 0:
return left;
case 1:
return right;
default:
throw new IndexOutOfBoundsException();
}
}
}
......@@ -587,22 +587,24 @@ public class Comparison extends Condition {
return null;
}
/**
* Get the left sub-expression of this condition.
*
* @return the left sub-expression
*/
public Expression getLeftSubExpression() {
return left;
@Override
public int getSubexpressionCount() {
return compareType == IS_NULL || compareType == IS_NOT_NULL ? 1 : 2;
}
/**
* Get the right sub-expression of this condition.
*
* @return the right sub-expression
*/
public Expression getRightSubExpression() {
return right;
@Override
public Expression getSubexpression(int index) {
switch (index) {
case 0:
return left;
case 1:
if (compareType != IS_NULL && compareType != IS_NOT_NULL) {
return right;
}
//$FALL-THROUGH$
default:
throw new IndexOutOfBoundsException();
}
}
}
......@@ -283,22 +283,21 @@ public class ConditionAndOr extends Condition {
return left.getCost() + right.getCost();
}
/**
* Get the left sub-expression of this condition.
*
* @return the left sub-expression
*/
public Expression getLeftSubExpression() {
return left;
@Override
public int getSubexpressionCount() {
return 2;
}
/**
* Get the right sub-expression of this condition.
*
* @return the right sub-expression
*/
public Expression getRightSubExpression() {
return right;
@Override
public Expression getSubexpression(int index) {
switch (index) {
case 0:
return left;
case 1:
return right;
default:
throw new IndexOutOfBoundsException();
}
}
}
......@@ -98,13 +98,17 @@ public class ConditionNot extends Condition {
return condition.getCost();
}
/**
* Get the sub-expression of this condition.
*
* @return the sub-expression
*/
public Expression getSubCondition() {
return condition;
@Override
public int getSubexpressionCount() {
return 1;
}
@Override
public Expression getSubexpression(int index) {
if (index == 0) {
return condition;
}
throw new IndexOutOfBoundsException();
}
}
......@@ -357,4 +357,24 @@ public abstract class Expression {
}
}
/**
* Returns count of subexpressions.
*
* @return count of subexpressions
*/
public int getSubexpressionCount() {
return 0;
}
/**
* Returns subexpression with specified index.
*
* @param index 0-based index
* @return subexpression with specified index
* @throws IndexOutOfBoundsException if specified index is not valid
*/
public Expression getSubexpression(int index) {
throw new IndexOutOfBoundsException();
}
}
......@@ -2710,4 +2710,14 @@ public class Function extends Expression implements FunctionCall {
return info.type == NEXTVAL;
}
@Override
public int getSubexpressionCount() {
return args.length;
}
@Override
public Expression getSubexpression(int index) {
return args[index];
}
}
/*
* Copyright 2004-2018 H2 Group. Multiple-Licensed under the MPL 2.0,
* and the EPL 1.0 (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.expression;
import org.h2.engine.Session;
import org.h2.table.ColumnResolver;
import org.h2.table.TableFilter;
import org.h2.value.Value;
import org.h2.value.ValueNull;
/**
* Unary operation. Only negation operation is currently supported.
*/
public class UnaryOperation extends Expression {
private Expression arg;
private int dataType;
public UnaryOperation(Expression arg) {
this.arg = arg;
}
@Override
public String getSQL() {
// don't remove the space, otherwise it might end up some thing like
// --1 which is a line remark
return "(- " + arg.getSQL() + ')';
}
@Override
public Value getValue(Session session) {
Value a = arg.getValue(session).convertTo(dataType, session.getDatabase().getMode());
return a == ValueNull.INSTANCE ? a : a.negate();
}
@Override
public void mapColumns(ColumnResolver resolver, int level) {
arg.mapColumns(resolver, level);
}
@Override
public Expression optimize(Session session) {
arg = arg.optimize(session);
dataType = arg.getType();
if (dataType == Value.UNKNOWN) {
dataType = Value.DECIMAL;
} else if (dataType == Value.ENUM) {
dataType = Value.INT;
}
if (arg.isConstant()) {
return ValueExpression.get(getValue(session));
}
return this;
}
@Override
public void setEvaluatable(TableFilter tableFilter, boolean b) {
arg.setEvaluatable(tableFilter, b);
}
@Override
public int getType() {
return dataType;
}
@Override
public long getPrecision() {
return arg.getPrecision();
}
@Override
public int getDisplaySize() {
return arg.getDisplaySize();
}
@Override
public int getScale() {
return arg.getScale();
}
@Override
public void updateAggregate(Session session) {
arg.updateAggregate(session);
}
@Override
public boolean isEverything(ExpressionVisitor visitor) {
return arg.isEverything(visitor);
}
@Override
public int getCost() {
return arg.getCost() + 1;
}
@Override
public int getSubexpressionCount() {
return 1;
}
@Override
public Expression getSubexpression(int index) {
if (index == 0) {
return arg;
}
throw new IndexOutOfBoundsException();
}
}
......@@ -669,19 +669,17 @@ public class FullText {
ArrayList<String> data, Expression expr) {
if (expr instanceof ConditionAndOr) {
ConditionAndOr and = (ConditionAndOr) expr;
Expression left = and.getLeftSubExpression();
Expression right = and.getRightSubExpression();
addColumnData(columns, data, left);
addColumnData(columns, data, right);
addColumnData(columns, data, and.getSubexpression(0));
addColumnData(columns, data, and.getSubexpression(1));
} else {
Comparison comp = (Comparison) expr;
ExpressionColumn ec = (ExpressionColumn) comp.getLeftSubExpression();
ValueExpression ev = (ValueExpression) comp.getRightSubExpression();
ExpressionColumn ec = (ExpressionColumn) comp.getSubexpression(0);
String columnName = ec.getColumnName();
columns.add(columnName);
if (ev == null) {
if (expr.getSubexpressionCount() == 1) {
data.add(null);
} else {
ValueExpression ev = (ValueExpression) comp.getSubexpression(1);
data.add(ev.getValue(null).getString());
}
}
......
......@@ -66,6 +66,9 @@ SELECT DISTINCT NAME, ID + 1 FROM TEST ORDER BY UPPER(NAME) || (ID + 1);
SELECT DISTINCT ID FROM TEST ORDER BY NAME;
> exception ORDER_BY_NOT_IN_RESULT
SELECT DISTINCT ID FROM TEST ORDER BY UPPER(NAME);
> exception ORDER_BY_NOT_IN_RESULT
SELECT DISTINCT ID FROM TEST ORDER BY CURRENT_TIMESTAMP;
> exception ORDER_BY_NOT_IN_RESULT
......
......@@ -789,4 +789,4 @@ inconsistencies discover eliminated violates tweaks postpone leftovers
tied ties
launched unavailable smallmoney erroneously multiplier newid pan streamline unmap preview unexpectedly presumably
converging smth rng curs casts unmapping unmapper
immediate hhmmss scheduled hhmm prematurely postponed arranges
immediate hhmmss scheduled hhmm prematurely postponed arranges subexpression subexpressions
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论