/* * #%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 * <http://www.gnu.org/licenses/lgpl-2.1.html>. * #L% */ package net.sf.jsqlparser.util.deparser; import net.sf.jsqlparser.expression.*; import net.sf.jsqlparser.expression.operators.arithmetic.*; import net.sf.jsqlparser.expression.operators.conditional.AndExpression; import net.sf.jsqlparser.expression.operators.conditional.OrExpression; import net.sf.jsqlparser.expression.operators.relational.*; import net.sf.jsqlparser.schema.*; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.SubSelect; import net.sf.jsqlparser.expression.operators.relational.JsonOperator; import java.util.Iterator; 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 "; private StringBuilder buffer = new StringBuilder(); private SelectVisitor selectVisitor; private boolean useBracketsInExprList = true; public ExpressionDeParser() { } /** * @param selectVisitor a SelectVisitor to de-parse SubSelects. It has to share the same<br> * StringBuilder as this object in order to work, as: * * <pre> * <code> * StringBuilder myBuf = new StringBuilder(); * MySelectDeparser selectDeparser = new MySelectDeparser(); * selectDeparser.setBuffer(myBuf); * ExpressionDeParser expressionDeParser = new ExpressionDeParser(selectDeparser, myBuf); * </code> * </pre> * * @param buffer the buffer that will be filled with the expression */ public ExpressionDeParser(SelectVisitor selectVisitor, StringBuilder buffer) { this.selectVisitor = selectVisitor; this.buffer = buffer; } 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); } 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.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) { 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) { buffer.append("("); if (selectVisitor != null) { if (subSelect.getWithItemsList() != null) { buffer.append("WITH "); for (Iterator<WithItem> iter = subSelect.getWithItemsList().iterator(); iter. hasNext();) { iter.next().accept(selectVisitor); if (iter.hasNext()) { buffer.append(", "); } buffer.append(" "); } buffer.append(" "); } subSelect.getSelectBody().accept(selectVisitor); } 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) { buffer.append("()"); } else { boolean oldUseBracketsInExprList = useBracketsInExprList; if (function.isDistinct()) { useBracketsInExprList = false; buffer.append("(DISTINCT "); } else if (function.isAllColumns()) { useBracketsInExprList = false; buffer.append("(ALL "); } 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<Expression> iter = expressionList.getExpressions().iterator(); iter.hasNext();) { Expression expression = iter.next(); expression.accept(this); if (iter.hasNext()) { buffer.append(", "); } } 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) { buffer.append(aexpr.toString()); } @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<ExpressionList> 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(WithinGroupExpression wgexpr) { buffer.append(wgexpr.toString()); } @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(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()); } }