net.sf.jsqlparser.util.deparser.ExpressionDeParser Maven / Gradle / Ivy
The newest version!
/*
* #%L
* JSQLParser library
* %%
* Copyright (C) 2004 - 2013 JSQLParser
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package net.sf.jsqlparser.util.deparser;
import java.util.Iterator;
import java.util.List;
import net.sf.jsqlparser.expression.AllComparisonExpression;
import net.sf.jsqlparser.expression.AnalyticExpression;
import net.sf.jsqlparser.expression.AnyComparisonExpression;
import net.sf.jsqlparser.expression.BinaryExpression;
import net.sf.jsqlparser.expression.CaseExpression;
import net.sf.jsqlparser.expression.CastExpression;
import net.sf.jsqlparser.expression.DateTimeLiteralExpression;
import net.sf.jsqlparser.expression.DateValue;
import net.sf.jsqlparser.expression.DoubleValue;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.ExpressionVisitor;
import net.sf.jsqlparser.expression.ExtractExpression;
import net.sf.jsqlparser.expression.Function;
import net.sf.jsqlparser.expression.HexValue;
import net.sf.jsqlparser.expression.IntervalExpression;
import net.sf.jsqlparser.expression.JdbcNamedParameter;
import net.sf.jsqlparser.expression.JdbcParameter;
import net.sf.jsqlparser.expression.JsonExpression;
import net.sf.jsqlparser.expression.KeepExpression;
import net.sf.jsqlparser.expression.LongValue;
import net.sf.jsqlparser.expression.MySQLGroupConcat;
import net.sf.jsqlparser.expression.NotExpression;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.NumericBind;
import net.sf.jsqlparser.expression.OracleHierarchicalExpression;
import net.sf.jsqlparser.expression.OracleHint;
import net.sf.jsqlparser.expression.Parenthesis;
import net.sf.jsqlparser.expression.RowConstructor;
import net.sf.jsqlparser.expression.SignedExpression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.TimeKeyExpression;
import net.sf.jsqlparser.expression.TimeValue;
import net.sf.jsqlparser.expression.TimestampValue;
import net.sf.jsqlparser.expression.UserVariable;
import net.sf.jsqlparser.expression.ValueListExpression;
import net.sf.jsqlparser.expression.WhenClause;
import net.sf.jsqlparser.expression.WindowElement;
import net.sf.jsqlparser.expression.operators.arithmetic.Addition;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseAnd;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseLeftShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseOr;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseRightShift;
import net.sf.jsqlparser.expression.operators.arithmetic.BitwiseXor;
import net.sf.jsqlparser.expression.operators.arithmetic.Concat;
import net.sf.jsqlparser.expression.operators.arithmetic.Division;
import net.sf.jsqlparser.expression.operators.arithmetic.Modulo;
import net.sf.jsqlparser.expression.operators.arithmetic.Multiplication;
import net.sf.jsqlparser.expression.operators.arithmetic.Subtraction;
import net.sf.jsqlparser.expression.operators.conditional.AndExpression;
import net.sf.jsqlparser.expression.operators.conditional.OrExpression;
import net.sf.jsqlparser.expression.operators.relational.Between;
import net.sf.jsqlparser.expression.operators.relational.EqualsTo;
import net.sf.jsqlparser.expression.operators.relational.ExistsExpression;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.NamedExpressionList;
import net.sf.jsqlparser.expression.operators.relational.GreaterThan;
import net.sf.jsqlparser.expression.operators.relational.GreaterThanEquals;
import net.sf.jsqlparser.expression.operators.relational.InExpression;
import net.sf.jsqlparser.expression.operators.relational.IsNullExpression;
import net.sf.jsqlparser.expression.operators.relational.ItemsListVisitor;
import net.sf.jsqlparser.expression.operators.relational.JsonOperator;
import net.sf.jsqlparser.expression.operators.relational.LikeExpression;
import net.sf.jsqlparser.expression.operators.relational.Matches;
import net.sf.jsqlparser.expression.operators.relational.MinorThan;
import net.sf.jsqlparser.expression.operators.relational.MinorThanEquals;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.expression.operators.relational.NotEqualsTo;
import net.sf.jsqlparser.expression.operators.relational.OldOracleJoinBinaryExpression;
import net.sf.jsqlparser.expression.operators.relational.RegExpMatchOperator;
import net.sf.jsqlparser.expression.operators.relational.RegExpMySQLOperator;
import net.sf.jsqlparser.expression.operators.relational.SupportsOldOracleJoinSyntax;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.OrderByElement;
import net.sf.jsqlparser.statement.select.SelectVisitor;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.select.WithItem;
/**
* A class to de-parse (that is, tranform from JSqlParser hierarchy into a string) an
* {@link net.sf.jsqlparser.expression.Expression}
*/
public class ExpressionDeParser implements ExpressionVisitor, ItemsListVisitor {
private static final String NOT = "NOT ";
protected StringBuilder buffer = new StringBuilder();
private SelectVisitor selectVisitor;
private boolean useBracketsInExprList = true;
private OrderByDeParser orderByDeParser = new OrderByDeParser();
public ExpressionDeParser() {
}
/**
* @param selectVisitor a SelectVisitor to de-parse SubSelects. It has to share the same
* StringBuilder as this object in order to work, as:
*
*
*
* StringBuilder myBuf = new StringBuilder();
* MySelectDeparser selectDeparser = new MySelectDeparser();
* selectDeparser.setBuffer(myBuf);
* ExpressionDeParser expressionDeParser = new ExpressionDeParser(selectDeparser, myBuf);
*
*
*
* @param buffer the buffer that will be filled with the expression
*/
public ExpressionDeParser(SelectVisitor selectVisitor, StringBuilder buffer) {
this(selectVisitor, buffer, new OrderByDeParser());
}
ExpressionDeParser(SelectVisitor selectVisitor, StringBuilder buffer, OrderByDeParser orderByDeParser) {
this.selectVisitor = selectVisitor;
this.buffer = buffer;
this.orderByDeParser = orderByDeParser;
}
public StringBuilder getBuffer() {
return buffer;
}
public void setBuffer(StringBuilder buffer) {
this.buffer = buffer;
}
@Override
public void visit(Addition addition) {
visitBinaryExpression(addition, " + ");
}
@Override
public void visit(AndExpression andExpression) {
visitBinaryExpression(andExpression, " AND ");
}
@Override
public void visit(Between between) {
between.getLeftExpression().accept(this);
if (between.isNot()) {
buffer.append(" NOT");
}
buffer.append(" BETWEEN ");
between.getBetweenExpressionStart().accept(this);
buffer.append(" AND ");
between.getBetweenExpressionEnd().accept(this);
}
@Override
public void visit(EqualsTo equalsTo) {
visitOldOracleJoinBinaryExpression(equalsTo, " = ");
}
@Override
public void visit(Division division) {
visitBinaryExpression(division, " / ");
}
@Override
public void visit(DoubleValue doubleValue) {
buffer.append(doubleValue.toString());
}
@Override
public void visit(HexValue hexValue) {
buffer.append(hexValue.toString());
}
@Override
public void visit(NotExpression notExpr) {
buffer.append(NOT);
notExpr.getExpression().accept(this);
}
@Override
public void visit(BitwiseRightShift expr) {
visitBinaryExpression(expr, " >> ");
}
@Override
public void visit(BitwiseLeftShift expr) {
visitBinaryExpression(expr, " << ");
}
public void visitOldOracleJoinBinaryExpression(OldOracleJoinBinaryExpression expression, String operator) {
if (expression.isNot()) {
buffer.append(NOT);
}
expression.getLeftExpression().accept(this);
if (expression.getOldOracleJoinSyntax() == EqualsTo.ORACLE_JOIN_RIGHT) {
buffer.append("(+)");
}
buffer.append(operator);
expression.getRightExpression().accept(this);
if (expression.getOldOracleJoinSyntax() == EqualsTo.ORACLE_JOIN_LEFT) {
buffer.append("(+)");
}
}
@Override
public void visit(GreaterThan greaterThan) {
visitOldOracleJoinBinaryExpression(greaterThan, " > ");
}
@Override
public void visit(GreaterThanEquals greaterThanEquals) {
visitOldOracleJoinBinaryExpression(greaterThanEquals, " >= ");
}
@Override
public void visit(InExpression inExpression) {
if (inExpression.getLeftExpression() == null) {
inExpression.getLeftItemsList().accept(this);
} else {
inExpression.getLeftExpression().accept(this);
if (inExpression.getOldOracleJoinSyntax() == SupportsOldOracleJoinSyntax.ORACLE_JOIN_RIGHT) {
buffer.append("(+)");
}
}
if (inExpression.isNot()) {
buffer.append(" NOT");
}
buffer.append(" IN ");
inExpression.getRightItemsList().accept(this);
}
@Override
public void visit(SignedExpression signedExpression) {
buffer.append(signedExpression.getSign());
signedExpression.getExpression().accept(this);
}
@Override
public void visit(IsNullExpression isNullExpression) {
isNullExpression.getLeftExpression().accept(this);
if (isNullExpression.isUseIsNull()) {
if (isNullExpression.isNot()) {
buffer.append(" NOT ISNULL");
} else {
buffer.append(" ISNULL");
}
} else {
if (isNullExpression.isNot()) {
buffer.append(" IS NOT NULL");
} else {
buffer.append(" IS NULL");
}
}
}
@Override
public void visit(JdbcParameter jdbcParameter) {
buffer.append("?");
if (jdbcParameter.isUseFixedIndex()) {
buffer.append(jdbcParameter.getIndex());
}
}
@Override
public void visit(LikeExpression likeExpression) {
visitBinaryExpression(likeExpression, likeExpression.isCaseInsensitive() ? " ILIKE " : " LIKE ");
String escape = likeExpression.getEscape();
if (escape != null) {
buffer.append(" ESCAPE '").append(escape).append('\'');
}
}
@Override
public void visit(ExistsExpression existsExpression) {
if (existsExpression.isNot()) {
buffer.append("NOT EXISTS ");
} else {
buffer.append("EXISTS ");
}
existsExpression.getRightExpression().accept(this);
}
@Override
public void visit(LongValue longValue) {
buffer.append(longValue.getStringValue());
}
@Override
public void visit(MinorThan minorThan) {
visitOldOracleJoinBinaryExpression(minorThan, " < ");
}
@Override
public void visit(MinorThanEquals minorThanEquals) {
visitOldOracleJoinBinaryExpression(minorThanEquals, " <= ");
}
@Override
public void visit(Multiplication multiplication) {
visitBinaryExpression(multiplication, " * ");
}
@Override
public void visit(NotEqualsTo notEqualsTo) {
visitOldOracleJoinBinaryExpression(notEqualsTo, " " + notEqualsTo.getStringExpression() + " ");
}
@Override
public void visit(NullValue nullValue) {
buffer.append(nullValue.toString());
}
@Override
public void visit(OrExpression orExpression) {
visitBinaryExpression(orExpression, " OR ");
}
@Override
public void visit(Parenthesis parenthesis) {
if (parenthesis.isNot()) {
buffer.append(NOT);
}
buffer.append("(");
parenthesis.getExpression().accept(this);
buffer.append(")");
}
@Override
public void visit(StringValue stringValue) {
if (stringValue.getPrefix() != null) {
buffer.append(stringValue.getPrefix());
}
buffer.append("'").append(stringValue.getValue()).append("'");
}
@Override
public void visit(Subtraction subtraction) {
visitBinaryExpression(subtraction, " - ");
}
private void visitBinaryExpression(BinaryExpression binaryExpression, String operator) {
if (binaryExpression.isNot()) {
buffer.append(NOT);
}
binaryExpression.getLeftExpression().accept(this);
buffer.append(operator);
binaryExpression.getRightExpression().accept(this);
}
@Override
public void visit(SubSelect subSelect) {
if (subSelect.isUseBrackets()) {
buffer.append("(");
}
if (selectVisitor != null) {
if (subSelect.getWithItemsList() != null) {
buffer.append("WITH ");
for (Iterator iter = subSelect.getWithItemsList().iterator(); iter.
hasNext();) {
iter.next().accept(selectVisitor);
if (iter.hasNext()) {
buffer.append(", ");
}
buffer.append(" ");
}
buffer.append(" ");
}
subSelect.getSelectBody().accept(selectVisitor);
}
if (subSelect.isUseBrackets()) {
buffer.append(")");
}
}
@Override
public void visit(Column tableColumn) {
final Table table = tableColumn.getTable();
String tableName = null;
if (table != null) {
if (table.getAlias() != null) {
tableName = table.getAlias().getName();
} else {
tableName = table.getFullyQualifiedName();
}
}
if (tableName != null && !tableName.isEmpty()) {
buffer.append(tableName).append(".");
}
buffer.append(tableColumn.getColumnName());
}
@Override
public void visit(Function function) {
if (function.isEscaped()) {
buffer.append("{fn ");
}
buffer.append(function.getName());
if (function.isAllColumns() && function.getParameters() == null) {
buffer.append("(*)");
} else if (function.getParameters() == null && function.getNamedParameters() == null) {
buffer.append("()");
} else {
boolean oldUseBracketsInExprList = useBracketsInExprList;
if (function.isDistinct()) {
useBracketsInExprList = false;
buffer.append("(DISTINCT ");
} else if (function.isAllColumns()) {
useBracketsInExprList = false;
buffer.append("(ALL ");
}
if(function.getNamedParameters() != null){
visit(function.getNamedParameters());
}
if(function.getParameters() != null){
visit(function.getParameters());
}
useBracketsInExprList = oldUseBracketsInExprList;
if (function.isDistinct() || function.isAllColumns()) {
buffer.append(")");
}
}
if (function.getAttribute() != null) {
buffer.append(".").append(function.getAttribute());
}
if (function.getKeep() != null) {
buffer.append(" ").append(function.getKeep());
}
if (function.isEscaped()) {
buffer.append("}");
}
}
@Override
public void visit(ExpressionList expressionList) {
if (useBracketsInExprList) {
buffer.append("(");
}
for (Iterator iter = expressionList.getExpressions().iterator(); iter.hasNext();) {
Expression expression = iter.next();
expression.accept(this);
if (iter.hasNext()) {
buffer.append(", ");
}
}
if (useBracketsInExprList) {
buffer.append(")");
}
}
@Override
public void visit(NamedExpressionList namedExpressionList) {
if (useBracketsInExprList) {
buffer.append("(");
}
List names = namedExpressionList.getNames();
List expressions = namedExpressionList.getExpressions();
for (int i=0; i0){
buffer.append(" ");
}
String name = names.get(i);
if(! name.equals("")){
buffer.append(name);
buffer.append(" ");
}
expressions.get(i).accept(this);
}
if (useBracketsInExprList) {
buffer.append(")");
}
}
public SelectVisitor getSelectVisitor() {
return selectVisitor;
}
public void setSelectVisitor(SelectVisitor visitor) {
selectVisitor = visitor;
}
@Override
public void visit(DateValue dateValue) {
buffer.append("{d '").append(dateValue.getValue().toString()).append("'}");
}
@Override
public void visit(TimestampValue timestampValue) {
buffer.append("{ts '").append(timestampValue.getValue().toString()).append("'}");
}
@Override
public void visit(TimeValue timeValue) {
buffer.append("{t '").append(timeValue.getValue().toString()).append("'}");
}
@Override
public void visit(CaseExpression caseExpression) {
buffer.append("CASE ");
Expression switchExp = caseExpression.getSwitchExpression();
if (switchExp != null) {
switchExp.accept(this);
buffer.append(" ");
}
for (Expression exp : caseExpression.getWhenClauses()) {
exp.accept(this);
}
Expression elseExp = caseExpression.getElseExpression();
if (elseExp != null) {
buffer.append("ELSE ");
elseExp.accept(this);
buffer.append(" ");
}
buffer.append("END");
}
@Override
public void visit(WhenClause whenClause) {
buffer.append("WHEN ");
whenClause.getWhenExpression().accept(this);
buffer.append(" THEN ");
whenClause.getThenExpression().accept(this);
buffer.append(" ");
}
@Override
public void visit(AllComparisonExpression allComparisonExpression) {
buffer.append("ALL ");
allComparisonExpression.getSubSelect().accept((ExpressionVisitor) this);
}
@Override
public void visit(AnyComparisonExpression anyComparisonExpression) {
buffer.append(anyComparisonExpression.getAnyType().name()).append(" ");
anyComparisonExpression.getSubSelect().accept((ExpressionVisitor) this);
}
@Override
public void visit(Concat concat) {
visitBinaryExpression(concat, " || ");
}
@Override
public void visit(Matches matches) {
visitOldOracleJoinBinaryExpression(matches, " @@ ");
}
@Override
public void visit(BitwiseAnd bitwiseAnd) {
visitBinaryExpression(bitwiseAnd, " & ");
}
@Override
public void visit(BitwiseOr bitwiseOr) {
visitBinaryExpression(bitwiseOr, " | ");
}
@Override
public void visit(BitwiseXor bitwiseXor) {
visitBinaryExpression(bitwiseXor, " ^ ");
}
@Override
public void visit(CastExpression cast) {
if (cast.isUseCastKeyword()) {
buffer.append("CAST(");
buffer.append(cast.getLeftExpression());
buffer.append(" AS ");
buffer.append(cast.getType());
buffer.append(")");
} else {
buffer.append(cast.getLeftExpression());
buffer.append("::");
buffer.append(cast.getType());
}
}
@Override
public void visit(Modulo modulo) {
visitBinaryExpression(modulo, " % ");
}
@Override
public void visit(AnalyticExpression aexpr) {
String name = aexpr.getName();
Expression expression = aexpr.getExpression();
Expression offset = aexpr.getOffset();
Expression defaultValue = aexpr.getDefaultValue();
boolean isAllColumns = aexpr.isAllColumns();
KeepExpression keep = aexpr.getKeep();
ExpressionList partitionExpressionList = aexpr.getPartitionExpressionList();
List orderByElements = aexpr.getOrderByElements();
WindowElement windowElement = aexpr.getWindowElement();
buffer.append(name).append("(");
if (aexpr.isDistinct()) {
buffer.append("DISTINCT ");
}
if (expression != null) {
expression.accept(this);
if (offset != null) {
buffer.append(", ");
offset.accept(this);
if (defaultValue != null) {
buffer.append(", ");
defaultValue.accept(this);
}
}
} else if (isAllColumns) {
buffer.append("*");
}
if (aexpr.isIgnoreNulls()) {
buffer.append(" IGNORE NULLS");
}
buffer.append(") ");
if (keep != null) {
keep.accept(this);
buffer.append(" ");
}
switch (aexpr.getType()) {
case WITHIN_GROUP:
buffer.append("WITHIN GROUP");
break;
default:
buffer.append("OVER");
}
buffer.append(" (");
if (partitionExpressionList != null && !partitionExpressionList.getExpressions().isEmpty()) {
buffer.append("PARTITION BY ");
List expressions = partitionExpressionList.getExpressions();
for (int i = 0; i < expressions.size(); i++) {
if (i > 0) {
buffer.append(", ");
}
expressions.get(i).accept(this);
}
buffer.append(" ");
}
if (orderByElements != null && !orderByElements.isEmpty()) {
buffer.append("ORDER BY ");
orderByDeParser.setExpressionVisitor(this);
orderByDeParser.setBuffer(buffer);
for (int i = 0; i < orderByElements.size(); i++) {
if (i > 0) {
buffer.append(", ");
}
orderByDeParser.deParseElement(orderByElements.get(i));
}
if (windowElement != null) {
buffer.append(' ');
buffer.append(windowElement);
}
}
buffer.append(")");
}
@Override
public void visit(ExtractExpression eexpr) {
buffer.append("EXTRACT(").append(eexpr.getName());
buffer.append(" FROM ");
eexpr.getExpression().accept(this);
buffer.append(')');
}
@Override
public void visit(MultiExpressionList multiExprList) {
for (Iterator it = multiExprList.getExprList().iterator(); it.hasNext();) {
it.next().accept(this);
if (it.hasNext()) {
buffer.append(", ");
}
}
}
@Override
public void visit(IntervalExpression iexpr) {
buffer.append(iexpr.toString());
}
@Override
public void visit(JdbcNamedParameter jdbcNamedParameter) {
buffer.append(jdbcNamedParameter.toString());
}
@Override
public void visit(OracleHierarchicalExpression oexpr) {
buffer.append(oexpr.toString());
}
@Override
public void visit(RegExpMatchOperator rexpr) {
visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " ");
}
@Override
public void visit(RegExpMySQLOperator rexpr) {
visitBinaryExpression(rexpr, " " + rexpr.getStringExpression() + " ");
}
@Override
public void visit(JsonExpression jsonExpr) {
buffer.append(jsonExpr.toString());
}
@Override
public void visit(JsonOperator jsonExpr) {
visitBinaryExpression(jsonExpr, " " + jsonExpr.getStringExpression() + " ");
}
@Override
public void visit(UserVariable var) {
buffer.append(var.toString());
}
@Override
public void visit(NumericBind bind) {
buffer.append(bind.toString());
}
@Override
public void visit(KeepExpression aexpr) {
buffer.append(aexpr.toString());
}
@Override
public void visit(MySQLGroupConcat groupConcat) {
buffer.append(groupConcat.toString());
}
@Override
public void visit(ValueListExpression valueList) {
buffer.append(valueList.toString());
}
@Override
public void visit(RowConstructor rowConstructor) {
if (rowConstructor.getName() != null) {
buffer.append(rowConstructor.getName());
}
buffer.append("(");
boolean first = true;
for (Expression expr : rowConstructor.getExprList().getExpressions()) {
if (first) {
first = false;
} else {
buffer.append(", ");
}
expr.accept(this);
}
buffer.append(")");
}
@Override
public void visit(OracleHint hint) {
buffer.append(hint.toString());
}
@Override
public void visit(TimeKeyExpression timeKeyExpression) {
buffer.append(timeKeyExpression.toString());
}
@Override
public void visit(DateTimeLiteralExpression literal) {
buffer.append(literal.toString());
}
}