package com.alibaba.druid.sql.dialect.postgresql.ast.stmt;

import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObject;
import com.alibaba.druid.sql.dialect.postgresql.ast.PGSQLObjectImpl;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;

public class PGSelectQueryBlock extends SQLSelectQueryBlock implements PGSQLObject {
   private List<SQLExpr> distinctOn = new ArrayList(2);
   private FetchClause fetch;
   private ForClauses forClause;
   private IntoOption intoOption;

   public PGSelectQueryBlock() {
      this.dbType = DbType.postgresql;
   }

   public IntoOption getIntoOption() {
      return this.intoOption;
   }

   public void setIntoOption(IntoOption intoOption) {
      this.intoOption = intoOption;
   }

   protected void accept0(SQLASTVisitor visitor) {
      if (visitor instanceof PGASTVisitor) {
         this.accept0((PGASTVisitor)visitor);
      } else {
         super.accept0(visitor);
      }

   }

   public void accept0(PGASTVisitor visitor) {
      if (visitor.visit(this)) {
         this.acceptChild(visitor, this.distinctOn);
         this.acceptChild(visitor, this.selectList);
         this.acceptChild(visitor, this.into);
         this.acceptChild(visitor, this.from);
         this.acceptChild(visitor, this.where);
         this.acceptChild(visitor, this.groupBy);
         this.acceptChild(visitor, this.windows);
         this.acceptChild(visitor, this.orderBy);
         this.acceptChild(visitor, this.limit);
         this.acceptChild(visitor, this.fetch);
         this.acceptChild(visitor, this.forClause);
      }

      visitor.endVisit(this);
   }

   public FetchClause getFetch() {
      return this.fetch;
   }

   public void setFetch(FetchClause fetch) {
      this.fetch = fetch;
   }

   public ForClauses getForClause() {
      return this.forClause;
   }

   public void setForClause(ForClauses forClause) {
      this.forClause = forClause;
   }

   public List<SQLExpr> getDistinctOn() {
      return this.distinctOn;
   }

   public void setDistinctOn(List<SQLExpr> distinctOn) {
      this.distinctOn = distinctOn;
   }

   public static enum IntoOption {
      TEMPORARY,
      TEMP,
      UNLOGGED;
   }

   public static class FetchClause extends PGSQLObjectImpl {
      private Option option;
      private SQLExpr count;

      public Option getOption() {
         return this.option;
      }

      public void setOption(Option option) {
         this.option = option;
      }

      public SQLExpr getCount() {
         return this.count;
      }

      public void setCount(SQLExpr count) {
         this.count = count;
      }

      public void accept0(PGASTVisitor visitor) {
         if (visitor.visit(this)) {
            this.acceptChild(visitor, this.count);
         }

         visitor.endVisit(this);
      }

      public static enum Option {
         FIRST,
         NEXT;
      }
   }

   public static class ForClause extends PGSQLObjectImpl {
      private List<SQLExpr> of = new ArrayList(2);
      private boolean noWait;
      private boolean skipLocked;
      private Option option;

      public Option getOption() {
         return this.option;
      }

      public void setOption(Option option) {
         this.option = option;
      }

      public List<SQLExpr> getOf() {
         return this.of;
      }

      public void setOf(List<SQLExpr> of) {
         this.of = of;
      }

      public boolean isNoWait() {
         return this.noWait;
      }

      public void setNoWait(boolean noWait) {
         this.noWait = noWait;
      }

      public boolean isSkipLocked() {
         return this.skipLocked;
      }

      public void setSkipLocked(boolean skipLocked) {
         this.skipLocked = skipLocked;
      }

      public void accept0(PGASTVisitor visitor) {
         if (visitor.visit(this)) {
            this.acceptChild(visitor, this.of);
         }

         visitor.endVisit(this);
      }

      public static enum Option {
         UPDATE,
         SHARE,
         NO_KEY_UPDATE,
         KEY_SHARE;
      }
   }

   public static class ForClauses extends PGSQLObjectImpl {
      protected List<ForClause> clauses = new ArrayList();

      public List<ForClause> getClauses() {
         return this.clauses;
      }

      public void setClauses(List<ForClause> clauses) {
         this.clauses = clauses;
      }

      public void addForClause(ForClause forClause) {
         forClause.setParent(this);
         this.clauses.add(forClause);
      }

      public void accept0(PGASTVisitor visitor) {
         if (visitor.visit(this)) {
            this.acceptChild(visitor, this.clauses);
         }

         visitor.endVisit(this);
      }

      public ForClauses clone() {
         ForClauses c = new ForClauses();
         if (this.clauses != null && this.clauses.size() > 0) {
            for(ForClause cl : this.clauses) {
               c.addForClause((ForClause)cl.clone());
            }
         }

         return c;
      }
   }
}
