package com.chenyang.druid.sql.dialect.db2.visitor;

import com.chenyang.druid.DbType;
import com.chenyang.druid.sql.ast.SQLArrayDataType;
import com.chenyang.druid.sql.ast.SQLDataType;
import com.chenyang.druid.sql.ast.SQLExpr;
import com.chenyang.druid.sql.ast.SQLLimit;
import com.chenyang.druid.sql.ast.SQLName;
import com.chenyang.druid.sql.ast.SQLStatement;
import com.chenyang.druid.sql.ast.SQLWindow;
import com.chenyang.druid.sql.ast.expr.SQLBinaryExpr;
import com.chenyang.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.chenyang.druid.sql.ast.expr.SQLIdentifierExpr;
import com.chenyang.druid.sql.ast.expr.SQLListExpr;
import com.chenyang.druid.sql.ast.expr.SQLPropertyExpr;
import com.chenyang.druid.sql.ast.expr.SQLVariantRefExpr;
import com.chenyang.druid.sql.ast.statement.SQLAlterTableItem;
import com.chenyang.druid.sql.ast.statement.SQLAssignItem;
import com.chenyang.druid.sql.ast.statement.SQLColumnConstraint;
import com.chenyang.druid.sql.ast.statement.SQLColumnDefinition;
import com.chenyang.druid.sql.ast.statement.SQLCommitStatement;
import com.chenyang.druid.sql.ast.statement.SQLCreateTriggerStatement;
import com.chenyang.druid.sql.ast.statement.SQLDB2TimeIntervalDataType;
import com.chenyang.druid.sql.ast.statement.SQLDropTableStatement;
import com.chenyang.druid.sql.ast.statement.SQLExprTableSource;
import com.chenyang.druid.sql.ast.statement.SQLGrantStatement;
import com.chenyang.druid.sql.ast.statement.SQLIfStatement;
import com.chenyang.druid.sql.ast.statement.SQLPrivilegeItem;
import com.chenyang.druid.sql.ast.statement.SQLRollbackStatement;
import com.chenyang.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.chenyang.druid.sql.ast.statement.SQLSelectStatement;
import com.chenyang.druid.sql.ast.statement.SQLSetStatement;
import com.chenyang.druid.sql.ast.statement.SQLTableElement;
import com.chenyang.druid.sql.ast.statement.SQLTableSource;
import com.chenyang.druid.sql.ast.statement.SQLTruncateStatement;
import com.chenyang.druid.sql.ast.statement.SQLUpdateSetItem;
import com.chenyang.druid.sql.ast.statement.SQLWithSubqueryClause;
import com.chenyang.druid.sql.dialect.db2.ast.DB2SQLIndexSpec;
import com.chenyang.druid.sql.dialect.db2.ast.DB2SQLPartition;
import com.chenyang.druid.sql.dialect.db2.ast.DB2SQLPartitionBy;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2BoxExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2CidrExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2CircleExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2ColumnSimpleDefinitionExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2CurrentTimeExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2ExtractExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2InetExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2LineSegmentsExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2MacAddrExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2OptionValue;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2PointExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2PolygonExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2SQLObjectCollection;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2SchemaTables;
import com.chenyang.druid.sql.dialect.db2.ast.expr.DB2TypeCastExpr;
import com.chenyang.druid.sql.dialect.db2.ast.expr.constraint.DB2Constraint;
import com.chenyang.druid.sql.dialect.db2.ast.expr.constraint.DB2StorageParameter;
import com.chenyang.druid.sql.dialect.db2.ast.expr.tablesource.DB2ExprTableSource;
import com.chenyang.druid.sql.dialect.db2.ast.expr.tablesource.DB2FunctionTableSource;
import com.chenyang.druid.sql.dialect.db2.ast.expr.tablesource.DB2MethodInvokeTableSource;
import com.chenyang.druid.sql.dialect.db2.ast.expr.tablesource.DB2RowsFromTableSource;
import com.chenyang.druid.sql.dialect.db2.ast.expr.tablesource.DB2SubqueryTableSource;
import com.chenyang.druid.sql.dialect.db2.ast.expr.tablesource.DB2ValuesTableSource;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterDatabaseStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterGroupStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterIndexStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterRoleStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterSchemaStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterSequenceStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterSessionStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterSynonymStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterSystemKillSessionStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterTableSpaceStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterTableStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterTriggerStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2AlterViewStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CommonStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2ConnectToStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateDatabaseStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateGroupStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateIndexStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateMaterializedViewStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateRoleStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateSchemaStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateSeqenceStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateSynonymStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateTableAsStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateTableSpaceStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateTableStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateTriggerStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2CreateViewStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2DeleteStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2DropConnectionStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2DropSchemaStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2DropSequenceStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2DropSessionStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2DropTriggerStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2GrantStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2InsertStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2LockTableStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2RevokeStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2SelectStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2SetConnectionStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2SetSessionStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2SetTransactionStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2ShowStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2StartTransactionStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.DB2UpdateStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableAddColumn;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableAddConstraint;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableAlterColumn;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableAlterColumnOptions;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableCluster;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableDisableEnabelTrigger;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableDropColumn;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableDropConstraint;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableInheriteOrNotParentTable;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableModify;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableOf;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableRenameColumn;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableRenameConstraint;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableRenameTo;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableSetNewTableSpace;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableSetReset;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableSetSchema;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableSetTableSpace;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableSetWith;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterTableValidateConstraint;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2AlterUserStatement;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2ColumnDefinition;
import com.chenyang.druid.sql.dialect.db2.ast.stmt.alterTable.DB2CreateUserStatement;
import com.chenyang.druid.sql.visitor.SQLASTOutputVisitor;
import com.chenyang.druid.util.FnvHash;
import java.util.ArrayList;
import java.util.List;
import util.StringJoin;

public class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisitor {
   public DB2OutputVisitor(Appendable appender) {
      super(appender);
      this.dbType = DbType.db2;
   }

   public DB2OutputVisitor(Appendable appender, boolean parameterized) {
      super(appender, parameterized);
      this.dbType = DbType.db2;
   }

   public boolean visit(DB2SelectQueryBlock.FetchClause x) {
      this.print0(this.ucase ? "FETCH " : "fetch ");
      if (DB2SelectQueryBlock.FetchClause.Option.FIRST.equals(x.getOption())) {
         this.print0(this.ucase ? "FIRST " : "first ");
      } else if (DB2SelectQueryBlock.FetchClause.Option.NEXT.equals(x.getOption())) {
         this.print0(this.ucase ? "NEXT " : "next ");
      }

      x.getCount().accept(this);
      this.print0(this.ucase ? " ROWS ONLY" : " rows only");
      return false;
   }

   public void endVisit(DB2SelectQueryBlock.ForClause x) {
   }

   public boolean visit(DB2SelectQueryBlock.ForClauses x) {
      if (x != null && x.getClauses() != null && x.getClauses().size() > 0) {
         for(int i = 0; i < x.getClauses().size(); ++i) {
            DB2SelectQueryBlock.ForClause forClause = (DB2SelectQueryBlock.ForClause)x.getClauses().get(i);
            forClause.accept(this);
            if (i != x.getClauses().size() - 1) {
               this.println();
            }
         }
      }

      return false;
   }

   public void endVisit(DB2ColumnSimpleDefinitionExpr x) {
   }

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

   public void endVisit(DB2RowsFromTableSource x) {
   }

   public boolean visit(DB2SelectQueryBlock.ForClause x) {
      this.print0(this.ucase ? "FOR " : "for ");
      if (DB2SelectQueryBlock.ForClause.Option.UPDATE.equals(x.getOption())) {
         this.print0(this.ucase ? "UPDATE" : "update");
      } else if (DB2SelectQueryBlock.ForClause.Option.SHARE.equals(x.getOption())) {
         this.print0(this.ucase ? "SHARE" : "share");
      } else if (DB2SelectQueryBlock.ForClause.Option.NO_KEY_UPDATE.equals(x.getOption())) {
         this.print0(this.ucase ? "NO KEY UPDATE" : "no key update");
      } else if (DB2SelectQueryBlock.ForClause.Option.KEY_SHARE.equals(x.getOption())) {
         this.print0(this.ucase ? "KEY SHARE" : "key share");
      }

      if (x.getOf().size() > 0) {
         this.print(' ');
         this.print0(this.ucase ? "OF" : "of");
         this.print(' ');

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

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

      if (x.isNoWait()) {
         this.print0(this.ucase ? " NOWAIT" : " nowait");
      } else if (x.isSkipLocked()) {
         this.print0(this.ucase ? " SKIP LOCKED" : " skip locked");
      }

      return false;
   }

   public void endVisit(DB2DeleteStatement x) {
   }

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

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

      boolean bracket = x.isBracket();
      if (bracket) {
         this.print('(');
      }

      this.print0(this.ucase ? "SELECT " : "select ");
      if (1 == x.getDistionOption()) {
         this.print0(this.ucase ? "ALL " : "all ");
      } else if (2 == x.getDistionOption()) {
         this.print0(this.ucase ? "DISTINCT " : "distinct ");
         List<SQLExpr> distinctOn = x.getDistinctOn();
         if (distinctOn != null && distinctOn.size() > 0) {
            this.print0(this.ucase ? "ON " : "on ");
            if (distinctOn.size() == 1 && distinctOn.get(0) instanceof SQLListExpr) {
               this.printExpr((SQLExpr)distinctOn.get(0));
               this.print(' ');
            } else {
               this.print0("(");
               this.printAndAccept(distinctOn, ", ");
               this.print0(") ");
            }
         }
      }

      this.printSelectList(x.getSelectList());
      if (x.getInto() != null) {
         this.println();
         if (x.getIntoOption() != null) {
            this.print0(x.getIntoOption().name());
            this.print(' ');
         }

         this.print0(this.ucase ? "INTO " : "into ");
         x.getInto().accept(this);
      }

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

      SQLExpr where = x.getWhere();
      if (where != null) {
         this.println();
         this.print0(this.ucase ? "WHERE " : "where ");
         where.accept(this);
         if (where.hasAfterComment() && this.isPrettyFormat()) {
            this.print(' ');
            this.printlnComment(x.getWhere().getAfterCommentsDirect());
         }
      }

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

      List<SQLWindow> windows = x.getWindows();
      if (windows != null && windows.size() > 0) {
         this.println();
         this.print0(this.ucase ? "WINDOW " : "window ");
         this.printAndAccept(windows, ", ");
      }

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

      if (x.isUsing()) {
         this.print0(this.ucase ? " USING " : " using ");
         x.getUsingOperator().accept(this);
      }

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

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

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

      if (bracket) {
         this.print(')');
      }

      return false;
   }

   public void endVisit(DB2SelectQueryBlock.FetchClause x) {
   }

   public boolean visit(SQLTruncateStatement x) {
      this.print0(this.ucase ? "TRUNCATE TABLE " : "truncate table ");
      if (x.isOnly()) {
         this.print0(this.ucase ? "ONLY " : "only ");
      }

      this.printlnAndAccept(x.getTableSources(), ", ");
      if (x.getRestartIdentity() != null) {
         if (x.getRestartIdentity()) {
            this.print0(this.ucase ? " RESTART IDENTITY" : " restart identity");
         } else {
            this.print0(this.ucase ? " CONTINUE IDENTITY" : " continue identity");
         }
      }

      if (x.getCascade() != null) {
         if (x.getCascade()) {
            this.print0(this.ucase ? " CASCADE" : " cascade");
         } else {
            this.print0(this.ucase ? " RESTRICT" : " restrict");
         }
      }

      if (x.isPurge()) {
         this.print0(this.ucase ? " PURGE " : " purge ");
      }

      return false;
   }

   public boolean visit(DB2AlterSessionStatement x) {
      this.print0(this.ucase ? "ALTER SESSION " : "alter session ");
      x.getSessionId().accept(this);
      this.print(" ");
      if (x.isRollback()) {
         this.printUcase("ROLLBACK TRANSACTION ");
      }

      if (x.isSet()) {
         this.printUcase("SET ");
         if (x.isPriorityTo()) {
            this.printUcase("PRIORITY TO ");
            x.getPriority().accept(this);
         }
      }

      if (x.isAdd()) {
         this.printUcase("ADD ");
      }

      if (x.isRemove()) {
         this.printUcase("REMOVE ");
      }

      if (x.isTag()) {
         this.printUcase("TAG ");
         x.getTagValue().accept(this);
      }

      return false;
   }

   public void endVisit(DB2AlterSystemKillSessionStatement x) {
   }

   public boolean visit(DB2AlterSystemKillSessionStatement x) {
      this.print0(this.ucase ? "ALTER SYSTEM KILL SESSION " : "alter system kill session ");
      if (x.getConfigParameter() != null) {
         x.getConfigParameter().accept(this);
         this.print0(" ");
      }

      if (x.isImmediate()) {
         this.print0(this.ucase ? "IMMEDIATE " : "immediate ");
      }

      return false;
   }

   public void endVisit(DB2AlterTableSpaceStatement x) {
   }

   public boolean visit(DB2DeleteStatement x) {
      if (x.getWith() != null) {
         x.getWith().accept(this);
         this.println();
      }

      this.print0(this.ucase ? "DELETE FROM " : "delete from ");
      if (x.isOnly()) {
         this.print0(this.ucase ? "ONLY " : "only ");
      }

      this.printTableSourceExpr(x.getTableName());
      if (x.getAlias() != null) {
         this.print0(this.ucase ? " AS " : " as ");
         this.print0(x.getAlias());
      }

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

      List<SQLTableSource> usingList = x.getUsingList();
      if (usingList != null) {
         this.println();
         this.print0(this.ucase ? "USING " : "using ");

         for(int i = 0; i < usingList.size(); ++i) {
            SQLExprTableSource sqlExprTableSource = (SQLExprTableSource)usingList.get(i);
            if (i == usingList.size() - 1) {
               this.print0(sqlExprTableSource.getExpr().toString() + " ");
            } else {
               this.print0(sqlExprTableSource.getExpr().toString() + ", ");
            }
         }
      }

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

      if (x.isReturning()) {
         this.println();
         this.print0(this.ucase ? "RETURNING *" : "returning *");
      }

      return false;
   }

   public void endVisit(DB2InsertStatement x) {
   }

