Code review comment: can not bind before write edit log. or clean up when failed.

Code before review:
public Table createTable(LocalMetastore metastore, Database db, CreateTableStmt stmt) throws DdlException {
GlobalStateMgr stateMgr = metastore.getStateMgr();
ColocateTableIndex colocateTableIndex = metastore.getColocateTableIndex();
String tableName = stmt.getTableName();
LOG.debug("begin create olap table: {}", tableName);
List<Column> baseSchema = stmt.getColumns();
metastore.validateColumns(baseSchema);
PartitionDesc partitionDesc = stmt.getPartitionDesc();
PartitionInfo partitionInfo;
Map<String, Long> partitionNameToId = Maps.newHashMap();
if (partitionDesc != null) {
if (partitionDesc instanceof RangePartitionDesc) {
RangePartitionDesc rangePartitionDesc = (RangePartitionDesc) partitionDesc;
for (SingleRangePartitionDesc desc : rangePartitionDesc.getSingleRangePartitionDescs()) {
long partitionId = metastore.getNextId();
partitionNameToId.put(desc.getPartitionName(), partitionId);
}
} else if (partitionDesc instanceof ListPartitionDesc) {
ListPartitionDesc listPartitionDesc = (ListPartitionDesc) partitionDesc;
listPartitionDesc.findAllPartitionNames()
.forEach(partitionName -> partitionNameToId.put(partitionName, metastore.getNextId()));
} else if (partitionDesc instanceof ExpressionPartitionDesc) {
ExpressionPartitionDesc expressionPartitionDesc = (ExpressionPartitionDesc) partitionDesc;
for (SingleRangePartitionDesc desc : expressionPartitionDesc.getRangePartitionDesc()
.getSingleRangePartitionDescs()) {
long partitionId = metastore.getNextId();
partitionNameToId.put(desc.getPartitionName(), partitionId);
}
DynamicPartitionUtil.checkIfAutomaticPartitionAllowed(stmt.getProperties());
} else {
throw new DdlException("Currently only support range or list partition with engine type olap");
}
partitionInfo = partitionDesc.toPartitionInfo(baseSchema, partitionNameToId, false);
if (partitionInfo.isAutomaticPartition()) {
long partitionId = metastore.getNextId();
String replicateNum = String.valueOf(RunMode.defaultReplicationNum());
if (stmt.getProperties() != null) {
replicateNum = stmt.getProperties().getOrDefault("replication_num",
String.valueOf(RunMode.defaultReplicationNum()));
}
partitionInfo.createAutomaticShadowPartition(partitionId, replicateNum);
partitionNameToId.put(ExpressionRangePartitionInfo.AUTOMATIC_SHADOW_PARTITION_NAME, partitionId);
}
} else {
if (DynamicPartitionUtil.checkDynamicPartitionPropertiesExist(stmt.getProperties())) {
throw new DdlException("Only support dynamic partition properties on range partition table");
}
long partitionId = metastore.getNextId();
partitionNameToId.put(tableName, partitionId);
partitionInfo = new SinglePartitionInfo();
}
KeysDesc keysDesc = stmt.getKeysDesc();
Preconditions.checkNotNull(keysDesc);
KeysType keysType = keysDesc.getKeysType();
DistributionDesc distributionDesc = stmt.getDistributionDesc();
Preconditions.checkNotNull(distributionDesc);
DistributionInfo distributionInfo = distributionDesc.toDistributionInfo(baseSchema);
short shortKeyColumnCount = 0;
List<Integer> sortKeyIdxes = new ArrayList<>();
if (stmt.getSortKeys() != null) {
List<String> baseSchemaNames = baseSchema.stream().map(Column::getName).collect(Collectors.toList());
for (String column : stmt.getSortKeys()) {
int idx = baseSchemaNames.indexOf(column);
if (idx == -1) {
throw new DdlException("Invalid column '" + column + "': not exists in all columns.");
}
sortKeyIdxes.add(idx);
}
shortKeyColumnCount =
GlobalStateMgr.calcShortKeyColumnCount(baseSchema, stmt.getProperties(), sortKeyIdxes);
} else {
shortKeyColumnCount = GlobalStateMgr.calcShortKeyColumnCount(baseSchema, stmt.getProperties());
}
LOG.debug("create table[{}] short key column count: {}", tableName, shortKeyColumnCount);
TableIndexes indexes = new TableIndexes(stmt.getIndexes());
Map<String, String> properties = stmt.getProperties();
long tableId = GlobalStateMgr.getCurrentState().getNextId();
OlapTable table;
String storageVolumeId = "";
if (stmt.isExternal()) {
table = new ExternalOlapTable(db.getId(), tableId, tableName, baseSchema, keysType, partitionInfo,
distributionInfo, indexes, properties);
if (GlobalStateMgr.getCurrentState().getNodeMgr()
.checkFeExistByRPCPort(((ExternalOlapTable) table).getSourceTableHost(),
((ExternalOlapTable) table).getSourceTablePort())) {
throw new DdlException("can not create OLAP external table of self cluster");
}
} else if (stmt.isOlapEngine()) {
RunMode runMode = RunMode.getCurrentRunMode();
String volume = "";
if (properties != null && properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_VOLUME)) {
volume = properties.remove(PropertyAnalyzer.PROPERTIES_STORAGE_VOLUME);
}
if (runMode == RunMode.SHARED_DATA) {
if (volume.equals(StorageVolumeMgr.LOCAL)) {
throw new DdlException("Cannot create table " +
"without persistent volume in current run mode \"" + runMode + "\"");
}
StorageVolumeMgr svm = GlobalStateMgr.getCurrentState().getStorageVolumeMgr();
StorageVolume sv = null;
if (volume.isEmpty()) {
String dbStorageVolumeId = svm.getStorageVolumeIdOfDb(db.getId());
if (dbStorageVolumeId != null) {
sv = svm.getStorageVolume(dbStorageVolumeId);
} else {
sv = svm.getStorageVolumeByName(SharedDataStorageVolumeMgr.BUILTIN_STORAGE_VOLUME);
}
} else if (volume.equals(StorageVolumeMgr.DEFAULT)) {
sv = svm.getDefaultStorageVolume();
} else {
sv = svm.getStorageVolumeByName(volume);
}
if (sv == null) {
throw new DdlException("Unknown storage volume \"" + volume + "\"");
}
table = new LakeTable(tableId, tableName, baseSchema, keysType, partitionInfo, distributionInfo, indexes);
storageVolumeId = sv.getId();
metastore.setLakeStorageInfo(table, storageVolumeId, properties);
table.setStorageVolume(sv.getName());
} else {
table = new OlapTable(tableId, tableName, baseSchema, keysType, partitionInfo, distributionInfo, indexes);
table.setStorageVolume(StorageVolumeMgr.LOCAL);
}
} else {
throw new DdlException("Unrecognized engine \"" + stmt.getEngineName() + "\"");
}
table.setComment(stmt.getComment());
long baseIndexId = metastore.getNextId();
table.setBaseIndexId(baseIndexId);
Set<String> bfColumns = null;
double bfFpp = 0;
try {
bfColumns = PropertyAnalyzer.analyzeBloomFilterColumns(properties, baseSchema,
table.getKeysType() == KeysType.PRIMARY_KEYS);
if (bfColumns != null && bfColumns.isEmpty()) {
bfColumns = null;
}
bfFpp = PropertyAnalyzer.analyzeBloomFilterFpp(properties);
if (bfColumns != null && bfFpp == 0) {
bfFpp = FeConstants.DEFAULT_BLOOM_FILTER_FPP;
} else if (bfColumns == null) {
bfFpp = 0;
}
table.setBloomFilterInfo(bfColumns, bfFpp);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
short replicationNum = RunMode.defaultReplicationNum();
try {
boolean isReplicationNumSet =
properties != null && properties.containsKey(PropertyAnalyzer.PROPERTIES_REPLICATION_NUM);
replicationNum = PropertyAnalyzer.analyzeReplicationNum(properties, replicationNum);
if (isReplicationNumSet) {
table.setReplicationNum(replicationNum);
}
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
boolean isInMemory =
PropertyAnalyzer.analyzeBooleanProp(properties, PropertyAnalyzer.PROPERTIES_INMEMORY, false);
table.setIsInMemory(isInMemory);
boolean enablePersistentIndex =
PropertyAnalyzer.analyzeBooleanProp(properties, PropertyAnalyzer.PROPERTIES_ENABLE_PERSISTENT_INDEX,
false);
if (enablePersistentIndex && table.isCloudNativeTable()) {
throw new DdlException("Cannot create cloud native table with persistent index yet");
}
table.setEnablePersistentIndex(enablePersistentIndex);
if (properties != null && (properties.containsKey(PropertyAnalyzer.PROPERTIES_BINLOG_ENABLE) ||
properties.containsKey(PropertyAnalyzer.PROPERTIES_BINLOG_MAX_SIZE) ||
properties.containsKey(PropertyAnalyzer.PROPERTIES_BINLOG_TTL))) {
try {
boolean enableBinlog = PropertyAnalyzer.analyzeBooleanProp(properties,
PropertyAnalyzer.PROPERTIES_BINLOG_ENABLE, false);
long binlogTtl = PropertyAnalyzer.analyzeLongProp(properties,
PropertyAnalyzer.PROPERTIES_BINLOG_TTL, Config.binlog_ttl_second);
long binlogMaxSize = PropertyAnalyzer.analyzeLongProp(properties,
PropertyAnalyzer.PROPERTIES_BINLOG_MAX_SIZE, Config.binlog_max_size);
BinlogConfig binlogConfig = new BinlogConfig(0, enableBinlog,
binlogTtl, binlogMaxSize);
table.setCurBinlogConfig(binlogConfig);
LOG.info("create table {} set binlog config, enable_binlog = {}, binlogTtl = {}, binlog_max_size = {}",
tableName, enableBinlog, binlogTtl, binlogMaxSize);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
}
try {
table.setWriteQuorum(PropertyAnalyzer.analyzeWriteQuorum(properties));
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
table.setEnableReplicatedStorage(
PropertyAnalyzer.analyzeBooleanProp(
properties, PropertyAnalyzer.PROPERTIES_REPLICATED_STORAGE,
Config.enable_replicated_storage_as_default_engine));
if (table.enableReplicatedStorage().equals(false)) {
for (Column col : baseSchema) {
if (col.isAutoIncrement()) {
throw new DdlException("Table with AUTO_INCREMENT column must use Replicated Storage");
}
}
}
TTabletType tabletType = TTabletType.TABLET_TYPE_DISK;
try {
tabletType = PropertyAnalyzer.analyzeTabletType(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
if (table.isCloudNativeTable() && properties != null) {
try {
PeriodDuration duration = PropertyAnalyzer.analyzeDataCachePartitionDuration(properties);
if (duration != null) {
table.setDataCachePartitionDuration(duration);
}
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
}
if (partitionInfo.getType() == PartitionType.UNPARTITIONED) {
long partitionId = partitionNameToId.get(tableName);
DataProperty dataProperty = null;
try {
boolean hasMedium = false;
if (properties != null) {
hasMedium = properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_MEDIUM);
}
dataProperty = PropertyAnalyzer.analyzeDataProperty(properties,
DataProperty.getInferredDefaultDataProperty(), false);
if (hasMedium) {
table.setStorageMedium(dataProperty.getStorageMedium());
}
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
Preconditions.checkNotNull(dataProperty);
partitionInfo.setDataProperty(partitionId, dataProperty);
partitionInfo.setReplicationNum(partitionId, replicationNum);
partitionInfo.setIsInMemory(partitionId, isInMemory);
partitionInfo.setTabletType(partitionId, tabletType);
StorageInfo storageInfo = table.getTableProperty().getStorageInfo();
DataCacheInfo dataCacheInfo = storageInfo == null ? null : storageInfo.getDataCacheInfo();
partitionInfo.setDataCacheInfo(partitionId, dataCacheInfo);
}
String colocateGroup = PropertyAnalyzer.analyzeColocate(properties);
boolean addedToColocateGroup = colocateTableIndex.addTableToGroup(db, table,
colocateGroup, false /* expectLakeTable */);
if (!(table instanceof ExternalOlapTable) && addedToColocateGroup) {
DistributionInfo defaultDistributionInfo = table.getDefaultDistributionInfo();
if (defaultDistributionInfo.getBucketNum() == 0) {
int bucketNum = CatalogUtils.calBucketNumAccordingToBackends();
defaultDistributionInfo.setBucketNum(bucketNum);
}
}
TStorageType baseIndexStorageType = null;
try {
baseIndexStorageType = PropertyAnalyzer.analyzeStorageType(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
Preconditions.checkNotNull(baseIndexStorageType);
int schemaVersion = 0;
try {
schemaVersion = PropertyAnalyzer.analyzeSchemaVersion(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
int schemaHash = Util.schemaHash(schemaVersion, baseSchema, bfColumns, bfFpp);
if (stmt.getSortKeys() != null) {
table.setIndexMeta(baseIndexId, tableName, baseSchema, schemaVersion, schemaHash,
shortKeyColumnCount, baseIndexStorageType, keysType, null, sortKeyIdxes);
} else {
table.setIndexMeta(baseIndexId, tableName, baseSchema, schemaVersion, schemaHash,
shortKeyColumnCount, baseIndexStorageType, keysType, null);
}
for (AlterClause alterClause : stmt.getRollupAlterClauseList()) {
AddRollupClause addRollupClause = (AddRollupClause) alterClause;
Long baseRollupIndex = table.getIndexIdByName(tableName);
TStorageType rollupIndexStorageType = null;
try {
rollupIndexStorageType = PropertyAnalyzer.analyzeStorageType(addRollupClause.getProperties());
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
Preconditions.checkNotNull(rollupIndexStorageType);
List<Column> rollupColumns = stateMgr.getRollupHandler().checkAndPrepareMaterializedView(addRollupClause,
table, baseRollupIndex);
short rollupShortKeyColumnCount =
GlobalStateMgr.calcShortKeyColumnCount(rollupColumns, alterClause.getProperties());
int rollupSchemaHash = Util.schemaHash(schemaVersion, rollupColumns, bfColumns, bfFpp);
long rollupIndexId = metastore.getNextId();
table.setIndexMeta(rollupIndexId, addRollupClause.getRollupName(), rollupColumns, schemaVersion,
rollupSchemaHash, rollupShortKeyColumnCount, rollupIndexStorageType, keysType);
}
Long version = null;
try {
version = PropertyAnalyzer.analyzeVersionInfo(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
Preconditions.checkNotNull(version);
if (properties != null) {
properties.remove("storage_format");
}
TCompressionType compressionType = TCompressionType.LZ4_FRAME;
try {
compressionType = PropertyAnalyzer.analyzeCompressionType(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
table.setCompressionType(compressionType);
int partitionLiveNumber;
if (properties != null && properties.containsKey(PropertyAnalyzer.PROPERTIES_PARTITION_LIVE_NUMBER)) {
try {
partitionLiveNumber = PropertyAnalyzer.analyzePartitionLiveNumber(properties, true);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
table.setPartitionLiveNumber(partitionLiveNumber);
}
try {
processConstraint(db, table, properties);
} catch (AnalysisException e) {
throw new DdlException(
String.format("processing constraint failed when creating table:%s. exception msg:%s",
table.getName(), e.getMessage()), e);
}
Set<Long> tabletIdSet = new HashSet<Long>();
if (table.isOlapOrCloudNativeTable()) {
if (partitionInfo.getType() == PartitionType.UNPARTITIONED) {
if (properties != null && !properties.isEmpty()) {
throw new DdlException("Unknown properties: " + properties);
}
long partitionId = partitionNameToId.get(tableName);
Partition partition = metastore.createPartition(db, table, partitionId, tableName, version, tabletIdSet);
metastore.buildPartitions(db, table, Collections.singletonList(partition));
table.addPartition(partition);
} else if (partitionInfo.isRangePartition() || partitionInfo.getType() == PartitionType.LIST) {
try {
boolean hasMedium = false;
if (properties != null) {
hasMedium = properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_MEDIUM);
}
DataProperty dataProperty = PropertyAnalyzer.analyzeDataProperty(properties,
DataProperty.getInferredDefaultDataProperty(), false);
DynamicPartitionUtil.checkAndSetDynamicPartitionProperty(table, properties);
if (table.dynamicPartitionExists() && table.getColocateGroup() != null) {
HashDistributionInfo info = (HashDistributionInfo) distributionInfo;
if (info.getBucketNum() !=
table.getTableProperty().getDynamicPartitionProperty().getBuckets()) {
throw new DdlException("dynamic_partition.buckets should equal the distribution buckets"
+ " if creating a colocate table");
}
}
if (hasMedium) {
table.setStorageMedium(dataProperty.getStorageMedium());
}
if (properties != null && !properties.isEmpty()) {
throw new DdlException("Unknown properties: " + properties);
}
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
List<Partition> partitions = new ArrayList<>(partitionNameToId.size());
for (Map.Entry<String, Long> entry : partitionNameToId.entrySet()) {
Partition partition = metastore.createPartition(db, table, entry.getValue(), entry.getKey(), version,
tabletIdSet);
partitions.add(partition);
}
metastore.buildPartitions(db, table, partitions);
for (Partition partition : partitions) {
table.addPartition(partition);
}
} else {
throw new DdlException("Unsupported partition method: " + partitionInfo.getType().name());
}
if (table.isBinlogEnabled()) {
Map<String, String> binlogAvailableVersion = table.buildBinlogAvailableVersion();
table.setBinlogAvailableVersion(binlogAvailableVersion);
LOG.info("set binlog available version when create table, tableName : {}, partitions : {}",
tableName, binlogAvailableVersion.toString());
}
}
colocateTableIndex.addTableToGroup(db, table, colocateGroup, true /* expectLakeTable */);
if (RunMode.getCurrentRunMode() == RunMode.SHARED_DATA && !storageVolumeId.isEmpty()) {
StorageVolumeMgr svm = GlobalStateMgr.getCurrentState().getStorageVolumeMgr();
svm.bindTableToStorageVolume(storageVolumeId, tableId);
}
LOG.info("Successfully create table[{};{}]", tableName, tableId);
return table;
}

Line under review: svm.bindTableToStorageVolume(storageVolumeId, tableId);

Code after addressing the review:
public Table createTable(LocalMetastore metastore, Database db, CreateTableStmt stmt) throws DdlException {
GlobalStateMgr stateMgr = metastore.getStateMgr();
ColocateTableIndex colocateTableIndex = metastore.getColocateTableIndex();
String tableName = stmt.getTableName();
LOG.debug("begin create olap table: {}", tableName);
List<Column> baseSchema = stmt.getColumns();
metastore.validateColumns(baseSchema);
PartitionDesc partitionDesc = stmt.getPartitionDesc();
PartitionInfo partitionInfo;
Map<String, Long> partitionNameToId = Maps.newHashMap();
if (partitionDesc != null) {
if (partitionDesc instanceof RangePartitionDesc) {
RangePartitionDesc rangePartitionDesc = (RangePartitionDesc) partitionDesc;
for (SingleRangePartitionDesc desc : rangePartitionDesc.getSingleRangePartitionDescs()) {
long partitionId = metastore.getNextId();
partitionNameToId.put(desc.getPartitionName(), partitionId);
}
} else if (partitionDesc instanceof ListPartitionDesc) {
ListPartitionDesc listPartitionDesc = (ListPartitionDesc) partitionDesc;
listPartitionDesc.findAllPartitionNames()
.forEach(partitionName -> partitionNameToId.put(partitionName, metastore.getNextId()));
} else if (partitionDesc instanceof ExpressionPartitionDesc) {
ExpressionPartitionDesc expressionPartitionDesc = (ExpressionPartitionDesc) partitionDesc;
for (SingleRangePartitionDesc desc : expressionPartitionDesc.getRangePartitionDesc()
.getSingleRangePartitionDescs()) {
long partitionId = metastore.getNextId();
partitionNameToId.put(desc.getPartitionName(), partitionId);
}
DynamicPartitionUtil.checkIfAutomaticPartitionAllowed(stmt.getProperties());
} else {
throw new DdlException("Currently only support range or list partition with engine type olap");
}
partitionInfo = partitionDesc.toPartitionInfo(baseSchema, partitionNameToId, false);
if (partitionInfo.isAutomaticPartition()) {
long partitionId = metastore.getNextId();
String replicateNum = String.valueOf(RunMode.defaultReplicationNum());
if (stmt.getProperties() != null) {
replicateNum = stmt.getProperties().getOrDefault("replication_num",
String.valueOf(RunMode.defaultReplicationNum()));
}
partitionInfo.createAutomaticShadowPartition(partitionId, replicateNum);
partitionNameToId.put(ExpressionRangePartitionInfo.AUTOMATIC_SHADOW_PARTITION_NAME, partitionId);
}
} else {
if (DynamicPartitionUtil.checkDynamicPartitionPropertiesExist(stmt.getProperties())) {
throw new DdlException("Only support dynamic partition properties on range partition table");
}
long partitionId = metastore.getNextId();
partitionNameToId.put(tableName, partitionId);
partitionInfo = new SinglePartitionInfo();
}
KeysDesc keysDesc = stmt.getKeysDesc();
Preconditions.checkNotNull(keysDesc);
KeysType keysType = keysDesc.getKeysType();
DistributionDesc distributionDesc = stmt.getDistributionDesc();
Preconditions.checkNotNull(distributionDesc);
DistributionInfo distributionInfo = distributionDesc.toDistributionInfo(baseSchema);
short shortKeyColumnCount = 0;
List<Integer> sortKeyIdxes = new ArrayList<>();
if (stmt.getSortKeys() != null) {
List<String> baseSchemaNames = baseSchema.stream().map(Column::getName).collect(Collectors.toList());
for (String column : stmt.getSortKeys()) {
int idx = baseSchemaNames.indexOf(column);
if (idx == -1) {
throw new DdlException("Invalid column '" + column + "': not exists in all columns.");
}
sortKeyIdxes.add(idx);
}
shortKeyColumnCount =
GlobalStateMgr.calcShortKeyColumnCount(baseSchema, stmt.getProperties(), sortKeyIdxes);
} else {
shortKeyColumnCount = GlobalStateMgr.calcShortKeyColumnCount(baseSchema, stmt.getProperties());
}
LOG.debug("create table[{}] short key column count: {}", tableName, shortKeyColumnCount);
TableIndexes indexes = new TableIndexes(stmt.getIndexes());
Map<String, String> properties = stmt.getProperties();
long tableId = GlobalStateMgr.getCurrentState().getNextId();
OlapTable table;
if (stmt.isExternal()) {
table = new ExternalOlapTable(db.getId(), tableId, tableName, baseSchema, keysType, partitionInfo,
distributionInfo, indexes, properties);
if (GlobalStateMgr.getCurrentState().getNodeMgr()
.checkFeExistByRPCPort(((ExternalOlapTable) table).getSourceTableHost(),
((ExternalOlapTable) table).getSourceTablePort())) {
throw new DdlException("can not create OLAP external table of self cluster");
}
} else if (stmt.isOlapEngine()) {
RunMode runMode = RunMode.getCurrentRunMode();
String volume = "";
if (properties != null && properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_VOLUME)) {
volume = properties.remove(PropertyAnalyzer.PROPERTIES_STORAGE_VOLUME);
}
if (runMode == RunMode.SHARED_DATA) {
if (volume.equals(StorageVolumeMgr.LOCAL)) {
throw new DdlException("Cannot create table " +
"without persistent volume in current run mode \"" + runMode + "\"");
}
StorageVolumeMgr svm = GlobalStateMgr.getCurrentState().getStorageVolumeMgr();
StorageVolume sv = null;
if (volume.isEmpty()) {
String dbStorageVolumeId = svm.getStorageVolumeIdOfDb(db.getId());
if (dbStorageVolumeId != null) {
sv = svm.getStorageVolume(dbStorageVolumeId);
} else {
sv = svm.getStorageVolumeByName(SharedDataStorageVolumeMgr.BUILTIN_STORAGE_VOLUME);
}
} else if (volume.equals(StorageVolumeMgr.DEFAULT)) {
sv = svm.getDefaultStorageVolume();
} else {
sv = svm.getStorageVolumeByName(volume);
}
if (sv == null) {
throw new DdlException("Unknown storage volume \"" + volume + "\"");
}
table = new LakeTable(tableId, tableName, baseSchema, keysType, partitionInfo, distributionInfo, indexes);
String storageVolumeId = sv.getId();
metastore.setLakeStorageInfo(table, storageVolumeId, properties);
if (!svm.bindTableToStorageVolume(sv.getId(), table.getId())) {
throw new DdlException(String.format("Storage volume with id %s not exists", storageVolumeId));
}
table.setStorageVolume(sv.getName());
} else {
table = new OlapTable(tableId, tableName, baseSchema, keysType, partitionInfo, distributionInfo, indexes);
table.setStorageVolume(StorageVolumeMgr.LOCAL);
}
} else {
throw new DdlException("Unrecognized engine \"" + stmt.getEngineName() + "\"");
}
try {
table.setComment(stmt.getComment());
long baseIndexId = metastore.getNextId();
table.setBaseIndexId(baseIndexId);
Set<String> bfColumns = null;
double bfFpp = 0;
try {
bfColumns = PropertyAnalyzer.analyzeBloomFilterColumns(properties, baseSchema,
table.getKeysType() == KeysType.PRIMARY_KEYS);
if (bfColumns != null && bfColumns.isEmpty()) {
bfColumns = null;
}
bfFpp = PropertyAnalyzer.analyzeBloomFilterFpp(properties);
if (bfColumns != null && bfFpp == 0) {
bfFpp = FeConstants.DEFAULT_BLOOM_FILTER_FPP;
} else if (bfColumns == null) {
bfFpp = 0;
}
table.setBloomFilterInfo(bfColumns, bfFpp);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
short replicationNum = RunMode.defaultReplicationNum();
try {
boolean isReplicationNumSet =
properties != null && properties.containsKey(PropertyAnalyzer.PROPERTIES_REPLICATION_NUM);
replicationNum = PropertyAnalyzer.analyzeReplicationNum(properties, replicationNum);
if (isReplicationNumSet) {
table.setReplicationNum(replicationNum);
}
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
boolean isInMemory =
PropertyAnalyzer.analyzeBooleanProp(properties, PropertyAnalyzer.PROPERTIES_INMEMORY, false);
table.setIsInMemory(isInMemory);
boolean enablePersistentIndex =
PropertyAnalyzer.analyzeBooleanProp(properties, PropertyAnalyzer.PROPERTIES_ENABLE_PERSISTENT_INDEX,
false);
if (enablePersistentIndex && table.isCloudNativeTable()) {
throw new DdlException("Cannot create cloud native table with persistent index yet");
}
table.setEnablePersistentIndex(enablePersistentIndex);
if (properties != null && (properties.containsKey(PropertyAnalyzer.PROPERTIES_BINLOG_ENABLE) ||
properties.containsKey(PropertyAnalyzer.PROPERTIES_BINLOG_MAX_SIZE) ||
properties.containsKey(PropertyAnalyzer.PROPERTIES_BINLOG_TTL))) {
try {
boolean enableBinlog = PropertyAnalyzer.analyzeBooleanProp(properties,
PropertyAnalyzer.PROPERTIES_BINLOG_ENABLE, false);
long binlogTtl = PropertyAnalyzer.analyzeLongProp(properties,
PropertyAnalyzer.PROPERTIES_BINLOG_TTL, Config.binlog_ttl_second);
long binlogMaxSize = PropertyAnalyzer.analyzeLongProp(properties,
PropertyAnalyzer.PROPERTIES_BINLOG_MAX_SIZE, Config.binlog_max_size);
BinlogConfig binlogConfig = new BinlogConfig(0, enableBinlog,
binlogTtl, binlogMaxSize);
table.setCurBinlogConfig(binlogConfig);
LOG.info("create table {} set binlog config, enable_binlog = {}, binlogTtl = {}, binlog_max_size = {}",
tableName, enableBinlog, binlogTtl, binlogMaxSize);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
}
try {
table.setWriteQuorum(PropertyAnalyzer.analyzeWriteQuorum(properties));
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
table.setEnableReplicatedStorage(
PropertyAnalyzer.analyzeBooleanProp(
properties, PropertyAnalyzer.PROPERTIES_REPLICATED_STORAGE,
Config.enable_replicated_storage_as_default_engine));
if (table.enableReplicatedStorage().equals(false)) {
for (Column col : baseSchema) {
if (col.isAutoIncrement()) {
throw new DdlException("Table with AUTO_INCREMENT column must use Replicated Storage");
}
}
}
TTabletType tabletType = TTabletType.TABLET_TYPE_DISK;
try {
tabletType = PropertyAnalyzer.analyzeTabletType(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
if (table.isCloudNativeTable() && properties != null) {
try {
PeriodDuration duration = PropertyAnalyzer.analyzeDataCachePartitionDuration(properties);
if (duration != null) {
table.setDataCachePartitionDuration(duration);
}
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
}
if (partitionInfo.getType() == PartitionType.UNPARTITIONED) {
long partitionId = partitionNameToId.get(tableName);
DataProperty dataProperty = null;
try {
boolean hasMedium = false;
if (properties != null) {
hasMedium = properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_MEDIUM);
}
dataProperty = PropertyAnalyzer.analyzeDataProperty(properties,
DataProperty.getInferredDefaultDataProperty(), false);
if (hasMedium) {
table.setStorageMedium(dataProperty.getStorageMedium());
}
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
Preconditions.checkNotNull(dataProperty);
partitionInfo.setDataProperty(partitionId, dataProperty);
partitionInfo.setReplicationNum(partitionId, replicationNum);
partitionInfo.setIsInMemory(partitionId, isInMemory);
partitionInfo.setTabletType(partitionId, tabletType);
StorageInfo storageInfo = table.getTableProperty().getStorageInfo();
DataCacheInfo dataCacheInfo = storageInfo == null ? null : storageInfo.getDataCacheInfo();
partitionInfo.setDataCacheInfo(partitionId, dataCacheInfo);
}
String colocateGroup = PropertyAnalyzer.analyzeColocate(properties);
boolean addedToColocateGroup = colocateTableIndex.addTableToGroup(db, table,
colocateGroup, false /* expectLakeTable */);
if (!(table instanceof ExternalOlapTable) && addedToColocateGroup) {
DistributionInfo defaultDistributionInfo = table.getDefaultDistributionInfo();
if (defaultDistributionInfo.getBucketNum() == 0) {
int bucketNum = CatalogUtils.calBucketNumAccordingToBackends();
defaultDistributionInfo.setBucketNum(bucketNum);
}
}
TStorageType baseIndexStorageType = null;
try {
baseIndexStorageType = PropertyAnalyzer.analyzeStorageType(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
Preconditions.checkNotNull(baseIndexStorageType);
int schemaVersion = 0;
try {
schemaVersion = PropertyAnalyzer.analyzeSchemaVersion(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
int schemaHash = Util.schemaHash(schemaVersion, baseSchema, bfColumns, bfFpp);
if (stmt.getSortKeys() != null) {
table.setIndexMeta(baseIndexId, tableName, baseSchema, schemaVersion, schemaHash,
shortKeyColumnCount, baseIndexStorageType, keysType, null, sortKeyIdxes);
} else {
table.setIndexMeta(baseIndexId, tableName, baseSchema, schemaVersion, schemaHash,
shortKeyColumnCount, baseIndexStorageType, keysType, null);
}
for (AlterClause alterClause : stmt.getRollupAlterClauseList()) {
AddRollupClause addRollupClause = (AddRollupClause) alterClause;
Long baseRollupIndex = table.getIndexIdByName(tableName);
TStorageType rollupIndexStorageType = null;
try {
rollupIndexStorageType = PropertyAnalyzer.analyzeStorageType(addRollupClause.getProperties());
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
Preconditions.checkNotNull(rollupIndexStorageType);
List<Column> rollupColumns = stateMgr.getRollupHandler().checkAndPrepareMaterializedView(addRollupClause,
table, baseRollupIndex);
short rollupShortKeyColumnCount =
GlobalStateMgr.calcShortKeyColumnCount(rollupColumns, alterClause.getProperties());
int rollupSchemaHash = Util.schemaHash(schemaVersion, rollupColumns, bfColumns, bfFpp);
long rollupIndexId = metastore.getNextId();
table.setIndexMeta(rollupIndexId, addRollupClause.getRollupName(), rollupColumns, schemaVersion,
rollupSchemaHash, rollupShortKeyColumnCount, rollupIndexStorageType, keysType);
}
Long version = null;
try {
version = PropertyAnalyzer.analyzeVersionInfo(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
Preconditions.checkNotNull(version);
if (properties != null) {
properties.remove("storage_format");
}
TCompressionType compressionType = TCompressionType.LZ4_FRAME;
try {
compressionType = PropertyAnalyzer.analyzeCompressionType(properties);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
table.setCompressionType(compressionType);
int partitionLiveNumber;
if (properties != null && properties.containsKey(PropertyAnalyzer.PROPERTIES_PARTITION_LIVE_NUMBER)) {
try {
partitionLiveNumber = PropertyAnalyzer.analyzePartitionLiveNumber(properties, true);
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
table.setPartitionLiveNumber(partitionLiveNumber);
}
try {
processConstraint(db, table, properties);
} catch (AnalysisException e) {
throw new DdlException(
String.format("processing constraint failed when creating table:%s. exception msg:%s",
table.getName(), e.getMessage()), e);
}
Set<Long> tabletIdSet = new HashSet<Long>();
if (table.isOlapOrCloudNativeTable()) {
if (partitionInfo.getType() == PartitionType.UNPARTITIONED) {
if (properties != null && !properties.isEmpty()) {
throw new DdlException("Unknown properties: " + properties);
}
long partitionId = partitionNameToId.get(tableName);
Partition partition = metastore.createPartition(db, table, partitionId, tableName, version, tabletIdSet);
metastore.buildPartitions(db, table, Collections.singletonList(partition));
table.addPartition(partition);
} else if (partitionInfo.isRangePartition() || partitionInfo.getType() == PartitionType.LIST) {
try {
boolean hasMedium = false;
if (properties != null) {
hasMedium = properties.containsKey(PropertyAnalyzer.PROPERTIES_STORAGE_MEDIUM);
}
DataProperty dataProperty = PropertyAnalyzer.analyzeDataProperty(properties,
DataProperty.getInferredDefaultDataProperty(), false);
DynamicPartitionUtil.checkAndSetDynamicPartitionProperty(table, properties);
if (table.dynamicPartitionExists() && table.getColocateGroup() != null) {
HashDistributionInfo info = (HashDistributionInfo) distributionInfo;
if (info.getBucketNum() !=
table.getTableProperty().getDynamicPartitionProperty().getBuckets()) {
throw new DdlException("dynamic_partition.buckets should equal the distribution buckets"
+ " if creating a colocate table");
}
}
if (hasMedium) {
table.setStorageMedium(dataProperty.getStorageMedium());
}
if (properties != null && !properties.isEmpty()) {
throw new DdlException("Unknown properties: " + properties);
}
} catch (AnalysisException e) {
throw new DdlException(e.getMessage());
}
List<Partition> partitions = new ArrayList<>(partitionNameToId.size());
for (Map.Entry<String, Long> entry : partitionNameToId.entrySet()) {
Partition partition = metastore.createPartition(db, table, entry.getValue(), entry.getKey(), version,
tabletIdSet);
partitions.add(partition);
}
metastore.buildPartitions(db, table, partitions);
for (Partition partition : partitions) {
table.addPartition(partition);
}
} else {
throw new DdlException("Unsupported partition method: " + partitionInfo.getType().name());
}
if (table.isBinlogEnabled()) {
Map<String, String> binlogAvailableVersion = table.buildBinlogAvailableVersion();
table.setBinlogAvailableVersion(binlogAvailableVersion);
LOG.info("set binlog available version when create table, tableName : {}, partitions : {}",
tableName, binlogAvailableVersion.toString());
}
}
colocateTableIndex.addTableToGroup(db, table, colocateGroup, true /* expectLakeTable */);
} catch (DdlException e) {
if (RunMode.getCurrentRunMode() == RunMode.SHARED_DATA) {
GlobalStateMgr.getCurrentState().getStorageVolumeMgr().unbindTableToStorageVolume(tableId);
}
throw e;
}
LOG.info("Successfully create table[{};{}]", tableName, tableId);
return table;
}