com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of druid Show documentation
Show all versions of druid Show documentation
An JDBC datasource implementation.
/*
* Copyright 1999-2017 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.sql.ast.expr;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.*;
import com.alibaba.druid.sql.visitor.ParameterizedVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import com.alibaba.druid.sql.visitor.VisitorFeature;
import com.alibaba.druid.util.FnvHash;
import com.alibaba.druid.util.Utils;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class SQLBinaryOpExpr extends SQLExprImpl implements SQLReplaceable, Serializable, SQLDbTypedObject, Comparable {
private static final long serialVersionUID = 1L;
protected SQLExpr left;
protected SQLExpr right;
protected SQLBinaryOperator operator;
protected DbType dbType;
private boolean parenthesized;
// only for parameterized output
protected transient List mergedList;
public SQLBinaryOpExpr() {
}
public SQLBinaryOpExpr(DbType dbType) {
this.dbType = dbType;
}
public SQLBinaryOpExpr(SQLExpr left, SQLBinaryOperator operator, SQLExpr right) {
if (left != null) {
left.setParent(this);
}
if (right != null) {
right.setParent(this);
}
this.left = left;
this.right = right;
this.operator = operator;
if (dbType == null) {
if (left instanceof SQLBinaryOpExpr) {
dbType = ((SQLBinaryOpExpr) left).dbType;
}
}
if (dbType == null) {
if (right instanceof SQLBinaryOpExpr) {
dbType = ((SQLBinaryOpExpr) right).dbType;
}
}
}
public SQLBinaryOpExpr(SQLExpr left, SQLBinaryOperator operator, SQLExpr right, DbType dbType) {
if (left != null) {
left.setParent(this);
}
if (right != null) {
right.setParent(this);
}
this.left = left;
this.right = right;
this.operator = operator;
if (dbType == null) {
if (left instanceof SQLBinaryOpExpr) {
dbType = ((SQLBinaryOpExpr) left).dbType;
}
}
if (dbType == null) {
if (right instanceof SQLBinaryOpExpr) {
dbType = ((SQLBinaryOpExpr) right).dbType;
}
}
this.dbType = dbType;
}
public SQLBinaryOpExpr(SQLExpr left, SQLExpr right, SQLBinaryOperator operator) {
if (left != null) {
left.setParent(this);
}
if (right != null) {
right.setParent(this);
}
this.left = left;
this.right = right;
this.operator = operator;
}
public DbType getDbType() {
return dbType;
}
public void setDbType(DbType dbType) {
this.dbType = dbType;
}
public SQLExpr getLeft() {
return this.left;
}
public void setLeft(SQLExpr left) {
if (left != null) {
left.setParent(this);
}
this.left = left;
}
public SQLExpr getRight() {
return this.right;
}
public void setRight(SQLExpr right) {
if (right != null) {
right.setParent(this);
}
this.right = right;
}
public SQLBinaryOperator getOperator() {
return this.operator;
}
public void setOperator(SQLBinaryOperator operator) {
this.operator = operator;
}
public boolean isParenthesized() {
return parenthesized;
}
public void setParenthesized(boolean parenthesized) {
this.parenthesized = parenthesized;
}
protected void accept0(SQLASTVisitor visitor) {
if (visitor.visit(this)) {
if (left != null) {
left.accept(visitor);
}
if (right != null) {
right.accept(visitor);
}
}
visitor.endVisit(this);
}
@Override
public List getChildren() {
return Arrays.asList(this.left, this.right);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((left == null) ? 0 : left.hashCode());
result = prime * result + ((operator == null) ? 0 : operator.hashCode());
result = prime * result + ((right == null) ? 0 : right.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof SQLBinaryOpExpr)) {
return false;
}
SQLBinaryOpExpr other = (SQLBinaryOpExpr) obj;
return operator == other.operator
&& SQLExprUtils.equals(left, other.left)
&& SQLExprUtils.equals(right, other.right);
}
public boolean equals(SQLBinaryOpExpr other) {
return operator == other.operator
&& SQLExprUtils.equals(left, other.left)
&& SQLExprUtils.equals(right, other.right);
}
public boolean equalsIgoreOrder(SQLBinaryOpExpr other) {
if (this == other) {
return true;
}
if (other == null) {
return false;
}
if (operator != other.operator) {
return false;
}
return (Utils.equals(this.left, other.left)
&& Utils.equals(this.right, other.right))
|| (Utils.equals(this.left, other.right)
&& Utils.equals(this.right, other.left));
}
public SQLBinaryOpExpr clone() {
SQLBinaryOpExpr x = new SQLBinaryOpExpr();
if (left != null) {
x.setLeft(left.clone());
}
if (right != null) {
x.setRight(right.clone());
}
x.operator = operator;
x.dbType = dbType;
x.parenthesized = parenthesized;
if (hint != null) {
x.hint = hint.clone();
}
return x;
}
public String toString() {
return SQLUtils.toSQLString(this, getDbType());
}
public static SQLExpr combine(List extends SQLExpr> items, SQLBinaryOperator op) {
if (items == null || op == null) {
return null;
}
int size = items.size();
if (size == 0) {
return null;
}
if (size == 1) {
return items.get(0);
}
SQLBinaryOpExpr expr = new SQLBinaryOpExpr(items.get(0), op, items.get(1));
for (int i = 2; i < size; ++i) {
SQLExpr item = items.get(i);
expr = new SQLBinaryOpExpr(expr, op, item);
}
return expr;
}
public static List split(SQLBinaryOpExpr x) {
return split(x, x.getOperator());
}
public static List split(SQLExpr x, SQLBinaryOperator op) {
if (x instanceof SQLBinaryOpExprGroup) {
SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) x;
if (group.getOperator() == op) {
return new ArrayList(group.getItems());
}
} else if (x instanceof SQLBinaryOpExpr) {
return split((SQLBinaryOpExpr) x, op);
}
List list = new ArrayList(1);
list.add(x);
return list;
}
public static List split(SQLBinaryOpExpr x, SQLBinaryOperator op) {
if (x.getOperator() != op) {
List groupList = new ArrayList(1);
groupList.add(x);
return groupList;
}
List groupList = new ArrayList();
split(groupList, x, op);
return groupList;
}
public static void split(List outList, SQLExpr expr, SQLBinaryOperator op) {
if (expr == null) {
return;
}
if (!(expr instanceof SQLBinaryOpExpr)) {
outList.add(expr);
return;
}
SQLBinaryOpExpr binaryExpr = (SQLBinaryOpExpr) expr;
if (binaryExpr.getOperator() != op) {
outList.add(binaryExpr);
return;
}
List rightList = new ArrayList();
rightList.add(binaryExpr.getRight());
for (SQLExpr left = binaryExpr.getLeft(); ; ) {
if (left instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr leftBinary = (SQLBinaryOpExpr) left;
if (leftBinary.operator == op) {
left = ((SQLBinaryOpExpr) leftBinary).getLeft();
rightList.add(leftBinary.getRight());
} else {
outList.add(leftBinary);
break;
}
} else {
outList.add(left);
break;
}
}
for (int i = rightList.size() - 1; i >= 0; --i) {
SQLExpr right = rightList.get(i);
if (right instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr binaryRight = (SQLBinaryOpExpr) right;
if (binaryRight.operator == op) {
{
SQLExpr rightLeft = binaryRight.getLeft();
if (rightLeft instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr rightLeftBinary = (SQLBinaryOpExpr) rightLeft;
if (rightLeftBinary.operator == op) {
split(outList, rightLeftBinary, op);
} else {
outList.add(rightLeftBinary);
}
} else {
outList.add(rightLeft);
}
}
{
SQLExpr rightRight = binaryRight.getRight();
if (rightRight instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr rightRightBinary = (SQLBinaryOpExpr) rightRight;
if (rightRightBinary.operator == op) {
split(outList, rightRightBinary, op);
} else {
outList.add(rightRightBinary);
}
} else {
outList.add(rightRight);
}
}
} else {
outList.add(binaryRight);
}
} else {
outList.add(right);
}
}
}
public static SQLExpr and(SQLExpr a, SQLExpr b) {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
if (a instanceof SQLBinaryOpExprGroup) {
SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) a;
if (group.getOperator() == SQLBinaryOperator.BooleanAnd) {
group.add(b);
return group;
} else if (group.getOperator() == SQLBinaryOperator.BooleanOr && group.getItems().size() == 1) {
a = group.getItems().get(0).clone();
}
}
if (b instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr bb = (SQLBinaryOpExpr) b;
if (bb.operator == SQLBinaryOperator.BooleanAnd) {
return and(and(a, bb.left), bb.right);
}
} else if (b instanceof SQLBinaryOpExprGroup) {
SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) b;
if (group.getOperator() == SQLBinaryOperator.BooleanOr && group.getItems().size() == 1) {
b = group.getItems().get(0).clone();
}
}
if (a instanceof SQLBinaryOpExpr
&& b instanceof SQLBinaryOpExprGroup
&& ((SQLBinaryOpExprGroup) b).getOperator() == SQLBinaryOperator.BooleanAnd) {
SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) b;
group.add(0, a);
return group;
}
return new SQLBinaryOpExpr(a, SQLBinaryOperator.BooleanAnd, b);
}
public static SQLExpr and(SQLExpr a, SQLExpr b, SQLExpr c) {
return and(and(a, b), c);
}
public static SQLExpr or(SQLExpr a, SQLExpr b) {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
if (a instanceof SQLBinaryOpExprGroup) {
SQLBinaryOpExprGroup group = (SQLBinaryOpExprGroup) a;
if (group.getOperator() == SQLBinaryOperator.BooleanOr) {
group.add(b);
return group;
}
}
if (b instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr bb = (SQLBinaryOpExpr) b;
if (bb.operator == SQLBinaryOperator.BooleanOr) {
return or(or(a, bb.left), bb.right);
}
}
return new SQLBinaryOpExpr(a, SQLBinaryOperator.BooleanOr, b);
}
public static SQLExpr or(List extends SQLExpr> list) {
if (list.isEmpty()) {
return null;
}
SQLExpr first = list.get(0);
for (int i = 1; i < list.size(); i++) {
first = or(first, list.get(i));
}
return first;
}
public static SQLExpr andIfNotExists(SQLExpr a, SQLExpr b) {
if (a == null) {
return b;
}
if (b == null) {
return a;
}
List groupListA = new ArrayList();
List groupListB = new ArrayList();
split(groupListA, a, SQLBinaryOperator.BooleanAnd);
split(groupListB, b, SQLBinaryOperator.BooleanAnd);
for (SQLExpr itemB : groupListB) {
boolean exist = false;
for (SQLExpr itemA : groupListA) {
if (itemA.equals(itemB)) {
exist = true;
} else if (itemA instanceof SQLBinaryOpExpr
&& itemB instanceof SQLBinaryOpExpr) {
if (((SQLBinaryOpExpr) itemA).equalsIgoreOrder((SQLBinaryOpExpr) itemB)) {
exist = true;
}
}
}
if (!exist) {
groupListA.add(itemB);
}
}
return combine(groupListA, SQLBinaryOperator.BooleanAnd);
}
public static SQLBinaryOpExpr isNotNull(SQLExpr expr) {
return new SQLBinaryOpExpr(expr, SQLBinaryOperator.IsNot, new SQLNullExpr());
}
public static SQLBinaryOpExpr isNull(SQLExpr expr) {
return new SQLBinaryOpExpr(expr, SQLBinaryOperator.Is, new SQLNullExpr());
}
public boolean replace(SQLExpr expr, SQLExpr target) {
SQLObject parent = getParent();
if (left == expr) {
if (target == null) {
if (parent instanceof SQLReplaceable) {
return ((SQLReplaceable) parent).replace(this, right);
} else {
return false;
}
}
this.setLeft(target);
return true;
}
if (right == expr) {
if (target == null) {
if (parent instanceof SQLReplaceable) {
return ((SQLReplaceable) parent).replace(this, left);
} else {
return false;
}
}
this.setRight(target);
return true;
}
if (left instanceof SQLBinaryOpExpr) {
final SQLBinaryOperator operator = ((SQLBinaryOpExpr) left).getOperator();
if (operator == SQLBinaryOperator.BooleanAnd) {
if (((SQLBinaryOpExpr) left).replace(expr, target)) {
return true;
}
}
}
return false;
}
public SQLExpr other(SQLExpr x) {
if (x == left) {
return right;
}
if (x == right) {
return left;
}
return null;
}
public boolean contains(SQLExpr item) {
if (item instanceof SQLBinaryOpExpr) {
if (this.equalsIgoreOrder((SQLBinaryOpExpr) item)) {
return true;
}
return left.equals(item) || right.equals(item);
}
return false;
}
public SQLDataType computeDataType() {
if (operator == null) {
return null;
}
if (operator.isRelational()) {
return SQLBooleanExpr.DATA_TYPE;
}
SQLDataType leftDataType = null, rightDataType = null;
if (left != null) {
leftDataType = left.computeDataType();
}
if (right != null) {
rightDataType = right.computeDataType();
}
switch (operator) {
case Concat:
if (leftDataType != null) {
return leftDataType;
}
if (rightDataType != null) {
return rightDataType;
}
return SQLCharExpr.DATA_TYPE;
case BooleanXor:
case Modulus:
case Mod:
case DIV:
case Divide:
if (leftDataType != null) {
return leftDataType;
}
if (rightDataType != null) {
return rightDataType;
}
return null;
case Subtract:
case Add:
case Multiply:
if (leftDataType != null) {
if (rightDataType != null) {
if (leftDataType.nameHashCode64() == FnvHash.Constants.BIGINT
&& rightDataType.nameHashCode64() == FnvHash.Constants.NUMBER) {
return rightDataType;
}
if (leftDataType.isInt()
&& rightDataType.nameHashCode64() == FnvHash.Constants.INTERVAL) {
return rightDataType;
}
if ((leftDataType.nameHashCode64() == FnvHash.Constants.DATE
|| leftDataType.nameHashCode64() == FnvHash.Constants.DATETIME
|| leftDataType.nameHashCode64() == FnvHash.Constants.TIMESTAMP)
&& (
rightDataType.nameHashCode64() == FnvHash.Constants.DATE
|| rightDataType.nameHashCode64() == FnvHash.Constants.DATETIME
|| rightDataType.nameHashCode64() == FnvHash.Constants.TIMESTAMP
)) {
return new SQLDataTypeImpl("BIGING");
}
}
return leftDataType;
}
return null;
default:
return null;
}
}
public boolean conditionContainsTable(String alias) {
if (left == null || right == null) {
return false;
}
if (left instanceof SQLPropertyExpr) {
if (((SQLPropertyExpr) left).matchOwner(alias)) {
return true;
}
} else if (left instanceof SQLBinaryOpExpr) {
if (((SQLBinaryOpExpr) left).conditionContainsTable(alias)) {
return true;
}
}
if (right instanceof SQLPropertyExpr) {
if (((SQLPropertyExpr) right).matchOwner(alias)) {
return true;
}
} else if (right instanceof SQLBinaryOpExpr) {
return ((SQLBinaryOpExpr) right).conditionContainsTable(alias);
}
return false;
}
public boolean conditionContainsColumn(String column) {
if (left == null || right == null) {
return false;
}
if (left instanceof SQLIdentifierExpr) {
if (((SQLIdentifierExpr) left).nameEquals(column)) {
return true;
}
} else if (right instanceof SQLIdentifierExpr) {
if (((SQLIdentifierExpr) right).nameEquals(column)) {
return true;
}
}
return false;
}
/**
* only for parameterized output
*
* @param v
* @param x
* @return
*/
public static SQLBinaryOpExpr merge(ParameterizedVisitor v, SQLBinaryOpExpr x) {
SQLObject parent = x.parent;
for (; ; ) {
if (x.right instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr rightBinary = (SQLBinaryOpExpr) x.right;
if (x.left instanceof SQLBinaryOpExpr) {
SQLBinaryOpExpr leftBinaryExpr = (SQLBinaryOpExpr) x.left;
if (SQLExprUtils.equals(leftBinaryExpr.right, rightBinary)) {
x = leftBinaryExpr;
v.incrementReplaceCunt();
continue;
}
}
SQLExpr mergedRight = merge(v, rightBinary);
if (mergedRight != x.right) {
x = new SQLBinaryOpExpr(x.left, x.operator, mergedRight);
v.incrementReplaceCunt();
}
x.setParent(parent);
}
break;
}
if (x.left instanceof SQLBinaryOpExpr) {
SQLExpr mergedLeft = merge(v, (SQLBinaryOpExpr) x.left);
if (mergedLeft != x.left) {
SQLBinaryOpExpr tmp = new SQLBinaryOpExpr(mergedLeft, x.operator, x.right);
tmp.setParent(parent);
x = tmp;
v.incrementReplaceCunt();
}
}
// ID = ? OR ID = ? => ID = ?
if (x.operator == SQLBinaryOperator.BooleanOr && !v.isEnabled(VisitorFeature.OutputParameterizedQuesUnMergeInList)) {
if ((x.left instanceof SQLBinaryOpExpr) && (x.right instanceof SQLBinaryOpExpr)) {
SQLBinaryOpExpr leftBinary = (SQLBinaryOpExpr) x.left;
SQLBinaryOpExpr rightBinary = (SQLBinaryOpExpr) x.right;
if (mergeEqual(leftBinary, rightBinary)) {
v.incrementReplaceCunt();
leftBinary.setParent(x.parent);
leftBinary.addMergedItem(rightBinary);
return leftBinary;
}
if (SQLExprUtils.isLiteralExpr(leftBinary.left) //
&& leftBinary.operator == SQLBinaryOperator.BooleanOr) {
if (mergeEqual(leftBinary.right, x.right)) {
v.incrementReplaceCunt();
leftBinary.addMergedItem(rightBinary);
return leftBinary;
}
}
}
}
return x;
}
/**
* only for parameterized output
*
* @param item
* @return
*/
private void addMergedItem(SQLBinaryOpExpr item) {
if (mergedList == null) {
mergedList = new ArrayList();
}
mergedList.add(item);
}
/**
* only for parameterized output
*
* @return
*/
public List getMergedList() {
return mergedList;
}
/**
* only for parameterized output
*
* @param a
* @param b
* @return
*/
private static boolean mergeEqual(SQLExpr a, SQLExpr b) {
if (!(a instanceof SQLBinaryOpExpr)) {
return false;
}
if (!(b instanceof SQLBinaryOpExpr)) {
return false;
}
SQLBinaryOpExpr binaryA = (SQLBinaryOpExpr) a;
SQLBinaryOpExpr binaryB = (SQLBinaryOpExpr) b;
if (binaryA.operator != SQLBinaryOperator.Equality) {
return false;
}
if (binaryB.operator != SQLBinaryOperator.Equality) {
return false;
}
if (!(binaryA.right instanceof SQLLiteralExpr || binaryA.right instanceof SQLVariantRefExpr)) {
return false;
}
if (!(binaryB.right instanceof SQLLiteralExpr || binaryB.right instanceof SQLVariantRefExpr)) {
return false;
}
return binaryA.left.equals(binaryB.left);
}
public static boolean isOr(SQLExpr x) {
return x instanceof SQLBinaryOpExpr
&& ((SQLBinaryOpExpr) x).getOperator() == SQLBinaryOperator.BooleanOr;
}
public static boolean isAnd(SQLExpr x) {
return x instanceof SQLBinaryOpExpr
&& ((SQLBinaryOpExpr) x).getOperator() == SQLBinaryOperator.BooleanAnd;
}
public boolean isLeftNameAndRightLiteral() {
return left instanceof SQLName
&& right instanceof SQLLiteralExpr;
}
public boolean isLeftFunctionAndRightLiteral() {
return left instanceof SQLMethodInvokeExpr
&& right instanceof SQLLiteralExpr;
}
public boolean isNameAndLiteral() {
return (left instanceof SQLLiteralExpr
&& right instanceof SQLName)
|| (left instanceof SQLName
&& right instanceof SQLLiteralExpr);
}
public boolean isBothName() {
return left instanceof SQLName
&& right instanceof SQLName;
}
@Override
public int compareTo(SQLBinaryOpExpr o) {
int leftResult = SQLExprComparor.compareTo(left, o.left);
if (leftResult != 0) {
return leftResult;
}
int opResult = this.operator.compareTo(o.operator);
if (opResult != 0) {
return opResult;
}
int rightResult = SQLExprComparor.compareTo(right, o.right);
if (rightResult != 0) {
return rightResult;
}
return 0;
}
public boolean isLeftLiteralAndRightName() {
return right instanceof SQLName
&& left instanceof SQLLiteralExpr;
}
public static SQLBinaryOpExpr conditionEq(String column, String value) {
return new SQLBinaryOpExpr(
SQLUtils.toSQLExpr(column),
SQLBinaryOperator.Equality, new SQLCharExpr(value)
);
}
public static SQLBinaryOpExpr conditionEq(String column, int value) {
return new SQLBinaryOpExpr(
SQLUtils.toSQLExpr(column),
SQLBinaryOperator.Equality,
new SQLIntegerExpr(value)
);
}
public static SQLBinaryOpExpr conditionLike(String column, String value) {
return new SQLBinaryOpExpr(
SQLUtils.toSQLExpr(column),
SQLBinaryOperator.Like,
new SQLCharExpr(value)
);
}
public static SQLBinaryOpExpr conditionLike(String column, SQLExpr value) {
return new SQLBinaryOpExpr(
SQLUtils.toSQLExpr(column),
SQLBinaryOperator.Like,
value
);
}
public static SQLBinaryOpExpr eq(SQLExpr a, SQLExpr b) {
return new SQLBinaryOpExpr(a, SQLBinaryOperator.Equality, b);
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy