public void validate()

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();
    }