in fe/fe-core/src/main/java/org/apache/doris/nereids/trees/plans/commands/info/ColumnDefinition.java [286:494]
public void validate(boolean isOlap, Set<String> keysSet, Set<String> clusterKeySet, boolean isEnableMergeOnWrite,
KeysType keysType) {
try {
FeNameFormat.checkColumnName(name);
FeNameFormat.checkColumnCommentLength(comment);
} catch (Exception e) {
throw new AnalysisException(e.getMessage(), e);
}
type.validateDataType();
type = updateCharacterTypeLength(type);
if (type.isArrayType()) {
int depth = 0;
DataType curType = type;
while (curType.isArrayType()) {
curType = ((ArrayType) curType).getItemType();
depth++;
}
if (depth > 9) {
throw new AnalysisException("Type exceeds the maximum nesting depth of 9");
}
}
if (type.isHllType() || type.isQuantileStateType() || type.isBitmapType()) {
if (isKey) {
throw new AnalysisException("Key column can not set complex type:" + name);
}
if (keysType.equals(KeysType.AGG_KEYS)) {
if (aggType == null) {
throw new AnalysisException("complex type have to use aggregate function: " + name);
}
}
if (isNullable) {
throw new AnalysisException("complex type column must be not nullable, column:" + name);
}
}
if (keysSet.contains(name)) {
isKey = true;
}
// check keys type
if (isKey || clusterKeySet.contains(name)) {
checkKeyColumnType(isOlap);
}
if (aggType != null) {
if (isKey) {
throw new AnalysisException(
String.format("Key column %s can not set aggregation type", name));
}
// check if aggregate type is valid
if (aggType != AggregateType.GENERIC
&& !aggType.checkCompatibility(type.toCatalogDataType().getPrimitiveType())) {
throw new AnalysisException(String.format("Aggregate type %s is not compatible with primitive type %s",
aggType, type.toSql()));
}
if (aggType == AggregateType.GENERIC) {
if (!SessionVariable.enableAggState()) {
throw new AnalysisException("agg state not enable, need set enable_agg_state=true");
}
}
} else if (aggType == null && isOlap && !isKey) {
Preconditions.checkState(keysType != null, "keysType is null");
if (keysType.equals(KeysType.DUP_KEYS)) {
aggType = AggregateType.NONE;
} else if (keysType.equals(KeysType.UNIQUE_KEYS) && isEnableMergeOnWrite) {
aggType = AggregateType.NONE;
} else if (!keysType.equals(KeysType.AGG_KEYS)) {
aggType = AggregateType.REPLACE;
} else {
throw new AnalysisException("should set aggregation type to non-key column in aggregate key table");
}
}
if (isOlap) {
if (!isKey) {
if (keysType.equals(KeysType.UNIQUE_KEYS)) {
if (isEnableMergeOnWrite) {
aggTypeImplicit = false;
} else {
aggTypeImplicit = true;
}
} else if (keysType.equals(KeysType.DUP_KEYS)) {
aggTypeImplicit = true;
}
}
// If aggregate type is REPLACE_IF_NOT_NULL, we set it nullable.
// If default value is not set, we set it NULL
if (aggType == AggregateType.REPLACE_IF_NOT_NULL) {
if (!isNullable) {
throw new AnalysisException(
"REPLACE_IF_NOT_NULL column must be nullable, maybe should use REPLACE, column:" + name);
}
if (!defaultValue.isPresent()) {
defaultValue = Optional.of(DefaultValue.NULL_DEFAULT_VALUE);
}
}
}
// check default value
if (type.isHllType()) {
if (defaultValue.isPresent()) {
throw new AnalysisException("Hll type column can not set default value");
}
defaultValue = Optional.of(DefaultValue.HLL_EMPTY_DEFAULT_VALUE);
} else if (type.isBitmapType()) {
if (defaultValue.isPresent() && isOlap && defaultValue.get() != DefaultValue.NULL_DEFAULT_VALUE
&& !defaultValue.get().getValue().equals(DefaultValue.BITMAP_EMPTY_DEFAULT_VALUE.getValue())) {
throw new AnalysisException("Bitmap type column default value only support "
+ DefaultValue.BITMAP_EMPTY_DEFAULT_VALUE);
}
defaultValue = Optional.of(DefaultValue.BITMAP_EMPTY_DEFAULT_VALUE);
} else if (type.isArrayType() && defaultValue.isPresent() && isOlap
&& defaultValue.get() != DefaultValue.NULL_DEFAULT_VALUE && !defaultValue.get()
.getValue().equals(DefaultValue.ARRAY_EMPTY_DEFAULT_VALUE.getValue())) {
throw new AnalysisException("Array type column default value only support null or "
+ DefaultValue.ARRAY_EMPTY_DEFAULT_VALUE);
} else if (type.isMapType()) {
if (defaultValue.isPresent() && defaultValue.get() != DefaultValue.NULL_DEFAULT_VALUE) {
throw new AnalysisException("Map type column default value just support null");
}
} else if (type.isStructType()) {
if (defaultValue.isPresent() && defaultValue.get() != DefaultValue.NULL_DEFAULT_VALUE) {
throw new AnalysisException("Struct type column default value just support null");
}
} else if (type.isJsonType() || type.isVariantType()) {
if (defaultValue.isPresent() && defaultValue.get() != DefaultValue.NULL_DEFAULT_VALUE) {
throw new AnalysisException("Json or Variant type column default value just support null");
}
}
if (!isNullable && defaultValue.isPresent()
&& defaultValue.get() == DefaultValue.NULL_DEFAULT_VALUE) {
throw new AnalysisException(
"Can not set null default value to non nullable column: " + name);
}
if (defaultValue.isPresent()
&& defaultValue.get().getValue() != null
&& type.toCatalogDataType().isScalarType()) {
try {
ColumnDef.validateDefaultValue(type.toCatalogDataType(),
defaultValue.get().getValue(), defaultValue.get().getDefaultValueExprDef());
} catch (Exception e) {
throw new AnalysisException(e.getMessage(), e);
}
}
if (onUpdateDefaultValue.isPresent()
&& onUpdateDefaultValue.get().getValue() != null
&& type.toCatalogDataType().isScalarType()) {
try {
ColumnDef.validateDefaultValue(type.toCatalogDataType(),
onUpdateDefaultValue.get().getValue(), onUpdateDefaultValue.get().getDefaultValueExprDef());
} catch (Exception e) {
throw new AnalysisException("meet error when validating the on update value of column["
+ name + "], reason: " + e.getMessage());
}
if (onUpdateDefaultValue.get().isCurrentTimeStamp()) {
if (!defaultValue.isPresent() || !defaultValue.get().isCurrentTimeStamp()) {
throw new AnalysisException("You must set the default value of the column["
+ name + "] to CURRENT_TIMESTAMP when using 'ON UPDATE CURRENT_TIMESTAMP'.");
}
} else if (onUpdateDefaultValue.get().isCurrentTimeStampWithPrecision()) {
if (!defaultValue.isPresent() || !defaultValue.get().isCurrentTimeStampWithPrecision()) {
throw new AnalysisException("You must set the default value of the column["
+ name + "] to CURRENT_TIMESTAMP when using 'ON UPDATE CURRENT_TIMESTAMP'.");
}
long precision1 = onUpdateDefaultValue.get().getCurrentTimeStampPrecision();
long precision2 = defaultValue.get().getCurrentTimeStampPrecision();
if (precision1 != precision2) {
throw new AnalysisException("The precision of the default value of column["
+ name + "] should be the same with the precision in 'ON UPDATE CURRENT_TIMESTAMP'.");
}
}
}
// from old planner CreateTableStmt's analyze method, after call columnDef.analyze(engineName.equals("olap"));
if (isOlap && type.isComplexType()) {
if (isKey) {
throw new AnalysisException(type.toCatalogDataType().getPrimitiveType()
+ " can only be used in the non-key column at present.");
}
if (type.isAggStateType()) {
if (aggType == null) {
throw new AnalysisException(type.toCatalogDataType().getPrimitiveType()
+ " column must have aggregation type");
} else {
if (aggType != AggregateType.GENERIC
&& aggType != AggregateType.NONE
&& aggType != AggregateType.REPLACE
&& aggType != AggregateType.REPLACE_IF_NOT_NULL) {
throw new AnalysisException(type.toCatalogDataType().getPrimitiveType()
+ " column can't support aggregation " + aggType);
}
}
} else {
if (aggType != null && aggType != AggregateType.NONE && aggType != AggregateType.REPLACE
&& aggType != AggregateType.REPLACE_IF_NOT_NULL) {
throw new AnalysisException(type.toCatalogDataType().getPrimitiveType()
+ " column can't support aggregation " + aggType);
}
}
}
if (type.isTimeLikeType()) {
throw new AnalysisException("Time type is not supported for olap table");
}
validateGeneratedColumnInfo();
}