/** * Copyright 2004-2016 Riccardo Solmi. All rights reserved. * This file is part of the Whole Platform. * * The Whole Platform 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 3 of the License, or * (at your option) any later version. * * The Whole Platform 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 Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Whole Platform. If not, see <http://www.gnu.org/licenses/>. */ package org.whole.lang.sql.visitors; import java.sql.Blob; import java.sql.Clob; import java.sql.SQLException; import org.whole.lang.model.adapters.IEntityAdapter; import org.whole.lang.operations.IPrettyPrintWriter; import org.whole.lang.operations.PrettyPrinterOperation; import org.whole.lang.sql.model.*; import org.whole.lang.sql.parsers.SQLDataTypeParser; import org.whole.lang.sql.reflect.OperatorGroupEnum; import org.whole.lang.sql.reflect.SQLEntityDescriptorEnum; import org.whole.lang.util.DataTypeUtils; import org.whole.lang.util.EntityUtils; /** * @author Riccardo Solmi */ public class SQLPrettyPrinterVisitor extends SQLTraverseAllVisitor { protected final IPrettyPrintWriter out; private String[] constraintArray = new String[] { "NULL", "NOT NULL", "PRIMARY KEY", "UNIQUE", "AUTOINCREMENT"}; public SQLPrettyPrinterVisitor(PrettyPrinterOperation operation) { out = operation.getPrettyPrintWriter(); } public boolean visitAdapter(IEntityAdapter entity) { stagedVisit(entity.wGetAdaptee(false)); return false; } @Override public void visit(SQLStatements entity) { for (int i = 0; i < entity.wSize(); i++) { ((SQLStatement) entity.wGet(i)).accept(this); out.printlnRaw(";"); } } public void visit(Insert entity) { out.printRaw("INSERT INTO "); entity.getTableName().accept(this); entity.getColumnNames().accept(this); out.printRaw(" VALUES "); entity.getValues().accept(this); } public void visit(TableName entity) { out.printRaw(entity.getValue()); } public void visit(ColumnName entity) { out.printRaw(entity.getValue()); } public void visit(ColumnNames entity) { if (!entity.wIsEmpty()) { out.printRaw(" ("); for (int i = 0; i < entity.wSize(); i++) { if (i > 0) out.print(','); ((ColumnName) entity.wGet(i)).accept(this); } out.print(')'); } } public void visit(Values entity) { for (int i = 0; i < entity.wSize(); i++) { if (i > 0) out.print(','); out.print('('); ((SQLExpressions) entity.wGet(i)).accept(this); out.print(')'); } } public void visit(SQLExpressions entity) { for (int i = 0; i < entity.wSize(); i++) { if (i > 0) out.print(','); ((SQLExpression) entity.wGet(i)).accept(this); } } public void visit(Subquery entity) { out.print('('); entity.getQuery().accept(this); out.print(')'); } public void visit(In entity) { entity.getLeftExpr().accept(this); out.printRaw(" IN "); entity.getInPredicate().accept(this); } public void visit(NotIn entity) { entity.getLeftExpr().accept(this); out.printRaw(" NOT IN "); entity.getInPredicate().accept(this); } public void visit(InValueList entity) { out.print('('); for (int i = 0; i < entity.wSize(); i++) { if (i > 0) out.print(','); ((SQLExpression) entity.wGet(i)).accept(this); } out.print(')'); } public void visit(Between entity) { entity.getExpression().accept(this); out.printRaw(" BETWEEN "); entity.getLowerExpression().accept(this); out.printRaw(" AND "); entity.getUpperExpression().accept(this); } public void visit(NotBetween entity) { entity.getExpression().accept(this); out.printRaw(" NOT BETWEEN "); entity.getLowerExpression().accept(this); out.printRaw(" AND "); entity.getUpperExpression().accept(this); } public void visit(Is entity) { entity.getExpression().accept(this); out.printRaw(" IS "); entity.getType().accept(this); } public void visit(IsType entity) { out.printRaw(SQLDataTypeParser.instance().unparseEnumValue( entity.wGetEntityDescriptor(), entity.getValue())); } public void visit(NullValue entity) { out.printRaw("NULL"); } public void visit(BlobValue entity) { out.printRaw("X'");//TODO Oracle "'" Blob blob = entity.getValue(); try { out.printRaw(SQLDataTypeParser.instance().unparseObject( SQLEntityDescriptorEnum.BinaryValue, blob.getBytes(1l, (int) blob.length()))); //TODO Oracle .toUpperCase()); } catch (SQLException e) { } out.print('\''); } public void visit(ClobValue entity) { out.print('\''); Clob clob = entity.getValue(); try { out.printRaw(clob.getSubString(1l, (int) clob.length())); } catch (SQLException e) { } out.print('\''); } public void visit(ArrayValue entity) { Object value = entity.getValue(); assert value.getClass().isArray(); out.printRaw("("); out.printRaw(SQLDataTypeParser.instance().unparseObject( entity.wGetEntityDescriptor(), entity.getValue())); out.printRaw(")"); } public void visit(BooleanValue entity) { out.printRaw(SQLDataTypeParser.instance().unparseObject( entity.wGetEntityDescriptor(), entity.isValue())); } public void visit(TinyIntValue entity) { out.print(entity.getValue()); } public void visit(SmallIntValue entity) { out.print(entity.getValue()); } public void visit(IntValue entity) { out.print(entity.getValue()); } public void visit(BigIntValue entity) { out.print(entity.getValue()); } public void visit(DoubleValue entity) { out.printRaw(SQLDataTypeParser.instance().unparseDouble( entity.wGetEntityDescriptor(), entity.getValue())); } public void visit(RealValue entity) { out.printRaw(SQLDataTypeParser.instance().unparseFloat( entity.wGetEntityDescriptor(), entity.getValue())); } public void visit(DecimalValue entity) { out.printRaw(SQLDataTypeParser.instance().unparseObject( entity.wGetEntityDescriptor(), entity.getValue())); } public void visit(StringValue entity) { out.print('\''); out.printRaw(SQLDataTypeParser.instance().unparseString( entity.wGetEntityDescriptor(), entity.getValue())); out.print('\''); } public void visit(BinaryValue entity) { Object value = entity.getValue(); assert value.getClass().isArray(); out.printRaw("X'");//TODO Oracle "'" out.printRaw(SQLDataTypeParser.instance().unparseObject( entity.wGetEntityDescriptor(), entity.getValue())); //TODO Oracle .toUpperCase()); out.print('\''); } public void visit(DateValue entity) { out.printRaw("DATE '"); out.printRaw(SQLDataTypeParser.instance().unparseObject( entity.wGetEntityDescriptor(), entity.getValue())); out.print('\''); } public void visit(TimeValue entity) { out.printRaw("TIME '"); out.printRaw(SQLDataTypeParser.instance().unparseObject( entity.wGetEntityDescriptor(), entity.getValue())); out.print('\''); } public void visit(TimestampValue entity) { out.printRaw("TIMESTAMP '");//TODO DB2 "TIMESTAMP('" out.printRaw(SQLDataTypeParser.instance().unparseObject( entity.wGetEntityDescriptor(), entity.getValue())); out.print('\'');//TODO DB2 "')" } public void visit(RawValue entity) { out.print('\''); out.printRaw(SQLDataTypeParser.instance().unparseObject( entity.wGetEntityDescriptor(), entity.getValue())); out.print('\''); } public void visit(InsertFromSelect entity) { out.printRaw("INSERT INTO "); entity.getTableName().accept(this); entity.getColumnNames().accept(this); out.print(' '); entity.getSelect().accept(this); } public void visit(Select entity) { out.printRaw("SELECT "); if (EntityUtils.isNotResolver(entity.getSelectType())) { entity.getSelectType().accept(this); out.print(' '); } entity.getColumnExprs().accept(this); out.printRaw(" FROM "); entity.getFromClauses().accept(this); if (EntityUtils.isNotResolver(entity.getWhereExpr())) { out.printRaw(" WHERE "); entity.getWhereExpr().accept(this); } if (EntityUtils.isNotResolver(entity.getGroupByExprs())) { out.printRaw(" GROUP BY "); entity.getGroupByExprs().accept(this); } if (EntityUtils.isNotResolver(entity.getHavingExpr())) { out.printRaw(" HAVING "); entity.getHavingExpr().accept(this); } if (EntityUtils.isNotResolver(entity.getOrderByColumnExprs())) { out.printRaw(" ORDER BY "); entity.getOrderByColumnExprs().accept(this); } } public void visit(UnionSelect entity) { entity.getSimpleSelect().accept(this); out.printRaw(" UNION "); entity.getUnionSelectStatement().accept(this); } public void visit(SelectType entity) { out.print(entity.getValue()); out.print(' '); } public void visit(ColumnExpressions entity) { if (!entity.wIsEmpty()) { for (int i = 0; i < entity.wSize(); i++) { if (i > 0) out.printRaw(", "); ((ColumnExpression) entity.wGet(i)).accept(this); } } } public void visit(ColumnExpression entity) { entity.getExpression().accept(this); entity.getAlias().accept(this); } public void visit(Alias entity) { out.printRaw(" AS "); out.printRaw(entity.getValue()); } public void visit(FunctionExpression entity) { entity.getFunctionName().accept(this); out.print('('); entity.getParams().accept(this); out.print(')'); } public void visit(FunctionName entity) { out.printRaw(entity.getValue()); } public void visit(FromClauses entity) { for (int i = 0; i < entity.wSize(); i++) { if (i>0) out.print(','); ((FromClause) entity.wGet(i)).accept(this); } } public void visit(InnerJoinFromClause entity) { entity.getTableName().accept(this); out.printRaw(" INNER JOIN "); entity.getInnerTable().accept(this); out.printRaw(" ON "); entity.getOnExpression().accept(this); } public void visit(LeftOuterJoinFromClause entity) { entity.getTableName().accept(this); out.printRaw(" LEFT JOIN "); entity.getOuterTable().accept(this); out.printRaw(" ON "); entity.getOnExpression().accept(this); } public void visit(RightOuterJoinFromClause entity) { entity.getTableName().accept(this); out.printRaw(" RIGHT JOIN "); entity.getOuterTable().accept(this); out.printRaw(" ON "); entity.getOnExpression().accept(this); } public void visit(SimpleFromClause entity) { out.printRaw(entity.getValue()); } public void visit(OrderByColumnExpressions entity) { if (!entity.wIsEmpty()) { for (int i = 0; i < entity.wSize(); i++) { if (i > 0) out.print(','); ((OrderByColumnExpression) entity.wGet(i)).accept(this); } } } public void visit(OrderByColumnExpression entity) { entity.getExpression().accept(this); out.print(' '); entity.getOrderType().accept(this); } public void visit(OrderType entity) { out.print(entity.getValue()); } public void visit(Update entity) { out.printRaw("UPDATE "); entity.getTableName().accept(this); out.printRaw(" SET "); entity.getSetClauses().accept(this); if (EntityUtils.isNotResolver(entity.getFromClauses())) { out.printRaw(" FROM "); entity.getFromClauses().accept(this); } if (EntityUtils.isNotResolver(entity.getWhereExpr())) { out.printRaw(" WHERE "); entity.getWhereExpr().accept(this); } if (EntityUtils.isNotResolver(entity.getLimit())) { out.printRaw(" LIMIT "); entity.getLimit().accept(this); } } public void visit(SetClauses entity) { for (int i = 0; i < entity.wSize(); i++) { if (i > 0) out.print(','); ((SetClause) entity.wGet(i)).accept(this); } } public void visit(SetClause entity) { entity.getColumnName().accept(this); out.print('='); entity.getExpression().accept(this); } public void visit(Delete entity) { out.printRaw("DELETE FROM "); entity.getTableName().accept(this); if (EntityUtils.isNotResolver(entity.getWhereExpr())) { out.printRaw(" WHERE "); entity.getWhereExpr().accept(this); } if (EntityUtils.isNotResolver(entity.getLimit())) { out.printRaw(" LIMIT "); entity.getLimit().accept(this); } } @Override public void visit(ParenthesizedExpression entity) { out.print('('); entity.getExpression().accept(this); out.print(')'); } public void visit(BooleanBinaryExpression entity) { SQLExpression leftExpr = entity.getLeftExpr(); SQLExpression rightExpr = entity.getRightExpr(); boolean showLeftParen = OperatorGroupEnum.hasPrecedence(entity, leftExpr); boolean showRightParen = OperatorGroupEnum.hasPrecedence(entity, rightExpr); if (showLeftParen) out.printRaw("("); leftExpr.accept(this); if (showLeftParen) out.printRaw(")"); out.printRaw(" "); entity.getOperator().accept(this); out.printRaw(" "); if (showRightParen) out.printRaw("("); rightExpr.accept(this); if (showRightParen) out.printRaw(")"); } public void visit(BooleanOperator entity) { out.printRaw(SQLDataTypeParser.instance().unparseEnumValue(entity.wGetEntityDescriptor(), entity.getValue())); } public void visit(BinaryExpression entity) { SQLExpression leftExpr = entity.getLeftExpr(); SQLExpression rightExpr = entity.getRightExpr(); boolean showLeftParen = OperatorGroupEnum.hasPrecedence(entity, leftExpr); boolean showRightParen = OperatorGroupEnum.hasPrecedence(entity, rightExpr); if (showLeftParen) out.printRaw("("); leftExpr.accept(this); if (showLeftParen) out.printRaw(")"); out.printRaw(" "); entity.getOperator().accept(this); out.printRaw(" "); if (showRightParen) out.printRaw("("); rightExpr.accept(this); if (showRightParen) out.printRaw(")"); } public void visit(BinaryOperator entity) { out.printRaw(SQLDataTypeParser.instance().unparseEnumValue(entity.wGetEntityDescriptor(), entity.getValue())); } public void visit(CaseExpression entity) { out.printRaw("CASE"); entity.getWhenClauses().accept(this); out.printRaw(" ELSE "); entity.getElseClause().accept(this); out.printRaw(" END"); } public void visit(WhenClause entity) { out.printRaw(" WHEN "); entity.getCondition().accept(this); out.printRaw(" THEN "); entity.getResult().accept(this); } public void visit(Truncate entity) { out.printRaw("TRUNCATE "); entity.getTableName().accept(this); } public void visit(Create entity) { out.printRaw("CREATE TABLE "); entity.getTableName().accept(this); out.printRaw(" ("); entity.getDeclarationOrConstraints().accept(this); out.printRaw(") "); } public void visit(AlterTable entity) { out.printRaw("ALTER TABLE "); entity.getTableName().accept(this); entity.getAction().accept(this); } @Override public void visit(AddAction entity) { out.printRaw(" ADD "); super.visit(entity); } public void visit(DeclarationOrConstraints entity) { for (int i = 0; i < entity.wSize(); i++) { if (i>0) out.printRaw(", "); ((ISQLEntity) entity.wGet(i)).accept(this); } } public void visit(ColumnDeclaration entity) { entity.getColumnName().accept(this); out.printRaw(" "); entity.getColumnType().accept(this); entity.getColumnConstraints().accept(this); } public void visit(ColumnType entity) { String typeValue = entity.getType().wStringValue(); out.printRaw(typeValue); if (DataTypeUtils.getDataKind(entity.getSize()).isInt()) { out.print('('); out.print(entity.getSize().wIntValue()); if (DataTypeUtils.getDataKind(entity.getPrecision()).isInt()) { out.print('('); out.print(entity.getPrecision().wIntValue()); out.print(')'); } out.print(')'); } } public void visit(SimpleColumnConstraint entity) { out.printRaw(" "); out.printRaw(constraintArray[entity.wEnumValue().getOrdinal()]); } public void visit(PrimaryKeyTableConstraint entity) { out.printRaw("PRIMARY KEY "); entity.getColumnNames().accept(this); } public void visit(ForeignKeyTableConstraint entity) { out.printRaw("FOREIGN KEY "); entity.getColumnNames().accept(this); out.printRaw(" REFERENCES "); entity.getForeignTableName().accept(this); entity.getForeignColumnNames().accept(this); } public void visit(ForeignKeyColumnConstraint entity) { out.printRaw(" REFERENCES "); entity.getForeignTableName().accept(this); entity.getForeignColumnName().accept(this); } public void visit(Drop entity) { out.printRaw("DROP TABLE "); entity.getTableName().accept(this); } }