[feature](alter) support rename column for table with unique column id (#13410)
This commit is contained in:
@ -190,6 +190,7 @@ import org.apache.doris.persist.StorageInfo;
|
||||
import org.apache.doris.persist.StorageInfoV2;
|
||||
import org.apache.doris.persist.TableInfo;
|
||||
import org.apache.doris.persist.TablePropertyInfo;
|
||||
import org.apache.doris.persist.TableRenameColumnInfo;
|
||||
import org.apache.doris.persist.TruncateTableInfo;
|
||||
import org.apache.doris.persist.meta.MetaHeader;
|
||||
import org.apache.doris.persist.meta.MetaReader;
|
||||
@ -4030,12 +4031,114 @@ public class Env {
|
||||
}
|
||||
}
|
||||
|
||||
public void renameColumn(Database db, OlapTable table, ColumnRenameClause renameClause) throws DdlException {
|
||||
throw new DdlException("not implemented");
|
||||
public void renameColumn(Database db, OlapTable table, String colName,
|
||||
String newColName, boolean isReplay) throws DdlException {
|
||||
if (table.getState() != OlapTableState.NORMAL) {
|
||||
throw new DdlException("Table[" + table.getName() + "] is under " + table.getState());
|
||||
}
|
||||
|
||||
if (colName.equalsIgnoreCase(newColName)) {
|
||||
throw new DdlException("Same column name");
|
||||
}
|
||||
|
||||
Map<Long, MaterializedIndexMeta> indexIdToMeta = table.getIndexIdToMeta();
|
||||
for (Map.Entry<Long, MaterializedIndexMeta> entry : indexIdToMeta.entrySet()) {
|
||||
// rename column is not implemented for table without column unique id.
|
||||
if (entry.getValue().getMaxColUniqueId() < 0) {
|
||||
throw new DdlException("not implemented for table without column unique id,"
|
||||
+ " which are created with property 'light_schema_change'.");
|
||||
}
|
||||
// check if new name is already used
|
||||
if (entry.getValue().getColumnByName(newColName) != null) {
|
||||
throw new DdlException("Column name[" + newColName + "] is already used");
|
||||
}
|
||||
}
|
||||
|
||||
// 1. modify MaterializedIndexMeta
|
||||
boolean hasColumn = false;
|
||||
for (Map.Entry<Long, MaterializedIndexMeta> entry : indexIdToMeta.entrySet()) {
|
||||
Column column = entry.getValue().getColumnByName(colName);
|
||||
if (column != null) {
|
||||
column.setName(newColName);
|
||||
hasColumn = true;
|
||||
}
|
||||
}
|
||||
if (!hasColumn) {
|
||||
throw new DdlException("Column[" + colName + "] does not exists");
|
||||
}
|
||||
|
||||
// 2. modify partition key
|
||||
PartitionInfo partitionInfo = table.getPartitionInfo();
|
||||
List<Column> partitionColumns = partitionInfo.getPartitionColumns();
|
||||
for (Column column : partitionColumns) {
|
||||
if (column.getName().equalsIgnoreCase(colName)) {
|
||||
column.setName(newColName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 3. modify index
|
||||
List<Index> indexes = table.getIndexes();
|
||||
for (Index index : indexes) {
|
||||
List<String> columns = index.getColumns();
|
||||
for (int i = 0; i < columns.size(); i++) {
|
||||
if (columns.get(i).equalsIgnoreCase(colName)) {
|
||||
columns.set(i, newColName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 4. modify distribution info
|
||||
DistributionInfo distributionInfo = table.getDefaultDistributionInfo();
|
||||
if (distributionInfo.getType() == DistributionInfoType.HASH) {
|
||||
List<Column> distributionColumns = ((HashDistributionInfo) distributionInfo).getDistributionColumns();
|
||||
for (Column column : distributionColumns) {
|
||||
if (column.getName().equalsIgnoreCase(colName)) {
|
||||
column.setName(newColName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
table.rebuildFullSchema();
|
||||
|
||||
if (!isReplay) {
|
||||
// log
|
||||
TableRenameColumnInfo info = new TableRenameColumnInfo(db.getId(), table.getId(), colName, newColName);
|
||||
editLog.logColumnRename(info);
|
||||
LOG.info("rename coloumn[{}] to {}", colName, newColName);
|
||||
}
|
||||
}
|
||||
|
||||
public void replayRenameColumn(TableInfo tableInfo) throws DdlException {
|
||||
throw new DdlException("not implemented");
|
||||
public void renameColumn(Database db, OlapTable table, ColumnRenameClause renameClause) throws DdlException {
|
||||
table.writeLockOrDdlException();
|
||||
try {
|
||||
String colName = renameClause.getColName();
|
||||
String newColName = renameClause.getNewColName();
|
||||
renameColumn(db, table, colName, newColName, false);
|
||||
} finally {
|
||||
table.writeUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void replayRenameColumn(TableRenameColumnInfo info) throws MetaNotFoundException {
|
||||
LOG.debug("info:{}", info);
|
||||
long dbId = info.getDbId();
|
||||
long tableId = info.getTableId();
|
||||
String colName = info.getColName();
|
||||
String newColName = info.getNewColName();
|
||||
|
||||
Database db = getCurrentEnv().getInternalCatalog().getDbOrMetaException(dbId);
|
||||
OlapTable table = (OlapTable) db.getTableOrMetaException(tableId, TableType.OLAP);
|
||||
table.writeLock();
|
||||
try {
|
||||
renameColumn(db, table, colName, newColName, true);
|
||||
} catch (DdlException e) {
|
||||
// should not happen
|
||||
LOG.warn("failed to replay rename column", e);
|
||||
} finally {
|
||||
table.writeUnlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void modifyTableDynamicPartition(Database db, OlapTable table, Map<String, String> properties)
|
||||
|
||||
@ -92,6 +92,7 @@ import org.apache.doris.persist.SetReplicaStatusOperationLog;
|
||||
import org.apache.doris.persist.TableAddOrDropColumnsInfo;
|
||||
import org.apache.doris.persist.TableInfo;
|
||||
import org.apache.doris.persist.TablePropertyInfo;
|
||||
import org.apache.doris.persist.TableRenameColumnInfo;
|
||||
import org.apache.doris.persist.TruncateTableInfo;
|
||||
import org.apache.doris.plugin.PluginInfo;
|
||||
import org.apache.doris.policy.DropPolicyLog;
|
||||
@ -256,6 +257,11 @@ public class JournalEntity implements Writable {
|
||||
isRead = true;
|
||||
break;
|
||||
}
|
||||
case OperationType.OP_RENAME_COLUMN: {
|
||||
data = TableRenameColumnInfo.read(in);
|
||||
isRead = true;
|
||||
break;
|
||||
}
|
||||
case OperationType.OP_MODIFY_VIEW_DEF: {
|
||||
data = AlterViewInfo.read(in);
|
||||
isRead = true;
|
||||
|
||||
@ -279,6 +279,11 @@ public class EditLog {
|
||||
env.replayRenamePartition(info);
|
||||
break;
|
||||
}
|
||||
case OperationType.OP_RENAME_COLUMN: {
|
||||
TableRenameColumnInfo info = (TableRenameColumnInfo) journal.getData();
|
||||
env.replayRenameColumn(info);
|
||||
break;
|
||||
}
|
||||
case OperationType.OP_BACKUP_JOB: {
|
||||
BackupJob job = (BackupJob) journal.getData();
|
||||
env.getBackupHandler().replayAddJob(job);
|
||||
@ -1220,6 +1225,10 @@ public class EditLog {
|
||||
logEdit(OperationType.OP_RENAME_PARTITION, tableInfo);
|
||||
}
|
||||
|
||||
public void logColumnRename(TableRenameColumnInfo info) {
|
||||
logEdit(OperationType.OP_RENAME_COLUMN, info);
|
||||
}
|
||||
|
||||
public void logCreateCluster(Cluster cluster) {
|
||||
logEdit(OperationType.OP_CREATE_CLUSTER, cluster);
|
||||
}
|
||||
|
||||
@ -46,6 +46,7 @@ public class OperationType {
|
||||
public static final short OP_RECOVER_PARTITION = 18;
|
||||
public static final short OP_RENAME_TABLE = 19;
|
||||
public static final short OP_RENAME_PARTITION = 110;
|
||||
public static final short OP_RENAME_COLUMN = 115;
|
||||
public static final short OP_BACKUP_JOB = 116;
|
||||
public static final short OP_RESTORE_JOB = 117;
|
||||
public static final short OP_TRUNCATE_TABLE = 118;
|
||||
|
||||
@ -0,0 +1,101 @@
|
||||
// Licensed to the Apache Software Foundation (ASF) under one
|
||||
// or more contributor license agreements. See the NOTICE file
|
||||
// distributed with this work for additional information
|
||||
// regarding copyright ownership. The ASF licenses this file
|
||||
// to you 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 org.apache.doris.persist;
|
||||
|
||||
import org.apache.doris.common.io.Text;
|
||||
import org.apache.doris.common.io.Writable;
|
||||
import org.apache.doris.persist.gson.GsonUtils;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* PersistInfo for Table rename column info
|
||||
*/
|
||||
public class TableRenameColumnInfo implements Writable {
|
||||
@SerializedName(value = "dbId")
|
||||
private long dbId;
|
||||
@SerializedName(value = "tableId")
|
||||
private long tableId;
|
||||
@SerializedName(value = "colName")
|
||||
private String colName;
|
||||
@SerializedName(value = "newColName")
|
||||
private String newColName;
|
||||
|
||||
public TableRenameColumnInfo(long dbId, long tableId,
|
||||
String colName, String newColName) {
|
||||
this.dbId = dbId;
|
||||
this.tableId = tableId;
|
||||
this.colName = colName;
|
||||
this.newColName = newColName;
|
||||
}
|
||||
|
||||
public long getDbId() {
|
||||
return dbId;
|
||||
}
|
||||
|
||||
public long getTableId() {
|
||||
return tableId;
|
||||
}
|
||||
|
||||
public String getColName() {
|
||||
return colName;
|
||||
}
|
||||
|
||||
public String getNewColName() {
|
||||
return newColName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(DataOutput out) throws IOException {
|
||||
Text.writeString(out, GsonUtils.GSON.toJson(this));
|
||||
}
|
||||
|
||||
public static TableRenameColumnInfo read(DataInput in) throws IOException {
|
||||
return GsonUtils.GSON.fromJson(Text.readString(in), TableRenameColumnInfo.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (obj == this) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof TableRenameColumnInfo)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TableRenameColumnInfo info = (TableRenameColumnInfo) obj;
|
||||
|
||||
return (dbId == info.dbId && tableId == tableId
|
||||
&& colName.equals(info.colName) && newColName.equals(info.newColName));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(" dbId: ").append(dbId);
|
||||
sb.append(" tableId: ").append(tableId);
|
||||
sb.append(" colName: ").append(colName);
|
||||
sb.append(" newColName: ").append(newColName);
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user