in fe/src/main/java/org/apache/impala/service/CatalogOpExecutor.java [1188:1457]
private void alterTable(TAlterTableParams params, @Nullable String debugAction,
boolean wantMinimalResult, TDdlExecResponse response, EventSequence catalogTimeline)
throws ImpalaException {
// When true, loads the file/block metadata.
boolean reloadFileMetadata = false;
// When true, loads the table schema and the column stats from the Hive Metastore.
boolean reloadTableSchema = false;
Reference<Long> numUpdatedPartitions = new Reference<>(0L);
TableName tableName = TableName.fromThrift(params.getTable_name());
Table tbl = getExistingTable(tableName.getDb(), tableName.getTbl(),
"Load for ALTER TABLE", catalogTimeline);
if (params.getAlter_type() == TAlterTableType.RENAME_VIEW
|| params.getAlter_type() == TAlterTableType.RENAME_TABLE) {
TableName newTableName = TableName.fromThrift(
params.getRename_params().getNew_table_name());
Preconditions.checkState(!catalog_.isBlacklistedTable(newTableName),
String.format("Can't rename to blacklisted table name: %s. %s", newTableName,
BLACKLISTED_TABLES_INCONSISTENT_ERR_STR));
}
tryWriteLock(tbl, catalogTimeline);
// get table's catalogVersion before altering it
long oldCatalogVersion = tbl.getCatalogVersion();
// Get a new catalog version, wrap it in InProgressTableModification, and assign new
// version to the table being altered.
InProgressTableModification modification =
new InProgressTableModification(catalog_, tbl);
catalog_.getLock().writeLock().unlock();
modification.addCatalogServiceIdentifiersToTable();
final Timer.Context context
= tbl.getMetrics().getTimer(Table.ALTER_DURATION_METRIC).time();
try {
if (params.getAlter_type() == TAlterTableType.RENAME_VIEW
|| params.getAlter_type() == TAlterTableType.RENAME_TABLE) {
alterTableOrViewRename(tbl,
TableName.fromThrift(params.getRename_params().getNew_table_name()),
modification, wantMinimalResult, response, catalogTimeline, debugAction);
modification.validateInProgressModificationComplete();
return;
}
String responseSummaryMsg = null;
if (tbl instanceof KuduTable && altersKuduTable(params.getAlter_type())) {
alterKuduTable(params, response, (KuduTable) tbl, modification, wantMinimalResult,
catalogTimeline, debugAction);
modification.validateInProgressModificationComplete();
return;
} else if (tbl instanceof IcebergTable &&
altersIcebergTable(params.getAlter_type())) {
boolean needToUpdateHms = alterIcebergTable(params, response, (IcebergTable) tbl,
wantMinimalResult, debugAction, catalogTimeline, modification);
if (!needToUpdateHms) {
modification.validateInProgressModificationComplete();
return;
}
}
boolean reloadMetadata = true;
switch (params.getAlter_type()) {
case ADD_COLUMNS:
boolean added = false;
// Columns could be ignored/cleared in AlterTableAddColsStmt,
// that may cause columns to be empty.
if (params.getAdd_cols_params() != null
&& params.getAdd_cols_params().getColumnsSize() != 0) {
TAlterTableAddColsParams addColParams = params.getAdd_cols_params();
added = alterTableAddCols(tbl, addColParams.getColumns(),
addColParams.isIf_not_exists(), catalogTimeline, modification);
reloadTableSchema = true;
}
if (added) {
responseSummaryMsg = "New column(s) have been added to the table.";
} else {
responseSummaryMsg = "No new column(s) have been added to the table.";
}
break;
case REPLACE_COLUMNS:
TAlterTableReplaceColsParams replaceColParams = params.getReplace_cols_params();
alterTableReplaceCols(
tbl, replaceColParams.getColumns(), catalogTimeline, modification);
reloadTableSchema = true;
responseSummaryMsg = "Table columns have been replaced.";
break;
case ADD_PARTITION:
// Create and add HdfsPartition objects to the corresponding HdfsTable and load
// their block metadata. Update the table object with the new catalog version.
THdfsFileFormat format = null;
if(params.isSetSet_file_format_params()) {
format = params.getSet_file_format_params().file_format;
}
alterTableAddPartitions(tbl, params.getAdd_partition_params(), format,
catalogTimeline, modification, debugAction);
reloadMetadata = false;
responseSummaryMsg = "New partition has been added to the table.";
break;
case DROP_COLUMN:
TAlterTableDropColParams dropColParams = params.getDrop_col_params();
alterTableDropCol(
tbl, dropColParams.getCol_name(), catalogTimeline, modification);
reloadTableSchema = true;
responseSummaryMsg = "Column has been dropped.";
break;
case ALTER_COLUMN:
TAlterTableAlterColParams alterColParams = params.getAlter_col_params();
alterTableAlterCol(tbl, alterColParams.getCol_name(),
alterColParams.getNew_col_def(), catalogTimeline, modification);
reloadTableSchema = true;
responseSummaryMsg = "Column has been altered.";
break;
case DROP_PARTITION:
TAlterTableDropPartitionParams dropPartParams =
params.getDrop_partition_params();
// Drop the partition from the corresponding table. If "purge" option is
// specified partition data is purged by skipping Trash, if configured.
alterTableDropPartition(tbl, dropPartParams.getPartition_set(),
dropPartParams.isIf_exists(), dropPartParams.isPurge(),
numUpdatedPartitions, catalogTimeline, modification);
responseSummaryMsg =
"Dropped " + numUpdatedPartitions.getRef() + " partition(s).";
reloadMetadata = false;
break;
case RENAME_TABLE:
case RENAME_VIEW:
Preconditions.checkState(false,
"RENAME TABLE/VIEW operation has been processed");
break;
case SET_FILE_FORMAT:
TAlterTableSetFileFormatParams fileFormatParams =
params.getSet_file_format_params();
reloadFileMetadata = alterTableSetFileFormat(tbl,
fileFormatParams.getPartition_set(), fileFormatParams.getFile_format(),
numUpdatedPartitions, catalogTimeline, modification);
if (fileFormatParams.isSetPartition_set()) {
responseSummaryMsg =
"Updated " + numUpdatedPartitions.getRef() + " partition(s).";
} else {
responseSummaryMsg = "Updated table.";
}
break;
case SET_ROW_FORMAT:
TAlterTableSetRowFormatParams rowFormatParams =
params.getSet_row_format_params();
reloadFileMetadata = alterTableSetRowFormat(tbl,
rowFormatParams.getPartition_set(), rowFormatParams.getRow_format(),
numUpdatedPartitions, catalogTimeline, modification);
if (rowFormatParams.isSetPartition_set()) {
responseSummaryMsg =
"Updated " + numUpdatedPartitions.getRef() + " partition(s).";
} else {
responseSummaryMsg = "Updated table.";
}
break;
case SET_LOCATION:
TAlterTableSetLocationParams setLocationParams =
params.getSet_location_params();
List<TPartitionKeyValue> partitionSpec = setLocationParams.getPartition_spec();
reloadFileMetadata = alterTableSetLocation(tbl, partitionSpec,
setLocationParams.getLocation(), catalogTimeline, modification);
if (partitionSpec == null) {
responseSummaryMsg = "New location has been set.";
} else {
responseSummaryMsg = "New location has been set for the specified partition.";
}
break;
case SET_TBL_PROPERTIES:
alterTableSetTblProperties(tbl, params.getSet_tbl_properties_params(),
numUpdatedPartitions, catalogTimeline, modification);
reloadTableSchema = true;
if (params.getSet_tbl_properties_params().isSetPartition_set()) {
responseSummaryMsg =
"Updated " + numUpdatedPartitions.getRef() + " partition(s).";
} else {
responseSummaryMsg = "Updated table.";
}
break;
case UNSET_TBL_PROPERTIES:
alterTableUnSetTblProperties(tbl, params.getUnset_tbl_properties_params(),
numUpdatedPartitions, catalogTimeline, modification);
reloadTableSchema = true;
if (params.getUnset_tbl_properties_params().isSetPartition_set()) {
responseSummaryMsg =
"Updated " + numUpdatedPartitions.getRef() + " partition(s).";
} else {
responseSummaryMsg = "Updated table.";
}
break;
case SET_VIEW_PROPERTIES:
alterViewSetTblProperties(
tbl, params.getSet_tbl_properties_params(), catalogTimeline, modification);
reloadTableSchema = true;
responseSummaryMsg = "Updated view.";
break;
case UNSET_VIEW_PROPERTIES:
alterViewUnSetTblProperties(tbl, params.getUnset_tbl_properties_params(),
catalogTimeline, modification);
reloadTableSchema = true;
responseSummaryMsg = "Updated view.";
break;
case UPDATE_STATS:
Preconditions.checkState(params.isSetUpdate_stats_params());
Reference<Long> numUpdatedColumns = new Reference<>(0L);
alterTableUpdateStats(tbl, params.getUpdate_stats_params(),
numUpdatedPartitions, numUpdatedColumns, debugAction, catalogTimeline,
modification);
reloadTableSchema = true;
responseSummaryMsg = "Updated " + numUpdatedPartitions.getRef() +
" partition(s) and " + numUpdatedColumns.getRef() + " column(s).";
break;
case SET_CACHED:
Preconditions.checkState(params.isSetSet_cached_params());
String op = params.getSet_cached_params().getCache_op().isSet_cached() ?
"Cached " : "Uncached ";
if (params.getSet_cached_params().getPartition_set() == null) {
reloadFileMetadata = alterTableSetCached(
tbl, params.getSet_cached_params(), catalogTimeline, modification);
responseSummaryMsg = op + "table.";
} else {
alterPartitionSetCached(tbl, params.getSet_cached_params(),
numUpdatedPartitions, catalogTimeline, modification);
responseSummaryMsg = op + numUpdatedPartitions.getRef() + " partition(s).";
}
break;
case RECOVER_PARTITIONS:
alterTableRecoverPartitions(tbl, debugAction, catalogTimeline, modification);
responseSummaryMsg = "Partitions have been recovered.";
break;
case SET_OWNER:
Preconditions.checkState(params.isSetSet_owner_params());
alterTableOrViewSetOwner(
tbl, params.getSet_owner_params(), response, catalogTimeline, modification);
responseSummaryMsg = "Updated table/view.";
break;
default:
throw new UnsupportedOperationException(
"Unknown ALTER TABLE operation type: " + params.getAlter_type());
}
// Make sure we won't forget finalizing the modification.
if (modification.isInProgress()) {
Preconditions.checkState(reloadMetadata,
"In-progress modification of table %s must be followed by metadata reload.",
tbl.getFullName());
}
if (reloadMetadata) {
loadTableMetadata(tbl, modification.newVersionNumber(), reloadFileMetadata,
reloadTableSchema, "ALTER TABLE " + params.getAlter_type().name(),
debugAction, catalogTimeline);
modification.markInflightEventRegistrationComplete();
}
addSummary(response, responseSummaryMsg);
// add table to catalog update if its old and existing versions do not match
if (tbl.getCatalogVersion() != oldCatalogVersion) {
addTableToCatalogUpdate(tbl, wantMinimalResult, response.result);
}
// Make sure all the modifications are done.
modification.validateInProgressModificationComplete();
} catch (Exception ex) {
modification.cancelInflightEventIfExist();
throw ex;
} finally {
context.stop();
UnlockWriteLockIfErronouslyLocked();
// Clear in-progress modifications in case of exceptions.
tbl.resetInProgressModification();
tbl.releaseWriteLock();
}
}