content: /*
   * Copyright 1999-2017 Alibaba Group Holding Ltd.
   *
   * Licensed under the Apache License, Version 2.0 (the "License");
   * you may not use this file except in compliance with the License.
   * You may obtain a copy of the License at
   *
   *      http://www.apache.org/licenses/LICENSE-2.0
   *
   * Unless required by applicable law or agreed to in writing, software
   * distributed under the License is distributed on an "AS IS" BASIS,
   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   * See the License for the specific language governing permissions and
   * limitations under the License.
   */
  package com.alibaba.druid.sql.ast.statement;
  
  import com.alibaba.druid.DbType;
  import com.alibaba.druid.sql.SQLUtils;
  import com.alibaba.druid.sql.ast.*;
  import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
  import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
  import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
  import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
  import com.alibaba.druid.sql.visitor.SQLASTVisitor;
  
  import java.sql.Types;
  import java.util.ArrayList;
  import java.util.List;
  
  public class SQLColumnDefinition extends SQLObjectImpl implements SQLTableElement, SQLObjectWithDataType, SQLReplaceable, SQLDbTypedObject {
      protected DbType dbType;
  
      protected boolean ifNotExists;
      protected SQLName name;
      protected SQLDataType dataType;
      protected SQLExpr defaultExpr;
      protected final List<SQLColumnConstraint> constraints = new ArrayList<SQLColumnConstraint>(0);
      protected boolean disableNovalidate;
      protected SQLExpr comment;
  
      protected Boolean enable;
      protected Boolean validate;
      protected Boolean rely;
  
      // for mysql
      protected boolean autoIncrement;
      protected SQLExpr onUpdate;
      protected SQLExpr format;
      protected SQLExpr storage;
      protected SQLExpr charsetExpr;
      protected SQLExpr collateExpr;
      protected SQLExpr asExpr;
      protected boolean stored;
      protected boolean virtual;
      protected boolean visible;
      protected AutoIncrementType sequenceType;
      protected boolean preSort; // for ads
      protected int preSortOrder; // for ads
      protected Identity identity;
  
      // for ads
      protected SQLExpr generatedAlwaysAs;
      protected SQLExpr delimiter; // for ads
      protected SQLExpr delimiterTokenizer; // for ads3.0 multivalue
      protected SQLExpr nlpTokenizer; // for ads3.0 multivalue
      protected SQLExpr valueType; // for ads3.0 multivalue
      protected boolean disableIndex; //for ads
      protected SQLExpr jsonIndexAttrsExpr;    // for ads
      protected SQLAnnIndex annIndex;
      private SQLExpr unitCount;
      private SQLExpr unitIndex;
      private SQLExpr step;
      private SQLExpr encode;
      private SQLExpr compression;
      protected SQLCharExpr aggType; // for starrocks
      protected SQLCharExpr bitmap; // for starrocks
      protected SQLCharExpr indexComment; // for starrocks
  
      // for aliyun data lake anlytics
      private List<SQLAssignItem> mappedBy;
      private List<SQLAssignItem> colProperties;
  
      protected SQLIntegerExpr blockSize; // for impala for kudu
  
      private boolean generateByDefault;
  
      public SQLCharExpr getIndexComment() {
          return indexComment;
      }
  
      public void setIndexComment(SQLCharExpr indexComment) {
          this.indexComment = indexComment;
      }
  
      public SQLCharExpr getBitmap() {
          return bitmap;
      }
  
      public void setBitmap(SQLCharExpr bitmap) {
          this.bitmap = bitmap;
      }
  
      public SQLCharExpr getAggType() {
          return aggType;
      }
  
      public void setAggType(SQLCharExpr aggType) {
          this.aggType = aggType;
      }
  
      public SQLColumnDefinition() {
      }
  
      public SQLColumnDefinition(SQLName name) {
          this.setName(name);
      }
  
      public SQLColumnDefinition(String name, SQLDataType dataType) {
          setName(name);
          setDataType(dataType);
      }
  
      public Identity getIdentity() {
          return identity;
      }
  
      // for sqlserver
      public void setIdentity(Identity identity) {
          if (identity != null) {
              identity.setParent(this);
          }
          this.identity = identity;
      }
  
      public Boolean getEnable() {
          return enable;
      }
  
      public void setEnable(Boolean enable) {
          this.enable = enable;
      }
  
      public Boolean getValidate() {
          return validate;
      }
  
      public void setValidate(Boolean validate) {
          this.validate = validate;
      }
  
      public Boolean getRely() {
          return rely;
      }
  
      public void setRely(Boolean rely) {
          this.rely = rely;
      }
  
      public boolean isIfNotExists() {
          return ifNotExists;
      }
  
      public void setIfNotExists(boolean ifNotExists) {
          this.ifNotExists = ifNotExists;
      }
  
      public SQLName getName() {
          return name;
      }
  
      public String getColumnName() {
          if (name == null) {
              return null;
          }
  
          return name.getSimpleName();
      }
  
      public long nameHashCode64() {
          if (name == null) {
              return 0;
          }
  
          return name.hashCode64();
      }
  
      public String getNameAsString() {
          if (name == null) {
              return null;
          }
  
          return name.toString();
      }
  
      public void setName(SQLName name) {
          this.name = name;
      }
  
      public void setName(String name) {
          this.setName(new SQLIdentifierExpr(name));
      }
  
      public SQLDataType getDataType() {
          return dataType;
      }
  
      public int jdbcType() {
          if (dataType == null) {
              return Types.OTHER;
          }
  
          return dataType.jdbcType();
      }
  
      public void setDataType(SQLDataType dataType) {
          if (dataType != null) {
              dataType.setParent(this);
          }
          this.dataType = dataType;
      }
  
      public SQLExpr getDefaultExpr() {
          return defaultExpr;
      }
  
      public void setDefaultExpr(SQLExpr defaultExpr) {
          if (defaultExpr != null) {
              defaultExpr.setParent(this);
          }
          this.defaultExpr = defaultExpr;
      }
  
      public List<SQLColumnConstraint> getConstraints() {
          return constraints;
      }
  
      public boolean isPrimaryKey() {
          for (SQLColumnConstraint constraint : constraints) {
              if (constraint instanceof SQLColumnPrimaryKey) {
                  return true;
              }
          }
  
          if (parent instanceof SQLCreateTableStatement) {
              return ((SQLCreateTableStatement) parent)
                      .isPrimaryColumn(
                              nameHashCode64());
          }
  
          return false;
      }
  
      public boolean isOnlyPrimaryKey() {
          for (SQLColumnConstraint constraint : constraints) {
              if (constraint instanceof SQLColumnPrimaryKey) {
                  return true;
              }
          }
  
          if (parent instanceof SQLCreateTableStatement) {
              return ((SQLCreateTableStatement) parent)
                      .isPrimaryColumn(
                              nameHashCode64());
          }
  
          return false;
      }
  
      public boolean isPartitionBy() {
          if (!(parent instanceof SQLCreateTableStatement)) {
              return false;
          }
  
          SQLCreateTableStatement stmt = (SQLCreateTableStatement) parent;
          final SQLPartitionBy partitioning = stmt.getPartitioning();
          if (partitioning == null) {
              return false;
          }
  
          if (name == null) {
              return false;
          }
  
          return partitioning.isPartitionByColumn(
                  nameHashCode64());
      }
  
      public void addConstraint(SQLColumnConstraint constraint) {
          if (constraint != null) {
              constraint.setParent(this);
          }
          this.constraints.add(constraint);
      }
  
      public boolean isDisableNovalidate() {
          return disableNovalidate;
      }
  
      public void setDisableNovalidate(boolean disableNovalidate) {
          this.disableNovalidate = disableNovalidate;
      }
  
      @Override
      protected void accept0(SQLASTVisitor visitor) {
          if (visitor.visit(this)) {
              this.acceptChild(visitor, name);
              this.acceptChild(visitor, dataType);
              this.acceptChild(visitor, defaultExpr);
              this.acceptChild(visitor, constraints);
          }
          visitor.endVisit(this);
      }
  
      public SQLExpr getComment() {
          return comment;
      }
  
      public void setComment(String comment) {
          SQLCharExpr expr;
          if (comment == null) {
              expr = null;
          } else {
              expr = new SQLCharExpr(comment);
          }
          this.setComment(expr);
      }
  
      public void setComment(SQLExpr comment) {
          if (comment != null) {
              comment.setParent(this);
          }
          this.comment = comment;
      }
  
      public boolean isVirtual() {
          return virtual;
      }
  
      public void setVirtual(boolean virtual) {
          this.virtual = virtual;
      }
  
      public boolean isStored() {
          return stored;
      }
  
      public void setStored(boolean stored) {
          this.stored = stored;
      }
  
      public SQLExpr getCharsetExpr() {
          return charsetExpr;
      }
  
      public void setCharsetExpr(SQLExpr charsetExpr) {
          if (charsetExpr != null) {
              charsetExpr.setParent(this);
          }
          this.charsetExpr = charsetExpr;
      }
  
      public SQLExpr getCollateExpr() {
          return collateExpr;
      }
  
      public void setCollateExpr(SQLExpr x) {
          if (charsetExpr != null) {
              charsetExpr.setParent(this);
          }
          this.collateExpr = x;
      }
  
      public SQLExpr getAsExpr() {
          return asExpr;
      }
  
      public void setAsExpr(SQLExpr asExpr) {
          if (charsetExpr != null) {
              charsetExpr.setParent(this);
          }
          this.asExpr = asExpr;
      }
  
      public boolean isAutoIncrement() {
          return autoIncrement;
      }
  
      public void setAutoIncrement(boolean autoIncrement) {
          this.autoIncrement = autoIncrement;
      }
  
      public SQLExpr getOnUpdate() {
          return onUpdate;
      }
  
      public void setOnUpdate(SQLExpr onUpdate) {
          this.onUpdate = onUpdate;
      }
  
      public SQLExpr getFormat() {
          return format;
      }
  
      public void setFormat(SQLExpr format) {
          this.format = format;
      }
  
      public SQLExpr getStorage() {
          return storage;
      }
  
      public void setStorage(SQLExpr storage) {
          this.storage = storage;
      }
  
      @Override
      public boolean replace(SQLExpr expr, SQLExpr target) {
          if (defaultExpr == expr) {
              setDefaultExpr(target);
              return true;
          }
  
          if (name == expr) {
              setName((SQLName) target);
              return true;
          }
  
          if (comment == expr) {
              setComment(target);
              return true;
          }
  
          return false;
      }
  
      public void setUnitCount(SQLExpr unitCount) {
          if (unitCount != null) {
              unitCount.setParent(this);
          }
          this.unitCount = unitCount;
      }
  
      public boolean isGenerateByDefault() {
          return generateByDefault;
      }
  
      public void setGenerateByDefault(boolean generateByDefault) {
          this.generateByDefault = generateByDefault;
      }
  
      public static class Identity extends SQLObjectImpl implements SQLExpr{
          private Integer seed;
          private Integer increment;
  
          private boolean notForReplication;
          private boolean cycle;
  
          private Integer minValue;
          private Integer maxValue;
  
          public Identity() {
          }
  
          public Integer getSeed() {
              return seed;
          }
  
          public void setSeed(Integer seed) {
              this.seed = seed;
          }
  
          public Integer getIncrement() {
              return increment;
          }
  
          public void setIncrement(Integer increment) {
              this.increment = increment;
          }
  
          public boolean isCycle() {
              return cycle;
          }
  
          public void setCycle(boolean cycle) {
              this.cycle = cycle;
          }
  
          public Integer getMinValue() {
              return minValue;
          }
  
          public void setMinValue(Integer minValue) {
              this.minValue = minValue;
          }
  
          public Integer getMaxValue() {
              return maxValue;
          }
  
          public void setMaxValue(Integer maxValue) {
              this.maxValue = maxValue;
          }
  
          public boolean isNotForReplication() {
              return notForReplication;
          }
  
          public void setNotForReplication(boolean notForReplication) {
              this.notForReplication = notForReplication;
          }
  
          @Override
          public void accept0(SQLASTVisitor visitor) {
              visitor.visit(this);
              visitor.endVisit(this);
          }
  
          public Identity clone() {
              Identity x = new Identity();
              x.seed = seed;
              x.increment = increment;
              x.cycle = cycle;
              x.minValue = minValue;
              x.maxValue = maxValue;
              x.notForReplication = notForReplication;
              return x;
          }
  
          @Override
          public List<SQLObject> getChildren() {
              return null;
          }
      }
  
      public String computeAlias() {
          String alias = null;
  
          if (name instanceof SQLIdentifierExpr) {
              alias = ((SQLIdentifierExpr) name).getName();
          } else if (name instanceof SQLPropertyExpr) {
              alias = ((SQLPropertyExpr) name).getName();
          }
  
          return SQLUtils.normalize(alias);
      }
  
      public SQLColumnDefinition clone() {
          SQLColumnDefinition x = new SQLColumnDefinition();
          x.setDbType(dbType);
  
          if (name != null) {
              x.setName(name.clone());
          }
  
          if (dataType != null) {
              x.setDataType(dataType.clone());
          }
  
          if (defaultExpr != null) {
              x.setDefaultExpr(defaultExpr.clone());
          }
  
          for (SQLColumnConstraint item : constraints) {
              SQLColumnConstraint itemCloned = item.clone();
              itemCloned.setParent(x);
              x.constraints.add(itemCloned);
          }
  
          if (comment != null) {
              x.setComment(comment.clone());
          }
  
          x.enable = enable;
          x.validate = validate;
          x.rely = rely;
  
          x.autoIncrement = autoIncrement;
  
          if (onUpdate != null) {
              x.setOnUpdate(onUpdate.clone());
          }
  
          if (format != null) {
              x.setFormat(format.clone());
          }
  
          if (storage != null) {
              x.setStorage(storage.clone());
          }
  
          if (charsetExpr != null) {
              x.setCharsetExpr(charsetExpr.clone());
          }
  
          if (collateExpr != null) {
              x.setCollateExpr(collateExpr.clone());
          }
  
          if (asExpr != null) {
              x.setAsExpr(asExpr.clone());
          }
  
          x.stored = stored;
          x.virtual = virtual;
  
          if (identity != null) {
              x.setIdentity(identity.clone());
          }
  
          if (delimiter != null) {
              x.setDelimiter(delimiter.clone());
          }
  
          if (valueType != null) {
              x.setValueType(valueType.clone());
          }
  
          if (nlpTokenizer != null) {
              x.setNplTokenizer(nlpTokenizer.clone());
          }
  
          x.preSort = preSort;
          x.preSortOrder = preSortOrder;
  
          if (jsonIndexAttrsExpr != null) {
              x.setJsonIndexAttrsExpr(jsonIndexAttrsExpr.clone());
          }
  
          if (annIndex != null) {
              x.setAnnIndex(annIndex.clone());
          }
  
          if (mappedBy != null) {
              for (SQLAssignItem item : mappedBy) {
                  SQLAssignItem item2 = item.clone();
                  item2.setParent(this);
                  if (x.mappedBy == null) {
                      x.mappedBy = new ArrayList<SQLAssignItem>();
                  }
                  x.mappedBy.add(item2);
              }
          }
  
          if (colProperties != null) {
              for (SQLAssignItem item : colProperties) {
                  SQLAssignItem item2 = item.clone();
                  item2.setParent(this);
                  if (x.colProperties == null) {
                      x.colProperties = new ArrayList<SQLAssignItem>();
                  }
                  x.colProperties.add(item2);
              }
          }
  
          return x;
      }
  
      public DbType getDbType() {
          return dbType;
      }
  
      public void setDbType(DbType dbType) {
          this.dbType = dbType;
      }
  
      public void simplify() {
          enable = null;
          validate = null;
          rely = null;
  
          if (this.name instanceof SQLIdentifierExpr) {
              SQLIdentifierExpr identExpr = (SQLIdentifierExpr) this.name;
              String columnName = identExpr.getName();
              String normalized = SQLUtils.normalize(columnName, dbType);
              if (normalized != columnName) {
                  this.setName(normalized);
              }
          }
      }
  
      @Deprecated
      public boolean containsNotNullConstaint() {
          return containsNotNullConstraint();
      }
      public boolean containsNotNullConstraint() {
          for (SQLColumnConstraint constraint : this.constraints) {
              if (constraint instanceof SQLNotNullConstraint) {
                  return true;
              }
          }
  
          return false;
      }
  
      public SQLExpr getGeneratedAlwaysAs() {
          return generatedAlwaysAs;
      }
  
      public void setGeneratedAlwaysAs(SQLExpr x) {
          if (x != null) {
              x.setParent(this);
          }
          this.generatedAlwaysAs = x;
      }
  
      public boolean isVisible() {
          return visible;
      }
  
      public void setVisible(boolean visible) {
          this.visible = visible;
      }
  
      public SQLExpr getDelimiter() {
          return delimiter;
      }
  
      public boolean isDisableIndex() {
          return disableIndex;
      }
  
      public void setDisableIndex(boolean disableIndex) {
          this.disableIndex = disableIndex;
      }
  
      public void setDelimiter(SQLExpr x) {
          if (x != null) {
              x.setParent(this);
          }
          this.delimiter = x;
      }
  
      public SQLExpr getDelimiterTokenizer() {
          return delimiterTokenizer;
      }
  
      public void setDelimiterTokenizer(SQLExpr delimiterTokenizer) {
          this.delimiterTokenizer = delimiterTokenizer;
      }
  
      public SQLExpr getNlpTokenizer() {
          return nlpTokenizer;
      }
  
      public void setNlpTokenizer(SQLExpr nlpTokenizer) {
          this.nlpTokenizer = nlpTokenizer;
      }
  
      public SQLExpr getValueType() {
          return valueType;
      }
  
      public void setValueType(SQLExpr x) {
          if (x != null) {
              x.setParent(this);
          }
          this.valueType = x;
      }
  
      public boolean isPreSort() {
          return preSort;
      }
  
      public void setPreSort(boolean preSort) {
          this.preSort = preSort;
      }
  
      public int getPreSortOrder() {
          return preSortOrder;
      }
  
      public void setPreSortOrder(int preSortOrder) {
          this.preSortOrder = preSortOrder;
      }
  
      public SQLExpr getJsonIndexAttrsExpr() {
          return jsonIndexAttrsExpr;
      }
  
      public void setJsonIndexAttrsExpr(SQLExpr jsonIndexAttrsExpr) {
          this.jsonIndexAttrsExpr = jsonIndexAttrsExpr;
      }
  
      public SQLAnnIndex getAnnIndex() {
          return annIndex;
      }
  
      public void setAnnIndex(SQLAnnIndex x) {
          if (x != null) {
              x.setParent(this);
          }
          this.annIndex = x;
      }
  
      public AutoIncrementType getSequenceType() {
          return sequenceType;
      }
  
      public void setSequenceType(AutoIncrementType sequenceType) {
          this.sequenceType = sequenceType;
      }
  
      public String toString() {
          return SQLUtils.toSQLString(this, dbType);
      }
  
      public SQLExpr getUnitCount() {
          return unitCount;
      }
  
      public SQLExpr getUnitIndex() {
          return unitIndex;
      }
  
      public void setUnitIndex(SQLExpr unitIndex) {
          if (unitIndex != null) {
              unitIndex.setParent(this);
          }
          this.unitIndex = unitIndex;
      }
  
      public SQLExpr getNplTokenizer() {
          return nlpTokenizer;
      }
  
      public void setNplTokenizer(SQLExpr x) {
          if (x != null) {
              x.setParent(this);
          }
          this.nlpTokenizer = x;
      }
  
      public SQLExpr getStep() {
          return step;
      }
  
      public void setStep(SQLExpr step) {
          if (step != null) {
              step.setParent(this);
          }
          this.step = step;
      }
  
      public List<SQLAssignItem> getMappedBy() {
          if (mappedBy == null) {
              mappedBy = new ArrayList<SQLAssignItem>();
          }
          return mappedBy;
      }
  
      public List<SQLAssignItem> getMappedByDirect() {
          return mappedBy;
      }
  
      public List<SQLAssignItem> getColProperties() {
          if (colProperties == null) {
              colProperties = new ArrayList<SQLAssignItem>();
          }
          return colProperties;
      }
  
      public SQLExpr getEncode() {
          return encode;
      }
  
      public void setEncode(SQLExpr encode) {
          this.encode = encode;
      }
  
      public SQLExpr getCompression() {
          return compression;
      }
  
      public void setCompression(SQLExpr compression) {
          this.compression = compression;
      }
  
      public void setBlockSize(SQLIntegerExpr blockSize) {
          this.blockSize = blockSize;
      }
  
      public SQLIntegerExpr getBlockSize() {
          return blockSize;
      }
  
      public List<SQLAssignItem> getColPropertiesDirect() {
          return colProperties;
      }
  
  }
  