Code review comment: > So that means this function can only be called by `AlterJobMgr::processAlterTable`? But my question is that if `AlterJobMgr::processAlterTable` is refactored someday, will it cause new issues here? Because he/she may not know this function depends on its implementation. It seems there is no statement or function name to notice developer that this function needs db lock to be held.  If someone refactor the function `AlterJobMgr::processAlterTable` and remove db lock, it maybe cause new issue. I change the `maxColumnUniqueId` to atomic to prevent it.

Code under review:
public AlterJobV2 analyzeAndCreateJob(List<AlterClause> alterClauses, Database db, OlapTable olapTable) throws UserException {
        
        if (olapTable == null) {
            throw new DdlException("olapTable is null");
        }
        boolean fastSchemaEvolution = olapTable.getUseFastSchemaEvolution();
        
        IntSupplier colUniqueIdSupplier = new IntSupplier() {
            private int pendingMaxColUniqueId = olapTable.getMaxColUniqueId();

            @Override
            public int getAsInt() {
                pendingMaxColUniqueId++;
                return pendingMaxColUniqueId;
            }
        };

        
        Map<Long, LinkedList<Column>> indexSchemaMap = new HashMap<>();
        for (Map.Entry<Long, List<Column>> entry : olapTable.getIndexIdToSchema().entrySet()) {
            indexSchemaMap.put(entry.getKey(), new LinkedList<>(entry.getValue()));
        }
        List<Index> newIndexes = olapTable.getCopiedIndexes();
        Map<String, String> propertyMap = new HashMap<>();
        Set<String> modifyFieldColumns = new HashSet<>();
        for (AlterClause alterClause : alterClauses) {
            Map<String, String> properties = alterClause.getProperties();
            if (properties != null) {
                if (propertyMap.isEmpty()) {
                    propertyMap.putAll(properties);
                } else {
                    throw new DdlException("reduplicated PROPERTIES");
                }

                
                
                
                if (properties.containsKey(PropertyAnalyzer.PROPERTIES_COLOCATE_WITH)) {
                    if (olapTable.getLocation() != null) {
                        ErrorReport.reportDdlException(
                                ErrorCode.ERR_LOC_AWARE_UNSUPPORTED_FOR_COLOCATE_TBL, olapTable.getName());
                    }
                    String colocateGroup = properties.get(PropertyAnalyzer.PROPERTIES_COLOCATE_WITH);
                    GlobalStateMgr.getCurrentState().getColocateTableIndex()
                            .modifyTableColocate(db, olapTable, colocateGroup, false, null);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_DISTRIBUTION_TYPE)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().convertDistributionType(db, olapTable);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_SEND_CLEAR_ALTER_TASK)) {
                    /*
                     * This is only for fixing bug when upgrading StarRocks from 0.9.x to 0.10.x.
                     */
                    sendClearAlterTask(db, olapTable);
                    return null;
                } else if (DynamicPartitionUtil.checkDynamicPartitionPropertiesExist(properties)) {
                    if (!olapTable.dynamicPartitionExists()) {
                        try {
                            DynamicPartitionUtil
                                    .checkInputDynamicPartitionProperties(olapTable, properties, olapTable.getPartitionInfo());
                        } catch (DdlException e) {
                            
                            throw new DdlException("Table " + db.getOriginName() + "." +
                                    olapTable.getName() + " is not a dynamic partition table.");
                        }
                    }
                    if (properties.containsKey(DynamicPartitionProperty.BUCKETS)) {
                        String colocateGroup = olapTable.getColocateGroup();
                        if (colocateGroup != null) {
                            throw new DdlException("The table has a colocate group:" + colocateGroup + ". so cannot " +
                                    "modify dynamic_partition.buckets. Colocate tables must have same bucket number.");
                        }
                    }
                    GlobalStateMgr.getCurrentState().getLocalMetastore().modifyTableDynamicPartition(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey("default." + PropertyAnalyzer.PROPERTIES_REPLICATION_NUM)) {
                    Preconditions.checkNotNull(properties.get(PropertyAnalyzer.PROPERTIES_REPLICATION_NUM));
                    GlobalStateMgr.getCurrentState().getLocalMetastore()
                            .modifyTableDefaultReplicationNum(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_REPLICATION_NUM)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().modifyTableReplicationNum(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_WRITE_QUORUM)) {
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_REPLICATED_STORAGE)) {
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_PARTITION_LIVE_NUMBER)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_MEDIUM)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_COOLDOWN_TTL)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_DATACACHE_PARTITION_DURATION)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_LABELS_LOCATION)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                }
            }

            if (GlobalStateMgr.getCurrentState().getInsertOverwriteJobMgr().hasRunningOverwriteJob(olapTable.getId())) {
                
                throw new DdlException("Table[" + olapTable.getName() + "] is doing insert overwrite job, " +
                        "please start schema change after insert overwrite finished");
            }
            
            if (olapTable.existTempPartitions()) {
                throw new DdlException("Can not alter table when there are temp partitions in table");
            }

            if (alterClause instanceof AddColumnClause) {
                
                fastSchemaEvolution &=
                        processAddColumn((AddColumnClause) alterClause, olapTable, indexSchemaMap, colUniqueIdSupplier);
            } else if (alterClause instanceof AddColumnsClause) {
                
                fastSchemaEvolution &=
                        processAddColumns((AddColumnsClause) alterClause, olapTable, indexSchemaMap, colUniqueIdSupplier);
            } else if (alterClause instanceof DropColumnClause) {
                DropColumnClause dropColumnClause = (DropColumnClause) alterClause;
                
                Set<String> modifiedColumns = Set.of(dropColumnClause.getColName());
                checkModifiedColumWithMaterializedViews(olapTable, modifiedColumns);

                
                fastSchemaEvolution &=
                        processDropColumn((DropColumnClause) alterClause, olapTable, indexSchemaMap,
                                newIndexes);
            } else if (alterClause instanceof ModifyColumnClause) {
                ModifyColumnClause modifyColumnClause = (ModifyColumnClause) alterClause;

                
                Set<String> modifiedColumns = Set.of(modifyColumnClause.getColumn().getName());
                checkModifiedColumWithMaterializedViews(olapTable, modifiedColumns);

                
                fastSchemaEvolution &= processModifyColumn(modifyColumnClause, olapTable, indexSchemaMap);
            } else if (alterClause instanceof AddFieldClause) {
                if (RunMode.isSharedDataMode()) {
                    throw new DdlException("Add field for struct column not support shared-data mode so far");
                }
                if (!fastSchemaEvolution) {
                    throw new DdlException("Add field for struct column require table enable fast schema evolution");
                }
                AddFieldClause addFieldClause = (AddFieldClause) alterClause;
                modifyFieldColumns = Set.of(addFieldClause.getColName());
                checkModifiedColumWithMaterializedViews(olapTable, modifyFieldColumns);

                
                
                
                int id = olapTable.incAndGetMaxColUniqueId();
                processAddField((AddFieldClause) alterClause, olapTable, indexSchemaMap, id, newIndexes);
            } else if (alterClause instanceof DropFieldClause) {
                if (RunMode.isSharedDataMode()) {
                    throw new DdlException("Drop field for struct column not support shared-data mode so far");
                }
                if (!fastSchemaEvolution) {
                    throw new DdlException("Drop field for struct column require table enable fast schema evolution");
                }
                DropFieldClause dropFieldClause = (DropFieldClause) alterClause;
                modifyFieldColumns = Set.of(dropFieldClause.getColName());
                checkModifiedColumWithMaterializedViews(olapTable, modifyFieldColumns);
                processDropField((DropFieldClause) alterClause, olapTable, indexSchemaMap, newIndexes);
            } else if (alterClause instanceof ReorderColumnsClause) {
                
                fastSchemaEvolution = false;
                if (changeSortKeyColumn((ReorderColumnsClause) alterClause, olapTable)) {
                    
                    List<Integer> sortKeyIdxes = new ArrayList<>();
                    List<Integer> sortKeyUniqueIds = new ArrayList<>();
                    processModifySortKeyColumn((ReorderColumnsClause) alterClause, olapTable, indexSchemaMap, sortKeyIdxes,
                            sortKeyUniqueIds);
                    return createJobForProcessModifySortKeyColumn(db.getId(), olapTable, indexSchemaMap, sortKeyIdxes,
                            sortKeyUniqueIds);
                } else {
                    processReorderColumn((ReorderColumnsClause) alterClause, olapTable, indexSchemaMap);
                }
            } else if (alterClause instanceof ModifyTablePropertiesClause) {
                
                
                fastSchemaEvolution = false;
            } else if (alterClause instanceof CreateIndexClause) {
                fastSchemaEvolution = false;
                processAddIndex((CreateIndexClause) alterClause, olapTable, newIndexes);
            } else if (alterClause instanceof DropIndexClause) {
                fastSchemaEvolution = false;
                processDropIndex((DropIndexClause) alterClause, olapTable, newIndexes);
            } else if (alterClause instanceof OptimizeClause) {
                return createOptimizeTableJob((OptimizeClause) alterClause, db, olapTable, propertyMap);
            } else {
                Preconditions.checkState(false);
            }
        } 

        SchemaChangeData schemaChangeData = finalAnalyze(db, olapTable, indexSchemaMap, propertyMap, newIndexes,
                                                         modifyFieldColumns);

        if (schemaChangeData.getNewIndexSchema().isEmpty() && !schemaChangeData.isHasIndexChanged()) {
            
            return null;
        }

        if (!fastSchemaEvolution) {
            return createJob(schemaChangeData);
        } else if (RunMode.isSharedNothingMode()) {
            fastSchemaEvolutionInShareNothingMode(schemaChangeData);
            return null;
        } else {
            return createFastSchemaEvolutionJobInSharedDataMode(schemaChangeData);
        }
    }


