package com.alibaba.druid.sql.dialect.oracle.visitor;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.ast.SQLArgument;
import com.alibaba.druid.sql.ast.SQLDataType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLHint;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLOver;
import com.alibaba.druid.sql.ast.SQLParameter;
import com.alibaba.druid.sql.ast.SQLPartitionBy;
import com.alibaba.druid.sql.ast.SQLPartitionValue;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.SQLSubPartition;
import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.SQLAlterProcedureStatement;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableItem;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableRename;
import com.alibaba.druid.sql.ast.statement.SQLAlterTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLBlockStatement;
import com.alibaba.druid.sql.ast.statement.SQLCharacterDataType;
import com.alibaba.druid.sql.ast.statement.SQLCheck;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLCreateFunctionStatement;
import com.alibaba.druid.sql.ast.statement.SQLCreateIndexStatement;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
import com.alibaba.druid.sql.ast.statement.SQLForeignKeyImpl;
import com.alibaba.druid.sql.ast.statement.SQLIfStatement;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSavePointStatement;
import com.alibaba.druid.sql.ast.statement.SQLScriptCommitStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement;
import com.alibaba.druid.sql.ast.statement.SQLUnique;
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
import com.alibaba.druid.sql.ast.statement.SQLWithSubqueryClause;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay;
import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.ModelClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleLobStorageClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleReturningClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleStorageClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.OracleWithSubqueryEntry;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.PartitionExtensionClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SampleClause;
import com.alibaba.druid.sql.dialect.oracle.ast.clause.SearchClause;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalytic;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAnalyticWindowing;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArgumentExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryDoubleExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleBinaryFloatExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleCursorExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleDatetimeExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIntervalExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsOfTypeExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleIsSetExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleJsonArrayAggExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleJsonObjectExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleMethodInvokeAccessExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleMultisetExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleOuterExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleRangeExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleSysdateExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleTreatExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleXmlContentExpr;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSessionStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterSynonymStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableDropPartition;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableModify;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableMoveTablespace;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableSplitPartition;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTableTruncatePartition;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTablespaceAddDataFile;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTablespaceStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterTriggerStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleAlterViewStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCheck;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleConstraint;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleContinueStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateDatabaseDbLinkStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateIndexStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreatePackageStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateSynonymStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTableStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleCreateTypeStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDropDbLinkStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExceptionStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExecuteImmediateStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExitStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleExplainStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleFileSpecification;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleForStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleForeignKey;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleGotoStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLabelStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleLockTableStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePipeRowStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePrimaryKey;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleRaiseStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleRunStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectJoin;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectPivot;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectPivotBase;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectRestriction;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectSubqueryTableSource;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectTableReference;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectUnPivot;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSetTransactionStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSupplementalIdKey;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSupplementalLogGrp;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUnique;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUsingIndexClause;
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleXmlColumnProperties;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleFunctionDataType;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleProcedureDataType;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import java.util.List;