   public boolean visit(DB2InsertStatement x) {
      if (x.getWith() != null) {
         x.getWith().accept(this);
         this.println();
      }

      this.print0(this.ucase ? "INSERT INTO " : "insert into ");
      x.getTableSource().accept(this);
      this.printInsertColumns(x.getColumns());
      if (x.getValues() != null) {
         this.println();
         this.print0(this.ucase ? "VALUES " : "values ");
         this.printlnAndAccept(x.getValuesList(), ", ");
      } else if (x.getQuery() != null) {
         this.println();
         x.getQuery().accept(this);
      }

      List<SQLExpr> duplicateKeyUpdate = x.getDuplicateKeyUpdate();
      if (duplicateKeyUpdate.size() != 0) {
         this.println();
         this.print0(this.ucase ? "ON DUPLICATE KEY UPDATE " : "on duplicate key update ");
         int i = 0;

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

               this.print0(", ");
            }

            ((SQLExpr)duplicateKeyUpdate.get(i)).accept(this);
         }
      }

      List<SQLExpr> onConflictTarget = x.getOnConflictTarget();
      List<SQLUpdateSetItem> onConflictUpdateSetItems = x.getOnConflictUpdateSetItems();
      boolean onConflictDoNothing = x.isOnConflictDoNothing();
      if (onConflictDoNothing || onConflictTarget != null && onConflictTarget.size() > 0 || onConflictUpdateSetItems != null && onConflictUpdateSetItems.size() > 0) {
         this.println();
         this.print0(this.ucase ? "ON CONFLICT" : "on conflict");
         if (onConflictTarget != null && onConflictTarget.size() > 0) {
            this.print0(" (");
            this.printAndAccept(onConflictTarget, ", ");
            this.print(')');
         }

         SQLName onConflictConstraint = x.getOnConflictConstraint();
         if (onConflictConstraint != null) {
            this.print0(this.ucase ? " ON CONSTRAINT " : " on constraint ");
            this.printExpr(onConflictConstraint);
         }

         SQLExpr onConflictWhere = x.getOnConflictWhere();
         if (onConflictWhere != null) {
            this.print0(this.ucase ? " WHERE " : " where ");
            this.printExpr(onConflictWhere);
         }

         if (onConflictDoNothing) {
            this.print0(this.ucase ? " DO NOTHING" : " do nothing");
         } else if (onConflictUpdateSetItems != null && onConflictUpdateSetItems.size() > 0) {
            this.print0(this.ucase ? " DO UPDATE SET " : " do update set ");
            this.printAndAccept(onConflictUpdateSetItems, ", ");
            SQLExpr onConflictUpdateWhere = x.getOnConflictUpdateWhere();
            if (onConflictUpdateWhere != null) {
               this.print0(this.ucase ? " WHERE " : " where ");
               this.printExpr(onConflictUpdateWhere);
            }
         }
      }

      if (x.getReturning() != null) {
         this.println();
         this.print0(this.ucase ? "RETURNING " : "returning ");
         x.getReturning().accept(this);
      }

      return false;
   }

   public void endVisit(DB2SelectStatement x) {
      this.endVisit((SQLSelectStatement)x);
   }

   public boolean visit(DB2SelectStatement x) {
      return this.visit((SQLSelectStatement)x);
   }

   public void endVisit(DB2UpdateStatement x) {
   }

   public boolean visit(DB2UpdateStatement x) {
      SQLWithSubqueryClause with = x.getWith();
      if (with != null) {
         this.visit((SQLWithSubqueryClause)with);
         this.println();
      }

      this.print0(this.ucase ? "UPDATE " : "update ");
      if (x.isOnly()) {
         this.print0(this.ucase ? "ONLY " : "only ");
      }

      this.printTableSource(x.getTableSource());
      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 item = (SQLUpdateSetItem)x.getItems().get(i);
         this.visit((SQLUpdateSetItem)item);
      }

      SQLTableSource from = x.getFrom();
      if (from != null) {
         this.println();
         this.print0(this.ucase ? "FROM " : "from ");
         this.printTableSource(from);
      }

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

      List<SQLExpr> returning = x.getReturning();
      if (returning.size() > 0) {
         this.println();
         this.print0(this.ucase ? "RETURNING " : "returning ");
         this.printAndAccept(returning, ", ");
      }

      return false;
   }

   public void endVisit(DB2FunctionTableSource x) {
   }

   public boolean visit(DB2FunctionTableSource x) {
      x.getExpr().accept(this);
      if (x.getAlias() != null) {
         this.print0(this.ucase ? " AS " : " as ");
         this.print0(x.getAlias());
      }

      if (x.getParameters().size() > 0) {
         this.print('(');
         this.printAndAccept(x.getParameters(), ", ");
         this.print(')');
      }

      return false;
   }

   public void endVisit(DB2TypeCastExpr x) {
   }

   public boolean visit(DB2TypeCastExpr x) {
      SQLExpr expr = x.getExpr();
      SQLDataType dataType = x.getDataType();
      if (dataType.nameHashCode64() == FnvHash.Constants.VARBIT) {
         dataType.accept(this);
         this.print(' ');
         this.printExpr(expr);
         return false;
      } else {
         if (expr != null) {
            if (expr instanceof SQLBinaryOpExpr) {
               this.print('(');
               expr.accept(this);
               this.print(')');
            } else {
               if (expr instanceof DB2TypeCastExpr && dataType.getArguments().size() == 0) {
                  dataType.accept(this);
                  this.print('(');
                  this.visit((DB2TypeCastExpr)expr);
                  this.print(')');
                  return false;
               }

               expr.accept(this);
            }
         }

         this.print0("::");
         dataType.accept(this);
         return false;
      }
   }

   public void endVisit(DB2ExtractExpr x) {
   }

   public boolean visit(DB2ExtractExpr x) {
      this.print0(this.ucase ? "EXTRACT (" : "extract (");
      this.print0(x.getField().name());
      this.print0(this.ucase ? " FROM " : " from ");
      x.getSource().accept(this);
      this.print(')');
      return false;
   }

   public void endVisit(DB2BoxExpr x) {
   }

   public boolean visit(DB2BoxExpr x) {
      this.print0(this.ucase ? "BOX " : "box ");
      x.getValue().accept(this);
      return false;
   }

   public void endVisit(DB2PointExpr x) {
   }

   public boolean visit(DB2PointExpr x) {
      this.print0(this.ucase ? "POINT " : "point ");
      x.getValue().accept(this);
      return false;
   }

   public void endVisit(DB2MacAddrExpr x) {
   }

   public boolean visit(DB2MacAddrExpr x) {
      this.print0("macaddr ");
      x.getValue().accept(this);
      return false;
   }

   public void endVisit(DB2InetExpr x) {
   }

   public boolean visit(DB2InetExpr x) {
      this.print0("inet ");
      x.getValue().accept(this);
      return false;
   }

   public void endVisit(DB2CurrentTimeExpr x) {
   }

   public boolean visit(DB2CurrentTimeExpr x) {
      this.printUcase(x.getText());
      return false;
   }

   public void endVisit(DB2CidrExpr x) {
   }

   public boolean visit(DB2CidrExpr x) {
      this.print0("cidr ");
      x.getValue().accept(this);
      return false;
   }

   public void endVisit(DB2PolygonExpr x) {
   }

   public boolean visit(DB2PolygonExpr x) {
      this.print0("polygon ");
      x.getValue().accept(this);
      return false;
   }

   public void endVisit(DB2CircleExpr x) {
   }

   public boolean visit(DB2CircleExpr x) {
      this.print0("circle ");
      x.getValue().accept(this);
      return false;
   }

   public void endVisit(DB2LineSegmentsExpr x) {
   }

   public boolean visit(DB2LineSegmentsExpr x) {
      this.print0("lseg ");
      x.getValue().accept(this);
      return false;
   }

   public void endVisit(DB2ShowStatement x) {
   }

   public boolean visit(SQLBinaryExpr x) {
      this.print0(this.ucase ? "B'" : "b'");
      this.print0(x.getText());
      this.print('\'');
      return false;
   }

   public boolean visit(DB2ShowStatement x) {
      this.print0(this.ucase ? "SHOW " : "show ");
      x.getExpr().accept(this);
      return false;
   }

   public void endVisit(DB2StartTransactionStatement x) {
   }

   public boolean visit(SQLLimit x) {
      if (x.getRowCount() != null) {
         this.print0(this.ucase ? "LIMIT " : "limit ");
         x.getRowCount().accept(this);
      }

      if (x.getOffset() != null) {
         this.print0(this.ucase ? " OFFSET " : " offset ");
         x.getOffset().accept(this);
      }

      return false;
   }

   public boolean visit(DB2StartTransactionStatement x) {
      this.print0(this.ucase ? "START TRANSACTION" : "start transaction");
      return false;
   }

   public void endVisit(DB2ConnectToStatement x) {
   }

   public boolean visit(DB2ConnectToStatement x) {
      this.print0(this.ucase ? "CONNECT TO " : "connect to ");
      x.getTarget().accept(this);
      return false;
   }

   public void endVisit(DB2CreateSchemaStatement x) {
   }

   public boolean visit(DB2CreateSchemaStatement x) {
      this.printUcase("CREATE SCHEMA ");
      if (x.getSchemaName() != null) {
         x.getSchemaName().accept(this);
         this.print0(" ");
      }

      if (x.isAuthorization()) {
         this.printUcase("AUTHORIZATION ");
         x.getUserName().accept(this);
         this.print0(" ");
      }

      if (x.isPath()) {
         this.printUcase("PATH ");
         x.getSchemaPath().accept(this);
         this.print0(" ");
      }

      if (x.getElements() != null && x.getElements().size() > 0) {
         this.incrementIndent();

         for(SQLStatement element : x.getElements()) {
            this.println();
            this.printIndent();
            element.accept(this);
         }
      }

      if (x.isDataVersionRetentionTime()) {
         this.printUcase("DATA_VERSION-RETENTION_TIME ");
         x.getDataVersionRetentionTimeNum().accept(this);
         this.print0(" ");
      }

      return false;
   }

   public void endVisit(DB2DropSchemaStatement x) {
   }

   public boolean visit(DB2DropSchemaStatement x) {
      this.printUcase("DROP SCHEMA ");
      x.getSchema().accept(this);
      if (x.isCascade()) {
         this.printUcase(" CASCADE ");
      } else if (x.isRestrict()) {
         this.printUcase(" RESTRICT ");
      }

      return false;
   }

   public void endVisit(DB2AlterSchemaStatement x) {
   }

   public boolean visit(DB2AlterSchemaStatement x) {
      this.printUcase("ALTER SCHEMA ");
      x.getSchemaName().accept(this);
      if (x.getNewName() != null) {
         this.print0(" RENAME TO ");
         x.getNewName().accept(this);
      } else if (x.getNewOwner() != null) {
         this.print0(" AUTHORIZATION TO ");
         x.getNewOwner().accept(this);
      }

      if (x.isPath()) {
         this.print0(" SET PATH ");
         if (x.getSchemaPath() != null) {
            x.getSchemaPath().accept(this);
         }
      }

      if (x.isDataVersionRetentionTime()) {
         this.print0(" DATA_VERSION_RETENTION_TIME ");
         x.getDataVersionRetentionTimeNum().accept(this);
         this.print0(" NOCASCADE ");
      }

      return false;
   }

   public void endVisit(DB2MethodInvokeTableSource x) {
   }

   public boolean visit(SQLSetStatement x) {
      this.print0(this.ucase ? "SET " : "set ");
      SQLSetStatement.Option option = x.getOption();
      if (option != null) {
         this.print(option.name());
         this.print(' ');
      }

      List<SQLAssignItem> items = x.getItems();

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

         SQLAssignItem item = (SQLAssignItem)x.getItems().get(i);
         SQLExpr target = item.getTarget();
         target.accept(this);
         SQLExpr value = item.getValue();
         this.print(' ');
         if (target instanceof SQLIdentifierExpr && ((SQLIdentifierExpr)target).getName().equalsIgnoreCase("TIME ZONE")) {
            this.print(' ');
         } else if (value instanceof SQLPropertyExpr && ((SQLPropertyExpr)value).getOwner() instanceof SQLVariantRefExpr) {
            this.print0(" := ");
         }

         if (value instanceof SQLListExpr) {
            SQLListExpr listExpr = (SQLListExpr)value;
            this.printAndAccept(listExpr.getItems(), ", ");
         } else {
            value.accept(this);
         }
      }

      return false;
   }

   public boolean visit(DB2CreateUserStatement x) {
      this.print0(this.ucase ? "CREATE USER " : "create user ");
      x.getUser().accept(this);
      this.print0(" ");
      if (x.isWith()) {
         this.printUcase("WITH ");
      }

      if (x.isPasswordFlag()) {
         this.printUcase(" PASSWORD ");
         x.getPassword().accept(this);
      }

      if (x.isExpirePassword()) {
         this.printUcase(" EXPIRE PASSWORD ");
      }

      if (x.isPasswordexpiry()) {
         this.printUcase(" PASSWORDEXPIRY ");
         x.getPasswordexpiryDay().accept(this);
      }

      if (x.isAuth()) {
         this.printUcase(" AUTH ");
         x.getAuthType().accept(this);
      }

      if (x.isSysid()) {
         this.printUcase(" SYSID ");
         x.getSysidValue().accept(this);
      }

      if (x.isInGroup()) {
         this.printUcase(" IN GROUP ");
         this.printAndAccept(x.getInGroupList().getItems(), ", ");
      }

      if (x.isInResourcegroup()) {
         this.printUcase(" IN RESOURCEGROUP ");
         x.getInResourcegroupRsg().accept(this);
      }

      if (x.isValidUntil()) {
         this.printUcase(" VALID UNTIL ");
         x.getValidDate().accept(this);
      }

      if (x.isDefpriority()) {
         this.printUcase(" DEFPRIORITY ");
         x.getDefpriorityType().accept(this);
      }

      if (x.isMaxpriority()) {
         this.printUcase(" MAXPRIORITY ");
         x.getMaxpriorityType().accept(this);
      }

      if (x.isRowsetlimit()) {
         this.printUcase(" ROWSETLIMIT ");
         x.getRslimit().accept(this);
      }

      if (x.isSessiontimeout()) {
         this.printUcase(" SESSIONTIMEOUT ");
         x.getSessiontimeoutValue().accept(this);
      }

      if (x.isQuerytimeout()) {
         this.printUcase(" QUERYTIMEOUT ");
         x.getQuerytimeoutValue().accept(this);
      }

      if (x.isConcurrentSessions()) {
         this.printUcase(" CONCURRENT SESSIONS ");
         x.getConcurrentSessionsValue().accept(this);
      }

      if (x.isSecurityLabel()) {
         this.printUcase(" SECURITY LABEL ");
         x.getSecurityLabelValue().accept(this);
      }

      if (x.isAuditCategory()) {
         this.printUcase(" AUDIT CATEGORY ");
         this.printAndAccept(x.getAuditCategoryList().getItems(), ", ");
      }

      if (x.isCollectHistory()) {
         this.printUcase(" COLLECT HISTORY ");
         x.getCollectHistoryType().accept(this);
      }

      if (x.isAllowCrossJoin()) {
         this.printUcase(" ALLOW CROSS JOIN ");
         x.getAllowCrossJoinType().accept(this);
      }

      if (x.isAccessTime()) {
         this.printUcase(" ACCESS TIME ");
         if (x.getAccessTimeValue() != null) {
            x.getAccessTimeValue().accept(this);
         } else {
            this.print0("(");
            this.printAndAccept(x.getAccessTimeList().getItems(), ", ");
            this.print0(")");
         }
      }

      return false;
   }

   public boolean visit(DB2CreateRoleStatement x) {
      this.print0(this.ucase ? "CREATE ROLE " : "create role ");
      x.getName().accept(this);
      if (x.isEncrypted()) {
         this.printUcase(" ENCRYPTED ");
      } else if (x.isUnencrypted()) {
         this.printUcase(" UNENCRYPTED ");
      }

      if (x.isPasswordFlag()) {
         this.print0(this.ucase ? " PASSWORD " : " password ");
      } else {
         this.printUcase(" IDENTIFIED BY ");
      }

      SQLExpr passoword = x.getPassword();
      if (passoword instanceof SQLIdentifierExpr) {
         this.print('\'');
         passoword.accept(this);
         this.print('\'');
      } else {
         passoword.accept(this);
      }

      if (x.isExpired()) {
         this.printUcase(" EXPIRED ");
      }

      if (x.isDisable()) {
         this.printUcase(" DISABLE ");
      }

      return false;
   }

   public void endVisit(DB2AlterRoleStatement x) {
   }

   public boolean visit(DB2CreateGroupStatement x) {
      this.print0(this.ucase ? "CREATE GROUP " : "create group ");
      x.getUser().accept(this);
      if (x.isEncrypted()) {
         this.printUcase(" ENCRYPTED ");
      } else if (x.isUnencrypted()) {
         this.printUcase(" UNENCRYPTED ");
      }

      if (x.isPasswordFlag()) {
         this.print0(this.ucase ? " PASSWORD " : " password ");
      } else {
         this.printUcase(" IDENTIFIED BY ");
      }

      SQLExpr passoword = x.getPassword();
      if (passoword instanceof SQLIdentifierExpr) {
         this.print('\'');
         passoword.accept(this);
         this.print('\'');
      } else {
         passoword.accept(this);
      }

      if (x.isExpired()) {
         this.printUcase(" EXPIRED ");
      }

      if (x.isDisable()) {
         this.printUcase(" DISABLE ");
      }

      return false;
   }

   public void endVisit(DB2AlterGroupStatement x) {
   }

   public void endVisit(DB2AlterUserStatement x) {
   }

   public boolean visit(DB2AlterUserStatement x) {
      this.print0(this.ucase ? "ALTER USER " : "alter user ");
      x.getUser().accept(this);
      this.print0(" ");
      if (x.isRenameTo()) {
         this.printUcase("RENAME TO ");
         x.getNewName().accept(this);
         this.print0(" ");
      }

      if (x.isResetAccount()) {
         this.printUcase("RESET ACCOUNT ");
      }

      if (x.isWith()) {
         this.printUcase("WITH ");
      }

      if (x.isPasswordFlag()) {
         this.printUcase(" PASSWORD ");
         x.getPassword().accept(this);
      }

      if (x.isExpirePassword()) {
         this.printUcase(" EXPIRE PASSWORD ");
      }

      if (x.isPasswordexpiry()) {
         this.printUcase(" PASSWORDEXPIRY ");
         x.getPasswordexpiryDay().accept(this);
      }

      if (x.isAuth()) {
         this.printUcase(" AUTH ");
         x.getAuthType().accept(this);
      }

      if (x.isSysid()) {
         this.printUcase(" SYSID ");
         x.getSysidValue().accept(this);
      }

      if (x.isInGroup()) {
         this.printUcase(" IN GROUP ");
         this.printAndAccept(x.getInGroupList().getItems(), ", ");
      }

      if (x.isInResourcegroup()) {
         this.printUcase(" IN RESOURCEGROUP ");
         x.getInResourcegroupRsg().accept(this);
      }

      if (x.isValidUntil()) {
         this.printUcase(" VALID UNTIL ");
         x.getValidDate().accept(this);
      }

      if (x.isDefpriority()) {
         this.printUcase(" DEFPRIORITY ");
         x.getDefpriorityType().accept(this);
      }

      if (x.isMaxpriority()) {
         this.printUcase(" MAXPRIORITY ");
         x.getMaxpriorityType().accept(this);
      }

      if (x.isRowsetlimit()) {
         this.printUcase(" ROWSETLIMIT ");
         x.getRslimit().accept(this);
      }

      if (x.isSessiontimeout()) {
         this.printUcase(" SESSIONTIMEOUT ");
         x.getSessiontimeoutValue().accept(this);
      }

      if (x.isQuerytimeout()) {
         this.printUcase(" QUERYTIMEOUT ");
         x.getQuerytimeoutValue().accept(this);
      }

      if (x.isConcurrentSessions()) {
         this.printUcase(" CONCURRENT SESSIONS ");
         x.getConcurrentSessionsValue().accept(this);
      }

      if (x.isSecurityLabel()) {
         this.printUcase(" SECURITY LABEL ");
         x.getSecurityLabelValue().accept(this);
      }

      if (x.isAuditCategory()) {
         this.printUcase(" AUDIT CATEGORY ");
         this.printAndAccept(x.getAuditCategoryList().getItems(), ", ");
      }

      if (x.isCollectHistory()) {
         this.printUcase(" COLLECT HISTORY ");
         x.getCollectHistoryType().accept(this);
      }

      if (x.isAllowCrossJoin()) {
         this.printUcase(" ALLOW CROSS JOIN ");
         x.getAllowCrossJoinType().accept(this);
      }

      if (x.isAccessTime()) {
         this.printUcase(" ACCESS TIME ");
         if (x.getAccessTimeValue() != null) {
            x.getAccessTimeValue().accept(this);
         } else {
            this.print0("(");
            this.printAndAccept(x.getAccessTimeList().getItems(), ", ");
            this.print0(")");
         }
      }

      return false;
   }

   public boolean visit(DB2AlterRoleStatement x) {
      this.print0(this.ucase ? "ALTER ROLE " : "alter role ");
      x.getUser().accept(this);
      if (x.isRenameTo()) {
         this.printUcase(" RENAME TO ");
         x.getNewName().accept(this);
         return true;
      } else if (x.isAccount()) {
         this.printUcase(" ACCOUNT ");
         if (x.isLock()) {
            this.printUcase("LOCK ");
         }

         if (x.isUnlock()) {
            this.printUcase("UNLOCK ");
         }

         return true;
      } else {
         if (x.isEncrypted()) {
            this.printUcase(" ENCRYPTED ");
         } else if (x.isUnencrypted()) {
            this.printUcase(" UNENCRYPTED ");
         }

         if (x.isPasswordFlag()) {
            this.print0(this.ucase ? " PASSWORD " : " password ");
         } else {
            this.printUcase(" IDENTIFIED BY ");
         }

         SQLExpr passoword = x.getPassword();
         if (passoword instanceof SQLIdentifierExpr) {
            this.print('\'');
            passoword.accept(this);
            this.print('\'');
         } else {
            passoword.accept(this);
         }

         if (x.isExpired()) {
            this.printUcase(" EXPIRED ");
         }

         if (x.isDisable()) {
            this.printUcase(" DISABLE ");
         }

         return false;
      }
   }

   public void endVisit(DB2CreateTableAsStatement x) {
   }

   public boolean visit(DB2AlterGroupStatement x) {
      this.printUcase("ALTER GROUP ");
      x.getGroupName().accept(this);
      if (x.isRenameTo()) {
         this.printUcase(" RENAME TO ");
         x.getNewName().accept(this);
         return true;
      } else if (x.isAddUser()) {
         this.printUcase(" ADD USER ");
         this.printAndAccept(x.getNames().getItems(), ", ");
         return true;
      } else {
         if (x.isDropUser()) {
            this.printUcase(" DROP USER ");
            this.printAndAccept(x.getNames().getItems(), ", ");
         }

         return true;
      }
   }

   public void endVisit(DB2CreateMaterializedViewStatement x) {
   }

   public void endVisit(DB2CommonStatement x) {
   }

   public boolean visit(DB2CommonStatement x) {
      if (x.isShutdown()) {
         this.printUcase("SHUTDOWN ");
         if (x.getShutdownParam() != null) {
            x.getShutdownParam().accept(this);
         }
      }

      if (x.isDropGroup()) {
         this.printUcase("DROP GROUP ");
         if (x.isIfExists()) {
            this.printUcase("IF EXISTS ");
         }

         this.printAndAccept(x.getGroupNameList().getItems(), ", ");
      }

      if (x.isSavepoint()) {
         this.printUcase("SAVEPOINT ");
         if (x.getSavepointName() != null) {
            x.getSavepointName().accept(this);
         }
      }

      if (x.isRollback()) {
         this.printUcase("ROLLBACK ");
         if (x.isPrepared()) {
            this.printUcase("PREPARED ");
         }

         if (x.isWork()) {
            this.printUcase("WORK ");
         }

         if (x.isTransaction()) {
            this.printUcase("TRANSACTION ");
         }

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

      if (x.isCheckpoint()) {
         this.printUcase("CHECKPOINT ");
      }

      if (x.isReset()) {
         this.printUcase("RESET ");
         if (x.isRole()) {
            this.printUcase("ROLE ");
         }
      }

      if (x.isCommit()) {
         this.printUcase("COMMIT ");
         if (x.isPrepared()) {
            this.printUcase("PREPARED ");
         }

         if (x.isWork()) {
            this.printUcase("WORK ");
         }

         if (x.isTransaction()) {
            this.printUcase("TRANSACTION ");
         }

         if (x.getTransactionId() != null) {
            x.getTransactionId().accept(this);
            this.print(" ");
            if (x.isWith()) {
               this.printUcase("WITH ");
            }

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

      if (x.isEnd()) {
         this.printUcase("END ");
         if (x.isWork()) {
            this.printUcase("WORK ");
         }

         if (x.isTransaction()) {
            this.printUcase("TRANSACTION ");
         }
      }

      return false;
   }

   public void endVisit(DB2CreateGroupStatement x) {
   }

   protected void printGrantPrivileges(SQLGrantStatement x) {
      List<SQLPrivilegeItem> privileges = x.getPrivileges();
      int i = 0;

      for(SQLPrivilegeItem privilege : privileges) {
         if (i != 0) {
            this.print(", ");
         }

         SQLExpr action = privilege.getAction();
         if (action instanceof SQLIdentifierExpr) {
            String name = ((SQLIdentifierExpr)action).getName();
            if ("RESOURCE".equalsIgnoreCase(name)) {
               continue;
            }
         }

         privilege.accept(this);
         ++i;
      }

   }

   public boolean visit(DB2GrantStatement x) {
      this.print0(this.ucase ? "GRANT " : "grant ");
      this.printAndAccept(x.getPrivileges(), ", ");
      this.printGrantOn(x);
      if (!x.isOn()) {
         this.printUcase(" IN ");
      }

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

      if (x.getUsers() != null && x.getUsers().size() > 0) {
         this.print0(this.ucase ? " TO " : " to ");
         this.printAndAccept(x.getUsers(), ",");
      }

      if (x.getGroups() != null && x.getGroups().size() > 0) {
         this.print0(this.ucase ? " TO Group " : " to group ");
         this.printAndAccept(x.getGroups(), ",");
      }

      if (x.getWithGrantOption()) {
         this.print0(this.ucase ? " WITH GRANT OPTION" : " with grant option");
      }

      return false;
   }

   public boolean visit(DB2RevokeStatement x) {
      this.print0(this.ucase ? "REVOKE " : "revoke ");
      if (x.isGrantOptionFor()) {
         this.print0(this.ucase ? "GRANT OPTION FOR " : "grant option for ");
      }

      this.printAndAccept(x.getPrivileges(), ", ");
      this.printRevokeOn(x);
      if (!x.isOn()) {
         this.printUcase(" IN ");
      }

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

      if (x.getUsers() != null && x.getUsers().size() > 0) {
         this.print0(this.ucase ? " FROM " : " from ");
         this.printAndAccept(x.getUsers(), ",");
      }

      if (x.getGroups() != null && x.getGroups().size() > 0) {
         this.print0(this.ucase ? " FROM Group " : " from group ");
         this.printAndAccept(x.getGroups(), ",");
      }

      if (x.isCascade()) {
         this.printUcase(" CASCADE");
      }

      if (x.isRestrict()) {
         this.printUcase(" RESTRICT");
      }

      return false;
   }

   public void endVisit(DB2CreateTriggerStatement x) {
   }

   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(SQLDB2TimeIntervalDataType x) {
      this.printUcase("INTERVAL ");
      this.printUcase(x.getIntervalTime() + " ");
      this.printUcase("TO ");
      this.printUcase(x.getToTime() + " ");
      return false;
   }

   public boolean visit(SQLArrayDataType x) {
      x.getComponentType().accept(this);
      this.print('[');
      this.printAndAccept(x.getArguments(), ", ");
      this.print(']');
      return false;
   }

   public boolean visit(DB2ExprTableSource ts) {
      if (ts.isOnly()) {
         this.print0(" ONLY ");
      }

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

      if (ts.getAlias() != null) {
         this.print0(" AS ");
         this.print0(ts.getAlias());
         this.print0(" ");
      }

      if (ts.getColumns() != null && ts.getColumns().size() > 0) {
         this.print0("(");

         for(int i = 0; i < ts.getColumns().size(); ++i) {
            ((SQLName)ts.getColumns().get(i)).accept(this);
            if (i != ts.getColumns().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

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

      return false;
   }

   public void endVisit(DB2SubqueryTableSource x) {
   }

   public boolean visit(DB2SubqueryTableSource ts) {
      if (ts.isOnly()) {
         this.print0(" ONLY ");
      }

      if (ts.getSelect() != null) {
         this.print0("(");
         ts.getSelect().accept(this);
         this.print0(")");
      }

      if (ts.getAlias() != null) {
         this.print0(" AS ");
         this.print0(ts.getAlias());
         this.print0(" ");
      }

      if (ts.getColumns() != null && ts.getColumns().size() > 0) {
         this.print0("(");

         for(int i = 0; i < ts.getColumns().size(); ++i) {
            ((SQLName)ts.getColumns().get(i)).accept(this);
            if (i != ts.getColumns().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      return false;
   }

   public void endVisit(DB2ValuesTableSource x) {
   }

   public boolean visit(DB2MethodInvokeTableSource ts) {
      if (ts.isOnly()) {
         this.print0(" ONLY ");
      }

      ts.getExpr().accept(this);
      this.print0("(");

      for(int i = 0; i < ts.getParameters().size(); ++i) {
         ((SQLExpr)ts.getParameters().get(i)).accept(this);
         if (i != ts.getParameters().size() - 1) {
            this.print0(",");
         }
      }

      this.print0(")");
      if (ts.isWithOrdinality()) {
         this.print0(this.ucase ? " WITH ORDINALITY " : " with ordinality ");
      }

      if (ts.getAlias() != null) {
         this.print0(this.ucase ? " AS " : " as ");
         this.print0(ts.getAlias());
      }

      List<DB2ColumnSimpleDefinitionExpr> defines = ts.getDefines();
      boolean flag = false;
      if (defines != null && defines.size() > 0) {
         flag = true;
         this.print0(this.ucase ? " AS (" : " as (");

         for(int i = 0; i < defines.size(); ++i) {
            DB2ColumnSimpleDefinitionExpr def = (DB2ColumnSimpleDefinitionExpr)defines.get(i);
            def.getName().accept(this);
            if (def.getType() != null) {
               this.print0(" ");
               def.getType().accept(this);
            }

            if (i != defines.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      if (!flag && ts.getColumns() != null && ts.getColumns().size() > 0) {
         this.print0("(");

         for(int i = 0; i < ts.getColumns().size(); ++i) {
            ((SQLName)ts.getColumns().get(i)).accept(this);
            if (i != ts.getColumns().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      return false;
   }

   public void endVisit(DB2ExprTableSource x) {
   }

   public boolean visit(DB2RowsFromTableSource ts) {
      this.print0(this.ucase ? "ROWS FROM (" : "rows from (");

      for(int i = 0; i < ts.getInvokers().size(); ++i) {
         ((DB2MethodInvokeTableSource)ts.getInvokers().get(i)).accept(this);
         if (i != ts.getInvokers().size() - 1) {
            this.print0(",");
         }
      }

      this.print0(")");
      if (ts.isWithOrdinality()) {
         this.print0(this.ucase ? " WITH ORDINALITY " : " with ordinality ");
      }

      if (ts.getAlias() != null) {
         this.print0(this.ucase ? " AS " : " as ");
         this.print0(ts.getAlias());
      }

      if (ts.getColumns() != null && ts.getColumns().size() > 0) {
         this.print0("(");

         for(int i = 0; i < ts.getColumns().size(); ++i) {
            ((SQLName)ts.getColumns().get(i)).accept(this);
            if (i != ts.getColumns().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      if (ts.isRowsFrom()) {
         this.print0(") ");
      }

      return false;
   }

   public void endVisit(DB2AlterDatabaseStatement x) {
   }

   public boolean visit(DB2ValuesTableSource ts) {
      this.println();
      this.print0("(");
      this.print0(this.ucase ? "VALUES " : "values ");

      for(int i = 0; i < ts.getRows().size(); ++i) {
         DB2ValuesTableSource.ValueRow row = (DB2ValuesTableSource.ValueRow)ts.getRows().get(i);
         this.print0("(");

         for(int j = 0; j < row.getVals().size(); ++j) {
            ((SQLExpr)row.getVals().get(j)).accept(this);
            if (j != row.getVals().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
         if (i != ts.getRows().size() - 1) {
            this.print0(",");
         }
      }

      this.print0(") ");
      this.print0(ts.getAlias());
      if (ts.getColumns().size() > 0) {
         List<SQLName> columns = ts.getColumns();
         this.print0(" (");

         for(int i = 0; i < columns.size(); ++i) {
            ((SQLName)columns.get(i)).accept(this);
            if (i != columns.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      return false;
   }

   public void endVisit(DB2ValuesTableSource.ValueRow x) {
   }

   public boolean visit(DB2ValuesTableSource.ValueRow x) {
      return true;
   }

   public void endVisit(DB2SelectQueryBlock.ForClauses x) {
   }

   public boolean visit(DB2AlterDatabaseStatement x) {
      this.print0(this.ucase ? "ALTER DATABASE " : "alter database ");
      x.getName().accept(this);
      this.print0(" ");
      if (x.getNewName() != null) {
         this.print0(this.ucase ? "RENAME TO " : "rename to ");
         x.getNewName().accept(this);
      } else if (x.getNewOwner() != null) {
         this.print0(this.ucase ? "OWNER TO " : "owner to ");
         x.getNewOwner().accept(this);
      } else if (x.isSet()) {
         this.printUcase("SET ");
         if (x.isDefaultSchema()) {
            this.printUcase("DEFAULT SCHEMA ");
            x.getDefaultSchemaName().accept(this);
         } else if (x.isDefaultCharacterSetLatin9()) {
            this.printUcase("DEFAULT CHARACTER SET LATIN9 ");
         }
      } else if (x.isCollectHistory()) {
         this.printUcase("COLLECT HISTORY ");
         x.getCollectHistoryType().accept(this);
      } else if (x.isDataVersionRetentionTime()) {
         this.printUcase("DATA_VERSION_RETENTION_TIME ");
         x.getDataVersionRetentionTimeNum().accept(this);
         this.print(" NOCASCADE ");
      } else if (x.isGroomBackupset()) {
         this.printUcase("GROOM BACKUPSET ");
         x.getGroomBackupsetNum().accept(this);
      }

      return false;
   }

   public void endVisit(DB2AlterIndexStatement x) {
   }

   public boolean visit(DB2AlterIndexStatement x) {
      this.print0(this.ucase ? "ALTER INDEX " : "alter index ");
      x.getName().accept(this);
      if (x.getRenameTo() != null) {
         this.print0(this.ucase ? " RENAME TO " : " rename to ");
         x.getRenameTo().accept(this);
      }

      if (x.isReorganize()) {
         this.printUcase(" REORGANIZE ");
         if (x.isOn()) {
            this.printUcase("ON ");
            if (x.getTableName() != null) {
               x.getTableName().accept(this);
            }
         }
      }

      if (x.isSetTableSpace()) {
         this.printUcase(" WITH TABLESPACE ");
         if (x.getNewTableSpace() != null) {
            x.getNewTableSpace().accept(this);
         }
      }

      return false;
   }

   public void endVisit(DB2AlterSequenceStatement x) {
   }

   public boolean visit(DB2AlterSequenceStatement x) {
      this.print0(this.ucase ? "ALTER " : "alter ");
      if (x.isLarge()) {
         this.print0(this.ucase ? "LARGE " : "large ");
      }

      this.print0(this.ucase ? "SEQUENCE " : "sequence ");
      if (x.isIfExists()) {
         this.printUcase("IF EXISTS ");
      }

      x.getName().accept(this);
      if (x.getIncrementBy() != null) {
         this.print0(this.ucase ? " INCREMENT " : " increment ");
         if (x.isBy()) {
            this.print0(this.ucase ? "BY " : "by ");
         }

         x.getIncrementBy().accept(this);
      }

      if (x.getMinValue() != null) {
         this.print0(this.ucase ? " MINVALUE " : " minvalue ");
         x.getMinValue().accept(this);
      }

      if (x.getMaxValue() != null) {
         this.print0(this.ucase ? " MAXVALUE " : " maxvalue ");
         x.getMaxValue().accept(this);
      }

      if (x.isNoMaxValue()) {
         this.print0(this.ucase ? " NO MAXVALUE" : " no maxvalue");
      }

      if (x.isNoMinValue()) {
         this.print0(this.ucase ? " NO MINVALUE" : " no minvalue");
      }

      if (x.getStartWith() != null) {
         this.print0(this.ucase ? " START " : " start ");
         if (x.isStart()) {
            this.print0(this.ucase ? "WITH " : "with ");
         }

         x.getStartWith().accept(this);
      }

      SQLExpr restartWith = x.getRestartWith();
      if (restartWith != null) {
         this.print0(this.ucase ? " RESTART" : " restart");
         if (x.isRestart()) {
            this.print0(this.ucase ? " WITH " : " with ");
         }

         restartWith.accept(this);
      }

      Boolean cache = x.getCache();
      if (cache != null && cache) {
         this.print0(this.ucase ? " CACHE " : " cache ");
         SQLExpr cacheValue = x.getCacheValue();
         if (cacheValue != null) {
            cacheValue.accept(this);
         }
      }

      if (x.getCycle() != null) {
         if (x.isCycleNo()) {
            this.print0(this.ucase ? " NO" : " no");
         }

         if (x.getCycle()) {
            this.print0(this.ucase ? " CYCLE" : " cycle");
         }
      }

      if (x.isOwnedBy()) {
         this.print0(this.ucase ? " OWNED BY " : " owned by ");
         x.getOwnedByName().accept(this);
      }

      if (x.isNone()) {
         this.print0(this.ucase ? " NONE " : " none ");
      }

      if (x.isOwnerTo()) {
         this.print0(this.ucase ? " OWNER TO " : " owner to ");
         x.getNewOwner().accept(this);
      }

      if (x.isRenameTo()) {
         this.print0(this.ucase ? " RENAME TO " : " rename to ");
         x.getNewName().accept(this);
      }

      if (x.isSetSchema()) {
         this.print0(this.ucase ? " SET SCHEMA " : " set schema ");
         x.getNewSchema().accept(this);
      }

      return false;
   }

   public void endVisit(DB2AlterTableStatement x) {
   }

   public boolean visit(DB2AlterTableStatement stmt) {
      this.print0(this.ucase ? "ALTER TABLE " : "alter table ");
      if (stmt.isIfExists()) {
         this.print0(this.ucase ? "IF EXISTS " : "if exists ");
      }

      if (stmt.isOnly()) {
         this.print0(this.ucase ? "ONLY " : "only ");
      }

      if (stmt.getTableName() != null) {
         stmt.getName().accept(this);
      }

      this.print0(" ");
      if (stmt.isPrivileges()) {
         this.printUcase("SET PRIVILEGES TO ");
         stmt.getTableSource().accept(this);
      }

      for(int i = 0; i < stmt.getItems().size(); ++i) {
         this.println();
         this.print("\t");
         ((SQLAlterTableItem)stmt.getItems().get(i)).accept(this);
         if (i != stmt.getItems().size() - 1) {
            this.print0(",");
         }
      }

      return false;
   }

   public void endVisit(DB2AlterTableRenameColumn x) {
   }

   public boolean visit(DB2AlterTableRenameColumn item) {
      this.print0(this.ucase ? "RENAME COLUMN " : "rename column ");
      item.getCol().accept(this);
      this.print0(this.ucase ? " TO " : " to ");
      item.getTo().accept(this);
      return false;
   }

   public void endVisit(DB2AlterTableRenameConstraint x) {
   }

   public boolean visit(DB2AlterTableRenameConstraint item) {
      this.print0(this.ucase ? "RENAME CONSTRAINT " : "rename constraint ");
      item.getCol().accept(this);
      this.print0(this.ucase ? " TO " : " to ");
      item.getTo().accept(this);
      return false;
   }

   public void endVisit(DB2AlterTableRenameTo x) {
   }

   public boolean visit(DB2AlterTableRenameTo item) {
      this.print0(this.ucase ? "RENAME TO " : "rename to ");
      item.getTo().accept(this);
      return false;
   }

   public void endVisit(DB2AlterTableSetSchema x) {
   }

   public boolean visit(DB2AlterTableSetSchema item) {
      this.print0(this.ucase ? "SET SCHEMA " : "set schema ");
      item.getSchema().accept(this);
      return false;
   }

   public void endVisit(DB2AlterTableSetNewTableSpace x) {
   }

   public boolean visit(DB2AlterTableSetNewTableSpace item) {
      this.print0(this.ucase ? "ALL IN TABLESPACE " : "all in tablespace ");
      item.getName().accept(this);
      this.print0(" ");
      if (item.getOwners() != null && item.getOwners().size() > 0) {
         this.print0(this.ucase ? "OWNED BY " : "owned by ");

         for(int i = 0; i < item.getOwners().size(); ++i) {
            ((SQLExpr)item.getOwners().get(i)).accept(this);
            if (i != item.getOwners().size() - 1) {
               this.print(",");
            }
         }

         this.print0(" ");
      }

      this.print0(this.ucase ? "SET TABLESPACE " : "set tablespace ");
      item.getNewTablespace().accept(this);
      if (item.isNowait()) {
         this.print0(this.ucase ? " NOWAIT " : " nowait ");
      }

      return false;
   }

   public void endVisit(DB2AlterTableSetWith x) {
   }

   public boolean visit(DB2AlterTableSetWith item) {
      this.print0(this.ucase ? "SET " : "set ");
      switch (item.getDistributeType()) {
         case with:
            this.print0(this.ucase ? "WITH (REORGANIZE=" : "with (reorganize=");
            this.print0(item.isWithReorgnize() ? "true" : "false");
            this.print0(")");
            break;
         case by:
            this.print0(this.ucase ? "DISTRIBUTED BY (" : "distributed by (");

            for(int i = 0; i < item.getOptions().size(); ++i) {
               DB2AlterTableSetWith.DB2AlterTableDistributeByOption option = (DB2AlterTableSetWith.DB2AlterTableDistributeByOption)item.getOptions().get(i);
               option.getColumnName().accept(this);
               if (option.getOpClass() != null) {
                  this.print0(" ");
                  option.getOpClass().accept(this);
               }

               if (i != item.getOptions().size() - 1) {
                  this.print0(",");
               }
            }

            this.print0(")");
            break;
         case randomly:
            this.print0(this.ucase ? "DISTRIBUTED RANDOMLY" : "distributed randomly");
            break;
         case replicated:
            this.print0(this.ucase ? "DISTRIBUTED REPLICATED" : "distributed replicated");
      }

      return false;
   }

   public void endVisit(DB2AlterTableAddColumn x) {
   }

   public boolean visit(DB2AlterTableAddColumn item) {
      this.print0(this.ucase ? "ADD COLUMN " : "add column ");
      DB2ColumnDefinition column = (DB2ColumnDefinition)item.getColumns().get(0);
      column.getName().accept(this);
      this.print0(" ");
      column.getType().accept(this);
      this.print0(" ");
      SQLExpr defaultExpr = column.getDefaultExpr();
      if (defaultExpr != null) {
         this.print0(this.ucase ? "DEFAULT " : "default ");
         defaultExpr.accept(this);
         this.print0(" ");
      }

      List<SQLColumnConstraint> constraints = column.getConstraints();
      if (constraints != null && constraints.size() > 0) {
         for(SQLColumnConstraint constraint : constraints) {
            constraint.accept(this);
            this.print0(" ");
         }
      }

      SQLExpr collateExpr = column.getCollateExpr();
      if (collateExpr != null) {
         this.print0(this.ucase ? "COLLATE " : "collate ");
         collateExpr.accept(this);
         this.print0(" ");
      }

      List<SQLExpr> encodings = column.getEncodings();
      if (encodings != null && encodings.size() > 0) {
         this.print0(this.ucase ? "ENCODING (" : "encoding (");

         for(int i = 0; i < encodings.size(); ++i) {
            ((SQLExpr)encodings.get(i)).accept(this);
            if (i != encodings.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      return false;
   }

   public void endVisit(DB2AlterTableSetWith.DB2AlterTableDistributeByOption x) {
   }

   public boolean visit(DB2AlterTableSetWith.DB2AlterTableDistributeByOption x) {
      return true;
   }

   public void endVisit(DB2AlterTableDropColumn x) {
   }

   public boolean visit(DB2AlterTableDropColumn item) {
      this.print0(this.ucase ? "DROP COLUMN " : "drop column ");
      if (item.isIfExists()) {
         this.print0(this.ucase ? "IF EXISTS " : "if exists ");
      }

      item.getColumnName().accept(this);
      this.print0(" ");
      DB2AlterTableDropColumn.DropColumType type = item.getType();
      if (type != null) {
         if (type == DB2AlterTableDropColumn.DropColumType.restrict) {
            this.print0(this.ucase ? "RESTRICT " : "restrict ");
         } else {
            this.print0(this.ucase ? "CASCADE " : "cascade ");
         }
      }

      return false;
   }

   public void endVisit(DB2AlterTableAlterColumn x) {
   }

   public boolean visit(DB2AlterTableAlterColumn item) {
      this.print0(this.ucase ? "ALTER COLUMN " : "alter column ");
      item.getColumn().accept(this);
      this.print0(" ");
      switch (item.getType()) {
         case setType:
            this.print0(this.ucase ? "SET DATA TYPE " : "set data type ");
            item.getDataType().accept(this);
            this.print0(" ");
            SQLExpr collation = item.getCollation();
            if (collation != null) {
               this.print0(this.ucase ? "COLLATE " : "collate ");
               collation.accept(this);
               this.print0(" ");
            }

            SQLExpr usingExpression = item.getUsingExpression();
            if (usingExpression != null) {
               this.print0(this.ucase ? "USING " : "using ");
               usingExpression.accept(this);
               this.print0(" ");
            }
            break;
         case setDefault:
            this.print0(this.ucase ? "SET DEFAULT " : "set default ");
            item.getDefaultExpression().accept(this);
            break;
         case dropDefault:
            this.print0(this.ucase ? "DROP DEFAULT " : "drop default ");
            break;
         case setNotNull:
            this.print0(this.ucase ? "SET NOT NULL " : "set not null ");
            break;
         case dropNotNull:
            this.print0(this.ucase ? "DROP NOT NULL " : "drop not null ");
            break;
         case setStatistics:
            this.print0(this.ucase ? "SET STATISTICS " : "set statistics ");
            item.getStatics().accept(this);
            this.print0(" ");
      }

      return false;
   }

   public void endVisit(DB2AlterTableAlterColumnOptions x) {
   }

   public boolean visit(DB2AlterTableAlterColumnOptions item) {
      this.print0(this.ucase ? "ALTER COLUMN COLUMN " : "alter column column ");
      if (item.isSet()) {
         this.print0(this.ucase ? "SET (" : "set (");
      } else {
         this.print0(this.ucase ? "RESET (" : "reset (");
      }

      List<DB2AlterTableAlterColumnOptions.DB2AlterTableAlterColumnOptionValue> options = item.getOptions();

      for(int i = 0; i < options.size(); ++i) {
         DB2AlterTableAlterColumnOptions.DB2AlterTableAlterColumnOptionValue option = (DB2AlterTableAlterColumnOptions.DB2AlterTableAlterColumnOptionValue)options.get(i);
         option.getAttribute().accept(this);
         SQLExpr value = option.getValue();
         if (value != null) {
            this.print0("=");
            value.accept(this);
         }

         if (i != options.size() - 1) {
            this.print0(",");
         }
      }

      this.print0(") ");
      return false;
   }

   public void endVisit(DB2AlterTableAlterColumnOptions.DB2AlterTableAlterColumnOptionValue x) {
   }

   public boolean visit(DB2AlterTableAlterColumnOptions.DB2AlterTableAlterColumnOptionValue x) {
      return true;
   }

   public void endVisit(DB2AlterTableAddConstraint x) {
   }

   public boolean visit(DB2AlterTableAddConstraint item) {
      this.print0(this.ucase ? "ADD " : "add ");
      if (item.getConstraint() != null) {
         item.getConstraint().accept(this);
      } else if (item.getUsingIndex() != null) {
         DB2AlterTableAddConstraint.DB2AlterTableAddConstraintUsingIndex index = item.getUsingIndex();
         if (index.getConstraint() != null) {
            this.print0(this.ucase ? "CONSTRAINT " : "constraint ");
            index.getConstraint().accept(this);
            this.print0(" ");
         }

         if (index.getType() == DB2AlterTableAddConstraint.DB2AlterTableAddConstraintUsingIndex.ConstraintType.unique) {
            this.print0(this.ucase ? "UNIQUE " : "unique ");
         } else {
            this.print0(this.ucase ? "PRIMARY KEY " : "primary key ");
         }

         this.print0(this.ucase ? "USING INDEX " : "using index ");
         index.getIndexName().accept(this);
         this.print0(" ");
         if (index.getStrategy() != null) {
            switch (index.getStrategy()) {
               case deferable:
                  this.print0(this.ucase ? "DEFERRABLE " : "deferrable");
                  break;
               case notDeferable:
                  this.print0(this.ucase ? "NOT DEFERRABLE " : "not deferrable");
                  break;
               case initiallyDefered:
                  this.print0(this.ucase ? "INITIALLY DEFERRED " : "initially deferred ");
                  break;
               case initiallyImmediate:
                  this.print0(this.ucase ? "INITIALLY IMMEDIATE " : "initially immediate ");
            }
         }
      }

      return false;
   }

   public void endVisit(DB2AlterTableAddConstraint.DB2AlterTableAddConstraintUsingIndex x) {
   }

   public boolean visit(DB2AlterTableAddConstraint.DB2AlterTableAddConstraintUsingIndex x) {
      return true;
   }

   public void endVisit(DB2AlterTableValidateConstraint x) {
   }

   public boolean visit(DB2AlterTableValidateConstraint item) {
      this.print0(this.ucase ? "VALIDATE CONSTRAINT " : "validate constraint ");
      item.getConstraint().accept(this);
      this.print0(" ");
      return false;
   }

   public void endVisit(DB2AlterTableDropConstraint x) {
   }

   public boolean visit(DB2AlterTableDropConstraint item) {
      this.print0(this.ucase ? "DROP CONSTRAINT " : "drop constraint ");
      if (item.isIfExists()) {
         this.print0(this.ucase ? "IF EXISTS " : "if exists ");
      }

      item.getConstraint().accept(this);
      this.print0(" ");
      DB2AlterTableDropConstraint.DorpType type = item.getType();
      if (type != null) {
         if (type == DB2AlterTableDropConstraint.DorpType.cascade) {
            this.print0(this.ucase ? "RESTRICT " : "restrict ");
         } else {
            this.print0(this.ucase ? "CASCADE " : "cascade ");
         }
      }

      return false;
   }

   public void endVisit(DB2AlterTableDisableEnabelTrigger x) {
   }

   public boolean visit(DB2AlterTableDisableEnabelTrigger item) {
      if (!item.isEnable()) {
         this.print0(this.ucase ? "DISABLE TRIGGER " : "disable trigger ");
      } else {
         this.print0(this.ucase ? "ENABLE TRIGGER " : "enable trigger ");
      }

      if (item.getTrigger() != null) {
         item.getTrigger().accept(this);
      } else if (item.getType() != null) {
         if (item.getType() == DB2AlterTableDisableEnabelTrigger.Type.all) {
            this.print0(this.ucase ? "ALL " : "all ");
         } else {
            this.print0(this.ucase ? "USER " : "user ");
         }
      }

      return false;
   }

   public void endVisit(DB2AlterTableCluster x) {
   }

   public boolean visit(DB2AlterTableCluster item) {
      this.print0(this.ucase ? "CLUSTER ON " : "cluster on ");
      item.getIndex().accept(this);
      this.print0(" ");
      return false;
   }

   public void endVisit(DB2AlterTableSetReset x) {
   }

   public boolean visit(DB2AlterTableSetReset item) {
      if (item.isSet()) {
         this.print0(this.ucase ? "SET " : "set ");
      } else {
         this.print0(this.ucase ? "RESET " : "reset ");
      }

      if (item.isCluster()) {
         this.print0(this.ucase ? "WITHOUT CLUSTER " : "without cluster ");
         return false;
      } else if (item.isOids()) {
         this.print0(this.ucase ? "WITHOUT OIDS" : "without oids ");
         return false;
      } else if (item.getTablespace() != null) {
         this.print0(this.ucase ? "TABLESPACE  " : "tablespace ");
         item.getTablespace().accept(this);
         this.print0(" ");
         return false;
      } else {
         List<DB2AlterTableSetReset.StorageParameter> parameters = item.getParameters();
         if (parameters != null && parameters.size() > 0) {
            this.print0("(");

            for(int i = 0; i < parameters.size(); ++i) {
               DB2AlterTableSetReset.StorageParameter parameter = (DB2AlterTableSetReset.StorageParameter)parameters.get(i);
               parameter.getParameter().accept(this);
               SQLExpr value = parameter.getValue();
               if (value != null) {
                  this.print0("=");
                  value.accept(this);
               }

               if (i != parameters.size() - 1) {
                  this.print0(",");
               }
            }

            this.print0(")");
         }

         return false;
      }
   }

   public void endVisit(DB2AlterTableSetReset.StorageParameter x) {
   }

   public boolean visit(DB2AlterTableSetReset.StorageParameter x) {
      return true;
   }

   public void endVisit(DB2AlterTableInheriteOrNotParentTable x) {
   }

   public boolean visit(DB2AlterTableInheriteOrNotParentTable item) {
      if (item.isInherite()) {
         this.print0(this.ucase ? "INHERIT " : "inherit ");
      } else {
         this.print0(this.ucase ? "NO INHERIT " : "no inherit ");
      }

      item.getParentTable().accept(this);
      this.print0(" ");
      return false;
   }

   public void endVisit(DB2AlterTableOf x) {
   }

   public boolean visit(DB2AlterTableOf item) {
      if (item.isOf()) {
         this.print0(this.ucase ? "OF " : "of ");
         item.getTypeName().accept(this);
      }

      if (item.isNotOf()) {
         this.print0(this.ucase ? "NOT OF " : "not of ");
      }

      if (item.isOwn()) {
         this.print0(this.ucase ? "OWNER TO  " : "owner to  ");
         item.getNewOwner().accept(this);
      }

      this.print0(" ");
      return false;
   }

   public void endVisit(DB2AlterTableSetTableSpace x) {
   }

   public boolean visit(DB2AlterTableSetTableSpace item) {
      this.print0(this.ucase ? "SET TABLESPACE " : "set tablespace ");
      item.getName().accept(this);
      return false;
   }

   public void endVisit(DB2CreateDatabaseStatement x) {
   }

   public boolean visit(DB2CreateDatabaseStatement x) {
      this.print0(this.ucase ? "CREATE DATABSE " : "create database ");
      x.getName().accept(this);
      this.print0(" ");
      if (x.isWithAndSoOn()) {
         this.printUcase("WITH DEFAULT CHARACTER SET LATIN9 COLLATION BINARY ");
      }

      if (x.isCollectHistory()) {
         this.printUcase("COLLECT HISTORY ");
         x.getCollectHistoryType().accept(this);
         this.print(" ");
      }

      if (x.isDataVersionRetentionTime()) {
         this.printUcase("DATA_VERSION_RETENTION_TIME ");
         x.getDataVersionRetentionTimeNum().accept(this);
      }

      return false;
   }

   public void endVisit(DB2Constraint x) {
   }

   public boolean visit(DB2CreateTableStatement stmt) {
      this.print0(this.ucase ? "CREATE " : "create ");
      if (stmt.getTableType() != null) {
         switch (stmt.getTableType()) {
            case GLOBAL_TEMPORARY:
               this.print0(this.ucase ? "GLOBAL TEMPORARY " : "golbal temporary ");
               break;
            case LOCAL_TEMPORARY:
               this.print0(this.ucase ? "LOCAL TEMPORARY " : "local temporary ");
               break;
            case GLOBAL_TEMP:
               this.print0(this.ucase ? "GLOBAL TEMP " : "golbal temp ");
               break;
            case LOCAL_TEMP:
               this.print0(this.ucase ? "LOCAL TEMP " : "local temp ");
               break;
            case GLOBAL_UNLOGGED:
               this.print0(this.ucase ? "GLOBAL UNLOGGED " : "golbal unlogged ");
               break;
            case LOCAL_UNLOGGED:
               this.print0(this.ucase ? "LOCAL UNLOGGED " : "local unlogged ");
               break;
            case TEMPORARY:
               this.print0(this.ucase ? "TEMPORARY " : "temporary ");
               break;
            case TEMP:
               this.print0(this.ucase ? "TEMP " : "temp ");
               break;
            case UNLOGGED:
               this.print0(this.ucase ? "UNLOGGED " : "unlogged ");
         }
      }

      this.print0(this.ucase ? "TABLE " : "table ");
      if (stmt.isIfNotExists()) {
         this.print0(this.ucase ? "IF NOT EXISTS " : "if not exists ");
      }

      stmt.getTableSource().accept(this);
      this.print0(" ");
      if (stmt.getOfType() != null) {
         this.print0(this.ucase ? "OF " : "of ");
         stmt.getOfType().accept(this);
         this.print0(" ");
      }

      if (stmt.getTableElementList() != null && stmt.getTableElementList().size() > 0) {
         this.print0("(");

         for(int i = 0; i < stmt.getTableElementList().size(); ++i) {
            this.println();
            SQLTableElement element = (SQLTableElement)stmt.getTableElementList().get(i);
            element.accept(this);
            if (i != stmt.getTableElementList().size() - 1) {
               this.print0(",");
            }
         }

         this.println();
         this.print0(")");
      }

      List<SQLExpr> parentTables = stmt.getParentTables();
      if (parentTables != null && parentTables.size() > 0) {
         this.println();
         this.print0(this.ucase ? "INHERITS " : "inherits ");
         this.print0("(");

         for(int i = 0; i < parentTables.size(); ++i) {
            ((SQLExpr)parentTables.get(i)).accept(this);
            if (i != parentTables.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      if (stmt.getParameters() != null && stmt.getParameters().size() > 0) {
         this.println();
         this.print0(this.ucase ? "WITH " : "with ");
         this.print0("(");

         for(int i = 0; i < stmt.getParameters().size(); ++i) {
            DB2StorageParameter paramter = (DB2StorageParameter)stmt.getParameters().get(i);
            paramter.accept(this);
            this.println();
            if (i != stmt.getParameters().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      if (stmt.getTableOptions() != null && stmt.getTableOptions().size() > 0) {
         this.println();
         this.print0(this.ucase ? "WITH " : "with ");
         this.print0("(");

         for(int i = 0; i < stmt.getTableOptions().size(); ++i) {
            SQLAssignItem paramter = (SQLAssignItem)stmt.getTableOptions().get(i);
            paramter.accept(this);
            this.println();
            if (i != stmt.getTableOptions().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      if (stmt.getOnCommit() != null) {
         this.println();
         this.print0(this.ucase ? "ON COMMIT " : "on commit ");
         switch (stmt.getOnCommit()) {
            case preserveRows:
               this.print0(this.ucase ? "PRESERVE ROWS" : "preserve rows");
               break;
            case deleteRows:
               this.print0(this.ucase ? "DELETE ROWS" : "delete rows");
               break;
            case drop:
               this.print0(this.ucase ? "DROP" : "drop");
         }
      }

      if (stmt.getTablespace() != null) {
         this.println();
         this.print0(this.ucase ? "TABLESPACE " : "tablespace ");
         stmt.getTablespace().accept(this);
      }

      if (stmt.getSelect() != null) {
         this.printUcase(" AS ");
         stmt.getSelect().accept(this);
         if (stmt.getWithData() != null && stmt.getWithData()) {
            this.printUcase(" WITH DATA ");
         }

         if (stmt.getWithNoData() != null && stmt.getWithNoData()) {
            this.printUcase(" WITH NO DATA ");
         }
      }

      if (stmt.getDistributedBy() != null) {
         this.println();
         stmt.getDistributedBy().accept(this);
      }

      if (stmt.getPartitioning() != null) {
         this.println();
         stmt.getPartitioning().accept(this);
      }

      if (stmt.getDistributeOn()) {
         this.println();
         this.printUcase("DISTRIBUTE ON ");
         if (stmt.getRandom()) {
            this.printUcase("RANDOM ");
         }

         if (stmt.getHash()) {
            this.printUcase("HASH ");
            this.print0("(");
            this.printAndAccept(stmt.getHashCols().getItems(), ", ");
            this.print0(")");
         }
      }

      if (stmt.getOrganizeOn()) {
         this.println();
         this.printUcase("ORGANIZE ON ");
         if (stmt.getOrganizeOnCol() != null) {
            this.print0("(");
            stmt.getOrganizeOnCol().accept(this);
            this.print0(")");
         }

         if (stmt.getNone()) {
            this.printUcase("NONE ");
         }
      }

      if (stmt.getRowSecurity()) {
         this.println();
         this.printUcase("ROW SECURITY ");
      }

      if (stmt.isDataVersionRetentionTime()) {
         this.println();
         this.printUcase("DATA_VERSION_RETENTION_TIME ");
         stmt.getDataVersionRetentionTimeNum().accept(this);
      }

      return false;
   }

   public void endVisit(DB2CreateTableStatement.DB2TableDistributedBy x) {
   }

   public boolean visit(DB2ColumnDefinition d) {
      this.incrementIndent();
      this.printIndent();
      d.getName().accept(this);
      this.space();
      if (d.isWith()) {
         this.print0(this.ucase ? "WITH OPTIONS " : "with options ");
      } else {
         if (d.getType() != null) {
            d.getType().accept(this);
         } else if (d.getDataType() != null) {
            d.getDataType().accept(this);
         }

         this.space();
         if (d.getCollateExpr() != null) {
            this.print0(this.ucase ? "COLLATE " : "collate ");
            d.getCollateExpr().accept(this);
         }
      }

      List<SQLColumnConstraint> constraints = d.getConstraints();
      if (constraints != null && constraints.size() > 0) {
         for(int i = 0; i < constraints.size(); ++i) {
            ((SQLColumnConstraint)constraints.get(i)).accept(this);
         }
      }

      List<SQLExpr> encodings = d.getEncodings();
      if (encodings != null && encodings.size() > 0) {
         this.println();
         this.print0(this.ucase ? "ENCODING " : "encoding ");
         this.print0("(");

         for(int i = 0; i < encodings.size(); ++i) {
            SQLExpr sqlExpr = (SQLExpr)encodings.get(i);
            sqlExpr.accept(this);
            if (i != encodings.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

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

      if (d.getLike() != null) {
         this.print0(this.ucase ? "LIKE " : "like ");
         d.getLike().accept(this);
         this.space();
         List<DB2ColumnDefinition.ColumnLikeOption> likeOptions = d.getLikeOptions();
         if (likeOptions != null && likeOptions.size() > 0) {
            for(int i = 0; i < likeOptions.size(); ++i) {
               DB2ColumnDefinition.ColumnLikeOption option = (DB2ColumnDefinition.ColumnLikeOption)likeOptions.get(i);
               switch (option.getIncludeType()) {
                  case including:
                     this.print0(this.ucase ? "INCLUDING " : "including ");
                     break;
                  case excluding:
                     this.print0(this.ucase ? "EXCLUDING " : "excluding ");
               }

               switch (option.getOption()) {
                  case defaults:
                     this.print0(this.ucase ? "DEFAULTS " : "defaults ");
                     break;
                  case constraints:
                     this.print0(this.ucase ? "CONSTRAINTS " : "constraints ");
                     break;
                  case indexes:
                     this.print0(this.ucase ? "INDEXES " : "indexes ");
                     break;
                  case storage:
                     this.print0(this.ucase ? "STORAGE " : "storage ");
                     break;
                  case comments:
                     this.print0(this.ucase ? "COMMENTS " : "comments ");
                     break;
                  case all:
                     this.print0(this.ucase ? "ALL " : "all ");
               }
            }
         }
      }

      List<DB2Constraint.DB2Reference> columnReferenceStorageDirectives = d.getColumnReferenceStorageDirectives();
      if (columnReferenceStorageDirectives != null && columnReferenceStorageDirectives.size() > 0) {
         for(int i = 0; i < columnReferenceStorageDirectives.size(); ++i) {
            DB2Constraint.DB2Reference DB2Reference = (DB2Constraint.DB2Reference)columnReferenceStorageDirectives.get(i);
            DB2Reference.accept(this);
            if (i != columnReferenceStorageDirectives.size() - 1) {
               this.print0(",");
            }
         }
      }

      this.decrementIndent();
      return false;
   }

   public void endVisit(DB2CreateTableStatement x) {
   }

   public boolean visit(DB2Constraint constraint) {
      if (constraint.getName() != null) {
         this.println();
         this.print0(this.ucase ? "CONSTRAINT " : "constraint ");
         constraint.getName().accept(this);
      }

      if (constraint.getiNull() != null && constraint.getiNull()) {
         this.println();
         this.print0(this.ucase ? "NULL " : "null ");
      }

      if (constraint.getNotNull() != null && constraint.getNotNull()) {
         this.println();
         this.print0(this.ucase ? "NOT NULL " : "not null ");
      }

      if (constraint.getCheck() != null) {
         this.println();
         this.print0(this.ucase ? "CHECK " : "check ");
         this.print0("(");
         constraint.getCheck().getExpr().accept(this);
         this.print0(")");
         this.space();
         if (constraint.getCheck().isNoInherit()) {
            this.print0(this.ucase ? "NO INHERIT " : "no inherit ");
         }
      }

      if (constraint.getDefValue() != null) {
         this.println();
         this.print0(this.ucase ? "DEFAULT " : "default ");
         constraint.getDefValue().accept(this);
      }

      if (constraint.getUnique() != null) {
         this.println();
         this.print0(this.ucase ? "UNIQUE " : "unique ");
         List<SQLName> columns = constraint.getUnique().getColumns();
         if (columns != null && columns.size() > 0) {
            this.print0("(");

            for(int i = 0; i < columns.size(); ++i) {
               ((SQLName)columns.get(i)).accept(this);
               if (i != columns.size() - 1) {
                  this.print0(",");
               }
            }

            this.print0(") ");
         }

         DB2Constraint.DB2IndexParamaters indexParamaters = constraint.getUnique().getIndexParamaters();
         if (indexParamaters != null) {
            indexParamaters.accept(this);
         }
      }

      if (constraint.getPrimaryKey() != null) {
         this.println();
         this.print0(this.ucase ? "PRIMARY KEY " : "primary key ");
         DB2Constraint.DB2IndexParamaters indexParamaters = constraint.getPrimaryKey().getIndexParamaters();
         if (indexParamaters != null) {
            indexParamaters.accept(this);
         }
      }

      if (constraint.getReference() != null) {
         this.println();
         constraint.getReference().accept(this);
      }

      if (constraint.getType() != null) {
         switch (constraint.getType()) {
            case deferrable:
               this.print0(this.ucase ? "DEFERRABLE " : "deferrable ");
               break;
            case notDeferrable:
               this.print0(this.ucase ? "NOT DEFERRABLE " : "not deferrable ");
               break;
            case initiallyDeferred:
               this.print0(this.ucase ? "INITIALLY DEFERRED " : "initially deferred ");
               break;
            case initiallyImmediate:
               this.print0(this.ucase ? "INITIALLY IMMEDIATE " : "initially immediate ");
         }
      }

      return false;
   }

   public void endVisit(DB2Constraint.DB2ConstraintCheck x) {
   }

   public boolean visit(DB2Constraint.DB2ConstraintCheck x) {
      return true;
   }

   public void endVisit(DB2Constraint.DB2Unique x) {
   }

   public boolean visit(DB2Constraint.DB2Unique x) {
      return true;
   }

   public void endVisit(DB2Constraint.DB2PrimaryKey x) {
   }

   public boolean visit(DB2Constraint.DB2PrimaryKey x) {
      return true;
   }

   public void endVisit(DB2Constraint.DB2ForeignKey x) {
   }

   public boolean visit(DB2Constraint.DB2ForeignKey x) {
      return true;
   }

   public void endVisit(DB2OptionValue x) {
   }

   public boolean visit(DB2Constraint.DB2IndexParamaters r) {
      List<DB2StorageParameter> parameters = r.getParameters();
      if (parameters != null && parameters.size() > 0) {
         this.print0(this.ucase ? "WITH (" : "with (");

         for(int i = 0; i < parameters.size(); ++i) {
            ((DB2StorageParameter)parameters.get(i)).accept(this);
            if (i != parameters.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(") ");
      }

      if (r.getTablespace() != null) {
         this.print0(this.ucase ? "USING INDEX TABLESPACE " : "using index tablespace ");
         r.getTablespace().accept(this);
         this.space();
      }

      return false;
   }

   public void endVisit(DB2Constraint.DB2Reference x) {
   }

   public boolean visit(DB2Constraint.DB2Reference r) {
      this.print0(this.ucase ? "REFERENCES " : "references ");
      r.getRefTable().accept(this);
      this.space();
      List<SQLExpr> columns = r.getColumns();
      if (columns != null && columns.size() > 0) {
         this.print0("(");

         for(int i = 0; i < columns.size(); ++i) {
            ((SQLExpr)columns.get(i)).accept(this);
            if (i != columns.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(") ");
      }

      DB2Constraint.DB2Reference.MatchType matchType = r.getMatchType();
      if (matchType != null) {
         switch (matchType) {
            case full:
               this.print0(this.ucase ? "MATCH FULL " : "match full ");
               break;
            case partial:
               this.print0(this.ucase ? "MATCH PARTIAL " : "match partial ");
               break;
            case simple:
               this.print0(this.ucase ? "MATCH SIMPLE " : "match simple ");
         }
      }

      if (r.getDeleteAction() != null) {
         this.print0(this.ucase ? "ON DELETE " : "on delete ");
         switch (r.getDeleteAction()) {
            case onDelete:
               this.print0(this.ucase ? "ON DELETE " : "on delete ");
               break;
            case onUpdate:
               this.print0(this.ucase ? "ON UPDATE " : "on update ");
               break;
            case noAction:
               this.print0(this.ucase ? "NO ACTION " : "no action ");
               break;
            case restrict:
               this.print0(this.ucase ? "RESTRICT " : "restrict ");
               break;
            case cascade:
               this.print0(this.ucase ? "CASCADE " : "cascade ");
               break;
            case setNull:
               this.print0(this.ucase ? "SET NULL " : "set null ");
               break;
            case setDefault:
               this.print0(this.ucase ? "SET DEFAULT " : "set default ");
         }
      }

      if (r.getUpdateAction() != null) {
         this.print0(this.ucase ? "ON UPDATE " : "on update ");
         switch (r.getUpdateAction()) {
            case onDelete:
               this.print0(this.ucase ? "ON DELETE " : "on delete ");
               break;
            case onUpdate:
               this.print0(this.ucase ? "ON UPDATE " : "on update ");
               break;
            case noAction:
               this.print0(this.ucase ? "NO ACTION " : "no action ");
               break;
            case restrict:
               this.print0(this.ucase ? "RESTRICT " : "restrict ");
               break;
            case cascade:
               this.print0(this.ucase ? "CASCADE " : "cascade ");
               break;
            case setNull:
               this.print0(this.ucase ? "SET NULL " : "set null ");
               break;
            case setDefault:
               this.print0(this.ucase ? "SET DEFAULT " : "set default ");
         }
      }

      return false;
   }

   public void endVisit(DB2ColumnDefinition x) {
   }

   public boolean visit(DB2CreateTableStatement.DB2TableDistributedBy by) {
      this.print0(this.ucase ? "DISTRIBUTED " : "distributed ");
      List<DB2OptionValue> columns = by.getColumns();
      if (columns != null && columns.size() > 0) {
         this.print0(this.ucase ? "BY (" : "by (");

         for(int i = 0; i < columns.size(); ++i) {
            ((DB2OptionValue)columns.get(i)).accept(this);
            if (i != columns.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(") ");
      }

      DB2CreateTableStatement.DB2TableDistributedBy.Option option = by.getOption();
      if (option != null) {
         switch (option) {
            case randomly:
               this.print0(this.ucase ? "RANDOMLY " : "randomly ");
               break;
            case replicated:
               this.print0(this.ucase ? "REPLICATED " : "replicated ");
         }
      }

      return false;
   }

   public void endVisit(DB2SQLObjectCollection x) {
   }

   public boolean visit(DB2OptionValue value) {
      value.getOption().accept(this);
      if (value.isEq()) {
         if (value.getValue() != null) {
            this.print0("=");
            value.getValue().accept(this);
         }
      } else {
         this.print0(" ");
         if (value.getValue() != null) {
            value.getValue().accept(this);
            this.print0(" ");
         }
      }

      return false;
   }

   public void endVisit(DB2StorageParameter x) {
   }

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

   public void endVisit(DB2Constraint.DB2IndexParamaters x) {
   }

   public boolean visit(DB2SQLObjectCollection datas) {
      if (datas != null && datas.size() > 0) {
         for(int i = 0; i < datas.size(); ++i) {
            datas.get(i).accept(this);
            if (i != datas.size() - 1) {
               this.print0(",");
            }
         }
      }

      return false;
   }

   public void endVisit(DB2SchemaTables x) {
   }

   public boolean visit(DB2SchemaTables datas) {
      if (datas != null && datas.size() > 0) {
         this.print0(this.ucase ? "ALL TABLES IN SCHEMA " : "all tables in schema ");

         for(int i = 0; i < datas.size(); ++i) {
            datas.get(i).accept(this);
            if (i != datas.size() - 1) {
               this.print0(",");
            }
         }
      }

      return false;
   }

   public void endVisit(DB2GrantStatement x) {
   }

   private void space() {
      this.print0(" ");
   }

   public boolean visit(DB2AlterViewStatement x) {
      this.printUcase("ALTER ");
      if (x.isMaterialized()) {
         this.printUcase("MATERIALIZED ");
      }

      if (x.isView()) {
         this.printUcase("VIEW ");
         x.getViewName().accept(this);
         if (x.isRenameTo()) {
            this.print0(this.ucase ? " RENAME TO " : " rename to ");
            x.getNewViewName().accept(this);
         } else if (x.isOwnerTo()) {
            this.print0(this.ucase ? " OWNER TO " : " owner to ");
            x.getNewOwner().accept(this);
         } else if (x.isSet()) {
            this.print0(this.ucase ? " SET " : " set ");
            if (x.isPrivilegesTo()) {
               this.print0(this.ucase ? "PRIVILEGES TO " : "privileges to ");
            }

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

      if (x.isViews() && x.isOn()) {
         this.printUcase("ON ");
         if (x.getTableName() != null) {
            x.getTableName().accept(this);
            this.print(" ");
         }
      }

      if (x.isMaterialize()) {
         this.printUcase(" MATERIALIZE ");
         if (x.isRefresh()) {
            this.printUcase("REFRESH ");
         }

         if (x.isSuspend()) {
            this.printUcase("SUSPEND ");
         }
      }

      return false;
   }

   public boolean visit(DB2CreateSeqenceStatement x) {
      this.print0(this.ucase ? " CREATE " : " create ");
      if (x.isLarge()) {
         this.print0(this.ucase ? " LARGE " : " LARGE ");
      }

      this.print0(this.ucase ? " SEQUENCE " : " sequence ");
      x.getSqeunceName().accept(this);
      if (x.isAs()) {
         this.print0(this.ucase ? " AS " : " as ");
         x.getDataType().accept(this);
         this.print0(" ");
      }

      if (x.isIncrement()) {
         this.print0(this.ucase ? " INCREMENT " : " increment ");
         x.getIncrementValue().accept(this);
      }

      if (x.isIncrementBy()) {
         this.print0(this.ucase ? " INCREMENT BY " : " increment by ");
         x.getIncrementValue().accept(this);
      }

      if (x.isMin()) {
         this.print0(this.ucase ? " MINVALUE " : " minvalue ");
         x.getMinValue().accept(this);
      }

      if (x.isMax()) {
         this.print0(this.ucase ? " MAXVALUE " : " maxvalue ");
         x.getMaxValue().accept(this);
      }

      if (x.isNoMax()) {
         this.print0(this.ucase ? " NO MAXVALUE " : " no maxvalue ");
      }

      if (x.isNoMin()) {
         this.print0(this.ucase ? " NO MINVALUE " : " no minvalue ");
      }

      if (x.isStart()) {
         this.print0(this.ucase ? " START " : " start ");
         x.getStartValue().accept(this);
      }

      if (x.isStartWith()) {
         this.print0(this.ucase ? " START WITH " : " start with ");
         x.getStartValue().accept(this);
      }

      if (x.isCache()) {
         this.print0(this.ucase ? " CACHE " : " cache ");
         x.getCacheName().accept(this);
      }

      if (x.isCycle()) {
         this.print0(this.ucase ? " CYCLE " : " cycle ");
      }

      if (x.isNoCycle()) {
         this.print0(this.ucase ? " NO CYCLE " : " no cycle ");
      }

      if (x.isOwnedBy()) {
         this.print0(this.ucase ? " OWNED BY " : " owned by ");
         x.getOwnedByName().accept(this);
      }

      return false;
   }

   public boolean visit(DB2CreateTableSpaceStatement x) {
      this.print0(this.ucase ? " CREATE TABLESPACE " : " create tablespace ");
      x.getTableSpaceName().accept(this);
      if (x.isIn()) {
         this.printUcase(" IN ");
         x.getGroupName().accept(this);
      }

      if (x.isManagedBy()) {
         this.printUcase(" MANAGED BY ");
         x.getManagedType().accept(this);
      }

      if (x.isExtentsize()) {
         this.printUcase(" EXTENTSIZE ");
         x.getExtentsizeNum().accept(this);
      }

      if (x.isBufferpoo()) {
         this.printUcase(" BUFFERPOOL ");
         x.getBufferpoolName().accept(this);
      }

      if (x.isAutoresize()) {
         this.printUcase(" AUTORESIZE ");
         if (x.isYesOrNo()) {
            this.printUcase("YES ");
         } else {
            this.printUcase("NO ");
         }
      }

      if (x.isMaxsize()) {
         this.printUcase(" MAXSIZE ");
         x.getMaxsizeNum().accept(this);
      }

      if (x.isOverhead()) {
         this.printUcase(" OVERHEAD ");
         x.getOverheadNum().accept(this);
      }

      if (x.isTransferrate()) {
         this.printUcase(" TRANSFERRATE ");
         x.getTransferrateNum().accept(this);
      }

      if (x.isPagesize()) {
         this.printUcase(" PAGESIZE ");
         x.getPagesizeNum().accept(this);
      }

      if (x.isSegsize()) {
         this.printUcase(" SEGSIZE ");
         x.getSegsizeNum().accept(this);
      }

      if (x.isFile()) {
         this.printUcase(" FILE ");
         x.getFileSpecification().accept(this);
      }

      return false;
   }

   public boolean visit(DB2AlterTableSpaceStatement x) {
      this.print0(this.ucase ? "ALTER TABLESPACE " : "alter tablespace ");
      if (x.getTableSpaceName() != null) {
         x.getTableSpaceName().accept(this);
      }

      if (x.isManagedBy()) {
         this.printUcase(" MANAGED BY ");
         x.getManagedType().accept(this);
      }

      if (x.isExtentsize()) {
         this.printUcase(" EXTENTSIZE ");
         x.getExtentsizeNum().accept(this);
      }

      if (x.isBufferpoo()) {
         this.printUcase(" BUFFERPOOL ");
         x.getBufferpoolName().accept(this);
      }

      if (x.isAutoresize()) {
         this.printUcase(" AUTORESIZE ");
         if (x.isYesOrNo()) {
            this.printUcase("YES ");
         } else {
            this.printUcase("NO ");
         }
      }

      if (x.isMaxsize()) {
         this.printUcase(" MAXSIZE ");
         x.getMaxsizeNum().accept(this);
      }

      return false;
   }

   public void endVisit(DB2AlterTableModify x) {
   }

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

      if (x.isTemp()) {
         this.print0(this.ucase ? " TEMP " : " temp ");
      }

      if (x.isTemporary()) {
         this.print0(this.ucase ? " TEMPORARY " : " temporary ");
      }

      if (x.isRecursiveView()) {
         this.print0(this.ucase ? " RECURSIVE " : " recursive ");
      }

      this.print0(this.ucase ? " VIEW " : " view ");
      x.getViewName().accept(this);
      List<SQLExpr> columnList = x.getColumnList();
      if (columnList != null && columnList.size() > 0) {
         this.print0("(");
         this.printAndAccept(columnList, ", ");
         this.print0(")");
      }

      if (x.isWithOption()) {
         this.print0(this.ucase ? " WITH" : " with");
         List<SQLUpdateSetItem> withList = x.getWithList();
         this.print0("(");
         this.printAndAccept(withList, ", ");
         this.print0(")");
      }

      this.print0(this.ucase ? " AS " : " as ");
      if (x.isAsWithRecursive()) {
         x.getWithSubqueryClause().accept(this);
      } else {
         x.getSubQuery().accept(this);
         if (x.isWithCascaded()) {
            this.print0(this.ucase ? " WITH CASCADED CHECK OPTION " : " with cascaded check option ");
         }

         if (x.isWithLocal()) {
            this.print0(this.ucase ? " WITH LOCAL CHECK OPTION " : " with local check option ");
         }
      }

      return false;
   }

   public boolean visit(DB2CreateMaterializedViewStatement x) {
      this.printUcase(" CREATE ");
      if (x.isOrReplace()) {
         this.printUcase("OR REPLACE ");
      }

      this.printUcase("MATERIALIZED VIEW ");
      x.getViewName().accept(this);
      List<SQLExpr> columnList = x.getColumnList();
      if (columnList != null && columnList.size() > 0) {
         this.print0("(");
         this.printAndAccept(columnList, ", ");
         this.print0(")");
      }

      if (x.isWithOption()) {
         this.print0(this.ucase ? " WITH" : " with");
         List<SQLUpdateSetItem> withList = x.getWithList();
         this.print0("(");
         this.printAndAccept(withList, ", ");
         this.print0(")");
      }

      this.print0(this.ucase ? " AS " : " as ");
      x.getSubQuery().accept(this);
      this.print0(" ");
      if (x.isWithData()) {
         this.printUcase("WITH ");
         if (x.isNo()) {
            this.printUcase("NO ");
         }

         this.printUcase("DATA ");
      }

      return false;
   }

   public void endVisit(DB2DropSequenceStatement x) {
   }

   public void endVisit(DB2CreateSynonymStatement x) {
   }

   public boolean visit(DB2CreateSynonymStatement x) {
      this.printUcase("CREATE ");
      if (x.isOrReplace()) {
         this.printUcase("OR REPLACE ");
      }

      this.printUcase("SYNONYM ");
      if (x.getName() != null) {
         x.getName().accept(this);
         this.print0(" ");
      }

      this.printUcase("FOR ");
      if (x.getObject() != null) {
         x.getObject().accept(this);
         this.print0(" ");
      }

      return false;
   }

   public void endVisit(DB2AlterSynonymStatement x) {
   }

   public boolean visit(DB2AlterSynonymStatement x) {
      this.printUcase("ALTER SYNONYM ");
      if (x.getName() != null) {
         x.getName().accept(this);
         this.print0(" ");
      }

      if (x.isRename()) {
         this.printUcase("RENAME TO ");
      }

      if (x.isOwner()) {
         this.printUcase("OWNER TO ");
      }

      if (x.getNewName() != null) {
         x.getNewName().accept(this);
         this.print0(" ");
      }

      return false;
   }

   public void endVisit(DB2CreateRoleStatement x) {
   }

   public boolean visit(DB2DropSequenceStatement x) {
      this.print0(this.ucase ? "DROP " : " drop ");
      if (x.isLarge()) {
         this.print0(this.ucase ? "LARGE " : "large ");
      }

      this.print0(this.ucase ? "SEQUENCE " : "sequence ");
      if (x.isIfExists()) {
         this.print0(this.ucase ? " IF EXISTS " : " if exists ");
      }

      ArrayList<SQLIdentifierExpr> seqList = x.getSeqList();
      if (seqList != null && seqList.size() > 0) {
         this.printAndAccept(seqList, ", ");
      }

      if (x.isCascade()) {
         this.print0(this.ucase ? " CASCADE " : " cascade ");
      } else if (x.isRestrict()) {
         this.print0(this.ucase ? " RESTRICT " : " restrict ");
      }

      return false;
   }

   public boolean visit(SQLDropTableStatement x) {
      this.print0(this.ucase ? "DROP TABLE " : " drop table ");
      this.printAndAccept(x.getTableSources(), ",");
      if (x.isCascade()) {
         this.print0(this.ucase ? " CASCADE " : " cascade ");
      } else if (x.isRestrict()) {
         this.print0(this.ucase ? " RESTRICT " : " restrict ");
      }

      if (x.isIfExists()) {
         this.print0(this.ucase ? " IF EXISTS " : " if exists ");
      }

      return false;
   }

   public boolean visit(SQLCommitStatement x) {
      this.print0(this.ucase ? "COMMIT" : "commit");
      if (x.isWork()) {
         this.print0(this.ucase ? " WORK" : " work");
      } else if (x.isTransaction()) {
         this.print0(this.ucase ? " TRANSACTION" : " transaction");
      }

      return false;
   }

   public boolean visit(SQLRollbackStatement x) {
      this.print0(this.ucase ? "ROLLBACK" : "rollback");
      if (x.isWork()) {
         this.print0(this.ucase ? " WORK" : " work");
      } else if (x.isTransaction()) {
         this.print0(this.ucase ? " TRANSACTION" : " transaction");
      }

      if (x.getTo() != null) {
         this.print0(this.ucase ? " TO " : " to ");
         if (x.isHasSavepoint()) {
            this.print0(this.ucase ? " SAVEPOINT " : " savepoint ");
         }

         x.getTo().accept(this);
      }

      return false;
   }

   public boolean visit(DB2SQLPartitionBy x) {
      this.print0(this.ucase ? "PARTITION BY " : " partition by ");
      SQLName partitionType = x.getPartitionType();
      partitionType.accept(this);
      this.print0(" (");
      x.getColumn().accept(this);
      this.print0(")\n");
      ArrayList<DB2SQLPartitionBy> subPartitionByList = x.getSubPartitionByList();
      if (subPartitionByList != null && subPartitionByList.size() > 0) {
         boolean ifUseTemplate = ((DB2SQLPartitionBy)subPartitionByList.get(0)).isIfUseTemplate();
         if (!ifUseTemplate) {
            for(DB2SQLPartitionBy subPartitionBy : subPartitionByList) {
               this.print0(this.ucase ? " SUBPARTITION BY " : " subpartition by ");
               this.print0("(");
               subPartitionBy.getPartitionType().accept(this);
               this.print0(")");
               this.print0("\n ");
            }

            this.print0(this.visitPartitionRecursive(x, 0));
            return false;
         }

         for(DB2SQLPartitionBy subPartitionBy : subPartitionByList) {
            this.print0(this.ucase ? " SUBPARTITION BY " : " subpartition by ");
            subPartitionBy.getPartitionType().accept(this);
            this.print0(" (");
            subPartitionBy.getColumn().accept(this);
            this.print0(")\n");
            this.print0(this.ucase ? "  SUBPARTITION TEMPLATE" : "  subpartition template");
            this.print0(" (\n ");
            ArrayList<DB2SQLPartition> subPartitionList = subPartitionBy.getPartitionList();
            if (subPartitionList != null && subPartitionList.size() > 0) {
               this.printAndAccept(subPartitionList, ",\n ");
            }

            this.print0(")\n");
         }
      }

      this.print0("(");
      List<DB2SQLPartition> specList = x.getPartitionList();
      if (specList != null && specList.size() > 0) {
         this.printAndAccept(specList, ",\n");
      }

      this.print0("\n) ");
      return false;
   }

   private String visitPartitionRecursive(DB2SQLPartitionBy partitionBy, int level) {
      ArrayList<DB2SQLPartitionBy> subPartitionByList = partitionBy.getSubPartitionByList();
      ArrayList<DB2SQLPartition> crtPartitions;
      if (level == 0) {
         crtPartitions = partitionBy.getPartitionList();
      } else {
         crtPartitions = ((DB2SQLPartitionBy)subPartitionByList.get(level - 1)).getPartitionList();
      }

      if (level == subPartitionByList.size()) {
         return "(" + StringJoin.join(crtPartitions, ",") + ")";
      } else {
         String result = "(";

         for(DB2SQLPartition crtPartition : crtPartitions) {
            if (!"(".equals(result)) {
               result = result + ",\n";
            }

            result = result + crtPartition + "\n" + this.visitPartitionRecursive(partitionBy, level + 1);
         }

         result = result + ")";
         return result;
      }
   }

   public boolean visit(DB2SQLPartition x) {
      SQLName name = x.getName();
      if (name != null) {
         boolean subPartition = x.isSubPartition();
         if (x.isIfDefault()) {
            this.print0(this.ucase ? " DEFAULT PARTITION " : " default partition ");
            x.getName().accept(this);
            return false;
         }

         if (subPartition) {
            this.print0(this.ucase ? " SUBPARTITION " : " subpartition ");
         } else {
            this.print0(this.ucase ? " PARTITION " : " partition ");
         }

         x.getName().accept(this);
      }

      ArrayList<SQLExpr> valueList = x.getValueList();
      if (valueList != null && valueList.size() > 0) {
         this.print0(this.ucase ? " VALUES " : " values ");
         this.print0(" (");
         this.printAndAccept(valueList, ", ");
         this.print0(") ");
      } else {
         if (x.isStart()) {
            this.print0(this.ucase ? " START" : " star ");
            this.print0("(");
            SQLExpr startDataType = x.getStartDataType();
            if (startDataType != null) {
               startDataType.accept(this);
               this.print0(" ");
            }

            x.getStartValue().accept(this);
            this.print0(")");
            if (x.isStartInclusive()) {
               this.print0(this.ucase ? " INCLUSIVE " : " inclusive ");
            }

            if (x.isStartExclusive()) {
               this.print0(this.ucase ? " EXCLUSIVE " : " exclusive ");
            }
         }

         if (x.isEnd()) {
            this.print0(this.ucase ? " END" : " end");
            this.print0("(");
            SQLExpr endDataType = x.getEndDataType();
            if (endDataType != null) {
               endDataType.accept(this);
               this.print0(" ");
            }

            x.getEndValue().accept(this);
            this.print0(")");
            if (x.isEndInclusive()) {
               this.print0(this.ucase ? " INCLUSIVE " : " inclusive ");
            }

            if (x.isEndExclusive()) {
               this.print0(this.ucase ? " EXCLUSIVE " : " exclusive ");
            }
         }

         if (x.isEvery()) {
            this.print0(this.ucase ? " EVERY " : " every ");
            this.print0("(");
            SQLExpr everyDataType = x.getEveryDataType();
            if (everyDataType != null) {
               everyDataType.accept(this);
               this.print0(" ");
            }

            x.getEveryValue().accept(this);
            this.print0(")");
         }
      }

      if (x.isWith()) {
         this.print0(this.ucase ? " WITH " : " with ");
         List<SQLUpdateSetItem> withList = x.getWithList();
         if (withList != null && withList.size() > 0) {
            this.printAndAccept(withList, ",");
         }
      }

      SQLName tableSpace = x.getTableSpace();
      if (tableSpace != null) {
         this.print0(this.ucase ? " TABLESPACE " : " tablespace ");
         tableSpace.accept(this);
      }

      return false;
   }

   public boolean visit(DB2SQLIndexSpec x) {
      x.getName().accept(this);
      SQLExpr collateParam = x.getCollateParam();
      if (collateParam != null) {
         this.print0(this.ucase ? " COLLATE " : " collate ");
         collateParam.accept(this);
      }

      SQLName opclass = x.getOpclass();
      if (opclass != null) {
         this.print0(" ");
         opclass.accept(this);
      }

      if (x.isAsc()) {
         this.print0(this.ucase ? " ASC " : " asc ");
      } else if (x.isDesc()) {
         this.print0(this.ucase ? " DESC " : " desc ");
      }

      if (x.isNullsFirst()) {
         this.print0(this.ucase ? " NULLS FIRST " : " nulls first ");
      } else if (x.isNullsLast()) {
         this.print0(this.ucase ? " NULLS LAST " : " nulls last ");
      }

      return false;
   }

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

      this.print0(this.ucase ? "INDEX" : "index");
      if (x.isConcurrently()) {
         this.printUcase(" CONCURRENTLY ");
      }

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

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

      this.print0(" (");
      this.printAndAccept(x.getSpecList(), ", ");
      this.print(')');
      List<SQLUpdateSetItem> withList = x.getWithList();
      if (withList != null && withList.size() > 0) {
         this.print0(this.ucase ? " WITH " : " with ");
         this.print0(" (");
         this.printAndAccept(withList, ",");
         this.print(')');
      }

      SQLName tablespace = x.getTablespace();
      if (tablespace != null) {
         this.print0(this.ucase ? " TABLESPACE " : " tablespace ");
         tablespace.accept(this);
      }

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

      return false;
   }

   public void endVisit(DB2AlterSessionStatement x) {
   }

   public boolean visit(DB2AlterTableModify 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 void endVisit(DB2CreateUserStatement x) {
   }

   public boolean visit(DB2CreateTableAsStatement stmt) {
      this.print0(this.ucase ? "CREATE " : "create ");
      if (stmt.getTableType() != null) {
         switch (stmt.getTableType()) {
            case GLOBAL_TEMPORARY:
               this.print0(this.ucase ? "GLOBAL TEMPORARY " : "golbal temporary ");
               break;
            case LOCAL_TEMPORARY:
               this.print0(this.ucase ? "LOCAL TEMPORARY " : "local temporary ");
               break;
            case GLOBAL_TEMP:
               this.print0(this.ucase ? "GLOBAL TEMP " : "golbal temp ");
               break;
            case LOCAL_TEMP:
               this.print0(this.ucase ? "LOCAL TEMP " : "local temp ");
               break;
            case GLOBAL_UNLOGGED:
               this.print0(this.ucase ? "GLOBAL UNLOGGED " : "golbal unlogged ");
               break;
            case LOCAL_UNLOGGED:
               this.print0(this.ucase ? "LOCAL UNLOGGED " : "local unlogged ");
               break;
            case TEMPORARY:
               this.print0(this.ucase ? "TEMPORARY " : "temporary ");
               break;
            case TEMP:
               this.print0(this.ucase ? "TEMP " : "temp ");
               break;
            case UNLOGGED:
               this.print0(this.ucase ? "UNLOGGED " : "unlogged ");
         }
      }

      this.print0(this.ucase ? "TABLE " : "table ");
      if (stmt.isIfNotExists()) {
         this.print0(this.ucase ? "IF NOT EXISTS " : "if not exists ");
      }

      stmt.getTableSource().accept(this);
      this.print0(" ");
      if (stmt.getOfType() != null) {
         this.print0(this.ucase ? "OF " : "of ");
         stmt.getOfType().accept(this);
         this.print0(" ");
      }

      if (stmt.getTableElementList() != null && stmt.getTableElementList().size() > 0) {
         this.print0("(");

         for(int i = 0; i < stmt.getTableElementList().size(); ++i) {
            this.println();
            SQLTableElement element = (SQLTableElement)stmt.getTableElementList().get(i);
            element.accept(this);
            if (i != stmt.getTableElementList().size() - 1) {
               this.print0(",");
            }
         }

         this.println();
         this.print0(")");
      }

      List<SQLExpr> parentTables = stmt.getParentTables();
      if (parentTables != null && parentTables.size() > 0) {
         this.println();
         this.print0(this.ucase ? "INHERITS " : "inherits ");
         this.print0("(");

         for(int i = 0; i < parentTables.size(); ++i) {
            ((SQLExpr)parentTables.get(i)).accept(this);
            if (i != parentTables.size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      if (stmt.getParameters() != null && stmt.getParameters().size() > 0) {
         this.println();
         this.print0(this.ucase ? "WITH " : "with ");
         this.print0("(");

         for(int i = 0; i < stmt.getParameters().size(); ++i) {
            DB2StorageParameter paramter = (DB2StorageParameter)stmt.getParameters().get(i);
            paramter.accept(this);
            this.println();
            if (i != stmt.getParameters().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      if (stmt.getTableOptions() != null && stmt.getTableOptions().size() > 0) {
         this.println();
         this.print0(this.ucase ? "WITH " : "with ");
         this.print0("(");

         for(int i = 0; i < stmt.getTableOptions().size(); ++i) {
            SQLAssignItem paramter = (SQLAssignItem)stmt.getTableOptions().get(i);
            paramter.accept(this);
            this.println();
            if (i != stmt.getTableOptions().size() - 1) {
               this.print0(",");
            }
         }

         this.print0(")");
      }

      if (stmt.getOnCommit() != null) {
         this.println();
         this.print0(this.ucase ? "ON COMMIT " : "on commit ");
         switch (stmt.getOnCommit()) {
            case preserveRows:
               this.print0(this.ucase ? "PRESERVE ROWS" : "preserve rows");
               break;
            case deleteRows:
               this.print0(this.ucase ? "DELETE ROWS" : "delete rows");
               break;
            case drop:
               this.print0(this.ucase ? "DROP" : "drop");
         }
      }

      if (stmt.getTablespace() != null) {
         this.println();
         this.print0(this.ucase ? "TABLESPACE " : "tablespace ");
         stmt.getTablespace().accept(this);
      }

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

      if (stmt.getDistributedBy() != null) {
         this.println();
         stmt.getDistributedBy().accept(this);
      }

      if (stmt.getPartitioning() != null) {
         this.println();
         stmt.getPartitioning().accept(this);
      }

      return false;
   }

   public void endVisit(DB2RevokeStatement x) {
   }

   public boolean visit(DB2AlterTriggerStatement x) {
      this.print0(this.ucase ? "ALTER TRIGGER " : "alter trigger ");
      x.getName().accept(this);
      this.print0(this.ucase ? " ON " : " on ");
      x.getTableName().accept(this);
      this.print0(this.ucase ? " RENAME TO " : " rename to ");
      x.getNewName().accept(this);
      return true;
   }

   public void endVisit(DB2DropTriggerStatement x) {
   }

   public boolean visit(DB2DropTriggerStatement x) {
      this.print0(this.ucase ? "DROP TRIGGER " : "drop trigger ");
      x.getName().accept(this);
      return true;
   }

   public void endVisit(DB2SetTransactionStatement x) {
   }

   public boolean visit(DB2CreateTriggerStatement x) {
      this.print0(this.ucase ? "CREATE " : "create ");
      if (x.isConstraint()) {
         this.printUcase("CONSTRAINT ");
      }

      this.print0(this.ucase ? "TRIGGER " : "trigger ");
      x.getName().accept(this);
      ++this.indentCount;
      this.println();
      if (SQLCreateTriggerStatement.TriggerType.INSTEAD_OF.equals(x.getTriggerType())) {
         this.print0(this.ucase ? "INSTEAD OF" : "instead of");
      } else {
         String triggerTypeName = x.getTriggerType().name();
         this.print0(this.ucase ? triggerTypeName : triggerTypeName.toLowerCase());
      }

      if (x.isInsert()) {
         this.print0(this.ucase ? " INSERT" : " insert");
      }

      if (x.isDelete()) {
         if (x.isInsert()) {
            this.print0(this.ucase ? " OR" : " or");
         }

         this.print0(this.ucase ? " DELETE" : " delete");
      }

      if (x.isUpdate()) {
         if (x.isInsert() || x.isDelete()) {
            this.print0(this.ucase ? " OR" : " or");
         }

         this.print0(this.ucase ? " UPDATE" : " update");

         for(SQLName colum : x.getUpdateOfColumns()) {
            this.print(' ');
            colum.accept(this);
         }
      }

      this.println();
      this.print0(this.ucase ? "ON " : "on ");
      x.getOn().accept(this);
      if (x.isForEachRow()) {
         this.println();
         this.print0(this.ucase ? "FOR EACH ROW" : "for each row");
      }

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

      if (x.isExecuteProcedure()) {
         this.println();
         this.printUcase("EXECUTE PROCEDURE ");
         x.getFunctionName().accept(this);
      }

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

      return false;
   }

   public void endVisit(DB2AlterTriggerStatement x) {
   }

   public boolean visit(DB2SetTransactionStatement x) {
      this.printUcase("SET TRANSACTION ");
      if (x.isReadWrite()) {
         this.printUcase("READ WRITE ");
      }

      if (x.isReadOnly()) {
         this.printUcase("READ ONLY ");
      }

      if (x.isIsolationLevel()) {
         this.printUcase("ISOLATION LEVEL ");
         if (x.isSerializable()) {
            this.printUcase("SERIALIZABLE ");
         }

         if (x.isReadCommitted()) {
            this.printUcase("READ COMMITTED ");
         }

         if (x.isReadUncommitted()) {
            this.printUcase("READ UNCOMMITTED ");
         }

         if (x.isRepeatableRead()) {
            this.printUcase("REPEATABLE READ ");
         }
      }

      return false;
   }

   public void endVisit(DB2SetSessionStatement x) {
   }

   public boolean visit(DB2SetSessionStatement x) {
      this.printUcase("SET SESSION ");
      if (x.isReadWrite()) {
         this.printUcase("READ WRITE ");
      }

      if (x.isReadOnly()) {
         this.printUcase("READ ONLY ");
      }

      return false;
   }

   public void endVisit(DB2DropSessionStatement x) {
   }

   public boolean visit(DB2DropSessionStatement x) {
      this.printUcase("DROP SESSION ");
      x.getSessionId().accept(this);
      return false;
   }

   public void endVisit(DB2SetConnectionStatement x) {
   }

   public boolean visit(DB2SetConnectionStatement x) {
      this.printUcase("SET CONNECTION ");
      x.getHostType().accept(this);
      this.print(" ");
      if (x.isDatabase()) {
         this.printUcase("DATABASE ");
         x.getDatabaseName().accept(this);
         this.print(" ");
      }

      if (x.isIpaddr()) {
         this.printUcase("IPADDR ");
         x.getIpAddress().accept(this);
         this.print(" ");
      }

      if (x.isIpMask()) {
         this.printUcase("IPMASK ");
         x.getIpAddressMask().accept(this);
         this.print(" ");
      }

      if (x.isAuth()) {
         this.printUcase("AUTH ");
         x.getAuthType().accept(this);
         this.print(" ");
      }

      return false;
   }

   public void endVisit(DB2DropConnectionStatement x) {
   }

   public boolean visit(DB2DropConnectionStatement x) {
      this.printUcase("DROP CONNECTION ");
      x.getConnectionId().accept(this);
      return false;
   }

   public void endVisit(DB2LockTableStatement x) {
   }

   public boolean visit(DB2LockTableStatement x) {
      this.printUcase("LOCK TABLE ");
      x.getTableName().accept(this);
      this.printUcase(" IN ");
      if (x.isAccessExclusive()) {
         this.printUcase("ACCESS EXCLUSIVE ");
      } else if (x.isAccessShare()) {
         this.printUcase("ACCESS SHARE ");
      } else if (x.isRowExclusive()) {
         this.printUcase("ROW EXCLUSIVE ");
      } else if (x.isShare()) {
         this.printUcase("SHARE ");
      } else if (x.isRowShare()) {
         this.printUcase("ROW SHARE ");
      } else if (x.isShareRowExclusive()) {
         this.printUcase("SHARE ROW EXCLUSIVE ");
      } else if (x.isExclusive()) {
         this.printUcase("EXCLUSIVE ");
      }

      this.printUcase("MODE ");
      if (x.isNowait()) {
         this.printUcase("NOWAIT ");
      }

      return false;
   }
}