Revised code:
public AlterJobV2 analyzeAndCreateJob(List<AlterClause> alterClauses, Database db, OlapTable olapTable) throws UserException {
        
        if (olapTable == null) {
            throw new DdlException("olapTable is null");
        }
        boolean fastSchemaEvolution = olapTable.getUseFastSchemaEvolution();
        
        IntSupplier colUniqueIdSupplier = new IntSupplier() {
            private int pendingMaxColUniqueId = olapTable.getMaxColUniqueId();

            @Override
            public int getAsInt() {
                pendingMaxColUniqueId++;
                return pendingMaxColUniqueId;
            }
        };

        
        Map<Long, LinkedList<Column>> indexSchemaMap = new HashMap<>();
        for (Map.Entry<Long, List<Column>> entry : olapTable.getIndexIdToSchema().entrySet()) {
            indexSchemaMap.put(entry.getKey(), new LinkedList<>(entry.getValue()));
        }
        List<Index> newIndexes = olapTable.getCopiedIndexes();
        Map<String, String> propertyMap = new HashMap<>();
        Set<String> modifyFieldColumns = new HashSet<>();
        for (AlterClause alterClause : alterClauses) {
            Map<String, String> properties = alterClause.getProperties();
            if (properties != null) {
                if (propertyMap.isEmpty()) {
                    propertyMap.putAll(properties);
                } else {
                    throw new DdlException("reduplicated PROPERTIES");
                }

                
                
                
                if (properties.containsKey(PropertyAnalyzer.PROPERTIES_COLOCATE_WITH)) {
                    if (olapTable.getLocation() != null) {
                        ErrorReport.reportDdlException(
                                ErrorCode.ERR_LOC_AWARE_UNSUPPORTED_FOR_COLOCATE_TBL, olapTable.getName());
                    }
                    String colocateGroup = properties.get(PropertyAnalyzer.PROPERTIES_COLOCATE_WITH);
                    GlobalStateMgr.getCurrentState().getColocateTableIndex()
                            .modifyTableColocate(db, olapTable, colocateGroup, false, null);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_DISTRIBUTION_TYPE)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().convertDistributionType(db, olapTable);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_SEND_CLEAR_ALTER_TASK)) {
                    /*
                     * This is only for fixing bug when upgrading StarRocks from 0.9.x to 0.10.x.
                     */
                    sendClearAlterTask(db, olapTable);
                    return null;
                } else if (DynamicPartitionUtil.checkDynamicPartitionPropertiesExist(properties)) {
                    if (!olapTable.dynamicPartitionExists()) {
                        try {
                            DynamicPartitionUtil
                                    .checkInputDynamicPartitionProperties(olapTable, properties, olapTable.getPartitionInfo());
                        } catch (DdlException e) {
                            
                            throw new DdlException("Table " + db.getOriginName() + "." +
                                    olapTable.getName() + " is not a dynamic partition table.");
                        }
                    }
                    if (properties.containsKey(DynamicPartitionProperty.BUCKETS)) {
                        String colocateGroup = olapTable.getColocateGroup();
                        if (colocateGroup != null) {
                            throw new DdlException("The table has a colocate group:" + colocateGroup + ". so cannot " +
                                    "modify dynamic_partition.buckets. Colocate tables must have same bucket number.");
                        }
                    }
                    GlobalStateMgr.getCurrentState().getLocalMetastore().modifyTableDynamicPartition(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey("default." + PropertyAnalyzer.PROPERTIES_REPLICATION_NUM)) {
                    Preconditions.checkNotNull(properties.get(PropertyAnalyzer.PROPERTIES_REPLICATION_NUM));
                    GlobalStateMgr.getCurrentState().getLocalMetastore()
                            .modifyTableDefaultReplicationNum(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_REPLICATION_NUM)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().modifyTableReplicationNum(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_WRITE_QUORUM)) {
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_REPLICATED_STORAGE)) {
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_PARTITION_LIVE_NUMBER)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_MEDIUM)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_COOLDOWN_TTL)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_DATACACHE_PARTITION_DURATION)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_LABELS_LOCATION)) {
                    GlobalStateMgr.getCurrentState().getLocalMetastore().alterTableProperties(db, olapTable, properties);
                    return null;
                }
            }

            if (GlobalStateMgr.getCurrentState().getInsertOverwriteJobMgr().hasRunningOverwriteJob(olapTable.getId())) {
                
                throw new DdlException("Table[" + olapTable.getName() + "] is doing insert overwrite job, " +
                        "please start schema change after insert overwrite finished");
            }
            
            if (olapTable.existTempPartitions()) {
                throw new DdlException("Can not alter table when there are temp partitions in table");
            }

            if (alterClause instanceof AddColumnClause) {
                
                fastSchemaEvolution &=
                        processAddColumn((AddColumnClause) alterClause, olapTable, indexSchemaMap, colUniqueIdSupplier);
            } else if (alterClause instanceof AddColumnsClause) {
                
                fastSchemaEvolution &=
                        processAddColumns((AddColumnsClause) alterClause, olapTable, indexSchemaMap, colUniqueIdSupplier);
            } else if (alterClause instanceof DropColumnClause) {
                DropColumnClause dropColumnClause = (DropColumnClause) alterClause;
                
                Set<String> modifiedColumns = Set.of(dropColumnClause.getColName());
                checkModifiedColumWithMaterializedViews(olapTable, modifiedColumns);

                
                fastSchemaEvolution &=
                        processDropColumn((DropColumnClause) alterClause, olapTable, indexSchemaMap,
                                newIndexes);
            } else if (alterClause instanceof ModifyColumnClause) {
                ModifyColumnClause modifyColumnClause = (ModifyColumnClause) alterClause;

                
                Set<String> modifiedColumns = Set.of(modifyColumnClause.getColumn().getName());
                checkModifiedColumWithMaterializedViews(olapTable, modifiedColumns);

                
                fastSchemaEvolution &= processModifyColumn(modifyColumnClause, olapTable, indexSchemaMap);
            } else if (alterClause instanceof AddFieldClause) {
                if (RunMode.isSharedDataMode()) {
                    throw new DdlException("Add field for struct column not support shared-data mode so far");
                }
                if (!fastSchemaEvolution) {
                    throw new DdlException("Add field for struct column require table enable fast schema evolution");
                }
                AddFieldClause addFieldClause = (AddFieldClause) alterClause;
                modifyFieldColumns = Set.of(addFieldClause.getColName());
                checkModifiedColumWithMaterializedViews(olapTable, modifyFieldColumns);
  
                int id = colUniqueIdSupplier.getAsInt();
                processAddField((AddFieldClause) alterClause, olapTable, indexSchemaMap, id, newIndexes);
            } else if (alterClause instanceof DropFieldClause) {
                if (RunMode.isSharedDataMode()) {
                    throw new DdlException("Drop field for struct column not support shared-data mode so far");
                }
                if (!fastSchemaEvolution) {
                    throw new DdlException("Drop field for struct column require table enable fast schema evolution");
                }
                DropFieldClause dropFieldClause = (DropFieldClause) alterClause;
                modifyFieldColumns = Set.of(dropFieldClause.getColName());
                checkModifiedColumWithMaterializedViews(olapTable, modifyFieldColumns);
                processDropField((DropFieldClause) alterClause, olapTable, indexSchemaMap, newIndexes);
            } else if (alterClause instanceof ReorderColumnsClause) {
                
                fastSchemaEvolution = false;
                if (changeSortKeyColumn((ReorderColumnsClause) alterClause, olapTable)) {
                    
                    List<Integer> sortKeyIdxes = new ArrayList<>();
                    List<Integer> sortKeyUniqueIds = new ArrayList<>();
                    processModifySortKeyColumn((ReorderColumnsClause) alterClause, olapTable, indexSchemaMap, sortKeyIdxes,
                            sortKeyUniqueIds);
                    return createJobForProcessModifySortKeyColumn(db.getId(), olapTable, indexSchemaMap, sortKeyIdxes,
                            sortKeyUniqueIds);
                } else {
                    processReorderColumn((ReorderColumnsClause) alterClause, olapTable, indexSchemaMap);
                }
            } else if (alterClause instanceof ModifyTablePropertiesClause) {
                
                
                fastSchemaEvolution = false;
            } else if (alterClause instanceof CreateIndexClause) {
                fastSchemaEvolution = false;
                processAddIndex((CreateIndexClause) alterClause, olapTable, newIndexes);
            } else if (alterClause instanceof DropIndexClause) {
                fastSchemaEvolution = false;
                processDropIndex((DropIndexClause) alterClause, olapTable, newIndexes);
            } else if (alterClause instanceof OptimizeClause) {
                return createOptimizeTableJob((OptimizeClause) alterClause, db, olapTable, propertyMap);
            } else {
                Preconditions.checkState(false);
            }
        } 

        SchemaChangeData schemaChangeData = finalAnalyze(db, olapTable, indexSchemaMap, propertyMap, newIndexes,
                                                         modifyFieldColumns);

        if (schemaChangeData.getNewIndexSchema().isEmpty() && !schemaChangeData.isHasIndexChanged()) {
            
            return null;
        }

        if (!fastSchemaEvolution) {
            return createJob(schemaChangeData);
        } else if (RunMode.isSharedNothingMode()) {
            fastSchemaEvolutionInShareNothingMode(schemaChangeData);
            return null;
        } else {
            return createFastSchemaEvolutionJobInSharedDataMode(schemaChangeData);
        }
    }