public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleASTVisitor {
   private final boolean printPostSemi;

   public OracleOutputVisitor(Appendable appender) {
      this(appender, true);
   }

   public OracleOutputVisitor(Appendable appender, boolean printPostSemi) {
      super(appender);
      this.dbType = DbType.oracle;
      this.printPostSemi = printPostSemi;
   }

   public boolean isPrintPostSemi() {
      return this.printPostSemi;
   }

   private void printHints(List<SQLHint> hints) {
      if (hints.size() > 0) {
         this.print0("/*+ ");
         this.printAndAccept(hints, ", ");
         this.print0(" */");
      }

   }

   public boolean visit(OracleAnalytic x) {
      this.print0(this.ucase ? "(" : "(");
      boolean space = false;
      if (x.getPartitionBy().size() > 0) {
         this.print0(this.ucase ? "PARTITION BY " : "partition by ");
         this.printAndAccept(x.getPartitionBy(), ", ");
         space = true;
      }

      SQLOrderBy orderBy = x.getOrderBy();
      if (orderBy != null) {
         if (space) {
            this.print(' ');
         }

         this.visit((SQLOrderBy)orderBy);
         space = true;
      }

      OracleAnalyticWindowing windowing = x.getWindowing();
      if (windowing != null) {
         if (space) {
            this.print(' ');
         }

         this.visit(windowing);
      }

      if (x.isWindowingPreceding()) {
         this.print0(this.ucase ? " PRECEDING" : " preceding");
      }

      this.print(')');
      return false;
   }

   public boolean visit(OracleAnalyticWindowing x) {
      this.print0(x.getType().name().toUpperCase());
      this.print(' ');
      SQLExpr expr = x.getExpr();
      if (expr instanceof SQLBetweenExpr && x.getParent() instanceof SQLOver) {
         SQLOver over = (SQLOver)x.getParent();
         SQLBetweenExpr betweenExpr = (SQLBetweenExpr)expr;
         SQLOver.WindowingBound beginBound = over.getWindowingBetweenBeginBound();
         if (beginBound != null) {
            this.print0(this.ucase ? " BETWEEN " : " between ");
            betweenExpr.getBeginExpr().accept(this);
            this.print(' ');
            this.print0(this.ucase ? beginBound.name : beginBound.name_lower);
            this.print0(this.ucase ? " AND " : " and ");
            betweenExpr.getEndExpr().accept(this);
            return false;
         }
      }

      expr.accept(this);
      return false;
   }

   public boolean visit(OracleDeleteStatement x) {
      this.print0(this.ucase ? "DELETE " : "delete ");
      SQLTableSource tableSource = x.getTableSource();
      if (x.getHints().size() > 0) {
         this.printAndAccept(x.getHints(), ", ");
         this.print(' ');
      }

      this.print0(this.ucase ? "FROM " : "from ");
      if (x.isOnly()) {
         this.print0(this.ucase ? "ONLY (" : "only (");
         x.getTableName().accept(this);
         this.print(')');
         this.printAlias(x.getAlias());
      } else {
         x.getTableSource().accept(this);
      }

      if (x.getWhere() != null) {
         this.println();
         ++this.indentCount;
         this.print0(this.ucase ? "WHERE " : "where ");
         x.getWhere().accept(this);
         --this.indentCount;
      }

      if (x.getReturning() != null) {
         this.println();
         x.getReturning().accept(this);
      }

      return false;
   }

   public boolean visit(OracleIntervalExpr x) {
      SQLExpr value = x.getValue();
      if (!(value instanceof SQLLiteralExpr) && !(value instanceof SQLVariantRefExpr)) {
         this.print('(');
         value.accept(this);
         this.print0(") ");
      } else {
         this.print0(this.ucase ? "INTERVAL " : "interval ");
         value.accept(this);
         this.print(' ');
      }

      this.print0(x.getType().name());
      if (x.getPrecision() != null) {
         this.print('(');
         this.printExpr(x.getPrecision(), this.parameterized);
         if (x.getFactionalSecondsPrecision() != null) {
            this.print0(", ");
            this.print(x.getFactionalSecondsPrecision());
         }

         this.print(')');
      }

      if (x.getToType() != null) {
         this.print0(this.ucase ? " TO " : " to ");
         this.print0(x.getToType().name());
         if (x.getToFactionalSecondsPrecision() != null) {
            this.print('(');
            this.printExpr(x.getToFactionalSecondsPrecision(), this.parameterized);
            this.print(')');
         }
      }

      return false;
   }

   public boolean visit(OracleOuterExpr x) {
      x.getExpr().accept(this);
      this.print0("(+)");
      return false;
   }

   public boolean visit(SQLScriptCommitStatement astNode) {
      this.print('/');
      this.println();
      return false;
   }

   public boolean visit(SQLSelect x) {
      SQLWithSubqueryClause with = x.getWithSubQuery();
      if (with != null) {
         with.accept(this);
         this.println();
      }

      SQLSelectQuery query = x.getQuery();
      query.accept(this);
      if (x.getRestriction() != null) {
         this.println();
         this.print("WITH ");
         x.getRestriction().accept(this);
      }

      SQLOrderBy orderBy = x.getOrderBy();
      if (orderBy != null) {
         boolean hasFirst = false;
         if (query instanceof SQLSelectQueryBlock) {
            SQLSelectQueryBlock queryBlock = (SQLSelectQueryBlock)query;
            hasFirst = queryBlock.getFirst() != null;
         }

         if (!hasFirst) {
            this.println();
            orderBy.accept(this);
         }
      }

      return false;
   }

   public boolean visit(OracleSelectJoin x) {
      x.getLeft().accept(this);
      SQLTableSource right = x.getRight();
      if (x.getJoinType() == SQLJoinTableSource.JoinType.COMMA) {
         this.print0(", ");
         x.getRight().accept(this);
      } else {
         boolean isRoot = x.getParent() instanceof SQLSelectQueryBlock;
         if (isRoot) {
            ++this.indentCount;
         }

         this.println();
         this.print0(this.ucase ? x.getJoinType().name : x.getJoinType().name_lcase);
         this.print(' ');
         if (right instanceof SQLJoinTableSource) {
            this.print('(');
            this.incrementIndent();
            this.println();
            right.accept(this);
            this.decrementIndent();
            this.println();
            this.print(')');
         } else {
            right.accept(this);
         }

         if (isRoot) {
            --this.indentCount;
         }

         if (x.getCondition() != null) {
            this.print0(this.ucase ? " ON " : " on ");
            this.incrementIndent();
            x.getCondition().accept(this);
            this.decrementIndent();
            this.print(' ');
         }

         if (x.getUsing().size() > 0) {
            this.print0(this.ucase ? " USING (" : " using (");
            this.printAndAccept(x.getUsing(), ", ");
            this.print(')');
         }

         this.printFlashback(x.getFlashback());
      }

      OracleSelectPivotBase pivot = x.getPivot();
      if (pivot != null) {
         this.println();
         pivot.accept(this);
      }

      return false;
   }

   public boolean visit(SQLSelectOrderByItem x) {
      x.getExpr().accept(this);
      if (x.getType() != null) {
         this.print(' ');
         String typeName = x.getType().name();
         this.print0(this.ucase ? typeName.toUpperCase() : typeName.toLowerCase());
      }

      if (x.getNullsOrderType() != null) {
         this.print(' ');
         this.print0(x.getNullsOrderType().toFormalString());
      }

      return false;
   }

   public boolean visit(OracleSelectPivot x) {
      this.print0(this.ucase ? "PIVOT" : "pivot");
      if (x.isXml()) {
         this.print0(this.ucase ? " XML" : " xml");
      }

      this.print0(" (");
      this.printAndAccept(x.getItems(), ", ");
      if (x.getPivotFor().size() > 0) {
         this.print0(this.ucase ? " FOR " : " for ");
         if (x.getPivotFor().size() == 1) {
            ((SQLExpr)x.getPivotFor().get(0)).accept(this);
         } else {
            this.print('(');
            this.printAndAccept(x.getPivotFor(), ", ");
            this.print(')');
         }
      }

      if (x.getPivotIn().size() > 0) {
         this.print0(this.ucase ? " IN (" : " in (");
         this.printAndAccept(x.getPivotIn(), ", ");
         this.print(')');
      }

      this.print(')');
      return false;
   }

   public boolean visit(OracleSelectPivot.Item x) {
      x.getExpr().accept(this);
      if (x.getAlias() != null && x.getAlias().length() > 0) {
         this.print0(this.ucase ? " AS " : " as ");
         this.print0(x.getAlias());
      }

      return false;
   }

   public boolean visit(SQLSelectQueryBlock select) {
      return select instanceof OracleSelectQueryBlock ? this.visit((OracleSelectQueryBlock)select) : super.visit(select);
   }

   public boolean visit(OracleSelectQueryBlock x) {
      if (this.isPrettyFormat() && x.hasBeforeComment()) {
         this.printlnComments(x.getBeforeCommentsDirect());
      }

      this.print0(this.ucase ? "SELECT " : "select ");
      if (x.getHintsSize() > 0) {
         this.printAndAccept(x.getHints(), ", ");
         this.print(' ');
      }

      if (1 == x.getDistionOption()) {
         this.print0(this.ucase ? "ALL " : "all ");
      } else if (2 == x.getDistionOption()) {
         this.print0(this.ucase ? "DISTINCT " : "distinct ");
      } else if (3 == x.getDistionOption()) {
         this.print0(this.ucase ? "UNIQUE " : "unique ");
      }

      this.printSelectList(x.getSelectList());
      if (x.getInto() != null) {
         this.println();
         this.print0(this.ucase ? "INTO " : "into ");
         x.getInto().accept(this);
      }

      this.println();
      this.print0(this.ucase ? "FROM " : "from ");
      if (x.getFrom() == null) {
         this.print0(this.ucase ? "DUAL" : "dual");
      } else {
         x.getFrom().accept(this);
      }

      if (x.getWhere() != null) {
         this.println();
         this.print0(this.ucase ? "WHERE " : "where ");
         x.getWhere().accept(this);
      }

      this.printHierarchical(x);
      if (x.getGroupBy() != null) {
         this.println();
         x.getGroupBy().accept(this);
      }

      if (x.getModelClause() != null) {
         this.println();
         x.getModelClause().accept(this);
      }

      SQLOrderBy orderBy = x.getOrderBy();
      if (orderBy != null) {
         this.println();
         orderBy.accept(this);
      }

      this.printFetchFirst(x);
      if (x.isForUpdate()) {
         this.println();
         this.print0(this.ucase ? "FOR UPDATE" : "for update");
         if (x.getForUpdateOfSize() > 0) {
            this.print('(');
            this.printAndAccept(x.getForUpdateOf(), ", ");
            this.print(')');
         }

         if (x.isNoWait()) {
            this.print0(this.ucase ? " NOWAIT" : " nowait");
         } else if (x.isSkipLocked()) {
            this.print0(this.ucase ? " SKIP LOCKED" : " skip locked");
         } else if (x.getWaitTime() != null) {
            this.print0(this.ucase ? " WAIT " : " wait ");
            x.getWaitTime().accept(this);
         }
      }

      return false;
   }

   public boolean visit(OracleSelectRestriction.CheckOption x) {
      this.print0(this.ucase ? "CHECK OPTION" : "check option");
      if (x.getConstraint() != null) {
         this.print0(this.ucase ? " CONSTRAINT" : " constraint");
         this.print(' ');
         x.getConstraint().accept(this);
      }

      return false;
   }

   public boolean visit(OracleSelectRestriction.ReadOnly x) {
      this.print0(this.ucase ? "READ ONLY" : "read only");
      if (x.getConstraint() != null) {
         this.print0(this.ucase ? " CONSTRAINT" : " constraint");
         this.print(' ');
         x.getConstraint().accept(this);
      }

      return false;
   }

   public boolean visit(OracleSelectSubqueryTableSource x) {
      this.print('(');
      ++this.indentCount;
      this.println();
      x.getSelect().accept(this);
      --this.indentCount;
      this.println();
      this.print(')');
      OracleSelectPivotBase pivot = x.getPivot();
      if (pivot != null) {
         this.println();
         pivot.accept(this);
      }

      this.printFlashback(x.getFlashback());
      if (x.getAlias() != null && x.getAlias().length() != 0) {
         this.print(' ');
         this.print0(x.getAlias());
      }

      return false;
   }

   public boolean visit(OracleSelectTableReference x) {
      if (x.isOnly()) {
         this.print0(this.ucase ? "ONLY (" : "only (");
         this.printTableSourceExpr(x.getExpr());
         if (x.getPartition() != null) {
            this.print(' ');
            x.getPartition().accept(this);
         }

         this.print(')');
      } else {
         this.printTableSourceExpr(x.getExpr());
         if (x.getPartition() != null) {
            this.print(' ');
            x.getPartition().accept(this);
         }
      }

      if (x.getHints().size() > 0) {
         this.printHints(x.getHints());
      }

      if (x.getSampleClause() != null) {
         this.print(' ');
         x.getSampleClause().accept(this);
      }

      if (x.getPivot() != null) {
         this.println();
         x.getPivot().accept(this);
      }

      this.printFlashback(x.getFlashback());
      this.printAlias(x.getAlias());
      return false;
   }

   private void printFlashback(SQLExpr flashback) {
      if (flashback != null) {
         this.println();
         if (flashback instanceof SQLBetweenExpr) {
            flashback.accept(this);
         } else {
            this.print0(this.ucase ? "AS OF " : "as of ");
            flashback.accept(this);
         }

      }
   }

   public boolean visit(OracleSelectUnPivot x) {
      this.print0(this.ucase ? "UNPIVOT" : "unpivot");
      if (x.getNullsIncludeType() != null) {
         this.print(' ');
         this.print0(OracleSelectUnPivot.NullsIncludeType.toString(x.getNullsIncludeType(), this.ucase));
      }

      this.print0(" (");
      if (x.getItems().size() == 1) {
         ((SQLExpr)x.getItems().get(0)).accept(this);
      } else {
         this.print0(" (");
         this.printAndAccept(x.getItems(), ", ");
         this.print(')');
      }

      if (x.getPivotFor().size() > 0) {
         this.print0(this.ucase ? " FOR " : " for ");
         if (x.getPivotFor().size() == 1) {
            ((SQLExpr)x.getPivotFor().get(0)).accept(this);
         } else {
            this.print('(');
            this.printAndAccept(x.getPivotFor(), ", ");
            this.print(')');
         }
      }

      if (x.getPivotIn().size() > 0) {
         this.print0(this.ucase ? " IN (" : " in (");
         this.printAndAccept(x.getPivotIn(), ", ");
         this.print(')');
      }

      this.print(')');
      return false;
   }

   public boolean visit(OracleUpdateStatement x) {
      this.print0(this.ucase ? "UPDATE " : "update ");
      if (x.getHints().size() > 0) {
         this.printAndAccept(x.getHints(), ", ");
         this.print(' ');
      }

      if (x.isOnly()) {
         this.print0(this.ucase ? "ONLY (" : "only (");
         x.getTableSource().accept(this);
         this.print(')');
      } else {
         x.getTableSource().accept(this);
      }

      this.printAlias(x.getAlias());
      this.println();
      this.print0(this.ucase ? "SET " : "set ");
      int i = 0;

      for(int size = x.getItems().size(); i < size; ++i) {
         if (i != 0) {
            this.print0(", ");
         }

         ((SQLUpdateSetItem)x.getItems().get(i)).accept(this);
      }

      if (x.getWhere() != null) {
         this.println();
         this.print0(this.ucase ? "WHERE " : "where ");
         ++this.indentCount;
         x.getWhere().accept(this);
         --this.indentCount;
      }

      if (x.getReturning().size() > 0) {
         this.println();
         this.print0(this.ucase ? "RETURNING " : "returning ");
         this.printAndAccept(x.getReturning(), ", ");
         this.print0(this.ucase ? " INTO " : " into ");
         this.printAndAccept(x.getReturningInto(), ", ");
      }

      return false;
   }

   public boolean visit(SampleClause x) {
      this.print0(this.ucase ? "SAMPLE " : "sample ");
      if (x.isBlock()) {
         this.print0(this.ucase ? "BLOCK " : "block ");
      }

      this.print('(');
      this.printAndAccept(x.getPercent(), ", ");
      this.print(')');
      if (x.getSeedValue() != null) {
         this.print0(this.ucase ? " SEED (" : " seed (");
         x.getSeedValue().accept(this);
         this.print(')');
      }

      return false;
   }

   public boolean visit(PartitionExtensionClause x) {
      if (x.isSubPartition()) {
         this.print0(this.ucase ? "SUBPARTITION " : "subpartition ");
      } else {
         this.print0(this.ucase ? "PARTITION " : "partition ");
      }

      if (x.getPartition() != null) {
         this.print('(');
         x.getPartition().accept(this);
         this.print(')');
      } else {
         this.print0(this.ucase ? "FOR (" : "for (");
         this.printAndAccept(x.getFor(), ",");
         this.print(')');
      }

      return false;
   }

   public boolean visit(OracleWithSubqueryEntry x) {
      this.print0(x.getAlias());
      if (x.getColumns().size() > 0) {
         this.print0(" (");
         this.printAndAccept(x.getColumns(), ", ");
         this.print(')');
      }

      this.print0(this.ucase ? " AS " : " as ");
      this.print('(');
      ++this.indentCount;
      this.println();
      x.getSubQuery().accept(this);
      --this.indentCount;
      this.println();
      this.print(')');
      if (x.getSearchClause() != null) {
         this.println();
         x.getSearchClause().accept(this);
      }

      if (x.getCycleClause() != null) {
         this.println();
         x.getCycleClause().accept(this);
      }

      return false;
   }

   public boolean visit(SearchClause x) {
      this.print0(this.ucase ? "SEARCH " : "search ");
      this.print0(x.getType().name());
      this.print0(this.ucase ? " FIRST BY " : " first by ");
      this.printAndAccept(x.getItems(), ", ");
      this.print0(this.ucase ? " SET " : " set ");
      x.getOrderingColumn().accept(this);
      return false;
   }

   public boolean visit(CycleClause x) {
      this.print0(this.ucase ? "CYCLE " : "cycle ");
      this.printAndAccept(x.getAliases(), ", ");
      this.print0(this.ucase ? " SET " : " set ");
      x.getMark().accept(this);
      this.print0(this.ucase ? " TO " : " to ");
      x.getValue().accept(this);
      this.print0(this.ucase ? " DEFAULT " : " default ");
      x.getDefaultValue().accept(this);
      return false;
   }

   public boolean visit(OracleBinaryFloatExpr x) {
      this.print0(x.getValue().toString());
      this.print('F');
      return false;
   }

   public boolean visit(OracleBinaryDoubleExpr x) {
      this.print0(x.getValue().toString());
      this.print('D');
      return false;
   }

   public boolean visit(OracleIsSetExpr x) {
      x.getNestedTable().accept(this);
      this.print0(this.ucase ? " IS A SET" : " is a set");
      return false;
   }

   public boolean visit(ModelClause.ReturnRowsClause x) {
      if (x.isAll()) {
         this.print0(this.ucase ? "RETURN ALL ROWS" : "return all rows");
      } else {
         this.print0(this.ucase ? "RETURN UPDATED ROWS" : "return updated rows");
      }

      return false;
   }

   public boolean visit(ModelClause x) {
      this.print0(this.ucase ? "MODEL" : "model");
      ++this.indentCount;

      for(ModelClause.CellReferenceOption opt : x.getCellReferenceOptions()) {
         this.print(' ');
         this.print0(opt.name);
      }

      if (x.getReturnRowsClause() != null) {
         this.print(' ');
         x.getReturnRowsClause().accept(this);
      }

      for(ModelClause.ReferenceModelClause item : x.getReferenceModelClauses()) {
         this.print(' ');
         item.accept(this);
      }

      x.getMainModel().accept(this);
      --this.indentCount;
      return false;
   }

   public boolean visit(ModelClause.MainModelClause x) {
      if (x.getMainModelName() != null) {
         this.print0(this.ucase ? " MAIN " : " main ");
         x.getMainModelName().accept(this);
      }

      this.println();
      x.getModelColumnClause().accept(this);

      for(ModelClause.CellReferenceOption opt : x.getCellReferenceOptions()) {
         this.println();
         this.print0(opt.name);
      }

      this.println();
      x.getModelRulesClause().accept(this);
      return false;
   }

   public boolean visit(ModelClause.ModelColumnClause x) {
      if (x.getQueryPartitionClause() != null) {
         x.getQueryPartitionClause().accept(this);
         this.println();
      }

      this.print0(this.ucase ? "DIMENSION BY (" : "dimension by (");
      this.printAndAccept(x.getDimensionByColumns(), ", ");
      this.print(')');
      this.println();
      this.print0(this.ucase ? "MEASURES (" : "measures (");
      this.printAndAccept(x.getMeasuresColumns(), ", ");
      this.print(')');
      return false;
   }

   public boolean visit(ModelClause.QueryPartitionClause x) {
      this.print0(this.ucase ? "PARTITION BY (" : "partition by (");
      this.printAndAccept(x.getExprList(), ", ");
      this.print(')');
      return false;
   }

   public boolean visit(ModelClause.ModelColumn x) {
      x.getExpr().accept(this);
      if (x.getAlias() != null) {
         this.print(' ');
         this.print0(x.getAlias());
      }

      return false;
   }

   public boolean visit(ModelClause.ModelRulesClause x) {
      if (x.getOptions().size() > 0) {
         this.print0(this.ucase ? "RULES" : "rules");

         for(ModelClause.ModelRuleOption opt : x.getOptions()) {
            this.print(' ');
            this.print0(opt.name);
         }
      }

      if (x.getIterate() != null) {
         this.print0(this.ucase ? " ITERATE (" : " iterate (");
         x.getIterate().accept(this);
         this.print(')');
         if (x.getUntil() != null) {
            this.print0(this.ucase ? " UNTIL (" : " until (");
            x.getUntil().accept(this);
            this.print(')');
         }
      }

      this.print0(" (");
      this.printAndAccept(x.getCellAssignmentItems(), ", ");
      this.print(')');
      return false;
   }

   public boolean visit(ModelClause.CellAssignmentItem x) {
      if (x.getOption() != null) {
         this.print0(x.getOption().name);
         this.print(' ');
      }

      x.getCellAssignment().accept(this);
      if (x.getOrderBy() != null) {
         this.print(' ');
         x.getOrderBy().accept(this);
      }

      this.print0(" = ");
      x.getExpr().accept(this);
      return false;
   }

   public boolean visit(ModelClause.CellAssignment x) {
      x.getMeasureColumn().accept(this);
      this.print0("[");
      this.printAndAccept(x.getConditions(), ", ");
      this.print0("]");
      return false;
   }

   public boolean visit(OracleReturningClause x) {
      this.print0(this.ucase ? "RETURNING " : "returning ");
      this.printAndAccept(x.getItems(), ", ");
      this.print0(this.ucase ? " INTO " : " into ");
      this.printAndAccept(x.getValues(), ", ");
      return false;
   }

   public boolean visit(OracleInsertStatement x) {
      this.print0(this.ucase ? "INSERT " : "insert ");
      if (x.getHints().size() > 0) {
         this.printAndAccept(x.getHints(), ", ");
         this.print(' ');
      }

      this.print0(this.ucase ? "INTO " : "into ");
      if (x.getSelect() != null) {
         x.getSelect().accept(this);
      }

      if (x.getTableSource() != null) {
         x.getTableSource().accept(this);
      }

      this.printInsertColumns(x.getColumns());
      if (x.getValues() != null) {
         this.println();
         this.print0(this.ucase ? "VALUES " : "values ");
         x.getValues().accept(this);
      } else if (x.getQuery() != null) {
         this.println();
         x.getQuery().accept(this);
      }

      if (x.getReturning() != null) {
         this.println();
         x.getReturning().accept(this);
      }

      if (x.getErrorLogging() != null) {
         this.println();
         x.getErrorLogging().accept(this);
      }

      return false;
   }

   public boolean visit(OracleMultiInsertStatement.InsertIntoClause x) {
      this.print0(this.ucase ? "INTO " : "into ");
      x.getTableSource().accept(this);
      if (x.getColumns().size() > 0) {
         ++this.indentCount;
         this.println();
         this.print('(');
         int i = 0;

         for(int size = x.getColumns().size(); i < size; ++i) {
            if (i != 0) {
               if (i % 5 == 0) {
                  this.println();
               }

               this.print0(", ");
            }

            ((SQLExpr)x.getColumns().get(i)).accept(this);
         }

         this.print(')');
         --this.indentCount;
      }

      if (x.getValues() != null) {
         this.println();
         this.print0(this.ucase ? "VALUES " : "values ");
         x.getValues().accept(this);
      } else if (x.getQuery() != null) {
         this.println();
         x.getQuery().accept(this);
      }

      return false;
   }

   public boolean visit(OracleMultiInsertStatement x) {
      this.print0(this.ucase ? "INSERT " : "insert ");
      if (x.getHints().size() > 0) {
         this.printHints(x.getHints());
      }

      if (x.getOption() != null) {
         this.print0(x.getOption().name());
         this.print(' ');
      }

      int i = 0;

      for(int size = x.getEntries().size(); i < size; ++i) {
         ++this.indentCount;
         this.println();
         ((OracleMultiInsertStatement.Entry)x.getEntries().get(i)).accept(this);
         --this.indentCount;
      }

      this.println();
      x.getSubQuery().accept(this);
      return false;
   }

   public boolean visit(OracleMultiInsertStatement.ConditionalInsertClause x) {
      int i = 0;

      for(int size = x.getItems().size(); i < size; ++i) {
         if (i != 0) {
            this.println();
         }

         OracleMultiInsertStatement.ConditionalInsertClauseItem item = (OracleMultiInsertStatement.ConditionalInsertClauseItem)x.getItems().get(i);
         item.accept(this);
      }

      if (x.getElseItem() != null) {
         this.println();
         this.print0(this.ucase ? "ELSE" : "else");
         ++this.indentCount;
         this.println();
         x.getElseItem().accept(this);
         --this.indentCount;
      }

      return false;
   }

   public boolean visit(OracleMultiInsertStatement.ConditionalInsertClauseItem x) {
      this.print0(this.ucase ? "WHEN " : "when ");
      x.getWhen().accept(this);
      this.print0(this.ucase ? " THEN" : " then");
      ++this.indentCount;
      this.println();
      x.getThen().accept(this);
      --this.indentCount;
      return false;
   }

   public boolean visit(OracleLockTableStatement x) {
      this.print0(this.ucase ? "LOCK TABLE " : "lock table ");
      x.getTable().accept(this);
      if (x.getPartition() != null) {
         this.print0(" PARTITION (");
         x.getPartition().accept(this);
         this.print0(") ");
      }

      this.print0(this.ucase ? " IN " : " in ");
      this.print0(x.getLockMode().toString());
      this.print0(this.ucase ? " MODE " : " mode ");
      if (x.isNoWait()) {
         this.print0(this.ucase ? "NOWAIT" : "nowait");
      } else if (x.getWait() != null) {
         this.print0(this.ucase ? "WAIT " : "wait ");
         x.getWait().accept(this);
      }

      return false;
   }

   public boolean visit(OracleAlterSessionStatement x) {
      this.print0(this.ucase ? "ALTER SESSION SET " : "alter session set ");
      this.printAndAccept(x.getItems(), ", ");
      return false;
   }

   public boolean visit(OracleDatetimeExpr x) {
      x.getExpr().accept(this);
      SQLExpr timeZone = x.getTimeZone();
      if (timeZone instanceof SQLIdentifierExpr && ((SQLIdentifierExpr)timeZone).getName().equalsIgnoreCase("LOCAL")) {
         this.print0(this.ucase ? " AT LOCAL" : "alter session set ");
         return false;
      } else {
         this.print0(this.ucase ? " AT TIME ZONE " : " at time zone ");
         timeZone.accept(this);
         return false;
      }
   }

   public boolean visit(OracleSysdateExpr x) {
      this.print0(this.ucase ? "SYSDATE" : "sysdate");
      if (x.getOption() != null) {
         this.print('@');
         this.print0(x.getOption());
      }

      return false;
   }

   public boolean visit(OracleExceptionStatement.Item x) {
      this.print0(this.ucase ? "WHEN " : "when ");
      x.getWhen().accept(this);
      this.print0(this.ucase ? " THEN" : " then");
      ++this.indentCount;
      if (x.getStatements().size() > 1) {
         this.println();
      } else if (x.getStatements().size() == 1 && x.getStatements().get(0) instanceof SQLIfStatement) {
         this.println();
      } else {
         this.print(' ');
      }

      int i = 0;

      for(int size = x.getStatements().size(); i < size; ++i) {
         if (i != 0 && size > 1) {
            this.println();
         }

         SQLStatement stmt = (SQLStatement)x.getStatements().get(i);
         stmt.accept(this);
      }

      --this.indentCount;
      return false;
   }

   public boolean visit(OracleExceptionStatement x) {
      this.print0(this.ucase ? "EXCEPTION" : "exception");
      ++this.indentCount;
      List<OracleExceptionStatement.Item> items = x.getItems();
      int i = 0;

      for(int size = items.size(); i < size; ++i) {
         this.println();
         OracleExceptionStatement.Item item = (OracleExceptionStatement.Item)items.get(i);
         item.accept(this);
      }

      --this.indentCount;
      return false;
   }

   public boolean visit(OracleArgumentExpr x) {
      this.print0(x.getArgumentName());
      this.print0(" => ");
      x.getValue().accept(this);
      return false;
   }

   public boolean visit(OracleSetTransactionStatement x) {
      if (x.isReadOnly()) {
         this.print0(this.ucase ? "SET TRANSACTION READ ONLY" : "set transaction read only");
      } else {
         this.print0(this.ucase ? "SET TRANSACTION" : "set transaction");
      }

      SQLExpr name = x.getName();
      if (name != null) {
         this.print0(this.ucase ? " NAME " : " name ");
         name.accept(this);
      }

      return false;
   }

   public boolean visit(OracleExplainStatement x) {
      this.print0(this.ucase ? "EXPLAIN PLAN" : "explain plan");
      ++this.indentCount;
      this.println();
      if (x.getStatementId() != null) {
         this.print0(this.ucase ? "SET STATEMENT_ID = " : "set statement_id = ");
         x.getStatementId().accept(this);
         this.println();
      }

      if (x.getInto() != null) {
         this.print0(this.ucase ? "INTO " : "into ");
         x.getInto().accept(this);
         this.println();
      }

      this.print0(this.ucase ? "FOR" : "for");
      this.println();
      x.getStatement().accept(this);
      --this.indentCount;
      return false;
   }

   public boolean visit(SQLAlterProcedureStatement x) {
      this.print0(this.ucase ? "ALTER PROCEDURE " : "alter procedure ");
      x.getName().accept(this);
      if (x.isCompile()) {
         this.print0(this.ucase ? " COMPILE" : " compile");
      }

      if (x.isReuseSettings()) {
         this.print0(this.ucase ? " REUSE SETTINGS" : " reuse settings");
      }

      return false;
   }

   public boolean visit(OracleAlterTableDropPartition x) {
      this.print0(this.ucase ? "DROP PARTITION " : "drop partition ");
      x.getName().accept(this);
      return false;
   }

   public boolean visit(SQLAlterTableStatement x) {
      if (x.getItems().size() == 1) {
         SQLAlterTableItem item = (SQLAlterTableItem)x.getItems().get(0);
         if (item instanceof SQLAlterTableRename) {
            SQLExpr to = ((SQLAlterTableRename)item).getTo().getExpr();
            this.print0(this.ucase ? "RENAME " : "rename ");
            x.getName().accept(this);
            this.print0(this.ucase ? " TO " : " to ");
            to.accept(this);
            return false;
         }
      }

      this.print0(this.ucase ? "ALTER TABLE " : "alter table ");
      this.printTableSourceExpr(x.getName());
      ++this.indentCount;

      for(SQLAlterTableItem item : x.getItems()) {
         this.println();
         item.accept(this);
      }

      if (x.isUpdateGlobalIndexes()) {
         this.println();
         this.print0(this.ucase ? "UPDATE GLOABL INDEXES" : "update gloabl indexes");
      }

      --this.indentCount;
      return false;
   }

   public boolean visit(OracleAlterTableTruncatePartition x) {
      this.print0(this.ucase ? "TRUNCATE PARTITION " : "truncate partition ");
      x.getName().accept(this);
      return false;
   }

   public boolean visit(OracleAlterTableSplitPartition.TableSpaceItem x) {
      this.print0(this.ucase ? "TABLESPACE " : "tablespace ");
      x.getTablespace().accept(this);
      return false;
   }

   public boolean visit(OracleAlterTableSplitPartition.UpdateIndexesClause x) {
      this.print0(this.ucase ? "UPDATE INDEXES" : "update indexes");
      if (x.getItems().size() > 0) {
         this.print('(');
         this.printAndAccept(x.getItems(), ", ");
         this.print(')');
      }

      return false;
   }

   public boolean visit(OracleAlterTableSplitPartition x) {
      this.print0(this.ucase ? "SPLIT PARTITION " : "split partition ");
      x.getName().accept(this);
      if (x.getAt().size() > 0) {
         ++this.indentCount;
         this.println();
         this.print0(this.ucase ? "AT (" : "at (");
         this.printAndAccept(x.getAt(), ", ");
         this.print(')');
         --this.indentCount;
      }

      if (x.getInto().size() > 0) {
         this.println();
         ++this.indentCount;
         this.print0(this.ucase ? "INTO (" : "into (");
         this.printAndAccept(x.getInto(), ", ");
         this.print(')');
         --this.indentCount;
      }

      if (x.getUpdateIndexes() != null) {
         this.println();
         ++this.indentCount;
         x.getUpdateIndexes().accept(this);
         --this.indentCount;
      }

      return false;
   }

   public boolean visit(OracleAlterTableSplitPartition.NestedTablePartitionSpec x) {
      this.print0(this.ucase ? "PARTITION " : "partition ");
      x.getPartition().accept(this);

      for(SQLObject item : x.getSegmentAttributeItems()) {
         this.print(' ');
         item.accept(this);
      }

      return false;
   }

   public boolean visit(OracleAlterTableModify x) {
      this.print0(this.ucase ? "MODIFY (" : "modify (");
      ++this.indentCount;
      int i = 0;

      for(int size = x.getColumns().size(); i < size; ++i) {
         this.println();
         SQLColumnDefinition column = (SQLColumnDefinition)x.getColumns().get(i);
         column.accept(this);
         if (i != size - 1) {
            this.print0(", ");
         }
      }

      --this.indentCount;
      this.println();
      this.print(')');
      return false;
   }

   public boolean visit(OracleCreateIndexStatement x) {
      this.print0(this.ucase ? "CREATE " : "create ");
      if (x.getType() != null) {
         this.print0(x.getType());
         this.print(' ');
      }

      this.print0(this.ucase ? "INDEX " : "index ");
      x.getName().accept(this);
      this.print0(this.ucase ? " ON " : " on ");
      if (x.isCluster()) {
         this.print0(this.ucase ? "CLUSTER " : "cluster ");
      }

      x.getTable().accept(this);
      List<SQLSelectOrderByItem> items = x.getItems();
      if (items.size() > 0) {
         this.print('(');
         this.printAndAccept(items, ", ");
         this.print(')');
      }

      if (x.isIndexOnlyTopLevel()) {
         this.println();
         this.print0(this.ucase ? "INDEX ONLY TOPLEVEL" : "index only toplevel");
      }

      if (x.isComputeStatistics()) {
         this.println();
         this.print0(this.ucase ? "COMPUTE STATISTICS" : "compute statistics");
      }

      if (x.isReverse()) {
         this.println();
         this.print0(this.ucase ? "REVERSE" : "reverse");
      }

      this.printOracleSegmentAttributes(x);
      if (x.isOnline()) {
         this.print0(this.ucase ? " ONLINE" : " online");
      }

      if (x.isNoParallel()) {
         this.print0(this.ucase ? " NOPARALLEL" : " noparallel");
      } else if (x.getParallel() != null) {
         this.print0(this.ucase ? " PARALLEL " : " parallel ");
         x.getParallel().accept(this);
      }

      Boolean sort = x.getSort();
      if (sort != null) {
         if (sort) {
            this.print0(this.ucase ? " SORT" : " sort");
         } else {
            this.print0(this.ucase ? " NOSORT" : " nosort");
         }
      }

      if (x.getLocalPartitions().size() > 0) {
         this.println();
         this.print0(this.ucase ? "LOCAL (" : "local (");
         ++this.indentCount;
         this.println();
         this.printlnAndAccept(x.getLocalPartitions(), ",");
         --this.indentCount;
         this.println();
         this.print(')');
      } else if (x.isLocal()) {
         this.print0(this.ucase ? " LOCAL" : " local");
      }

      List<SQLName> localStoreIn = x.getLocalStoreIn();
      if (localStoreIn.size() > 0) {
         this.print0(this.ucase ? " STORE IN (" : " store in (");
         this.printAndAccept(localStoreIn, ", ");
         this.print(')');
      }

      List<SQLPartitionBy> globalPartitions = x.getGlobalPartitions();
      if (globalPartitions.size() > 0) {
         for(SQLPartitionBy globalPartition : globalPartitions) {
            this.println();
            this.print0(this.ucase ? "GLOBAL " : "global ");
            this.print0(this.ucase ? "PARTITION BY " : "partition by ");
            globalPartition.accept(this);
         }
      } else if (x.isGlobal()) {
         this.print0(this.ucase ? " GLOBAL" : " global");
      }

      return false;
   }

   public boolean visit(OracleForStatement x) {
      boolean all = x.isAll();
      if (all) {
         this.print0(this.ucase ? "FORALL " : "forall ");
      } else {
         this.print0(this.ucase ? "FOR " : "for ");
      }

      x.getIndex().accept(this);
      this.print0(this.ucase ? " IN " : " in ");
      SQLExpr range = x.getRange();
      range.accept(this);
      if (!all) {
         this.println();
         this.print0(this.ucase ? "LOOP" : "loop");
      }

      ++this.indentCount;
      this.println();
      int i = 0;

      for(int size = x.getStatements().size(); i < size; ++i) {
         SQLStatement stmt = (SQLStatement)x.getStatements().get(i);
         stmt.accept(this);
         if (!all && i != size - 1) {
            this.println();
         }
      }

      --this.indentCount;
      if (!all) {
         this.println();
         this.print0(this.ucase ? "END LOOP" : "end loop");
         SQLName endLabel = x.getEndLabel();
         if (endLabel != null) {
            this.print(' ');
            endLabel.accept(this);
         }
      }

      return false;
   }

   public boolean visit(SQLIfStatement.Else x) {
      this.print0(this.ucase ? "ELSE" : "else");
      ++this.indentCount;
      this.println();
      int i = 0;

      for(int size = x.getStatements().size(); i < size; ++i) {
         if (i != 0) {
            this.println();
         }

         SQLStatement item = (SQLStatement)x.getStatements().get(i);
         item.accept(this);
      }

      --this.indentCount;
      return false;
   }

   public boolean visit(SQLIfStatement.ElseIf x) {
      this.print0(this.ucase ? "ELSE IF " : "else if ");
      x.getCondition().accept(this);
      this.print0(this.ucase ? " THEN" : " then");
      ++this.indentCount;
      int i = 0;

      for(int size = x.getStatements().size(); i < size; ++i) {
         this.println();
         SQLStatement item = (SQLStatement)x.getStatements().get(i);
         item.accept(this);
      }

      --this.indentCount;
      return false;
   }

   public boolean visit(SQLIfStatement x) {
      this.print0(this.ucase ? "IF " : "if ");
      int lines = this.lines;
      ++this.indentCount;
      x.getCondition().accept(this);
      --this.indentCount;
      if (lines != this.lines) {
         this.println();
      } else {
         this.print(' ');
      }

      this.print0(this.ucase ? "THEN" : "then");
      ++this.indentCount;
      int i = 0;

      for(int size = x.getStatements().size(); i < size; ++i) {
         this.println();
         SQLStatement item = (SQLStatement)x.getStatements().get(i);
         item.accept(this);
      }

      --this.indentCount;

      for(SQLIfStatement.ElseIf elseIf : x.getElseIfList()) {
         this.println();
         elseIf.accept(this);
      }

      if (x.getElseItem() != null) {
         this.println();
         x.getElseItem().accept(this);
      }

      this.println();
      this.print0(this.ucase ? "END IF" : "end if");
      return false;
   }

   public boolean visit(OracleRangeExpr x) {
      x.getLowBound().accept(this);
      this.print0("..");
      x.getUpBound().accept(this);
      return false;
   }

   protected void visitColumnDefault(SQLColumnDefinition x) {
      if (x.getParent() instanceof SQLBlockStatement) {
         this.print0(" := ");
      } else {
         this.print0(this.ucase ? " DEFAULT " : " default ");
      }

      this.printExpr(x.getDefaultExpr(), false);
   }

   public boolean visit(OraclePrimaryKey x) {
      if (x.getName() != null) {
         this.print0(this.ucase ? "CONSTRAINT " : "constraint ");
         x.getName().accept(this);
         this.print(' ');
      }

      this.print0(this.ucase ? "PRIMARY KEY (" : "primary key (");
      this.printAndAccept(x.getColumns(), ", ");
      this.print(')');
      Boolean rely = x.getRely();
      if (rely != null && rely) {
         this.print0(this.ucase ? " RELY" : " rely");
      }

      this.printConstraintState(x);
      Boolean validate = x.getValidate();
      if (validate != null) {
         if (validate) {
            this.print0(this.ucase ? " VALIDATE" : " validate");
         } else {
            this.print0(this.ucase ? " NOVALIDATE" : " novalidate");
         }
      }

      return false;
   }

   protected void printConstraintState(OracleConstraint x) {
      ++this.indentCount;
      if (x.getUsing() != null) {
         this.println();
         x.getUsing().accept(this);
      }

      if (x.getExceptionsInto() != null) {
         this.println();
         this.print0(this.ucase ? "EXCEPTIONS INTO " : "exceptions into ");
         x.getExceptionsInto().accept(this);
      }

      Boolean enable = x.getEnable();
      if (enable != null) {
         if (enable) {
            this.print0(this.ucase ? " ENABLE" : " enable");
         } else {
            this.print0(this.ucase ? " DISABLE" : " disable");
         }
      }

      if (x.getInitially() != null) {
         this.print0(this.ucase ? " INITIALLY " : " initially ");
         this.print0(x.getInitially().name());
      }

      if (x.getDeferrable() != null) {
         if (x.getDeferrable()) {
            this.print0(this.ucase ? " DEFERRABLE" : " deferrable");
         } else {
            this.print0(this.ucase ? " NOT DEFERRABLE" : " not deferrable");
         }
      }

      --this.indentCount;
   }

   public boolean visit(OracleCreateTableStatement x) {
      this.printCreateTable(x, false);
      if (x.getOf() != null) {
         this.println();
         this.print0(this.ucase ? "OF " : "of ");
         x.getOf().accept(this);
      }

      OracleCreateTableStatement.OIDIndex oidIndex = x.getOidIndex();
      if (oidIndex != null) {
         this.println();
         oidIndex.accept(this);
      }

      OracleCreateTableStatement.Organization organization = x.getOrganization();
      if (organization != null) {
         this.println();
         ++this.indentCount;
         organization.accept(this);
         --this.indentCount;
      }

      if (x.getIncluding().size() > 0) {
         this.print0(this.ucase ? " INCLUDING " : " including ");
         this.printAndAccept(x.getIncluding(), ", ");
         this.print0(this.ucase ? " OVERFLOW " : " overflow ");
      }

      this.printOracleSegmentAttributes(x);
      if (x.isInMemoryMetadata()) {
         this.println();
         this.print0(this.ucase ? "IN_MEMORY_METADATA" : "in_memory_metadata");
      }

      if (x.isCursorSpecificSegment()) {
         this.println();
         this.print0(this.ucase ? "CURSOR_SPECIFIC_SEGMENT" : "cursor_specific_segment");
      }

      if (x.getParallel() == Boolean.TRUE) {
         this.println();
         this.print0(this.ucase ? "PARALLEL" : "parallel");
         SQLExpr parallelValue = x.getParallelValue();
         if (parallelValue != null) {
            this.print(' ');
            this.printExpr(parallelValue);
         }
      } else if (x.getParallel() == Boolean.FALSE) {
         this.println();
         this.print0(this.ucase ? "NOPARALLEL" : "noparallel");
      }

      if (x.getCache() == Boolean.TRUE) {
         this.println();
         this.print0(this.ucase ? "CACHE" : "cache");
      } else if (x.getCache() == Boolean.FALSE) {
         this.println();
         this.print0(this.ucase ? "NOCACHE" : "nocache");
      }

      if (x.getLobStorage() != null) {
         this.println();
         x.getLobStorage().accept(this);
      }

      if (x.isOnCommitPreserveRows()) {
         this.println();
         this.print0(this.ucase ? "ON COMMIT PRESERVE ROWS" : "on commit preserve rows");
      } else if (x.isOnCommitDeleteRows()) {
         this.println();
         this.print0(this.ucase ? "ON COMMIT DELETE ROWS" : "on commit delete rows");
      }

      if (x.isMonitoring()) {
         this.println();
         this.print0(this.ucase ? "MONITORING" : "monitoring");
      }

      if (x.getPartitioning() != null) {
         this.println();
         this.print0(this.ucase ? "PARTITION BY " : "partition by ");
         x.getPartitioning().accept(this);
      }

      if (x.getCluster() != null) {
         this.println();
         this.print0(this.ucase ? "CLUSTER " : "cluster ");
         x.getCluster().accept(this);
         this.print0(" (");
         this.printAndAccept(x.getClusterColumns(), ",");
         this.print0(")");
      }

      OracleXmlColumnProperties xmlTypeColumnProperties = x.getXmlTypeColumnProperties();
      if (xmlTypeColumnProperties != null) {
         this.println();
         xmlTypeColumnProperties.accept(this);
      }

      SQLSelect select = x.getSelect();
      if (select != null) {
         this.println();
         this.print0(this.ucase ? "AS" : "as");
         this.println();
         select.accept(this);
      }

      return false;
   }

   public boolean visit(OracleStorageClause x) {
      this.print0(this.ucase ? "STORAGE (" : "storage (");
      ++this.indentCount;
      SQLExpr initial = x.getInitial();
      if (initial != null) {
         this.println();
         this.print0(this.ucase ? "INITIAL " : "initial ");
         this.printExpr(initial, false);
      }

      SQLExpr next = x.getNext();
      if (next != null) {
         this.println();
         this.print0(this.ucase ? "NEXT " : "next ");
         this.printExpr(next, false);
      }

      SQLExpr minExtents = x.getMinExtents();
      if (minExtents != null) {
         this.println();
         this.print0(this.ucase ? "MINEXTENTS " : "minextents ");
         this.printExpr(minExtents, false);
      }

      SQLExpr maxExtents = x.getMaxExtents();
      if (maxExtents != null) {
         this.println();
         this.print0(this.ucase ? "MAXEXTENTS " : "maxextents ");
         this.printExpr(maxExtents, false);
      }

      SQLExpr pctIncrease = x.getPctIncrease();
      if (pctIncrease != null) {
         this.println();
         this.print0(this.ucase ? "PCTINCREASE " : "pctincrease ");
         this.printExpr(pctIncrease, false);
      }

      SQLExpr maxSize = x.getMaxSize();
      if (maxSize != null) {
         this.println();
         this.print0(this.ucase ? "MAXSIZE " : "maxsize ");
         this.printExpr(maxSize, false);
      }

      SQLExpr freeLists = x.getFreeLists();
      if (freeLists != null) {
         this.println();
         this.print0(this.ucase ? "FREELISTS " : "freelists ");
         this.printExpr(freeLists, false);
      }

      SQLExpr freeListGroups = x.getFreeListGroups();
      if (freeListGroups != null) {
         this.println();
         this.print0(this.ucase ? "FREELIST GROUPS " : "freelist groups ");
         this.printExpr(freeListGroups, false);
      }

      SQLExpr bufferPool = x.getBufferPool();
      if (bufferPool != null) {
         this.println();
         this.print0(this.ucase ? "BUFFER_POOL " : "buffer_pool ");
         this.printExpr(bufferPool, false);
      }

      SQLExpr objno = x.getObjno();
      if (objno != null) {
         this.println();
         this.print0(this.ucase ? "OBJNO " : "objno ");
         this.printExpr(objno, false);
      }

      if (x.getFlashCache() != null) {
         this.println();
         this.print0(this.ucase ? "FLASH_CACHE " : "flash_cache ");
         this.print0(this.ucase ? x.getFlashCache().name() : x.getFlashCache().name().toLowerCase());
      }

      if (x.getCellFlashCache() != null) {
         this.println();
         this.print0(this.ucase ? "CELL_FLASH_CACHE " : "cell_flash_cache ");
         this.print0(this.ucase ? x.getCellFlashCache().name() : x.getCellFlashCache().name().toLowerCase());
      }

      --this.indentCount;
      this.println();
      this.print(')');
      return false;
   }

   public boolean visit(OracleGotoStatement x) {
      this.print0(this.ucase ? "GOTO " : "GOTO ");
      x.getLabel().accept(this);
      return false;
   }

   public boolean visit(OracleLabelStatement x) {
      this.print0("<<");
      x.getLabel().accept(this);
      this.print0(">>");
      return false;
   }

   public boolean visit(OracleAlterTriggerStatement x) {
      this.print0(this.ucase ? "ALTER TRIGGER " : "alter trigger ");
      x.getName().accept(this);
      if (x.isCompile()) {
         this.print0(this.ucase ? " COMPILE" : " compile");
      }

      if (x.getEnable() != null) {
         if (x.getEnable()) {
            this.print0(this.ucase ? "ENABLE" : "enable");
         } else {
            this.print0(this.ucase ? "DISABLE" : "disable");
         }
      }

      return false;
   }

   public boolean visit(OracleAlterSynonymStatement x) {
      this.print0(this.ucase ? "ALTER SYNONYM " : "alter synonym ");
      x.getName().accept(this);
      if (x.isCompile()) {
         this.print0(this.ucase ? " COMPILE" : " compile");
      }

      if (x.getEnable() != null) {
         if (x.getEnable()) {
            this.print0(this.ucase ? "ENABLE" : "enable");
         } else {
            this.print0(this.ucase ? "DISABLE" : "disable");
         }
      }

      return false;
   }

   public boolean visit(OracleAlterViewStatement x) {
      this.print0(this.ucase ? "ALTER VIEW " : "alter view ");
      x.getName().accept(this);
      if (x.isCompile()) {
         this.print0(this.ucase ? " COMPILE" : " compile");
      }

      if (x.getEnable() != null) {
         if (x.getEnable()) {
            this.print0(this.ucase ? "ENABLE" : "enable");
         } else {
            this.print0(this.ucase ? "DISABLE" : "disable");
         }
      }

      return false;
   }

   public boolean visit(OracleAlterTableMoveTablespace x) {
      this.print0(this.ucase ? " MOVE TABLESPACE " : " move tablespace ");
      x.getName().accept(this);
      return false;
   }

   public boolean visit(OracleFileSpecification x) {
      this.printAndAccept(x.getFileNames(), ", ");
      if (x.getSize() != null) {
         this.print0(this.ucase ? " SIZE " : " size ");
         x.getSize().accept(this);
      }

      if (x.isAutoExtendOff()) {
         this.print0(this.ucase ? " AUTOEXTEND OFF" : " autoextend off");
      } else if (x.getAutoExtendOn() != null) {
         this.print0(this.ucase ? " AUTOEXTEND ON " : " autoextend on ");
         x.getAutoExtendOn().accept(this);
      }

      return false;
   }

   public boolean visit(OracleAlterTablespaceAddDataFile x) {
      this.print0(this.ucase ? "ADD DATAFILE" : "add datafile");
      ++this.indentCount;

      for(OracleFileSpecification file : x.getFiles()) {
         this.println();
         file.accept(this);
      }

      --this.indentCount;
      return false;
   }

   public boolean visit(OracleAlterTablespaceStatement x) {
      this.print0(this.ucase ? "ALTER TABLESPACE " : "alter tablespace ");
      x.getName().accept(this);
      this.println();
      x.getItem().accept(this);
      return false;
   }

   public boolean visit(SQLTruncateStatement x) {
      this.print0(this.ucase ? "TRUNCATE TABLE " : "truncate table ");
      this.printAndAccept(x.getTableSources(), ", ");
      if (x.isPurgeSnapshotLog()) {
         this.print0(this.ucase ? " PURGE SNAPSHOT LOG" : " purge snapshot log");
      }

      return false;
   }

   public boolean visit(OracleExitStatement x) {
      this.print0(this.ucase ? "EXIT" : "exit");
      if (x.getLabel() != null) {
         this.print(' ');
         this.print0(x.getLabel());
      }

      if (x.getWhen() != null) {
         this.print0(this.ucase ? " WHEN " : " when ");
         x.getWhen().accept(this);
      }

      return false;
   }

   public boolean visit(OracleContinueStatement x) {
      this.print0(this.ucase ? "CONTINUE" : "continue");
      String label = x.getLabel();
      if (label != null) {
         this.print(' ');
         this.print0(label);
      }

      if (x.getWhen() != null) {
         this.print0(this.ucase ? " WHEN " : " when ");
         x.getWhen().accept(this);
      }

      return false;
   }

   public boolean visit(OracleRaiseStatement x) {
      this.print0(this.ucase ? "RAISE" : "raise");
      if (x.getException() != null) {
         this.print(' ');
         x.getException().accept(this);
      }

      this.print(';');
      return false;
   }

   public boolean visit(SQLSavePointStatement x) {
      this.print0(this.ucase ? "SAVEPOINT" : "savepoint");
      if (x.getName() != null) {
         this.print0(this.ucase ? " TO " : " to ");
         x.getName().accept(this);
      }

      return false;
   }

   public boolean visit(SQLCreateFunctionStatement x) {
      boolean create = x.isCreate();
      if (!create) {
         this.print0(this.ucase ? "FUNCTION " : "function ");
      } else if (x.isOrReplace()) {
         this.print0(this.ucase ? "CREATE OR REPLACE FUNCTION " : "create or replace function ");
      } else {
         this.print0(this.ucase ? "CREATE FUNCTION " : "create function ");
      }

      x.getName().accept(this);
      int paramSize = x.getParameters().size();
      if (paramSize > 0) {
         this.print0(" (");
         ++this.indentCount;
         this.println();

         for(int i = 0; i < paramSize; ++i) {
            if (i != 0) {
               this.print0(", ");
               this.println();
            }

            SQLParameter param = (SQLParameter)x.getParameters().get(i);
            param.accept(this);
         }

         --this.indentCount;
         this.println();
         this.print(')');
      }

      String wrappedSource = x.getWrappedSource();
      if (wrappedSource != null) {
         this.print0(this.ucase ? " WRAPPED " : " wrapped ");
         this.print0(wrappedSource);
         if (x.isAfterSemi()) {
            this.print(';');
         }

         return false;
      } else {
         this.println();
         this.print(this.ucase ? "RETURN " : "return ");
         x.getReturnDataType().accept(this);
         if (x.isPipelined()) {
            this.print(this.ucase ? "PIPELINED " : "pipelined ");
         }

         if (x.isDeterministic()) {
            this.print(this.ucase ? "DETERMINISTIC " : "deterministic ");
         }

         SQLName authid = x.getAuthid();
         if (authid != null) {
            this.print(this.ucase ? " AUTHID " : " authid ");
            authid.accept(this);
         }

         SQLStatement block = x.getBlock();
         if (block != null && !create) {
            this.println();
            this.println("IS");
         } else {
            this.println();
            if (block instanceof SQLBlockStatement) {
               SQLBlockStatement blockStatement = (SQLBlockStatement)block;
               if (blockStatement.getParameters().size() > 0 || authid != null) {
                  this.println(this.ucase ? "AS" : "as");
               }
            }
         }

         String javaCallSpec = x.getJavaCallSpec();
         if (javaCallSpec != null) {
            this.print0(this.ucase ? "LANGUAGE JAVA NAME '" : "language java name '");
            this.print0(javaCallSpec);
            this.print('\'');
            return false;
         } else {
            if (x.isParallelEnable()) {
               this.print0(this.ucase ? "PARALLEL_ENABLE" : "parallel_enable");
               this.println();
            }

            if (x.isAggregate()) {
               this.print0(this.ucase ? "AGGREGATE" : "aggregate");
               this.println();
            }

            SQLName using = x.getUsing();
            if (using != null) {
               this.print0(this.ucase ? "USING " : "using ");
               using.accept(this);
            }

            if (block != null) {
               block.accept(this);
            }

            return false;
         }
      }
   }

   public boolean visit(OracleCreateDatabaseDbLinkStatement x) {
      this.print0(this.ucase ? "CREATE " : "create ");
      if (x.isShared()) {
         this.print0(this.ucase ? "SHARE " : "share ");
      }

      if (x.isPublic()) {
         this.print0(this.ucase ? "PUBLIC " : "public ");
      }

      this.print0(this.ucase ? "DATABASE LINK " : "database link ");
      x.getName().accept(this);
      if (x.getUser() != null) {
         this.print0(this.ucase ? " CONNECT TO " : " connect to ");
         x.getUser().accept(this);
         if (x.getPassword() != null) {
            this.print0(this.ucase ? " IDENTIFIED BY " : " identified by ");
            this.print0(x.getPassword());
         }
      }

      if (x.getAuthenticatedUser() != null) {
         this.print0(this.ucase ? " AUTHENTICATED BY " : " authenticated by ");
         x.getAuthenticatedUser().accept(this);
         if (x.getAuthenticatedPassword() != null) {
            this.print0(this.ucase ? " IDENTIFIED BY " : " identified by ");
            this.print0(x.getAuthenticatedPassword());
         }
      }

      if (x.getUsing() != null) {
         this.print0(this.ucase ? " USING " : " using ");
         x.getUsing().accept(this);
      }

      return false;
   }

   public boolean visit(OracleDropDbLinkStatement x) {
      this.print0(this.ucase ? "DROP " : "drop ");
      if (x.isPublic()) {
         this.print0(this.ucase ? "PUBLIC " : "public ");
      }

      this.print0(this.ucase ? "DATABASE LINK " : "database link ");
      x.getName().accept(this);
      return false;
   }

   public boolean visit(SQLCharacterDataType x) {
      this.print0(x.getName());
      List<SQLExpr> arguments = x.getArguments();
      if (arguments.size() > 0) {
         this.print('(');
         SQLExpr arg0 = (SQLExpr)arguments.get(0);
         this.printExpr(arg0, false);
         if (x.getCharType() != null) {
            this.print(' ');
            this.print0(x.getCharType());
         }

         this.print(')');
      }

      return false;
   }

   public boolean visit(OracleDataTypeIntervalYear x) {
      this.print0(x.getName());
      if (x.getArguments().size() > 0) {
         this.print('(');
         ((SQLExpr)x.getArguments().get(0)).accept(this);
         this.print(')');
      }

      this.print0(this.ucase ? " TO MONTH" : " to month");
      return false;
   }

   public boolean visit(OracleDataTypeIntervalDay x) {
      this.print0(x.getName());
      if (x.getArguments().size() > 0) {
         this.print('(');
         ((SQLExpr)x.getArguments().get(0)).accept(this);
         this.print(')');
      }

      this.print0(this.ucase ? " TO SECOND" : " to second");
      if (x.getFractionalSeconds().size() > 0) {
         this.print('(');
         ((SQLExpr)x.getFractionalSeconds().get(0)).accept(this);
         this.print(')');
      }

      return false;
   }

   public boolean visit(OracleUsingIndexClause x) {
      this.print0(this.ucase ? "USING INDEX" : "using index");
      SQLObject index = x.getIndex();
      if (index != null) {
         this.print(' ');
         if (index instanceof SQLCreateIndexStatement) {
            this.print('(');
            index.accept(this);
            this.print(')');
         } else {
            index.accept(this);
         }
      }

      this.printOracleSegmentAttributes(x);
      if (x.isComputeStatistics()) {
         this.println();
         this.print0(this.ucase ? "COMPUTE STATISTICS" : "compute statistics");
      }

      if (x.getEnable() != null) {
         if (x.getEnable()) {
            this.println();
            this.print0(this.ucase ? "ENABLE" : "enable");
         } else {
            this.println();
            this.print0(this.ucase ? "DISABLE" : "disable");
         }
      }

      if (x.isReverse()) {
         this.println();
         this.print0(this.ucase ? "REVERSE" : "reverse");
      }

      return false;
   }

   public boolean visit(OracleLobStorageClause x) {
      this.print0(this.ucase ? "LOB (" : "lob (");
      this.printAndAccept(x.getItems(), ",");
      this.print0(this.ucase ? ") STORE AS" : ") store as");
      if (x.isSecureFile()) {
         this.print0(this.ucase ? " SECUREFILE" : " securefile");
      }

      if (x.isBasicFile()) {
         this.print0(this.ucase ? " BASICFILE" : " basicfile");
      }

      SQLName segementName = x.getSegementName();
      if (segementName != null) {
         this.print(' ');
         segementName.accept(this);
      }

      this.print0(" (");
      ++this.indentCount;
      this.printOracleSegmentAttributes(x);
      if (x.getEnable() != null) {
         this.println();
         if (x.getEnable()) {
            this.print0(this.ucase ? "ENABLE STORAGE IN ROW" : "enable storage in row");
         } else {
            this.print0(this.ucase ? "DISABLE STORAGE IN ROW" : "disable storage in row");
         }
      }

      if (x.getChunk() != null) {
         this.println();
         this.print0(this.ucase ? "CHUNK " : "chunk ");
         x.getChunk().accept(this);
      }

      if (x.getCache() != null) {
         this.println();
         if (x.getCache()) {
            this.print0(this.ucase ? "CACHE" : "cache");
         } else {
            this.print0(this.ucase ? "NOCACHE" : "nocache");
         }
      }

      if (x.getKeepDuplicate() != null) {
         this.println();
         if (x.getKeepDuplicate()) {
            this.print0(this.ucase ? "KEEP_DUPLICATES" : "keep_duplicates");
         } else {
            this.print0(this.ucase ? "DEDUPLICATE" : "deduplicate");
         }
      }

      if (x.isRetention()) {
         this.println();
         this.print0(this.ucase ? "RETENTION" : "retention");
      }

      --this.indentCount;
      this.println();
      this.print(')');
      return false;
   }

   public boolean visit(OracleUnique x) {
      this.visit((SQLUnique)x);
      this.printConstraintState(x);
      return false;
   }

   public boolean visit(OracleForeignKey x) {
      this.visit((SQLForeignKeyImpl)x);
      this.printConstraintState(x);
      return false;
   }

   public boolean visit(OracleCheck x) {
      this.visit((SQLCheck)x);
      this.printConstraintState(x);
      return false;
   }

   protected void printCascade() {
      this.print0(this.ucase ? " CASCADE CONSTRAINTS" : " cascade constraints");
   }

   public boolean visit(SQLCharExpr x, boolean parameterized) {
      if (x.getText() != null && x.getText().length() == 0) {
         this.print0(this.ucase ? "NULL" : "null");
      } else {
         super.visit(x, parameterized);
      }

      return false;
   }

   public boolean visit(OracleSupplementalIdKey x) {
      this.print0(this.ucase ? "SUPPLEMENTAL LOG DATA (" : "supplemental log data (");
      int count = 0;
      if (x.isAll()) {
         this.print0(this.ucase ? "ALL" : "all");
         ++count;
      }

      if (x.isPrimaryKey()) {
         if (count != 0) {
            this.print0(", ");
         }

         this.print0(this.ucase ? "PRIMARY KEY" : "primary key");
         ++count;
      }

      if (x.isUnique()) {
         if (count != 0) {
            this.print0(", ");
         }

         this.print0(this.ucase ? "UNIQUE" : "unique");
         ++count;
      }

      if (x.isUniqueIndex()) {
         if (count != 0) {
            this.print0(", ");
         }

         this.print0(this.ucase ? "UNIQUE INDEX" : "unique index");
         ++count;
      }

      if (x.isForeignKey()) {
         if (count != 0) {
            this.print0(", ");
         }

         this.print0(this.ucase ? "FOREIGN KEY" : "foreign key");
         ++count;
      }

      this.print0(this.ucase ? ") COLUMNS" : ") columns");
      return false;
   }

   public boolean visit(OracleSupplementalLogGrp x) {
      this.print0(this.ucase ? "SUPPLEMENTAL LOG GROUP " : "supplemental log group ");
      x.getGroup().accept(this);
      this.print0(" (");
      this.printAndAccept(x.getColumns(), ", ");
      this.print(')');
      if (x.isAlways()) {
         this.print0(this.ucase ? " ALWAYS" : " always");
      }

      return false;
   }

   public boolean visit(OracleCreateTableStatement.Organization x) {
      String type = x.getType();
      this.print0(this.ucase ? "ORGANIZATION " : "organization ");
      this.print0(this.ucase ? type : type.toLowerCase());
      this.printOracleSegmentAttributes(x);
      if (x.getPctthreshold() != null) {
         this.println();
         this.print0(this.ucase ? "PCTTHRESHOLD " : "pctthreshold ");
         this.print(x.getPctthreshold());
      }

      if ("EXTERNAL".equalsIgnoreCase(type)) {
         this.print0(" (");
         ++this.indentCount;
         if (x.getExternalType() != null) {
            this.println();
            this.print0(this.ucase ? "TYPE " : "type ");
            x.getExternalType().accept(this);
         }

         if (x.getExternalDirectory() != null) {
            this.println();
            this.print0(this.ucase ? "DEFAULT DIRECTORY " : "default directory ");
            x.getExternalDirectory().accept(this);
         }

         if (x.getExternalDirectoryRecordFormat() != null) {
            this.println();
            ++this.indentCount;
            this.print0(this.ucase ? "ACCESS PARAMETERS (" : "access parameters (");
            x.getExternalDirectoryRecordFormat().accept(this);
            --this.indentCount;
            this.println();
            this.print(')');
         }

         if (x.getExternalDirectoryLocation().size() > 0) {
            this.println();
            this.print0(this.ucase ? "LOCATION (" : " location(");
            this.printAndAccept(x.getExternalDirectoryLocation(), ", ");
            this.print(')');
         }

         --this.indentCount;
         this.println();
         this.print(')');
         if (x.getExternalRejectLimit() != null) {
            this.println();
            this.print0(this.ucase ? "REJECT LIMIT " : "reject limit ");
            x.getExternalRejectLimit().accept(this);
         }
      }

      return false;
   }

   public boolean visit(OracleCreateTableStatement.OIDIndex x) {
      this.print0(this.ucase ? "OIDINDEX" : "oidindex");
      if (x.getName() != null) {
         this.print(' ');
         x.getName().accept(this);
      }

      this.print(" (");
      ++this.indentCount;
      this.printOracleSegmentAttributes(x);
      --this.indentCount;
      this.println();
      this.print(")");
      return false;
   }

   public boolean visit(OracleCreatePackageStatement x) {
      if (x.isOrReplace()) {
         this.print0(this.ucase ? "CREATE OR REPLACE PACKAGE " : "create or replace procedure ");
      } else {
         this.print0(this.ucase ? "CREATE PACKAGE " : "create procedure ");
      }

      if (x.isBody()) {
         this.print0(this.ucase ? "BODY " : "body ");
      }

      x.getName().accept(this);
      if (x.isBody()) {
         this.println();
         this.print0(this.ucase ? "BEGIN" : "begin");
      }

      ++this.indentCount;
      List<SQLStatement> statements = x.getStatements();
      int i = 0;

      for(int size = statements.size(); i < size; ++i) {
         this.println();
         SQLStatement stmt = (SQLStatement)statements.get(i);
         stmt.accept(this);
      }

      --this.indentCount;
      if (x.isBody() || statements.size() > 0) {
         this.println();
         this.print0(this.ucase ? "END " : "end ");
         x.getName().accept(this);
         this.print(';');
      }

      return false;
   }

   public boolean visit(SQLAssignItem x) {
      x.getTarget().accept(this);
      this.print0(" := ");
      x.getValue().accept(this);
      return false;
   }

   public boolean visit(OracleExecuteImmediateStatement x) {
      this.print0(this.ucase ? "EXECUTE IMMEDIATE " : "execute immediate ");
      x.getDynamicSql().accept(this);
      List<SQLExpr> into = x.getInto();
      if (into.size() > 0) {
         this.print0(this.ucase ? " INTO " : " into ");
         this.printAndAccept(into, ", ");
      }

      List<SQLArgument> using = x.getArguments();
      if (using.size() > 0) {
         this.print0(this.ucase ? " USING " : " using ");
         this.printAndAccept(using, ", ");
      }

      List<SQLExpr> returnInto = x.getReturnInto();
      if (returnInto.size() > 0) {
         this.print0(this.ucase ? " RETURNNING INTO " : " returnning into ");
         this.printAndAccept(returnInto, ", ");
      }

      return false;
   }

   public boolean visit(OracleTreatExpr x) {
      this.print0(this.ucase ? "TREAT (" : "treat (");
      x.getExpr().accept(this);
      this.print0(this.ucase ? " AS " : " as ");
      if (x.isRef()) {
         this.print0(this.ucase ? "REF " : "ref ");
      }

      x.getType().accept(this);
      this.print(')');
      return false;
   }

   public boolean visit(OracleCreateSynonymStatement x) {
      if (x.isOrReplace()) {
         this.print0(this.ucase ? "CREATE OR REPLACE " : "create or replace ");
      } else {
         this.print0(this.ucase ? "CREATE " : "create ");
      }

      if (x.isPublic()) {
         this.print0(this.ucase ? "PUBLIC " : "public ");
      }

      this.print0(this.ucase ? "SYNONYM " : "synonym ");
      x.getName().accept(this);
      this.print0(this.ucase ? " FOR " : " for ");
      x.getObject().accept(this);
      return false;
   }

   public boolean visit(OracleCreateTypeStatement x) {
      if (x.isOrReplace()) {
         this.print0(this.ucase ? "CREATE OR REPLACE TYPE " : "create or replace type ");
      } else {
         this.print0(this.ucase ? "CREATE TYPE " : "create type ");
      }

      if (x.isBody()) {
         this.print0(this.ucase ? "BODY " : "body ");
      }

      x.getName().accept(this);
      SQLName under = x.getUnder();
      if (under != null) {
         this.print0(this.ucase ? " UNDER " : " under ");
         under.accept(this);
      }

      SQLName authId = x.getAuthId();
      if (authId != null) {
         this.print0(this.ucase ? " AUTHID " : " authid ");
         authId.accept(this);
      }

      if (x.isForce()) {
         this.print0(this.ucase ? "FORCE " : "force ");
      }

      List<SQLParameter> parameters = x.getParameters();
      SQLDataType tableOf = x.getTableOf();
      if (x.isObject()) {
         this.print0(" AS OBJECT");
      }

      if (parameters.size() > 0) {
         if (x.isParen()) {
            this.print(" (");
         } else {
            this.print0(this.ucase ? " IS" : " is");
         }

         ++this.indentCount;
         this.println();

         for(int i = 0; i < parameters.size(); ++i) {
            SQLParameter param = (SQLParameter)parameters.get(i);
            param.accept(this);
            SQLDataType dataType = param.getDataType();
            if (i < parameters.size() - 1) {
               if (dataType instanceof OracleFunctionDataType && ((OracleFunctionDataType)dataType).getBlock() != null) {
                  this.println();
               } else if (dataType instanceof OracleProcedureDataType && ((OracleProcedureDataType)dataType).getBlock() != null) {
                  this.println();
               } else {
                  this.println(", ");
               }
            }
         }

         --this.indentCount;
         this.println();
         if (x.isParen()) {
            this.print0(")");
         } else {
            this.print0("END");
         }
      } else if (tableOf != null) {
         this.print0(this.ucase ? " AS TABLE OF " : " as table of ");
         tableOf.accept(this);
      } else if (x.getVarraySizeLimit() != null) {
         this.print0(this.ucase ? " VARRAY (" : " varray (");
         x.getVarraySizeLimit().accept(this);
         this.print0(this.ucase ? ") OF " : ") of ");
         x.getVarrayDataType().accept(this);
      }

      Boolean isFinal = x.getFinal();
      if (isFinal != null) {
         if (isFinal) {
            this.print0(this.ucase ? " FINAL" : " final");
         } else {
            this.print0(this.ucase ? " NOT FINAL" : " not final");
         }
      }

      Boolean instantiable = x.getInstantiable();
      if (instantiable != null) {
         if (instantiable) {
            this.print0(this.ucase ? " INSTANTIABLE" : " instantiable");
         } else {
            this.print0(this.ucase ? " NOT INSTANTIABLE" : " not instantiable");
         }
      }

      String wrappedSource = x.getWrappedSource();
      if (wrappedSource != null) {
         this.print0(this.ucase ? " WRAPPED" : " wrapped");
         this.print0(wrappedSource);
      }

      return false;
   }

   public boolean visit(OraclePipeRowStatement x) {
      this.print0(this.ucase ? "PIPE ROW(" : "pipe row(");
      this.printAndAccept(x.getParameters(), ", ");
      this.print(')');
      return false;
   }

   public boolean visit(OracleIsOfTypeExpr x) {
      this.printExpr(x.getExpr());
      this.print0(this.ucase ? " IS OF TYPE (" : " is of type (");
      List<SQLExpr> types = x.getTypes();
      int i = 0;

      for(int size = types.size(); i < size; ++i) {
         if (i != 0) {
            this.print0(", ");
         }

         SQLExpr type = (SQLExpr)types.get(i);
         if (Boolean.TRUE == type.getAttribute("ONLY")) {
            this.print0(this.ucase ? "ONLY " : "only ");
         }

         type.accept(this);
      }

      this.print(')');
      return false;
   }

   public boolean visit(OracleRunStatement x) {
      this.print0("@@");
      this.printExpr(x.getExpr());
      return false;
   }

   public boolean visit(OracleXmlColumnProperties x) {
      this.print0(this.ucase ? "XMLTYPE " : "xmltype ");
      x.getColumn().accept(this);
      OracleXmlColumnProperties.OracleXMLTypeStorage storage = x.getStorage();
      if (storage != null) {
         storage.accept(this);
      }

      Boolean allowNonSchema = x.getAllowNonSchema();
      if (allowNonSchema != null) {
         if (allowNonSchema) {
            this.print0(this.ucase ? " ALLOW NONSCHEMA" : " allow nonschema");
         } else {
            this.print0(this.ucase ? " DISALLOW NONSCHEMA" : " disallow nonschema");
         }
      }

      Boolean allowAnySchema = x.getAllowAnySchema();
      if (allowAnySchema != null) {
         if (allowAnySchema) {
            this.print0(this.ucase ? " ALLOW ANYSCHEMA" : " allow anyschema");
         } else {
            this.print0(this.ucase ? " DISALLOW ANYSCHEMA" : " disallow anyschema");
         }
      }

      return false;
   }

   public boolean visit(OracleXmlColumnProperties.OracleXMLTypeStorage x) {
      return false;
   }

   public boolean visit(SQLSubPartition x) {
      super.visit(x);
      this.incrementIndent();
      this.printOracleSegmentAttributes(x);
      this.decrementIndent();
      return false;
   }

   public boolean visit(SQLPartitionValue x) {
      super.visit(x);
      this.incrementIndent();
      this.printOracleSegmentAttributes(x);
      this.decrementIndent();
      return false;
   }

   public boolean visit(OracleMultisetExpr x) {
      x.getLeftNestedTable().accept(this);
      this.print0(" MULTISET ");
      x.getType().accept(this);
      if (x.getDistinct() != null) {
         this.print0(" DISTINCT");
      }

      this.print0(" ");
      x.getRightNestedTable().accept(this);
      return false;
   }

   public boolean visit(OracleJsonObjectExpr x) {
      for(OracleJsonObjectExpr.OracleJsonObjectExprItem item : x.getItems()) {
         if (item.isHasKey()) {
            this.print0(" KEY ");
         }

         if (item.getKey() != null) {
            item.getKey().accept(this);
         }

         this.print0(" VALUE ");
         item.getValue().accept(this);
         if (item.isFormatJson()) {
            this.print0(" FORMAT JSON ");
         }
      }

      if (x.getNullClause() != null) {
         x.getNullClause().accept(this);
         this.print0(" ON NULL ");
      }

      if (x.getReturnClause() != null) {
         this.print0(" RETURNING VARCHAR2 ");
         OracleJsonObjectExpr.OracleJsonObjectReturnClause returnClause = x.getReturnClause();
         SQLExpr size = returnClause.getSize();
         if (size != null) {
            SQLExpr byteOrChar = returnClause.getByteOrChar();
            this.print0(" ( ");
            size.accept(this);
            byteOrChar.accept(this);
            this.print0(" ) ");
         }
      }

      return false;
   }

   public boolean visit(OracleJsonArrayAggExpr x) {
      x.getExpr().accept(this);
      if (x.isFormatJson()) {
         this.print0(" FORMAT JSON ");
      }

      if (x.getOrderBy() != null) {
         x.getOrderBy().accept(this);
      }

      if (x.getNullClause() != null) {
         x.getNullClause().accept(this);
         this.print0(" ON NULL ");
      }

      if (x.getReturnClause() != null) {
         this.print0(" RETURNING ");
         OracleJsonArrayAggExpr.OracleJsonAggArrayReturnClause returnClause = x.getReturnClause();
         returnClause.getType().accept(this);
         SQLExpr size = returnClause.getSize();
         if (size != null) {
            SQLExpr byteOrChar = returnClause.getByteOrChar();
            this.print0(" ( ");
            size.accept(this);
            byteOrChar.accept(this);
            this.print0(" ) ");
         }
      }

      return false;
   }

   public void endVisit(OracleAnalytic x) {
   }

   public void endVisit(OracleAnalyticWindowing x) {
   }

   public void endVisit(OracleDeleteStatement x) {
      this.endVisit((SQLDeleteStatement)x);
   }

   public void endVisit(OracleIntervalExpr x) {
   }

   public void endVisit(OracleOuterExpr x) {
   }

   public void endVisit(OracleSelectJoin x) {
   }

   public void endVisit(OracleSelectPivot x) {
   }

   public void endVisit(OracleSelectPivot.Item x) {
   }

   public void endVisit(OracleSelectRestriction.CheckOption x) {
   }

   public void endVisit(OracleSelectRestriction.ReadOnly x) {
   }

   public void endVisit(OracleSelectSubqueryTableSource x) {
   }

   public void endVisit(OracleSelectUnPivot x) {
   }

   public void endVisit(OracleUpdateStatement x) {
   }

   public void endVisit(SampleClause x) {
   }

   public void endVisit(OracleSelectTableReference x) {
   }

   public void endVisit(PartitionExtensionClause x) {
   }

   public void endVisit(OracleWithSubqueryEntry x) {
   }

   public void endVisit(SearchClause x) {
   }

   public void endVisit(CycleClause x) {
   }

   public void endVisit(OracleBinaryFloatExpr x) {
   }

   public void endVisit(OracleBinaryDoubleExpr x) {
   }

   public boolean visit(OracleCursorExpr x) {
      return true;
   }

   public void endVisit(OracleCursorExpr x) {
   }

   public void endVisit(OracleIsSetExpr x) {
   }

   public void endVisit(ModelClause.ReturnRowsClause x) {
   }

   public void endVisit(ModelClause.MainModelClause x) {
   }

   public void endVisit(ModelClause.ModelColumnClause x) {
   }

   public void endVisit(ModelClause.QueryPartitionClause x) {
   }

   public void endVisit(ModelClause.ModelColumn x) {
   }

   public void endVisit(ModelClause.ModelRulesClause x) {
   }

   public void endVisit(ModelClause.CellAssignmentItem x) {
   }

   public void endVisit(ModelClause.CellAssignment x) {
   }

   public void endVisit(ModelClause x) {
   }

   public void endVisit(OracleReturningClause x) {
   }

   public void endVisit(OracleInsertStatement x) {
      this.endVisit((SQLInsertStatement)x);
   }

   public void endVisit(OracleMultiInsertStatement.InsertIntoClause x) {
   }

   public void endVisit(OracleMultiInsertStatement x) {
   }

   public void endVisit(OracleMultiInsertStatement.ConditionalInsertClause x) {
   }

   public void endVisit(OracleMultiInsertStatement.ConditionalInsertClauseItem x) {
   }

   public void endVisit(OracleSelectQueryBlock x) {
      this.endVisit((SQLSelectQueryBlock)x);
   }

   public void endVisit(OracleLockTableStatement x) {
   }

   public void endVisit(OracleAlterSessionStatement x) {
   }

   public void endVisit(OracleDatetimeExpr x) {
   }

   public void endVisit(OracleSysdateExpr x) {
   }

   public void endVisit(OracleExceptionStatement x) {
   }

   public void endVisit(OracleExceptionStatement.Item x) {
   }

   public void endVisit(OracleArgumentExpr x) {
   }

   public void endVisit(OracleSetTransactionStatement x) {
   }

   public void endVisit(OracleExplainStatement x) {
   }

   public void endVisit(OracleAlterTableDropPartition x) {
   }

   public void endVisit(OracleAlterTableTruncatePartition x) {
   }

   public void endVisit(OracleAlterTableSplitPartition.TableSpaceItem x) {
   }

   public void endVisit(OracleAlterTableSplitPartition.UpdateIndexesClause x) {
   }

   public void endVisit(OracleAlterTableSplitPartition.NestedTablePartitionSpec x) {
   }

   public void endVisit(OracleAlterTableSplitPartition x) {
   }

   public void endVisit(OracleAlterTableModify x) {
   }

   public void endVisit(OracleCreateIndexStatement x) {
      this.endVisit((SQLCreateIndexStatement)x);
   }

   public void endVisit(OracleForStatement x) {
   }

   public void endVisit(OracleRangeExpr x) {
   }

   public void endVisit(OraclePrimaryKey x) {
   }

   public void endVisit(OracleCreateTableStatement x) {
      this.endVisit((SQLCreateTableStatement)x);
   }

   public void endVisit(OracleStorageClause x) {
   }

   public void endVisit(OracleGotoStatement x) {
   }

   public void endVisit(OracleLabelStatement x) {
   }

   public void endVisit(OracleAlterTriggerStatement x) {
   }

   public void endVisit(OracleAlterSynonymStatement x) {
   }

   public void endVisit(OracleAlterViewStatement x) {
   }

   public void endVisit(OracleAlterTableMoveTablespace x) {
   }

   public void endVisit(OracleFileSpecification x) {
   }

   public void endVisit(OracleAlterTablespaceAddDataFile x) {
   }

   public void endVisit(OracleAlterTablespaceStatement x) {
   }

   public void endVisit(OracleExitStatement x) {
   }

   public void endVisit(OracleContinueStatement x) {
   }

   public void endVisit(OracleRaiseStatement x) {
   }

   public void endVisit(OracleCreateDatabaseDbLinkStatement x) {
   }

   public void endVisit(OracleDropDbLinkStatement x) {
   }

   public void endVisit(OracleDataTypeIntervalYear x) {
   }

   public void endVisit(OracleDataTypeIntervalDay x) {
   }

   public void endVisit(OracleUsingIndexClause x) {
   }

   public void endVisit(OracleLobStorageClause x) {
   }

   public void endVisit(OracleUnique x) {
      this.endVisit((SQLUnique)x);
   }

   public void endVisit(OracleForeignKey x) {
      this.endVisit((SQLForeignKeyImpl)x);
   }

   public void endVisit(OracleCheck x) {
      this.endVisit((SQLCheck)x);
   }

   public void endVisit(OracleSupplementalIdKey x) {
   }

   public void endVisit(OracleSupplementalLogGrp x) {
   }

   public void endVisit(OracleCreateTableStatement.Organization x) {
   }

   public void endVisit(OracleCreateTableStatement.OIDIndex x) {
   }

   public void endVisit(OracleCreatePackageStatement x) {
   }

   public void endVisit(OracleExecuteImmediateStatement x) {
   }

   public void endVisit(OracleTreatExpr x) {
   }

   public void endVisit(OracleCreateSynonymStatement x) {
   }

   public void endVisit(OracleCreateTypeStatement x) {
   }

   public void endVisit(OraclePipeRowStatement x) {
   }

   public void endVisit(OracleIsOfTypeExpr x) {
   }

   public void endVisit(OracleRunStatement x) {
   }

   public void endVisit(OracleXmlColumnProperties x) {
   }

   public void endVisit(OracleXmlColumnProperties.OracleXMLTypeStorage x) {
   }

   public boolean visit(OracleXmlContentExpr x) {
      return true;
   }

   public void endVisit(OracleXmlContentExpr x) {
   }

   public boolean visit(OracleMethodInvokeAccessExpr x) {
      return true;
   }

   public void endVisit(OracleMethodInvokeAccessExpr x) {
   }

   public void endVisit(OracleMultisetExpr x) {
   }

   public void endVisit(OracleJsonObjectExpr x) {
   }

   public boolean visit(OracleJsonObjectExpr.OracleJsonObjectExprItem x) {
      return true;
   }

   public void endVisit(OracleJsonObjectExpr.OracleJsonObjectExprItem x) {
   }

   public boolean visit(OracleJsonObjectExpr.OracleJsonObjectOnNullClause x) {
      return true;
   }

   public void endVisit(OracleJsonObjectExpr.OracleJsonObjectOnNullClause x) {
   }

   public boolean visit(OracleJsonObjectExpr.OracleJsonObjectReturnClause x) {
      return true;
   }

   public void endVisit(OracleJsonObjectExpr.OracleJsonObjectReturnClause x) {
   }

   public void endVisit(OracleJsonArrayAggExpr x) {
   }

   public boolean visit(OracleJsonArrayAggExpr.OracleJsonAggArrayOnNullClause x) {
      return true;
   }

   public void endVisit(OracleJsonArrayAggExpr.OracleJsonAggArrayOnNullClause x) {
   }

   public boolean visit(OracleJsonArrayAggExpr.OracleJsonAggArrayReturnClause x) {
      return true;
   }

   public void endVisit(OracleJsonArrayAggExpr.OracleJsonAggArrayReturnClause x) {
   }
}
