package com.alibaba.druid.sql.dialect.greenplum.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.greenplum.ast.GPSQLObject;
import com.alibaba.druid.sql.dialect.greenplum.ast.GPSQLObjectImpl;
import com.alibaba.druid.sql.dialect.greenplum.visitor.GPASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
import java.util.ArrayList;
import java.util.List;

public class GPSelectQueryBlock extends SQLSelectQueryBlock implements GPSQLObject {
   private List<SQLExpr> distinctOn = new ArrayList(2);
   private FetchClause fetch;
   private ForClauses forClause;
   private IntoOption intoOption;
   protected boolean using = false;
   private SQLExpr usingOperator;

   public boolean isUsing() {
      return this.using;
   }

   public void setUsing(boolean using) {
      this.using = using;
   }

   public SQLExpr getUsingOperator() {
      return this.usingOperator;
   }

   public void setUsingOperator(SQLExpr usingOperator) {
      this.usingOperator = usingOperator;
   }

   public GPSelectQueryBlock() {
      this.dbType = DbType.greenplum;
   }

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

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

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

   }

   public void accept0(GPASTVisitor 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 GPSelectQueryBlock clone() {
      GPSelectQueryBlock x = new GPSelectQueryBlock();
      this.cloneTo(x);
      if (this.distinctOn != null && this.distinctOn.size() > 0) {
         for(SQLExpr sqlExpr : this.distinctOn) {
            SQLExpr c = sqlExpr.clone();
            c.setParent(x);
            x.distinctOn.add(c);
         }
      }

      if (this.fetch != null) {
         x.setFetch(this.fetch.clone());
      }

      return x;
   }

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

   public static class FetchClause extends GPSQLObjectImpl {
      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(GPASTVisitor visitor) {
         if (visitor.visit(this)) {
            this.acceptChild(visitor, this.count);
         }

         visitor.endVisit(this);
      }

      public FetchClause clone() {
         FetchClause c = new FetchClause();
         c.option = this.option;
         c.count = this.count.clone();
         return c;
      }

      public static enum Option {
         FIRST,
         NEXT;
      }
   }

   public static class ForClauses extends GPSQLObjectImpl {
      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(GPASTVisitor 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;
      }
   }

   public static class ForClause extends GPSQLObjectImpl {
      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(GPASTVisitor visitor) {
         if (visitor.visit(this)) {
            this.acceptChild(visitor, this.of);
         }

         visitor.endVisit(this);
      }

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