package net.sf.jsqlparser.util.deparser; import java.util.Iterator; import java.util.List; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.ExpressionVisitor; import net.sf.jsqlparser.schema.Column; import net.sf.jsqlparser.schema.Table; import net.sf.jsqlparser.statement.select.AllColumns; import net.sf.jsqlparser.statement.select.AllTableColumns; import net.sf.jsqlparser.statement.select.FromItem; import net.sf.jsqlparser.statement.select.FromItemVisitor; import net.sf.jsqlparser.statement.select.Join; import net.sf.jsqlparser.statement.select.Limit; import net.sf.jsqlparser.statement.select.OrderByElement; import net.sf.jsqlparser.statement.select.OrderByVisitor; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.SelectExpressionItem; import net.sf.jsqlparser.statement.select.SelectItem; import net.sf.jsqlparser.statement.select.SelectItemVisitor; import net.sf.jsqlparser.statement.select.SelectVisitor; import net.sf.jsqlparser.statement.select.SubJoin; import net.sf.jsqlparser.statement.select.SubSelect; import net.sf.jsqlparser.statement.select.Top; import net.sf.jsqlparser.statement.select.Union; import net.sf.jsqlparser.statement.select.UnionTypes; /** * A class to de-parse (that is, tranform from JSqlParser hierarchy into a * string) a {@link net.sf.jsqlparser.statement.select.Select} */ public class SelectDeParser implements SelectVisitor, OrderByVisitor, SelectItemVisitor, FromItemVisitor { protected StringBuilder buffer; protected ExpressionVisitor expressionVisitor; public SelectDeParser() { } /** * @param aExpressionVisitor a {@link ExpressionVisitor} to de-parse * expressions. It has to share the same<br> * StringBuilder (buffer parameter) as this object in order to work * @param aBuilder the buffer that will be filled with the select */ public SelectDeParser(ExpressionVisitor aExpressionVisitor, StringBuilder aBuilder) { buffer = aBuilder; expressionVisitor = aExpressionVisitor; } public void visit(PlainSelect aPlainSelect) { buffer.append(aPlainSelect.getComment() != null ? aPlainSelect.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Select "); Top top = aPlainSelect.getTop(); if (top != null) { top.toString(); } if (aPlainSelect.getDistinct() != null) { buffer.append(aPlainSelect.getDistinct().getComment() != null ? aPlainSelect.getDistinct().getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Distinct "); if (aPlainSelect.getDistinct().getOnSelectItems() != null) { buffer.append(aPlainSelect.getDistinct().getCommentOn() != null ? aPlainSelect.getDistinct().getCommentOn() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("on") .append(aPlainSelect.getDistinct().getCommentBeginBracket() != null ? " " + aPlainSelect.getDistinct().getCommentBeginBracket() + ExpressionDeParser.LINE_SEPARATOR : "").append(" ("); for (int i = 0; i < aPlainSelect.getDistinct().getOnSelectItems().size(); i++) { SelectItem selectItem = (SelectItem) aPlainSelect.getDistinct().getOnSelectItems().get(i); selectItem.accept(this); if (i < aPlainSelect.getDistinct().getOnSelectItems().size() - 1) { buffer.append(!"".equals(aPlainSelect.getDistinct().getCommentsComma().get(i)) ? " " + aPlainSelect.getDistinct().getCommentsComma().get(i) + ExpressionDeParser.LINE_SEPARATOR : "") .append(", "); } } buffer.append(aPlainSelect.getDistinct().getCommentEndBracket() != null ? aPlainSelect.getDistinct().getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(") "); } } int selectItemsCounter = 0; for (int i = 0, s = aPlainSelect.getSelectItems().size(); i < s; i++) { SelectItem selectItem = (SelectItem) aPlainSelect.getSelectItems().get(i); selectItem.accept(this); if (i < aPlainSelect.getSelectItems().size() - 1) { buffer.append(!aPlainSelect.getCommentCommaItems().get(i).toString().isEmpty() ? " " + aPlainSelect.getCommentCommaItems().get(i) + " " : ""); if (selectItemsCounter++ == 2) { selectItemsCounter = 0; buffer.append(ExpressionDeParser.LINE_SEPARATOR).append(", "); } else { buffer.append(", "); } } } buffer.append(" "); if (aPlainSelect.getFromItem() != null) { buffer.append(aPlainSelect.getCommentFrom() != null ? aPlainSelect.getCommentFrom() + " " : "") .append(ExpressionDeParser.LINE_SEPARATOR).append("From "); aPlainSelect.getFromItem().accept(this); } if (aPlainSelect.getJoins() != null) { for (Iterator iter = aPlainSelect.getJoins().iterator(); iter.hasNext();) { Join join = (Join) iter.next(); buffer.append(ExpressionDeParser.LINE_SEPARATOR); deparseJoin(join); } } if (aPlainSelect.getWhere() != null) { buffer.append(aPlainSelect.getCommentWhere() != null ? " " + aPlainSelect.getCommentWhere() : "") .append(ExpressionDeParser.LINE_SEPARATOR).append(" Where "); aPlainSelect.getWhere().accept(expressionVisitor); } if (aPlainSelect.getConnect() != null) { aPlainSelect.getConnect().accept(expressionVisitor); } if (aPlainSelect.getGroupByColumnReferences() != null) { buffer.append(aPlainSelect.getCommentGroup() != null ? " " + aPlainSelect.getCommentGroup() : "") .append(ExpressionDeParser.LINE_SEPARATOR).append(" Group") .append(aPlainSelect.getCommentGroupBy() != null ? " " + aPlainSelect.getCommentGroupBy() + ExpressionDeParser.LINE_SEPARATOR : "").append(" by "); for (int i = 0; i < aPlainSelect.getGroupByColumnReferences().size(); i++) { Expression columnReference = (Expression) aPlainSelect.getGroupByColumnReferences().get(i); columnReference.accept(expressionVisitor); if (i < aPlainSelect.getGroupByColumnReferences().size() - 1) { buffer.append(!"".equals(aPlainSelect.getCommentCommaGroupBy().get(i)) ? " " + aPlainSelect.getCommentCommaGroupBy().get(i) + ExpressionDeParser.LINE_SEPARATOR : "") .append(", "); } } } if (aPlainSelect.getHaving() != null) { buffer.append(aPlainSelect.getCommentHaving() != null ? " " + aPlainSelect.getCommentHaving() : "") .append(ExpressionDeParser.LINE_SEPARATOR).append(" Having "); aPlainSelect.getHaving().accept(expressionVisitor); } if (aPlainSelect.getOrderByElements() != null) { buffer.append(aPlainSelect.getCommentOrder() != null ? " " + aPlainSelect.getCommentOrder() : "") .append(ExpressionDeParser.LINE_SEPARATOR).append(" Order") .append(aPlainSelect.getCommentOrderBy() != null ? " " + aPlainSelect.getCommentOrderBy() + ExpressionDeParser.LINE_SEPARATOR : "").append(" by "); for (int i = 0; i < aPlainSelect.getOrderByElements().size(); i++) { OrderByElement orderByElement = (OrderByElement) aPlainSelect.getOrderByElements().get(i); orderByElement.accept(this); if (i < aPlainSelect.getOrderByElements().size() - 1) { buffer.append(!"".equals(aPlainSelect.getCommentCommaOrderBy().get(i)) ? " " + aPlainSelect.getCommentCommaOrderBy().get(i) + ExpressionDeParser.LINE_SEPARATOR : "") .append(", "); } } } if (aPlainSelect.getLimit() != null) { deparseLimit(aPlainSelect.getLimit()); } } public void visit(Union union) { for (int i = 0; i < union.getPlainSelects().size(); i++) { assert union.getTypeOperations().size() == union.getPlainSelects().size() - 1; if (union.getCommentsBeginBracket() != null) { buffer.append(!union.getCommentsBeginBracket().get(i).toString().isEmpty() ? union.getCommentsBeginBracket().get(i) + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("("); } PlainSelect plainSelect = (PlainSelect) union.getPlainSelects().get(i); plainSelect.accept(this); if (union.getCommentsEndBracket() != null) { buffer.append(!union.getCommentsEndBracket().get(i).toString().isEmpty() ? union.getCommentsEndBracket().get(i) + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")"); } if (i < union.getPlainSelects().size() - 1) { buffer.append(ExpressionDeParser.LINE_SEPARATOR).append((UnionTypes) union.getTypeOperations().get(i)).append(ExpressionDeParser.LINE_SEPARATOR); } else { buffer.append(ExpressionDeParser.LINE_SEPARATOR); } } if (union.getOrderByElements() != null) { buffer.append(union.getCommentOrder() != null ? " " + union.getCommentOrder() : "") .append(ExpressionDeParser.LINE_SEPARATOR).append(" Order") .append(union.getCommentOrderBy() != null ? " " + union.getCommentOrderBy() + ExpressionDeParser.LINE_SEPARATOR : "").append(" by "); for (int i = 0; i < union.getOrderByElements().size(); i++) { OrderByElement orderByElement = (OrderByElement) union.getOrderByElements().get(i); orderByElement.accept(this); if (i < union.getOrderByElements().size() - 1) { buffer.append(!"".equals(union.getCommentCommaOrderBy().get(i)) ? " " + union.getCommentCommaOrderBy().get(i) + ExpressionDeParser.LINE_SEPARATOR : "") .append(", "); } } } if (union.getLimit() != null) { deparseLimit(union.getLimit()); } } public void visit(OrderByElement orderBy) { orderBy.getExpression().accept(expressionVisitor); if (orderBy.isAsc()) { buffer.append(orderBy.getComment() != null ? " " + orderBy.getComment() + ExpressionDeParser.LINE_SEPARATOR : "").append(" asc"); } if (orderBy.isDesc()) { buffer.append(orderBy.getComment() != null ? " " + orderBy.getComment() + ExpressionDeParser.LINE_SEPARATOR : "").append(" desc"); } } public void visit(Column column) { buffer.append(column.getComment() != null ? column.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(column.getWholeColumnName()); } public void visit(AllColumns allColumns) { buffer.append(allColumns.getComment() != null ? allColumns.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("*"); } public void visit(AllTableColumns allTableColumns) { buffer.append(allTableColumns.getTable().getWholeTableName()).append(".*"); } public void visit(SelectExpressionItem selectExpressionItem) { selectExpressionItem.getExpression().accept(expressionVisitor); if (selectExpressionItem.getAlias() != null) { buffer.append(" ").append(selectExpressionItem.getAlias().toString()); } } public void visit(SubSelect subSelect) { buffer.append(subSelect.getCommentBeginBracket() != null ? subSelect.getCommentBeginBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("("); subSelect.getSelectBody().accept(this); buffer.append(subSelect.getCommentEndBracket() != null ? subSelect.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")"); String alias = subSelect.getAlias() != null ? subSelect.getAlias().toString() : ""; if (alias != null && !alias.isEmpty()) { buffer.append(" ").append(alias);// it's very strange, but in fact oracle doesn't permit as key word if form clause // buffer.append(" as ").append(alias); } } public void visit(Table aTable) { buffer.append(aTable.getComment() != null ? aTable.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(aTable.getWholeTableName()); String alias = aTable.getAlias() != null ? aTable.getAlias().toString() : ""; if (alias != null && !alias.isEmpty()) { buffer.append(" ").append(alias);// it's very strange, but in fact oracle doesn't permit as key word if form clause // buffer.append(" as ").append(alias); } } public void deparseOrderBy(List orderByElements) { buffer.append(ExpressionDeParser.LINE_SEPARATOR).append(" Order by "); for (Iterator iter = orderByElements.iterator(); iter.hasNext();) { OrderByElement orderByElement = (OrderByElement) iter.next(); orderByElement.accept(this); if (iter.hasNext()) { buffer.append(", "); } } } public void deparseLimit(Limit limit) { // LIMIT n OFFSET skip buffer.append(ExpressionDeParser.LINE_SEPARATOR) .append(limit.getCommentLimit() != null ? " " + limit.getCommentLimit() + ExpressionDeParser.LINE_SEPARATOR : "").append(" Limit"); if (limit.isLimitAll()) { buffer.append(limit.getCommentAll() != null ? " " + limit.getCommentAll() + ExpressionDeParser.LINE_SEPARATOR : "").append(" All "); } buffer.append(limit.getCommentLimitValue() != null ? limit.getCommentLimitValue() + " " + ExpressionDeParser.LINE_SEPARATOR : ""); if (limit.isComma()) { if (limit.isOffsetJdbcParameter()) { buffer.append("?"); } else if (limit.getOffset() != 0) { buffer.append(limit.getOffset()); } buffer.append(limit.getCommentComma() != null ? limit.getCommentComma() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(", ") .append(limit.getCommentAfterCommaValue() != null ? limit.getCommentAfterCommaValue() + " " + ExpressionDeParser.LINE_SEPARATOR : ""); if (limit.isRowCountJdbcParameter()) { buffer.append("?"); } else if (limit.getRowCount() != 0) { buffer.append(limit.getRowCount()); } } else { if (limit.isRowCountJdbcParameter()) { buffer.append("?"); } else { if (limit.getRowCount() != 0) { buffer.append(limit.getRowCount()); } else { /* from mysql docs: For compatibility with PostgreSQL, MySQL also supports the LIMIT row_count OFFSET offset syntax. To retrieve all rows from a certain offset up to the end of the result set, you can use some large number for the second parameter. */ buffer.append("18446744073709551615"); } } } if (limit.isOffsetJdbcParameter()) { buffer.append(limit.getCommentOffset() != null ? " " + limit.getCommentOffset() + ExpressionDeParser.LINE_SEPARATOR : "").append(" Offset") .append(limit.getCommentOffsetValue() != null ? " " + limit.getCommentOffsetValue() + ExpressionDeParser.LINE_SEPARATOR : "").append(" ?"); } else if (limit.getOffset() != 0) { buffer.append(limit.getCommentOffset() != null ? " " + limit.getCommentOffset() + ExpressionDeParser.LINE_SEPARATOR : "").append(" Offset ") .append(limit.getCommentOffsetValue() != null ? " " + limit.getCommentOffsetValue() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(limit.getOffset()); } } public StringBuilder getBuffer() { return buffer; } public void setBuffer(StringBuilder buffer) { this.buffer = buffer; } public ExpressionVisitor getExpressionVisitor() { return expressionVisitor; } public void setExpressionVisitor(ExpressionVisitor visitor) { expressionVisitor = visitor; } public void visit(SubJoin subjoin) { buffer.append(subjoin.getCommentBeginBracket() != null ? subjoin.getCommentBeginBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("("); subjoin.getLeft().accept(this); buffer.append(" "); deparseJoin(subjoin.getJoin()); buffer.append(subjoin.getCommentEndBracket() != null ? subjoin.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")"); } public void deparseJoin(Join join) { if (join.isSimple()) { buffer.append(join.getComment() != null ? join.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(", "); } else { buffer.append(" "); if (join.isRight()) { buffer.append(join.getCommentRight() != null ? join.getCommentRight() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Right "); } else if (join.isNatural()) { buffer.append(join.getCommentNatural() != null ? join.getCommentNatural() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Natural "); } else if (join.isFull()) { buffer.append(join.getCommentFull() != null ? join.getCommentFull() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Full "); } else if (join.isLeft()) { buffer.append(join.getCommentLeft() != null ? join.getCommentLeft() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Left "); } if (join.isOuter()) { buffer.append(join.getCommentOuter() != null ? join.getCommentOuter() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Outer "); } else if (join.isInner()) { buffer.append(join.getCommentInner() != null ? join.getCommentInner() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Inner "); } buffer.append(join.getCommentJoin() != null ? join.getCommentJoin() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append("Join "); } FromItem fromItem = join.getRightItem(); fromItem.accept(this); if (join.getOnExpression() != null) { buffer.append(join.getCommentOn() != null ? " " + join.getCommentOn() + ExpressionDeParser.LINE_SEPARATOR : "").append(" on "); join.getOnExpression().accept(expressionVisitor); } if (join.getUsingColumns() != null) { buffer.append(join.getCommentUsing() != null ? " " + join.getCommentUsing() + ExpressionDeParser.LINE_SEPARATOR : "").append(" Using") .append(join.getCommentBeginBracket() != null ? " " + join.getCommentBeginBracket() + ExpressionDeParser.LINE_SEPARATOR : "").append(" ( "); for (int i = 0, s = join.getUsingColumns().size(); i < s; i++) { Column column = (Column) join.getUsingColumns().get(i); buffer.append(column.getComment() != null ? column.getComment() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(column.getWholeColumnName()); if (i < join.getUsingColumns().size() - 1) { buffer.append(!join.getCommentComma().get(i).toString().isEmpty() ? " " + join.getCommentComma().get(i) + " " + ExpressionDeParser.LINE_SEPARATOR : ""); buffer.append(", "); } } buffer.append(join.getCommentEndBracket() != null ? join.getCommentEndBracket() + " " + ExpressionDeParser.LINE_SEPARATOR : "").append(")"); } } }