public void process()

in fe/fe-core/src/main/java/org/apache/doris/alter/SchemaChangeHandler.java [1905:2208]


    public void process(String rawSql, List<AlterClause> alterClauses, Database db,
                        OlapTable olapTable)
            throws UserException {
        olapTable.writeLockOrDdlException();
        try {
            olapTable.checkNormalStateForAlter();
            //alterClauses can or cannot light schema change
            boolean lightSchemaChange = true;
            boolean lightIndexChange = false;
            boolean buildIndexChange = false;

            // index id -> index schema
            Map<Long, LinkedList<Column>> indexSchemaMap = new HashMap<>();

            //for multi add columns clauses
            //index id -> index col_unique_id supplier
            Map<Long, IntSupplier> colUniqueIdSupplierMap = new HashMap<>();
            for (Map.Entry<Long, List<Column>> entry : olapTable.getIndexIdToSchema(true).entrySet()) {
                indexSchemaMap.put(entry.getKey(), new LinkedList<>(entry.getValue()));

                IntSupplier colUniqueIdSupplier = null;
                if (olapTable.getEnableLightSchemaChange()) {
                    colUniqueIdSupplier = new IntSupplier() {
                        public int pendingMaxColUniqueId = olapTable.getIndexMetaByIndexId(entry.getKey())
                                .getMaxColUniqueId();
                        public long indexId = entry.getKey();

                        @Override
                        public int getAsInt() {
                            pendingMaxColUniqueId++;
                            if (LOG.isDebugEnabled()) {
                                LOG.debug("index id:{}, pendingMaxColUniqueId:{}", indexId, pendingMaxColUniqueId);
                            }
                            return pendingMaxColUniqueId;
                        }
                    };
                }
                colUniqueIdSupplierMap.put(entry.getKey(), colUniqueIdSupplier);
            }
            if (LOG.isDebugEnabled()) {
                LOG.debug("in process indexSchemaMap:{}", indexSchemaMap);
            }

            List<Index> newIndexes = olapTable.getCopiedIndexes();
            List<Index> alterIndexes = new ArrayList<>();
            Map<Long, Set<String>> invertedIndexOnPartitions = new HashMap<>();
            boolean isDropIndex = false;
            Map<String, String> propertyMap = new HashMap<>();
            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");
                    }

                    // modification of colocate property is handle alone.
                    // And because there should be only one colocate property modification clause in stmt,
                    // so just return after finished handling.
                    if (properties.containsKey(PropertyAnalyzer.PROPERTIES_COLOCATE_WITH)) {
                        String colocateGroup = properties.get(PropertyAnalyzer.PROPERTIES_COLOCATE_WITH);
                        Env.getCurrentEnv().modifyTableColocate(db, olapTable, colocateGroup, false, null);
                        return;
                    } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_DISTRIBUTION_TYPE)) {
                        String distributionType = properties.get(PropertyAnalyzer.PROPERTIES_DISTRIBUTION_TYPE);
                        if (!distributionType.equalsIgnoreCase("random")) {
                            throw new DdlException(
                                    "Only support modifying distribution type of table from" + " hash to random");
                        }
                        Env.getCurrentEnv().convertDistributionType(db, olapTable);
                        return;
                    } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_SEND_CLEAR_ALTER_TASK)) {
                        /*
                         * This is only for fixing bug when upgrading Doris from 0.9.x to 0.10.x.
                         */
                        sendClearAlterTask(db, olapTable);
                        return;
                    } else if (DynamicPartitionUtil.checkDynamicPartitionPropertiesExist(properties)) {
                        DynamicPartitionUtil.checkDynamicPartitionPropertyKeysValid(properties);
                        if (!olapTable.dynamicPartitionExists()) {
                            try {
                                DynamicPartitionUtil.checkInputDynamicPartitionProperties(properties,
                                        olapTable);
                            } catch (DdlException e) {
                                // This table is not a dynamic partition table
                                // and didn't supply all dynamic partition properties
                                throw new DdlException("Table " + db.getFullName() + "." + olapTable.getName()
                                        + " is not a dynamic partition table." + " Use command `HELP ALTER TABLE` "
                                        + "to see how to change a normal table to a dynamic partition table.");
                            }
                        }
                        Env.getCurrentEnv().modifyTableDynamicPartition(db, olapTable, properties);
                        return;
                    } else if (properties.containsKey(
                            "default." + PropertyAnalyzer.PROPERTIES_REPLICATION_ALLOCATION)) {
                        Preconditions.checkNotNull(
                                properties.get("default." + PropertyAnalyzer.PROPERTIES_REPLICATION_ALLOCATION));
                        Env.getCurrentEnv().modifyTableDefaultReplicaAllocation(db, olapTable, properties);
                        return;
                    } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_REPLICATION_ALLOCATION)) {
                        Env.getCurrentEnv().modifyTableReplicaAllocation(db, olapTable, properties);
                        return;
                    } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_POLICY)) {
                        olapTable.setStoragePolicy(properties.get(PropertyAnalyzer.PROPERTIES_STORAGE_POLICY));
                        return;
                    } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_ENABLE_LIGHT_SCHEMA_CHANGE)) {
                        lightSchemaChange = Boolean.parseBoolean(
                                properties.get(PropertyAnalyzer.PROPERTIES_ENABLE_LIGHT_SCHEMA_CHANGE));
                        if (Objects.equals(olapTable.getEnableLightSchemaChange(), lightSchemaChange)) {
                            return;
                        }
                        if (!lightSchemaChange) {
                            throw new DdlException("Can not alter light_schema_change from true to false currently");
                        }
                        enableLightSchemaChange(db, olapTable);
                        return;
                    } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_STORE_ROW_COLUMN)
                                || properties.containsKey(PropertyAnalyzer.PROPERTIES_ROW_STORE_COLUMNS)) {
                        String value = properties.get(PropertyAnalyzer.PROPERTIES_STORE_ROW_COLUMN);
                        if (value != null && value.equalsIgnoreCase("false")) {
                            throw new DdlException("Can not alter store_row_column from true to false currently");
                        }
                        if (!olapTable.storeRowColumn()) {
                            Column rowColumn = ColumnDefinition
                                    .newRowStoreColumnDefinition(null).translateToCatalogStyle();
                            int maxColUniqueId = olapTable
                                    .getIndexMetaByIndexId(olapTable.getBaseIndexId()).getMaxColUniqueId();
                            rowColumn.setUniqueId(maxColUniqueId + 1);
                            indexSchemaMap.get(olapTable.getBaseIndexId()).add(rowColumn);
                        }
                    } else if (properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_MEDIUM)) {
                        Env.getCurrentEnv().modifyTableProperties(db, olapTable, properties);
                        return;
                    }
                }

                // the following operations can not be done when there are temp partitions exist.
                if (olapTable.existTempPartitions()) {
                    throw new DdlException("Can not alter table when there are temp partitions in table");
                }

                if (alterClause instanceof AddColumnClause) {
                    // add column
                    boolean clauseCanLightSchemaChange = processAddColumn((AddColumnClause) alterClause, olapTable,
                            indexSchemaMap, colUniqueIdSupplierMap);
                    if (!clauseCanLightSchemaChange) {
                        lightSchemaChange = false;
                    }
                } else if (alterClause instanceof AddColumnsClause) {
                    // add columns
                    boolean clauseCanLightSchemaChange = processAddColumns((AddColumnsClause) alterClause, olapTable,
                            indexSchemaMap, false, colUniqueIdSupplierMap);
                    if (!clauseCanLightSchemaChange) {
                        lightSchemaChange = false;
                    }
                } else if (alterClause instanceof DropColumnClause) {
                    // drop column and drop indexes on this column
                    boolean clauseCanLightSchemaChange = processDropColumn((DropColumnClause) alterClause, olapTable,
                            indexSchemaMap, newIndexes);
                    if (!clauseCanLightSchemaChange) {
                        lightSchemaChange = false;
                    }
                } else if (alterClause instanceof ModifyColumnClause) {
                    // modify column
                    boolean clauseCanLightSchemaChange = processModifyColumn((ModifyColumnClause) alterClause,
                            olapTable, indexSchemaMap);
                    if (!clauseCanLightSchemaChange) {
                        lightSchemaChange = false;
                    }
                } else if (alterClause instanceof ReorderColumnsClause) {
                    // reorder column
                    processReorderColumn((ReorderColumnsClause) alterClause, olapTable, indexSchemaMap);
                    lightSchemaChange = false;
                } else if (alterClause instanceof ModifyTablePropertiesClause) {
                    // modify table properties
                    // do nothing, properties are already in propertyMap
                    lightSchemaChange = false;
                } else if (alterClause instanceof CreateIndexClause) {
                    CreateIndexClause createIndexClause = (CreateIndexClause) alterClause;
                    Index index = createIndexClause.getIndex();
                    if (processAddIndex(createIndexClause, olapTable, newIndexes)) {
                        return;
                    }
                    lightSchemaChange = false;

                    if (index.isLightIndexChangeSupported() && !Config.isCloudMode()) {
                        alterIndexes.add(index);
                        isDropIndex = false;
                        // now only support light index change for inverted index
                        lightIndexChange = true;
                    }
                } else if (alterClause instanceof BuildIndexClause) {
                    BuildIndexClause buildIndexClause = (BuildIndexClause) alterClause;
                    IndexDef indexDef = buildIndexClause.getIndexDef();
                    Index index = buildIndexClause.getIndex();
                    if (Config.isCloudMode()) {
                        throw new DdlException("BUILD INDEX operation failed: No need to do it in cloud mode.");
                    }

                    if (!olapTable.isPartitionedTable()) {
                        List<String> specifiedPartitions = indexDef.getPartitionNames();
                        if (!specifiedPartitions.isEmpty()) {
                            throw new DdlException("table " + olapTable.getName()
                                    + " is not partitioned, cannot build index with partitions.");
                        }
                    }
                    List<Index> existedIndexes = olapTable.getIndexes();
                    boolean found = false;
                    for (Index existedIdx : existedIndexes) {
                        if (existedIdx.getIndexName().equalsIgnoreCase(indexDef.getIndexName())) {
                            found = true;
                            if (!existedIdx.isLightIndexChangeSupported()) {
                                throw new DdlException("BUILD INDEX operation failed: The index "
                                        + existedIdx.getIndexName() + " of type " + existedIdx.getIndexType()
                                        + " does not support lightweight index changes.");
                            }
                            for (Column column : olapTable.getBaseSchema()) {
                                if (!column.getType().isVariantType()) {
                                    continue;
                                }
                                // variant type column can not support for building index
                                for (String indexColumn : existedIdx.getColumns()) {
                                    if (column.getName().equalsIgnoreCase(indexColumn)) {
                                        throw new DdlException("BUILD INDEX operation failed: The "
                                                + indexDef.getIndexName() + " index can not be built on the "
                                                + indexColumn + " column, because it is a variant type column.");
                                    }
                                }
                            }
                            index = existedIdx.clone();
                            if (indexDef.getPartitionNames().isEmpty()) {
                                invertedIndexOnPartitions.put(index.getIndexId(), olapTable.getPartitionNames());
                            } else {
                                invertedIndexOnPartitions.put(
                                        index.getIndexId(), new HashSet<>(indexDef.getPartitionNames()));
                            }
                            break;
                        }
                    }
                    if (!found) {
                        throw new DdlException("index " + indexDef.getIndexName()
                                + " not exist, cannot build it with defferred.");
                    }

                    if (indexDef.isInvertedIndex()) {
                        alterIndexes.add(index);
                    }
                    buildIndexChange = true;
                    lightSchemaChange = false;
                } else if (alterClause instanceof DropIndexClause) {
                    if (processDropIndex((DropIndexClause) alterClause, olapTable, newIndexes)) {
                        return;
                    }
                    lightSchemaChange = false;

                    DropIndexClause dropIndexClause = (DropIndexClause) alterClause;
                    List<Index> existedIndexes = olapTable.getIndexes();
                    Index found = null;
                    for (Index existedIdx : existedIndexes) {
                        if (existedIdx.getIndexName().equalsIgnoreCase(dropIndexClause.getIndexName())) {
                            found = existedIdx;
                            break;
                        }
                    }
                    if (found.isLightIndexChangeSupported() && !Config.isCloudMode()) {
                        alterIndexes.add(found);
                        isDropIndex = true;
                        lightIndexChange = true;
                    }
                } else {
                    Preconditions.checkState(false);
                }
            } // end for alter clauses

            if (LOG.isDebugEnabled()) {
                LOG.debug("table: {}({}), lightSchemaChange: {}, lightIndexChange: {},"
                        + " buildIndexChange: {}, indexSchemaMap:{}",
                        olapTable.getName(), olapTable.getId(), lightSchemaChange,
                        lightIndexChange, buildIndexChange, indexSchemaMap);
            }

            if (lightSchemaChange) {
                long jobId = Env.getCurrentEnv().getNextId();
                //for schema change add/drop value column optimize, direct modify table meta.
                modifyTableLightSchemaChange(rawSql, db, olapTable, indexSchemaMap, newIndexes,
                                             null, isDropIndex, jobId, false);
            } else if (Config.enable_light_index_change && lightIndexChange) {
                long jobId = Env.getCurrentEnv().getNextId();
                //for schema change add/drop inverted index optimize, direct modify table meta firstly.
                modifyTableLightSchemaChange(rawSql, db, olapTable, indexSchemaMap, newIndexes,
                                             alterIndexes, isDropIndex, jobId, false);
            } else if (buildIndexChange) {
                if (Config.enable_light_index_change) {
                    buildOrDeleteTableInvertedIndices(db, olapTable, indexSchemaMap,
                                                      alterIndexes, invertedIndexOnPartitions, false);
                }
            } else {
                createJob(rawSql, db.getId(), olapTable, indexSchemaMap, propertyMap, newIndexes);
            }
        } finally {
            olapTable.writeUnlock();
        }
    }